Updated Spanish translation
[anjuta-git-plugin.git] / src / anjuta-app.c
blob7ca82b896a81737a2eda98cacf9d17fa27bfa98e
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta.c Copyright (C) 2003 Naba Kumar <naba@gnome.org>
4 *
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)
8 * any later version.
9 *
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
13 * for more details.
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
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <signal.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <sys/wait.h>
30 #include <gnome.h>
31 #include <gtk/gtkwidget.h>
32 #include <glade/glade.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-callbacks.h"
48 #include "anjuta-actions.h"
49 #include "about.h"
51 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta.ui"
52 #define GLADE_FILE PACKAGE_DATA_DIR"/glade/anjuta.glade"
53 #define ICON_FILE "anjuta-preferences-general-48.png"
55 #define DOCK_PH_LEFT "ph_left"
56 #define DOCK_PH_RIGHT "ph_right"
57 #define DOCK_PH_TOP "ph_top"
58 #define DOCK_PH_BOTTOM "ph_bottom"
60 static void anjuta_app_layout_load (AnjutaApp *app,
61 const gchar *layout_filename,
62 const gchar *name);
63 static void anjuta_app_layout_save (AnjutaApp *app,
64 const gchar *layout_filename,
65 const gchar *name);
67 static gpointer parent_class = NULL;
68 static GList* toolbars = NULL;
70 static void
71 on_gdl_style_changed (GConfClient* client, guint id, GConfEntry* entry,
72 gpointer user_data)
74 AnjutaApp* app = ANJUTA_APP (user_data);
75 GdlSwitcherStyle style = GDL_SWITCHER_STYLE_BOTH;
77 gchar* pr_style = anjuta_preferences_get (app->preferences, "anjuta.gdl.style");
79 if (pr_style)
81 if (strcasecmp (pr_style, "Text") == 0)
82 style = GDL_SWITCHER_STYLE_TEXT;
83 else if (strcasecmp (pr_style, "Icon") == 0)
84 style = GDL_SWITCHER_STYLE_ICON;
85 else if (strcasecmp (pr_style, "Both") == 0)
86 style = GDL_SWITCHER_STYLE_BOTH;
87 else if (strcasecmp (pr_style, "Toolbar") == 0)
88 style = GDL_SWITCHER_STYLE_TOOLBAR;
89 else if (strcasecmp (pr_style, "Tabs") == 0)
90 style = GDL_SWITCHER_STYLE_TABS;
92 DEBUG_PRINT ("Switcher style: %s", pr_style);
94 g_free (pr_style);
96 g_object_set (G_OBJECT(app->layout_manager->master), "switcher-style",
97 style, NULL);
100 static void
101 on_toggle_widget_view (GtkCheckMenuItem *menuitem, GtkWidget *dockitem)
103 gboolean state;
104 state = gtk_check_menu_item_get_active (menuitem);
105 if (state)
106 gdl_dock_item_show_item (GDL_DOCK_ITEM (dockitem));
107 else
108 gdl_dock_item_hide_item (GDL_DOCK_ITEM (dockitem));
111 static void
112 on_update_widget_view_menuitem (gpointer key, gpointer wid, gpointer data)
114 GtkCheckMenuItem *menuitem;
115 GdlDockItem *dockitem;
117 dockitem = g_object_get_data (G_OBJECT (wid), "dockitem");
118 menuitem = g_object_get_data (G_OBJECT (wid), "menuitem");
120 g_signal_handlers_block_by_func (menuitem,
121 G_CALLBACK (on_toggle_widget_view),
122 dockitem);
124 if (GDL_DOCK_OBJECT_ATTACHED (dockitem))
125 gtk_check_menu_item_set_active (menuitem, TRUE);
126 else
127 gtk_check_menu_item_set_active (menuitem, FALSE);
129 g_signal_handlers_unblock_by_func (menuitem,
130 G_CALLBACK (on_toggle_widget_view),
131 dockitem);
134 static void
135 on_layout_dirty_notify (GObject *object, GParamSpec *pspec, gpointer user_data)
137 if (!strcmp (pspec->name, "dirty")) {
138 gboolean dirty;
139 g_object_get (object, "dirty", &dirty, NULL);
140 if (dirty) {
141 /* Update UI toggle buttons */
142 g_hash_table_foreach (ANJUTA_APP (user_data)->widgets,
143 on_update_widget_view_menuitem,
144 NULL);
149 static void
150 on_layout_locked_notify (GdlDockMaster *master,
151 GParamSpec *pspec,
152 AnjutaApp *app)
154 AnjutaUI *ui;
155 GtkAction *action;
156 gint locked;
158 ui = app->ui;
159 action = anjuta_ui_get_action (ui, "ActionGroupToggleView",
160 "ActionViewLockLayout");
162 g_object_get (master, "locked", &locked, NULL);
163 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
164 (locked == 1));
167 static void
168 on_toolbar_view_toggled (GtkCheckMenuItem *menuitem, GtkWidget *widget)
170 AnjutaApp *app;
171 BonoboDockItem *dock_item;
172 const gchar *name;
173 gint band;
174 gint position;
175 gint offset;
178 name = gtk_widget_get_name (widget);
179 app = g_object_get_data (G_OBJECT(widget), "app");
180 dock_item = g_object_get_data (G_OBJECT(widget), "dock_item");
181 band = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget), "band"));
182 position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget), "position"));
183 offset = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(widget), "offset"));
186 if (gtk_check_menu_item_get_active (menuitem))
188 if (!dock_item)
190 static gint count;
191 gchar *unique_name = g_strdup_printf ("%s-%d", name, count);
193 /* gnome_app_add_docked() does not allow adding a widget using
194 * a previously used name (even if the previous widget has
195 * has be destroyed. Hence a unique_name is used by using a
196 * static counter */
197 DEBUG_PRINT ("Adding dock item %s band %d, offset %d, position %d", unique_name,
198 band, offset, position);
200 /* Widget not yet added to the dock. Add it */
201 gnome_app_add_docked (GNOME_APP (app), widget,
202 unique_name,
203 BONOBO_DOCK_ITEM_BEH_NEVER_VERTICAL |
204 BONOBO_DOCK_ITEM_BEH_NEVER_FLOATING,
205 BONOBO_DOCK_TOP, band, position, offset);
207 dock_item = gnome_app_get_dock_item_by_name (GNOME_APP (app),
208 unique_name);
209 g_object_set_data_full (G_OBJECT(dock_item), "unique_name", unique_name, g_free);
210 g_object_set_data (G_OBJECT(widget), "dock_item", dock_item);
211 count++;
213 gtk_widget_show (GTK_WIDGET (dock_item));
214 gtk_widget_show (GTK_BIN (dock_item)->child);
216 else if (dock_item)
218 gtk_widget_hide (GTK_WIDGET (dock_item));
219 gtk_widget_hide (GTK_BIN (dock_item)->child);
223 static void
224 on_merge_widget_destroy (GtkWidget *merge_widget, GtkWidget *menuitem)
226 toolbars = g_list_remove (toolbars, merge_widget);
227 DEBUG_PRINT ("Destroying menuitem for toolbar widget");
228 gtk_widget_destroy (menuitem);
231 static void
232 on_add_merge_widget (GtkUIManager *merge, GtkWidget *widget,
233 GtkWidget *ui_container)
235 DEBUG_PRINT ("Adding UI item ...");
237 if (GTK_IS_MENU_BAR (widget))
239 gnome_app_set_menus (GNOME_APP (ui_container), GTK_MENU_BAR (widget));
240 gtk_widget_show (widget);
242 else
244 static gint count = 0;
245 const gchar *toolbarname;
246 gchar* visible_key;
247 gchar* band_key;
248 gchar* position_key;
249 gchar* offset_key;
250 AnjutaPreferences *pr;
251 GtkWidget *menuitem;
252 gint band;
253 gint position;
254 gint offset;
255 pr = ANJUTA_PREFERENCES (ANJUTA_APP(ui_container)->preferences);
257 /* Showing the arrows seem to break anything completly! */
258 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (widget), FALSE);
260 gtk_widget_show (widget);
261 g_object_set_data (G_OBJECT (widget), "app", ui_container);
263 /* Load toolbar position */
264 toolbarname = gtk_widget_get_name (widget);
265 band_key = g_strconcat (toolbarname, ".band", NULL);
266 position_key = g_strconcat (toolbarname, ".position", NULL);
267 offset_key = g_strconcat (toolbarname, ".offset", NULL);
268 band = anjuta_preferences_get_int_with_default(pr, band_key, -1);
269 position = anjuta_preferences_get_int_with_default(pr, position_key, 0);
270 offset = anjuta_preferences_get_int_with_default(pr, offset_key, 0);
271 /* Without these check you might see odd results */
272 if (band < 1)
273 band = count + 1;
274 g_object_set_data(G_OBJECT(widget), "position", GINT_TO_POINTER(position));
275 g_object_set_data(G_OBJECT(widget), "offset", GINT_TO_POINTER(offset));
276 g_object_set_data (G_OBJECT (widget), "band",
277 GINT_TO_POINTER(band));
278 g_free(offset_key);
279 g_free(position_key);
280 g_free(band_key);
281 DEBUG_PRINT ("Adding toolbar: %s", toolbarname);
283 if (!ANJUTA_APP (ui_container)->toolbars_menu)
285 ANJUTA_APP (ui_container)->toolbars_menu = gtk_menu_new ();
286 gtk_widget_show (GTK_WIDGET (ANJUTA_APP (ui_container)->toolbars_menu));
289 menuitem = gtk_check_menu_item_new_with_label (toolbarname);
290 gtk_menu_append (GTK_MENU (ANJUTA_APP (ui_container)->toolbars_menu),
291 menuitem);
292 gtk_widget_show (GTK_WIDGET (menuitem));
293 g_signal_connect (G_OBJECT (menuitem), "toggled",
294 G_CALLBACK (on_toolbar_view_toggled), widget);
295 g_object_set_data(G_OBJECT(widget), "menuitem", menuitem);
297 /* When the toolbar is destroyed make sure corresponding menuitem is
298 * also destroyed */
299 g_signal_connect (widget, "destroy",
300 G_CALLBACK (on_merge_widget_destroy),
301 menuitem);
303 toolbars = g_list_append(toolbars, widget);
305 /* Show/hide toolbar */
306 visible_key = g_strconcat (toolbarname, ".visible", NULL);
307 if (anjuta_preferences_get_int_with_default (pr, visible_key,
308 (count == 0)? 1:0))
310 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
311 TRUE);
313 g_free (visible_key);
314 count ++;
318 static void
319 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
320 AnjutaSession *session, AnjutaApp *app)
322 gchar *geometry, *layout_file;
323 GdkWindowState state;
324 GList* node = toolbars;
327 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
328 return;
330 /* Save toolbars */
331 while (node)
333 GtkWidget* widget = node->data;
334 GtkWidget* dock_item = g_object_get_data (G_OBJECT(widget), "dock_item");;
335 const gchar* toolbarname = gtk_widget_get_name(widget);
336 AnjutaPreferences* pr = ANJUTA_PREFERENCES (app->preferences);
338 if (dock_item)
340 gboolean visible;
341 gchar* key = g_strconcat (toolbarname, ".visible", NULL);
342 gchar* band_key = g_strconcat (toolbarname, ".band", NULL);
343 gchar* position_key = g_strconcat (toolbarname, ".position", NULL);
344 gchar* offset_key = g_strconcat (toolbarname, ".offset", NULL);
345 GnomeApp* gnome_app = GNOME_APP(app);
347 /* Save visibility */
348 g_object_get(G_OBJECT(dock_item), "visible", &visible, NULL);
349 anjuta_preferences_set_int(pr, key, visible);
350 g_free(key);
352 /* Save toolbar position */
353 if (gnome_app->dock != NULL)
355 guint band;
356 guint position;
357 guint offset;
358 BonoboDockPlacement placement;
359 gchar* unique_name = g_object_get_data(G_OBJECT(dock_item), "unique_name");
361 BonoboDockItem* item = bonobo_dock_get_item_by_name(BONOBO_DOCK(gnome_app->dock),
362 unique_name, &placement,
363 &band, &position, &offset);
364 g_return_if_fail(item != NULL);
366 anjuta_preferences_set_int(pr, band_key, band);
367 anjuta_preferences_set_int(pr, position_key, position);
368 anjuta_preferences_set_int(pr, offset_key, offset);
371 node = g_list_next(node);
374 /* Save geometry */
375 state = gdk_window_get_state (GTK_WIDGET (app)->window);
376 if (state & GDK_WINDOW_STATE_MAXIMIZED) {
377 anjuta_session_set_int (session, "Anjuta", "Maximized", 1);
379 if (state & GDK_WINDOW_STATE_FULLSCREEN) {
380 anjuta_session_set_int (session, "Anjuta", "Fullscreen", 1);
383 /* Save geometry only if window is not maximized or fullscreened */
384 if (!(state & GDK_WINDOW_STATE_MAXIMIZED) ||
385 !(state & GDK_WINDOW_STATE_FULLSCREEN))
387 geometry = anjuta_app_get_geometry (app);
388 if (geometry)
389 anjuta_session_set_string (session, "Anjuta", "Geometry",
390 geometry);
391 g_free (geometry);
394 /* Save layout */
395 layout_file = g_build_filename (anjuta_session_get_session_directory (session),
396 "dock-layout.xml", NULL);
397 anjuta_app_layout_save (app, layout_file, NULL);
398 g_free (layout_file);
401 static void
402 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
403 AnjutaSession *session, AnjutaApp *app)
405 /* We load layout at last so that all plugins would have loaded by now */
406 if (phase == ANJUTA_SESSION_PHASE_LAST)
408 gchar *geometry;
409 gchar *layout_file;
411 /* Restore geometry */
412 geometry = anjuta_session_get_string (session, "Anjuta", "Geometry");
413 anjuta_app_set_geometry (app, geometry);
415 /* Restore window state */
416 if (anjuta_session_get_int (session, "Anjuta", "Fullscreen"))
418 /* bug #304495 */
419 AnjutaUI* ui = anjuta_shell_get_ui(shell, NULL);
420 GtkAction* action = anjuta_ui_get_action (ui, "ActionGroupToggleView",
421 "ActionViewFullscreen");
422 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
423 TRUE);
425 gtk_window_fullscreen (GTK_WINDOW (shell));
428 else if (anjuta_session_get_int (session, "Anjuta", "Maximized"))
430 gtk_window_maximize (GTK_WINDOW (shell));
433 /* Restore layout */
434 layout_file = g_build_filename (anjuta_session_get_session_directory (session),
435 "dock-layout.xml", NULL);
436 anjuta_app_layout_load (app, layout_file, NULL);
437 g_free (layout_file);
441 static void
442 on_accel_changed (GtkAccelGroup *accelgroup, guint arg1, GdkModifierType arg2,
443 GClosure *arg3, AnjutaApp *app)
445 gnome_accelerators_sync ();
448 static void
449 anjuta_app_dispose (GObject *widget)
451 AnjutaApp *app;
452 GList *tmp_list;
454 g_return_if_fail (ANJUTA_IS_APP (widget));
456 app = ANJUTA_APP (widget);
458 if (app->widgets)
460 if (g_hash_table_size (app->widgets) > 0)
463 g_warning ("Some widgets are still inside shell (%d widgets), they are:",
464 g_hash_table_size (app->widgets));
465 g_hash_table_foreach (app->widgets, (GHFunc)puts, NULL);
468 g_hash_table_destroy (app->widgets);
469 app->widgets = NULL;
472 if (app->values)
474 if (g_hash_table_size (app->values) > 0)
477 g_warning ("Some Values are still left in shell (%d Values), they are:",
478 g_hash_table_size (app->values));
479 g_hash_table_foreach (app->values, (GHFunc)puts, NULL);
482 g_hash_table_destroy (app->values);
483 app->values = NULL;
486 /* We need to destroy to the toolbars now so that the
487 * on_merge_widget_destroy() does not produce a error trying to destory
488 * already destroyed menuitems which happen when the window is being
489 * destroyed
491 * Make a tmp list because the handler removes items from 'toolbars' list.
492 * FIXME: Why is 'toolbars' a global static variable?
494 tmp_list = g_list_copy (toolbars);
495 g_list_foreach (tmp_list, (GFunc)gtk_widget_destroy, NULL);
496 g_list_free (tmp_list);
498 if (app->layout_manager) {
499 g_object_unref (app->layout_manager);
500 app->layout_manager = NULL;
502 if (app->profile_manager) {
503 g_object_unref (G_OBJECT (app->profile_manager));
504 app->profile_manager = NULL;
506 if (app->plugin_manager) {
507 g_object_unref (G_OBJECT (app->plugin_manager));
508 app->plugin_manager = NULL;
510 if (app->status) {
511 g_object_unref (G_OBJECT (app->status));
512 app->status = NULL;
514 GNOME_CALL_PARENT(G_OBJECT_CLASS, dispose, (widget));
517 static void
518 anjuta_app_finalize (GObject *widget)
520 AnjutaApp *app;
522 g_return_if_fail (ANJUTA_IS_APP (widget));
524 app = ANJUTA_APP (widget);
526 gtk_widget_destroy (GTK_WIDGET (app->ui));
527 gtk_widget_destroy (GTK_WIDGET (app->preferences));
529 GNOME_CALL_PARENT(G_OBJECT_CLASS, finalize, (widget));
532 static void
533 anjuta_app_instance_init (AnjutaApp *app)
535 gint merge_id;
536 GtkWidget *toolbar_menu, *about_menu;
537 GtkWidget *view_menu, *hbox;
538 GtkWidget *dockbar;
539 GtkAccelGroup *accel_group;
540 GtkAction* action;
541 GList *plugins_dirs = NULL;
542 GdkGeometry size_hints = {
543 100, 100, 0, 0, 100, 100, 1, 1, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
546 DEBUG_PRINT ("Initializing Anjuta...");
548 gtk_window_set_geometry_hints (GTK_WINDOW (app), GTK_WIDGET (app),
549 &size_hints, GDK_HINT_RESIZE_INC);
550 gtk_window_set_resizable (GTK_WINDOW (app), TRUE);
552 gnome_app_enable_layout_config (GNOME_APP (app), FALSE);
554 app->layout_manager = NULL;
556 app->values = NULL;
557 app->widgets = NULL;
559 /* configure dock */
560 hbox = gtk_hbox_new (FALSE, 0);
561 gtk_widget_show (hbox);
562 gnome_app_set_contents (GNOME_APP (app), hbox);
563 app->dock = gdl_dock_new ();
564 gtk_widget_show (app->dock);
565 gtk_box_pack_end(GTK_BOX (hbox), app->dock, TRUE, TRUE, 0);
567 dockbar = gdl_dock_bar_new (GDL_DOCK(app->dock));
568 gtk_widget_show (dockbar);
569 gtk_box_pack_start(GTK_BOX (hbox), dockbar, FALSE, FALSE, 0);
571 app->layout_manager = gdl_dock_layout_new (GDL_DOCK (app->dock));
572 g_signal_connect (app->layout_manager, "notify::dirty",
573 G_CALLBACK (on_layout_dirty_notify), app);
574 g_signal_connect (app->layout_manager->master, "notify::locked",
575 G_CALLBACK (on_layout_locked_notify), app);
576 /* Status bar */
577 app->status = ANJUTA_STATUS (anjuta_status_new ());
578 anjuta_status_set_title_window (app->status, GTK_WIDGET (app));
579 gtk_widget_show (GTK_WIDGET (app->status));
580 gnome_app_set_statusbar (GNOME_APP (app), GTK_WIDGET (app->status));
581 g_object_ref (G_OBJECT (app->status));
582 g_object_add_weak_pointer (G_OBJECT (app->status), (gpointer)&app->status);
584 /* UI engine */
585 app->ui = anjuta_ui_new ();
587 accel_group = anjuta_ui_get_accel_group (app->ui);
588 g_signal_connect (accel_group, "accel-changed",
589 G_CALLBACK (on_accel_changed), app);
591 gtk_window_add_accel_group (GTK_WINDOW (app), accel_group);
592 g_signal_connect (G_OBJECT (app->ui),
593 "add_widget", G_CALLBACK (on_add_merge_widget),
594 app);
595 g_object_add_weak_pointer (G_OBJECT (app->ui), (gpointer)&app->ui);
597 /* Plugin Manager */
598 plugins_dirs = g_list_prepend (plugins_dirs, PACKAGE_PLUGIN_DIR);
599 app->plugin_manager = anjuta_plugin_manager_new (G_OBJECT (app),
600 app->status,
601 plugins_dirs);
602 app->profile_manager = anjuta_profile_manager_new (app->plugin_manager);
603 g_list_free (plugins_dirs);
605 /* Preferences */
606 app->preferences = anjuta_preferences_new (app->plugin_manager);
607 g_object_add_weak_pointer (G_OBJECT (app->preferences),
608 (gpointer)&app->preferences);
610 anjuta_preferences_notify_add (app->preferences, "anjuta.gdl.style",
611 on_gdl_style_changed, app, NULL);
613 on_gdl_style_changed (NULL, 0, NULL, app);
615 /* Register actions */
616 anjuta_ui_add_action_group_entries (app->ui, "ActionGroupFile", _("File"),
617 menu_entries_file,
618 G_N_ELEMENTS (menu_entries_file),
619 GETTEXT_PACKAGE, TRUE, app);
620 anjuta_ui_add_action_group_entries (app->ui, "ActionGroupEdit", _("Edit"),
621 menu_entries_edit,
622 G_N_ELEMENTS (menu_entries_edit),
623 GETTEXT_PACKAGE, TRUE, app);
624 anjuta_ui_add_action_group_entries (app->ui, "ActionGroupView", _("View"),
625 menu_entries_view,
626 G_N_ELEMENTS (menu_entries_view),
627 GETTEXT_PACKAGE, TRUE, app);
628 anjuta_ui_add_toggle_action_group_entries (app->ui, "ActionGroupToggleView",
629 _("Toggle View"),
630 menu_entries_toggle_view,
631 G_N_ELEMENTS (menu_entries_toggle_view),
632 GETTEXT_PACKAGE, TRUE, app);
633 anjuta_ui_add_action_group_entries (app->ui, "ActionGroupHelp", _("Help"),
634 menu_entries_help,
635 G_N_ELEMENTS (menu_entries_help),
636 GETTEXT_PACKAGE, TRUE, app);
638 /* Merge UI */
639 merge_id = anjuta_ui_merge (app->ui, UI_FILE);
641 /* Disable unavailible tutorials */
642 action = anjuta_ui_get_action(app->ui, "ActionGroupHelp", "ActionHelpTutorial");
643 g_object_set(G_OBJECT(action), "visible", FALSE, NULL);
644 action = anjuta_ui_get_action(app->ui, "ActionGroupHelp", "ActionHelpAdvancedTutorial");
645 g_object_set(G_OBJECT(action), "visible", FALSE, NULL);
647 /* create toolbar menus */
648 toolbar_menu =
649 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app->ui),
650 "/MenuMain/MenuView/Toolbars");
651 if (toolbar_menu)
652 gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolbar_menu),
653 app->toolbars_menu);
654 else
655 g_warning ("Cannot retrive main menu widget");
657 /* Create widgets menu */
658 view_menu =
659 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app->ui),
660 "/MenuMain/MenuView");
661 app->view_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (view_menu));
663 /* Create about plugins menu */
664 about_menu =
665 gtk_ui_manager_get_widget (GTK_UI_MANAGER(app->ui),
666 "/MenuMain/PlaceHolderHelpMenus/MenuHelp/"
667 "PlaceHolderHelpAbout/AboutPlugins");
668 about_create_plugins_submenu (ANJUTA_SHELL (app), about_menu);
670 /* Connect to session */
671 g_signal_connect (G_OBJECT (app), "save_session",
672 G_CALLBACK (on_session_save), app);
673 g_signal_connect (G_OBJECT (app), "load_session",
674 G_CALLBACK (on_session_load), app);
677 static void
678 anjuta_app_class_init (AnjutaAppClass *class)
680 GObjectClass *object_class;
681 GtkWidgetClass *widget_class;
683 parent_class = g_type_class_peek_parent (class);
684 object_class = (GObjectClass*) class;
685 widget_class = (GtkWidgetClass*) class;
686 object_class->finalize = anjuta_app_finalize;
687 object_class->dispose = anjuta_app_dispose;
690 GtkWidget *
691 anjuta_app_new (void)
693 AnjutaApp *app;
695 app = ANJUTA_APP (g_object_new (ANJUTA_TYPE_APP,
696 "title", "Anjuta",
697 NULL));
698 return GTK_WIDGET (app);
701 gchar*
702 anjuta_app_get_geometry (AnjutaApp *app)
704 gchar *geometry;
705 gint width, height, posx, posy;
707 g_return_val_if_fail (ANJUTA_IS_APP (app), NULL);
709 geometry = NULL;
710 width = height = posx = posy = 0;
711 if (GTK_WIDGET(app)->window)
713 gtk_window_get_size (GTK_WINDOW (app), &width, &height);
714 gtk_window_get_position (GTK_WINDOW(app), &posx, &posy);
716 geometry = g_strdup_printf ("%dx%d+%d+%d", width, height, posx, posy);
718 return geometry;
721 void
722 anjuta_app_set_geometry (AnjutaApp *app, const gchar *geometry)
724 gint width, height, posx, posy;
725 gboolean geometry_set = FALSE;
727 if (geometry && strlen (geometry) > 0)
729 DEBUG_PRINT ("Setting geometry: %s", geometry);
731 if (sscanf (geometry, "%dx%d+%d+%d", &width, &height,
732 &posx, &posy) == 4)
734 if (GTK_WIDGET_REALIZED (app))
736 gtk_window_resize (GTK_WINDOW (app), width, height);
738 else
740 gtk_window_set_default_size (GTK_WINDOW (app), width, height);
741 gtk_window_move (GTK_WINDOW (app), posx, posy);
743 geometry_set = TRUE;
745 else
747 g_warning ("Failed to parse geometry: %s", geometry);
750 if (!geometry_set)
752 posx = 10;
753 posy = 10;
754 width = gdk_screen_width () - 10;
755 height = gdk_screen_height () - 25;
756 width = (width < 790)? width : 790;
757 height = (height < 575)? width : 575;
758 if (GTK_WIDGET_REALIZED (app) == FALSE)
760 gtk_window_set_default_size (GTK_WINDOW (app), width, height);
761 gtk_window_move (GTK_WINDOW (app), posx, posy);
766 static void
767 anjuta_app_layout_save (AnjutaApp *app, const gchar *filename,
768 const gchar *name)
770 g_return_if_fail (ANJUTA_IS_APP (app));
771 g_return_if_fail (filename != NULL);
773 gdl_dock_layout_save_layout (app->layout_manager, name);
774 if (!gdl_dock_layout_save_to_file (app->layout_manager, filename))
775 g_warning ("Saving dock layout to '%s' failed!", filename);
778 static void
779 anjuta_app_layout_load (AnjutaApp *app, const gchar *layout_filename,
780 const gchar *name)
782 g_return_if_fail (ANJUTA_IS_APP (app));
784 if (!layout_filename ||
785 !gdl_dock_layout_load_from_file (app->layout_manager, layout_filename))
787 gchar *datadir, *filename;
788 datadir = anjuta_res_get_data_dir();
790 filename = g_build_filename (datadir, "layout.xml", NULL);
791 DEBUG_PRINT ("Layout = %s", filename);
792 g_free (datadir);
793 if (!gdl_dock_layout_load_from_file (app->layout_manager, filename))
794 g_warning ("Loading layout from '%s' failed!!", filename);
795 g_free (filename);
798 if (!gdl_dock_layout_load_layout (app->layout_manager, name))
799 g_warning ("Loading layout failed!!");
802 void
803 anjuta_app_layout_reset (AnjutaApp *app)
805 anjuta_app_layout_load (app, NULL, NULL);
808 void
809 anjuta_app_install_preferences (AnjutaApp *app)
811 GladeXML *gxml;
812 GtkWidget *notebook, *shortcuts, *plugins, *remember_plugins;
814 /* Create preferences page */
815 gxml = glade_xml_new (GLADE_FILE, "anjuta_preferences_window", NULL);
816 anjuta_preferences_add_page (app->preferences, gxml,
817 "General", _("General"), ICON_FILE);
818 notebook = glade_xml_get_widget (gxml, "General");
819 shortcuts = anjuta_ui_get_accel_editor (ANJUTA_UI (app->ui));
820 plugins = anjuta_plugin_manager_get_plugins_page (app->plugin_manager);
821 remember_plugins = anjuta_plugin_manager_get_remembered_plugins_page (app->plugin_manager);
823 gtk_widget_show (shortcuts);
824 gtk_widget_show (plugins);
825 gtk_widget_show (remember_plugins);
827 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), plugins,
828 gtk_label_new (_("Installed plugins")));
829 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), remember_plugins,
830 gtk_label_new (_("Preferred plugins")));
831 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), shortcuts,
832 gtk_label_new (_("Shortcuts")));
834 g_object_unref (gxml);
837 /* AnjutaShell Implementation */
839 static void
840 on_value_removed_from_hash (gpointer value)
842 g_value_unset ((GValue*)value);
843 g_free (value);
846 static void
847 anjuta_app_add_value (AnjutaShell *shell, const char *name,
848 const GValue *value, GError **error)
850 GValue *copy;
851 AnjutaApp *app;
853 g_return_if_fail (ANJUTA_IS_APP (shell));
854 g_return_if_fail (name != NULL);
855 g_return_if_fail (G_IS_VALUE(value));
857 app = ANJUTA_APP (shell);
859 if (app->values == NULL)
861 app->values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
862 on_value_removed_from_hash);
864 anjuta_shell_remove_value (shell, name, error);
866 copy = g_new0 (GValue, 1);
867 g_value_init (copy, value->g_type);
868 g_value_copy (value, copy);
870 g_hash_table_insert (app->values, g_strdup (name), copy);
871 g_signal_emit_by_name (shell, "value_added", name, copy);
874 static void
875 anjuta_app_get_value (AnjutaShell *shell, const char *name, GValue *value,
876 GError **error)
878 GValue *val;
879 AnjutaApp *app;
881 g_return_if_fail (ANJUTA_IS_APP (shell));
882 g_return_if_fail (name != NULL);
883 /* g_return_if_fail (G_IS_VALUE (value)); */
885 app = ANJUTA_APP (shell);
887 val = NULL;
888 if (app->values)
889 val = g_hash_table_lookup (app->values, name);
890 if (val)
892 if (!value->g_type)
894 g_value_init (value, val->g_type);
896 g_value_copy (val, value);
898 else
900 if (error)
902 *error = g_error_new (ANJUTA_SHELL_ERROR,
903 ANJUTA_SHELL_ERROR_DOESNT_EXIST,
904 _("Value doesn't exist"));
909 static void
910 anjuta_app_remove_value (AnjutaShell *shell, const char *name, GError **error)
912 AnjutaApp *app;
913 GValue *value;
914 char *key;
916 g_return_if_fail (ANJUTA_IS_APP (shell));
917 g_return_if_fail (name != NULL);
919 app = ANJUTA_APP (shell);
922 g_return_if_fail (app->values != NULL);
923 if (app->widgets && g_hash_table_lookup_extended (app->widgets, name,
924 (gpointer*)&key,
925 (gpointer*)&w)) {
926 GtkWidget *item;
927 item = g_object_get_data (G_OBJECT (w), "dockitem");
928 gdl_dock_item_hide_item (GDL_DOCK_ITEM (item));
929 gdl_dock_object_unbind (GDL_DOCK_OBJECT (item));
930 g_free (key);
934 if (app->values && g_hash_table_lookup_extended (app->values, name,
935 (gpointer)&key,
936 (gpointer)&value)) {
937 g_signal_emit_by_name (app, "value_removed", name);
938 g_hash_table_remove (app->values, name);
942 static gboolean
943 remove_from_widgets_hash (gpointer name, gpointer hash_widget, gpointer widget)
945 if (hash_widget == widget)
946 return TRUE;
947 return FALSE;
950 static void
951 on_widget_destroy (GtkWidget *widget, AnjutaApp *app)
953 DEBUG_PRINT ("Widget about to be destroyed");
954 g_hash_table_foreach_remove (app->widgets, remove_from_widgets_hash,
955 widget);
958 static void
959 on_widget_remove (GtkWidget *container, GtkWidget *widget, AnjutaApp *app)
961 GtkWidget *dock_item;
962 GList* node = toolbars;
963 while (node)
965 if (node->data == widget)
967 g_message("Removing toolbar");
968 GtkWidget* menuitem = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "menuitem"));
969 gtk_widget_hide(menuitem);
970 gtk_widget_destroy(menuitem);
971 toolbars = g_list_delete_link(toolbars, node);
972 break;
974 node = g_list_next(node);
977 dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
978 if (dock_item)
980 gchar* unique_name = g_object_get_data(G_OBJECT(dock_item), "unique_name");
981 g_free(unique_name);
982 g_signal_handlers_disconnect_by_func (G_OBJECT (dock_item),
983 G_CALLBACK (on_widget_remove), app);
984 gdl_dock_item_unbind (GDL_DOCK_ITEM(dock_item));
986 if (g_hash_table_foreach_remove (app->widgets,
987 remove_from_widgets_hash,
988 widget)){
989 DEBUG_PRINT ("Widget removed from container");
993 static void
994 on_widget_removed_from_hash (gpointer widget)
996 AnjutaApp *app;
997 GtkWidget *menuitem;
998 GdlDockItem *dockitem;
1000 DEBUG_PRINT ("Removing widget from hash");
1002 app = g_object_get_data (G_OBJECT (widget), "app-object");
1003 dockitem = g_object_get_data (G_OBJECT (widget), "dockitem");
1004 menuitem = g_object_get_data (G_OBJECT (widget), "menuitem");
1006 gtk_widget_destroy (menuitem);
1008 g_object_set_data (G_OBJECT (widget), "dockitem", NULL);
1009 g_object_set_data (G_OBJECT (widget), "menuitem", NULL);
1011 g_signal_handlers_disconnect_by_func (G_OBJECT (widget),
1012 G_CALLBACK (on_widget_destroy), app);
1013 g_signal_handlers_disconnect_by_func (G_OBJECT (dockitem),
1014 G_CALLBACK (on_widget_remove), app);
1016 g_object_unref (G_OBJECT (widget));
1019 static void
1020 anjuta_app_add_widget_full (AnjutaShell *shell,
1021 GtkWidget *widget,
1022 const char *name,
1023 const char *title,
1024 const char *stock_id,
1025 AnjutaShellPlacement placement,
1026 gboolean locked,
1027 GError **error)
1029 AnjutaApp *app;
1030 GtkWidget *item;
1031 GtkCheckMenuItem* menuitem;
1033 g_return_if_fail (ANJUTA_IS_APP (shell));
1034 g_return_if_fail (GTK_IS_WIDGET (widget));
1035 g_return_if_fail (name != NULL);
1036 g_return_if_fail (title != NULL);
1038 app = ANJUTA_APP (shell);
1041 anjuta_shell_add (shell, name, G_TYPE_FROM_INSTANCE (widget),
1042 widget, NULL);
1045 /* Add the widget to hash */
1046 if (app->widgets == NULL)
1048 app->widgets = g_hash_table_new_full (g_str_hash, g_str_equal,
1049 g_free,
1050 on_widget_removed_from_hash);
1052 g_hash_table_insert (app->widgets, g_strdup (name), widget);
1053 g_object_ref (widget);
1055 /* Add the widget to dock */
1056 if (stock_id == NULL)
1057 item = gdl_dock_item_new (name, title, GDL_DOCK_ITEM_BEH_NORMAL);
1058 else
1059 item = gdl_dock_item_new_with_stock (name, title, stock_id,
1060 GDL_DOCK_ITEM_BEH_NORMAL);
1061 if (locked)
1063 guint flags = 0;
1064 flags |= GDL_DOCK_ITEM_BEH_NEVER_FLOATING;
1065 flags |= GDL_DOCK_ITEM_BEH_CANT_CLOSE;
1066 flags |= GDL_DOCK_ITEM_BEH_CANT_ICONIFY;
1067 flags |= GDL_DOCK_ITEM_BEH_NO_GRIP;
1068 g_object_set(G_OBJECT(item), "behavior", flags, NULL);
1071 gtk_container_add (GTK_CONTAINER (item), widget);
1072 gdl_dock_add_item (GDL_DOCK (app->dock),
1073 GDL_DOCK_ITEM (item), placement);
1074 gtk_widget_show_all (item);
1076 /* Add toggle button for the widget */
1077 menuitem = GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title));
1078 gtk_widget_show (GTK_WIDGET (menuitem));
1079 gtk_check_menu_item_set_active (menuitem, TRUE);
1080 gtk_menu_append (GTK_MENU (app->view_menu), GTK_WIDGET (menuitem));
1082 if (locked)
1083 g_object_set( G_OBJECT(menuitem), "visible", FALSE, NULL);
1086 g_object_set_data (G_OBJECT (widget), "app-object", app);
1087 g_object_set_data (G_OBJECT (widget), "menuitem", menuitem);
1088 g_object_set_data (G_OBJECT (widget), "dockitem", item);
1090 /* For toggling widget view on/off */
1091 g_signal_connect (G_OBJECT (menuitem), "toggled",
1092 G_CALLBACK (on_toggle_widget_view), item);
1095 Watch for widget removal/destruction so that it could be
1096 removed from widgets hash.
1098 g_signal_connect (G_OBJECT (item), "remove",
1099 G_CALLBACK (on_widget_remove), app);
1100 g_signal_connect_after (G_OBJECT (widget), "destroy",
1101 G_CALLBACK (on_widget_destroy), app);
1104 static void
1105 anjuta_app_remove_widget (AnjutaShell *shell, GtkWidget *widget,
1106 GError **error)
1108 AnjutaApp *app;
1109 GtkWidget *dock_item;
1111 g_return_if_fail (ANJUTA_IS_APP (shell));
1112 g_return_if_fail (GTK_IS_WIDGET (widget));
1114 app = ANJUTA_APP (shell);
1116 g_return_if_fail (app->widgets != NULL);
1118 dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
1119 g_return_if_fail (dock_item != NULL);
1121 /* Remove the widget from container */
1122 g_object_ref (widget);
1123 /* It should call on_widget_remove() and clean up should happen */
1124 gtk_container_remove (GTK_CONTAINER (dock_item), widget);
1125 g_object_unref (widget);
1128 static void
1129 anjuta_app_present_widget (AnjutaShell *shell, GtkWidget *widget,
1130 GError **error)
1132 AnjutaApp *app;
1133 GdlDockItem *dock_item;
1134 GtkWidget *parent;
1136 g_return_if_fail (ANJUTA_IS_APP (shell));
1137 g_return_if_fail (GTK_IS_WIDGET (widget));
1139 app = ANJUTA_APP (shell);
1141 g_return_if_fail (app->widgets != NULL);
1143 dock_item = g_object_get_data (G_OBJECT(widget), "dockitem");
1144 g_return_if_fail (dock_item != NULL);
1146 /* Hack to present the dock item if it's in a notebook dock item */
1147 parent = gtk_widget_get_parent (GTK_WIDGET(dock_item) );
1148 if (GTK_IS_NOTEBOOK (parent))
1150 gint pagenum;
1151 pagenum = gtk_notebook_page_num (GTK_NOTEBOOK (parent), GTK_WIDGET (dock_item));
1152 gtk_notebook_set_current_page (GTK_NOTEBOOK (parent), pagenum);
1154 else if (!GDL_DOCK_OBJECT_ATTACHED (dock_item))
1156 gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item));
1159 /* FIXME: If the item is floating, present the window */
1160 /* FIXME: There is no way to detect if a widget was floating before it was
1161 detached since it no longer has a parent there is no way to access the
1162 floating property of the GdlDock structure.*/
1165 static GObject*
1166 anjuta_app_get_object (AnjutaShell *shell, const char *iface_name,
1167 GError **error)
1169 g_return_val_if_fail (ANJUTA_IS_APP (shell), NULL);
1170 g_return_val_if_fail (iface_name != NULL, NULL);
1171 return anjuta_plugin_manager_get_plugin (ANJUTA_APP (shell)->plugin_manager,
1172 iface_name);
1175 static AnjutaStatus*
1176 anjuta_app_get_status (AnjutaShell *shell, GError **error)
1178 g_return_val_if_fail (ANJUTA_IS_APP (shell), NULL);
1179 return ANJUTA_APP (shell)->status;
1182 static AnjutaUI *
1183 anjuta_app_get_ui (AnjutaShell *shell, GError **error)
1185 g_return_val_if_fail (ANJUTA_IS_APP (shell), NULL);
1186 return ANJUTA_APP (shell)->ui;
1189 static AnjutaPreferences *
1190 anjuta_app_get_preferences (AnjutaShell *shell, GError **error)
1192 g_return_val_if_fail (ANJUTA_IS_APP (shell), NULL);
1193 return ANJUTA_APP (shell)->preferences;
1196 static AnjutaPluginManager *
1197 anjuta_app_get_plugin_manager (AnjutaShell *shell, GError **error)
1199 g_return_val_if_fail (ANJUTA_IS_APP (shell), NULL);
1200 return ANJUTA_APP (shell)->plugin_manager;
1203 static AnjutaProfileManager *
1204 anjuta_app_get_profile_manager (AnjutaShell *shell, GError **error)
1206 g_return_val_if_fail (ANJUTA_IS_APP (shell), NULL);
1207 return ANJUTA_APP (shell)->profile_manager;
1210 static void
1211 anjuta_shell_iface_init (AnjutaShellIface *iface)
1213 iface->add_widget_full = anjuta_app_add_widget_full;
1214 iface->remove_widget = anjuta_app_remove_widget;
1215 iface->present_widget = anjuta_app_present_widget;
1216 iface->add_value = anjuta_app_add_value;
1217 iface->get_value = anjuta_app_get_value;
1218 iface->remove_value = anjuta_app_remove_value;
1219 iface->get_object = anjuta_app_get_object;
1220 iface->get_status = anjuta_app_get_status;
1221 iface->get_ui = anjuta_app_get_ui;
1222 iface->get_preferences = anjuta_app_get_preferences;
1223 iface->get_plugin_manager = anjuta_app_get_plugin_manager;
1224 iface->get_profile_manager = anjuta_app_get_profile_manager;
1227 ANJUTA_TYPE_BEGIN(AnjutaApp, anjuta_app, GNOME_TYPE_APP);
1228 ANJUTA_TYPE_ADD_INTERFACE(anjuta_shell, ANJUTA_TYPE_SHELL);
1229 ANJUTA_TYPE_END;