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
31 #include <gtk/gtkwidget.h>
32 #include <glade/glade.h>
34 #include <gdl/gdl-dock.h>
35 #include <gdl/gdl-dock-bar.h>
37 #include <bonobo/bonobo-dock-item.h>
39 #include <libanjuta/anjuta-shell.h>
40 #include <libanjuta/anjuta-utils.h>
41 #include <libanjuta/resources.h>
42 #include <libanjuta/anjuta-plugin-manager.h>
43 #include <libanjuta/anjuta-debug.h>
45 #include "anjuta-app.h"
46 #include "anjuta-callbacks.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 "preferences-general.png"
54 #define DOCK_PH_LEFT "ph_left"
55 #define DOCK_PH_RIGHT "ph_right"
56 #define DOCK_PH_TOP "ph_top"
57 #define DOCK_PH_BOTTOM "ph_bottom"
59 static void anjuta_app_layout_load (AnjutaApp
*app
,
60 const gchar
*layout_filename
,
62 static void anjuta_app_layout_save (AnjutaApp
*app
,
63 const gchar
*layout_filename
,
66 static gpointer parent_class
= NULL
;
67 static GList
* toolbars
= NULL
;
70 on_toggle_widget_view (GtkCheckMenuItem
*menuitem
, GtkWidget
*dockitem
)
73 state
= gtk_check_menu_item_get_active (menuitem
);
75 gdl_dock_item_show_item (GDL_DOCK_ITEM (dockitem
));
77 gdl_dock_item_hide_item (GDL_DOCK_ITEM (dockitem
));
81 on_update_widget_view_menuitem (gpointer key
, gpointer wid
, gpointer data
)
83 GtkCheckMenuItem
*menuitem
;
84 GdlDockItem
*dockitem
;
86 dockitem
= g_object_get_data (G_OBJECT (wid
), "dockitem");
87 menuitem
= g_object_get_data (G_OBJECT (wid
), "menuitem");
89 g_signal_handlers_block_by_func (menuitem
,
90 G_CALLBACK (on_toggle_widget_view
),
93 if (GDL_DOCK_OBJECT_ATTACHED (dockitem
))
94 gtk_check_menu_item_set_active (menuitem
, TRUE
);
96 gtk_check_menu_item_set_active (menuitem
, FALSE
);
98 g_signal_handlers_unblock_by_func (menuitem
,
99 G_CALLBACK (on_toggle_widget_view
),
104 on_layout_dirty_notify (GObject
*object
, GParamSpec
*pspec
, gpointer user_data
)
106 if (!strcmp (pspec
->name
, "dirty")) {
108 g_object_get (object
, "dirty", &dirty
, NULL
);
110 /* Update UI toggle buttons */
111 g_hash_table_foreach (ANJUTA_APP (user_data
)->widgets
,
112 on_update_widget_view_menuitem
,
119 on_layout_locked_notify (GdlDockMaster
*master
,
128 action
= anjuta_ui_get_action (ui
, "ActionGroupToggleView",
129 "ActionViewLockLayout");
131 g_object_get (master
, "locked", &locked
, NULL
);
132 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
),
137 on_toolbar_view_toggled (GtkCheckMenuItem
*menuitem
, GtkWidget
*widget
)
140 BonoboDockItem
*dock_item
;
147 name
= gtk_widget_get_name (widget
);
148 app
= g_object_get_data (G_OBJECT(widget
), "app");
149 dock_item
= g_object_get_data (G_OBJECT(widget
), "dock_item");
150 band
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget
), "band"));
151 position
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget
), "position"));
152 offset
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget
), "offset"));
155 if (gtk_check_menu_item_get_active (menuitem
))
160 gchar
*unique_name
= g_strdup_printf ("%s-%d", name
, count
);
162 /* gnome_app_add_docked() does not allow adding a widget using
163 * a previously used name (even if the previous widget has
164 * has be destroyed. Hence a unique_name is used by using a
166 DEBUG_PRINT ("Adding dock item %s band %d, offset %d, position %d", unique_name
,
167 band
, offset
, position
);
169 /* Widget not yet added to the dock. Add it */
170 gnome_app_add_docked (GNOME_APP (app
), widget
,
172 BONOBO_DOCK_ITEM_BEH_NEVER_VERTICAL
|
173 BONOBO_DOCK_ITEM_BEH_NEVER_FLOATING
,
174 BONOBO_DOCK_TOP
, band
, position
, offset
);
176 dock_item
= gnome_app_get_dock_item_by_name (GNOME_APP (app
),
178 g_object_set_data_full (G_OBJECT(dock_item
), "unique_name", unique_name
, g_free
);
179 g_object_set_data (G_OBJECT(widget
), "dock_item", dock_item
);
182 gtk_widget_show (GTK_WIDGET (dock_item
));
183 gtk_widget_show (GTK_BIN (dock_item
)->child
);
187 gtk_widget_hide (GTK_WIDGET (dock_item
));
188 gtk_widget_hide (GTK_BIN (dock_item
)->child
);
193 on_merge_widget_destroy (GtkWidget
*merge_widget
, GtkWidget
*menuitem
)
195 toolbars
= g_list_remove (toolbars
, merge_widget
);
196 DEBUG_PRINT ("Destroying menuitem for toolbar widget");
197 gtk_widget_destroy (menuitem
);
201 on_add_merge_widget (GtkUIManager
*merge
, GtkWidget
*widget
,
202 GtkWidget
*ui_container
)
204 DEBUG_PRINT ("Adding UI item ...");
206 if (GTK_IS_MENU_BAR (widget
))
208 gnome_app_set_menus (GNOME_APP (ui_container
), GTK_MENU_BAR (widget
));
209 gtk_widget_show (widget
);
213 static gint count
= 0;
214 const gchar
*toolbarname
;
219 AnjutaPreferences
*pr
;
224 pr
= ANJUTA_PREFERENCES (ANJUTA_APP(ui_container
)->preferences
);
226 /* Showing the arrows seem to break anything completly! */
227 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (widget
), FALSE
);
229 gtk_widget_show (widget
);
230 g_object_set_data (G_OBJECT (widget
), "app", ui_container
);
232 /* Load toolbar position */
233 toolbarname
= gtk_widget_get_name (widget
);
234 band_key
= g_strconcat (toolbarname
, ".band", NULL
);
235 position_key
= g_strconcat (toolbarname
, ".position", NULL
);
236 offset_key
= g_strconcat (toolbarname
, ".offset", NULL
);
237 band
= anjuta_preferences_get_int_with_default(pr
, band_key
, -1);
238 position
= anjuta_preferences_get_int_with_default(pr
, position_key
, 0);
239 offset
= anjuta_preferences_get_int_with_default(pr
, offset_key
, 0);
240 /* Without these check you might see odd results */
243 g_object_set_data(G_OBJECT(widget
), "position", GINT_TO_POINTER(position
));
244 g_object_set_data(G_OBJECT(widget
), "offset", GINT_TO_POINTER(offset
));
245 g_object_set_data (G_OBJECT (widget
), "band",
246 GINT_TO_POINTER(band
));
248 g_free(position_key
);
250 DEBUG_PRINT ("Adding toolbar: %s", toolbarname
);
252 if (!ANJUTA_APP (ui_container
)->toolbars_menu
)
254 ANJUTA_APP (ui_container
)->toolbars_menu
= gtk_menu_new ();
255 gtk_widget_show (GTK_WIDGET (ANJUTA_APP (ui_container
)->toolbars_menu
));
258 menuitem
= gtk_check_menu_item_new_with_label (toolbarname
);
259 gtk_menu_append (GTK_MENU (ANJUTA_APP (ui_container
)->toolbars_menu
),
261 gtk_widget_show (GTK_WIDGET (menuitem
));
262 g_signal_connect (G_OBJECT (menuitem
), "toggled",
263 G_CALLBACK (on_toolbar_view_toggled
), widget
);
264 g_object_set_data(G_OBJECT(widget
), "menuitem", menuitem
);
266 /* When the toolbar is destroyed make sure corresponding menuitem is
268 g_signal_connect (widget
, "destroy",
269 G_CALLBACK (on_merge_widget_destroy
),
272 toolbars
= g_list_append(toolbars
, widget
);
274 /* Show/hide toolbar */
275 visible_key
= g_strconcat (toolbarname
, ".visible", NULL
);
276 if (anjuta_preferences_get_int_with_default (pr
, visible_key
,
279 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem
),
282 g_free (visible_key
);
288 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
289 AnjutaSession
*session
, AnjutaApp
*app
)
291 gchar
*geometry
, *layout_file
;
292 GdkWindowState state
;
293 GList
* node
= toolbars
;
296 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
302 GtkWidget
* widget
= node
->data
;
303 GtkWidget
* dock_item
= g_object_get_data (G_OBJECT(widget
), "dock_item");;
304 const gchar
* toolbarname
= gtk_widget_get_name(widget
);
305 AnjutaPreferences
* pr
= ANJUTA_PREFERENCES (app
->preferences
);
310 gchar
* key
= g_strconcat (toolbarname
, ".visible", NULL
);
311 gchar
* band_key
= g_strconcat (toolbarname
, ".band", NULL
);
312 gchar
* position_key
= g_strconcat (toolbarname
, ".position", NULL
);
313 gchar
* offset_key
= g_strconcat (toolbarname
, ".offset", NULL
);
314 GnomeApp
* gnome_app
= GNOME_APP(app
);
316 /* Save visibility */
317 g_object_get(G_OBJECT(dock_item
), "visible", &visible
, NULL
);
318 anjuta_preferences_set_int(pr
, key
, visible
);
321 /* Save toolbar position */
322 if (gnome_app
->dock
!= NULL
)
327 BonoboDockPlacement placement
;
328 gchar
* unique_name
= g_object_get_data(G_OBJECT(dock_item
), "unique_name");
330 BonoboDockItem
* item
= bonobo_dock_get_item_by_name(BONOBO_DOCK(gnome_app
->dock
),
331 unique_name
, &placement
,
332 &band
, &position
, &offset
);
333 g_return_if_fail(item
!= NULL
);
335 anjuta_preferences_set_int(pr
, band_key
, band
);
336 anjuta_preferences_set_int(pr
, position_key
, position
);
337 anjuta_preferences_set_int(pr
, offset_key
, offset
);
340 node
= g_list_next(node
);
344 state
= gdk_window_get_state (GTK_WIDGET (app
)->window
);
345 if (state
& GDK_WINDOW_STATE_MAXIMIZED
) {
346 anjuta_session_set_int (session
, "Anjuta", "Maximized", 1);
348 if (state
& GDK_WINDOW_STATE_FULLSCREEN
) {
349 anjuta_session_set_int (session
, "Anjuta", "Fullscreen", 1);
352 /* Save geometry only if window is not maximized or fullscreened */
353 if (!(state
& GDK_WINDOW_STATE_MAXIMIZED
) ||
354 !(state
& GDK_WINDOW_STATE_FULLSCREEN
))
356 geometry
= anjuta_app_get_geometry (app
);
358 anjuta_session_set_string (session
, "Anjuta", "Geometry",
364 layout_file
= g_build_filename (anjuta_session_get_session_directory (session
),
365 "dock-layout.xml", NULL
);
366 anjuta_app_layout_save (app
, layout_file
, NULL
);
367 g_free (layout_file
);
371 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
372 AnjutaSession
*session
, AnjutaApp
*app
)
374 /* We load layout at last so that all plugins would have loaded by now */
375 if (phase
== ANJUTA_SESSION_PHASE_LAST
)
380 /* Restore geometry */
381 geometry
= anjuta_session_get_string (session
, "Anjuta", "Geometry");
382 anjuta_app_set_geometry (app
, geometry
);
384 /* Restore window state */
385 if (anjuta_session_get_int (session
, "Anjuta", "Fullscreen"))
388 AnjutaUI
* ui
= anjuta_shell_get_ui(shell
, NULL
);
389 GtkAction
* action
= anjuta_ui_get_action (ui
, "ActionGroupToggleView",
390 "ActionViewFullscreen");
391 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
),
394 gtk_window_fullscreen (GTK_WINDOW (shell
));
397 else if (anjuta_session_get_int (session
, "Anjuta", "Maximized"))
399 gtk_window_maximize (GTK_WINDOW (shell
));
403 layout_file
= g_build_filename (anjuta_session_get_session_directory (session
),
404 "dock-layout.xml", NULL
);
405 anjuta_app_layout_load (app
, layout_file
, NULL
);
406 g_free (layout_file
);
411 on_accel_changed (GtkAccelGroup
*accelgroup
, guint arg1
, GdkModifierType arg2
,
412 GClosure
*arg3
, AnjutaApp
*app
)
414 gnome_accelerators_sync ();
418 anjuta_app_dispose (GObject
*widget
)
423 g_return_if_fail (ANJUTA_IS_APP (widget
));
425 app
= ANJUTA_APP (widget
);
429 if (g_hash_table_size (app
->widgets
) > 0)
432 g_warning ("Some widgets are still inside shell (%d widgets), they are:",
433 g_hash_table_size (app->widgets));
434 g_hash_table_foreach (app->widgets, (GHFunc)puts, NULL);
437 g_hash_table_destroy (app
->widgets
);
443 if (g_hash_table_size (app
->values
) > 0)
446 g_warning ("Some Values are still left in shell (%d Values), they are:",
447 g_hash_table_size (app->values));
448 g_hash_table_foreach (app->values, (GHFunc)puts, NULL);
451 g_hash_table_destroy (app
->values
);
455 /* We need to destroy to the toolbars now so that the
456 * on_merge_widget_destroy() does not produce a error trying to destory
457 * already destroyed menuitems which happen when the window is being
460 * Make a tmp list because the handler removes items from 'toolbars' list.
461 * FIXME: Why is 'toolbars' a global static variable?
463 tmp_list
= g_list_copy (toolbars
);
464 g_list_foreach (tmp_list
, (GFunc
)gtk_widget_destroy
, NULL
);
465 g_list_free (tmp_list
);
467 if (app
->layout_manager
) {
468 g_object_unref (app
->layout_manager
);
469 app
->layout_manager
= NULL
;
471 if (app
->profile_manager
) {
472 g_object_unref (G_OBJECT (app
->profile_manager
));
473 app
->profile_manager
= NULL
;
475 if (app
->plugin_manager
) {
476 g_object_unref (G_OBJECT (app
->plugin_manager
));
477 app
->plugin_manager
= NULL
;
480 g_object_unref (G_OBJECT (app
->status
));
483 GNOME_CALL_PARENT(G_OBJECT_CLASS
, dispose
, (widget
));
487 anjuta_app_finalize (GObject
*widget
)
491 g_return_if_fail (ANJUTA_IS_APP (widget
));
493 app
= ANJUTA_APP (widget
);
495 gtk_widget_destroy (GTK_WIDGET (app
->ui
));
496 gtk_widget_destroy (GTK_WIDGET (app
->preferences
));
498 GNOME_CALL_PARENT(G_OBJECT_CLASS
, finalize
, (widget
));
502 anjuta_app_instance_init (AnjutaApp
*app
)
505 GtkWidget
*toolbar_menu
, *about_menu
;
506 GtkWidget
*view_menu
, *hbox
;
508 GtkAccelGroup
*accel_group
;
510 GList
*plugins_dirs
= NULL
;
511 GdkGeometry size_hints
= {
512 100, 100, 0, 0, 100, 100, 1, 1, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
515 DEBUG_PRINT ("Initializing Anjuta...");
517 gtk_window_set_geometry_hints (GTK_WINDOW (app
), GTK_WIDGET (app
),
518 &size_hints
, GDK_HINT_RESIZE_INC
);
519 gtk_window_set_resizable (GTK_WINDOW (app
), TRUE
);
521 gnome_app_enable_layout_config (GNOME_APP (app
), FALSE
);
523 app
->layout_manager
= NULL
;
529 hbox
= gtk_hbox_new (FALSE
, 0);
530 gtk_widget_show (hbox
);
531 gnome_app_set_contents (GNOME_APP (app
), hbox
);
532 app
->dock
= gdl_dock_new ();
533 gtk_widget_show (app
->dock
);
534 gtk_box_pack_end(GTK_BOX (hbox
), app
->dock
, TRUE
, TRUE
, 0);
536 dockbar
= gdl_dock_bar_new (GDL_DOCK(app
->dock
));
537 gtk_widget_show (dockbar
);
538 gtk_box_pack_start(GTK_BOX (hbox
), dockbar
, FALSE
, FALSE
, 0);
540 app
->layout_manager
= gdl_dock_layout_new (GDL_DOCK (app
->dock
));
541 g_signal_connect (app
->layout_manager
, "notify::dirty",
542 G_CALLBACK (on_layout_dirty_notify
), app
);
543 g_signal_connect (app
->layout_manager
->master
, "notify::locked",
544 G_CALLBACK (on_layout_locked_notify
), app
);
546 app
->status
= ANJUTA_STATUS (anjuta_status_new ());
547 anjuta_status_set_title_window (app
->status
, GTK_WIDGET (app
));
548 gtk_widget_show (GTK_WIDGET (app
->status
));
549 gnome_app_set_statusbar (GNOME_APP (app
), GTK_WIDGET (app
->status
));
550 g_object_ref (G_OBJECT (app
->status
));
551 g_object_add_weak_pointer (G_OBJECT (app
->status
), (gpointer
)&app
->status
);
554 app
->ui
= anjuta_ui_new ();
556 accel_group
= anjuta_ui_get_accel_group (app
->ui
);
557 g_signal_connect (accel_group
, "accel-changed",
558 G_CALLBACK (on_accel_changed
), app
);
560 gtk_window_add_accel_group (GTK_WINDOW (app
), accel_group
);
561 g_signal_connect (G_OBJECT (app
->ui
),
562 "add_widget", G_CALLBACK (on_add_merge_widget
),
564 g_object_add_weak_pointer (G_OBJECT (app
->ui
), (gpointer
)&app
->ui
);
567 plugins_dirs
= g_list_prepend (plugins_dirs
, PACKAGE_PLUGIN_DIR
);
568 app
->plugin_manager
= anjuta_plugin_manager_new (G_OBJECT (app
),
571 app
->profile_manager
= anjuta_profile_manager_new (app
->plugin_manager
);
572 g_list_free (plugins_dirs
);
575 app
->preferences
= anjuta_preferences_new (app
->plugin_manager
);
576 g_object_add_weak_pointer (G_OBJECT (app
->preferences
),
577 (gpointer
)&app
->preferences
);
579 /* Register actions */
580 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupFile", _("File"),
582 G_N_ELEMENTS (menu_entries_file
),
583 GETTEXT_PACKAGE
, TRUE
, app
);
584 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupEdit", _("Edit"),
586 G_N_ELEMENTS (menu_entries_edit
),
587 GETTEXT_PACKAGE
, TRUE
, app
);
588 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupView", _("View"),
590 G_N_ELEMENTS (menu_entries_view
),
591 GETTEXT_PACKAGE
, TRUE
, app
);
592 anjuta_ui_add_toggle_action_group_entries (app
->ui
, "ActionGroupToggleView",
594 menu_entries_toggle_view
,
595 G_N_ELEMENTS (menu_entries_toggle_view
),
596 GETTEXT_PACKAGE
, TRUE
, app
);
597 anjuta_ui_add_action_group_entries (app
->ui
, "ActionGroupHelp", _("Help"),
599 G_N_ELEMENTS (menu_entries_help
),
600 GETTEXT_PACKAGE
, TRUE
, app
);
603 merge_id
= anjuta_ui_merge (app
->ui
, UI_FILE
);
605 /* Disable unavailible tutorials */
606 action
= anjuta_ui_get_action(app
->ui
, "ActionGroupHelp", "ActionHelpTutorial");
607 g_object_set(G_OBJECT(action
), "visible", FALSE
, NULL
);
608 action
= anjuta_ui_get_action(app
->ui
, "ActionGroupHelp", "ActionHelpAdvancedTutorial");
609 g_object_set(G_OBJECT(action
), "visible", FALSE
, NULL
);
611 /* create toolbar menus */
613 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
614 "/MenuMain/MenuView/Toolbars");
616 gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolbar_menu
),
619 g_warning ("Cannot retrive main menu widget");
621 /* Create widgets menu */
623 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
624 "/MenuMain/MenuView");
625 app
->view_menu
= gtk_menu_item_get_submenu (GTK_MENU_ITEM (view_menu
));
627 /* Create about plugins menu */
629 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app
->ui
),
630 "/MenuMain/PlaceHolderHelpMenus/MenuHelp/"
631 "PlaceHolderHelpAbout/AboutPlugins");
632 about_create_plugins_submenu (ANJUTA_SHELL (app
), about_menu
);
634 /* Connect to session */
635 g_signal_connect (G_OBJECT (app
), "save_session",
636 G_CALLBACK (on_session_save
), app
);
637 g_signal_connect (G_OBJECT (app
), "load_session",
638 G_CALLBACK (on_session_load
), app
);
642 anjuta_app_class_init (AnjutaAppClass
*class)
644 GObjectClass
*object_class
;
645 GtkWidgetClass
*widget_class
;
647 parent_class
= g_type_class_peek_parent (class);
648 object_class
= (GObjectClass
*) class;
649 widget_class
= (GtkWidgetClass
*) class;
650 object_class
->finalize
= anjuta_app_finalize
;
651 object_class
->dispose
= anjuta_app_dispose
;
655 anjuta_app_new (void)
659 app
= ANJUTA_APP (g_object_new (ANJUTA_TYPE_APP
,
662 return GTK_WIDGET (app
);
666 anjuta_app_get_geometry (AnjutaApp
*app
)
669 gint width
, height
, posx
, posy
;
671 g_return_val_if_fail (ANJUTA_IS_APP (app
), NULL
);
674 width
= height
= posx
= posy
= 0;
675 if (GTK_WIDGET(app
)->window
)
677 gtk_window_get_size (GTK_WINDOW (app
), &width
, &height
);
678 gtk_window_get_position (GTK_WINDOW(app
), &posx
, &posy
);
680 geometry
= g_strdup_printf ("%dx%d+%d+%d", width
, height
, posx
, posy
);
686 anjuta_app_set_geometry (AnjutaApp
*app
, const gchar
*geometry
)
688 gint width
, height
, posx
, posy
;
689 gboolean geometry_set
= FALSE
;
691 if (geometry
&& strlen (geometry
) > 0)
693 DEBUG_PRINT ("Setting geometry: %s", geometry
);
695 if (sscanf (geometry
, "%dx%d+%d+%d", &width
, &height
,
698 if (GTK_WIDGET_REALIZED (app
))
700 gtk_window_resize (GTK_WINDOW (app
), width
, height
);
704 gtk_window_set_default_size (GTK_WINDOW (app
), width
, height
);
705 gtk_window_move (GTK_WINDOW (app
), posx
, posy
);
711 g_warning ("Failed to parse geometry: %s", geometry
);
718 width
= gdk_screen_width () - 10;
719 height
= gdk_screen_height () - 25;
720 width
= (width
< 790)? width
: 790;
721 height
= (height
< 575)? width
: 575;
722 if (GTK_WIDGET_REALIZED (app
) == FALSE
)
724 gtk_window_set_default_size (GTK_WINDOW (app
), width
, height
);
725 gtk_window_move (GTK_WINDOW (app
), posx
, posy
);
731 anjuta_app_layout_save (AnjutaApp
*app
, const gchar
*filename
,
734 g_return_if_fail (ANJUTA_IS_APP (app
));
735 g_return_if_fail (filename
!= NULL
);
737 gdl_dock_layout_save_layout (app
->layout_manager
, name
);
738 if (!gdl_dock_layout_save_to_file (app
->layout_manager
, filename
))
739 g_warning ("Saving dock layout to '%s' failed!", filename
);
743 anjuta_app_layout_load (AnjutaApp
*app
, const gchar
*layout_filename
,
746 g_return_if_fail (ANJUTA_IS_APP (app
));
748 if (!layout_filename
||
749 !gdl_dock_layout_load_from_file (app
->layout_manager
, layout_filename
))
751 gchar
*datadir
, *filename
;
752 datadir
= anjuta_res_get_data_dir();
754 filename
= g_build_filename (datadir
, "layout.xml", NULL
);
755 DEBUG_PRINT ("Layout = %s", filename
);
757 if (!gdl_dock_layout_load_from_file (app
->layout_manager
, filename
))
758 g_warning ("Loading layout from '%s' failed!!", filename
);
762 if (!gdl_dock_layout_load_layout (app
->layout_manager
, name
))
763 g_warning ("Loading layout failed!!");
767 anjuta_app_layout_reset (AnjutaApp
*app
)
769 anjuta_app_layout_load (app
, NULL
, NULL
);
773 anjuta_app_install_preferences (AnjutaApp
*app
)
776 GtkWidget
*notebook
, *shortcuts
, *plugins
, *remember_plugins
;
778 /* Create preferences page */
779 gxml
= glade_xml_new (GLADE_FILE
, "anjuta_preferences_window", NULL
);
780 anjuta_preferences_add_page (app
->preferences
, gxml
,
781 "General", _("General"), ICON_FILE
);
782 notebook
= glade_xml_get_widget (gxml
, "General");
783 shortcuts
= anjuta_ui_get_accel_editor (ANJUTA_UI (app
->ui
));
784 plugins
= anjuta_plugin_manager_get_plugins_page (app
->plugin_manager
);
785 remember_plugins
= anjuta_plugin_manager_get_remembered_plugins_page (app
->plugin_manager
);
787 gtk_widget_show (shortcuts
);
788 gtk_widget_show (plugins
);
789 gtk_widget_show (remember_plugins
);
791 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), plugins
,
792 gtk_label_new (_("Installed plugins")));
793 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), remember_plugins
,
794 gtk_label_new (_("Preferred plugins")));
795 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
), shortcuts
,
796 gtk_label_new (_("Shortcuts")));
798 g_object_unref (gxml
);
801 /* AnjutaShell Implementation */
804 on_value_removed_from_hash (gpointer value
)
806 g_value_unset ((GValue
*)value
);
811 anjuta_app_add_value (AnjutaShell
*shell
, const char *name
,
812 const GValue
*value
, GError
**error
)
817 g_return_if_fail (ANJUTA_IS_APP (shell
));
818 g_return_if_fail (name
!= NULL
);
819 g_return_if_fail (G_IS_VALUE(value
));
821 app
= ANJUTA_APP (shell
);
823 if (app
->values
== NULL
)
825 app
->values
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
,
826 on_value_removed_from_hash
);
828 anjuta_shell_remove_value (shell
, name
, error
);
830 copy
= g_new0 (GValue
, 1);
831 g_value_init (copy
, value
->g_type
);
832 g_value_copy (value
, copy
);
834 g_hash_table_insert (app
->values
, g_strdup (name
), copy
);
835 g_signal_emit_by_name (shell
, "value_added", name
, copy
);
839 anjuta_app_get_value (AnjutaShell
*shell
, const char *name
, GValue
*value
,
845 g_return_if_fail (ANJUTA_IS_APP (shell
));
846 g_return_if_fail (name
!= NULL
);
847 /* g_return_if_fail (G_IS_VALUE (value)); */
849 app
= ANJUTA_APP (shell
);
853 val
= g_hash_table_lookup (app
->values
, name
);
858 g_value_init (value
, val
->g_type
);
860 g_value_copy (val
, value
);
866 *error
= g_error_new (ANJUTA_SHELL_ERROR
,
867 ANJUTA_SHELL_ERROR_DOESNT_EXIST
,
868 _("Value doesn't exist"));
874 anjuta_app_remove_value (AnjutaShell
*shell
, const char *name
, GError
**error
)
880 g_return_if_fail (ANJUTA_IS_APP (shell
));
881 g_return_if_fail (name
!= NULL
);
883 app
= ANJUTA_APP (shell
);
886 g_return_if_fail (app->values != NULL);
887 if (app->widgets && g_hash_table_lookup_extended (app->widgets, name,
891 item = g_object_get_data (G_OBJECT (w), "dockitem");
892 gdl_dock_item_hide_item (GDL_DOCK_ITEM (item));
893 gdl_dock_object_unbind (GDL_DOCK_OBJECT (item));
898 if (app
->values
&& g_hash_table_lookup_extended (app
->values
, name
,
901 g_signal_emit_by_name (app
, "value_removed", name
);
902 g_hash_table_remove (app
->values
, name
);
907 remove_from_widgets_hash (gpointer name
, gpointer hash_widget
, gpointer widget
)
909 if (hash_widget
== widget
)
915 on_widget_destroy (GtkWidget
*widget
, AnjutaApp
*app
)
917 DEBUG_PRINT ("Widget about to be destroyed");
918 g_hash_table_foreach_remove (app
->widgets
, remove_from_widgets_hash
,
923 on_widget_remove (GtkWidget
*container
, GtkWidget
*widget
, AnjutaApp
*app
)
925 GtkWidget
*dock_item
;
926 GList
* node
= toolbars
;
929 if (node
->data
== widget
)
931 g_message("Removing toolbar");
932 GtkWidget
* menuitem
= GTK_WIDGET(g_object_get_data(G_OBJECT(widget
), "menuitem"));
933 gtk_widget_hide(menuitem
);
934 gtk_widget_destroy(menuitem
);
935 toolbars
= g_list_delete_link(toolbars
, node
);
938 node
= g_list_next(node
);
941 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
944 gchar
* unique_name
= g_object_get_data(G_OBJECT(dock_item
), "unique_name");
946 g_signal_handlers_disconnect_by_func (G_OBJECT (dock_item
),
947 G_CALLBACK (on_widget_remove
), app
);
948 gdl_dock_item_unbind (GDL_DOCK_ITEM(dock_item
));
950 if (g_hash_table_foreach_remove (app
->widgets
,
951 remove_from_widgets_hash
,
953 DEBUG_PRINT ("Widget removed from container");
958 on_widget_removed_from_hash (gpointer widget
)
962 GdlDockItem
*dockitem
;
964 DEBUG_PRINT ("Removing widget from hash");
966 app
= g_object_get_data (G_OBJECT (widget
), "app-object");
967 dockitem
= g_object_get_data (G_OBJECT (widget
), "dockitem");
968 menuitem
= g_object_get_data (G_OBJECT (widget
), "menuitem");
970 gtk_widget_destroy (menuitem
);
972 g_object_set_data (G_OBJECT (widget
), "dockitem", NULL
);
973 g_object_set_data (G_OBJECT (widget
), "menuitem", NULL
);
975 g_signal_handlers_disconnect_by_func (G_OBJECT (widget
),
976 G_CALLBACK (on_widget_destroy
), app
);
977 g_signal_handlers_disconnect_by_func (G_OBJECT (dockitem
),
978 G_CALLBACK (on_widget_remove
), app
);
980 g_object_unref (G_OBJECT (widget
));
984 anjuta_app_add_widget_full (AnjutaShell
*shell
,
988 const char *stock_id
,
989 AnjutaShellPlacement placement
,
995 GtkCheckMenuItem
* menuitem
;
997 g_return_if_fail (ANJUTA_IS_APP (shell
));
998 g_return_if_fail (GTK_IS_WIDGET (widget
));
999 g_return_if_fail (name
!= NULL
);
1000 g_return_if_fail (title
!= NULL
);
1002 app
= ANJUTA_APP (shell
);
1005 anjuta_shell_add (shell, name, G_TYPE_FROM_INSTANCE (widget),
1009 /* Add the widget to hash */
1010 if (app
->widgets
== NULL
)
1012 app
->widgets
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
1014 on_widget_removed_from_hash
);
1016 g_hash_table_insert (app
->widgets
, g_strdup (name
), widget
);
1017 g_object_ref (widget
);
1019 /* Add the widget to dock */
1020 if (stock_id
== NULL
)
1021 item
= gdl_dock_item_new (name
, title
, GDL_DOCK_ITEM_BEH_NORMAL
);
1023 item
= gdl_dock_item_new_with_stock (name
, title
, stock_id
,
1024 GDL_DOCK_ITEM_BEH_NORMAL
);
1028 flags
|= GDL_DOCK_ITEM_BEH_NEVER_FLOATING
;
1029 flags
|= GDL_DOCK_ITEM_BEH_CANT_CLOSE
;
1030 flags
|= GDL_DOCK_ITEM_BEH_CANT_ICONIFY
;
1031 flags
|= GDL_DOCK_ITEM_BEH_NO_GRIP
;
1032 g_object_set(G_OBJECT(item
), "behavior", flags
, NULL
);
1035 gtk_container_add (GTK_CONTAINER (item
), widget
);
1036 gdl_dock_add_item (GDL_DOCK (app
->dock
),
1037 GDL_DOCK_ITEM (item
), placement
);
1038 gtk_widget_show_all (item
);
1040 /* Add toggle button for the widget */
1041 menuitem
= GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title
));
1042 gtk_widget_show (GTK_WIDGET (menuitem
));
1043 gtk_check_menu_item_set_active (menuitem
, TRUE
);
1044 gtk_menu_append (GTK_MENU (app
->view_menu
), GTK_WIDGET (menuitem
));
1047 g_object_set( G_OBJECT(menuitem
), "visible", FALSE
);
1050 g_object_set_data (G_OBJECT (widget
), "app-object", app
);
1051 g_object_set_data (G_OBJECT (widget
), "menuitem", menuitem
);
1052 g_object_set_data (G_OBJECT (widget
), "dockitem", item
);
1054 /* For toggling widget view on/off */
1055 g_signal_connect (G_OBJECT (menuitem
), "toggled",
1056 G_CALLBACK (on_toggle_widget_view
), item
);
1059 Watch for widget removal/destruction so that it could be
1060 removed from widgets hash.
1062 g_signal_connect (G_OBJECT (item
), "remove",
1063 G_CALLBACK (on_widget_remove
), app
);
1064 g_signal_connect_after (G_OBJECT (widget
), "destroy",
1065 G_CALLBACK (on_widget_destroy
), app
);
1069 anjuta_app_remove_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
1073 GtkWidget
*dock_item
;
1075 g_return_if_fail (ANJUTA_IS_APP (shell
));
1076 g_return_if_fail (GTK_IS_WIDGET (widget
));
1078 app
= ANJUTA_APP (shell
);
1080 g_return_if_fail (app
->widgets
!= NULL
);
1082 dock_item
= g_object_get_data (G_OBJECT (widget
), "dockitem");
1083 g_return_if_fail (dock_item
!= NULL
);
1085 /* Remove the widget from container */
1086 g_object_ref (widget
);
1087 /* It should call on_widget_remove() and clean up should happen */
1088 gtk_container_remove (GTK_CONTAINER (dock_item
), widget
);
1089 g_object_unref (widget
);
1093 anjuta_app_present_widget (AnjutaShell
*shell
, GtkWidget
*widget
,
1097 GdlDockItem
*dock_item
;
1100 g_return_if_fail (ANJUTA_IS_APP (shell
));
1101 g_return_if_fail (GTK_IS_WIDGET (widget
));
1103 app
= ANJUTA_APP (shell
);
1105 g_return_if_fail (app
->widgets
!= NULL
);
1107 dock_item
= g_object_get_data (G_OBJECT(widget
), "dockitem");
1108 g_return_if_fail (dock_item
!= NULL
);
1110 /* Hack to present the dock item if it's in a notebook dock item */
1111 parent
= gtk_widget_get_parent (GTK_WIDGET(dock_item
) );
1112 if (GTK_IS_NOTEBOOK (parent
))
1115 pagenum
= gtk_notebook_page_num (GTK_NOTEBOOK (parent
), GTK_WIDGET (dock_item
));
1116 gtk_notebook_set_current_page (GTK_NOTEBOOK (parent
), pagenum
);
1118 else if (!GDL_DOCK_OBJECT_ATTACHED (dock_item
))
1120 gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item
));
1123 /* FIXME: If the item is floating, present the window */
1124 /* FIXME: There is no way to detect if a widget was floating before it was
1125 detached since it no longer has a parent there is no way to access the
1126 floating property of the GdlDock structure.*/
1130 anjuta_app_get_object (AnjutaShell
*shell
, const char *iface_name
,
1133 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1134 g_return_val_if_fail (iface_name
!= NULL
, NULL
);
1135 return anjuta_plugin_manager_get_plugin (ANJUTA_APP (shell
)->plugin_manager
,
1139 static AnjutaStatus
*
1140 anjuta_app_get_status (AnjutaShell
*shell
, GError
**error
)
1142 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1143 return ANJUTA_APP (shell
)->status
;
1147 anjuta_app_get_ui (AnjutaShell
*shell
, GError
**error
)
1149 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1150 return ANJUTA_APP (shell
)->ui
;
1153 static AnjutaPreferences
*
1154 anjuta_app_get_preferences (AnjutaShell
*shell
, GError
**error
)
1156 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1157 return ANJUTA_APP (shell
)->preferences
;
1160 static AnjutaPluginManager
*
1161 anjuta_app_get_plugin_manager (AnjutaShell
*shell
, GError
**error
)
1163 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1164 return ANJUTA_APP (shell
)->plugin_manager
;
1167 static AnjutaProfileManager
*
1168 anjuta_app_get_profile_manager (AnjutaShell
*shell
, GError
**error
)
1170 g_return_val_if_fail (ANJUTA_IS_APP (shell
), NULL
);
1171 return ANJUTA_APP (shell
)->profile_manager
;
1175 anjuta_shell_iface_init (AnjutaShellIface
*iface
)
1177 iface
->add_widget_full
= anjuta_app_add_widget_full
;
1178 iface
->remove_widget
= anjuta_app_remove_widget
;
1179 iface
->present_widget
= anjuta_app_present_widget
;
1180 iface
->add_value
= anjuta_app_add_value
;
1181 iface
->get_value
= anjuta_app_get_value
;
1182 iface
->remove_value
= anjuta_app_remove_value
;
1183 iface
->get_object
= anjuta_app_get_object
;
1184 iface
->get_status
= anjuta_app_get_status
;
1185 iface
->get_ui
= anjuta_app_get_ui
;
1186 iface
->get_preferences
= anjuta_app_get_preferences
;
1187 iface
->get_plugin_manager
= anjuta_app_get_plugin_manager
;
1188 iface
->get_profile_manager
= anjuta_app_get_profile_manager
;
1191 ANJUTA_TYPE_BEGIN(AnjutaApp
, anjuta_app
, GNOME_TYPE_APP
);
1192 ANJUTA_TYPE_ADD_INTERFACE(anjuta_shell
, ANJUTA_TYPE_SHELL
);