Updated Makefile.am files after make -f git.mk
[anjuta.git] / plugins / document-manager / anjuta-docman.c
blob40dbde2624dad4034bdc5d0799d916347e91afa7
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/anjuta-close-button.h>
26 #include <libanjuta/interfaces/ianjuta-file.h>
27 #include <libanjuta/interfaces/ianjuta-markable.h>
28 #include <libanjuta/interfaces/ianjuta-file-savable.h>
29 #include <libanjuta/interfaces/ianjuta-editor.h>
30 #include <libanjuta/interfaces/ianjuta-editor-factory.h>
31 #include <libanjuta/interfaces/ianjuta-project-manager.h>
33 #include <stdlib.h>
34 #include <gtk/gtk.h>
36 #include "anjuta-docman.h"
37 #include "file_history.h"
38 #include "plugin.h"
39 #include "action-callbacks.h"
40 #include "search-box.h"
42 #define MENU_PLACEHOLDER "/MenuMain/PlaceHolderDocumentsMenus/Documents/PlaceholderDocuments"
44 static gpointer parent_class;
46 enum
48 DOC_ADDED,
49 DOC_CHANGED,
50 DOC_REMOVED,
51 LAST_SIGNAL
54 /* Preference keys */
55 #define EDITOR_TABS_ORDERING "docman-tabs-ordering"
56 #define EDITOR_TABS_RECENT_FIRST "docman-tabs-recent-first"
58 typedef struct _AnjutaDocmanPage AnjutaDocmanPage;
60 struct _AnjutaDocmanPriv {
61 DocmanPlugin *plugin;
62 GSettings* settings;
63 GList *pages; /* list of AnjutaDocmanPage's */
65 GtkWidget *combo_box;
66 GtkComboBox *combo;
67 GtkListStore *combo_model;
69 GtkNotebook *notebook;
70 GtkWidget *fileselection;
72 GtkWidget *popup_menu; /* shared context-menu for main-notebook pages */
73 gboolean tab_pressed; /* flag for deferred notebook page re-arrangement */
74 gboolean shutingdown;
76 GSList* radio_group;
77 GtkActionGroup *documents_action_group;
78 gint documents_merge_id;
81 struct _AnjutaDocmanPage {
82 IAnjutaDocument *doc; /* a IAnjutaDocument */
83 GtkWidget *widget; /* notebook-page widget */
84 GtkWidget *box; /* notebook-tab-label parent widget */
85 GtkWidget *menu_box; /* notebook-tab-menu parent widget */
86 GtkWidget *close_button;
87 GtkWidget *mime_icon;
88 GtkWidget *menu_icon;
89 GtkWidget *label;
90 GtkWidget *menu_label; /* notebook page-switch menu-label */
91 guint doc_widget_key_press_id;
94 static guint docman_signals[LAST_SIGNAL] = { 0 };
96 static void anjuta_docman_order_tabs (AnjutaDocman *docman);
97 static void anjuta_docman_update_page_label (AnjutaDocman *docman,
98 IAnjutaDocument *doc);
99 static void anjuta_docman_grab_text_focus (AnjutaDocman *docman);
100 static void on_notebook_switch_page (GtkNotebook *notebook,
101 GtkWidget *page,
102 gint page_num, AnjutaDocman *docman);
103 static AnjutaDocmanPage *
104 anjuta_docman_get_page_for_document (AnjutaDocman *docman,
105 IAnjutaDocument *doc);
106 static AnjutaDocmanPage *
107 anjuta_docman_get_nth_page (AnjutaDocman *docman, gint page_num);
109 static AnjutaDocmanPage *
110 anjuta_docman_get_current_page (AnjutaDocman *docman);
112 static void
113 on_combo_changed (GtkComboBox *combo, gpointer user_data)
115 AnjutaDocman *docman = user_data;
116 GtkTreeIter iter;
118 if (gtk_combo_box_get_active_iter (combo, &iter))
120 IAnjutaDocument *document;
122 gtk_tree_model_get (GTK_TREE_MODEL (docman->priv->combo_model), &iter, 0, &document, -1);
123 anjuta_docman_set_current_document (docman, document);
124 g_object_unref (document);
128 static gint
129 combo_sort_func (GtkTreeModel *model,
130 GtkTreeIter *a,
131 GtkTreeIter *b,
132 gpointer user_data)
134 gchar *name1, *name2;
135 gint result;
137 gtk_tree_model_get (model, a, 1, &name1, -1);
138 gtk_tree_model_get (model, b, 1, &name2, -1);
139 result = g_strcmp0 (name1, name2);
141 g_free (name1);
142 g_free (name2);
144 return result;
147 static gchar*
148 anjuta_docman_get_combo_filename (AnjutaDocman *docman,
149 IAnjutaDocument *doc,
150 GFile *file)
152 gchar *dirty_char, *read_only, *filename;
154 if (!ianjuta_file_savable_is_dirty(IANJUTA_FILE_SAVABLE (doc), NULL))
156 dirty_char = "";
158 else
160 dirty_char = "*";
162 if (ianjuta_file_savable_is_read_only (IANJUTA_FILE_SAVABLE (doc), NULL))
164 read_only = _(" [read-only]");
166 else
168 read_only = "";
171 if (file)
173 gchar *path = g_file_get_path (file);
175 if (path && docman->priv->plugin->project_path &&
176 g_str_has_prefix (path, docman->priv->plugin->project_path))
178 gchar *name = path + strlen (docman->priv->plugin->project_path);
179 if (*name == G_DIR_SEPARATOR)
180 name++;
182 filename = g_strconcat (name, dirty_char, read_only, NULL);
184 else
186 gchar *parsename = g_file_get_parse_name (file);
187 filename = g_strconcat (parsename, dirty_char, read_only, NULL);
188 g_free (parsename);
191 g_free (path);
193 else
194 filename = g_strconcat (ianjuta_document_get_filename (doc, NULL),
195 dirty_char, read_only, NULL);
197 return filename;
200 static void
201 anjuta_docman_update_combo_filenames (AnjutaDocman *docman)
203 gboolean valid;
204 GtkTreeIter iter;
206 for (valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (docman->priv->combo_model), &iter);
207 valid;
208 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (docman->priv->combo_model), &iter))
210 IAnjutaDocument *doc;
211 GFile *file;
212 gchar *filename;
214 gtk_tree_model_get (GTK_TREE_MODEL (docman->priv->combo_model), &iter, 0, &doc, -1);
215 if (IANJUTA_IS_FILE (doc))
216 file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
218 filename = anjuta_docman_get_combo_filename (docman, doc, file);
219 gtk_list_store_set (docman->priv->combo_model, &iter, 1, filename, -1);
221 g_object_unref (doc);
222 if (file)
223 g_object_unref (file);
224 g_free (filename);
228 static void
229 anjuta_docman_add_document_to_combo (AnjutaDocman *docman,
230 IAnjutaDocument *doc,
231 GFile *file)
233 GtkTreeIter iter;
234 gchar *filename;
236 filename = anjuta_docman_get_combo_filename (docman, doc, file);
238 gtk_list_store_append (docman->priv->combo_model, &iter);
239 gtk_list_store_set (docman->priv->combo_model, &iter, 0, doc,
240 1, filename, -1);
242 g_free (filename);
245 static gboolean
246 anjuta_docman_get_iter_for_document (AnjutaDocman *docman,
247 IAnjutaDocument *doc,
248 GtkTreeIter *iter)
250 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (docman->priv->combo_model), iter))
254 IAnjutaDocument *document;
255 gboolean equal;
257 gtk_tree_model_get (GTK_TREE_MODEL (docman->priv->combo_model), iter, 0, &document, -1);
258 equal = (document == doc);
259 g_object_unref (document);
261 if (equal)
262 return TRUE;
264 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (docman->priv->combo_model), iter));
267 return FALSE;
270 static void
271 anjuta_docman_update_combo_label (AnjutaDocman *docman,
272 IAnjutaDocument *doc)
274 GtkTreeIter iter;
275 GFile *file = NULL;
276 gchar *filename;
278 if (!anjuta_docman_get_iter_for_document (docman, doc, &iter))
279 return;
281 if (IANJUTA_IS_FILE (doc))
282 file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
284 filename = anjuta_docman_get_combo_filename (docman, doc, file);
285 gtk_list_store_set (docman->priv->combo_model, &iter, 1, filename, -1);
286 g_free (filename);
289 static void
290 on_document_toggled (GtkAction* action,
291 AnjutaDocman* docman)
293 gint n;
295 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) == FALSE)
296 return;
298 n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
299 gtk_notebook_set_current_page (docman->priv->notebook, n);
302 static void
303 anjuta_docman_update_documents_menu_status (AnjutaDocman* docman)
305 AnjutaDocmanPriv *priv = docman->priv;
306 GtkUIManager* ui = GTK_UI_MANAGER (anjuta_shell_get_ui (ANJUTA_PLUGIN (priv->plugin)->shell,
307 NULL));
308 GtkAction* action;
309 gint n_pages = gtk_notebook_get_n_pages (docman->priv->notebook);
310 gint current_page = gtk_notebook_get_current_page (docman->priv->notebook);
311 gchar *action_name;
313 action = gtk_ui_manager_get_action (ui,
314 "/MenuMain/PlaceHolderDocumentsMenus/Documents/PreviousDocument");
315 g_object_set (action, "sensitive", current_page > 0, NULL);
316 action = gtk_ui_manager_get_action (ui,
317 "/MenuMain/PlaceHolderDocumentsMenus/Documents/NextDocument");
318 g_object_set (action, "sensitive", (current_page + 1) < n_pages, NULL);
319 action_name = g_strdup_printf ("Tab_%d", current_page);
320 action = gtk_action_group_get_action (docman->priv->documents_action_group, action_name);
321 g_free (action_name);
322 if (action)
323 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
326 static void
327 anjuta_docman_update_documents_menu (AnjutaDocman* docman)
329 AnjutaDocmanPriv *priv = docman->priv;
330 GtkUIManager* ui = GTK_UI_MANAGER (anjuta_shell_get_ui (ANJUTA_PLUGIN (priv->plugin)->shell,
331 NULL));
332 GList *actions, *l;
333 gint n, i;
334 guint id;
335 GSList *group = NULL;
337 g_return_if_fail (priv->documents_action_group != NULL);
339 if (priv->documents_merge_id != 0)
340 gtk_ui_manager_remove_ui (ui,
341 priv->documents_merge_id);
343 actions = gtk_action_group_list_actions (priv->documents_action_group);
344 for (l = actions; l != NULL; l = l->next)
346 g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),
347 G_CALLBACK (on_document_toggled),
348 docman);
349 gtk_action_group_remove_action (priv->documents_action_group,
350 GTK_ACTION (l->data));
352 g_list_free (actions);
354 n = gtk_notebook_get_n_pages (docman->priv->notebook);
356 id = (n > 0) ? gtk_ui_manager_new_merge_id (ui) : 0;
358 for (i = 0; i < n; i++)
360 AnjutaDocmanPage* page;
361 GtkRadioAction *action;
362 gchar *action_name;
363 const gchar *tab_name;
364 gchar *accel;
366 page = anjuta_docman_get_nth_page (docman, i);
368 /* NOTE: the action is associated to the position of the tab in
369 * the notebook not to the tab itself! This is needed to work
370 * around the gtk+ bug #170727: gtk leaves around the accels
371 * of the action. Since the accel depends on the tab position
372 * the problem is worked around, action with the same name always
373 * get the same accel.
375 action_name = g_strdup_printf ("Tab_%d", i);
376 tab_name = gtk_label_get_label (GTK_LABEL (page->label));
378 /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
379 accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
381 action = gtk_radio_action_new (action_name,
382 tab_name,
383 NULL,
384 NULL,
387 if (group != NULL)
388 gtk_radio_action_set_group (action, group);
390 /* note that group changes each time we add an action, so it must be updated */
391 group = gtk_radio_action_get_group (action);
393 gtk_action_group_add_action_with_accel (priv->documents_action_group,
394 GTK_ACTION (action),
395 accel);
397 g_signal_connect (action,
398 "toggled",
399 G_CALLBACK (on_document_toggled),
400 docman);
402 gtk_ui_manager_add_ui (ui,
404 MENU_PLACEHOLDER,
405 action_name, action_name,
406 GTK_UI_MANAGER_MENUITEM,
407 FALSE);
409 if (i == gtk_notebook_get_current_page (docman->priv->notebook))
410 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
412 g_object_unref (action);
414 g_free (action_name);
415 g_free (accel);
417 anjuta_docman_update_documents_menu_status (docman);
418 priv->documents_merge_id = id;
421 static gboolean
422 on_doc_widget_key_press_event (GtkWidget *widget,
423 GdkEventKey *event,
424 AnjutaDocman *docman)
426 AnjutaDocmanPage *page;
428 page = anjuta_docman_get_current_page (docman);
429 if (widget == page->widget && event->keyval == GDK_KEY_Escape)
431 search_box_hide (SEARCH_BOX (docman->priv->plugin->search_box));
432 return TRUE;
435 return FALSE;
438 static void
439 on_notebook_page_close_button_click (GtkButton* button,
440 AnjutaDocman* docman)
442 AnjutaDocmanPage *page;
444 page = anjuta_docman_get_current_page (docman);
445 if (page == NULL || page->close_button != GTK_WIDGET (button))
447 /* the close function works only on the current document */
448 GList* node;
449 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
451 page = (AnjutaDocmanPage *) node->data;
452 if (page->close_button == GTK_WIDGET (button))
454 anjuta_docman_set_current_document (docman, page->doc);
455 break;
458 if (node == NULL)
459 return;
462 if (page != NULL)
463 on_close_file_activate (NULL, docman->priv->plugin);
466 static void
467 on_close_other_file_activate_from_popup (GtkWidget* widget, IAnjutaDocument *doc)
469 GtkWidget *parent;
470 AnjutaDocman *docman;
472 parent = gtk_widget_get_parent (widget);
473 docman = ANJUTA_DOCMAN (gtk_menu_get_attach_widget (GTK_MENU (parent)));
475 anjuta_docman_set_current_document (docman, doc);
476 on_close_other_file_activate (NULL, docman->priv->plugin);
479 static void
480 on_tab_popup_clicked (GtkWidget* widget, IAnjutaDocument *doc)
482 GtkWidget *parent;
483 AnjutaDocman *docman;
485 parent = gtk_widget_get_parent (widget);
486 docman = ANJUTA_DOCMAN (gtk_menu_get_attach_widget (GTK_MENU (parent)));
488 anjuta_docman_set_current_document (docman, doc);
491 static gboolean
492 on_idle_gtk_widget_destroy (gpointer user_data)
494 gtk_widget_destroy (GTK_WIDGET (user_data));
495 return FALSE;
498 static void
499 on_menu_deactivate (GtkMenuShell *menushell,
500 gpointer user_data)
502 g_idle_add (on_idle_gtk_widget_destroy, menushell);
505 static GtkMenu*
506 anjuta_docman_create_tab_popup (GtkWidget *wid, AnjutaDocman *docman)
508 IAnjutaDocument *doc = NULL;
509 GtkWidget *menu, *menuitem;
510 gint n, i;
511 GList *node;
513 /* generate a menu that contains all the open tabs and a 'Close Others' option '*/
515 menu = gtk_menu_new ();
516 g_signal_connect (menu, "deactivate", G_CALLBACK (on_menu_deactivate),
517 NULL);
518 gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (docman), NULL);
520 /* figure out which tab was clicked, pass it to on_close_other_file_activate_from_popup */
521 for (n = 0, node = docman->priv->pages; node != NULL; node = g_list_next (node), n++)
523 AnjutaDocmanPage *page;
524 page = (AnjutaDocmanPage *) node->data;
526 if (page->box == wid)
528 doc = page->doc;
529 break;
533 menuitem = gtk_menu_item_new_with_label (_("Close Others"));
534 g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK
535 (on_close_other_file_activate_from_popup), doc);
536 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
537 gtk_widget_show (menuitem);
539 menuitem = gtk_separator_menu_item_new();
540 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
541 gtk_widget_show (menuitem);
543 n = gtk_notebook_get_n_pages (docman->priv->notebook);
545 for(i = 0; i < n; i++)
547 AnjutaDocmanPage *page;
548 const gchar *tab_name;
550 page = anjuta_docman_get_nth_page (docman, i);
551 tab_name = gtk_label_get_label (GTK_LABEL (page->label));
553 menuitem = gtk_menu_item_new_with_label(tab_name);
554 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(on_tab_popup_clicked), page->doc);
555 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
556 gtk_widget_show (menuitem);
559 return GTK_MENU (menu);
562 /* for managing deferred tab re-arrangement */
564 static gboolean
565 on_notebook_tab_btnpress (GtkWidget *wid, GdkEventButton *event, AnjutaDocman* docman)
567 if (event->type == GDK_BUTTON_PRESS && event->button != 3) /* right-click is for menu */
568 docman->priv->tab_pressed = TRUE;
570 if (event->type == GDK_BUTTON_PRESS && event->button == 3)
572 GtkMenu *popup_menu;
574 popup_menu = anjuta_docman_create_tab_popup (wid, docman);
575 if(popup_menu)
576 gtk_menu_popup (popup_menu, NULL, NULL, NULL, NULL, event->button, event->time);
579 return FALSE;
582 static gboolean
583 on_notebook_tab_btnrelease (GtkWidget *widget, GdkEventButton *event, AnjutaDocman* docman)
585 AnjutaDocmanPage *page;
586 AnjutaDocmanPage *curr_page = NULL;
588 docman->priv->tab_pressed = FALSE;
590 /* close on middle click */
591 if (event->button == 2)
593 /* the close function works only on the current document */
594 GList* node;
595 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
597 page = (AnjutaDocmanPage *) node->data;
598 if (page->box == widget)
600 /* we've found the page that user wants to close. Save the current
601 * page for a later setup
603 curr_page = anjuta_docman_get_current_page (docman);
604 anjuta_docman_set_current_document (docman, page->doc);
605 break;
608 if (node == NULL)
609 return FALSE;
611 if (page != NULL)
613 on_close_file_activate (NULL, docman->priv->plugin);
615 if (curr_page != NULL)
617 /* set the old current page */
618 anjuta_docman_set_current_document (docman, curr_page->doc);
622 return FALSE;
625 /* normal button click close */
626 if (g_settings_get_boolean (docman->priv->settings, EDITOR_TABS_RECENT_FIRST))
628 GList *node;
630 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
632 AnjutaDocmanPage *page;
634 page = (AnjutaDocmanPage *)node->data;
635 if (page->box == widget)
637 gtk_notebook_reorder_child (docman->priv->notebook, page->widget, 0);
638 break;
643 return FALSE;
646 static gboolean
647 on_notebook_tab_double_click(GtkWidget *widget, GdkEventButton *event,
648 AnjutaDocman* docman)
650 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
652 if(!docman->maximized)
653 anjuta_shell_maximize_widget(docman->shell, "AnjutaDocumentManager", NULL);
654 else
655 anjuta_shell_unmaximize(docman->shell, NULL);
656 docman->maximized = docman->maximized ? FALSE:TRUE;
659 return FALSE;
662 static void
663 on_notebook_page_reordered (GtkNotebook *notebook, GtkWidget *child,
664 guint page_num, AnjutaDocman *docman)
666 anjuta_docman_update_documents_menu(docman);
669 static void
670 on_close_button_clicked (GtkButton *close_button, gpointer user_data)
672 AnjutaDocman *docman = user_data;
674 on_close_file_activate (NULL, docman->priv->plugin);
677 static GdkPixbuf*
678 anjuta_docman_get_pixbuf_for_file (GFile* file)
680 /* add a nice mime-type icon if we can */
681 GdkPixbuf* pixbuf = NULL;
682 GFileInfo* file_info;
683 GError* err = NULL;
685 g_return_val_if_fail (file != NULL, NULL);
687 file_info = g_file_query_info (file,
688 "standard::*",
689 G_FILE_QUERY_INFO_NONE,
690 NULL,
691 &err);
692 if (err)
693 DEBUG_PRINT ("GFile-Error %s", err->message);
695 if (file_info != NULL)
697 GIcon* icon;
698 const gchar** icon_names;
699 gint width, height;
700 gint size = 0;
701 GtkIconInfo* icon_info;
703 icon = g_file_info_get_icon (file_info);
704 g_object_get (icon, "names", &icon_names, NULL);
705 if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height)) size = MIN(width, height);
706 icon_info = gtk_icon_theme_choose_icon (gtk_icon_theme_get_default(),
707 icon_names,
708 size,
710 if (icon_info != NULL)
712 pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
713 gtk_icon_info_free(icon_info);
715 g_object_unref (file_info);
718 return pixbuf;
721 static void
722 anjuta_docman_page_init (AnjutaDocman *docman, IAnjutaDocument *doc,
723 GFile* file, AnjutaDocmanPage *page)
725 GtkWidget *close_button;
726 GtkWidget *label, *menu_label;
727 GtkWidget *box, *menu_box;
728 GtkWidget *event_hbox;
729 GtkWidget *event_box;
730 const gchar *filename;
731 gchar *ruri;
733 g_return_if_fail (IANJUTA_IS_DOCUMENT (doc));
735 close_button = anjuta_close_button_new ();
736 gtk_widget_set_tooltip_text (close_button, _("Close file"));
738 filename = ianjuta_document_get_filename (doc, NULL);
739 label = gtk_label_new (filename);
740 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
741 gtk_widget_show (label);
743 menu_label = gtk_label_new (filename);
744 gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5);
745 gtk_widget_show (menu_label);
746 menu_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
748 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
749 /* create our layout/event boxes */
750 event_box = gtk_event_box_new();
751 gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
753 event_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
755 page->menu_icon = gtk_image_new();
756 page->mime_icon = gtk_image_new();
757 gtk_box_pack_start (GTK_BOX (event_hbox), page->mime_icon, FALSE, FALSE, 0);
758 gtk_box_pack_start (GTK_BOX (menu_box), page->menu_icon, FALSE, FALSE, 0);
759 if (file != NULL)
761 GdkPixbuf* pixbuf = anjuta_docman_get_pixbuf_for_file (file);
762 if (pixbuf != NULL)
764 gtk_image_set_from_pixbuf (GTK_IMAGE (page->menu_icon), pixbuf);
765 gtk_image_set_from_pixbuf (GTK_IMAGE (page->mime_icon), pixbuf);
766 g_object_unref (pixbuf);
768 ruri = g_file_get_parse_name (file);
769 if (ruri != NULL)
771 /* set the tab-tooltip */
772 gchar *tip;
773 tip = g_markup_printf_escaped ("<b>%s</b> %s", _("Path:"), ruri);
774 gtk_widget_set_tooltip_markup (event_box, tip);
776 g_free (ruri);
777 g_free (tip);
781 gtk_box_pack_start (GTK_BOX (event_hbox), label, TRUE, TRUE, 0);
782 gtk_box_pack_start (GTK_BOX (event_hbox), close_button, FALSE, FALSE, 0);
783 gtk_container_add (GTK_CONTAINER (event_box), event_hbox);
785 /* setup the data hierarchy */
786 g_object_set_data (G_OBJECT (box), "event_box", event_box);
788 /* pack our top-level layout box */
789 gtk_box_pack_start (GTK_BOX (box), event_box, TRUE, TRUE, 0);
791 /* show the widgets of the tab */
792 gtk_widget_show_all(box);
794 /* menu box */
795 gtk_box_pack_start (GTK_BOX (menu_box), menu_label, TRUE, TRUE, 0);
796 gtk_widget_show_all (menu_box);
798 /* main box */
799 g_signal_connect (G_OBJECT (close_button), "clicked",
800 G_CALLBACK (on_notebook_page_close_button_click),
801 docman);
802 g_signal_connect (G_OBJECT (box), "button-press-event",
803 G_CALLBACK (on_notebook_tab_btnpress),
804 docman);
805 g_signal_connect (G_OBJECT (box), "button-release-event",
806 G_CALLBACK (on_notebook_tab_btnrelease),
807 docman);
808 g_signal_connect (G_OBJECT (box), "event",
809 G_CALLBACK (on_notebook_tab_double_click),
810 docman);
812 page->doc_widget_key_press_id =
813 g_signal_connect (G_OBJECT (doc), "key-press-event",
814 G_CALLBACK (on_doc_widget_key_press_event), docman);
816 page->widget = GTK_WIDGET (doc); /* this is the notebook-page child widget */
817 page->doc = doc;
818 page->box = box;
819 page->close_button = close_button;
820 page->label = label;
821 page->menu_box = menu_box;
822 page->menu_label = menu_label;
824 gtk_widget_show_all (page->widget);
827 static AnjutaDocmanPage *
828 anjuta_docman_page_new (void)
830 AnjutaDocmanPage *page;
832 page = g_new0 (AnjutaDocmanPage, 1); /* don't try to survive a memory-crunch */
833 return page;
836 static void
837 anjuta_docman_page_destroy (AnjutaDocmanPage *page)
839 /* Notebook holds a reference on the widget of page and destroys
840 * them properly
842 g_free (page);
845 static void
846 on_open_filesel_response (GtkDialog* dialog, gint id, AnjutaDocman *docman)
848 gchar *uri;
849 // unused gchar *entry_filename = NULL;
850 int i;
851 GSList * list;
852 int elements;
854 if (id != GTK_RESPONSE_ACCEPT)
856 gtk_widget_hide (docman->priv->fileselection);
857 return;
860 list = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog));
861 if (list != NULL)
863 elements = g_slist_length(list);
864 for (i = 0; i < elements; i++)
866 uri = g_slist_nth_data (list, i);
867 if (uri)
869 GFile* file = g_file_new_for_uri (uri);
870 anjuta_docman_goto_file_line (docman, file, -1);
871 g_object_unref (file);
872 g_free (uri);
875 g_slist_free (list);
877 /* if (entry_filename)
879 list = g_slist_remove(list, entry_filename);
880 g_free(entry_filename);
886 static GtkWidget*
887 create_file_open_dialog_gui (GtkWindow* parent, AnjutaDocman* docman)
889 GtkWidget* dialog =
890 gtk_file_chooser_dialog_new (_("Open file"),
891 parent,
892 GTK_FILE_CHOOSER_ACTION_OPEN,
893 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
894 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
895 NULL);
896 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
897 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(dialog), TRUE);
898 g_signal_connect (G_OBJECT (dialog), "response",
899 G_CALLBACK (on_open_filesel_response), docman);
900 g_signal_connect_swapped (G_OBJECT (dialog), "delete-event",
901 G_CALLBACK (gtk_widget_hide), dialog);
902 return dialog;
905 static GtkWidget*
906 create_file_save_dialog_gui (GtkWindow* parent, AnjutaDocman* docman)
908 GtkWidget* dialog =
909 gtk_file_chooser_dialog_new (_("Save file as"),
910 parent,
911 GTK_FILE_CHOOSER_ACTION_SAVE,
912 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
913 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
914 NULL);
915 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
916 return dialog;
919 void
920 anjuta_docman_open_file (AnjutaDocman *docman)
922 if (!docman->priv->fileselection)
924 GtkWidget *parent;
925 parent = gtk_widget_get_toplevel (GTK_WIDGET (docman));
926 docman->priv->fileselection =
927 create_file_open_dialog_gui(GTK_WINDOW (parent), docman);
929 if (gtk_widget_get_visible (docman->priv->fileselection))
930 gtk_window_present (GTK_WINDOW (docman->priv->fileselection));
931 else
932 gtk_widget_show (docman->priv->fileselection);
935 gboolean
936 anjuta_docman_save_document_as (AnjutaDocman *docman, IAnjutaDocument *doc,
937 GtkWidget *parent_window)
939 gchar* uri;
940 GFile* file;
941 const gchar* filename;
942 GtkWidget *parent;
943 GtkWidget *dialog;
944 gint response;
945 gboolean file_saved = TRUE;
947 g_return_val_if_fail (ANJUTA_IS_DOCMAN (docman), FALSE);
948 g_return_val_if_fail (IANJUTA_IS_DOCUMENT (doc), FALSE);
950 if (parent_window)
952 parent = parent_window;
954 else
956 parent = gtk_widget_get_toplevel (GTK_WIDGET (docman));
959 dialog = create_file_save_dialog_gui (GTK_WINDOW (parent), docman);
961 if ((file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL)) != NULL)
963 gchar* file_uri = g_file_get_uri (file);
964 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (dialog), file_uri);
965 g_free (file_uri);
966 g_object_unref (file);
968 else if ((filename = ianjuta_document_get_filename (doc, NULL)) != NULL)
969 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
970 else
971 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "");
973 response = gtk_dialog_run (GTK_DIALOG (dialog));
974 if (response != GTK_RESPONSE_ACCEPT)
976 gtk_widget_destroy (dialog);
977 return FALSE;
980 uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
981 file = g_file_new_for_uri (uri);
982 if (g_file_query_exists (file, NULL))
984 GtkWidget *msg_dialog;
985 gchar* parse_uri = g_file_get_parse_name (file);
986 msg_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
987 GTK_DIALOG_DESTROY_WITH_PARENT,
988 GTK_MESSAGE_QUESTION,
989 GTK_BUTTONS_NONE,
990 _("The file '%s' already exists.\n"
991 "Do you want to replace it with the"
992 " one you are saving?"),
993 parse_uri);
994 g_free (parse_uri);
995 gtk_dialog_add_button (GTK_DIALOG (msg_dialog),
996 GTK_STOCK_CANCEL,
997 GTK_RESPONSE_CANCEL);
998 anjuta_util_dialog_add_button (GTK_DIALOG (msg_dialog),
999 _("_Replace"),
1000 GTK_STOCK_REFRESH,
1001 GTK_RESPONSE_YES);
1002 if (gtk_dialog_run (GTK_DIALOG (msg_dialog)) == GTK_RESPONSE_YES)
1003 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc), file,
1004 NULL);
1005 else
1006 file_saved = FALSE;
1007 gtk_widget_destroy (msg_dialog);
1009 else
1011 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc), file, NULL);
1014 if (g_settings_get_boolean (docman->priv->settings,
1015 EDITOR_TABS_ORDERING))
1016 anjuta_docman_order_tabs (docman);
1018 gtk_widget_destroy (dialog);
1019 g_free (uri);
1021 if (file_saved)
1023 /* Update mime icons */
1024 AnjutaDocmanPage* page = anjuta_docman_get_page_for_document (docman, doc);
1025 GdkPixbuf* pixbuf = anjuta_docman_get_pixbuf_for_file (file);
1026 if (pixbuf)
1028 gtk_image_set_from_pixbuf (GTK_IMAGE(page->menu_icon), pixbuf);
1029 gtk_image_set_from_pixbuf (GTK_IMAGE(page->mime_icon), pixbuf);
1030 g_object_unref (pixbuf);
1033 g_object_unref (file);
1035 return file_saved;
1038 gboolean
1039 anjuta_docman_save_document (AnjutaDocman *docman, IAnjutaDocument *doc,
1040 GtkWidget *parent_window)
1042 GFile* file;
1043 gboolean ret;
1045 file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1047 if (file == NULL)
1049 anjuta_docman_set_current_document (docman, doc);
1050 ret = anjuta_docman_save_document_as (docman, doc, parent_window);
1052 else
1054 /* Error checking must be done by the IAnjutaFile */
1055 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc), NULL);
1056 g_object_unref (file);
1057 ret = TRUE;
1059 return ret;
1062 static void
1063 anjuta_docman_dispose (GObject *obj)
1065 AnjutaDocman *docman;
1066 GList *node;
1068 docman = ANJUTA_DOCMAN (obj);
1069 docman->priv->shutingdown = TRUE;
1071 DEBUG_PRINT ("%s", "Disposing AnjutaDocman object");
1072 if (docman->priv->popup_menu)
1074 gtk_widget_destroy (docman->priv->popup_menu);
1075 docman->priv->popup_menu = NULL;
1077 if (docman->priv->pages)
1079 /* Destroy all page data (more than just the notebook-page-widgets) */
1080 GList *pages;
1082 g_signal_handlers_disconnect_by_func (G_OBJECT (docman->priv->notebook),
1083 (gpointer) on_notebook_switch_page,
1084 (gpointer) docman);
1085 pages = docman->priv->pages; /*work with copy so var can be NULL'ed ASAP*/
1086 docman->priv->pages = NULL;
1087 for (node = pages; node != NULL; node = g_list_next (node))
1089 AnjutaDocmanPage* page = node->data;
1091 g_signal_emit(docman, docman_signals[DOC_REMOVED], 0, page->doc);
1093 /* this also tries to destroy any notebook-page-widgets, in case
1094 they're not gone already. */
1095 anjuta_docman_page_destroy (page);
1097 g_list_free (pages);
1099 G_OBJECT_CLASS (parent_class)->dispose (obj);
1102 static void
1103 anjuta_docman_finalize (GObject *obj)
1105 AnjutaDocman *docman;
1107 DEBUG_PRINT ("%s", "Finalising AnjutaDocman object");
1108 docman = ANJUTA_DOCMAN (obj);
1110 if (docman->priv->fileselection)
1111 gtk_widget_destroy (docman->priv->fileselection);
1113 G_OBJECT_CLASS (parent_class)->finalize (obj);
1116 static void
1117 anjuta_docman_instance_init (AnjutaDocman *docman)
1119 GtkCellRenderer *cell;
1120 GtkWidget *close_image, *close_button;
1122 docman->priv = G_TYPE_INSTANCE_GET_PRIVATE (docman, ANJUTA_TYPE_DOCMAN,
1123 AnjutaDocmanPriv);
1125 docman->priv->combo_model = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING);
1126 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (docman->priv->combo_model), 1,
1127 GTK_SORT_ASCENDING);
1128 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (docman->priv->combo_model), 1,
1129 combo_sort_func, docman, NULL);
1131 docman->priv->combo_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1132 gtk_widget_set_sensitive (GTK_WIDGET (docman->priv->combo_box), FALSE);
1133 gtk_grid_attach (GTK_GRID (docman), GTK_WIDGET (docman->priv->combo_box),
1134 0, 0, 1, 1);
1136 docman->priv->combo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (docman->priv->combo_model)));
1137 gtk_widget_show (GTK_WIDGET (docman->priv->combo));
1139 cell = gtk_cell_renderer_text_new ();
1140 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (docman->priv->combo), cell, TRUE);
1141 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (docman->priv->combo),
1142 cell, "text", 1);
1144 g_signal_connect (G_OBJECT (docman->priv->combo), "changed",
1145 G_CALLBACK (on_combo_changed), docman);
1147 gtk_box_pack_start (GTK_BOX (docman->priv->combo_box), GTK_WIDGET (docman->priv->combo),
1148 TRUE, TRUE, 0);
1150 /* Create close button */
1151 close_image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
1152 gtk_widget_show (close_image);
1154 close_button = gtk_button_new ();
1155 gtk_widget_show (close_button);
1156 gtk_widget_set_tooltip_text (close_button, _("Close file"));
1157 gtk_container_add (GTK_CONTAINER (close_button), close_image);
1158 gtk_widget_set_vexpand (close_button, FALSE);
1159 gtk_box_pack_start (GTK_BOX (docman->priv->combo_box), close_button,
1160 FALSE, FALSE, 0);
1162 g_signal_connect (G_OBJECT (close_button), "clicked",
1163 G_CALLBACK (on_close_button_clicked), docman);
1165 /* Create the notebook */
1166 docman->priv->notebook = GTK_NOTEBOOK (gtk_notebook_new ());
1167 gtk_widget_show (GTK_WIDGET (docman->priv->notebook));
1168 gtk_notebook_set_show_tabs (docman->priv->notebook, FALSE);
1169 g_object_set (docman->priv->notebook, "expand", TRUE, NULL);
1170 gtk_grid_attach (GTK_GRID (docman), GTK_WIDGET (docman->priv->notebook),
1171 0, 1, 1, 1);
1173 gtk_notebook_popup_disable (docman->priv->notebook);
1174 gtk_notebook_set_scrollable (docman->priv->notebook, TRUE);
1175 g_signal_connect (G_OBJECT (docman->priv->notebook), "switch-page",
1176 G_CALLBACK (on_notebook_switch_page), docman);
1177 /* update pages-list after re-ordering (or deleting) */
1178 g_signal_connect (G_OBJECT (docman->priv->notebook), "page-reordered",
1179 G_CALLBACK (on_notebook_page_reordered), docman);
1182 static void
1183 anjuta_docman_class_init (AnjutaDocmanClass *klass)
1185 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1187 parent_class = g_type_class_peek_parent (klass);
1188 object_class->finalize = anjuta_docman_finalize;
1189 object_class->dispose = anjuta_docman_dispose;
1191 g_type_class_add_private (klass, sizeof(AnjutaDocmanPriv));
1193 /* Signals */
1194 docman_signals [DOC_ADDED] =
1195 g_signal_new ("document-added",
1196 ANJUTA_TYPE_DOCMAN,
1197 G_SIGNAL_RUN_LAST,
1198 G_STRUCT_OFFSET (AnjutaDocmanClass, document_added),
1199 NULL, NULL,
1200 g_cclosure_marshal_VOID__OBJECT,
1201 G_TYPE_NONE,
1203 G_TYPE_OBJECT);
1204 docman_signals [DOC_CHANGED] =
1205 g_signal_new ("document-changed",
1206 ANJUTA_TYPE_DOCMAN,
1207 G_SIGNAL_RUN_LAST,
1208 G_STRUCT_OFFSET (AnjutaDocmanClass, document_changed),
1209 NULL, NULL,
1210 g_cclosure_marshal_VOID__OBJECT,
1211 G_TYPE_NONE,
1213 G_TYPE_OBJECT);
1214 docman_signals [DOC_REMOVED] =
1215 g_signal_new ("document-removed",
1216 ANJUTA_TYPE_DOCMAN,
1217 G_SIGNAL_RUN_LAST,
1218 G_STRUCT_OFFSET (AnjutaDocmanClass, document_removed),
1219 NULL, NULL,
1220 g_cclosure_marshal_VOID__OBJECT,
1221 G_TYPE_NONE,
1223 G_TYPE_OBJECT);
1226 GtkWidget*
1227 anjuta_docman_new (DocmanPlugin* plugin)
1230 GtkWidget *docman;
1231 docman = gtk_widget_new (ANJUTA_TYPE_DOCMAN, NULL);
1232 if (docman)
1234 AnjutaUI* ui;
1235 AnjutaDocman* real_docman = ANJUTA_DOCMAN (docman);
1236 real_docman->priv->plugin = plugin;
1237 real_docman->priv->settings = plugin->settings;
1238 real_docman->priv->documents_action_group = gtk_action_group_new ("ActionGroupDocument");
1239 real_docman->maximized = FALSE;
1240 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
1241 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), real_docman->priv->documents_action_group, 0);
1242 g_object_unref (real_docman->priv->documents_action_group);
1245 return docman;
1248 /*! state flag for Ctrl-TAB */
1249 static gboolean g_tabbing = FALSE;
1251 static void
1252 on_notebook_switch_page (GtkNotebook *notebook,
1253 GtkWidget *notebook_page,
1254 gint page_num, AnjutaDocman *docman)
1256 if (!docman->priv->shutingdown)
1258 AnjutaDocmanPage *page;
1260 page = anjuta_docman_get_nth_page (docman, page_num);
1261 g_signal_handlers_block_by_func (G_OBJECT (docman->priv->notebook),
1262 (gpointer) on_notebook_switch_page,
1263 (gpointer) docman);
1264 anjuta_docman_set_current_document (docman, page->doc);
1265 g_signal_handlers_unblock_by_func (G_OBJECT (docman->priv->notebook),
1266 (gpointer) on_notebook_switch_page,
1267 (gpointer) docman);
1268 /* TTimo: reorder so that the most recently used files are
1269 * at the beginning of the tab list
1271 if (!docman->priv->tab_pressed /* after a tab-click, sorting is done upon release */
1272 && !g_tabbing
1273 && !g_settings_get_boolean (docman->priv->settings, EDITOR_TABS_ORDERING)
1274 && g_settings_get_boolean (docman->priv->settings, EDITOR_TABS_RECENT_FIRST))
1276 gtk_notebook_reorder_child (notebook, page->widget, 0);
1278 /* activate the right item in the documents menu */
1279 anjuta_docman_update_documents_menu_status (docman);
1281 g_signal_emit_by_name (G_OBJECT (docman), "document-changed", page->doc);
1285 static void
1286 on_document_update_save_ui (IAnjutaDocument *doc,
1287 AnjutaDocman *docman)
1289 if (!doc)
1290 return;
1292 anjuta_docman_update_page_label (docman, doc);
1293 anjuta_docman_update_combo_label (docman, doc);
1296 static void
1297 on_document_destroy (IAnjutaDocument *doc, AnjutaDocman *docman)
1299 AnjutaDocmanPage *page;
1300 gint page_num;
1302 g_signal_handlers_disconnect_by_func (G_OBJECT (doc),
1303 G_CALLBACK (on_document_update_save_ui),
1304 docman);
1305 g_signal_handlers_disconnect_by_func (G_OBJECT (doc),
1306 G_CALLBACK (on_document_destroy),
1307 docman);
1309 page = anjuta_docman_get_page_for_document (docman, doc);
1310 docman->priv->pages = g_list_remove (docman->priv->pages, page);
1312 if (!docman->priv->shutingdown)
1314 if ((page_num = gtk_notebook_get_current_page (docman->priv->notebook)) == -1)
1315 anjuta_docman_set_current_document (docman, NULL);
1316 else
1318 AnjutaDocmanPage *next_page;
1319 /* set a replacement active document */
1320 next_page = anjuta_docman_get_nth_page (docman, page_num);
1321 anjuta_docman_set_current_document (docman, next_page->doc);
1324 anjuta_docman_page_destroy (page);
1328 * anjuta_docman_add_editor:
1329 * @docman: pointer to docman data struct
1330 * @uri: string with uri of file to edit, may be "" or NULL
1331 * @name: string with name of file to edit, may be absolute path or just a basename or "" or NULL
1333 * Add a new editor, working on specified uri or filename if any
1335 * Return value: the editor
1337 IAnjutaEditor *
1338 anjuta_docman_add_editor (AnjutaDocman *docman, GFile* file,
1339 const gchar *name)
1341 IAnjutaEditor *te;
1342 IAnjutaEditorFactory* factory;
1344 factory = anjuta_shell_get_interface (docman->shell, IAnjutaEditorFactory, NULL);
1346 te = ianjuta_editor_factory_new_editor (factory, file, name, NULL);
1347 /* if file cannot be loaded, text-editor brings up an error dialog ? */
1348 if (te != NULL)
1350 if (IANJUTA_IS_EDITOR (te))
1351 ianjuta_editor_set_popup_menu (te, docman->priv->popup_menu, NULL);
1352 anjuta_docman_add_document (docman, IANJUTA_DOCUMENT (te), file);
1354 return te;
1357 void
1358 anjuta_docman_add_document (AnjutaDocman *docman, IAnjutaDocument *doc,
1359 GFile* file)
1361 AnjutaDocmanPage *page;
1363 page = anjuta_docman_page_new ();
1364 anjuta_docman_page_init (docman, doc, file, page);
1366 /* list order matches pages in book, initially at least */
1367 docman->priv->pages = g_list_prepend (docman->priv->pages, (gpointer)page);
1369 gtk_notebook_prepend_page_menu (docman->priv->notebook, page->widget,
1370 page->box, page->menu_box);
1371 gtk_notebook_set_tab_reorderable (docman->priv->notebook, page->widget,
1372 TRUE);
1374 g_signal_connect (G_OBJECT (doc), "update-save-ui",
1375 G_CALLBACK (on_document_update_save_ui), docman);
1376 g_signal_connect (G_OBJECT (doc), "destroy",
1377 G_CALLBACK (on_document_destroy), docman);
1379 g_object_ref (doc);
1381 /* Add document to combo */
1382 anjuta_docman_add_document_to_combo (docman, doc, file);
1384 anjuta_docman_set_current_document (docman, doc);
1385 anjuta_shell_present_widget (docman->shell, GTK_WIDGET (docman->priv->plugin->vbox), NULL);
1386 anjuta_docman_update_documents_menu (docman);
1388 gtk_widget_set_sensitive (GTK_WIDGET (docman->priv->combo_box), TRUE);
1390 g_signal_emit_by_name (docman, "document-added", doc);
1393 void
1394 anjuta_docman_remove_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1396 AnjutaDocmanPage *page;
1397 GtkTreeIter iter;
1399 if (!doc)
1400 doc = anjuta_docman_get_current_document (docman);
1402 if (!doc)
1403 return;
1405 page = anjuta_docman_get_page_for_document (docman, doc);
1406 if (page)
1408 docman->priv->pages = g_list_remove (docman->priv->pages, (gpointer)page);
1409 if (!g_list_length (docman->priv->pages))
1411 /* No documents => set the box containing combo and close button to insensitive */
1412 gtk_widget_set_sensitive (GTK_WIDGET (docman->priv->combo_box), FALSE);
1414 g_signal_emit (G_OBJECT (docman), docman_signals[DOC_CHANGED], 0, NULL);
1417 g_signal_handler_disconnect (doc, page->doc_widget_key_press_id);
1419 g_free (page);
1422 /* Emit document-removed */
1423 g_signal_emit(docman, docman_signals[DOC_REMOVED], 0, doc);
1426 gtk_widget_destroy(GTK_WIDGET(doc));
1427 anjuta_docman_update_documents_menu(docman);
1429 /* Remove document from combo model */
1430 if (anjuta_docman_get_iter_for_document (docman, doc, &iter))
1431 gtk_list_store_remove (docman->priv->combo_model, &iter);
1434 void
1435 anjuta_docman_set_popup_menu (AnjutaDocman *docman, GtkWidget *menu)
1437 if (menu)
1438 g_object_ref (G_OBJECT (menu));
1439 if (docman->priv->popup_menu)
1440 gtk_widget_destroy (docman->priv->popup_menu);
1441 docman->priv->popup_menu = menu;
1445 GtkWidget *
1446 anjuta_docman_get_current_focus_widget (AnjutaDocman *docman)
1448 GtkWidget *widget;
1449 widget = gtk_widget_get_toplevel (GTK_WIDGET (docman));
1450 if (gtk_widget_is_toplevel (widget) &&
1451 gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
1453 return gtk_window_get_focus (GTK_WINDOW (widget));
1455 return NULL;
1458 GtkWidget *
1459 anjuta_docman_get_current_popup (AnjutaDocman *docman)
1461 return docman->priv->popup_menu;
1464 static AnjutaDocmanPage *
1465 anjuta_docman_get_page_for_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1467 GList *node;
1468 node = docman->priv->pages;
1469 while (node)
1471 AnjutaDocmanPage *page;
1473 page = node->data;
1474 g_assert (page);
1475 if (page->doc == doc)
1476 return page;
1477 node = g_list_next (node);
1479 return NULL;
1482 static AnjutaDocmanPage *
1483 anjuta_docman_get_nth_page (AnjutaDocman *docman, gint page_num)
1485 GtkWidget *widget;
1486 GList *node;
1488 widget = gtk_notebook_get_nth_page (docman->priv->notebook, page_num);
1489 node = docman->priv->pages;
1490 while (node)
1492 AnjutaDocmanPage *page;
1494 page = node->data;
1495 g_assert (page);
1496 if (page->widget == widget)
1497 return page;
1498 node = g_list_next (node);
1501 return NULL;
1504 static AnjutaDocmanPage*
1505 anjuta_docman_get_current_page (AnjutaDocman* docman)
1507 AnjutaDocmanPage* page = anjuta_docman_get_nth_page (docman,
1508 gtk_notebook_get_current_page(docman->priv->notebook));
1509 return page;
1512 IAnjutaDocument *
1513 anjuta_docman_get_current_document (AnjutaDocman *docman)
1515 AnjutaDocmanPage* page = anjuta_docman_get_current_page (docman);
1516 if (page)
1517 return page->doc;
1518 else
1519 return NULL;
1522 void
1523 anjuta_docman_set_current_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1525 AnjutaDocmanPage *page;
1527 if (doc != NULL)
1529 page = anjuta_docman_get_page_for_document (docman, doc);
1530 /* proceed only if page data has been added before */
1531 if (page)
1533 gint page_num;
1534 GtkTreeIter iter;
1536 page_num = gtk_notebook_page_num (docman->priv->notebook,
1537 page->widget);
1538 gtk_notebook_set_current_page (docman->priv->notebook, page_num);
1540 if (g_settings_get_boolean (docman->priv->settings,
1541 EDITOR_TABS_ORDERING))
1542 anjuta_docman_order_tabs (docman);
1544 anjuta_docman_grab_text_focus (docman);
1546 /* set active document in combo box */
1547 if (anjuta_docman_get_iter_for_document(docman, page->doc, &iter))
1548 gtk_combo_box_set_active_iter (docman->priv->combo, &iter);
1553 IAnjutaEditor *
1554 anjuta_docman_goto_file_line (AnjutaDocman *docman, GFile* file, gint lineno)
1556 return anjuta_docman_goto_file_line_mark (docman, file, lineno, FALSE);
1559 IAnjutaEditor *
1560 anjuta_docman_goto_file_line_mark (AnjutaDocman *docman, GFile* file,
1561 gint line, gboolean mark)
1563 IAnjutaDocument *doc;
1564 IAnjutaEditor *te;
1565 AnjutaDocmanPage *page;
1567 g_return_val_if_fail (file != NULL, NULL);
1569 if (!g_file_query_exists (file, NULL))
1571 return NULL;
1574 /* Save current uri and line in document history list */
1575 page = anjuta_docman_get_current_page (docman);
1576 if (page && page->doc && IANJUTA_IS_FILE (page->doc))
1578 GFile* file = ianjuta_file_get_file (IANJUTA_FILE (page->doc), NULL);
1580 if (file)
1582 gint line = 0;
1584 if (IANJUTA_IS_EDITOR (page->doc))
1586 line = ianjuta_editor_get_lineno (IANJUTA_EDITOR (page->doc), NULL);
1589 an_file_history_push (file, line);
1593 /* if possible, use a document that's already open */
1594 doc = anjuta_docman_get_document_for_file (docman, file);
1595 if (doc == NULL)
1597 te = anjuta_docman_add_editor (docman, file, NULL);
1598 doc = IANJUTA_DOCUMENT (te);
1600 else if (IANJUTA_IS_EDITOR (doc))
1602 te = IANJUTA_EDITOR (doc);
1604 else
1606 doc = NULL;
1607 te = NULL;
1610 if (te != NULL)
1612 if (line >= 0)
1614 ianjuta_editor_goto_line (te, line, NULL);
1615 if (mark && IANJUTA_IS_MARKABLE (doc))
1617 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (doc),
1618 IANJUTA_MARKABLE_LINEMARKER,
1619 NULL);
1620 ianjuta_markable_mark (IANJUTA_MARKABLE (doc), line,
1621 IANJUTA_MARKABLE_LINEMARKER, NULL, NULL);
1625 if (doc != NULL)
1627 anjuta_docman_present_notebook_page (docman, doc);
1628 anjuta_docman_grab_text_focus (docman);
1631 return te;
1634 GFile*
1635 anjuta_docman_get_file (AnjutaDocman *docman, const gchar *fn)
1637 IAnjutaDocument *doc;
1638 GList *node;
1639 gchar *real_path;
1640 gchar *fname;
1642 g_return_val_if_fail (fn, NULL);
1644 /* If it is full and absolute path, there is no need to
1645 go further, even if the file is not found*/
1646 if (g_path_is_absolute(fn))
1648 return g_file_new_for_path (fn);
1651 /* First, check if we can get the file straightaway */
1652 real_path = anjuta_util_get_real_path (fn);
1653 if (g_file_test (real_path, G_FILE_TEST_IS_REGULAR))
1655 return g_file_new_for_path (real_path);
1657 g_free(real_path);
1659 /* Get the name part of the file */
1660 fname = g_path_get_basename (fn);
1662 /* Next, check if the current text editor buffer matches this name */
1663 if (NULL != (doc = anjuta_docman_get_current_document (docman)))
1665 if (strcmp(ianjuta_document_get_filename(doc, NULL), fname) == 0)
1667 g_free (fname);
1668 return ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1671 /* Next, see if the name matches any of the opened files */
1672 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1674 AnjutaDocmanPage *page;
1676 page = (AnjutaDocmanPage *) node->data;
1677 if (strcmp (fname, ianjuta_document_get_filename (page->doc, NULL)) == 0)
1679 g_free (fname);
1680 return ianjuta_file_get_file (IANJUTA_FILE (page->doc), NULL);
1683 g_free (fname);
1684 return NULL;
1687 void
1688 anjuta_docman_present_notebook_page (AnjutaDocman *docman, IAnjutaDocument *doc)
1690 GList *node;
1692 if (!doc)
1693 return;
1695 node = docman->priv->pages;
1697 while (node)
1699 AnjutaDocmanPage* page;
1700 page = (AnjutaDocmanPage *)node->data;
1701 if (page && page->doc == doc)
1703 gint curindx;
1704 curindx = gtk_notebook_page_num (docman->priv->notebook, page->widget);
1705 if (curindx != -1)
1707 if (curindx != gtk_notebook_get_current_page (docman->priv->notebook))
1708 gtk_notebook_set_current_page (docman->priv->notebook, curindx);
1709 /* Make sure current page is visible */
1710 anjuta_docman_grab_text_focus (docman);
1712 break;
1714 node = g_list_next (node);
1718 static void
1719 anjuta_docman_update_page_label (AnjutaDocman *docman, IAnjutaDocument *doc)
1721 AnjutaDocmanPage *page;
1722 gchar *basename;
1723 GFile* file;
1724 const gchar* doc_filename;
1725 gchar* dirty_char;
1726 gchar* read_only;
1727 gchar* label;
1729 page = anjuta_docman_get_page_for_document (docman, doc);
1730 if (!page || page->label == NULL || page->menu_label == NULL)
1731 return;
1733 if (!ianjuta_file_savable_is_dirty(IANJUTA_FILE_SAVABLE (doc), NULL))
1735 dirty_char = "";
1737 else
1739 dirty_char = "*";
1741 if (ianjuta_file_savable_is_read_only (IANJUTA_FILE_SAVABLE (doc), NULL))
1743 read_only = _("[read-only]");
1745 else
1747 read_only = "";
1750 file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1751 if (file)
1753 basename = g_file_get_basename (file);
1754 label = g_strconcat(dirty_char, basename, read_only, NULL);
1755 gtk_label_set_text (GTK_LABEL (page->label), label);
1756 gtk_label_set_text (GTK_LABEL (page->menu_label), label);
1757 g_free (label);
1758 g_free (basename);
1760 if (ianjuta_file_savable_is_conflict (IANJUTA_FILE_SAVABLE (doc), NULL))
1762 gtk_image_set_from_stock (GTK_IMAGE (page->menu_icon), GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
1763 gtk_image_set_from_stock (GTK_IMAGE (page->mime_icon), GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
1765 else
1767 GdkPixbuf* pixbuf = anjuta_docman_get_pixbuf_for_file (file);
1769 if (pixbuf)
1771 gtk_image_set_from_pixbuf (GTK_IMAGE(page->menu_icon), pixbuf);
1772 gtk_image_set_from_pixbuf (GTK_IMAGE(page->mime_icon), pixbuf);
1773 g_object_unref (pixbuf);
1776 g_object_unref (file);
1778 else if ((doc_filename = ianjuta_document_get_filename (doc, NULL)) != NULL)
1780 label = g_strconcat (dirty_char, doc_filename, read_only, NULL);
1781 gtk_label_set_text (GTK_LABEL (page->label), label);
1782 gtk_label_set_text (GTK_LABEL (page->menu_label), label);
1783 g_free (label);
1787 static void
1788 anjuta_docman_grab_text_focus (AnjutaDocman *docman)
1790 anjuta_shell_present_widget (docman->shell,
1791 GTK_WIDGET (docman->priv->plugin->vbox), NULL);
1793 ianjuta_document_grab_focus (anjuta_docman_get_current_document(docman),
1794 NULL);
1797 void
1798 anjuta_docman_delete_all_markers (AnjutaDocman *docman, gint marker)
1800 GList *node;
1802 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1804 AnjutaDocmanPage *page;
1806 page = (AnjutaDocmanPage *) node->data;
1807 if (IANJUTA_IS_EDITOR (page->doc))
1809 IAnjutaEditor* te;
1811 te = IANJUTA_EDITOR (page->doc);
1812 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (te), marker, NULL);
1817 void
1818 anjuta_docman_delete_all_indicators (AnjutaDocman *docman)
1820 GList *node;
1822 for (node = docman->priv->pages; node; node = g_list_next (node))
1824 AnjutaDocmanPage *page;
1826 page = (AnjutaDocmanPage *) node->data;
1827 if (IANJUTA_IS_EDITOR (page->doc))
1829 ianjuta_markable_unmark (IANJUTA_MARKABLE (page->doc), -1, -1, NULL);
1834 /* Saves a file to keep it synchronized with external programs */
1835 /* CHECKME unused */
1836 void
1837 anjuta_docman_save_file_if_modified (AnjutaDocman *docman, GFile* file)
1839 IAnjutaDocument *doc;
1841 g_return_if_fail (file != NULL);
1843 doc = anjuta_docman_get_document_for_file (docman, file);
1844 if (doc)
1846 if(ianjuta_file_savable_is_dirty (IANJUTA_FILE_SAVABLE (doc), NULL))
1848 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc), NULL);
1853 /* If an external program changed the file, we must reload it */
1854 /* CHECKME unused */
1855 void
1856 anjuta_docman_reload_file (AnjutaDocman *docman, GFile* file)
1858 IAnjutaDocument *doc;
1860 g_return_if_fail (file != NULL);
1862 doc = anjuta_docman_get_document_for_file (docman, file);
1863 if (doc && IANJUTA_IS_EDITOR (doc))
1865 IAnjutaEditor *te;
1866 te = IANJUTA_EDITOR (doc);
1867 glong nNowPos = ianjuta_editor_get_lineno (te, NULL);
1868 ianjuta_file_open (IANJUTA_FILE (doc), file, NULL);
1869 ianjuta_editor_goto_line (te, nNowPos, NULL);
1873 typedef struct _order_struct order_struct;
1874 struct _order_struct
1876 const gchar *m_label;
1877 GtkWidget *m_widget;
1880 static int
1881 do_ordertab1 (const void *a, const void *b)
1883 order_struct aos,bos;
1884 aos = *(order_struct*)a;
1885 bos = *(order_struct*)b;
1886 return (g_ascii_strcasecmp (aos.m_label, bos.m_label)); /* need g_utf8_collate() ? */
1889 static void
1890 anjuta_docman_order_tabs (AnjutaDocman *docman)
1892 gint i, num_pages;
1893 GList *node;
1894 AnjutaDocmanPage *page;
1895 order_struct *tab_labels;
1896 GtkNotebook *notebook;
1898 notebook = docman->priv->notebook;
1900 num_pages = gtk_notebook_get_n_pages (notebook);
1901 if (num_pages < 2)
1902 return;
1903 tab_labels = g_new0 (order_struct, num_pages);
1904 node = docman->priv->pages;
1905 for (i = 0; i < num_pages; i++)
1907 if (node != NULL && node->data != NULL)
1909 page = node->data;
1910 tab_labels[i].m_widget = page->widget; /* CHECKME needed ? */
1911 tab_labels[i].m_label = ianjuta_document_get_filename (page->doc, NULL);
1912 node = g_list_next (node);
1915 qsort (tab_labels, num_pages, sizeof(order_struct), do_ordertab1);
1916 g_signal_handlers_block_by_func (G_OBJECT (notebook),
1917 (gpointer) on_notebook_page_reordered,
1918 (gpointer) docman);
1919 for (i = 0; i < num_pages; i++)
1920 gtk_notebook_reorder_child (notebook, tab_labels[i].m_widget, i);
1921 g_signal_handlers_unblock_by_func (G_OBJECT (notebook),
1922 (gpointer) on_notebook_page_reordered,
1923 (gpointer) docman);
1924 g_free (tab_labels);
1925 anjuta_docman_update_documents_menu(docman);
1928 IAnjutaDocument *
1929 anjuta_docman_get_document_for_file (AnjutaDocman *docman, GFile* file)
1931 IAnjutaDocument *file_doc = NULL;
1932 GList *node;
1934 g_return_val_if_fail (file != NULL, NULL);
1936 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1938 AnjutaDocmanPage *page;
1939 GFile* doc_file;
1941 page = (AnjutaDocmanPage *) node->data;
1943 if (page && page->widget && IANJUTA_IS_DOCUMENT (page->doc))
1945 IAnjutaDocument *doc;
1947 doc = page->doc;
1948 doc_file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1949 if (doc_file)
1951 gchar *path;
1952 gchar *local_real_path = NULL;
1954 /* Try exact match first */
1955 if (g_file_equal (file, doc_file))
1957 g_object_unref (doc_file);
1958 file_doc = doc;
1959 break;
1962 /* Try a local file alias */
1963 path = g_file_get_path (file);
1964 if (path)
1966 local_real_path = anjuta_util_get_real_path (path);
1967 if (local_real_path)
1969 g_free (path);
1971 else
1973 local_real_path = path;
1976 else
1978 continue;
1981 if ((file_doc == NULL) && (local_real_path))
1983 gchar *doc_path = g_file_get_path (doc_file);
1984 if (doc_path)
1986 gchar *doc_real_path = anjuta_util_get_real_path (doc_path);
1987 if (doc_real_path)
1989 g_free (doc_path);
1991 else
1993 doc_real_path = doc_path;
1995 if ((strcmp (doc_real_path, local_real_path) == 0))
1997 file_doc = doc;
1999 g_free (doc_real_path);
2002 g_free (local_real_path);
2003 g_object_unref (doc_file);
2008 return file_doc;
2011 GList*
2012 anjuta_docman_get_all_doc_widgets (AnjutaDocman *docman)
2014 GList *wids;
2015 GList *node;
2017 wids = NULL;
2018 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
2020 AnjutaDocmanPage *page;
2021 page = (AnjutaDocmanPage *) node->data;
2022 if (page && page->doc)
2023 wids = g_list_prepend (wids, page->doc);
2025 if (wids)
2026 wids = g_list_reverse (wids);
2027 return wids;
2030 static gboolean
2031 next_page (AnjutaDocman *docman, gboolean forward)
2033 gint pages_nb, cur_page, next_page;
2035 if ((cur_page = gtk_notebook_get_current_page (docman->priv->notebook)) == -1)
2036 return FALSE;
2038 pages_nb = gtk_notebook_get_n_pages (docman->priv->notebook);
2040 if (forward)
2041 next_page = (cur_page < pages_nb - 1) ? cur_page + 1 : 0;
2042 else
2043 next_page = cur_page ? cur_page - 1 : pages_nb -1;
2045 gtk_notebook_set_current_page (docman->priv->notebook, next_page);
2046 return TRUE;
2049 gboolean
2050 anjuta_docman_next_page (AnjutaDocman *docman)
2052 return next_page (docman, TRUE);
2055 gboolean
2056 anjuta_docman_previous_page (AnjutaDocman *docman)
2058 return next_page (docman, FALSE);
2061 gboolean
2062 anjuta_docman_set_page (AnjutaDocman *docman, gint page)
2064 if (gtk_notebook_get_n_pages (docman->priv->notebook) < (page - 1))
2065 return FALSE;
2067 gtk_notebook_set_current_page (docman->priv->notebook, page);
2068 return TRUE;
2071 void
2072 anjuta_docman_set_open_documents_mode (AnjutaDocman *docman,
2073 AnjutaDocmanOpenDocumentsMode mode)
2075 switch (mode)
2077 case ANJUTA_DOCMAN_OPEN_DOCUMENTS_MODE_TABS:
2078 gtk_notebook_set_show_tabs (docman->priv->notebook, TRUE);
2079 gtk_widget_hide (GTK_WIDGET (docman->priv->combo_box));
2080 break;
2082 case ANJUTA_DOCMAN_OPEN_DOCUMENTS_MODE_COMBO:
2083 gtk_notebook_set_show_tabs (docman->priv->notebook, FALSE);
2084 gtk_widget_show (GTK_WIDGET (docman->priv->combo_box));
2085 break;
2087 case ANJUTA_DOCMAN_OPEN_DOCUMENTS_MODE_NONE:
2088 gtk_notebook_set_show_tabs (docman->priv->notebook, FALSE);
2089 gtk_widget_hide (GTK_WIDGET (docman->priv->combo_box));
2090 break;
2092 default:
2093 g_assert_not_reached ();
2097 void
2098 anjuta_docman_set_tab_pos (AnjutaDocman *docman, GtkPositionType pos)
2100 gtk_notebook_set_tab_pos (docman->priv->notebook, pos);
2103 void anjuta_docman_project_path_updated (AnjutaDocman *docman)
2105 anjuta_docman_update_combo_filenames (docman);
2108 ANJUTA_TYPE_BEGIN(AnjutaDocman, anjuta_docman, GTK_TYPE_GRID);
2109 ANJUTA_TYPE_END;