Reverted changes from Revision 3989
[anjuta-git-plugin.git] / plugins / document-manager / anjuta-docman.c
blob0eaa1e347d2148a974b4849b04b055151bd73ecf
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 anjuta-docman.c
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"
38 #include "plugin.h"
39 #include "action-callbacks.h"
40 #include "editor-tooltips.h"
42 #define MENU_PLACEHOLDER "/MenuMain/PlaceHolderDocumentsMenus/Documents/PlaceholderDocuments"
44 static gpointer parent_class;
46 enum
48 DOC_ADDED,
49 DOC_CHANGED,
50 LAST_SIGNAL
53 /* Preference keys */
54 #define EDITOR_TABS_POS "editor.tabs.pos"
55 #define EDITOR_TABS_HIDE "editor.tabs.hide"
56 #define EDITOR_TABS_ORDERING "editor.tabs.ordering"
57 #define EDITOR_TABS_RECENT_FIRST "editor.tabs.recent.first"
59 typedef struct _AnjutaDocmanPage AnjutaDocmanPage;
61 struct _AnjutaDocmanPriv {
62 DocmanPlugin *plugin;
63 AnjutaPreferences *preferences;
64 GList *pages; /* list of AnjutaDocmanPage's */
65 AnjutaDocmanPage *cur_page;
66 IAnjutaDocument *current_document; /* normally == IANJUTA_DOCUMENT (cur_page->widget) */
68 GtkWidget *fileselection;
70 GtkWidget *popup_menu; /* shared context-menu for main-notebook pages */
71 gboolean tab_pressed; /* flag for deferred notebook page re-arrangement */
72 gboolean shutingdown;
74 GSList* radio_group;
75 GtkActionGroup *documents_action_group;
76 gint documents_merge_id;
79 struct _AnjutaDocmanPage {
80 GtkWidget *widget; /* notebook-page widget, a GTK_WIDGET (IAnjutaDocument*) */
81 GtkWidget *box; /* notebook-tab-label parent widget */
82 GtkWidget *menu_box; /* notebook-tab-menu parent widget */
83 GtkWidget *close_image;
84 GtkWidget *close_button;
85 GtkWidget *mime_icon;
86 GtkWidget *label;
87 GtkWidget *menu_label; /* notebook page-switch menu-label */
88 gboolean is_current;
91 static guint docman_signals[LAST_SIGNAL] = { 0 };
93 static void anjuta_docman_order_tabs (AnjutaDocman *docman);
94 static void anjuta_docman_update_page_label (AnjutaDocman *docman,
95 GtkWidget *doc_widget);
96 static void anjuta_docman_grab_text_focus (AnjutaDocman *docman);
97 static gboolean anjuta_docman_sort_pagelist (AnjutaDocman *docman);
98 static void on_notebook_switch_page (GtkNotebook *notebook,
99 GtkNotebookPage *page,
100 gint page_num, AnjutaDocman *docman);
101 static AnjutaDocmanPage *
102 anjuta_docman_get_page_for_document (AnjutaDocman *docman,
103 IAnjutaDocument *doc);
105 static void
106 on_document_toggled (GtkAction* action,
107 AnjutaDocman* docman)
109 gint n;
111 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) == FALSE)
112 return;
114 n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
115 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman), n);
118 static void
119 anjuta_docman_update_documents_menu_status (AnjutaDocman* docman)
121 AnjutaDocmanPriv *priv = docman->priv;
122 GtkUIManager* ui = GTK_UI_MANAGER (anjuta_shell_get_ui (ANJUTA_PLUGIN (priv->plugin)->shell,
123 NULL));
124 GtkAction* action;
125 gint n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (docman));
126 gint current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (docman));
128 action = gtk_ui_manager_get_action (ui,
129 "/MenuMain/PlaceHolderDocumentsMenus/Documents/PreviousDocument");
130 g_object_set (action, "sensitive", current_page > 0, NULL);
131 action = gtk_ui_manager_get_action (ui,
132 "/MenuMain/PlaceHolderDocumentsMenus/Documents/NextDocument");
133 g_object_set (action, "sensitive", (current_page + 1) < n_pages, NULL);
136 static void
137 anjuta_docman_update_documents_menu (AnjutaDocman* docman)
139 AnjutaDocmanPriv *priv = docman->priv;
140 GtkUIManager* ui = GTK_UI_MANAGER (anjuta_shell_get_ui (ANJUTA_PLUGIN (priv->plugin)->shell,
141 NULL));
142 GList *actions, *l;
143 gint n, i;
144 guint id;
145 GSList *group = NULL;
147 g_return_if_fail (priv->documents_action_group != NULL);
149 if (priv->documents_merge_id != 0)
150 gtk_ui_manager_remove_ui (ui,
151 priv->documents_merge_id);
153 actions = gtk_action_group_list_actions (priv->documents_action_group);
154 for (l = actions; l != NULL; l = l->next)
156 g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),
157 G_CALLBACK (on_document_toggled),
158 docman);
159 gtk_action_group_remove_action (priv->documents_action_group,
160 GTK_ACTION (l->data));
162 g_list_free (actions);
164 n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (docman));
166 id = (n > 0) ? gtk_ui_manager_new_merge_id (ui) : 0;
168 for (i = 0; i < n; i++)
170 AnjutaDocmanPage* page;
171 GtkRadioAction *action;
172 gchar *action_name;
173 const gchar *tab_name;
174 gchar *accel;
176 page = anjuta_docman_get_page_for_document (docman,
177 IANJUTA_DOCUMENT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (docman), i)));
179 /* NOTE: the action is associated to the position of the tab in
180 * the notebook not to the tab itself! This is needed to work
181 * around the gtk+ bug #170727: gtk leaves around the accels
182 * of the action. Since the accel depends on the tab position
183 * the problem is worked around, action with the same name always
184 * get the same accel.
186 action_name = g_strdup_printf ("Tab_%d", i);
187 tab_name = gtk_label_get_label (GTK_LABEL (page->label));
189 /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
190 accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
192 action = gtk_radio_action_new (action_name,
193 tab_name,
194 NULL,
195 NULL,
198 if (group != NULL)
199 gtk_radio_action_set_group (action, group);
201 /* note that group changes each time we add an action, so it must be updated */
202 group = gtk_radio_action_get_group (action);
204 gtk_action_group_add_action_with_accel (priv->documents_action_group,
205 GTK_ACTION (action),
206 accel);
208 g_signal_connect (action,
209 "toggled",
210 G_CALLBACK (on_document_toggled),
211 docman);
213 gtk_ui_manager_add_ui (ui,
215 MENU_PLACEHOLDER,
216 action_name, action_name,
217 GTK_UI_MANAGER_MENUITEM,
218 FALSE);
220 if (i == gtk_notebook_get_current_page (GTK_NOTEBOOK (docman)))
221 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
223 g_object_unref (action);
225 g_free (action_name);
226 g_free (accel);
228 anjuta_docman_update_documents_menu_status (docman);
229 priv->documents_merge_id = id;
232 static void
233 on_notebook_page_close_button_click (GtkButton* button,
234 AnjutaDocman* docman)
236 AnjutaDocmanPage *page;
238 page = docman->priv->cur_page;
239 if (page == NULL || page->close_button != GTK_WIDGET (button))
241 /* the close function works only on the current document */
242 GList* node;
243 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
245 IAnjutaDocument *doc;
246 page = (AnjutaDocmanPage *) node->data;
247 if (page->close_button == GTK_WIDGET (button))
249 doc = IANJUTA_DOCUMENT (page->widget);
250 anjuta_docman_set_current_document (docman, doc);
251 break;
254 if (node == NULL)
255 return;
258 if (page != NULL)
259 on_close_file_activate (NULL, docman->priv->plugin);
262 static void
263 on_notebook_page_close_button_enter (GtkButton *button,
264 AnjutaDocmanPage *page)
266 g_return_if_fail (page != NULL);
268 gtk_widget_set_sensitive (page->close_image, TRUE);
271 static void
272 on_notebook_page_close_button_leave (GtkButton* button,
273 AnjutaDocmanPage *page)
275 g_return_if_fail (page != NULL);
277 if (! page->is_current)
278 gtk_widget_set_sensitive (page->close_image,FALSE);
281 /* for managing deferred tab re-arrangement */
282 static gboolean
283 on_notebook_tab_btnpress (GtkWidget *wid, GdkEventButton *event, AnjutaDocman* docman)
285 if (event->type == GDK_BUTTON_PRESS && event->button != 3) /* right-click is for menu */
286 docman->priv->tab_pressed = TRUE;
288 return FALSE;
291 static gboolean
292 on_notebook_tab_btnrelease (GtkWidget *widget, GdkEventButton *event, AnjutaDocman* docman)
294 docman->priv->tab_pressed = FALSE;
296 if (anjuta_preferences_get_int (docman->priv->preferences, EDITOR_TABS_RECENT_FIRST))
298 GList *node;
300 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
302 AnjutaDocmanPage *page;
304 page = (AnjutaDocmanPage *)node->data;
305 if (page->box == widget)
307 gtk_notebook_reorder_child (GTK_NOTEBOOK (docman), page->widget, 0);
308 break;
313 return FALSE;
316 static void
317 on_notebook_page_reordered (GtkNotebook *notebook, GtkWidget *child,
318 guint page_num, AnjutaDocman *docman)
320 /* conform pagelist order */
321 g_idle_add ((GSourceFunc) anjuta_docman_sort_pagelist, docman);
323 anjuta_docman_update_documents_menu(docman);
326 static gint
327 anjuta_docman_compare_pages (AnjutaDocmanPage *a, AnjutaDocmanPage *b, AnjutaDocman *docman)
329 gint pa, pb;
330 GtkNotebook *book;
332 book = GTK_NOTEBOOK (docman);
333 pa = gtk_notebook_page_num (book, a->widget);
334 pb = gtk_notebook_page_num (book, b->widget);
335 return ((pa < pb) ? 1:-1);
338 /* this is for idle or timer callback, as well as direct usage */
339 static gboolean
340 anjuta_docman_sort_pagelist (AnjutaDocman *docman)
342 DEBUG_PRINT ("In function: anjuta_docman_sort_pagelist");
343 if (docman->priv->pages != NULL && g_list_next (docman->priv->pages) != NULL)
344 docman->priv->pages = g_list_sort_with_data (
345 docman->priv->pages,
346 (GCompareDataFunc) anjuta_docman_compare_pages,
347 docman);
348 return FALSE;
351 static void
352 anjuta_docman_page_init (AnjutaDocman *docman, IAnjutaDocument *doc,
353 const gchar *uri, AnjutaDocmanPage *page)
355 GtkWidget *close_button;
356 GtkWidget *close_pixmap;
357 GtkWidget *label, *menu_label;
358 GtkWidget *box, *menu_box;
359 GtkWidget *event_hbox;
360 GtkWidget *event_box;
361 #if !GTK_CHECK_VERSION (2,12,0)
362 static GtkTooltips *tooltips = NULL;
363 #endif
364 gint h, w;
365 GdkColor color;
366 const gchar *filename;
367 gchar *uuri, *ruri;
369 g_return_if_fail (IANJUTA_IS_DOCUMENT (doc));
371 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
373 close_pixmap = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
374 gtk_widget_show (close_pixmap);
376 /* setup close button, zero out {x,y} thickness to get smallest possible size */
377 close_button = gtk_button_new();
378 gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE);
379 gtk_container_add(GTK_CONTAINER(close_button), close_pixmap);
380 gtk_button_set_relief(GTK_BUTTON(close_button), GTK_RELIEF_NONE);
382 gtk_widget_set_name (close_button, "anjuta-tab-close-button");
384 gtk_widget_set_size_request (close_button, w, h);
385 #if GTK_CHECK_VERSION (2,12,0)
386 gtk_widget_set_tooltip_text (close_button, _("Close file"));
387 #else
388 if (tooltips == NULL)
389 tooltips = gtk_tooltips_new ();
390 gtk_tooltips_set_tip (GTK_TOOLTIPS (tooltips), close_button, _("Close file"),
391 NULL);
392 #endif
393 filename = ianjuta_document_get_filename (doc, NULL);
394 label = gtk_label_new (filename);
395 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
396 gtk_widget_show (label);
398 menu_label = gtk_label_new (filename);
399 gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5);
400 gtk_widget_show (menu_label);
401 menu_box = gtk_hbox_new(FALSE, 2);
403 color.red = 0;
404 color.green = 0;
405 color.blue = 0;
407 gtk_widget_modify_fg (close_button, GTK_STATE_NORMAL, &color);
408 gtk_widget_modify_fg (close_button, GTK_STATE_INSENSITIVE, &color);
409 gtk_widget_modify_fg (close_button, GTK_STATE_ACTIVE, &color);
410 gtk_widget_modify_fg (close_button, GTK_STATE_PRELIGHT, &color);
411 gtk_widget_modify_fg (close_button, GTK_STATE_SELECTED, &color);
412 gtk_widget_show(close_button);
414 box = gtk_hbox_new (FALSE, 2);
415 /* create our layout/event boxes */
416 event_box = gtk_event_box_new();
417 gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
419 event_hbox = gtk_hbox_new (FALSE, 2);
421 uuri = (uri) ? (gchar *)uri : ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
422 if (uuri != NULL)
424 /* add a nice mime-type icon if we can */
425 GdlIcons *icons;
426 GdkPixbuf *pixbuf;
427 icons = gdl_icons_new (16);
428 pixbuf = gdl_icons_get_uri_icon (icons, uuri);
429 if (pixbuf != NULL)
431 GtkWidget *image, *menu_image;
432 image = gtk_image_new_from_pixbuf (pixbuf);
433 menu_image = gtk_image_new_from_pixbuf (pixbuf);
434 gtk_box_pack_start (GTK_BOX (event_hbox), image, FALSE, FALSE, 0);
435 gtk_box_pack_start (GTK_BOX (menu_box), menu_image, FALSE, FALSE, 0);
436 page->mime_icon = image;
437 g_object_unref (G_OBJECT (pixbuf));
439 g_object_unref (G_OBJECT (icons));
440 ruri = gnome_vfs_format_uri_for_display (uuri);
441 if (uuri != uri)
442 g_free (uuri);
443 if (ruri != NULL)
445 /* set the tab-tooltip */
446 gchar *tip;
447 #if !GTK_CHECK_VERSION (2,12,0)
448 EditorTooltips *tooltips;
449 tooltips = editor_tooltips_new (); /*CHECKME is this ever cleaned ?*/
450 #endif
451 tip = g_markup_printf_escaped ("<b>%s</b> %s", _("Path:"), ruri);
452 #if GTK_CHECK_VERSION (2,12,0)
453 gtk_widget_set_tooltip_markup (event_box, tip);
454 #else
455 editor_tooltips_set_tip (tooltips, event_box, tip, NULL);
456 #endif
457 g_free (ruri);
458 g_free (tip);
462 gtk_box_pack_start (GTK_BOX (event_hbox), label, TRUE, TRUE, 0);
463 gtk_box_pack_start (GTK_BOX (event_hbox), close_button, FALSE, FALSE, 0);
464 gtk_container_add (GTK_CONTAINER (event_box), event_hbox);
466 /* setup the data hierarchy */
467 g_object_set_data (G_OBJECT (box), "event_box", event_box);
469 /* pack our top-level layout box */
470 gtk_box_pack_start (GTK_BOX (box), event_box, TRUE, TRUE, 0);
472 /* show the widgets of the tab */
473 gtk_widget_show_all(box);
475 /* menu box */
476 gtk_box_pack_start (GTK_BOX (menu_box), menu_label, TRUE, TRUE, 0);
477 gtk_widget_show_all (menu_box);
479 g_signal_connect (G_OBJECT (close_button), "clicked",
480 G_CALLBACK (on_notebook_page_close_button_click),
481 docman);
482 g_signal_connect (G_OBJECT (close_button), "enter",
483 G_CALLBACK (on_notebook_page_close_button_enter),
484 page);
485 g_signal_connect (G_OBJECT (close_button), "leave",
486 G_CALLBACK (on_notebook_page_close_button_leave),
487 page);
488 g_signal_connect (G_OBJECT (box), "button-press-event",
489 G_CALLBACK (on_notebook_tab_btnpress),
490 docman);
491 g_signal_connect (G_OBJECT (box), "button-release-event",
492 G_CALLBACK (on_notebook_tab_btnrelease),
493 docman);
495 page->widget = GTK_WIDGET (doc); /* this is also the notebook-page child widget */
496 page->box = box;
497 page->close_image = close_pixmap;
498 page->close_button = close_button;
499 page->label = label;
500 page->menu_box = menu_box;
501 page->menu_label = menu_label;
503 gtk_widget_show (page->widget);
506 static AnjutaDocmanPage *
507 anjuta_docman_page_new (void)
509 AnjutaDocmanPage *page;
511 page = g_new0 (AnjutaDocmanPage, 1); /* don't try to survive a memory-crunch */
512 return page;
515 static void
516 anjuta_docman_page_destroy (AnjutaDocmanPage *page)
518 /* Notebook holds a reference on the widget of page and destroys
519 * them properly
521 g_free (page);
524 static void
525 on_open_filesel_response (GtkDialog* dialog, gint id, AnjutaDocman *docman)
527 gchar *uri;
528 // unused gchar *entry_filename = NULL;
529 int i;
530 GSList * list;
531 int elements;
533 if (id != GTK_RESPONSE_ACCEPT)
535 gtk_widget_hide (docman->priv->fileselection);
536 return;
539 list = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog));
540 if (list != NULL)
542 elements = g_slist_length(list);
543 for (i = 0; i < elements; i++)
545 uri = g_slist_nth_data (list, i);
546 if (uri)
548 anjuta_docman_goto_uri_line (docman, uri, -1);
549 g_free (uri);
552 g_slist_free (list);
554 /* if (entry_filename)
556 list = g_slist_remove(list, entry_filename);
557 g_free(entry_filename);
563 static GtkWidget*
564 create_file_open_dialog_gui (GtkWindow* parent, AnjutaDocman* docman)
566 GtkWidget* dialog =
567 gtk_file_chooser_dialog_new (_("Open file"),
568 parent,
569 GTK_FILE_CHOOSER_ACTION_OPEN,
570 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
571 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
572 NULL);
573 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
574 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(dialog), TRUE);
575 g_signal_connect (G_OBJECT (dialog), "response",
576 G_CALLBACK (on_open_filesel_response), docman);
577 g_signal_connect_swapped (G_OBJECT (dialog), "delete-event",
578 G_CALLBACK (gtk_widget_hide), dialog);
579 return dialog;
582 static GtkWidget*
583 create_file_save_dialog_gui (GtkWindow* parent, AnjutaDocman* docman)
585 GtkWidget* dialog =
586 gtk_file_chooser_dialog_new (_("Save file as"),
587 parent,
588 GTK_FILE_CHOOSER_ACTION_SAVE,
589 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
590 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
591 NULL);
592 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
593 return dialog;
596 void
597 anjuta_docman_open_file (AnjutaDocman *docman)
599 if (!docman->priv->fileselection)
601 GtkWidget *parent;
602 parent = gtk_widget_get_toplevel (GTK_WIDGET (docman));
603 docman->priv->fileselection =
604 create_file_open_dialog_gui(GTK_WINDOW (parent), docman);
606 if (GTK_WIDGET_VISIBLE (docman->priv->fileselection))
607 gtk_window_present (GTK_WINDOW (docman->priv->fileselection));
608 else
609 gtk_widget_show (docman->priv->fileselection);
612 gboolean
613 anjuta_docman_save_document_as (AnjutaDocman *docman, IAnjutaDocument *doc,
614 GtkWidget *parent_window)
616 gchar* uri;
617 GnomeVFSURI* vfs_uri;
618 gchar* file_uri;
619 const gchar* filename;
620 GtkWidget *parent;
621 GtkWidget *dialog;
622 gint response;
623 gboolean file_saved = TRUE;
625 g_return_val_if_fail (ANJUTA_IS_DOCMAN (docman), FALSE);
626 g_return_val_if_fail (IANJUTA_IS_DOCUMENT (doc), FALSE);
628 if (parent_window)
630 parent = parent_window;
632 else
634 parent = gtk_widget_get_toplevel (GTK_WIDGET (docman));
637 dialog = create_file_save_dialog_gui (GTK_WINDOW (parent), docman);
639 if ((file_uri = ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL)) != NULL)
641 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (dialog), file_uri);
642 g_free (file_uri);
644 else if ((filename = ianjuta_document_get_filename (doc, NULL)) != NULL)
645 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
646 else
647 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "");
649 response = gtk_dialog_run (GTK_DIALOG (dialog));
650 if (response != GTK_RESPONSE_ACCEPT)
652 gtk_widget_destroy (dialog);
653 return FALSE;
656 uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
657 vfs_uri = gnome_vfs_uri_new(uri);
658 if (gnome_vfs_uri_exists(vfs_uri))
660 GtkWidget *msg_dialog;
661 msg_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
662 GTK_DIALOG_DESTROY_WITH_PARENT,
663 GTK_MESSAGE_QUESTION,
664 GTK_BUTTONS_NONE,
665 _("The file '%s' already exists.\n"
666 "Do you want to replace it with the"
667 " one you are saving?"),
668 uri);
669 gtk_dialog_add_button (GTK_DIALOG (msg_dialog),
670 GTK_STOCK_CANCEL,
671 GTK_RESPONSE_CANCEL);
672 anjuta_util_dialog_add_button (GTK_DIALOG (msg_dialog),
673 _("_Replace"),
674 GTK_STOCK_REFRESH,
675 GTK_RESPONSE_YES);
676 if (gtk_dialog_run (GTK_DIALOG (msg_dialog)) == GTK_RESPONSE_YES)
677 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc), uri,
678 NULL);
679 else
680 file_saved = FALSE;
681 gtk_widget_destroy (msg_dialog);
683 else
685 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc), uri, NULL);
688 if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (docman->priv->preferences),
689 EDITOR_TABS_ORDERING))
690 anjuta_docman_order_tabs (docman);
692 gtk_widget_destroy (dialog);
693 g_free (uri);
694 gnome_vfs_uri_unref (vfs_uri);
695 return file_saved;
698 gboolean
699 anjuta_docman_save_document (AnjutaDocman *docman, IAnjutaDocument *doc,
700 GtkWidget *parent_window)
702 gchar *uri;
703 gboolean ret;
705 uri = ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
707 if (uri == NULL)
709 anjuta_docman_set_current_document (docman, doc);
710 ret = anjuta_docman_save_document_as (docman, doc, parent_window);
712 else
714 /* TODO: Error checking */
715 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc), NULL);
716 g_free (uri);
717 ret = TRUE;
719 return ret;
722 static void
723 anjuta_docman_dispose (GObject *obj)
725 AnjutaDocman *docman;
726 GList *node;
728 docman = ANJUTA_DOCMAN (obj);
729 docman->priv->shutingdown = TRUE;
731 DEBUG_PRINT ("Disposing AnjutaDocman object");
732 if (docman->priv->popup_menu)
734 gtk_widget_destroy (docman->priv->popup_menu);
735 docman->priv->popup_menu = NULL;
737 if (docman->priv->pages)
739 /* Destroy all page data (more than just the notebook-page-widgets) */
740 GList *pages;
742 g_signal_handlers_disconnect_by_func (G_OBJECT (docman),
743 (gpointer) on_notebook_switch_page,
744 (gpointer) docman);
745 pages = docman->priv->pages; /*work with copy so var can be NULL'ed ASAP*/
746 docman->priv->pages = NULL;
747 for (node = pages; node != NULL; node = g_list_next (node))
749 /* this also tries to destroy any notebook-page-widgets, in case
750 they're not gone already
751 CHECKME at shutdown do we need "destroy" signals in case other plugins
752 hold refs on any page(s) or their contents ?
754 anjuta_docman_page_destroy ((AnjutaDocmanPage *)node->data);
756 g_list_free (pages);
758 G_OBJECT_CLASS (parent_class)->dispose (obj);
761 static void
762 anjuta_docman_finalize (GObject *obj)
764 AnjutaDocman *docman;
766 DEBUG_PRINT ("Finalising AnjutaDocman object");
767 docman = ANJUTA_DOCMAN (obj);
768 if (docman->priv)
770 if (docman->priv->fileselection)
771 gtk_widget_destroy (docman->priv->fileselection);
772 g_free (docman->priv);
773 docman->priv = NULL;
775 G_OBJECT_CLASS (parent_class)->finalize (obj);
778 static void
779 anjuta_docman_instance_init (AnjutaDocman *docman)
781 docman->priv = g_new0 (AnjutaDocmanPriv, 1);
782 /*g_new0 NULL's all content
783 docman->priv->popup_menu = NULL;
784 docman->priv->popup_menu_det = NULL;
785 docman->priv->fileselection = NULL;
787 gtk_notebook_popup_enable (GTK_NOTEBOOK (docman));
788 gtk_notebook_set_scrollable (GTK_NOTEBOOK (docman), TRUE);
789 g_signal_connect (G_OBJECT (docman), "switch-page",
790 G_CALLBACK (on_notebook_switch_page), docman);
791 /* update pages-list after re-ordering (or deleting) */
792 g_signal_connect (G_OBJECT (docman), "page-reordered",
793 G_CALLBACK (on_notebook_page_reordered), docman);
796 static void
797 anjuta_docman_class_init (AnjutaDocmanClass *klass)
799 static gboolean initialized;
800 GObjectClass *object_class = G_OBJECT_CLASS (klass);
802 parent_class = g_type_class_peek_parent (klass);
803 object_class->finalize = anjuta_docman_finalize;
804 object_class->dispose = anjuta_docman_dispose;
806 if (!initialized)
808 initialized = TRUE;
810 /* Signals */
811 docman_signals [DOC_ADDED] =
812 g_signal_new ("document-added",
813 ANJUTA_TYPE_DOCMAN,
814 G_SIGNAL_RUN_LAST,
815 G_STRUCT_OFFSET (AnjutaDocmanClass, document_added),
816 NULL, NULL,
817 g_cclosure_marshal_VOID__OBJECT,
818 G_TYPE_NONE,
820 G_TYPE_OBJECT);
821 docman_signals [DOC_CHANGED] =
822 g_signal_new ("document-changed",
823 ANJUTA_TYPE_DOCMAN,
824 G_SIGNAL_RUN_LAST,
825 G_STRUCT_OFFSET (AnjutaDocmanClass, document_changed),
826 NULL, NULL,
827 g_cclosure_marshal_VOID__OBJECT,
828 G_TYPE_NONE,
830 G_TYPE_OBJECT);
834 gtk_rc_parse_string ("style \"anjuta-tab-close-button-style\"\n"
835 "{\n"
836 "GtkWidget::focus-padding = 0\n"
837 "GtkWidget::focus-line-width = 0\n"
838 "xthickness = 0\n"
839 "ythickness = 0\n"
840 "}\n"
841 "widget \"*.anjuta-tab-close-button\" style \"anjuta-tab-close-button-style\"");
844 GtkWidget*
845 anjuta_docman_new (DocmanPlugin* plugin, AnjutaPreferences *pref)
848 GtkWidget *docman;
849 docman = gtk_widget_new (ANJUTA_TYPE_DOCMAN, NULL);
850 if (docman)
852 AnjutaUI* ui;
853 AnjutaDocman* real_docman = ANJUTA_DOCMAN (docman);
854 real_docman->priv->plugin = plugin;
855 real_docman->priv->preferences = pref;
856 real_docman->priv->documents_action_group = gtk_action_group_new ("ActionGroupDocument");
857 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
858 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), real_docman->priv->documents_action_group, 0);
859 g_object_unref (real_docman->priv->documents_action_group);
862 return docman;
865 /*! state flag for Ctrl-TAB */
866 static gboolean g_tabbing = FALSE;
868 static void
869 on_notebook_switch_page (GtkNotebook *notebook,
870 GtkNotebookPage *page,
871 gint page_num, AnjutaDocman *docman)
873 if (!docman->priv->shutingdown)
875 GtkWidget *page_widget;
876 gchar* action_name;
877 GtkAction* action;
879 page_widget = gtk_notebook_get_nth_page (notebook, page_num);
880 anjuta_docman_set_current_document (docman, IANJUTA_DOCUMENT (page_widget));
882 /* activate the right item in the documents menu */
883 action_name = g_strdup_printf ("Tab_%d", page_num);
884 action = gtk_action_group_get_action (docman->priv->documents_action_group,
885 action_name);
887 /* sometimes the action doesn't exist yet, and the proper action
888 * is set active during the documents list menu creation
889 * CHECK: would it be nicer if active_tab was a property and we monitored the notify signal?
891 if (action != NULL)
892 gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action),
893 page_num);
895 g_free (action_name);
897 /* TTimo: reorder so that the most recently used files are
898 * at the beginning of the tab list
900 if (!docman->priv->tab_pressed /* after a tab-click, sorting is done upon release */
901 && !g_tabbing
902 && !anjuta_preferences_get_int (docman->priv->preferences, EDITOR_TABS_ORDERING)
903 && anjuta_preferences_get_int (docman->priv->preferences, EDITOR_TABS_RECENT_FIRST))
905 gtk_notebook_reorder_child (notebook, page_widget, 0);
907 anjuta_docman_update_documents_menu_status (docman);
911 static void
912 on_document_save_point (IAnjutaDocument *doc, gboolean entering,
913 AnjutaDocman *docman)
915 anjuta_docman_update_page_label (docman, GTK_WIDGET (doc));
918 static void
919 on_document_destroy (IAnjutaDocument *doc, AnjutaDocman *docman)
921 AnjutaDocmanPage *page;
922 gint page_num;
924 g_signal_handlers_disconnect_by_func (G_OBJECT (doc),
925 G_CALLBACK (on_document_save_point),
926 docman);
927 g_signal_handlers_disconnect_by_func (G_OBJECT (doc),
928 G_CALLBACK (on_document_destroy),
929 docman);
931 page = anjuta_docman_get_page_for_document (docman, doc);
932 docman->priv->pages = g_list_remove (docman->priv->pages, page);
934 if (!docman->priv->shutingdown)
936 if (page == docman->priv->cur_page)
937 docman->priv->cur_page = NULL;
938 if (GTK_NOTEBOOK (docman)->children == NULL)
939 anjuta_docman_set_current_document (docman, NULL);
940 else
942 GtkWidget *page_widget;
943 /* set a replacement active document */
944 page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (docman));
945 page_widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (docman), page_num);
946 anjuta_docman_set_current_document (docman, IANJUTA_DOCUMENT (page_widget));
949 anjuta_docman_page_destroy (page);
953 * anjuta_docman_add_editor:
954 * @docman: pointer to docman data struct
955 * @uri: string with uri of file to edit, may be "" or NULL
956 * @name: string with name of file to edit, may be absolute path or just a basename or "" or NULL
958 * Add a new editor, working on specified uri or filename if any
960 * Return value: the editor
962 IAnjutaEditor *
963 anjuta_docman_add_editor (AnjutaDocman *docman, const gchar *uri,
964 const gchar *name)
966 gchar *freeme;
967 const gchar *_uri, *_name;
968 IAnjutaEditor *te;
969 IAnjutaEditorFactory* factory;
971 freeme = NULL;
972 factory = anjuta_shell_get_interface (docman->shell, IAnjutaEditorFactory, NULL);
974 if (uri == NULL)
976 if (name == NULL)
978 _uri = "";
979 _name = _uri;
981 else
983 checkpath:
984 /* the editor-backends work better with uri's */
985 if (g_path_is_absolute (name))
987 gchar *canonical_path;
989 canonical_path = anjuta_util_get_real_path (name);
990 if (canonical_path != NULL)
992 freeme = gnome_vfs_get_uri_from_local_path (canonical_path);
993 g_free (canonical_path);
994 _uri = freeme;
996 else
997 _uri = "";
999 _name = "";
1001 else
1003 _uri = "";
1004 _name = name;
1008 else /* uri != NULL */
1010 if (name == NULL)
1012 _uri = uri;
1013 _name = "";
1015 else
1017 if (*uri == '\0')
1018 goto checkpath;
1019 _uri = uri;
1020 _name = name;
1024 te = ianjuta_editor_factory_new_editor (factory, _uri, _name, NULL);
1025 /* if file cannot be loaded, text-editor brings up an error dialog ? */
1026 if (te != NULL)
1028 if (IANJUTA_IS_EDITOR (te))
1029 ianjuta_editor_set_popup_menu (te, docman->priv->popup_menu, NULL);
1030 anjuta_docman_add_document (docman, IANJUTA_DOCUMENT (te), _uri);
1032 g_free (freeme);
1033 return te;
1036 void
1037 anjuta_docman_add_document (AnjutaDocman *docman, IAnjutaDocument *doc,
1038 const gchar *uri)
1040 AnjutaDocmanPage *page;
1042 page = anjuta_docman_page_new ();
1043 anjuta_docman_page_init (docman, doc, uri, page); /* NULL uri is ok */
1045 /* list order matches pages in book, initially at least */
1046 docman->priv->pages = g_list_prepend (docman->priv->pages, (gpointer)page);
1048 gtk_notebook_prepend_page_menu (GTK_NOTEBOOK (docman), page->widget,
1049 page->box, page->menu_box);
1050 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (docman), page->widget,
1051 TRUE);
1053 g_signal_connect (G_OBJECT (doc), "save_point",
1054 G_CALLBACK (on_document_save_point), docman);
1055 g_signal_connect (G_OBJECT (doc), "destroy",
1056 G_CALLBACK (on_document_destroy), docman);
1058 g_object_ref (doc);
1060 g_signal_emit (G_OBJECT (docman), docman_signals[DOC_ADDED], 0, doc);
1061 anjuta_docman_set_current_document (docman, doc);
1062 anjuta_shell_present_widget (docman->shell, GTK_WIDGET (docman->priv->plugin->vbox), NULL);
1063 anjuta_docman_update_documents_menu (docman);
1066 void
1067 anjuta_docman_remove_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1069 AnjutaDocmanPage *page;
1071 if (!doc)
1072 doc = anjuta_docman_get_current_document (docman);
1074 if (!doc)
1075 return;
1077 /* removing child-widget unrefs that as well as all tab-related widgets
1078 CHECKME except
1079 page->close_button, its refcount to 5
1080 page->widget, its refcount to 1, & surviving object seems to be used elsewhere */
1081 gtk_container_remove (GTK_CONTAINER (docman), GTK_WIDGET (doc));
1083 page = anjuta_docman_get_page_for_document (docman, doc);
1084 if (page)
1086 if (page == docman->priv->cur_page)
1087 docman->priv->cur_page = NULL;
1088 docman->priv->pages = g_list_remove (docman->priv->pages, (gpointer)page);
1089 g_free (page);
1091 anjuta_docman_update_documents_menu(docman);
1092 g_object_unref (doc);
1095 void
1096 anjuta_docman_set_popup_menu (AnjutaDocman *docman, GtkWidget *menu)
1098 if (menu)
1099 g_object_ref (G_OBJECT (menu));
1100 if (docman->priv->popup_menu)
1101 gtk_widget_destroy (docman->priv->popup_menu);
1102 docman->priv->popup_menu = menu;
1106 GtkWidget *
1107 anjuta_docman_get_current_focus_widget (AnjutaDocman *docman)
1109 GtkWidget *widget;
1110 widget = gtk_widget_get_toplevel (GTK_WIDGET (docman));
1111 if (GTK_WIDGET_TOPLEVEL (widget) &&
1112 gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
1114 return gtk_window_get_focus (GTK_WINDOW (widget));
1116 return NULL;
1119 GtkWidget *
1120 anjuta_docman_get_current_popup (AnjutaDocman *docman)
1122 return docman->priv->popup_menu;
1125 static AnjutaDocmanPage *
1126 anjuta_docman_get_page_for_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1128 GList *node;
1129 node = docman->priv->pages;
1130 while (node)
1132 AnjutaDocmanPage *page;
1134 page = node->data;
1135 g_assert (page);
1136 if (page->widget == GTK_WIDGET (doc))
1137 return page;
1138 node = g_list_next (node);
1140 return NULL;
1143 IAnjutaDocument *
1144 anjuta_docman_get_current_document (AnjutaDocman *docman)
1146 return docman->priv->current_document;
1149 void
1150 anjuta_docman_set_current_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1152 AnjutaDocmanPage *page;
1153 IAnjutaDocument *defdoc;
1155 defdoc = docman->priv->current_document;
1156 if (defdoc == doc)
1157 return;
1159 if (doc != NULL)
1161 page = anjuta_docman_get_page_for_document (docman, doc);
1162 /* proceed only if page data has been added before */
1163 if (page)
1165 gint page_num;
1167 if (defdoc != NULL)
1169 AnjutaDocmanPage *oldpage;
1170 oldpage = docman->priv->cur_page;
1171 if (oldpage)
1173 oldpage->is_current = FALSE;
1174 if (oldpage->close_button != NULL)
1176 gtk_widget_set_sensitive (oldpage->close_image, FALSE);
1177 if (oldpage->mime_icon)
1178 gtk_widget_set_sensitive (oldpage->mime_icon, FALSE);
1183 docman->priv->current_document = doc;
1184 docman->priv->cur_page = page;
1186 page->is_current = TRUE;
1187 if (page->close_button != NULL)
1189 gtk_widget_set_sensitive (page->close_image, TRUE);
1190 if (page->mime_icon)
1191 gtk_widget_set_sensitive (page->mime_icon, TRUE);
1193 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (docman),
1194 GTK_WIDGET (doc));
1195 g_signal_handlers_block_by_func (G_OBJECT (docman),
1196 (gpointer) on_notebook_switch_page,
1197 (gpointer) docman);
1198 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman), page_num);
1199 g_signal_handlers_unblock_by_func (G_OBJECT (docman),
1200 (gpointer) on_notebook_switch_page,
1201 (gpointer) docman);
1203 if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (docman->priv->preferences),
1204 EDITOR_TABS_ORDERING))
1205 anjuta_docman_order_tabs (docman);
1207 gtk_widget_grab_focus (GTK_WIDGET (doc));
1208 anjuta_docman_grab_text_focus (docman);
1210 if (IANJUTA_IS_FILE (doc))
1212 gchar *uri;
1213 uri = ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
1214 if (uri)
1216 gchar *hostname;
1217 gchar *filename;
1219 filename = g_filename_from_uri (uri, &hostname, NULL);
1220 if (hostname == NULL && filename != NULL)
1222 gchar *dir;
1223 dir = g_path_get_dirname (filename);
1224 if (dir)
1226 chdir (dir); /* CHECKME why is CWD relevant at all ?
1227 Anything else might change CWD at any time */
1228 g_free (dir);
1231 g_free (hostname);
1232 g_free (filename);
1233 g_free (uri);
1238 else /* doc == NULL */
1240 if (defdoc != NULL)
1242 page = docman->priv->cur_page;
1243 if (page)
1245 page->is_current = FALSE;
1246 if (page->close_button != NULL)
1248 gtk_widget_set_sensitive (page->close_image, FALSE);
1249 if (page->mime_icon)
1250 gtk_widget_set_sensitive (page->mime_icon, FALSE);
1254 docman->priv->current_document = NULL;
1255 docman->priv->cur_page = NULL;
1258 if (doc == NULL || page != NULL)
1259 g_signal_emit (G_OBJECT (docman), docman_signals[DOC_CHANGED], 0, doc);
1262 IAnjutaEditor *
1263 anjuta_docman_goto_uri_line (AnjutaDocman *docman, const gchar *uri, gint lineno)
1265 return anjuta_docman_goto_uri_line_mark (docman, uri, lineno, FALSE);
1268 /* file_uri must be an escaped URI string such as returned by
1269 gnome_vfs_get_uri_from_local_path() */
1270 IAnjutaEditor *
1271 anjuta_docman_goto_uri_line_mark (AnjutaDocman *docman, const gchar *file_uri,
1272 gint line, gboolean mark)
1274 GnomeVFSURI* vfs_uri;
1275 gchar *uri;
1276 const gchar *fragment;
1277 gint lineno;
1279 IAnjutaDocument *doc;
1280 IAnjutaEditor *te;
1282 g_return_val_if_fail (file_uri != NULL, NULL);
1284 vfs_uri = gnome_vfs_uri_new (file_uri);
1285 g_return_val_if_fail (vfs_uri != NULL, NULL);
1287 /* Extract linenum which sometimes comes as an appended uri fragment
1288 e.g. when loading a file at session start or later */
1289 fragment = gnome_vfs_uri_get_fragment_identifier (vfs_uri);
1290 if (fragment)
1292 const gchar *numstart;
1293 gchar *numend;
1294 gulong converted;
1296 DEBUG_PRINT ("uri fragment provided for %s line %d", file_uri, line);
1297 /* the real uri may have fragment(s) for vfs as well as for line-number */
1298 numstart = strrchr (fragment, '#');
1299 if (numstart == NULL)
1300 numstart = fragment;
1301 else
1302 numstart++;
1303 converted = strtoul (numstart, &numend, 10);
1304 if (*numstart == '\0' || numend == numstart || *numend != '\0')
1306 lineno = line;
1307 uri = g_strdup (file_uri);
1309 else /* the number is valid */
1311 lineno = (gint) converted;
1313 /* Restore URI without fragment identifier (linenum) */
1314 uri = gnome_vfs_uri_to_string (vfs_uri,
1315 GNOME_VFS_URI_HIDE_FRAGMENT_IDENTIFIER);
1316 if (uri != NULL && numstart != fragment)
1318 gchar *freeme, *freeme2;
1319 freeme = uri;
1320 freeme2 = g_strndup (fragment, numstart-fragment);
1321 uri = g_strconcat (uri, "#", freeme2, NULL);
1322 g_free (freeme);
1323 g_free (freeme2);
1327 else
1329 lineno = line;
1330 uri = g_strdup (file_uri);
1333 gnome_vfs_uri_unref (vfs_uri);
1334 g_return_val_if_fail (uri != NULL, NULL);
1336 DEBUG_PRINT("get document %s", uri);
1337 /* if possible, use a document that's already open */
1338 doc = anjuta_docman_get_document_for_uri (docman, uri);
1339 if (doc == NULL)
1341 DEBUG_PRINT("open new %s", uri);
1342 /* no deal, open a new document */
1343 te = anjuta_docman_add_editor (docman, uri, NULL); /* CHECKME NULL if not IANJUTA_IS_EDITOR () ? */
1344 doc = IANJUTA_DOCUMENT (te);
1346 else if (IANJUTA_IS_EDITOR (doc))
1348 DEBUG_PRINT("get te");
1349 te = IANJUTA_EDITOR (doc);
1351 else
1353 doc = NULL;
1354 te = NULL;
1356 g_free (uri);
1358 if (te != NULL)
1360 gchar *te_uri = ianjuta_file_get_uri (IANJUTA_FILE (te), NULL);
1361 an_file_history_push (te_uri, lineno);
1362 g_free (te_uri);
1364 if (lineno >= 0)
1366 ianjuta_editor_goto_line (te, lineno, NULL);
1367 if (mark && IANJUTA_IS_MARKABLE (doc))
1369 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (doc),
1370 IANJUTA_MARKABLE_LINEMARKER,
1371 NULL);
1372 ianjuta_markable_mark (IANJUTA_MARKABLE (doc), lineno,
1373 IANJUTA_MARKABLE_LINEMARKER, NULL);
1376 anjuta_docman_present_notebook_page (docman, doc);
1379 return te;
1382 gchar *
1383 anjuta_docman_get_uri (AnjutaDocman *docman, const gchar *fn)
1385 IAnjutaDocument *doc;
1386 GList *node;
1387 gchar *real_path;
1388 gchar *fname;
1390 g_return_val_if_fail (fn, NULL);
1391 real_path = anjuta_util_get_real_path (fn);
1393 /* If it is full and absolute path, there is no need to
1394 go further, even if the file is not found*/
1395 if (fn[0] == '/')
1397 gchar *uri;
1399 uri = gnome_vfs_get_uri_from_local_path(real_path);
1400 g_free (real_path);
1402 return uri;
1405 /* First, check if we can get the file straightaway */
1406 if (g_file_test (real_path, G_FILE_TEST_IS_REGULAR))
1408 gchar *uri;
1410 uri = gnome_vfs_get_uri_from_local_path(real_path);
1411 g_free (real_path);
1413 return uri;
1415 g_free(real_path);
1417 /* Get the name part of the file */
1418 fname = g_path_get_basename (fn);
1420 /* Next, check if the current text editor buffer matches this name */
1421 if (NULL != (doc = anjuta_docman_get_current_document (docman)))
1423 if (strcmp(ianjuta_document_get_filename(doc, NULL), fname) == 0)
1425 g_free (fname);
1426 return ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
1429 /* Next, see if the name matches any of the opened files */
1430 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1432 AnjutaDocmanPage *page;
1434 page = (AnjutaDocmanPage *) node->data;
1435 doc = IANJUTA_DOCUMENT (page->widget);
1436 if (strcmp (fname, ianjuta_document_get_filename (doc, NULL)) == 0)
1438 g_free (fname);
1439 return ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
1442 g_free (fname);
1443 return NULL;
1446 void
1447 anjuta_docman_present_notebook_page (AnjutaDocman *docman, IAnjutaDocument *doc)
1449 GList *node;
1451 if (!doc)
1452 return;
1454 node = docman->priv->pages;
1456 while (node)
1458 AnjutaDocmanPage* page;
1459 page = (AnjutaDocmanPage *)node->data;
1460 if (page && IANJUTA_DOCUMENT (page->widget) == doc)
1462 gint curindx;
1463 curindx = gtk_notebook_page_num (GTK_NOTEBOOK (docman), page->widget);
1464 if (curindx != -1)
1466 if (curindx != gtk_notebook_get_current_page (GTK_NOTEBOOK (docman)))
1467 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman), curindx);
1468 else
1469 /* Make sure current page is visible */
1470 anjuta_docman_grab_text_focus (docman);
1472 break;
1474 node = g_list_next (node);
1478 static void
1479 anjuta_docman_update_page_label (AnjutaDocman *docman, GtkWidget *page_widget)
1481 AnjutaDocmanPage *page;
1482 gchar *basename;
1483 gchar *uri;
1484 IAnjutaDocument *doc;
1485 const gchar* doc_filename;
1486 gchar* dirty_char;
1487 gchar* label;
1489 doc = IANJUTA_DOCUMENT (page_widget);
1490 if (doc == NULL)
1491 return;
1493 page = anjuta_docman_get_page_for_document (docman, doc);
1494 if (!page || page->label == NULL || page->menu_label == NULL)
1495 return;
1497 if (!ianjuta_file_savable_is_dirty(IANJUTA_FILE_SAVABLE (doc), NULL))
1499 dirty_char = "";
1501 else
1503 dirty_char = "*";
1506 uri = ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
1507 if (uri)
1509 basename = g_path_get_basename (uri);
1510 label = g_strconcat(dirty_char, basename, NULL);
1511 gtk_label_set_text (GTK_LABEL (page->label), label);
1512 gtk_label_set_text (GTK_LABEL (page->menu_label), label);
1513 g_free (label);
1514 g_free (basename);
1515 g_free (uri);
1517 else if ((doc_filename = ianjuta_document_get_filename (doc, NULL)) != NULL)
1519 label = g_strconcat (dirty_char, doc_filename, NULL);
1520 gtk_label_set_text (GTK_LABEL (page->label), label);
1521 gtk_label_set_text (GTK_LABEL (page->menu_label), label);
1522 g_free (label);
1526 static void
1527 anjuta_docman_grab_text_focus (AnjutaDocman *docman)
1529 anjuta_shell_present_widget (docman->shell,
1530 GTK_WIDGET (docman->priv->plugin->vbox), NULL);
1533 void
1534 anjuta_docman_delete_all_markers (AnjutaDocman *docman, gint marker)
1536 GList *node;
1538 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1540 AnjutaDocmanPage *page;
1542 page = (AnjutaDocmanPage *) node->data;
1543 if (IANJUTA_IS_EDITOR (page->widget))
1545 IAnjutaEditor* te;
1547 te = IANJUTA_EDITOR (page->widget);
1548 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (te), marker, NULL);
1553 void
1554 anjuta_docman_delete_all_indicators (AnjutaDocman *docman)
1556 GList *node;
1558 for (node = docman->priv->pages; node; node = g_list_next (node))
1560 AnjutaDocmanPage *page;
1562 page = (AnjutaDocmanPage *) node->data;
1563 if (IANJUTA_IS_EDITOR (page->widget))
1565 gchar *uri;
1567 uri = ianjuta_file_get_uri (IANJUTA_FILE (page->widget), NULL);
1568 if (uri)
1570 g_free (uri);
1571 ianjuta_markable_unmark (IANJUTA_MARKABLE (page->widget), -1, -1, NULL);
1577 /* Saves a file to keep it synchronized with external programs */
1578 /* CHECKME unused */
1579 void
1580 anjuta_docman_save_file_if_modified (AnjutaDocman *docman, const gchar *uri)
1582 IAnjutaDocument *doc;
1584 g_return_if_fail (uri != NULL);
1586 doc = anjuta_docman_get_document_for_uri (docman, uri);
1587 if (doc)
1589 if(ianjuta_file_savable_is_dirty (IANJUTA_FILE_SAVABLE (doc), NULL))
1591 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc), NULL);
1596 /* If an external program changed the file, we must reload it */
1597 /* CHECKME unused */
1598 void
1599 anjuta_docman_reload_file (AnjutaDocman *docman, const gchar *uri)
1601 IAnjutaDocument *doc;
1603 g_return_if_fail (uri != NULL);
1605 doc = anjuta_docman_get_document_for_uri (docman, uri);
1606 if (doc && IANJUTA_IS_EDITOR (doc))
1608 IAnjutaEditor *te;
1609 te = IANJUTA_EDITOR (doc);
1610 glong nNowPos = ianjuta_editor_get_lineno (te, NULL);
1611 ianjuta_file_open (IANJUTA_FILE (doc), uri, NULL);
1612 ianjuta_editor_goto_line (te, nNowPos, NULL);
1616 typedef struct _order_struct order_struct;
1617 struct _order_struct
1619 const gchar *m_label;
1620 GtkWidget *m_widget;
1623 static int
1624 do_ordertab1 (const void *a, const void *b)
1626 order_struct aos,bos;
1627 aos = *(order_struct*)a;
1628 bos = *(order_struct*)b;
1629 return (g_strcasecmp (aos.m_label, bos.m_label)); /* need g_utf8_collate() ? */
1632 static void
1633 anjuta_docman_order_tabs (AnjutaDocman *docman)
1635 gint i, num_pages;
1636 GtkWidget *page_widget;
1637 order_struct *tab_labels;
1638 GtkNotebook *notebook;
1640 notebook = GTK_NOTEBOOK (docman);
1642 num_pages = gtk_notebook_get_n_pages (notebook);
1643 if (num_pages < 2)
1644 return;
1645 tab_labels = g_new0 (order_struct, num_pages);
1646 for (i = 0; i < num_pages; i++)
1648 /*new0 NULL'ed things already
1649 if((widget = gtk_notebook_get_nth_page (notebook, i)) == NULL)
1651 tab_labels[i].m_label = NULL;
1652 tab_labels[i].m_widget = NULL;
1654 else
1656 if ((page_widget = gtk_notebook_get_nth_page (notebook, i)) != NULL)
1658 tab_labels[i].m_widget = page_widget; /* CHECKME needed ? */
1659 tab_labels[i].m_label = ianjuta_document_get_filename (
1660 IANJUTA_DOCUMENT (page_widget), NULL);
1663 qsort (tab_labels, num_pages, sizeof(order_struct), do_ordertab1);
1664 g_signal_handlers_block_by_func (G_OBJECT (notebook),
1665 (gpointer) on_notebook_page_reordered,
1666 (gpointer) docman);
1667 for (i = 0; i < num_pages; i++)
1668 gtk_notebook_reorder_child (notebook, tab_labels[i].m_widget, i);
1669 g_signal_handlers_unblock_by_func (G_OBJECT (notebook),
1670 (gpointer) on_notebook_page_reordered,
1671 (gpointer) docman);
1672 g_free (tab_labels);
1673 /* adjust pagelist order */
1674 g_idle_add ((GSourceFunc) anjuta_docman_sort_pagelist, docman);
1678 gboolean
1679 anjuta_docman_set_editor_properties (AnjutaDocman *docman)
1681 /* FIXME:
1682 TextEditor *te = IANJUTA_EDITOR (docman->priv->current_document);
1683 if (te)
1685 gchar *word;
1686 // FIXME: anjuta_set_file_properties (app->current_text_editor->uri);
1687 word = text_editor_get_current_word (te);
1688 prop_set_with_key (te->props_base, "current.file.selection", word?word:"");
1689 if (word)
1690 g_free(word);
1691 prop_set_int_with_key (te->props_base, "current.file.lineno",
1692 text_editor_get_current_lineno (te));
1693 return TRUE;
1695 else
1696 return FALSE; */
1697 return TRUE;
1700 IAnjutaDocument *
1701 anjuta_docman_get_document_for_uri (AnjutaDocman *docman, const gchar *file_uri)
1703 gchar *local_path;
1704 gchar *normalized_path;
1705 GList *node;
1707 g_return_val_if_fail (file_uri != NULL, NULL);
1709 local_path = gnome_vfs_get_local_path_from_uri (file_uri);
1710 /* grab a normalized file path for effective comparision */
1711 normalized_path = anjuta_util_get_real_path (local_path);
1712 g_free (local_path);
1714 if (normalized_path != NULL)
1716 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1718 AnjutaDocmanPage *page;
1719 page = (AnjutaDocmanPage *) node->data;
1721 if (page && page->widget && IANJUTA_IS_DOCUMENT (page->widget))
1723 IAnjutaDocument *doc;
1724 gchar *te_uri;
1726 doc = IANJUTA_DOCUMENT (page->widget);
1727 te_uri = ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
1728 if (te_uri)
1730 gchar *te_path;
1732 te_path = gnome_vfs_get_local_path_from_uri (te_uri);
1733 if (te_path)
1735 /* editor uri is local too */
1736 gchar *normalized_te_path;
1738 normalized_te_path = anjuta_util_get_real_path (te_path);
1739 g_free (te_path);
1740 if ((normalized_te_path != NULL) &&
1741 strcmp (normalized_te_path, normalized_path) == 0)
1743 g_free (normalized_path);
1744 g_free (te_uri);
1745 g_free (normalized_te_path);
1746 return doc;
1748 g_free (normalized_te_path);
1750 g_free (te_uri);
1754 g_free (normalized_path);
1756 else
1758 /* not a local uri, too bad about any links etc */
1759 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1761 AnjutaDocmanPage *page;
1762 page = (AnjutaDocmanPage *) node->data;
1764 if (page && page->widget && IANJUTA_IS_DOCUMENT (page->widget))
1766 IAnjutaDocument *doc;
1767 gchar *te_uri;
1769 doc = IANJUTA_DOCUMENT (page->widget);
1770 te_uri = ianjuta_file_get_uri (IANJUTA_FILE (doc), NULL);
1771 if (te_uri)
1773 if (strcmp (te_uri, file_uri) == 0)
1775 g_free (te_uri);
1776 return doc;
1778 g_free (te_uri);
1783 return NULL;
1786 GList*
1787 anjuta_docman_get_all_doc_widgets (AnjutaDocman *docman)
1789 GList *wids;
1790 GList *node;
1792 wids = NULL;
1793 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1795 AnjutaDocmanPage *page;
1796 page = (AnjutaDocmanPage *) node->data;
1797 if (page && page->widget)
1798 wids = g_list_prepend (wids, page->widget);
1800 if (wids)
1801 wids = g_list_reverse (wids);
1802 return wids;
1805 ANJUTA_TYPE_BEGIN(AnjutaDocman, anjuta_docman, GTK_TYPE_NOTEBOOK);
1806 ANJUTA_TYPE_END;