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
30 #include <glade/glade-xml.h>
31 #include <gtk/gtkwidget.h>
32 #include <gtk/gtkwindow.h>
34 #include <gdl/gdl-dock.h>
35 #include <gdl/gdl-dock-bar.h>
36 #include <gdl/gdl-switcher.h>
38 #include <bonobo/bonobo-dock-item.h>
40 #include <libanjuta/anjuta-shell.h>
41 #include <libanjuta/anjuta-utils.h>
42 #include <libanjuta/resources.h>
43 #include <libanjuta/anjuta-plugin-manager.h>
44 #include <libanjuta/anjuta-debug.h>
46 #include "anjuta-app.h"
47 #include "anjuta-actions.h"
50 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta.ui"
51 #define GLADE_FILE PACKAGE_DATA_DIR"/glade/anjuta.glade"
52 #define ICON_FILE "anjuta-preferences-general-48.png"
54 static void anjuta_app_layout_load (AnjutaApp
*app
,
55 const gchar
*layout_filename
,
57 static void anjuta_app_layout_save (AnjutaApp
*app
,
58 const gchar
*layout_filename
,
61 static gpointer parent_class
= NULL
;
62 static GList
* toolbars
= NULL
;
63 static GtkToolbarStyle style
= -1;
66 on_toolbar_style_changed (GConfClient
* client
, guint id
, GConfEntry
* entry
,
69 AnjutaApp
* app
= ANJUTA_APP (user_data
);
70 GList
*node
= toolbars
;
72 char* tb_style
= anjuta_preferences_get (app
->preferences
, "anjuta.toolbar.style");
76 if (strcasecmp (tb_style
, "Default") == 0)
78 else if (strcasecmp (tb_style
, "Both") == 0)
79 style
= GTK_TOOLBAR_BOTH
;
80 else if (strcasecmp (tb_style
, "Horiz") == 0)
81 style
= GTK_TOOLBAR_BOTH_HORIZ
;
82 else if (strcasecmp (tb_style
, "Icons") == 0)
83 style
= GTK_TOOLBAR_ICONS
;
84 else if (strcasecmp (tb_style
, "Text") == 0)
85 style
= GTK_TOOLBAR_TEXT
;
87 DEBUG_PRINT ("Toolbar style: %s", tb_style
);
96 gtk_toolbar_set_style (GTK_TOOLBAR (node
->data
), style
);
104 gtk_toolbar_unset_style (GTK_TOOLBAR (node
->data
));
115 get_accel_file (void)
117 gchar
*anjuta_dir
= NULL
;
118 gchar
*filename
= NULL
;
120 anjuta_dir
= anjuta_util_get_user_config_dir ();
122 if (anjuta_dir
!= NULL
)
123 filename
= g_build_filename (anjuta_dir
, "anjuta-accels", NULL
);
135 filename
= get_accel_file ();
136 if (filename
!= NULL
)
138 gtk_accel_map_load (filename
);
148 filename
= get_accel_file ();
149 if (filename
!= NULL
)
151 gtk_accel_map_save (filename
);
157 on_gdl_style_changed (GConfClient
* client
, guint id
, GConfEntry
* entry
,
160 AnjutaApp
* app
= ANJUTA_APP (user_data
);
161 GdlSwitcherStyle style
= GDL_SWITCHER_STYLE_BOTH
;
163 gchar
* pr_style
= anjuta_preferences_get (app
->preferences
, "anjuta.gdl.style");
167 if (strcasecmp (pr_style
, "Text") == 0)
168 style
= GDL_SWITCHER_STYLE_TEXT
;
169 else if (strcasecmp (pr_style
, "Icon") == 0)
170 style
= GDL_SWITCHER_STYLE_ICON
;
171 else if (strcasecmp (pr_style
, "Both") == 0)
172 style
= GDL_SWITCHER_STYLE_BOTH
;
173 else if (strcasecmp (pr_style
, "Toolbar") == 0)
174 style
= GDL_SWITCHER_STYLE_TOOLBAR
;
175 else if (strcasecmp (pr_style
, "Tabs") == 0)
176 style
= GDL_SWITCHER_STYLE_TABS
;
178 DEBUG_PRINT ("Switcher style: %s", pr_style
);
182 g_object_set (G_OBJECT(app
->layout_manager
->master
), "switcher-style",
187 on_toggle_widget_view (GtkCheckMenuItem
*menuitem
, GtkWidget
*dockitem
)
190 state
= gtk_check_menu_item_get_active (menuitem
);
192 gdl_dock_item_show_item (GDL_DOCK_ITEM (dockitem
));
194 gdl_dock_item_hide_item (GDL_DOCK_ITEM (dockitem
));
198 on_update_widget_view_menuitem (gpointer key
, gpointer wid
, gpointer data
)
200 GtkCheckMenuItem
*menuitem
;
201 GdlDockItem
*dockitem
;
203 dockitem
= g_object_get_data (G_OBJECT (wid
), "dockitem");
204 menuitem
= g_object_get_data (G_OBJECT (wid
), "menuitem");
206 g_signal_handlers_block_by_func (menuitem
,
207 G_CALLBACK (on_toggle_widget_view
),
210 if (GDL_DOCK_OBJECT_ATTACHED (dockitem
))
211 gtk_check_menu_item_set_active (menuitem
, TRUE
);
213 gtk_check_menu_item_set_active (menuitem
, FALSE
);
215 g_signal_handlers_unblock_by_func (menuitem
,
216 G_CALLBACK (on_toggle_widget_view
),
221 on_layout_dirty_notify (GObject
*object
, GParamSpec
*pspec
, gpointer user_data
)
223 if (!strcmp (pspec
->name
, "dirty")) {
225 g_object_get (object
, "dirty", &dirty
, NULL
);
227 /* Update UI toggle buttons */
228 g_hash_table_foreach (ANJUTA_APP (user_data
)->widgets
,
229 on_update_widget_view_menuitem
,
236 on_layout_locked_notify (GdlDockMaster
*master
, GParamSpec
*pspec
,
244 action
= anjuta_ui_get_action (ui
, "ActionGroupToggleView",
245 "ActionViewLockLayout");
247 g_object_get (master
, "locked", &locked
, NULL
);
248 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
),
253 layout_changed (GtkWidget
*w
, AnjutaApp
*app
)
255 BonoboDockLayout
*layout
;
258 g_return_if_fail (ANJUTA_IS_APP (app
));
259 g_return_if_fail (BONOBO_IS_DOCK (w
));
261 layout
= bonobo_dock_get_layout (BONOBO_DOCK (app
->bonobo_dock
));
262 s
= bonobo_dock_layout_create_string (layout
);
263 anjuta_preferences_set (app
->preferences
, "anjuta.bonobo.layout", s
);
264 g_object_unref (G_OBJECT (layout
));
269 anjuta_app_add_dock_item (AnjutaApp
*app
, BonoboDockItem
*item
,
270 BonoboDockPlacement placement
, gint band_num
,
271 gint band_position
, gint offset
)
273 if (app
->bonobo_layout
)
274 bonobo_dock_layout_add_item (app
->bonobo_layout
,
275 BONOBO_DOCK_ITEM (item
),
276 placement
, band_num
, band_position
,
279 bonobo_dock_add_item (BONOBO_DOCK(app
->bonobo_dock
),
280 BONOBO_DOCK_ITEM( item
),
281 placement
, band_num
, band_position
, offset
, FALSE
);
283 g_signal_emit_by_name (app
->bonobo_dock
, "layout_changed", app
);
288 on_toolbar_view_toggled (GtkCheckMenuItem
*menuitem
, GtkWidget
*widget
)
291 GtkWidget
*dock_item
;
298 name
= gtk_widget_get_name (widget
);
299 app
= g_object_get_data (G_OBJECT(widget
), "app");
300 dock_item
= g_object_get_data (G_OBJECT(widget
), "dock_item");
301 band
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget
), "band"));
302 position
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget
), "position"));
303 offset
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget
), "offset"));
306 if (gtk_check_menu_item_get_active (menuitem
))
311 gchar
*unique_name
= g_strdup_printf ("%s-%d", name
, count
);
313 DEBUG_PRINT ("Adding dock item %s band %d, offset %d, position %d",
314 unique_name
, band
, offset
, position
);
316 dock_item
= bonobo_dock_item_new (unique_name
,
317 BONOBO_DOCK_ITEM_BEH_NEVER_VERTICAL
|
318 BONOBO_DOCK_ITEM_BEH_NEVER_FLOATING
);
320 gtk_container_add (GTK_CONTAINER (dock_item
), widget
);
322 /* Widget not yet added to the dock. Add it */
323 anjuta_app_add_dock_item (app
, BONOBO_DOCK_ITEM (dock_item
),
324 BONOBO_DOCK_TOP
, band
, position
, offset
);
326 g_object_set_data_full (G_OBJECT(dock_item
), "unique_name",
327 unique_name
, g_free
);
328 g_object_set_data (G_OBJECT(widget
), "dock_item", dock_item
);
331 gtk_widget_show (dock_item
);
332 gtk_widget_show (GTK_BIN (dock_item
)->child
);
336 gtk_widget_hide (dock_item
);
337 gtk_widget_hide (GTK_BIN (dock_item
)->child
);
342 on_merge_widget_destroy (GtkWidget
*merge_widget
, GtkWidget
*menuitem
)
344 toolbars
= g_list_remove (toolbars
, merge_widget
);
345 DEBUG_PRINT ("Destroying menuitem for toolbar widget");
346 gtk_widget_destroy (menuitem
);
350 on_add_merge_widget (GtkUIManager
*merge
, GtkWidget
*widget
,
351 GtkWidget
*ui_container
)
353 DEBUG_PRINT ("Adding UI item ...");
355 if (GTK_IS_MENU_BAR (widget
))
357 /* We don't need to manage GtkMenuBar widgets */
362 static gint count
= 0;
363 const gchar
*toolbarname
;
368 AnjutaPreferences
*pr
;
373 pr
= ANJUTA_PREFERENCES (ANJUTA_APP(ui_container
)->preferences
);
375 /* Showing the arrows seem to break anything completly! */
376 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (widget
), FALSE
);
378 /* Set the toolbar style */
380 gtk_toolbar_set_style(GTK_TOOLBAR (widget
), style
);
382 gtk_widget_show (widget
);
383 g_object_set_data (G_OBJECT (widget
), "app", ui_container
);
385 /* Load toolbar position */
386 toolbarname
= gtk_widget_get_name (widget
);
387 band_key
= g_strconcat (toolbarname
, ".band", NULL
);
388 position_key
= g_strconcat (toolbarname
, ".position", NULL
);
389 offset_key
= g_strconcat (toolbarname
, ".offset", NULL
);
390 band
= anjuta_preferences_get_int_with_default(pr
, band_key
, -1);
391 position
= anjuta_preferences_get_int_with_default(pr
, position_key
, 0);
392 offset
= anjuta_preferences_get_int_with_default(pr
, offset_key
, 0);
393 /* Without these check you might see odd results */
396 g_object_set_data(G_OBJECT(widget
), "position", GINT_TO_POINTER(position
));
397 g_object_set_data(G_OBJECT(widget
), "offset", GINT_TO_POINTER(offset
));
398 g_object_set_data (G_OBJECT (widget
), "band",
399 GINT_TO_POINTER(band
));
401 g_free(position_key
);
403 DEBUG_PRINT ("Adding toolbar: %s", toolbarname
);
405 if (!ANJUTA_APP (ui_container
)->toolbars_menu
)
407 ANJUTA_APP (ui_container
)->toolbars_menu
= gtk_menu_new ();
408 gtk_widget_show (GTK_WIDGET (ANJUTA_APP (ui_container
)->toolbars_menu
));
411 menuitem
= gtk_check_menu_item_new_with_label (toolbarname
);
412 gtk_menu_append (GTK_MENU (ANJUTA_APP (ui_container
)->toolbars_menu
),
414 gtk_widget_show (GTK_WIDGET (menuitem
));
415 g_signal_connect (G_OBJECT (menuitem
), "toggled",
416 G_CALLBACK (on_toolbar_view_toggled
), widget
);
417 g_object_set_data(G_OBJECT(widget
), "menuitem", menuitem
);
419 /* When the toolbar is destroyed make sure corresponding menuitem is
421 g_signal_connect (widget
, "destroy",
422 G_CALLBACK (on_merge_widget_destroy
),
425 toolbars
= g_list_append(toolbars
, widget
);
427 /* Show/hide toolbar */
428 visible_key
= g_strconcat (toolbarname
, ".visible", NULL
);
429 if (anjuta_preferences_get_int_with_default (pr
, visible_key
,
432 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem
),
435 g_free (visible_key
);
441 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
442 AnjutaSession
*session
, AnjutaApp
*app
)
444 gchar
*geometry
, *layout_file
;
445 GdkWindowState state
;
446 GList
* node
= toolbars
;
449 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
455 GtkWidget
* widget
= node
->data
;
456 GtkWidget
* dock_item
= g_object_get_data (G_OBJECT(widget
), "dock_item");;
457 const gchar
* toolbarname
= gtk_widget_get_name(widget
);
458 AnjutaPreferences
* pr
= ANJUTA_PREFERENCES (app
->preferences
);
463 gchar
* key
= g_strconcat (toolbarname
, ".visible", NULL
);
464 gchar
* band_key
= g_strconcat (toolbarname
, ".band", NULL
);
465 gchar
* position_key
= g_strconcat (toolbarname
, ".position", NULL
);
466 gchar
* offset_key
= g_strconcat (toolbarname
, ".offset", NULL
);
468 /* Save visibility */
469 g_object_get(G_OBJECT(dock_item
), "visible", &visible
, NULL
);
470 anjuta_preferences_set_int(pr
, key
, visible
);
473 /* Save toolbar position */
474 if (app
->bonobo_dock
!= NULL
)
479 BonoboDockPlacement placement
;
480 gchar
* unique_name
= g_object_get_data(G_OBJECT(dock_item
),
483 BonoboDockItem
* item
= bonobo_dock_get_item_by_name(BONOBO_DOCK(app
->bonobo_dock
),
484 unique_name
, &placement
,
485 &band
, &position
, &offset
);
486 g_return_if_fail(item
!= NULL
);
488 anjuta_preferences_set_int(pr
, band_key
, band
);
489 anjuta_preferences_set_int(pr
, position_key
, position
);
490 anjuta_preferences_set_int(pr
, offset_key
, offset
);
494 g_free (position_key
);
497 node
= g_list_next(node
);
501 state
= gdk_window_get_state (GTK_WIDGET (app
)->window
);
502 if (state
& GDK_WINDOW_STATE_MAXIMIZED
) {
503 anjuta_session_set_int (session
, "Anjuta", "Maximized", 1);
505 if (state
& GDK_WINDOW_STATE_FULLSCREEN
) {
506 anjuta_session_set_int (session
, "Anjuta", "Fullscreen", 1);
509 /* Save geometry only if window is not maximized or fullscreened */
510 if (!(state
& GDK_WINDOW_STATE_MAXIMIZED
) ||
511 !(state
& GDK_WINDOW_STATE_FULLSCREEN
))
513 geometry
= anjuta_app_get_geometry (app
);
515 anjuta_session_set_string (session
, "Anjuta", "Geometry",
521 layout_file
= g_build_filename (anjuta_session_get_session_directory (session
),
522 "dock-layout.xml", NULL
);
523 anjuta_app_layout_save (app
, layout_file
, NULL
);
524 g_free (layout_file
);
528 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
529 AnjutaSession
*session
, AnjutaApp
*app
)
531 /* We load layout at last so that all plugins would have loaded by now */
532 if (phase
== ANJUTA_SESSION_PHASE_LAST
)
537 /* Restore geometry */
538 geometry
= anjuta_session_get_string (session
, "Anjuta", "Geometry");
539 anjuta_app_set_geometry (app
, geometry
);
541 /* Restore window state */
542 if (anjuta_session_get_int (session
, "Anjuta", "Fullscreen"))
545 AnjutaUI
* ui
= anjuta_shell_get_ui(shell
, NULL
);
546 GtkAction
* action
= anjuta_ui_get_action (ui
, "ActionGroupToggleView",
547 "ActionViewFullscreen");
548 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
),
551 gtk_window_fullscreen (GTK_WINDOW (shell
));
554 else if (anjuta_session_get_int (session
, "Anjuta", "Maximized"))
556 gtk_window_maximize (GTK_WINDOW (shell
));
560 layout_file
= g_build_filename (anjuta_session_get_session_directory (session
),
561 "dock-layout.xml", NULL
);
562 anjuta_app_layout_load (app
, layout_file
, NULL
);
563 g_free (layout_file
);
568 anjuta_app_dispose (GObject
*widget
)
573 g_return_if_fail (ANJUTA_IS_APP (widget
));
575 app
= ANJUTA_APP (widget
);
579 if (g_hash_table_size (app
->widgets
) > 0)
582 g_warning ("Some widgets are still inside shell (%d widgets), they are:",
583 g_hash_table_size (app->widgets));
584 g_hash_table_foreach (app->widgets, (GHFunc)puts, NULL);
587 g_hash_table_destroy (app
->widgets
);
593 if (g_hash_table_size (app
->values
) > 0)
596 g_warning ("Some Values are still left in shell (%d Values), they are:",
597 g_hash_table_size (app->values));
598 g_hash_table_foreach (app->values, (GHFunc)puts, NULL);
601 g_hash_table_destroy (app
->values
);
605 /* We need to destroy to the toolbars now so that the
606 * on_merge_widget_destroy() does not produce a error trying to destory
607 * already destroyed menuitems which happen when the window is being
610 * Make a tmp list because the handler removes items from 'toolbars' list.
611 * FIXME: Why is 'toolbars' a global static variable?
613 tmp_list
= g_list_copy (toolbars
);
614 g_list_foreach (tmp_list
, (GFunc
)gtk_widget_destroy
, NULL
);
615 g_list_free (tmp_list
);
617 if (app
->layout_manager
) {
618 g_object_unref (app
->layout_manager
);
619 app
->layout_manager
= NULL
;
621 if (app
->profile_manager
) {
622 g_object_unref (G_OBJECT (app
->profile_manager
));
623 app
->profile_manager
= NULL
;
625 if (app
->plugin_manager
) {
626 g_object_unref (G_OBJECT (app
->plugin_manager
));
627 app
->plugin_manager
= NULL
;
630 g_object_unref (G_OBJECT (app
->status
));
634 G_OBJECT_CLASS (parent_class
)->dispose (widget
);
638 anjuta_app_finalize (GObject
*widget
)
642 g_return_if_fail (ANJUTA_IS_APP (widget
));
644 app
= ANJUTA_APP (widget
);
646 gtk_widget_destroy (GTK_WIDGET (app
->ui
));
647 gtk_widget_destroy (GTK_WIDGET (app
->preferences
));
649 G_OBJECT_CLASS (parent_class
)->finalize (widget
);
653 anjuta_app_instance_init (AnjutaApp
*app
)
656 GtkWidget
*menubar
, *toolbar_menu
, *about_menu
;
657 GtkWidget
*view_menu
, *hbox
;
661 GList
*plugins_dirs
= NULL
;
662 gchar
*bonobo_string
= NULL
;
663 GdkGeometry size_hints
= {
664 100, 100, 0, 0, 100, 100, 1, 1, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
667 DEBUG_PRINT ("Initializing Anjuta...");
669 gtk_window_set_geometry_hints (GTK_WINDOW (app
), GTK_WIDGET (app
),
670 &size_hints
, GDK_HINT_RESIZE_INC
);
671 gtk_window_set_resizable (GTK_WINDOW (app
), TRUE
);
676 main_box
= gtk_vbox_new (FALSE
, 0);
677 gtk_container_add (GTK_CONTAINER (app
), main_box
);
678 gtk_widget_show (main_box
);
680 app
->layout_manager
= NULL
;
686 app
->status
= ANJUTA_STATUS (anjuta_status_new ());
687 anjuta_status_set_title_window (app
->status
, GTK_WIDGET (app
));
688 gtk_widget_show (GTK_WIDGET (app
->status
));
689 gtk_box_pack_end (GTK_BOX (main_box
),
690 GTK_WIDGET (app
->status
), FALSE
, TRUE
, 0);
691 g_object_ref (G_OBJECT (app
->status
));
692 g_object_add_weak_pointer (G_OBJECT (app
->status
), (gpointer
)&app
->status
);
695 hbox
= gtk_hbox_new (FALSE
, 0);
696 gtk_widget_show (hbox
);
697 app
->dock
= gdl_dock_new ();
698 gtk_widget_show (app
->dock
);
699 gtk_box_pack_end(GTK_BOX (hbox
), app
->dock
, TRUE
, TRUE
, 0);
701 dockbar
= gdl_dock_bar_new (GDL_DOCK(app
->dock
));
702 gtk_widget_show (dockbar
);
703 gtk_box_pack_start(GTK_BOX (hbox
), dockbar
, FALSE
, FALSE
, 0);
704 gtk_box_pack_end (GTK_BOX (main_box
), hbox
, TRUE
, TRUE
, 0);
706 app
->layout_manager
= gdl_dock_layout_new (GDL_DOCK (app
->dock
));
707 g_signal_connect (app
->layout_manager
, "notify::dirty",
708 G_CALLBACK (on_layout_dirty_notify
), app
);
709 g_signal_connect (app
->layout_manager
->master
, "notify::locked",
710 G_CALLBACK (on_layout_locked_notify
), app
);
713 app
->ui
= anjuta_ui_new ();
715 g_signal_connect (G_OBJECT (app
->ui
),
716 "add_widget", G_CALLBACK (on_add_merge_widget
),
718 g_object_add_weak_pointer (G_OBJECT (app
->ui
), (gpointer
)&app
->ui
);
721 plugins_dirs
= g_list_prepend (plugins_dirs
, PACKAGE_PLUGIN_DIR
);
722 app
->plugin_manager
= anjuta_plugin_manager_new (G_OBJECT (app
),
725 app
->profile_manager
= anjuta_profile_manager_new (app
->plugin_manager
);
726 g_list_free (plugins_dirs
);
729 app
->preferences
= anjuta_preferences_new (app
->plugin_manager
);
730 g_object_add_weak_pointer (G_OBJECT (app
->preferences
),
731 (gpointer
)&app
->preferences
);
733 anjuta_preferences_notify_add (app
->preferences
, "anjuta.gdl.style",
734 on_gdl_style_changed
, app
, NULL
);
736 on_gdl_style_changed (NULL
, 0, NULL
, app
);
738 anjuta_preferences_notify_add (app
->preferences
, "anjuta.toolbar.style",
739 on_toolbar_style_changed
, app
, NULL
);
741 on_toolbar_style_changed (NULL
, 0, NULL
, app
);
743 /* Register actions */
744 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupFile", _("File"),
746 G_N_ELEMENTS (menu_entries_file
),
747 GETTEXT_PACKAGE
, TRUE
, app
);
748 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupEdit", _("Edit"),
750 G_N_ELEMENTS (menu_entries_edit
),
751 GETTEXT_PACKAGE
, TRUE
, app
);
752 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupView", _("View"),
754 G_N_ELEMENTS (menu_entries_view
),
755 GETTEXT_PACKAGE
, TRUE
, app
);
756 anjuta_ui_add_toggle_action_group_entries (app
->ui
, "ActionGroupToggleView",
758 menu_entries_toggle_view
,
759 G_N_ELEMENTS (menu_entries_toggle_view
),
760 GETTEXT_PACKAGE
, TRUE
, app
);
761 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupHelp", _("Help"),
763 G_N_ELEMENTS (menu_entries_help
),
764 GETTEXT_PACKAGE
, TRUE
, app
);
767 app
->bonobo_dock
= bonobo_dock_new ();
768 gtk_widget_show (app
->bonobo_dock
);
770 g_signal_connect (app
->bonobo_dock
, "layout_changed",
771 G_CALLBACK (layout_changed
), app
);
773 app
->bonobo_layout
= bonobo_dock_layout_new ();
775 bonobo_string
= anjuta_preferences_get (app
->preferences
, "anjuta.bonobo.layout");
778 bonobo_dock_layout_parse_string (app
->bonobo_layout
, bonobo_string
);
779 g_free (bonobo_string
);
782 bonobo_dock_add_from_layout (BONOBO_DOCK (app
->bonobo_dock
),
785 g_object_unref (app
->bonobo_layout
);
786 app
->bonobo_layout
= NULL
;
789 merge_id
= anjuta_ui_merge (app
->ui
, UI_FILE
);
791 /* Adding accels group */
792 gtk_window_add_accel_group (GTK_WINDOW (app
),
793 gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (app
->ui
)));
795 /* create main menu */
796 menubar
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (app
->ui
),
798 gtk_box_pack_start (GTK_BOX (main_box
), menubar
, FALSE
, FALSE
, 0);
799 gtk_widget_show (menubar
);
802 * We have to add the dock after merging the ui
804 gtk_box_pack_start (GTK_BOX (main_box
), app
->bonobo_dock
,
807 /* create toolbar menus */
809 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
810 "/MenuMain/MenuView/Toolbars");
812 gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolbar_menu
),
815 g_warning ("Cannot retrive main menu widget");
817 /* Create widgets menu */
819 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
820 "/MenuMain/MenuView");
821 app
->view_menu
= gtk_menu_item_get_submenu (GTK_MENU_ITEM (view_menu
));
823 /* Disable unavailible tutorials */
824 action
= anjuta_ui_get_action(app
->ui
, "ActionGroupHelp", "ActionHelpTutorial");
825 g_object_set(G_OBJECT(action
), "visible", FALSE
, NULL
);
826 action
= anjuta_ui_get_action(app
->ui
, "ActionGroupHelp", "ActionHelpAdvancedTutorial");
827 g_object_set(G_OBJECT(action
), "visible", FALSE
, NULL
);
829 /* Create about plugins menu */
831 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
832 "/MenuMain/PlaceHolderHelpMenus/MenuHelp/"
833 "PlaceHolderHelpAbout/AboutPlugins");
834 about_create_plugins_submenu (ANJUTA_SHELL (app
), about_menu
);
836 /* Connect to session */
837 g_signal_connect (G_OBJECT (app
), "save_session",
838 G_CALLBACK (on_session_save
), app
);
839 g_signal_connect (G_OBJECT (app
), "load_session",
840 G_CALLBACK (on_session_load
), app
);
847 anjuta_app_class_init (AnjutaAppClass
*class)
849 GObjectClass
*object_class
;
850 GtkWidgetClass
*widget_class
;
852 parent_class
= g_type_class_peek_parent (class);
853 object_class
= (GObjectClass
*) class;
854 widget_class
= (GtkWidgetClass
*) class;
855 object_class
->finalize
= anjuta_app_finalize
;
856 object_class
->dispose
= anjuta_app_dispose
;
860 anjuta_app_new (void)
864 app
= ANJUTA_APP (g_object_new (ANJUTA_TYPE_APP
,
867 return GTK_WIDGET (app
);
871 anjuta_app_get_geometry (AnjutaApp
*app
)
874 gint width
, height
, posx
, posy
;
876 g_return_val_if_fail (ANJUTA_IS_APP (app
), NULL
);
879 width
= height
= posx
= posy
= 0;
880 if (GTK_WIDGET(app
)->window
)
882 gtk_window_get_size (GTK_WINDOW (app
), &width
, &height
);
883 gtk_window_get_position (GTK_WINDOW(app
), &posx
, &posy
);
885 geometry
= g_strdup_printf ("%dx%d+%d+%d", width
, height
, posx
, posy
);
891 anjuta_app_set_geometry (AnjutaApp
*app
, const gchar
*geometry
)
893 gint width
, height
, posx
, posy
;
894 gboolean geometry_set
= FALSE
;
896 if (geometry
&& strlen (geometry
) > 0)
898 DEBUG_PRINT ("Setting geometry: %s", geometry
);
900 if (sscanf (geometry
, "%dx%d+%d+%d", &width
, &height
,
903 if (GTK_WIDGET_REALIZED (app
))
905 gtk_window_resize (GTK_WINDOW (app
), width
, height
);
909 gtk_window_set_default_size (GTK_WINDOW (app
), width
, height
);
910 gtk_window_move (GTK_WINDOW (app
), posx
, posy
);
916 g_warning ("Failed to parse geometry: %s", geometry
);
923 width
= gdk_screen_width () - 10;
924 height
= gdk_screen_height () - 25;
925 width
= (width
< 790)? width
: 790;
926 height
= (height
< 575)? width
: 575;
927 if (GTK_WIDGET_REALIZED (app
) == FALSE
)
929 gtk_window_set_default_size (GTK_WINDOW (app
), width
, height
);
930 gtk_window_move (GTK_WINDOW (app
), posx
, posy
);
936 anjuta_app_layout_save (AnjutaApp
*app
, const gchar
*filename
,
939 g_return_if_fail (ANJUTA_IS_APP (app
));
940 g_return_if_fail (filename
!= NULL
);
942 gdl_dock_layout_save_layout (app
->layout_manager
, name
);
943 if (!gdl_dock_layout_save_to_file (app
->layout_manager
, filename
))
944 g_warning ("Saving dock layout to '%s' failed!", filename
);
946 /* This is a good place to save the accels too */
951 anjuta_app_layout_load (AnjutaApp
*app
, const gchar
*layout_filename
,
954 g_return_if_fail (ANJUTA_IS_APP (app
));
956 if (!layout_filename
||
957 !gdl_dock_layout_load_from_file (app
->layout_manager
, layout_filename
))
959 gchar
*datadir
, *filename
;
960 datadir
= anjuta_res_get_data_dir();
962 filename
= g_build_filename (datadir
, "layout.xml", NULL
);
963 DEBUG_PRINT ("Layout = %s", filename
);
965 if (!gdl_dock_layout_load_from_file (app
->layout_manager
, filename
))
966 g_warning ("Loading layout from '%s' failed!!", filename
);
970 if (!gdl_dock_layout_load_layout (app
->layout_manager
, name
))
971 g_warning ("Loading layout failed!!");
975 anjuta_app_layout_reset (AnjutaApp
*app
)
977 anjuta_app_layout_load (app
, NULL
, NULL
);
981 anjuta_app_install_preferences (AnjutaApp
*app
)
984 GtkWidget
*notebook
, *shortcuts
, *plugins
, *remember_plugins
;
986 /* Create preferences page */
987 gxml
= glade_xml_new (GLADE_FILE
, "anjuta_preferences_window", NULL
);
988 anjuta_preferences_add_page (app
->preferences
, gxml
,
989 "General", _("General"), ICON_FILE
);
990 notebook
= glade_xml_get_widget (gxml
, "General");
991 shortcuts
= anjuta_ui_get_accel_editor (ANJUTA_UI (app
->ui
));
992 plugins
= anjuta_plugin_manager_get_plugins_page (app
->plugin_manager
);
993 remember_plugins
= anjuta_plugin_manager_get_remembered_plugins_page (app
->plugin_manager
);
995 gtk_widget_show (shortcuts
);
996 gtk_widget_show (plugins
);
997 gtk_widget_show (remember_plugins
);
999 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), plugins
,
1000 gtk_label_new (_("Installed plugins")));
1001 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), remember_plugins
,
1002 gtk_label_new (_("Preferred plugins")));
1003 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), shortcuts
,
1004 gtk_label_new (_("Shortcuts")));
1006 g_object_unref (gxml
);
1009 /* AnjutaShell Implementation */
1012 on_value_removed_from_hash (gpointer value
)
1014 g_value_unset ((GValue
*)value
);
1019 anjuta_app_add_value (AnjutaShell
*shell
, const char *name
,
1020 const GValue
*value
, GError
**error
)
1025 g_return_if_fail (ANJUTA_IS_APP (shell
));
1026 g_return_if_fail (name
!= NULL
);
1027 g_return_if_fail (G_IS_VALUE(value
));
1029 app
= ANJUTA_APP (shell
);
1031 if (app
->values
== NULL
)
1033 app
->values
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
,
1034 on_value_removed_from_hash
);
1036 anjuta_shell_remove_value (shell
, name
, error
);
1038 copy
= g_new0 (GValue
, 1);
1039 g_value_init (copy
, value
->g_type
);
1040 g_value_copy (value
, copy
);
1042 g_hash_table_insert (app
->values
, g_strdup (name
), copy
);
1043 g_signal_emit_by_name (shell
, "value_added", name
, copy
);
1047 anjuta_app_get_value (AnjutaShell
*shell
, const char *name
, GValue
*value
,
1053 g_return_if_fail (ANJUTA_IS_APP (shell
));
1054 g_return_if_fail (name
!= NULL
);
1055 /* g_return_if_fail (G_IS_VALUE (value)); */
1057 app
= ANJUTA_APP (shell
);
1061 val
= g_hash_table_lookup (app
->values
, name
);
1066 g_value_init (value
, val
->g_type
);
1068 g_value_copy (val
, value
);
1074 *error
= g_error_new (ANJUTA_SHELL_ERROR
,
1075 ANJUTA_SHELL_ERROR_DOESNT_EXIST
,
1076 _("Value doesn't exist"));
1082 anjuta_app_remove_value (AnjutaShell
*shell
, const char *name
, GError
**error
)
1088 g_return_if_fail (ANJUTA_IS_APP (shell
));
1089 g_return_if_fail (name
!= NULL
);
1091 app
= ANJUTA_APP (shell
);
1094 g_return_if_fail (app->values != NULL);
1095 if (app->widgets && g_hash_table_lookup_extended (app->widgets, name,
1099 item = g_object_get_data (G_OBJECT (w), "dockitem");
1100 gdl_dock_item_hide_item (GDL_DOCK_ITEM (item));
1101 gdl_dock_object_unbind (GDL_DOCK_OBJECT (item));
1106 if (app
->values
&& g_hash_table_lookup_extended (app
->values
, name
,
1108 (gpointer
)&value
)) {
1109 g_signal_emit_by_name (app
, "value_removed", name
);
1110 g_hash_table_remove (app
->values
, name
);
1115 remove_from_widgets_hash (gpointer name
, gpointer hash_widget
, gpointer widget
)
1117 if (hash_widget
== widget
)
1123 on_widget_destroy (GtkWidget
*widget
, AnjutaApp
*app
)
1125 DEBUG_PRINT ("Widget about to be destroyed");
1126 g_hash_table_foreach_remove (app
->widgets
, remove_from_widgets_hash
,
1131 on_widget_remove (GtkWidget
*container
, GtkWidget
*widget
, AnjutaApp
*app
)
1133 GtkWidget
*dock_item
;
1134 GList
* node
= toolbars
;
1137 if (node
->data
== widget
)
1139 g_message("Removing toolbar");
1140 GtkWidget
* menuitem
= GTK_WIDGET(g_object_get_data(G_OBJECT(widget
), "menuitem"));
1141 gtk_widget_hide(menuitem
);
1142 gtk_widget_destroy(menuitem
);
1143 toolbars
= g_list_delete_link(toolbars
, node
);
1146 node
= g_list_next(node
);
1149 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1152 gchar
* unique_name
= g_object_get_data(G_OBJECT(dock_item
), "unique_name");
1153 g_free(unique_name
);
1154 g_signal_handlers_disconnect_by_func (G_OBJECT (dock_item
),
1155 G_CALLBACK (on_widget_remove
), app
);
1156 gdl_dock_item_unbind (GDL_DOCK_ITEM(dock_item
));
1158 if (g_hash_table_foreach_remove (app
->widgets
,
1159 remove_from_widgets_hash
,
1161 DEBUG_PRINT ("Widget removed from container");
1166 on_widget_removed_from_hash (gpointer widget
)
1169 GtkWidget
*menuitem
;
1170 GdlDockItem
*dockitem
;
1172 DEBUG_PRINT ("Removing widget from hash");
1174 app
= g_object_get_data (G_OBJECT (widget
), "app-object");
1175 dockitem
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1176 menuitem
= g_object_get_data (G_OBJECT (widget
), "menuitem");
1178 gtk_widget_destroy (menuitem
);
1180 g_object_set_data (G_OBJECT (widget
), "dockitem", NULL
);
1181 g_object_set_data (G_OBJECT (widget
), "menuitem", NULL
);
1183 g_signal_handlers_disconnect_by_func (G_OBJECT (widget
),
1184 G_CALLBACK (on_widget_destroy
), app
);
1185 g_signal_handlers_disconnect_by_func (G_OBJECT (dockitem
),
1186 G_CALLBACK (on_widget_remove
), app
);
1188 g_object_unref (G_OBJECT (widget
));
1192 anjuta_app_add_widget_full (AnjutaShell
*shell
,
1196 const char *stock_id
,
1197 AnjutaShellPlacement placement
,
1203 GtkCheckMenuItem
* menuitem
;
1205 g_return_if_fail (ANJUTA_IS_APP (shell
));
1206 g_return_if_fail (GTK_IS_WIDGET (widget
));
1207 g_return_if_fail (name
!= NULL
);
1208 g_return_if_fail (title
!= NULL
);
1210 app
= ANJUTA_APP (shell
);
1213 anjuta_shell_add (shell, name, G_TYPE_FROM_INSTANCE (widget),
1217 /* Add the widget to hash */
1218 if (app
->widgets
== NULL
)
1220 app
->widgets
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
1222 on_widget_removed_from_hash
);
1224 g_hash_table_insert (app
->widgets
, g_strdup (name
), widget
);
1225 g_object_ref (widget
);
1227 /* Add the widget to dock */
1228 if (stock_id
== NULL
)
1229 item
= gdl_dock_item_new (name
, title
, GDL_DOCK_ITEM_BEH_NORMAL
);
1231 item
= gdl_dock_item_new_with_stock (name
, title
, stock_id
,
1232 GDL_DOCK_ITEM_BEH_NORMAL
);
1236 flags
|= GDL_DOCK_ITEM_BEH_NEVER_FLOATING
;
1237 flags
|= GDL_DOCK_ITEM_BEH_CANT_CLOSE
;
1238 flags
|= GDL_DOCK_ITEM_BEH_CANT_ICONIFY
;
1239 flags
|= GDL_DOCK_ITEM_BEH_NO_GRIP
;
1240 g_object_set(G_OBJECT(item
), "behavior", flags
, NULL
);
1243 gtk_container_add (GTK_CONTAINER (item
), widget
);
1244 gdl_dock_add_item (GDL_DOCK (app
->dock
),
1245 GDL_DOCK_ITEM (item
), placement
);
1246 gtk_widget_show_all (item
);
1248 /* Add toggle button for the widget */
1249 menuitem
= GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title
));
1250 gtk_widget_show (GTK_WIDGET (menuitem
));
1251 gtk_check_menu_item_set_active (menuitem
, TRUE
);
1252 gtk_menu_append (GTK_MENU (app
->view_menu
), GTK_WIDGET (menuitem
));
1255 g_object_set( G_OBJECT(menuitem
), "visible", FALSE
, NULL
);
1258 g_object_set_data (G_OBJECT (widget
), "app-object", app
);
1259 g_object_set_data (G_OBJECT (widget
), "menuitem", menuitem
);
1260 g_object_set_data (G_OBJECT (widget
), "dockitem", item
);
1262 /* For toggling widget view on/off */
1263 g_signal_connect (G_OBJECT (menuitem
), "toggled",
1264 G_CALLBACK (on_toggle_widget_view
), item
);
1267 Watch for widget removal/destruction so that it could be
1268 removed from widgets hash.
1270 g_signal_connect (G_OBJECT (item
), "remove",
1271 G_CALLBACK (on_widget_remove
), app
);
1272 g_signal_connect_after (G_OBJECT (widget
), "destroy",
1273 G_CALLBACK (on_widget_destroy
), app
);
1277 anjuta_app_remove_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
1281 GtkWidget
*dock_item
;
1283 g_return_if_fail (ANJUTA_IS_APP (shell
));
1284 g_return_if_fail (GTK_IS_WIDGET (widget
));
1286 app
= ANJUTA_APP (shell
);
1288 g_return_if_fail (app
->widgets
!= NULL
);
1290 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1291 g_return_if_fail (dock_item
!= NULL
);
1293 /* Remove the widget from container */
1294 g_object_ref (widget
);
1295 /* It should call on_widget_remove() and clean up should happen */
1296 gtk_container_remove (GTK_CONTAINER (dock_item
), widget
);
1297 g_object_unref (widget
);
1301 anjuta_app_present_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
1305 GdlDockItem
*dock_item
;
1308 g_return_if_fail (ANJUTA_IS_APP (shell
));
1309 g_return_if_fail (GTK_IS_WIDGET (widget
));
1311 app
= ANJUTA_APP (shell
);
1313 g_return_if_fail (app
->widgets
!= NULL
);
1315 dock_item
= g_object_get_data (G_OBJECT(widget
), "dockitem");
1316 g_return_if_fail (dock_item
!= NULL
);
1318 /* Hack to present the dock item if it's in a notebook dock item */
1319 parent
= gtk_widget_get_parent (GTK_WIDGET(dock_item
) );
1320 if (GTK_IS_NOTEBOOK (parent
))
1323 pagenum
= gtk_notebook_page_num (GTK_NOTEBOOK (parent
), GTK_WIDGET (dock_item
));
1324 gtk_notebook_set_current_page (GTK_NOTEBOOK (parent
), pagenum
);
1326 else if (!GDL_DOCK_OBJECT_ATTACHED (dock_item
))
1328 gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item
));
1331 /* FIXME: If the item is floating, present the window */
1332 /* FIXME: There is no way to detect if a widget was floating before it was
1333 detached since it no longer has a parent there is no way to access the
1334 floating property of the GdlDock structure.*/
1338 anjuta_app_get_object (AnjutaShell
*shell
, const char *iface_name
,
1341 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1342 g_return_val_if_fail (iface_name
!= NULL
, NULL
);
1343 return anjuta_plugin_manager_get_plugin (ANJUTA_APP (shell
)->plugin_manager
,
1347 static AnjutaStatus
*
1348 anjuta_app_get_status (AnjutaShell
*shell
, GError
**error
)
1350 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1351 return ANJUTA_APP (shell
)->status
;
1355 anjuta_app_get_ui (AnjutaShell
*shell
, GError
**error
)
1357 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1358 return ANJUTA_APP (shell
)->ui
;
1361 static AnjutaPreferences
*
1362 anjuta_app_get_preferences (AnjutaShell
*shell
, GError
**error
)
1364 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1365 return ANJUTA_APP (shell
)->preferences
;
1368 static AnjutaPluginManager
*
1369 anjuta_app_get_plugin_manager (AnjutaShell
*shell
, GError
**error
)
1371 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1372 return ANJUTA_APP (shell
)->plugin_manager
;
1375 static AnjutaProfileManager
*
1376 anjuta_app_get_profile_manager (AnjutaShell
*shell
, GError
**error
)
1378 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1379 return ANJUTA_APP (shell
)->profile_manager
;
1383 anjuta_shell_iface_init (AnjutaShellIface
*iface
)
1385 iface
->add_widget_full
= anjuta_app_add_widget_full
;
1386 iface
->remove_widget
= anjuta_app_remove_widget
;
1387 iface
->present_widget
= anjuta_app_present_widget
;
1388 iface
->add_value
= anjuta_app_add_value
;
1389 iface
->get_value
= anjuta_app_get_value
;
1390 iface
->remove_value
= anjuta_app_remove_value
;
1391 iface
->get_object
= anjuta_app_get_object
;
1392 iface
->get_status
= anjuta_app_get_status
;
1393 iface
->get_ui
= anjuta_app_get_ui
;
1394 iface
->get_preferences
= anjuta_app_get_preferences
;
1395 iface
->get_plugin_manager
= anjuta_app_get_plugin_manager
;
1396 iface
->get_profile_manager
= anjuta_app_get_profile_manager
;
1399 ANJUTA_TYPE_BEGIN(AnjutaApp
, anjuta_app
, GTK_TYPE_WINDOW
);
1400 ANJUTA_TYPE_ADD_INTERFACE(anjuta_shell
, ANJUTA_TYPE_SHELL
);