1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2003-2007 Naba Kumar <naba@gnome.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <libanjuta/resources.h>
22 #include <libanjuta/anjuta-utils.h>
23 #include <libanjuta/anjuta-preferences.h>
24 #include <libanjuta/anjuta-debug.h>
25 #include <libanjuta/interfaces/ianjuta-file.h>
26 #include <libanjuta/interfaces/ianjuta-markable.h>
27 #include <libanjuta/interfaces/ianjuta-file-savable.h>
28 #include <libanjuta/interfaces/ianjuta-editor.h>
29 #include <libanjuta/interfaces/ianjuta-editor-factory.h>
31 #include <gtk/gtkfilechooserdialog.h>
32 #include <libgnomevfs/gnome-vfs.h>
34 #include <gdl/gdl-icons.h>
36 #include "anjuta-docman.h"
37 #include "file_history.h"
39 #include "action-callbacks.h"
40 #include "editor-tooltips.h"
42 static gpointer parent_class
;
52 #define EDITOR_TABS_POS "editor.tabs.pos"
53 #define EDITOR_TABS_HIDE "editor.tabs.hide"
54 #define EDITOR_TABS_ORDERING "editor.tabs.ordering"
55 #define EDITOR_TABS_RECENT_FIRST "editor.tabs.recent.first"
57 typedef struct _AnjutaDocmanPage AnjutaDocmanPage
;
59 struct _AnjutaDocmanPriv
{
61 AnjutaPreferences
*preferences
;
62 GList
*pages
; /* list of AnjutaDocmanPage's */
63 AnjutaDocmanPage
*cur_page
;
64 IAnjutaDocument
*current_document
; /* normally == IANJUTA_DOCUMENT (cur_page->widget) */
66 GtkWidget
*fileselection
;
68 GtkWidget
*popup_menu
; /* shared context-menu for main-notebook pages */
69 gboolean tab_pressed
; /* flags for deferring notebook page re-arrangement */
70 gboolean reorder_queued
;
75 struct _AnjutaDocmanPage
{
76 GtkWidget
*widget
; /* notebook-page widget, a GTK_WIDGET (IAnjutaDocument*) */
77 GtkWidget
*box
; /* notebook-tab-label parent widget */
78 GtkWidget
*close_image
;
79 GtkWidget
*close_button
;
82 GtkWidget
*menu_label
; /* notebook page-switch menu-label */
86 static guint docman_signals
[LAST_SIGNAL
] = { 0 };
88 static void anjuta_docman_order_tabs (AnjutaDocman
*docman
);
89 static void anjuta_docman_update_page_label (AnjutaDocman
*docman
,
90 GtkWidget
*doc_widget
);
91 static void anjuta_docman_grab_text_focus (AnjutaDocman
*docman
);
92 static void on_notebook_switch_page (GtkNotebook
* notebook
,
93 GtkNotebookPage
* page
,
94 gint page_num
, AnjutaDocman
*docman
);
95 static AnjutaDocmanPage
*
96 anjuta_docman_get_page_for_document (AnjutaDocman
*docman
,
97 IAnjutaDocument
*doc
);
100 on_notebook_page_close_button_click (GtkButton
* button
,
101 AnjutaDocman
* docman
)
105 node
= docman
->priv
->pages
;
108 AnjutaDocmanPage
*page
;
109 IAnjutaDocument
*doc
;
110 page
= (AnjutaDocmanPage
*) node
->data
;
111 if (page
->close_button
== GTK_WIDGET(button
))
113 doc
= IANJUTA_DOCUMENT (page
->widget
);
114 anjuta_docman_set_current_document(docman
, doc
);
117 node
= g_list_next (node
);
120 on_close_file_activate (NULL
, docman
->priv
->plugin
);
124 on_notebook_page_close_button_enter (GtkButton
*button
,
125 AnjutaDocmanPage
* page
)
127 g_return_if_fail (page
!= NULL
);
129 gtk_widget_set_sensitive (page
->close_image
, TRUE
);
133 on_notebook_page_close_button_leave (GtkButton
* button
,
134 AnjutaDocmanPage
* page
)
136 g_return_if_fail (page
!= NULL
);
138 if (! page
->is_current
)
139 gtk_widget_set_sensitive (page
->close_image
,FALSE
);
142 /* for managing deferred tab re-arrangement */
144 on_notebook_tab_btnpress (GtkWidget
*wid
, GdkEventButton
*event
, AnjutaDocman
* docman
)
146 if (event
->type
== GDK_BUTTON_PRESS
)
148 docman
->priv
->tab_pressed
= TRUE
;
149 docman
->priv
->reorder_queued
= FALSE
;
155 on_notebook_tab_btnrelease (GtkWidget
*widget
, GdkEventButton
*event
, AnjutaDocman
* docman
)
158 AnjutaDocmanPage
*page
;
159 DEBUG_PRINT ("In function: on_notebook_tab_btnrelease");
161 docman
->priv
->tab_pressed
= FALSE
;
163 page
= NULL
; /* assignment for warning prevention */
164 node
= docman
->priv
->pages
;
167 page
= (AnjutaDocmanPage
*)node
->data
;
168 if (page
->box
== widget
)
170 node
= g_list_next (node
);
175 if (docman
->priv
->reorder_queued
) /* re-ordering in effect and no drag to another book */
177 if (gtk_notebook_page_num (GTK_NOTEBOOK (docman
), page
->widget
) == docman
->priv
->old_indx
)
178 /* no drag happened in same book */
179 gtk_notebook_reorder_child (GTK_NOTEBOOK (docman
), page
->widget
, 0);
180 docman
->priv
->reorder_queued
= FALSE
;
187 anjuta_docman_page_setup (AnjutaDocmanPage
* page
, AnjutaDocman
* docman
)
189 GtkWidget
*close_button
;
190 GtkWidget
*close_pixmap
;
192 GtkWidget
*label
, *menu_label
;
194 GtkWidget
*event_hbox
;
195 GtkWidget
*event_box
;
196 GtkTooltips
*tooltips
;
199 const gchar
*filename
;
203 g_return_if_fail (GTK_IS_WIDGET(page
->widget
));
205 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU
, &w
, &h
);
207 close_pixmap
= gtk_image_new_from_stock(GTK_STOCK_CLOSE
, GTK_ICON_SIZE_MENU
);
208 gtk_widget_show(close_pixmap
);
210 /* setup close button, zero out {x,y}thickness to get smallest possible
212 close_button
= gtk_button_new();
213 gtk_button_set_focus_on_click (GTK_BUTTON (close_button
), FALSE
);
214 gtk_container_add(GTK_CONTAINER(close_button
), close_pixmap
);
215 gtk_button_set_relief(GTK_BUTTON(close_button
), GTK_RELIEF_NONE
);
216 rcstyle
= gtk_rc_style_new ();
217 rcstyle
->xthickness
= rcstyle
->ythickness
= 0;
218 gtk_widget_modify_style (close_button
, rcstyle
);
219 g_object_unref (G_OBJECT (rcstyle
));
221 gtk_widget_set_size_request (close_button
, w
, h
);
222 tooltips
= gtk_tooltips_new ();
223 /* this approach to tooltips is deprecated as from gtk 2.12 */
224 gtk_tooltips_set_tip (GTK_TOOLTIPS (tooltips
), close_button
,
228 filename
= ianjuta_document_get_filename (IANJUTA_DOCUMENT (page
->widget
), NULL
);
229 label
= gtk_label_new (filename
);
230 gtk_misc_set_alignment (GTK_MISC(label
), 0.0, 0.5);
231 gtk_widget_show (label
);
233 menu_label
= gtk_label_new (filename
);
234 gtk_widget_show (menu_label
);
240 gtk_widget_modify_fg (close_button
, GTK_STATE_NORMAL
, &color
);
241 gtk_widget_modify_fg (close_button
, GTK_STATE_INSENSITIVE
, &color
);
242 gtk_widget_modify_fg (close_button
, GTK_STATE_ACTIVE
, &color
);
243 gtk_widget_modify_fg (close_button
, GTK_STATE_PRELIGHT
, &color
);
244 gtk_widget_modify_fg (close_button
, GTK_STATE_SELECTED
, &color
);
245 gtk_widget_show(close_button
);
247 /* create our layout/event boxes */
248 event_box
= gtk_event_box_new();
249 gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box
), FALSE
);
251 event_hbox
= gtk_hbox_new (FALSE
, 2);
252 box
= gtk_hbox_new(FALSE
, 2);
254 /* Add a nice mime-type icon */
255 editor
= IANJUTA_FILE(page
->widget
);
256 uri
= ianjuta_file_get_uri(editor
, NULL
);
259 GdlIcons
* icons
= gdl_icons_new (16);
260 GdkPixbuf
*pixbuf
= gdl_icons_get_uri_icon(icons
, uri
);
261 GtkWidget
* image
= gtk_image_new_from_pixbuf (pixbuf
);
262 gtk_box_pack_start (GTK_BOX(event_hbox
), image
, FALSE
, FALSE
, 0);
263 page
->mime_icon
= image
;
264 g_object_unref (G_OBJECT (pixbuf
));
265 g_object_unref (G_OBJECT (icons
));
269 gtk_box_pack_start (GTK_BOX(event_hbox
), label
, TRUE
, TRUE
, 0);
270 gtk_box_pack_start (GTK_BOX (event_hbox
), close_button
, FALSE
, FALSE
, 0);
271 gtk_container_add (GTK_CONTAINER (event_box
), event_hbox
);
273 /* setup the data hierarchy */
274 g_object_set_data (G_OBJECT (box
), "event_box", event_box
);
276 /* pack our top-level layout box */
277 gtk_box_pack_start (GTK_BOX (box
), event_box
, TRUE
, TRUE
, 0);
279 /* show the widgets of the tab */
280 gtk_widget_show_all(box
);
282 g_signal_connect (G_OBJECT (close_button
), "clicked",
283 G_CALLBACK (on_notebook_page_close_button_click
),
285 g_signal_connect (G_OBJECT (close_button
), "enter",
286 G_CALLBACK (on_notebook_page_close_button_enter
),
288 g_signal_connect (G_OBJECT (close_button
), "leave",
289 G_CALLBACK (on_notebook_page_close_button_leave
),
291 g_signal_connect (G_OBJECT (box
), "button-press-event",
292 G_CALLBACK (on_notebook_tab_btnpress
),
294 g_signal_connect (G_OBJECT (box
), "button-release-event",
295 G_CALLBACK (on_notebook_tab_btnrelease
),
298 page
->close_image
= close_pixmap
;
299 page
->close_button
= close_button
;
301 page
->menu_label
= menu_label
;
304 static AnjutaDocmanPage
*
305 anjuta_docman_page_new (IAnjutaDocument
*doc
, AnjutaDocman
* docman
)
307 AnjutaDocmanPage
*page
;
309 page
= g_new0 (AnjutaDocmanPage
, 1); /* don't try to survive a memory-crunch */
314 anjuta_docman_page_destroy (AnjutaDocmanPage
*page
)
318 if (page
->widget
&& GTK_IS_WIDGET (page
->widget
))
319 /* CHECKME just unref in case other plugins hold ref on the page or its contents ? */
320 gtk_widget_destroy (page
->widget
);
321 if (page
->box
&& GTK_IS_WIDGET (page
->box
))
322 gtk_widget_destroy (page
->box
); /* the tab-label parent-widget */
328 on_open_filesel_response (GtkDialog
* dialog
, gint id
, AnjutaDocman
*docman
)
331 // unused gchar *entry_filename = NULL;
336 if (id
!= GTK_RESPONSE_ACCEPT
)
338 gtk_widget_hide (docman
->priv
->fileselection
);
342 list
= gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog
));
345 elements
= g_slist_length(list
);
346 for(i
=0;i
<elements
;i
++)
348 uri
= g_slist_nth_data (list
, i
);
351 anjuta_docman_goto_file_line (docman
, uri
, -1);
357 /* if (entry_filename)
359 list = g_slist_remove(list, entry_filename);
360 g_free(entry_filename);
367 create_file_open_dialog_gui (GtkWindow
* parent
, AnjutaDocman
* docman
)
370 gtk_file_chooser_dialog_new (_("Open file"),
372 GTK_FILE_CHOOSER_ACTION_OPEN
,
373 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
374 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
376 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_ACCEPT
);
377 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(dialog
), TRUE
);
378 g_signal_connect (G_OBJECT(dialog
), "response",
379 G_CALLBACK(on_open_filesel_response
), docman
);
380 g_signal_connect_swapped (G_OBJECT(dialog
), "delete-event",
381 G_CALLBACK(gtk_widget_hide
), dialog
);
386 create_file_save_dialog_gui (GtkWindow
* parent
, AnjutaDocman
* docman
)
389 gtk_file_chooser_dialog_new (_("Save file as"),
391 GTK_FILE_CHOOSER_ACTION_SAVE
,
392 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
393 GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
,
395 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_ACCEPT
);
400 anjuta_docman_open_file (AnjutaDocman
*docman
)
402 if (!docman
->priv
->fileselection
)
405 parent
= gtk_widget_get_toplevel (GTK_WIDGET (docman
));
406 docman
->priv
->fileselection
=
407 create_file_open_dialog_gui(GTK_WINDOW (parent
), docman
);
409 if (GTK_WIDGET_VISIBLE (docman
->priv
->fileselection
))
410 gtk_window_present (GTK_WINDOW (docman
->priv
->fileselection
));
412 gtk_widget_show (docman
->priv
->fileselection
);
416 anjuta_docman_save_document_as (AnjutaDocman
*docman
, IAnjutaDocument
*doc
,
417 GtkWidget
*parent_window
)
420 GnomeVFSURI
* vfs_uri
;
422 const gchar
* filename
;
426 gboolean file_saved
= TRUE
;
428 g_return_val_if_fail (ANJUTA_IS_DOCMAN (docman
), FALSE
);
429 g_return_val_if_fail (IANJUTA_IS_DOCUMENT (doc
), FALSE
);
432 parent
= parent_window
;
434 parent
= gtk_widget_get_toplevel (GTK_WIDGET (docman
));
436 dialog
= create_file_save_dialog_gui (GTK_WINDOW (parent
), docman
);
438 if ((file_uri
= ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
)) != NULL
)
440 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER(dialog
), file_uri
);
443 else if ((filename
= ianjuta_document_get_filename (doc
, NULL
)) != NULL
)
444 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(dialog
), filename
);
446 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(dialog
), "");
448 response
= gtk_dialog_run (GTK_DIALOG (dialog
));
449 if (response
!= GTK_RESPONSE_ACCEPT
)
451 gtk_widget_destroy (dialog
);
455 uri
= gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog
));
456 vfs_uri
= gnome_vfs_uri_new(uri
);
457 if (gnome_vfs_uri_exists(vfs_uri
))
459 GtkWidget
*msg_dialog
;
460 msg_dialog
= gtk_message_dialog_new (GTK_WINDOW (dialog
),
461 GTK_DIALOG_DESTROY_WITH_PARENT
,
462 GTK_MESSAGE_QUESTION
,
464 _("The file '%s' already exists.\n"
465 "Do you want to replace it with the"
466 " one you are saving?"),
468 gtk_dialog_add_button (GTK_DIALOG (msg_dialog
),
470 GTK_RESPONSE_CANCEL
);
471 anjuta_util_dialog_add_button (GTK_DIALOG (msg_dialog
),
475 if (gtk_dialog_run (GTK_DIALOG (msg_dialog
)) == GTK_RESPONSE_YES
)
476 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc
), uri
,
480 gtk_widget_destroy (msg_dialog
);
484 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc
), uri
, NULL
);
487 if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (docman
->priv
->preferences
),
488 EDITOR_TABS_ORDERING
))
489 anjuta_docman_order_tabs (docman
);
491 gtk_widget_destroy (dialog
);
493 gnome_vfs_uri_unref (vfs_uri
);
498 anjuta_docman_save_document (AnjutaDocman
*docman
, IAnjutaDocument
*doc
,
499 GtkWidget
*parent_window
)
504 uri
= ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
508 anjuta_docman_set_current_document (docman
, doc
);
509 ret
= anjuta_docman_save_document_as (docman
, doc
, parent_window
);
513 /* TODO: Error checking */
514 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc
), NULL
);
522 anjuta_docman_dispose (GObject
*obj
)
524 AnjutaDocman
*docman
;
527 docman
= ANJUTA_DOCMAN (obj
);
528 docman
->priv
->shutingdown
= TRUE
;
530 DEBUG_PRINT ("Disposing AnjutaDocman object");
531 if (docman
->priv
->popup_menu
)
533 gtk_widget_destroy (docman
->priv
->popup_menu
);
534 docman
->priv
->popup_menu
= NULL
;
536 if (docman
->priv
->pages
)
538 /* Destroy all page data (more than just the notebook-page-widgets) */
541 pages
= docman
->priv
->pages
; /*work with copy so var can be NULL'ed ASAP*/
542 docman
->priv
->pages
= NULL
;
543 for (node
= pages
; node
!= NULL
; node
= g_list_next (node
))
545 /* this also tries to destroy any notebook-page-widgets, in case
546 they're not gone already
547 CHECKME at shutdown do we need "destroy" signals in case other plugins
548 hold refs on any page(s) or their contents ?
550 anjuta_docman_page_destroy ((AnjutaDocmanPage
*)node
->data
);
554 GNOME_CALL_PARENT (G_OBJECT_CLASS
, dispose
, (G_OBJECT(obj
)));
558 anjuta_docman_finalize (GObject
*obj
)
560 AnjutaDocman
*docman
;
562 DEBUG_PRINT ("Finalising AnjutaDocman object");
563 docman
= ANJUTA_DOCMAN (obj
);
566 if (docman
->priv
->fileselection
)
567 gtk_widget_destroy (docman
->priv
->fileselection
);
568 g_free (docman
->priv
);
571 GNOME_CALL_PARENT (G_OBJECT_CLASS
, finalize
, (G_OBJECT(obj
)));
575 anjuta_docman_instance_init (AnjutaDocman
*docman
)
577 docman
->priv
= g_new0 (AnjutaDocmanPriv
, 1);
578 /*g_new0 NULL's all content
579 docman->priv->popup_menu = NULL;
580 docman->priv->popup_menu_det = NULL;
581 docman->priv->fileselection = NULL;
583 gtk_notebook_popup_enable (GTK_NOTEBOOK (docman
));
584 gtk_notebook_set_scrollable (GTK_NOTEBOOK (docman
), TRUE
);
585 g_signal_connect (G_OBJECT(docman
), "switch-page",
586 G_CALLBACK (on_notebook_switch_page
), docman
);
590 anjuta_docman_class_init (AnjutaDocmanClass
*klass
)
592 static gboolean initialized
;
593 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
595 parent_class
= g_type_class_peek_parent (klass
);
596 object_class
->finalize
= anjuta_docman_finalize
;
597 object_class
->dispose
= anjuta_docman_dispose
;
604 docman_signals
[DOC_ADDED
] =
605 g_signal_new ("document-added",
608 G_STRUCT_OFFSET (AnjutaDocmanClass
, document_added
),
610 g_cclosure_marshal_VOID__OBJECT
,
614 docman_signals
[DOC_CHANGED
] =
615 g_signal_new ("document-changed",
618 G_STRUCT_OFFSET (AnjutaDocmanClass
, document_changed
),
620 g_cclosure_marshal_VOID__OBJECT
,
629 anjuta_docman_new (DocmanPlugin
* plugin
, AnjutaPreferences
*pref
)
633 docman
= gtk_widget_new (ANJUTA_TYPE_DOCMAN
, NULL
);
636 ANJUTA_DOCMAN (docman
)->priv
->plugin
= plugin
;
637 ANJUTA_DOCMAN (docman
)->priv
->preferences
= pref
;
643 /*! state flag for Ctrl-TAB */
644 static gboolean g_tabbing
= FALSE
;
647 on_notebook_switch_page (GtkNotebook
* notebook
,
648 GtkNotebookPage
* page
,
649 gint page_num
, AnjutaDocman
*docman
)
651 if (!docman
->priv
->shutingdown
)
653 GtkWidget
*page_widget
;
654 /* TTimo: reorder so that the most recently used files are always
655 * at the beginning of the tab list
657 page_widget
= gtk_notebook_get_nth_page (notebook
, page_num
);
658 anjuta_docman_set_current_document (docman
, IANJUTA_DOCUMENT (page_widget
));
661 !anjuta_preferences_get_int (docman
->priv
->preferences
, EDITOR_TABS_ORDERING
) &&
662 anjuta_preferences_get_int (docman
->priv
->preferences
, EDITOR_TABS_RECENT_FIRST
))
664 gtk_notebook_reorder_child (notebook
, page_widget
, 0);
670 on_document_save_point (IAnjutaDocument
*doc
, gboolean entering
,
671 AnjutaDocman
*docman
)
673 anjuta_docman_update_page_label (docman
, GTK_WIDGET (doc
));
677 on_document_destroy (IAnjutaDocument
*doc
, AnjutaDocman
*docman
)
679 AnjutaDocmanPage
*page
;
682 DEBUG_PRINT ("In function: on_document_destroy");
685 g_signal_handlers_disconnect_by_func (G_OBJECT (IANJUTA_EDITOR (doc
)),
686 G_CALLBACK (on_editor_save_point
),
688 g_signal_handlers_disconnect_by_func (G_OBJECT (IANJUTA_EDITOR (doc
)),
689 G_CALLBACK (on_editor_destroy
),
692 breakpoints_dbase_clear_all_in_editor (debugger
.breakpoints_dbase
, IANJUTA_EDITOR (doc
));
694 page
= anjuta_docman_get_page_for_document (docman
, doc
);
695 docman
->priv
->pages
= g_list_remove (docman
->priv
->pages
, page
);
697 if (!docman
->priv
->shutingdown
)
699 if (page
== docman
->priv
->cur_page
)
700 docman
->priv
->cur_page
= NULL
;
701 if (GTK_NOTEBOOK (docman
)->children
== NULL
)
702 anjuta_docman_set_current_document (docman
, NULL
);
705 GtkWidget
*page_widget
;
706 /* set a replacement active document */
707 page_num
= gtk_notebook_get_current_page (GTK_NOTEBOOK (docman
));
708 page_widget
= gtk_notebook_get_nth_page (GTK_NOTEBOOK (docman
), page_num
);
709 anjuta_docman_set_current_document (docman
, IANJUTA_DOCUMENT (page_widget
));
712 anjuta_docman_page_destroy (page
);
716 anjuta_docman_add_editor (AnjutaDocman
*docman
, const gchar
*uri
,
720 IAnjutaEditorFactory
* factory
;
722 factory
= anjuta_shell_get_interface(docman
->shell
, IAnjutaEditorFactory
, NULL
);
725 te
= ianjuta_editor_factory_new_editor(factory
,
728 te
= ianjuta_editor_factory_new_editor(factory
,
731 te
= ianjuta_editor_factory_new_editor(factory
,
734 te
= ianjuta_editor_factory_new_editor(factory
,
737 /* File cannot be loaded, texteditor brings up an error dialog */
740 ianjuta_editor_set_popup_menu (te
, docman
->priv
->popup_menu
, NULL
);
742 anjuta_docman_add_document(docman
, IANJUTA_DOCUMENT(te
), uri
);
748 anjuta_docman_add_document (AnjutaDocman
*docman
, IAnjutaDocument
*doc
,
751 AnjutaDocmanPage
*page
;
754 page
= anjuta_docman_page_new (doc
, docman
);
755 /* list order matches pages in book */
756 docman
->priv
->pages
= g_list_prepend (docman
->priv
->pages
, (gpointer
)page
);
758 page
->widget
= GTK_WIDGET (doc
); /* this is also the notebook-page child widget */
759 gtk_widget_show (page
->widget
);
760 g_object_ref (G_OBJECT (doc
)); /* compensate for unref in cleanup processes */
762 anjuta_docman_page_setup (page
, docman
);
764 uuri
= (uri
) ? (gchar
*)uri
: ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
765 ruri
= (uuri
) ? gnome_vfs_format_uri_for_display (uuri
) : NULL
;
769 /* set the tooltip */
771 GtkWidget
*event_box
;
772 #if !GTK_CHECK_VERSION (2,12,0)
773 EditorTooltips
*tooltips
;
774 tooltips
= editor_tooltips_new (); /*CHECKME is this ever cleaned ?*/
776 event_box
= g_object_get_data (G_OBJECT (page
->box
), "event_box");
777 tip
= g_markup_printf_escaped ("<b>%s</b> %s", _("Path:"), ruri
);
778 #if GTK_CHECK_VERSION (2,12,0)
779 gtk_widget_set_tooltip_markup (event_box
, tip
);
781 editor_tooltips_set_tip (tooltips
, event_box
, tip
, NULL
);
786 if (uuri
&& uuri
!= uri
)
789 gtk_notebook_prepend_page_menu (GTK_NOTEBOOK (docman
), page
->widget
,
790 page
->box
, page
->menu_label
);
791 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (docman
), page
->widget
, TRUE
);
793 g_signal_handlers_block_by_func (G_OBJECT (docman
),
794 (gpointer
) on_notebook_switch_page
,
796 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman
), 0);
797 g_signal_handlers_unblock_by_func (G_OBJECT (docman
),
798 (gpointer
) on_notebook_switch_page
,
801 if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (docman
->priv
->preferences
),
802 EDITOR_TABS_ORDERING
))
803 anjuta_docman_order_tabs (docman
);
805 g_signal_connect (G_OBJECT (doc
), "save_point",
806 G_CALLBACK (on_document_save_point
), docman
);
807 g_signal_connect (G_OBJECT (doc
), "destroy",
808 G_CALLBACK (on_document_destroy
), docman
);
810 g_signal_emit (G_OBJECT (docman
), docman_signals
[DOC_ADDED
], 0, doc
);
812 anjuta_docman_set_current_document (docman
, doc
);
814 anjuta_shell_present_widget (docman
->shell
, GTK_WIDGET (docman
), NULL
);
818 anjuta_docman_remove_document (AnjutaDocman
*docman
, IAnjutaDocument
*doc
)
820 AnjutaDocmanPage
*page
;
823 doc
= anjuta_docman_get_current_document (docman
);
828 /* removing child-widget unrefs that as well as all tab-related widgets
830 page->close_button, its refcount to 5
831 page->widget, its refcount to 1, & surviving object seems to be used elsewhere */
832 gtk_container_remove (GTK_CONTAINER (docman
), GTK_WIDGET (doc
));
834 page
= anjuta_docman_get_page_for_document (docman
, doc
);
837 docman
->priv
->pages
= g_list_remove (docman
->priv
->pages
, (gpointer
)page
);
841 /*CHECKME need something like this if other code can ref the document ?
842 if ((G_OBJECT (doc))->ref_count > 0)
843 g_signal_emit (G_OBJECT (docman), docman_signals[DOC_REMOVED], 0, doc);
848 anjuta_docman_set_popup_menu (AnjutaDocman
*docman
, GtkWidget
*menu
)
851 g_object_ref (G_OBJECT (menu
));
852 if (docman
->priv
->popup_menu
)
853 gtk_widget_destroy (docman
->priv
->popup_menu
);
854 docman
->priv
->popup_menu
= menu
;
859 anjuta_docman_get_current_focus_widget (AnjutaDocman
*docman
)
862 widget
= gtk_widget_get_toplevel (GTK_WIDGET (docman
));
863 if (GTK_WIDGET_TOPLEVEL (widget
) &&
864 gtk_window_has_toplevel_focus (GTK_WINDOW (widget
)))
866 return gtk_window_get_focus (GTK_WINDOW (widget
));
871 static AnjutaDocmanPage
*
872 anjuta_docman_get_page_for_document (AnjutaDocman
*docman
, IAnjutaDocument
*doc
)
875 node
= docman
->priv
->pages
;
878 AnjutaDocmanPage
*page
;
882 if (page
->widget
== GTK_WIDGET (doc
))
884 node
= g_list_next (node
);
890 anjuta_docman_get_current_document (AnjutaDocman
*docman
)
892 return docman
->priv
->current_document
;
896 anjuta_docman_set_current_document(AnjutaDocman
*docman
, IAnjutaDocument
* doc
)
898 AnjutaDocmanPage
*page
;
899 IAnjutaDocument
*defdoc
;
901 defdoc
= docman
->priv
->current_document
;
907 page
= docman
->priv
->cur_page
;
910 page
->is_current
= FALSE
;
911 if (page
->close_button
!= NULL
)
913 gtk_widget_set_sensitive (page
->close_image
, FALSE
);
915 gtk_widget_set_sensitive (page
->mime_icon
, FALSE
);
920 docman
->priv
->current_document
= doc
;
921 docman
->priv
->cur_page
= NULL
; /* default, altered if possible */
925 page
= anjuta_docman_get_page_for_document (docman
, doc
);
926 docman
->priv
->cur_page
= page
;
929 page
->is_current
= TRUE
;
930 if (page
->close_button
!= NULL
)
932 gtk_widget_set_sensitive (page
->close_image
, TRUE
);
934 gtk_widget_set_sensitive (page
->mime_icon
, TRUE
);
937 page_num
= gtk_notebook_page_num (GTK_NOTEBOOK (docman
),
939 g_signal_handlers_block_by_func (G_OBJECT (docman
),
940 (gpointer
) on_notebook_switch_page
, (gpointer
) docman
);
941 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman
), page_num
);
942 g_signal_handlers_unblock_by_func (G_OBJECT (docman
),
943 (gpointer
) on_notebook_switch_page
, (gpointer
) docman
);
945 /* CHECKME does this sorting need to be deferred ? */
946 if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (docman
->priv
->preferences
),
947 EDITOR_TABS_ORDERING
))
948 anjuta_docman_order_tabs (docman
);
950 gtk_widget_grab_focus (GTK_WIDGET (doc
));
951 anjuta_docman_grab_text_focus (docman
);
953 /* else //doc == NULL
955 const gchar *dir = g_get_home_dir();
959 if (IANJUTA_IS_EDITOR (doc
))
963 te
= IANJUTA_EDITOR (doc
);
967 uri
= ianjuta_file_get_uri (IANJUTA_FILE (te
), NULL
);
973 filename
= g_filename_from_uri (uri
, &hostname
, NULL
);
974 if (hostname
== NULL
&& filename
!= NULL
)
977 dir
= g_path_get_dirname (filename
);
980 chdir (dir
); /* ??? why is CWD relevant at all ?
981 Anything else might change CWD at any time */
992 g_signal_emit (G_OBJECT (docman
), docman_signals
[DOC_CHANGED
], 0, doc
);
996 anjuta_docman_goto_file_line (AnjutaDocman
*docman
, const gchar
*fname
, gint lineno
)
998 return anjuta_docman_goto_file_line_mark (docman
, fname
, lineno
, FALSE
);
1002 anjuta_docman_goto_file_line_mark (AnjutaDocman
*docman
, const gchar
*fname
,
1003 gint line
, gboolean mark
)
1005 gchar
*uri
, *te_uri
;
1006 GnomeVFSURI
* vfs_uri
;
1008 const gchar
*linenum
;
1010 gboolean is_local_uri
;
1011 gchar
*normalized_path
= NULL
;
1013 IAnjutaDocument
*doc
;
1016 g_return_val_if_fail (fname
, NULL
);
1019 /* filename = anjuta_docman_get_full_filename (docman, fname); */
1020 vfs_uri
= gnome_vfs_uri_new (fname
);
1022 /* Extract linenum which comes as fragment identifier */
1023 linenum
= gnome_vfs_uri_get_fragment_identifier (vfs_uri
);
1025 lineno
= atoi (linenum
);
1029 /* Restore URI without fragment identifier (linenum) */
1030 uri
= gnome_vfs_uri_to_string (vfs_uri
,
1031 GNOME_VFS_URI_HIDE_FRAGMENT_IDENTIFIER
);
1033 /* Get the normalized file path for comparision */
1034 is_local_uri
= gnome_vfs_uri_is_local (vfs_uri
);
1036 normalized_path
= realpath (gnome_vfs_uri_get_path (vfs_uri
), NULL
);
1037 if (normalized_path
== NULL
)
1038 normalized_path
= g_strdup (uri
);
1040 gnome_vfs_uri_unref (vfs_uri
);
1041 /* g_free(filename); */
1043 g_return_val_if_fail (uri
!= NULL
, NULL
);
1045 node
= docman
->priv
->pages
;
1047 /* first, try to use a document that's already open */
1050 AnjutaDocmanPage
*page
;
1052 page
= (AnjutaDocmanPage
*) node
->data
;
1053 doc
= IANJUTA_DOCUMENT (page
->widget
);
1054 if (!IANJUTA_IS_EDITOR (doc
))
1057 te_uri
= ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
1060 gboolean te_is_local_uri
;
1061 gchar
*te_normalized_path
;
1063 /* Get the normalized file path for comparision */
1064 vfs_uri
= gnome_vfs_uri_new (te_uri
);
1065 te_is_local_uri
= gnome_vfs_uri_is_local (vfs_uri
);
1066 if (te_is_local_uri
)
1067 te_normalized_path
= realpath (gnome_vfs_uri_get_path (vfs_uri
),
1070 te_normalized_path
= g_strdup (te_uri
);
1071 gnome_vfs_uri_unref (vfs_uri
);
1073 if (!normalized_path
|| !te_normalized_path
)
1075 DEBUG_PRINT ("Unexpected NULL path");
1077 g_free (te_normalized_path
);
1078 node
= g_list_next (node
);
1082 if (strcmp (normalized_path
, te_normalized_path
) == 0)
1086 ianjuta_editor_goto_line(IANJUTA_EDITOR(doc
), lineno
, NULL
);
1089 ianjuta_markable_delete_all_markers(IANJUTA_MARKABLE(doc
),
1090 IANJUTA_MARKABLE_LINEMARKER
,
1092 ianjuta_markable_mark(IANJUTA_MARKABLE(doc
), lineno
,
1093 IANJUTA_MARKABLE_LINEMARKER
, NULL
);
1096 anjuta_docman_present_notebook_page (docman
, doc
);
1097 an_file_history_push (te_uri
, lineno
);
1099 g_free (te_normalized_path
);
1101 g_free (normalized_path
);
1102 return IANJUTA_EDITOR (doc
);
1105 g_free (te_normalized_path
);
1107 node
= g_list_next (node
);
1109 /* no deal, open a new document */
1110 te
= anjuta_docman_add_editor (docman
, uri
, NULL
);
1113 te_uri
= ianjuta_file_get_uri (IANJUTA_FILE (te
), NULL
);
1114 an_file_history_push (te_uri
, lineno
);
1118 ianjuta_editor_goto_line(te
, lineno
, NULL
);
1121 ianjuta_markable_mark(IANJUTA_MARKABLE(te
), lineno
,
1122 IANJUTA_MARKABLE_LINEMARKER
, NULL
);
1127 g_free (normalized_path
);
1132 get_real_path(const gchar
*file_name
)
1136 gchar path
[PATH_MAX
+1];
1137 memset(path
, '\0', PATH_MAX
+1);
1138 realpath(file_name
, path
);
1139 return g_strdup(path
);
1146 anjuta_docman_get_full_filename (AnjutaDocman
*docman
, const gchar
*fn
)
1148 IAnjutaDocument
*doc
;
1153 g_return_val_if_fail(fn
, NULL
);
1154 real_path
= get_real_path (fn
);
1156 /* If it is full and absolute path, there is no need to
1157 go further, even if the file is not found*/
1163 /* First, check if we can get the file straightaway */
1164 if (g_file_test (real_path
, G_FILE_TEST_IS_REGULAR
))
1168 /* Get the name part of the file */
1169 fname
= g_path_get_basename (fn
);
1171 /* Next, check if the current text editor buffer matches this name */
1172 if (NULL
!= (doc
= anjuta_docman_get_current_document (docman
)))
1174 if (strcmp(ianjuta_document_get_filename(doc
, NULL
), fname
) == 0)
1177 return ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
1180 /* Next, see if the name matches any of the opened files */
1181 for (node
= docman
->priv
->pages
; node
!= NULL
; node
= g_list_next (node
))
1183 AnjutaDocmanPage
*page
;
1185 page
= (AnjutaDocmanPage
*) node
->data
;
1186 doc
= IANJUTA_DOCUMENT (page
->widget
);
1187 if (strcmp (fname
, ianjuta_document_get_filename (doc
, NULL
)) == 0)
1190 return ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
1198 anjuta_docman_present_notebook_page (AnjutaDocman
*docman
, IAnjutaDocument
*doc
)
1205 node
= docman
->priv
->pages
;
1209 AnjutaDocmanPage
* page
;
1210 page
= (AnjutaDocmanPage
*)node
->data
;
1211 if (page
&& IANJUTA_DOCUMENT (page
->widget
) == doc
)
1214 curindx
= gtk_notebook_page_num (GTK_NOTEBOOK (docman
), page
->widget
);
1215 if (!(curindx
== -1 || curindx
== gtk_notebook_get_current_page (GTK_NOTEBOOK (docman
))))
1216 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman
), curindx
);
1217 /* this is done by the page-switch cb
1218 if (!page->is_current)
1220 anjuta_docman_set_current_document (docman, doc);
1225 node
= g_list_next (node
);
1230 anjuta_docman_update_page_label (AnjutaDocman
*docman
, GtkWidget
*page_widget
)
1232 AnjutaDocmanPage
*page
;
1235 IAnjutaDocument
*doc
;
1236 const gchar
* doc_filename
;
1240 doc
= IANJUTA_DOCUMENT (page_widget
);
1244 page
= anjuta_docman_get_page_for_document (docman
, doc
);
1245 if (!page
|| page
->label
== NULL
|| page
->menu_label
== NULL
)
1248 if (!ianjuta_file_savable_is_dirty(IANJUTA_FILE_SAVABLE (doc
), NULL
))
1257 uri
= ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
1260 basename
= g_path_get_basename (uri
);
1261 label
= g_strconcat(basename
, dirty_char
, NULL
);
1262 gtk_label_set_text (GTK_LABEL (page
->label
), label
);
1263 gtk_label_set_text (GTK_LABEL (page
->menu_label
), label
);
1268 else if ((doc_filename
= ianjuta_document_get_filename (doc
, NULL
)) != NULL
)
1270 label
= g_strconcat (doc_filename
, dirty_char
, NULL
);
1271 gtk_label_set_text (GTK_LABEL (page
->label
), label
);
1272 gtk_label_set_text (GTK_LABEL (page
->menu_label
), label
);
1278 anjuta_docman_grab_text_focus (AnjutaDocman
*docman
)
1280 anjuta_shell_present_widget(docman
->shell
,
1281 GTK_WIDGET(docman
->priv
->plugin
->vbox
), NULL
);
1285 anjuta_docman_delete_all_markers (AnjutaDocman
*docman
, gint marker
)
1289 for (node
= docman
->priv
->pages
; node
!= NULL
; node
= g_list_next (node
))
1291 AnjutaDocmanPage
*page
;
1295 te
= IANJUTA_EDITOR (page
->widget
);
1296 ianjuta_markable_delete_all_markers(IANJUTA_MARKABLE(te
), marker
, NULL
);
1301 anjuta_docman_delete_all_indicators (AnjutaDocman
*docman
)
1305 for (node
= docman
->priv
->pages
; node
; node
= g_list_next (node
))
1307 AnjutaDocmanPage
*page
;
1311 page
= (AnjutaDocmanPage
*) node
->data
;
1312 te
= IANJUTA_EDITOR (page
->widget
);
1313 uri
= ianjuta_file_get_uri (IANJUTA_FILE (te
), NULL
);
1317 ianjuta_markable_unmark(IANJUTA_MARKABLE(te
), -1, -1, NULL
);
1322 /* Saves a file to keep it synchronized with external programs */
1324 anjuta_docman_save_file_if_modified (AnjutaDocman
*docman
, const gchar
*szFullPath
)
1326 IAnjutaDocument
*doc
;
1328 g_return_if_fail ( szFullPath
!= NULL
);
1330 doc
= anjuta_docman_get_document_for_path (docman
, szFullPath
);
1333 if(ianjuta_file_savable_is_dirty (IANJUTA_FILE_SAVABLE (doc
), NULL
))
1335 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc
), NULL
);
1340 /* If an external program changed the file, we must reload it */
1342 anjuta_docman_reload_file (AnjutaDocman
*docman
, const gchar
*szFullPath
)
1344 IAnjutaDocument
*doc
;
1346 g_return_if_fail (szFullPath
!= NULL
);
1348 doc
= anjuta_docman_get_document_for_path (docman
, szFullPath
);
1349 if (doc
&& IANJUTA_IS_EDITOR (doc
))
1352 te
= IANJUTA_EDITOR (doc
);
1353 glong nNowPos
= ianjuta_editor_get_lineno (te
, NULL
);
1354 ianjuta_file_open (IANJUTA_FILE (doc
), szFullPath
, NULL
);
1355 ianjuta_editor_goto_line(te
, nNowPos
, NULL
);
1359 typedef struct _order_struct order_struct
;
1360 struct _order_struct
1362 const gchar
*m_label
;
1363 GtkWidget
*m_widget
;
1367 do_ordertab1 (const void *a
, const void *b
)
1369 order_struct aos
,bos
;
1370 aos
= *(order_struct
*)a
;
1371 bos
= *(order_struct
*)b
;
1372 return (g_strcasecmp (aos
.m_label
, bos
.m_label
)); /* need g_utf8_collate() ? */
1376 anjuta_docman_order_tabs (AnjutaDocman
*docman
)
1379 GtkWidget
*page_widget
;
1380 order_struct
*tab_labels
;
1381 GtkNotebook
*notebook
;
1383 notebook
= GTK_NOTEBOOK (docman
);
1385 num_pages
= gtk_notebook_get_n_pages (notebook
);
1388 tab_labels
= g_new0 (order_struct
, num_pages
);
1389 for (i
= 0; i
< num_pages
; i
++)
1391 /*new0 NULL'ed things already
1392 if((widget = gtk_notebook_get_nth_page (notebook, i)) == NULL)
1394 tab_labels[i].m_label = NULL;
1395 tab_labels[i].m_widget = NULL;
1399 if ((page_widget
= gtk_notebook_get_nth_page (notebook
, i
)) != NULL
)
1401 tab_labels
[i
].m_widget
= page_widget
; /* CHECKME needed ? */
1402 tab_labels
[i
].m_label
= ianjuta_document_get_filename (
1403 IANJUTA_DOCUMENT (page_widget
), NULL
);
1406 qsort (tab_labels
, num_pages
, sizeof(order_struct
), do_ordertab1
);
1407 for (i
= 0; i
< num_pages
; i
++)
1408 gtk_notebook_reorder_child (notebook
, tab_labels
[i
].m_widget
, i
);
1409 g_free (tab_labels
);
1414 anjuta_docman_set_editor_properties (AnjutaDocman
*docman
)
1417 TextEditor *te = IANJUTA_EDITOR (docman->priv->current_document);
1421 // FIXME: anjuta_set_file_properties (app->current_text_editor->uri);
1422 word = text_editor_get_current_word (te);
1423 prop_set_with_key (te->props_base, "current.file.selection", word?word:"");
1426 prop_set_int_with_key (te->props_base, "current.file.lineno",
1427 text_editor_get_current_lineno (te));
1436 anjuta_docman_get_document_for_path (AnjutaDocman
*docman
, const gchar
*file_path
)
1440 g_return_val_if_fail (file_path
!= NULL
, NULL
);
1442 for (node
= docman
->priv
->pages
; node
!= NULL
; node
= g_list_next (node
))
1444 AnjutaDocmanPage
*page
;
1445 page
= (AnjutaDocmanPage
*) node
->data
;
1447 if (page
&& page
->widget
&& IANJUTA_IS_DOCUMENT (page
->widget
))
1449 IAnjutaDocument
*doc
;
1452 doc
= IANJUTA_DOCUMENT (page
->widget
);
1453 uri
= ianjuta_file_get_uri (IANJUTA_FILE (doc
), NULL
);
1456 if (0 == strcmp (file_path
, uri
))
1469 anjuta_docman_get_all_doc_widgets (AnjutaDocman
*docman
)
1475 for (node
= docman
->priv
->pages
; node
!= NULL
; node
= g_list_next (node
))
1477 AnjutaDocmanPage
*page
;
1478 page
= (AnjutaDocmanPage
*) node
->data
;
1479 if (page
&& page
->widget
)
1480 wids
= g_list_prepend (wids
, page
->widget
);
1483 wids
= g_list_reverse (wids
);
1487 ANJUTA_TYPE_BEGIN(AnjutaDocman
, anjuta_docman
, GTK_TYPE_NOTEBOOK
);