1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * anjuta.c Copyright (C) 2003 Naba Kumar <naba@gnome.org>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <gtksourceview/gtksourceview.h>
36 #include <libanjuta/anjuta-shell.h>
37 #include <libanjuta/anjuta-ui.h>
38 #include <libanjuta/anjuta-utils.h>
39 #include <libanjuta/resources.h>
40 #include <libanjuta/anjuta-plugin-manager.h>
41 #include <libanjuta/anjuta-debug.h>
43 #include "anjuta-app.h"
44 #include "anjuta-actions.h"
47 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta.xml"
48 #define GLADE_FILE PACKAGE_DATA_DIR"/glade/preferences.ui"
49 #define ICON_FILE "anjuta-preferences-general-48.png"
51 #define PREF_SCHEMA "org.gnome.anjuta"
52 #define GDL_STYLE "gdl-style"
53 #define TOOLBAR_VISIBLE "toolbar-visible"
54 #define TOOLBAR_STYLE "toolbar-style"
56 static void anjuta_app_layout_load (AnjutaApp
*app
,
57 const gchar
*layout_filename
,
59 static void anjuta_app_layout_save (AnjutaApp
*app
,
60 const gchar
*layout_filename
,
63 static gpointer parent_class
= NULL
;
64 static GtkToolbarStyle style
= -1;
67 menu_item_select_cb (GtkMenuItem
*proxy
,
73 action
= gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy
));
74 g_return_if_fail (action
!= NULL
);
76 g_object_get (G_OBJECT (action
), "tooltip", &message
, NULL
);
79 anjuta_status_push (app
->status
, "%s", message
);
85 menu_item_deselect_cb (GtkMenuItem
*proxy
,
88 anjuta_status_pop (app
->status
);
93 connect_proxy_cb (GtkUIManager
*manager
,
98 if (GTK_IS_MENU_ITEM (proxy
))
100 g_signal_connect (proxy
, "select",
101 G_CALLBACK (menu_item_select_cb
), app
);
102 g_signal_connect (proxy
, "deselect",
103 G_CALLBACK (menu_item_deselect_cb
), app
);
108 disconnect_proxy_cb (GtkUIManager
*manager
,
113 if (GTK_IS_MENU_ITEM (proxy
))
115 g_signal_handlers_disconnect_by_func
116 (proxy
, G_CALLBACK (menu_item_select_cb
), app
);
117 g_signal_handlers_disconnect_by_func
118 (proxy
, G_CALLBACK (menu_item_deselect_cb
), app
);
123 anjuta_app_iconify_dockable_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
126 AnjutaApp
*app
= NULL
;
127 GtkWidget
*dock_item
= NULL
;
129 /* Argumments assertions */
130 g_return_if_fail (ANJUTA_IS_APP (shell
));
131 g_return_if_fail (GTK_IS_WIDGET (widget
));
133 app
= ANJUTA_APP (shell
);
134 g_return_if_fail (app
->widgets
!= NULL
);
136 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
137 g_return_if_fail (dock_item
!= NULL
);
139 /* Iconify the dockable item */
140 gdl_dock_item_iconify_item (GDL_DOCK_ITEM (dock_item
));
144 anjuta_app_hide_dockable_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
147 AnjutaApp
*app
= NULL
;
148 GtkWidget
*dock_item
= NULL
;
150 /* Argumments assertions */
151 g_return_if_fail (ANJUTA_IS_APP (shell
));
152 g_return_if_fail (GTK_IS_WIDGET (widget
));
154 app
= ANJUTA_APP (shell
);
155 g_return_if_fail (app
->widgets
!= NULL
);
157 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
158 g_return_if_fail (dock_item
!= NULL
);
160 /* Hide the dockable item */
161 gdl_dock_item_hide_item (GDL_DOCK_ITEM (dock_item
));
165 anjuta_app_show_dockable_widget (AnjutaShell
*shell
, GtkWidget
* widget
,
168 AnjutaApp
*app
= NULL
;
169 GtkWidget
*dock_item
= NULL
;
171 /* Argumments assertions */
172 g_return_if_fail (ANJUTA_IS_APP (shell
));
173 g_return_if_fail (GTK_IS_WIDGET (widget
));
175 app
= ANJUTA_APP (shell
);
176 g_return_if_fail (app
->widgets
!= NULL
);
178 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
179 g_return_if_fail (dock_item
!= NULL
);
181 /* Show the dockable item */
182 gdl_dock_item_show_item(GDL_DOCK_ITEM (dock_item
));
186 anjuta_app_maximize_widget (AnjutaShell
*shell
,
187 const char *widget_name
,
190 AnjutaApp
*app
= NULL
;
191 GtkWidget
*dock_item
= NULL
;
193 GtkWidget
*widget
= NULL
;
196 /* AnjutaApp assertions */
197 g_return_if_fail (ANJUTA_IS_APP (shell
));
198 app
= ANJUTA_APP (shell
);
200 /* If app->maximized is TRUE then another widget is already maximized.
201 Restoring the UI for a new maximization. */
203 gdl_dock_layout_load_layout (app
->layout_manager
, "back-up");
205 /* Back-up the layout so it can be restored */
206 gdl_dock_layout_save_layout(app
->layout_manager
, "back-up");
208 /* Mark the app as maximized (the other widgets except center are hidden) */
209 app
->maximized
= TRUE
;
211 /* Hide all DockItem's except the ones positioned in the center */
212 g_hash_table_iter_init (&iter
, app
->widgets
);
213 while (g_hash_table_iter_next (&iter
, &key
, &value
))
218 /* If it's the widget requesting maximization then continue */
219 if(!g_strcmp0((gchar
*)key
, widget_name
))
222 /* Widget assertions */
223 widget
= GTK_WIDGET (value
);
224 if(!GTK_IS_WIDGET (widget
))
227 /* DockItem assertions */
228 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
229 if(dock_item
== NULL
|| !GDL_IS_DOCK_ITEM (dock_item
))
233 gdl_dock_item_hide_item (GDL_DOCK_ITEM (dock_item
));
238 anjuta_app_unmaximize (AnjutaShell
*shell
,
241 AnjutaApp
*app
= NULL
;
243 /* AnjutaApp assertions */
244 g_return_if_fail (ANJUTA_IS_APP (shell
));
245 app
= ANJUTA_APP (shell
);
247 /* If not maximized then the operation doesn't make sence. */
248 g_return_if_fail (app
->maximized
);
250 /* Load the backed-up layout */
251 gdl_dock_layout_load_layout (app
->layout_manager
, "back-up");
252 gdl_dock_layout_delete_layout (app
->layout_manager
, "back-up");
254 /* Un-mark maximized */
255 app
->maximized
= FALSE
;
259 on_toolbar_style_changed (GSettings
* settings
,
263 AnjutaApp
* app
= ANJUTA_APP (user_data
);
264 gchar
* tb_style
= g_settings_get_string (settings
, key
);
266 if (strcasecmp (tb_style
, "Default") == 0)
268 else if (strcasecmp (tb_style
, "Both") == 0)
269 style
= GTK_TOOLBAR_BOTH
;
270 else if (strcasecmp (tb_style
, "Horiz") == 0)
271 style
= GTK_TOOLBAR_BOTH_HORIZ
;
272 else if (strcasecmp (tb_style
, "Icons") == 0)
273 style
= GTK_TOOLBAR_ICONS
;
274 else if (strcasecmp (tb_style
, "Text") == 0)
275 style
= GTK_TOOLBAR_TEXT
;
279 gtk_toolbar_set_style (GTK_TOOLBAR (app
->toolbar
), style
);
283 gtk_toolbar_unset_style (GTK_TOOLBAR (app
->toolbar
));
289 on_gdl_style_changed (GSettings
* settings
,
293 AnjutaApp
* app
= ANJUTA_APP (user_data
);
294 GdlSwitcherStyle style
= GDL_SWITCHER_STYLE_BOTH
;
296 gchar
* pr_style
= g_settings_get_string (settings
, key
);
298 if (strcasecmp (pr_style
, "Text") == 0)
299 style
= GDL_SWITCHER_STYLE_TEXT
;
300 else if (strcasecmp (pr_style
, "Icon") == 0)
301 style
= GDL_SWITCHER_STYLE_ICON
;
302 else if (strcasecmp (pr_style
, "Both") == 0)
303 style
= GDL_SWITCHER_STYLE_BOTH
;
304 else if (strcasecmp (pr_style
, "Toolbar") == 0)
305 style
= GDL_SWITCHER_STYLE_TOOLBAR
;
306 else if (strcasecmp (pr_style
, "Tabs") == 0)
307 style
= GDL_SWITCHER_STYLE_TABS
;
309 g_object_set (G_OBJECT(app
->layout_manager
->master
), "switcher-style",
315 on_toggle_widget_view (GtkCheckMenuItem
*menuitem
, GtkWidget
*dockitem
)
318 state
= gtk_check_menu_item_get_active (menuitem
);
320 gdl_dock_item_show_item (GDL_DOCK_ITEM (dockitem
));
322 gdl_dock_item_hide_item (GDL_DOCK_ITEM (dockitem
));
326 on_update_widget_view_menuitem (gpointer key
, gpointer wid
, gpointer data
)
328 GtkCheckMenuItem
*menuitem
;
329 GdlDockItem
*dockitem
;
331 dockitem
= g_object_get_data (G_OBJECT (wid
), "dockitem");
332 menuitem
= g_object_get_data (G_OBJECT (wid
), "menuitem");
334 g_signal_handlers_block_by_func (menuitem
,
335 G_CALLBACK (on_toggle_widget_view
),
338 if (GDL_DOCK_OBJECT_ATTACHED (dockitem
))
339 gtk_check_menu_item_set_active (menuitem
, TRUE
);
341 gtk_check_menu_item_set_active (menuitem
, FALSE
);
343 g_signal_handlers_unblock_by_func (menuitem
,
344 G_CALLBACK (on_toggle_widget_view
),
349 on_layout_dirty_notify (GObject
*object
, GParamSpec
*pspec
, gpointer user_data
)
351 if (!strcmp (pspec
->name
, "dirty")) {
353 g_object_get (object
, "dirty", &dirty
, NULL
);
355 /* Update UI toggle buttons */
356 g_hash_table_foreach (ANJUTA_APP (user_data
)->widgets
,
357 on_update_widget_view_menuitem
,
364 on_layout_locked_notify (GdlDockMaster
*master
, GParamSpec
*pspec
,
372 action
= anjuta_ui_get_action (ui
, "ActionGroupToggleView",
373 "ActionViewLockLayout");
375 g_object_get (master
, "locked", &locked
, NULL
);
376 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
),
381 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
382 AnjutaSession
*session
, AnjutaApp
*app
)
384 gchar
*geometry
, *layout_file
;
385 GdkWindowState state
;
387 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
391 state
= gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (app
)));
392 if (state
& GDK_WINDOW_STATE_MAXIMIZED
) {
393 anjuta_session_set_int (session
, "Anjuta", "Maximized", 1);
395 if (state
& GDK_WINDOW_STATE_FULLSCREEN
) {
396 anjuta_session_set_int (session
, "Anjuta", "Fullscreen", 1);
399 /* Save geometry only if window is not maximized or fullscreened */
400 if (!(state
& GDK_WINDOW_STATE_MAXIMIZED
) ||
401 !(state
& GDK_WINDOW_STATE_FULLSCREEN
))
403 geometry
= anjuta_app_get_geometry (app
);
405 anjuta_session_set_string (session
, "Anjuta", "Geometry",
411 layout_file
= g_build_filename (anjuta_session_get_session_directory (session
),
412 "dock-layout.xml", NULL
);
413 anjuta_app_layout_save (app
, layout_file
, NULL
);
414 g_free (layout_file
);
418 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
419 AnjutaSession
*session
, AnjutaApp
*app
)
421 /* We load layout at last so that all plugins would have loaded by now */
422 if (phase
== ANJUTA_SESSION_PHASE_LAST
)
427 /* Restore geometry */
428 geometry
= anjuta_session_get_string (session
, "Anjuta", "Geometry");
429 anjuta_app_set_geometry (app
, geometry
);
432 /* Restore window state */
433 if (anjuta_session_get_int (session
, "Anjuta", "Fullscreen"))
436 AnjutaUI
* ui
= anjuta_shell_get_ui(shell
, NULL
);
437 GtkAction
* action
= anjuta_ui_get_action (ui
, "ActionGroupToggleView",
438 "ActionViewFullscreen");
439 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
),
442 gtk_window_fullscreen (GTK_WINDOW (shell
));
445 else if (anjuta_session_get_int (session
, "Anjuta", "Maximized"))
447 gtk_window_maximize (GTK_WINDOW (shell
));
451 layout_file
= g_build_filename (anjuta_session_get_session_directory (session
),
452 "dock-layout.xml", NULL
);
453 anjuta_app_layout_load (app
, layout_file
, NULL
);
454 g_free (layout_file
);
459 anjuta_app_dispose (GObject
*widget
)
463 g_return_if_fail (ANJUTA_IS_APP (widget
));
465 app
= ANJUTA_APP (widget
);
469 if (g_hash_table_size (app
->widgets
) > 0)
472 g_warning ("Some widgets are still inside shell (%d widgets), they are:",
473 g_hash_table_size (app->widgets));
474 g_hash_table_foreach (app->widgets, (GHFunc)puts, NULL);
477 g_hash_table_destroy (app
->widgets
);
483 if (g_hash_table_size (app
->values
) > 0)
486 g_warning ("Some Values are still left in shell (%d Values), they are:",
487 g_hash_table_size (app->values));
488 g_hash_table_foreach (app->values, (GHFunc)puts, NULL);
491 g_hash_table_destroy (app
->values
);
495 if (app
->layout_manager
) {
496 g_object_unref (app
->layout_manager
);
497 app
->layout_manager
= NULL
;
499 if (app
->profile_manager
) {
500 g_object_unref (G_OBJECT (app
->profile_manager
));
501 app
->profile_manager
= NULL
;
503 if (app
->plugin_manager
) {
504 g_object_unref (G_OBJECT (app
->plugin_manager
));
505 app
->plugin_manager
= NULL
;
508 g_object_unref (G_OBJECT (app
->status
));
513 g_object_unref (app
->settings
);
514 app
->settings
= NULL
;
517 G_OBJECT_CLASS (parent_class
)->dispose (widget
);
521 anjuta_app_finalize (GObject
*widget
)
525 g_return_if_fail (ANJUTA_IS_APP (widget
));
527 app
= ANJUTA_APP (widget
);
529 gtk_widget_destroy (GTK_WIDGET (app
->ui
));
530 gtk_widget_destroy (GTK_WIDGET (app
->preferences
));
532 G_OBJECT_CLASS (parent_class
)->finalize (widget
);
536 anjuta_app_instance_init (AnjutaApp
*app
)
539 GtkWidget
*menubar
, *about_menu
;
540 GtkWidget
*view_menu
, *hbox
;
544 GList
*plugins_dirs
= NULL
;
545 GdkGeometry size_hints
= {
546 100, 100, 0, 0, 100, 100, 1, 1, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
549 DEBUG_PRINT ("%s", "Initializing Anjuta...");
551 gtk_window_set_geometry_hints (GTK_WINDOW (app
), GTK_WIDGET (app
),
552 &size_hints
, GDK_HINT_RESIZE_INC
);
553 gtk_window_set_resizable (GTK_WINDOW (app
), TRUE
);
558 main_box
= gtk_vbox_new (FALSE
, 0);
559 gtk_container_add (GTK_CONTAINER (app
), main_box
);
560 gtk_widget_show (main_box
);
564 app
->maximized
= FALSE
;
567 app
->settings
= g_settings_new (PREF_SCHEMA
);
570 app
->status
= ANJUTA_STATUS (anjuta_status_new ());
571 anjuta_status_set_title_window (app
->status
, GTK_WIDGET (app
));
572 gtk_widget_show (GTK_WIDGET (app
->status
));
573 gtk_box_pack_end (GTK_BOX (main_box
),
574 GTK_WIDGET (app
->status
), FALSE
, TRUE
, 0);
575 g_object_ref (G_OBJECT (app
->status
));
576 g_object_add_weak_pointer (G_OBJECT (app
->status
), (gpointer
)&app
->status
);
579 hbox
= gtk_hbox_new (FALSE
, 0);
580 gtk_widget_show (hbox
);
581 app
->dock
= gdl_dock_new ();
582 gtk_widget_show (app
->dock
);
583 gtk_box_pack_end(GTK_BOX (hbox
), app
->dock
, TRUE
, TRUE
, 0);
585 dockbar
= gdl_dock_bar_new (GDL_DOCK(app
->dock
));
586 gtk_widget_show (dockbar
);
587 gtk_box_pack_start(GTK_BOX (hbox
), dockbar
, FALSE
, FALSE
, 0);
589 app
->layout_manager
= gdl_dock_layout_new (GDL_DOCK (app
->dock
));
590 g_signal_connect (app
->layout_manager
, "notify::dirty",
591 G_CALLBACK (on_layout_dirty_notify
), app
);
592 g_signal_connect (app
->layout_manager
->master
, "notify::locked",
593 G_CALLBACK (on_layout_locked_notify
), app
);
596 app
->ui
= anjuta_ui_new ();
597 g_object_add_weak_pointer (G_OBJECT (app
->ui
), (gpointer
)&app
->ui
);
598 /* show tooltips in the statusbar */
599 g_signal_connect (app
->ui
,
601 G_CALLBACK (connect_proxy_cb
),
603 g_signal_connect (app
->ui
,
605 G_CALLBACK (disconnect_proxy_cb
),
609 plugins_dirs
= g_list_prepend (plugins_dirs
, PACKAGE_PLUGIN_DIR
);
610 app
->plugin_manager
= anjuta_plugin_manager_new (G_OBJECT (app
),
613 app
->profile_manager
= anjuta_profile_manager_new (app
->plugin_manager
);
614 g_list_free (plugins_dirs
);
617 app
->preferences
= anjuta_preferences_new (app
->plugin_manager
, PREF_SCHEMA
);
618 g_object_add_weak_pointer (G_OBJECT (app
->preferences
),
619 (gpointer
)&app
->preferences
);
621 g_signal_connect (app
->settings
, "changed::" GDL_STYLE
,
622 G_CALLBACK (on_gdl_style_changed
), app
);
623 on_gdl_style_changed (app
->settings
, GDL_STYLE
, app
);
625 /* Register actions */
626 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupFile", _("File"),
628 G_N_ELEMENTS (menu_entries_file
),
629 GETTEXT_PACKAGE
, TRUE
, app
);
630 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupEdit", _("Edit"),
632 G_N_ELEMENTS (menu_entries_edit
),
633 GETTEXT_PACKAGE
, TRUE
, app
);
634 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupView", _("View"),
636 G_N_ELEMENTS (menu_entries_view
),
637 GETTEXT_PACKAGE
, TRUE
, app
);
638 anjuta_ui_add_toggle_action_group_entries (app
->ui
, "ActionGroupToggleView",
640 menu_entries_toggle_view
,
641 G_N_ELEMENTS (menu_entries_toggle_view
),
642 GETTEXT_PACKAGE
, TRUE
, app
);
643 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupHelp", _("Help"),
645 G_N_ELEMENTS (menu_entries_help
),
646 GETTEXT_PACKAGE
, TRUE
, app
);
649 merge_id
= anjuta_ui_merge (app
->ui
, UI_FILE
);
651 /* Adding accels group */
652 gtk_window_add_accel_group (GTK_WINDOW (app
),
653 gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (app
->ui
)));
655 /* create main menu */
656 menubar
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (app
->ui
),
658 gtk_box_pack_start (GTK_BOX (main_box
), menubar
, FALSE
, FALSE
, 0);
659 gtk_widget_show (menubar
);
662 app
->toolbar
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (app
->ui
),
664 if (!g_settings_get_boolean (app
->settings
, TOOLBAR_VISIBLE
))
665 gtk_widget_hide (app
->toolbar
);
666 gtk_style_context_add_class (gtk_widget_get_style_context (app
->toolbar
),
667 GTK_STYLE_CLASS_PRIMARY_TOOLBAR
);
668 gtk_box_pack_start (GTK_BOX (main_box
), app
->toolbar
, FALSE
, FALSE
, 0);
669 action
= gtk_ui_manager_get_action (GTK_UI_MANAGER (app
->ui
),
670 "/MenuMain/MenuView/Toolbar");
671 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action
),
672 g_settings_get_boolean (app
->settings
,
674 g_signal_connect (app
->settings
, "changed::" TOOLBAR_STYLE
,
675 G_CALLBACK (on_toolbar_style_changed
), app
);
676 on_toolbar_style_changed (app
->settings
, TOOLBAR_STYLE
, app
);
678 /* Create widgets menu */
680 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
681 "/MenuMain/MenuView");
682 app
->view_menu
= gtk_menu_item_get_submenu (GTK_MENU_ITEM (view_menu
));
684 /* Create about plugins menu */
686 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
687 "/MenuMain/PlaceHolderHelpMenus/MenuHelp/"
688 "PlaceHolderHelpAbout/AboutPlugins");
689 about_create_plugins_submenu (ANJUTA_SHELL (app
), about_menu
);
692 gtk_box_pack_start (GTK_BOX (main_box
), hbox
, TRUE
, TRUE
, 0);
694 /* Connect to session */
695 g_signal_connect (G_OBJECT (app
), "save_session",
696 G_CALLBACK (on_session_save
), app
);
697 g_signal_connect (G_OBJECT (app
), "load_session",
698 G_CALLBACK (on_session_load
), app
);
701 anjuta_ui_load_accels (NULL
);
707 * GtkWindow catches keybindings for the menu items _before_ passing them to
708 * the focused widget. This is unfortunate and means that pressing ctrl+V
709 * in an entry on a panel ends up pasting text in the TextView.
710 * Here we override GtkWindow's handler to do the same things that it
711 * does, but in the opposite order and then we chain up to the grand
712 * parent handler, skipping gtk_window_key_press_event.
715 anjuta_app_key_press_event (GtkWidget
*widget
,
718 static gpointer grand_parent_class
= NULL
;
719 GtkWindow
*window
= GTK_WINDOW (widget
);
720 GtkWidget
*focus
= gtk_window_get_focus (window
);
721 gboolean handled
= FALSE
;
723 if (grand_parent_class
== NULL
)
724 grand_parent_class
= g_type_class_peek_parent (parent_class
);
726 /* Special case the editor - it catches all shortcuts otherwise */
727 if (GTK_SOURCE_IS_VIEW (focus
))
728 if (gtk_window_activate_key (window
, event
))
730 switch (event
->keyval
)
744 /* handle mnemonics and accelerators */
746 handled
= gtk_window_activate_key (window
, event
);
749 /* handle focus widget key events */
751 handled
= gtk_window_propagate_key_event (window
, event
);
754 /* handle mnemonics and accelerators */
756 handled
= gtk_window_activate_key (window
, event
);
758 /* Chain up, invokes binding set */
760 handled
= GTK_WIDGET_CLASS (grand_parent_class
)->key_press_event (widget
, event
);
766 anjuta_app_class_init (AnjutaAppClass
*class)
768 GObjectClass
*object_class
;
769 GtkWidgetClass
*widget_class
;
771 parent_class
= g_type_class_peek_parent (class);
772 object_class
= (GObjectClass
*) class;
773 widget_class
= (GtkWidgetClass
*) class;
775 object_class
->finalize
= anjuta_app_finalize
;
776 object_class
->dispose
= anjuta_app_dispose
;
778 widget_class
->key_press_event
= anjuta_app_key_press_event
;
782 anjuta_app_new (void)
786 app
= ANJUTA_APP (g_object_new (ANJUTA_TYPE_APP
,
789 return GTK_WIDGET (app
);
793 anjuta_app_get_geometry (AnjutaApp
*app
)
796 gint width
, height
, posx
, posy
;
798 g_return_val_if_fail (ANJUTA_IS_APP (app
), NULL
);
801 width
= height
= posx
= posy
= 0;
802 if (gtk_widget_get_window (GTK_WIDGET (app
)))
804 gtk_window_get_size (GTK_WINDOW (app
), &width
, &height
);
805 gtk_window_get_position (GTK_WINDOW(app
), &posx
, &posy
);
807 geometry
= g_strdup_printf ("%dx%d+%d+%d", width
, height
, posx
, posy
);
813 anjuta_app_set_geometry (AnjutaApp
*app
, const gchar
*geometry
)
815 gint width
, height
, posx
, posy
;
816 gboolean geometry_set
= FALSE
;
818 if (geometry
&& strlen (geometry
) > 0)
820 DEBUG_PRINT ("Setting geometry: %s", geometry
);
822 if (sscanf (geometry
, "%dx%d+%d+%d", &width
, &height
,
825 if (gtk_widget_get_realized (GTK_WIDGET (app
)))
827 gtk_window_resize (GTK_WINDOW (app
), width
, height
);
831 gtk_window_set_default_size (GTK_WINDOW (app
), width
, height
);
832 gtk_window_move (GTK_WINDOW (app
), posx
, posy
);
838 g_warning ("Failed to parse geometry: %s", geometry
);
845 width
= gdk_screen_width () - 10;
846 height
= gdk_screen_height () - 25;
847 width
= (width
< 790)? width
: 790;
848 height
= (height
< 575)? width
: 575;
849 if (gtk_widget_get_realized (GTK_WIDGET (app
)) == FALSE
)
851 gtk_window_set_default_size (GTK_WINDOW (app
), width
, height
);
852 gtk_window_move (GTK_WINDOW (app
), posx
, posy
);
858 anjuta_app_layout_save (AnjutaApp
*app
, const gchar
*filename
,
861 g_return_if_fail (ANJUTA_IS_APP (app
));
862 g_return_if_fail (filename
!= NULL
);
864 /* If maximized, the layout should be loaded from the back-up first */
866 gdl_dock_layout_load_layout (app
->layout_manager
, "back-up");
868 /* Continue with the saving */
869 gdl_dock_layout_save_layout (app
->layout_manager
, name
);
870 if (!gdl_dock_layout_save_to_file (app
->layout_manager
, filename
))
871 g_warning ("Saving dock layout to '%s' failed!", filename
);
873 /* This is a good place to save the accels too */
874 anjuta_ui_save_accels (NULL
);
878 anjuta_app_layout_load (AnjutaApp
*app
, const gchar
*layout_filename
,
881 g_return_if_fail (ANJUTA_IS_APP (app
));
883 if (!layout_filename
||
884 !gdl_dock_layout_load_from_file (app
->layout_manager
, layout_filename
))
886 gchar
*datadir
, *filename
;
887 datadir
= anjuta_res_get_data_dir();
889 filename
= g_build_filename (datadir
, "layout.xml", NULL
);
890 DEBUG_PRINT ("Layout = %s", filename
);
892 if (!gdl_dock_layout_load_from_file (app
->layout_manager
, filename
))
893 g_warning ("Loading layout from '%s' failed!!", filename
);
897 if (!gdl_dock_layout_load_layout (app
->layout_manager
, name
))
898 g_warning ("Loading layout failed!!");
902 anjuta_app_layout_reset (AnjutaApp
*app
)
904 anjuta_app_layout_load (app
, NULL
, NULL
);
908 anjuta_app_install_preferences (AnjutaApp
*app
)
910 GtkBuilder
* builder
= gtk_builder_new ();
911 GError
* error
= NULL
;
912 GtkWidget
*notebook
, *shortcuts
, *plugins
, *remember_plugins
;
914 /* Create preferences page */
915 gtk_builder_add_from_file (builder
, GLADE_FILE
, &error
);
918 g_warning("Could not load general preferences: %s",
920 g_error_free (error
);
923 anjuta_preferences_add_from_builder (app
->preferences
, builder
, app
->settings
,
924 "General", _("General"), ICON_FILE
);
925 notebook
= GTK_WIDGET (gtk_builder_get_object (builder
, "General"));
926 shortcuts
= anjuta_ui_get_accel_editor (ANJUTA_UI (app
->ui
));
927 plugins
= anjuta_plugin_manager_get_plugins_page (app
->plugin_manager
);
928 remember_plugins
= anjuta_plugin_manager_get_remembered_plugins_page (app
->plugin_manager
);
930 gtk_widget_show (shortcuts
);
931 gtk_widget_show (plugins
);
932 gtk_widget_show (remember_plugins
);
934 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), plugins
,
935 gtk_label_new (_("Installed plugins")));
936 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), remember_plugins
,
937 gtk_label_new (_("Preferred plugins")));
938 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), shortcuts
,
939 gtk_label_new (_("Shortcuts")));
941 g_object_unref (builder
);
944 /* AnjutaShell Implementation */
947 on_value_removed_from_hash (gpointer value
)
949 g_value_unset ((GValue
*)value
);
954 anjuta_app_add_value (AnjutaShell
*shell
, const char *name
,
955 const GValue
*value
, GError
**error
)
960 g_return_if_fail (ANJUTA_IS_APP (shell
));
961 g_return_if_fail (name
!= NULL
);
962 g_return_if_fail (G_IS_VALUE(value
));
964 app
= ANJUTA_APP (shell
);
966 if (app
->values
== NULL
)
968 app
->values
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
,
969 on_value_removed_from_hash
);
971 anjuta_shell_remove_value (shell
, name
, error
);
973 copy
= g_new0 (GValue
, 1);
974 g_value_init (copy
, value
->g_type
);
975 g_value_copy (value
, copy
);
977 g_hash_table_insert (app
->values
, g_strdup (name
), copy
);
978 g_signal_emit_by_name (shell
, "value_added", name
, copy
);
982 anjuta_app_get_value (AnjutaShell
*shell
, const char *name
, GValue
*value
,
988 g_return_if_fail (ANJUTA_IS_APP (shell
));
989 g_return_if_fail (name
!= NULL
);
990 /* g_return_if_fail (G_IS_VALUE (value)); */
992 app
= ANJUTA_APP (shell
);
996 val
= g_hash_table_lookup (app
->values
, name
);
1001 g_value_init (value
, val
->g_type
);
1003 g_value_copy (val
, value
);
1009 *error
= g_error_new (ANJUTA_SHELL_ERROR
,
1010 ANJUTA_SHELL_ERROR_DOESNT_EXIST
,
1011 _("Value doesn't exist"));
1017 anjuta_app_remove_value (AnjutaShell
*shell
, const char *name
, GError
**error
)
1023 g_return_if_fail (ANJUTA_IS_APP (shell
));
1024 g_return_if_fail (name
!= NULL
);
1026 app
= ANJUTA_APP (shell
);
1029 g_return_if_fail (app->values != NULL);
1030 if (app->widgets && g_hash_table_lookup_extended (app->widgets, name,
1034 item = g_object_get_data (G_OBJECT (w), "dockitem");
1035 gdl_dock_item_hide_item (GDL_DOCK_ITEM (item));
1036 gdl_dock_object_unbind (GDL_DOCK_OBJECT (item));
1041 if (app
->values
&& g_hash_table_lookup_extended (app
->values
, name
,
1043 (gpointer
)&value
)) {
1044 g_signal_emit_by_name (app
, "value_removed", name
);
1045 g_hash_table_remove (app
->values
, name
);
1050 anjuta_app_saving_push (AnjutaShell
* shell
)
1052 AnjutaApp
* app
= ANJUTA_APP (shell
);
1057 anjuta_app_saving_pop (AnjutaShell
* shell
)
1059 AnjutaApp
* app
= ANJUTA_APP (shell
);
1064 remove_from_widgets_hash (gpointer name
, gpointer hash_widget
, gpointer widget
)
1066 if (hash_widget
== widget
)
1072 on_widget_destroy (GtkWidget
*widget
, AnjutaApp
*app
)
1074 DEBUG_PRINT ("%s", "Widget about to be destroyed");
1075 g_hash_table_foreach_remove (app
->widgets
, remove_from_widgets_hash
,
1080 on_widget_remove (GtkWidget
*container
, GtkWidget
*widget
, AnjutaApp
*app
)
1082 GtkWidget
*dock_item
;
1084 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1087 gchar
* unique_name
= g_object_get_data(G_OBJECT(dock_item
), "unique_name");
1088 g_free(unique_name
);
1089 g_signal_handlers_disconnect_by_func (G_OBJECT (dock_item
),
1090 G_CALLBACK (on_widget_remove
), app
);
1091 gdl_dock_item_unbind (GDL_DOCK_ITEM(dock_item
));
1093 if (g_hash_table_foreach_remove (app
->widgets
,
1094 remove_from_widgets_hash
,
1096 DEBUG_PRINT ("%s", "Widget removed from container");
1101 on_widget_removed_from_hash (gpointer widget
)
1104 GtkWidget
*menuitem
;
1105 GdlDockItem
*dockitem
;
1107 DEBUG_PRINT ("%s", "Removing widget from hash");
1109 app
= g_object_get_data (G_OBJECT (widget
), "app-object");
1110 dockitem
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1111 menuitem
= g_object_get_data (G_OBJECT (widget
), "menuitem");
1113 gtk_widget_destroy (menuitem
);
1115 g_object_set_data (G_OBJECT (widget
), "dockitem", NULL
);
1116 g_object_set_data (G_OBJECT (widget
), "menuitem", NULL
);
1118 g_signal_handlers_disconnect_by_func (G_OBJECT (widget
),
1119 G_CALLBACK (on_widget_destroy
), app
);
1120 g_signal_handlers_disconnect_by_func (G_OBJECT (dockitem
),
1121 G_CALLBACK (on_widget_remove
), app
);
1123 g_object_unref (G_OBJECT (widget
));
1127 anjuta_app_setup_widget (AnjutaApp
* app
,
1134 GtkCheckMenuItem
* menuitem
;
1136 /* Add the widget to hash */
1137 if (app
->widgets
== NULL
)
1139 app
->widgets
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
1141 on_widget_removed_from_hash
);
1143 g_hash_table_insert (app
->widgets
, g_strdup (name
), widget
);
1144 g_object_ref (widget
);
1146 /* Add toggle button for the widget */
1147 menuitem
= GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title
));
1148 gtk_widget_show (GTK_WIDGET (menuitem
));
1149 gtk_check_menu_item_set_active (menuitem
, TRUE
);
1150 gtk_menu_shell_append (GTK_MENU_SHELL (app
->view_menu
), GTK_WIDGET (menuitem
));
1153 g_object_set( G_OBJECT(menuitem
), "visible", FALSE
, NULL
);
1156 g_object_set_data (G_OBJECT (widget
), "app-object", app
);
1157 g_object_set_data (G_OBJECT (widget
), "menuitem", menuitem
);
1158 g_object_set_data (G_OBJECT (widget
), "dockitem", item
);
1160 /* For toggling widget view on/off */
1161 g_signal_connect (G_OBJECT (menuitem
), "toggled",
1162 G_CALLBACK (on_toggle_widget_view
), item
);
1165 Watch for widget removal/destruction so that it could be
1166 removed from widgets hash.
1168 g_signal_connect (G_OBJECT (item
), "remove",
1169 G_CALLBACK (on_widget_remove
), app
);
1170 g_signal_connect_after (G_OBJECT (widget
), "destroy",
1171 G_CALLBACK (on_widget_destroy
), app
);
1173 gtk_widget_show_all (item
);
1178 anjuta_app_add_widget_full (AnjutaShell
*shell
,
1182 const char *stock_id
,
1183 AnjutaShellPlacement placement
,
1190 g_return_if_fail (ANJUTA_IS_APP (shell
));
1191 g_return_if_fail (GTK_IS_WIDGET (widget
));
1192 g_return_if_fail (name
!= NULL
);
1193 g_return_if_fail (title
!= NULL
);
1195 app
= ANJUTA_APP (shell
);
1197 /* Add the widget to dock */
1198 if (stock_id
== NULL
)
1199 item
= gdl_dock_item_new (name
, title
, GDL_DOCK_ITEM_BEH_NORMAL
);
1201 item
= gdl_dock_item_new_with_stock (name
, title
, stock_id
,
1202 GDL_DOCK_ITEM_BEH_NORMAL
);
1206 flags
|= GDL_DOCK_ITEM_BEH_NEVER_FLOATING
;
1207 flags
|= GDL_DOCK_ITEM_BEH_CANT_CLOSE
;
1208 flags
|= GDL_DOCK_ITEM_BEH_CANT_ICONIFY
;
1209 flags
|= GDL_DOCK_ITEM_BEH_NO_GRIP
;
1210 g_object_set(G_OBJECT(item
), "behavior", flags
, NULL
);
1213 gtk_container_add (GTK_CONTAINER (item
), widget
);
1214 gdl_dock_add_item (GDL_DOCK (app
->dock
),
1215 GDL_DOCK_ITEM (item
), placement
);
1218 gdl_dock_item_set_default_position(GDL_DOCK_ITEM(item
), GDL_DOCK_OBJECT(app
->dock
));
1220 anjuta_app_setup_widget (app
, name
, widget
, item
, title
, locked
);
1224 anjuta_app_add_widget_custom (AnjutaShell
*shell
,
1228 const char *stock_id
,
1230 AnjutaShellPlacement placement
,
1237 g_return_if_fail (ANJUTA_IS_APP (shell
));
1238 g_return_if_fail (GTK_IS_WIDGET (widget
));
1239 g_return_if_fail (name
!= NULL
);
1240 g_return_if_fail (title
!= NULL
);
1242 app
= ANJUTA_APP (shell
);
1244 /* Add the widget to dock */
1245 /* Add the widget to dock */
1246 if (stock_id
== NULL
)
1247 item
= gdl_dock_item_new (name
, title
, GDL_DOCK_ITEM_BEH_NORMAL
);
1249 item
= gdl_dock_item_new_with_stock (name
, title
, stock_id
,
1250 GDL_DOCK_ITEM_BEH_NORMAL
);
1252 gtk_container_add (GTK_CONTAINER (item
), widget
);
1253 gdl_dock_add_item (GDL_DOCK (app
->dock
),
1254 GDL_DOCK_ITEM (item
), placement
);
1256 grip
= gdl_dock_item_get_grip (GDL_DOCK_ITEM (item
));
1258 gdl_dock_item_grip_set_label (GDL_DOCK_ITEM_GRIP (grip
), label
);
1260 anjuta_app_setup_widget (app
, name
, widget
, item
, title
, FALSE
);
1264 anjuta_app_remove_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
1268 GtkWidget
*dock_item
;
1270 g_return_if_fail (ANJUTA_IS_APP (shell
));
1271 g_return_if_fail (GTK_IS_WIDGET (widget
));
1273 app
= ANJUTA_APP (shell
);
1275 g_return_if_fail (app
->widgets
!= NULL
);
1277 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1278 g_return_if_fail (dock_item
!= NULL
);
1280 /* Remove the widget from container */
1281 g_object_ref (widget
);
1282 /* It should call on_widget_remove() and clean up should happen */
1283 gtk_container_remove (GTK_CONTAINER (dock_item
), widget
);
1284 g_object_unref (widget
);
1288 anjuta_app_present_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
1292 GdlDockItem
*dock_item
;
1295 g_return_if_fail (ANJUTA_IS_APP (shell
));
1296 g_return_if_fail (GTK_IS_WIDGET (widget
));
1298 app
= ANJUTA_APP (shell
);
1300 g_return_if_fail (app
->widgets
!= NULL
);
1302 dock_item
= g_object_get_data (G_OBJECT(widget
), "dockitem");
1303 g_return_if_fail (dock_item
!= NULL
);
1305 /* Hack to present the dock item if it's in a notebook dock item */
1306 parent
= gtk_widget_get_parent (GTK_WIDGET(dock_item
) );
1307 if (!GDL_DOCK_OBJECT_ATTACHED (dock_item
))
1309 gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item
));
1311 if (GTK_IS_NOTEBOOK (parent
))
1314 pagenum
= gtk_notebook_page_num (GTK_NOTEBOOK (parent
), GTK_WIDGET (dock_item
));
1315 gtk_notebook_set_current_page (GTK_NOTEBOOK (parent
), pagenum
);
1318 /* FIXME: If the item is floating, present the window */
1319 /* FIXME: There is no way to detect if a widget was floating before it was
1320 detached since it no longer has a parent there is no way to access the
1321 floating property of the GdlDock structure.*/
1325 anjuta_app_get_object (AnjutaShell
*shell
, const char *iface_name
,
1328 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1329 g_return_val_if_fail (iface_name
!= NULL
, NULL
);
1330 return anjuta_plugin_manager_get_plugin (ANJUTA_APP (shell
)->plugin_manager
,
1334 static AnjutaStatus
*
1335 anjuta_app_get_status (AnjutaShell
*shell
, GError
**error
)
1337 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1338 return ANJUTA_APP (shell
)->status
;
1342 anjuta_app_get_ui (AnjutaShell
*shell
, GError
**error
)
1344 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1345 return ANJUTA_APP (shell
)->ui
;
1348 static AnjutaPreferences
*
1349 anjuta_app_get_preferences (AnjutaShell
*shell
, GError
**error
)
1351 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1352 return ANJUTA_APP (shell
)->preferences
;
1355 static AnjutaPluginManager
*
1356 anjuta_app_get_plugin_manager (AnjutaShell
*shell
, GError
**error
)
1358 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1359 return ANJUTA_APP (shell
)->plugin_manager
;
1362 static AnjutaProfileManager
*
1363 anjuta_app_get_profile_manager (AnjutaShell
*shell
, GError
**error
)
1365 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1366 return ANJUTA_APP (shell
)->profile_manager
;
1370 anjuta_shell_iface_init (AnjutaShellIface
*iface
)
1372 iface
->add_widget_full
= anjuta_app_add_widget_full
;
1373 iface
->add_widget_custom
= anjuta_app_add_widget_custom
;
1374 iface
->remove_widget
= anjuta_app_remove_widget
;
1375 iface
->present_widget
= anjuta_app_present_widget
;
1376 iface
->iconify_dockable_widget
= anjuta_app_iconify_dockable_widget
;
1377 iface
->hide_dockable_widget
= anjuta_app_hide_dockable_widget
;
1378 iface
->show_dockable_widget
= anjuta_app_show_dockable_widget
;
1379 iface
->maximize_widget
= anjuta_app_maximize_widget
;
1380 iface
->unmaximize
= anjuta_app_unmaximize
;
1381 iface
->add_value
= anjuta_app_add_value
;
1382 iface
->get_value
= anjuta_app_get_value
;
1383 iface
->remove_value
= anjuta_app_remove_value
;
1384 iface
->get_object
= anjuta_app_get_object
;
1385 iface
->get_status
= anjuta_app_get_status
;
1386 iface
->get_ui
= anjuta_app_get_ui
;
1387 iface
->get_preferences
= anjuta_app_get_preferences
;
1388 iface
->get_plugin_manager
= anjuta_app_get_plugin_manager
;
1389 iface
->get_profile_manager
= anjuta_app_get_profile_manager
;
1390 iface
->saving_push
= anjuta_app_saving_push
;
1391 iface
->saving_pop
= anjuta_app_saving_pop
;
1394 ANJUTA_TYPE_BEGIN(AnjutaApp
, anjuta_app
, GTK_TYPE_WINDOW
);
1395 ANJUTA_TYPE_ADD_INTERFACE(anjuta_shell
, ANJUTA_TYPE_SHELL
);