1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * anjuta-window.c
4  * Copyright (C) 2003 Naba Kumar  <naba@gnome.org>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * for more details.
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc., 59
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23 
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <sys/wait.h>
30 
31 #include <gtk/gtk.h>
32 
33 #include <gdl/gdl.h>
34 
35 #include <gtksourceview/gtksourceview.h>
36 
37 #include <libanjuta/anjuta-shell.h>
38 #include <libanjuta/anjuta-ui.h>
39 #include <libanjuta/anjuta-utils.h>
40 #include <libanjuta/resources.h>
41 #include <libanjuta/anjuta-plugin-manager.h>
42 #include <libanjuta/anjuta-debug.h>
43 
44 #include "anjuta-window.h"
45 #include "anjuta-actions.h"
46 #include "anjuta-application.h"
47 #include "about.h"
48 
49 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta.xml"
50 #define GLADE_FILE PACKAGE_DATA_DIR"/glade/preferences.ui"
51 #define ICON_FILE "anjuta-preferences-general-48.png"
52 
53 #define PREF_SCHEMA "org.gnome.anjuta"
54 #define GDL_STYLE "gdl-style"
55 #define TOOLBAR_VISIBLE "toolbar-visible"
56 #define TOOLBAR_STYLE "toolbar-style"
57 
58 #define WIDTH_MARGIN 48
59 #define HEIGHT_MARGIN 24
60 #define DEFAULT_WIDTH (1024 - WIDTH_MARGIN)
61 #define DEFAULT_HEIGHT (768 - HEIGHT_MARGIN)
62 
63 static void anjuta_window_layout_load (AnjutaWindow *win,
64 									const gchar *layout_filename,
65 									const gchar *name);
66 static void anjuta_window_layout_save (AnjutaWindow *win,
67 									const gchar *layout_filename,
68 									const gchar *name);
69 
70 static gpointer parent_class = NULL;
71 static GtkToolbarStyle style = -1;
72 
73 static void
menu_item_select_cb(GtkMenuItem * proxy,AnjutaWindow * win)74 menu_item_select_cb (GtkMenuItem *proxy,
75                      AnjutaWindow *win)
76 {
77 	GtkAction *action;
78 	char *message;
79 
80 	action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
81 	g_return_if_fail (action != NULL);
82 
83 	g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
84 	if (message)
85 	{
86 		anjuta_status_push (win->status, "%s", message);
87 		g_free (message);
88 	}
89 }
90 
91 static void
menu_item_deselect_cb(GtkMenuItem * proxy,AnjutaWindow * win)92 menu_item_deselect_cb (GtkMenuItem *proxy,
93                        AnjutaWindow *win)
94 {
95 	anjuta_status_pop (win->status);
96 }
97 
98 
99 static void
connect_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,AnjutaWindow * win)100 connect_proxy_cb (GtkUIManager *manager,
101                   GtkAction *action,
102                   GtkWidget *proxy,
103                   AnjutaWindow *win)
104 {
105 	if (GTK_IS_MENU_ITEM (proxy))
106 	{
107 		g_signal_connect (proxy, "select",
108 				  G_CALLBACK (menu_item_select_cb), win);
109 		g_signal_connect (proxy, "deselect",
110 				  G_CALLBACK (menu_item_deselect_cb), win);
111 	}
112 }
113 
114 static void
disconnect_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,AnjutaWindow * win)115 disconnect_proxy_cb (GtkUIManager *manager,
116                      GtkAction *action,
117                      GtkWidget *proxy,
118 	                 AnjutaWindow *win)
119 {
120 	if (GTK_IS_MENU_ITEM (proxy))
121 	{
122 		g_signal_handlers_disconnect_by_func
123 			(proxy, G_CALLBACK (menu_item_select_cb), win);
124 		g_signal_handlers_disconnect_by_func
125 			(proxy, G_CALLBACK (menu_item_deselect_cb), win);
126 	}
127 }
128 
129 static void
anjuta_window_iconify_dockable_widget(AnjutaShell * shell,GtkWidget * widget,GError ** error)130 anjuta_window_iconify_dockable_widget (AnjutaShell *shell, GtkWidget *widget,
131                                     GError **error)
132 {
133 	AnjutaWindow *win = NULL;
134 	GtkWidget *dock_item = NULL;
135 
136 	/* Argumments assertions */
137 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
138 	g_return_if_fail (GTK_IS_WIDGET (widget));
139 
140 	win = ANJUTA_WINDOW (shell);
141 	g_return_if_fail (win->widgets != NULL);
142 
143 	dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
144 	g_return_if_fail (dock_item != NULL);
145 
146 	/* Iconify the dockable item */
147 	gdl_dock_item_iconify_item (GDL_DOCK_ITEM (dock_item));
148 }
149 
150 static void
anjuta_window_hide_dockable_widget(AnjutaShell * shell,GtkWidget * widget,GError ** error)151 anjuta_window_hide_dockable_widget (AnjutaShell *shell, GtkWidget *widget,
152                                  GError **error)
153 {
154 	AnjutaWindow *win = NULL;
155 	GtkWidget *dock_item = NULL;
156 
157 	/* Argumments assertions */
158 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
159 	g_return_if_fail (GTK_IS_WIDGET (widget));
160 
161 	win = ANJUTA_WINDOW (shell);
162 	g_return_if_fail (win->widgets != NULL);
163 
164 	dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
165 	g_return_if_fail (dock_item != NULL);
166 
167 	/* Hide the dockable item */
168 	gdl_dock_item_hide_item (GDL_DOCK_ITEM (dock_item));
169 }
170 
171 static void
anjuta_window_show_dockable_widget(AnjutaShell * shell,GtkWidget * widget,GError ** error)172 anjuta_window_show_dockable_widget (AnjutaShell *shell, GtkWidget* widget,
173                                  GError **error)
174 {
175 	AnjutaWindow *win = NULL;
176 	GtkWidget *dock_item = NULL;
177 
178 	/* Argumments assertions */
179 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
180 	g_return_if_fail (GTK_IS_WIDGET (widget));
181 
182 	win = ANJUTA_WINDOW (shell);
183 	g_return_if_fail (win->widgets != NULL);
184 
185 	dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
186 	g_return_if_fail (dock_item != NULL);
187 
188 	/* Show the dockable item */
189 	gdl_dock_item_show_item(GDL_DOCK_ITEM (dock_item));
190 }
191 
192 static void
anjuta_window_maximize_widget(AnjutaShell * shell,const char * widget_name,GError ** error)193 anjuta_window_maximize_widget (AnjutaShell *shell,
194                             const char  *widget_name,
195                             GError **error)
196 {
197 	AnjutaWindow *win = NULL;
198 	GtkWidget *dock_item = NULL;
199 	gpointer  value, key;
200 	GtkWidget *widget = NULL;
201 	GHashTableIter iter;
202 
203 	/* AnjutaWindow assertions */
204 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
205 	win = ANJUTA_WINDOW (shell);
206 
207 	/* If win->maximized is TRUE then another widget is already maximized.
208 	   Restoring the UI for a new maximization. */
209 	if(win->maximized)
210 		gdl_dock_layout_load_layout (win->layout_manager, "back-up");
211 
212 	/* Back-up the layout so it can be restored */
213 	gdl_dock_layout_save_layout(win->layout_manager, "back-up");
214 
215 	/* Mark the win as maximized (the other widgets except center are hidden) */
216 	win->maximized = TRUE;
217 
218 	/* Hide all DockItem's except the ones positioned in the center */
219 	g_hash_table_iter_init (&iter, win->widgets);
220 	while (g_hash_table_iter_next (&iter, &key, &value))
221 	{
222 		if (value == NULL)
223 			continue;
224 
225 		/* Widget assertions */
226 		widget = GTK_WIDGET (value);
227 		if(!GTK_IS_WIDGET (widget))
228 			continue;
229 
230 		/* DockItem assertions */
231 		dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
232 		if(dock_item == NULL || !GDL_IS_DOCK_ITEM (dock_item))
233 			continue;
234 
235 		if(!g_strcmp0((gchar*)key, widget_name))
236 		{
237 			/* If it's the widget requesting maximization then make sure the
238 			 * widget is visible*/
239 			gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item));
240 		}
241 		else
242 		{
243 			/* Hide the other item */
244 			gdl_dock_item_hide_item (GDL_DOCK_ITEM (dock_item));
245 		}
246 	}
247 }
248 
249 static void
anjuta_window_unmaximize(AnjutaShell * shell,GError ** error)250 anjuta_window_unmaximize (AnjutaShell *shell,
251                        GError **error)
252 {
253 	AnjutaWindow *win = NULL;
254 
255 	/* AnjutaWindow assertions */
256 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
257 	win = ANJUTA_WINDOW (shell);
258 
259 	/* If not maximized then the operation doesn't make sence. */
260 	g_return_if_fail (win->maximized);
261 
262 	/* Load the backed-up layout */
263 	gdl_dock_layout_load_layout (win->layout_manager, "back-up");
264 	gdl_dock_layout_delete_layout (win->layout_manager, "back-up");
265 
266 	/* Un-mark maximized */
267 	win->maximized = FALSE;
268 }
269 
270 static AnjutaShell *
anjuta_window_create_window(AnjutaShell * shell,GError ** error)271 anjuta_window_create_window (AnjutaShell *shell,
272                           GError **error)
273 {
274 	AnjutaWindow *win = NULL;
275 	AnjutaApplication *app;
276 
277 	/* AnjutaWindow assertions */
278 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
279 
280 	app = ANJUTA_APPLICATION (gtk_window_get_application (GTK_WINDOW (shell)));
281 	win = anjuta_application_create_window (ANJUTA_APPLICATION (app));
282 
283 	return ANJUTA_SHELL (win);
284 }
285 
286 static void
on_toolbar_style_changed(GSettings * settings,const gchar * key,gpointer user_data)287 on_toolbar_style_changed (GSettings* settings,
288                           const gchar* key,
289                           gpointer user_data)
290 {
291 	AnjutaWindow* win = ANJUTA_WINDOW (user_data);
292 	gchar* tb_style = g_settings_get_string (settings, key);
293 
294 	if (strcasecmp (tb_style, "Default") == 0)
295 		style = -1;
296 	else if (strcasecmp (tb_style, "Both") == 0)
297 		style = GTK_TOOLBAR_BOTH;
298 	else if (strcasecmp (tb_style, "Horiz") == 0)
299 		style = GTK_TOOLBAR_BOTH_HORIZ;
300 	else if (strcasecmp (tb_style, "Icons") == 0)
301 		style = GTK_TOOLBAR_ICONS;
302 	else if (strcasecmp (tb_style, "Text") == 0)
303 		style = GTK_TOOLBAR_TEXT;
304 
305 	if (style != -1)
306 	{
307 		gtk_toolbar_set_style (GTK_TOOLBAR (win->toolbar), style);
308 	}
309 	else
310 	{
311 		gtk_toolbar_unset_style (GTK_TOOLBAR (win->toolbar));
312 	}
313 	g_free (tb_style);
314 }
315 
316 static void
on_gdl_style_changed(GSettings * settings,const gchar * key,gpointer user_data)317 on_gdl_style_changed (GSettings* settings,
318                       const gchar* key,
319                       gpointer user_data)
320 {
321 	AnjutaWindow* win = ANJUTA_WINDOW (user_data);
322 	GdlSwitcherStyle style = GDL_SWITCHER_STYLE_BOTH;
323 
324 	gchar* pr_style = g_settings_get_string (settings, key);
325 
326 	if (strcasecmp (pr_style, "Text") == 0)
327 		style = GDL_SWITCHER_STYLE_TEXT;
328 	else if (strcasecmp (pr_style, "Icon") == 0)
329 		style = GDL_SWITCHER_STYLE_ICON;
330 	else if (strcasecmp (pr_style, "Both") == 0)
331 		style = GDL_SWITCHER_STYLE_BOTH;
332 	else if (strcasecmp (pr_style, "Toolbar") == 0)
333 		style = GDL_SWITCHER_STYLE_TOOLBAR;
334 	else if (strcasecmp (pr_style, "Tabs") == 0)
335 		style = GDL_SWITCHER_STYLE_TABS;
336 
337 	g_object_set (gdl_dock_layout_get_master (win->layout_manager), "switcher-style",
338 				  style, NULL);
339 	g_free (pr_style);
340 }
341 
342 static void
on_toggle_widget_view(GtkCheckMenuItem * menuitem,GtkWidget * dockitem)343 on_toggle_widget_view (GtkCheckMenuItem *menuitem, GtkWidget *dockitem)
344 {
345 	gboolean state;
346 	state = gtk_check_menu_item_get_active (menuitem);
347 	if (state)
348 		gdl_dock_item_show_item (GDL_DOCK_ITEM (dockitem));
349 	else
350 		gdl_dock_item_hide_item (GDL_DOCK_ITEM (dockitem));
351 }
352 
353 static void
on_update_widget_view_menuitem(gpointer key,gpointer wid,gpointer data)354 on_update_widget_view_menuitem (gpointer key, gpointer wid, gpointer data)
355 {
356 	GtkCheckMenuItem *menuitem;
357 	GdlDockItem *dockitem;
358 
359 	dockitem = g_object_get_data (G_OBJECT (wid), "dockitem");
360 	menuitem = g_object_get_data (G_OBJECT (wid), "menuitem");
361 
362 	g_signal_handlers_block_by_func (menuitem,
363 									 G_CALLBACK (on_toggle_widget_view),
364 									 dockitem);
365 
366 	if (GDL_DOCK_OBJECT_ATTACHED (dockitem))
367 		gtk_check_menu_item_set_active (menuitem, TRUE);
368 	else
369 		gtk_check_menu_item_set_active (menuitem, FALSE);
370 
371 	g_signal_handlers_unblock_by_func (menuitem,
372 									   G_CALLBACK (on_toggle_widget_view),
373 									   dockitem);
374 }
375 
376 static void
on_layout_dirty_notify(GObject * object,GParamSpec * pspec,gpointer user_data)377 on_layout_dirty_notify (GObject *object, GParamSpec *pspec, gpointer user_data)
378 {
379 	if (!strcmp (pspec->name, "dirty")) {
380 		gboolean dirty;
381 		g_object_get (object, "dirty", &dirty, NULL);
382 		if (dirty) {
383 			/* Update UI toggle buttons */
384 			g_hash_table_foreach (ANJUTA_WINDOW (user_data)->widgets,
385 								  on_update_widget_view_menuitem,
386 								  NULL);
387 		}
388 	}
389 }
390 
391 static void
on_layout_locked_notify(GdlDockMaster * master,GParamSpec * pspec,AnjutaWindow * win)392 on_layout_locked_notify (GdlDockMaster *master, GParamSpec *pspec,
393 						 AnjutaWindow     *win)
394 {
395 	AnjutaUI *ui;
396 	GtkAction *action;
397 	gint locked;
398 
399 	ui = win->ui;
400 	action = anjuta_ui_get_action (ui, "ActionGroupToggleView",
401 								   "ActionViewLockLayout");
402 
403 	g_object_get (master, "locked", &locked, NULL);
404 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
405 								  (locked == 1));
406 }
407 
408 static void
on_session_save(AnjutaShell * shell,AnjutaSessionPhase phase,AnjutaSession * session,AnjutaWindow * win)409 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
410 				 AnjutaSession *session, AnjutaWindow *win)
411 {
412 	gchar *geometry, *layout_file;
413 	GdkWindowState state;
414 
415 	if (phase != ANJUTA_SESSION_PHASE_NORMAL)
416 		return;
417 
418 	/* Save geometry */
419 	state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (win)));
420 	if (state & GDK_WINDOW_STATE_MAXIMIZED) {
421 		anjuta_session_set_int (session, "Anjuta", "Maximized", 1);
422 	}
423 	if (state & GDK_WINDOW_STATE_FULLSCREEN) {
424 		anjuta_session_set_int (session, "Anjuta", "Fullscreen", 1);
425 	}
426 
427 	/* Save geometry only if window is not maximized or fullscreened */
428 	if (!(state & GDK_WINDOW_STATE_MAXIMIZED) ||
429 		!(state & GDK_WINDOW_STATE_FULLSCREEN))
430 	{
431 		geometry = anjuta_window_get_geometry (win);
432 		if (geometry)
433 			anjuta_session_set_string (session, "Anjuta", "Geometry",
434 									   geometry);
435 		g_free (geometry);
436 	}
437 
438 	/* Save layout */
439 	layout_file = g_build_filename (anjuta_session_get_session_directory (session),
440 									"dock-layout.xml", NULL);
441 	anjuta_window_layout_save (win, layout_file, NULL);
442 	g_free (layout_file);
443 }
444 
445 static void
on_session_load(AnjutaShell * shell,AnjutaSessionPhase phase,AnjutaSession * session,AnjutaWindow * win)446 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
447 				 AnjutaSession *session, AnjutaWindow *win)
448 {
449 	if (phase == ANJUTA_SESSION_PHASE_START)
450 	{
451 		AnjutaApplication *app;
452 
453 		app = ANJUTA_APPLICATION (gtk_window_get_application (GTK_WINDOW (win)));
454 		if (app != NULL)
455 		{
456 			if (anjuta_application_get_no_session (app))
457 			{
458 				/* Clear session */
459 				anjuta_session_clear (session);
460 			}
461 			else if (anjuta_application_get_no_files (app))
462 			{
463 				/* Clear files from session */
464 				anjuta_session_set_string_list (session, "File Loader",
465 				                                "Files", NULL);
466 			}
467 			if (anjuta_application_get_geometry (app))
468 			{
469 				/* Set new geometry */
470 				anjuta_session_set_string (session, "Anjuta", "Geometry",
471 				                           anjuta_application_get_geometry (app));
472 			}
473 		}
474 	}
475 
476 	/* We load layout at last so that all plugins would have loaded by now */
477 	if (phase == ANJUTA_SESSION_PHASE_LAST)
478 	{
479 		gchar *geometry;
480 		gchar *layout_file;
481 
482 		/* Restore geometry */
483 		geometry = anjuta_session_get_string (session, "Anjuta", "Geometry");
484 		anjuta_window_set_geometry (win, geometry);
485 		g_free (geometry);
486 
487 		/* Restore window state */
488 		if (anjuta_session_get_int (session, "Anjuta", "Fullscreen"))
489 		{
490 			/* bug #304495 */
491 			AnjutaUI* ui = anjuta_shell_get_ui(shell, NULL);
492 			GtkAction* action = anjuta_ui_get_action (ui, "ActionGroupToggleView",
493 								   "ActionViewFullscreen");
494 			gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
495 								  TRUE);
496 
497 			gtk_window_fullscreen (GTK_WINDOW (shell));
498 
499 		}
500 		else if (anjuta_session_get_int (session, "Anjuta", "Maximized"))
501 		{
502 			gtk_window_maximize (GTK_WINDOW (shell));
503 		}
504 		else
505 		{
506 			gtk_window_unmaximize (GTK_WINDOW (shell));
507 		}
508 		gtk_widget_show (GTK_WIDGET (win));
509 
510 		/* Restore layout */
511 		layout_file = g_build_filename (anjuta_session_get_session_directory (session),
512 										"dock-layout.xml", NULL);
513 		anjuta_window_layout_load (win, layout_file, NULL);
514 		g_free (layout_file);
515 	}
516 }
517 
518 static void
anjuta_window_dispose(GObject * widget)519 anjuta_window_dispose (GObject *widget)
520 {
521 	AnjutaWindow *win;
522 
523 	g_return_if_fail (ANJUTA_IS_WINDOW (widget));
524 
525 	win = ANJUTA_WINDOW (widget);
526 
527 	if (win->widgets)
528 	{
529 		if (g_hash_table_size (win->widgets) > 0)
530 		{
531 			/*
532 			g_warning ("Some widgets are still inside shell (%d widgets), they are:",
533 					   g_hash_table_size (win->widgets));
534 			g_hash_table_foreach (win->widgets, (GHFunc)puts, NULL);
535 			*/
536 		}
537 		g_hash_table_destroy (win->widgets);
538 		win->widgets = NULL;
539 	}
540 
541 	if (win->values)
542 	{
543 		if (g_hash_table_size (win->values) > 0)
544 		{
545 			/*
546 			g_warning ("Some Values are still left in shell (%d Values), they are:",
547 					   g_hash_table_size (win->values));
548 			g_hash_table_foreach (win->values, (GHFunc)puts, NULL);
549 			*/
550 		}
551 		g_hash_table_destroy (win->values);
552 		win->values = NULL;
553 	}
554 	if (win->ui) {
555 		g_object_unref (win->ui);
556 		win->ui = NULL;
557 	}
558 	if (win->preferences)
559 	{
560 		g_object_unref (win->preferences);
561 		win->preferences = NULL;
562 	}
563 	if (win->layout_manager) {
564 		/* Disconnect signal handlers so we don't get any signals after we're
565 		 * disposed. */
566 		g_signal_handlers_disconnect_by_func (win->layout_manager, on_layout_dirty_notify,
567 		                                      win);
568 		g_signal_handlers_disconnect_by_func (gdl_dock_layout_get_master (win->layout_manager),
569 		                                      on_layout_locked_notify, win);
570 		g_object_unref (win->layout_manager);
571 		win->layout_manager = NULL;
572 	}
573 	if (win->profile_manager) {
574 		g_object_unref (G_OBJECT (win->profile_manager));
575 		win->profile_manager = NULL;
576 	}
577 	if (win->plugin_manager) {
578 		g_object_unref (G_OBJECT (win->plugin_manager));
579 		win->plugin_manager = NULL;
580 	}
581 	if (win->status) {
582 		g_object_unref (G_OBJECT (win->status));
583 		win->status = NULL;
584 	}
585 
586 	if (win->settings) {
587 		g_object_unref (win->settings);
588 		win->settings = NULL;
589 	}
590 
591 	G_OBJECT_CLASS (parent_class)->dispose (widget);
592 }
593 
594 static void
anjuta_window_instance_init(AnjutaWindow * win)595 anjuta_window_instance_init (AnjutaWindow *win)
596 {
597 	GtkWidget *menubar, *about_menu;
598 	GtkWidget *view_menu, *hbox;
599 	GtkWidget *main_box;
600 	GtkWidget *dockbar;
601 	GtkAction* action;
602 	GList *plugins_dirs = NULL;
603 	GdkGeometry size_hints = {
604     	100, 100, 0, 0, 100, 100, 1, 1, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
605   	};
606 
607 	DEBUG_PRINT ("%s", "Initializing Anjuta...");
608 
609 	gtk_window_set_geometry_hints (GTK_WINDOW (win), GTK_WIDGET (win),
610 								   &size_hints, GDK_HINT_RESIZE_INC);
611 	gtk_window_set_resizable (GTK_WINDOW (win), TRUE);
612 
613 	/*
614 	 * Main box
615 	 */
616 	main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
617 	gtk_container_add (GTK_CONTAINER (win), main_box);
618 	gtk_widget_show (main_box);
619 
620 	win->values = NULL;
621 	win->widgets = NULL;
622 	win->maximized = FALSE;
623 
624 	/* Settings */
625 	win->settings = g_settings_new (PREF_SCHEMA);
626 
627 	/* Status bar */
628 	win->status = ANJUTA_STATUS (anjuta_status_new ());
629 	anjuta_status_set_title_window (win->status, GTK_WIDGET (win));
630 	gtk_widget_show (GTK_WIDGET (win->status));
631 	gtk_box_pack_end (GTK_BOX (main_box),
632 					  GTK_WIDGET (win->status), FALSE, TRUE, 0);
633 	g_object_ref (G_OBJECT (win->status));
634 	g_object_add_weak_pointer (G_OBJECT (win->status), (gpointer)&win->status);
635 
636 	/* configure dock */
637 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
638 	gtk_widget_show (hbox);
639 	win->dock = gdl_dock_new ();
640 	gtk_widget_show (win->dock);
641 	gtk_box_pack_end(GTK_BOX (hbox), win->dock, TRUE, TRUE, 0);
642 
643 	dockbar = gdl_dock_bar_new (G_OBJECT (win->dock));
644 	gtk_widget_show (dockbar);
645 	gtk_box_pack_start(GTK_BOX (hbox), dockbar, FALSE, FALSE, 0);
646 
647 	win->layout_manager = gdl_dock_layout_new (G_OBJECT (win->dock));
648 	g_signal_connect (win->layout_manager, "notify::dirty",
649 					  G_CALLBACK (on_layout_dirty_notify), win);
650 	g_signal_connect (gdl_dock_layout_get_master (win->layout_manager), "notify::locked",
651 					  G_CALLBACK (on_layout_locked_notify), win);
652 
653 	/* UI engine */
654 	win->ui = anjuta_ui_new ();
655 	g_object_add_weak_pointer (G_OBJECT (win->ui), (gpointer)&win->ui);
656 	/* show tooltips in the statusbar */
657 	g_signal_connect (win->ui,
658 			  "connect_proxy",
659 			  G_CALLBACK (connect_proxy_cb),
660 			  win);
661 	g_signal_connect (win->ui,
662 			  "disconnect_proxy",
663 			  G_CALLBACK (disconnect_proxy_cb),
664 			  win);
665 
666 	/* Plugin Manager */
667 	plugins_dirs = g_list_prepend (plugins_dirs, PACKAGE_PLUGIN_DIR);
668 	win->plugin_manager = anjuta_plugin_manager_new (G_OBJECT (win),
669 													 win->status,
670 													 plugins_dirs);
671 	win->profile_manager = anjuta_profile_manager_new (win->plugin_manager);
672 	g_list_free (plugins_dirs);
673 
674 	/* Preferences */
675 	win->preferences = anjuta_preferences_new (win->plugin_manager, PREF_SCHEMA);
676 	g_object_add_weak_pointer (G_OBJECT (win->preferences),
677 							   (gpointer)&win->preferences);
678 
679 	g_signal_connect (win->settings, "changed::" GDL_STYLE,
680 	                  G_CALLBACK (on_gdl_style_changed), win);
681 	on_gdl_style_changed (win->settings, GDL_STYLE, win);
682 
683 	/* Register actions */
684 	anjuta_ui_add_action_group_entries (win->ui, "ActionGroupFile", _("File"),
685 										menu_entries_file,
686 										G_N_ELEMENTS (menu_entries_file),
687 										GETTEXT_PACKAGE, TRUE, win);
688 	anjuta_ui_add_action_group_entries (win->ui, "ActionGroupEdit", _("Edit"),
689 										menu_entries_edit,
690 										G_N_ELEMENTS (menu_entries_edit),
691 										GETTEXT_PACKAGE, TRUE, win);
692 	anjuta_ui_add_action_group_entries (win->ui, "ActionGroupView", _("View"),
693 										menu_entries_view,
694 										G_N_ELEMENTS (menu_entries_view),
695 										GETTEXT_PACKAGE, TRUE, win);
696 	anjuta_ui_add_toggle_action_group_entries (win->ui, "ActionGroupToggleView",
697 										_("View"),
698 										menu_entries_toggle_view,
699 										G_N_ELEMENTS (menu_entries_toggle_view),
700 										GETTEXT_PACKAGE, TRUE, win);
701 	anjuta_ui_add_action_group_entries (win->ui, "ActionGroupHelp", _("Help"),
702 										menu_entries_help,
703 										G_N_ELEMENTS (menu_entries_help),
704 										GETTEXT_PACKAGE, TRUE, win);
705 
706 	/* Merge UI */
707 	anjuta_ui_merge (win->ui, UI_FILE);
708 
709 	/* Adding accels group */
710 	gtk_window_add_accel_group (GTK_WINDOW (win),
711 								gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (win->ui)));
712 
713 	/* create main menu */
714 	menubar = gtk_ui_manager_get_widget (GTK_UI_MANAGER (win->ui),
715 										 "/MenuMain");
716 	gtk_box_pack_start (GTK_BOX (main_box), menubar, FALSE, FALSE, 0);
717 	gtk_widget_show (menubar);
718 
719 	/* create toolbar */
720 	win->toolbar = gtk_ui_manager_get_widget (GTK_UI_MANAGER (win->ui),
721 										 "/ToolbarMain");
722     if (!g_settings_get_boolean (win->settings, TOOLBAR_VISIBLE))
723 		gtk_widget_hide (win->toolbar);
724 	gtk_style_context_add_class (gtk_widget_get_style_context (win->toolbar),
725 	                             GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
726 	gtk_toolbar_set_icon_size (GTK_TOOLBAR (win->toolbar),
727 	                           GTK_ICON_SIZE_MENU);
728 	gtk_box_pack_start (GTK_BOX (main_box), win->toolbar, FALSE, FALSE, 0);
729 	action = gtk_ui_manager_get_action (GTK_UI_MANAGER (win->ui),
730 										"/MenuMain/MenuView/Toolbar");
731 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action),
732 								  g_settings_get_boolean (win->settings,
733 								                          TOOLBAR_VISIBLE));
734 	g_signal_connect (win->settings, "changed::" TOOLBAR_STYLE,
735 	                  G_CALLBACK (on_toolbar_style_changed), win);
736 	on_toolbar_style_changed (win->settings, TOOLBAR_STYLE, win);
737 
738 	/* Create widgets menu */
739 	view_menu =
740 		gtk_ui_manager_get_widget (GTK_UI_MANAGER(win->ui),
741 								  "/MenuMain/MenuView");
742 	win->view_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (view_menu));
743 
744 	/* Create about plugins menu */
745 	about_menu =
746 		gtk_ui_manager_get_widget (GTK_UI_MANAGER(win->ui),
747 								   "/MenuMain/PlaceHolderHelpMenus/MenuHelp/"
748 								   "PlaceHolderHelpAbout/AboutPlugins");
749 	about_create_plugins_submenu (ANJUTA_SHELL (win), about_menu);
750 
751 	/* Add main view */
752 	gtk_box_pack_start (GTK_BOX (main_box), hbox, TRUE, TRUE, 0);
753 
754 	/* Connect to session */
755 	g_signal_connect (G_OBJECT (win), "save_session",
756 					  G_CALLBACK (on_session_save), win);
757 	g_signal_connect (G_OBJECT (win), "load_session",
758 					  G_CALLBACK (on_session_load), win);
759 
760 	/* Loading accels */
761 	anjuta_ui_load_accels (NULL);
762 
763 	win->save_count = 0;
764 }
765 
766 /*
767  * GtkWindow catches keybindings for the menu items _before_ passing them to
768  * the focused widget. This is unfortunate and means that pressing ctrl+V
769  * in an entry on a panel ends up pasting text in the TextView.
770  * Here we override GtkWindow's handler to do the same things that it
771  * does, but in the opposite order and then we chain up to the grand
772  * parent handler, skipping gtk_window_key_press_event.
773  */
774 static gboolean
anjuta_window_key_press_event(GtkWidget * widget,GdkEventKey * event)775 anjuta_window_key_press_event (GtkWidget   *widget,
776                             GdkEventKey *event)
777 {
778 	static gpointer grand_parent_class = NULL;
779 	GtkWindow *window = GTK_WINDOW (widget);
780 	GtkWidget *focus = gtk_window_get_focus (window);
781 	gboolean handled = FALSE;
782 
783 	if (grand_parent_class == NULL)
784 		grand_parent_class = g_type_class_peek_parent (parent_class);
785 
786 	/* Special case the editor - it catches all shortcuts otherwise */
787 	if (GTK_SOURCE_IS_VIEW (focus))
788 		if (gtk_window_activate_key (window, event))
789 			return TRUE;
790 	switch (event->keyval)
791 	{
792 		case GDK_KEY_F1:
793 		case GDK_KEY_F2:
794 		case GDK_KEY_F3:
795 		case GDK_KEY_F4:
796 		case GDK_KEY_F5:
797 		case GDK_KEY_F6:
798 		case GDK_KEY_F7:
799 		case GDK_KEY_F8:
800 		case GDK_KEY_F9:
801 		case GDK_KEY_F10:
802 		case GDK_KEY_F11:
803 		case GDK_KEY_F12:
804 			/* handle mnemonics and accelerators */
805 			if (!handled)
806 				handled = gtk_window_activate_key (window, event);
807 			break;
808 		default:
809 			/* handle focus widget key events */
810 			if (!handled)
811 				handled = gtk_window_propagate_key_event (window, event);
812 	}
813 
814 	/* handle mnemonics and accelerators */
815 	if (!handled)
816 		handled = gtk_window_activate_key (window, event);
817 
818 	/* Chain up, invokes binding set */
819 	if (!handled)
820 		handled = GTK_WIDGET_CLASS (grand_parent_class)->key_press_event (widget, event);
821 
822 	return handled;
823 }
824 
825 static void
anjuta_window_class_init(AnjutaWindowClass * class)826 anjuta_window_class_init (AnjutaWindowClass *class)
827 {
828 	GObjectClass *object_class;
829 	GtkWidgetClass *widget_class;
830 
831 	parent_class = g_type_class_peek_parent (class);
832 	object_class = (GObjectClass*) class;
833 	widget_class = (GtkWidgetClass*) class;
834 
835 	object_class->dispose = anjuta_window_dispose;
836 
837 	widget_class->key_press_event = anjuta_window_key_press_event;
838 }
839 
840 GtkWidget *
anjuta_window_new(GtkApplication * app)841 anjuta_window_new (GtkApplication* app)
842 {
843 	AnjutaWindow *win;
844 
845 	win = ANJUTA_WINDOW (g_object_new (ANJUTA_TYPE_WINDOW,
846 	                                   "title", "Anjuta",
847 	                                   "application", app,
848 	                                   NULL));
849 	return GTK_WIDGET (win);
850 }
851 
852 gchar*
anjuta_window_get_geometry(AnjutaWindow * win)853 anjuta_window_get_geometry (AnjutaWindow *win)
854 {
855 	gchar *geometry;
856 	gint width, height, posx, posy;
857 
858 	g_return_val_if_fail (ANJUTA_IS_WINDOW (win), NULL);
859 
860 	geometry = NULL;
861 	width = height = posx = posy = 0;
862 	if (gtk_widget_get_window (GTK_WIDGET (win)))
863 	{
864 		gtk_window_get_size (GTK_WINDOW (win), &width, &height);
865 		gtk_window_get_position (GTK_WINDOW(win), &posx, &posy);
866 
867 		geometry = g_strdup_printf ("%dx%d+%d+%d", width, height, posx, posy);
868 	}
869 	return geometry;
870 }
871 
872 void
anjuta_window_set_geometry(AnjutaWindow * win,const gchar * geometry)873 anjuta_window_set_geometry (AnjutaWindow *win, const gchar *geometry)
874 {
875 	gint width, height, posx, posy;
876 	gboolean geometry_set = FALSE;
877 
878 	if (geometry && strlen (geometry) > 0)
879 	{
880 		DEBUG_PRINT ("Setting geometry: %s", geometry);
881 
882 		if (sscanf (geometry, "%dx%d+%d+%d", &width, &height,
883 					&posx, &posy) == 4)
884 		{
885 			if (gtk_widget_get_realized (GTK_WIDGET (win)))
886 			{
887 				gtk_window_resize (GTK_WINDOW (win), width, height);
888 			}
889 			else
890 			{
891 				gtk_window_set_default_size (GTK_WINDOW (win), width, height);
892 				gtk_window_move (GTK_WINDOW (win), posx, posy);
893 			}
894 			geometry_set = TRUE;
895 		}
896 		else
897 		{
898 			g_warning ("Failed to parse geometry: %s", geometry);
899 		}
900 	}
901 	if (!geometry_set)
902 	{
903 		posx = 10;
904 		posy = 10;
905 		width = gdk_screen_width () - WIDTH_MARGIN;
906 		height = gdk_screen_height () - HEIGHT_MARGIN;
907 		width = (width < DEFAULT_WIDTH)? width : DEFAULT_WIDTH;
908 		height = (height < DEFAULT_HEIGHT)? width : DEFAULT_HEIGHT;
909 		if (gtk_widget_get_realized (GTK_WIDGET (win)) == FALSE)
910 		{
911 			gtk_window_set_default_size (GTK_WINDOW (win), width, height);
912 			gtk_window_move (GTK_WINDOW (win), posx, posy);
913 		}
914 	}
915 }
916 
917 static void
anjuta_window_layout_save(AnjutaWindow * win,const gchar * filename,const gchar * name)918 anjuta_window_layout_save (AnjutaWindow *win, const gchar *filename,
919 						const gchar *name)
920 {
921 	g_return_if_fail (ANJUTA_IS_WINDOW (win));
922 	g_return_if_fail (filename != NULL);
923 
924 	/* If maximized, the layout should be loaded from the back-up first */
925 	if(win->maximized)
926 		gdl_dock_layout_load_layout (win->layout_manager, "back-up");
927 
928 	/* Continue with the saving */
929 	gdl_dock_layout_save_layout (win->layout_manager, name);
930 	if (!gdl_dock_layout_save_to_file (win->layout_manager, filename))
931 		g_warning ("Saving dock layout to '%s' failed!", filename);
932 
933 	/* This is a good place to save the accels too */
934 	anjuta_ui_save_accels (NULL);
935 }
936 
937 static void
anjuta_window_layout_load(AnjutaWindow * win,const gchar * layout_filename,const gchar * name)938 anjuta_window_layout_load (AnjutaWindow *win, const gchar *layout_filename,
939 						const gchar *name)
940 {
941 	g_return_if_fail (ANJUTA_IS_WINDOW (win));
942 
943 	if (!layout_filename ||
944 		!gdl_dock_layout_load_from_file (win->layout_manager, layout_filename))
945 	{
946 		gchar *datadir, *filename;
947 		datadir = anjuta_res_get_data_dir();
948 
949 		filename = g_build_filename (datadir, "layout.xml", NULL);
950 		DEBUG_PRINT ("Layout = %s", filename);
951 		g_free (datadir);
952 		if (!gdl_dock_layout_load_from_file (win->layout_manager, filename))
953 			g_warning ("Loading layout from '%s' failed!!", filename);
954 		g_free (filename);
955 	}
956 
957 	if (!gdl_dock_layout_load_layout (win->layout_manager, name))
958 		g_warning ("Loading layout failed!!");
959 
960 	/* Layout loaded from file are not maximized */
961 	win->maximized = FALSE;
962 }
963 
964 void
anjuta_window_layout_reset(AnjutaWindow * win)965 anjuta_window_layout_reset (AnjutaWindow *win)
966 {
967 	anjuta_window_layout_load (win, NULL, NULL);
968 }
969 
970 void
anjuta_window_install_preferences(AnjutaWindow * win)971 anjuta_window_install_preferences (AnjutaWindow *win)
972 {
973 	GtkBuilder* builder = gtk_builder_new ();
974 	GError* error = NULL;
975 	GtkWidget *notebook, *shortcuts, *plugins, *remember_plugins;
976 
977 	/* Create preferences page */
978 	gtk_builder_add_from_file (builder, GLADE_FILE, &error);
979 	if (error)
980 	{
981 		g_warning("Could not load general preferences: %s",
982 			  error->message);
983 		g_error_free (error);
984 		return;
985 	}
986 	anjuta_preferences_add_from_builder (win->preferences, builder, win->settings,
987 								 "General", _("General"), ICON_FILE);
988 	notebook = 	GTK_WIDGET (gtk_builder_get_object (builder, "General"));
989 	shortcuts = anjuta_ui_get_accel_editor (ANJUTA_UI (win->ui));
990 	plugins = anjuta_plugin_manager_get_plugins_page (win->plugin_manager);
991 	remember_plugins = anjuta_plugin_manager_get_remembered_plugins_page (win->plugin_manager);
992 
993 	gtk_widget_show (shortcuts);
994 	gtk_widget_show (plugins);
995 	gtk_widget_show (remember_plugins);
996 
997 	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), plugins,
998 							  gtk_label_new (_("Installed plugins")));
999 	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), remember_plugins,
1000 							  gtk_label_new (_("Preferred plugins")));
1001 	gtk_notebook_append_page (GTK_NOTEBOOK (notebook), shortcuts,
1002 							  gtk_label_new (_("Shortcuts")));
1003 
1004 	g_object_unref (builder);
1005 }
1006 
1007 /* AnjutaShell Implementation */
1008 
1009 static void
on_value_removed_from_hash(gpointer value)1010 on_value_removed_from_hash (gpointer value)
1011 {
1012 	g_value_unset ((GValue*)value);
1013 	g_free (value);
1014 }
1015 
1016 static void
anjuta_window_add_value(AnjutaShell * shell,const char * name,const GValue * value,GError ** error)1017 anjuta_window_add_value (AnjutaShell *shell, const char *name,
1018 					  const GValue *value, GError **error)
1019 {
1020 	GValue *copy;
1021 	AnjutaWindow *win;
1022 
1023 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1024 	g_return_if_fail (name != NULL);
1025 	g_return_if_fail (G_IS_VALUE(value));
1026 
1027 	win = ANJUTA_WINDOW (shell);
1028 
1029 	if (win->values == NULL)
1030 	{
1031 		win->values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
1032 											 on_value_removed_from_hash);
1033 	}
1034 	anjuta_shell_remove_value (shell, name, error);
1035 
1036 	copy = g_new0 (GValue, 1);
1037 	g_value_init (copy, value->g_type);
1038 	g_value_copy (value, copy);
1039 
1040 	g_hash_table_insert (win->values, g_strdup (name), copy);
1041 	g_signal_emit_by_name (shell, "value_added", name, copy);
1042 }
1043 
1044 static void
anjuta_window_get_value(AnjutaShell * shell,const char * name,GValue * value,GError ** error)1045 anjuta_window_get_value (AnjutaShell *shell, const char *name, GValue *value,
1046 					  GError **error)
1047 {
1048 	GValue *val;
1049 	AnjutaWindow *win;
1050 
1051 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1052 	g_return_if_fail (name != NULL);
1053 	/* g_return_if_fail (G_IS_VALUE (value)); */
1054 
1055 	win = ANJUTA_WINDOW (shell);
1056 
1057 	val = NULL;
1058 	if (win->values)
1059 		val = g_hash_table_lookup (win->values, name);
1060 	if (val)
1061 	{
1062 		if (!value->g_type)
1063 		{
1064 			g_value_init (value, val->g_type);
1065 		}
1066 		g_value_copy (val, value);
1067 	}
1068 	else
1069 	{
1070 		if (error)
1071 		{
1072 			*error = g_error_new (ANJUTA_SHELL_ERROR,
1073 								  ANJUTA_SHELL_ERROR_DOESNT_EXIST,
1074 								  _("Value doesn't exist"));
1075 		}
1076 	}
1077 }
1078 
1079 static void
anjuta_window_remove_value(AnjutaShell * shell,const char * name,GError ** error)1080 anjuta_window_remove_value (AnjutaShell *shell, const char *name, GError **error)
1081 {
1082 	AnjutaWindow *win;
1083 	GValue *value;
1084 	char *key;
1085 
1086 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1087 	g_return_if_fail (name != NULL);
1088 
1089 	win = ANJUTA_WINDOW (shell);
1090 
1091 	/*
1092 	g_return_if_fail (win->values != NULL);
1093 	if (win->widgets && g_hash_table_lookup_extended (win->widgets, name,
1094 													  (gpointer*)&key,
1095 													  (gpointer*)&w)) {
1096 		GtkWidget *item;
1097 		item = g_object_get_data (G_OBJECT (w), "dockitem");
1098 		gdl_dock_item_hide_item (GDL_DOCK_ITEM (item));
1099 		gdl_dock_object_unbind (GDL_DOCK_OBJECT (item));
1100 		g_free (key);
1101 	}
1102 	*/
1103 
1104 	if (win->values && g_hash_table_lookup_extended (win->values, name,
1105 													 (gpointer)&key,
1106 													 (gpointer)&value)) {
1107 		g_signal_emit_by_name (win, "value_removed", name);
1108 		g_hash_table_remove (win->values, name);
1109 	}
1110 }
1111 
1112 static void
anjuta_window_saving_push(AnjutaShell * shell)1113 anjuta_window_saving_push (AnjutaShell* shell)
1114 {
1115 	AnjutaWindow* win = ANJUTA_WINDOW (shell);
1116 	win->save_count++;
1117 }
1118 
1119 static void
anjuta_window_saving_pop(AnjutaShell * shell)1120 anjuta_window_saving_pop (AnjutaShell* shell)
1121 {
1122 	AnjutaWindow* win = ANJUTA_WINDOW (shell);
1123 	win->save_count--;
1124 }
1125 
1126 static gboolean
remove_from_widgets_hash(gpointer name,gpointer hash_widget,gpointer widget)1127 remove_from_widgets_hash (gpointer name, gpointer hash_widget, gpointer widget)
1128 {
1129 	if (hash_widget == widget)
1130 		return TRUE;
1131 	return FALSE;
1132 }
1133 
1134 static void
on_widget_destroy(GtkWidget * widget,AnjutaWindow * win)1135 on_widget_destroy (GtkWidget *widget, AnjutaWindow *win)
1136 {
1137 	DEBUG_PRINT ("%s", "Widget about to be destroyed");
1138 	g_hash_table_foreach_remove (win->widgets, remove_from_widgets_hash,
1139 								 widget);
1140 }
1141 
1142 static void
on_widget_remove(GtkWidget * container,GtkWidget * widget,AnjutaWindow * win)1143 on_widget_remove (GtkWidget *container, GtkWidget *widget, AnjutaWindow *win)
1144 {
1145 	GtkWidget *dock_item;
1146 
1147 	dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
1148 	if (dock_item)
1149 	{
1150 		gchar* unique_name = g_object_get_data(G_OBJECT(dock_item), "unique_name");
1151 		g_free(unique_name);
1152 		g_signal_handlers_disconnect_by_func (G_OBJECT (dock_item),
1153 					G_CALLBACK (on_widget_remove), win);
1154 	}
1155 	if (g_hash_table_foreach_remove (win->widgets,
1156 									 remove_from_widgets_hash,
1157 									 widget)){
1158 		DEBUG_PRINT ("%s", "Widget removed from container");
1159 	}
1160 }
1161 
1162 static void
on_widget_removed_from_hash(gpointer widget)1163 on_widget_removed_from_hash (gpointer widget)
1164 {
1165 	AnjutaWindow *win;
1166 	GtkWidget *menuitem;
1167 	GdlDockItem *dockitem;
1168 
1169 	DEBUG_PRINT ("%s", "Removing widget from hash");
1170 
1171 	win = g_object_get_data (G_OBJECT (widget), "app-object");
1172 	dockitem = g_object_get_data (G_OBJECT (widget), "dockitem");
1173 	menuitem = g_object_get_data (G_OBJECT (widget), "menuitem");
1174 
1175 	gtk_widget_destroy (menuitem);
1176 
1177 	g_object_set_data (G_OBJECT (widget), "dockitem", NULL);
1178 	g_object_set_data (G_OBJECT (widget), "menuitem", NULL);
1179 
1180 	g_signal_handlers_disconnect_by_func (G_OBJECT (widget),
1181 				G_CALLBACK (on_widget_destroy), win);
1182 	g_signal_handlers_disconnect_by_func (G_OBJECT (dockitem),
1183 				G_CALLBACK (on_widget_remove), win);
1184 
1185 	g_object_unref (G_OBJECT (widget));
1186 }
1187 
1188 static void
anjuta_window_setup_widget(AnjutaWindow * win,const gchar * name,GtkWidget * widget,GtkWidget * item,const gchar * title,gboolean locked)1189 anjuta_window_setup_widget (AnjutaWindow* win,
1190                          const gchar* name,
1191                          GtkWidget *widget,
1192                          GtkWidget* item,
1193                          const gchar* title,
1194                          gboolean locked)
1195 {
1196 	GtkCheckMenuItem* menuitem;
1197 
1198 	/* Add the widget to hash */
1199 	if (win->widgets == NULL)
1200 	{
1201 		win->widgets = g_hash_table_new_full (g_str_hash, g_str_equal,
1202 											  g_free,
1203 											  on_widget_removed_from_hash);
1204 	}
1205 	g_hash_table_insert (win->widgets, g_strdup (name), widget);
1206 	g_object_ref (widget);
1207 
1208 	/* Add toggle button for the widget */
1209 	menuitem = GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title));
1210 	gtk_widget_show (GTK_WIDGET (menuitem));
1211 	gtk_check_menu_item_set_active (menuitem, TRUE);
1212 	gtk_menu_shell_append (GTK_MENU_SHELL (win->view_menu), GTK_WIDGET (menuitem));
1213 
1214 	if (locked)
1215 		g_object_set( G_OBJECT(menuitem), "visible", FALSE, NULL);
1216 
1217 
1218 	g_object_set_data (G_OBJECT (widget), "app-object", win);
1219 	g_object_set_data (G_OBJECT (widget), "menuitem", menuitem);
1220 	g_object_set_data (G_OBJECT (widget), "dockitem", item);
1221 
1222 	/* For toggling widget view on/off */
1223 	g_signal_connect (G_OBJECT (menuitem), "toggled",
1224 					  G_CALLBACK (on_toggle_widget_view), item);
1225 
1226 	/*
1227 	  Watch for widget removal/destruction so that it could be
1228 	  removed from widgets hash.
1229 	*/
1230 	g_signal_connect (G_OBJECT (item), "remove",
1231 					  G_CALLBACK (on_widget_remove), win);
1232 	g_signal_connect_after (G_OBJECT (widget), "destroy",
1233 					  G_CALLBACK (on_widget_destroy), win);
1234 
1235 	gtk_widget_show (item);
1236 }
1237 
1238 
1239 static void
anjuta_window_add_widget_full(AnjutaShell * shell,GtkWidget * widget,const char * name,const char * title,const char * stock_id,AnjutaShellPlacement placement,gboolean locked,GError ** error)1240 anjuta_window_add_widget_full (AnjutaShell *shell,
1241 					   GtkWidget *widget,
1242 					   const char *name,
1243 					   const char *title,
1244 					   const char *stock_id,
1245 					   AnjutaShellPlacement placement,
1246 					   gboolean locked,
1247 					   GError **error)
1248 {
1249 	AnjutaWindow *win;
1250 	GtkWidget *item;
1251 
1252 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1253 	g_return_if_fail (GTK_IS_WIDGET (widget));
1254 	g_return_if_fail (name != NULL);
1255 	g_return_if_fail (title != NULL);
1256 
1257 	win = ANJUTA_WINDOW (shell);
1258 
1259 	/* Add the widget to dock */
1260 	if (stock_id == NULL)
1261 		item = gdl_dock_item_new (name, title, GDL_DOCK_ITEM_BEH_NORMAL);
1262 	else
1263 		item = gdl_dock_item_new_with_stock (name, title, stock_id,
1264 											 GDL_DOCK_ITEM_BEH_NORMAL);
1265 	if (locked)
1266 	{
1267 		guint flags = 0;
1268 		flags |= GDL_DOCK_ITEM_BEH_NEVER_FLOATING;
1269 		flags |= GDL_DOCK_ITEM_BEH_CANT_CLOSE;
1270 		flags |= GDL_DOCK_ITEM_BEH_CANT_ICONIFY;
1271 		flags |= GDL_DOCK_ITEM_BEH_NO_GRIP;
1272 		g_object_set(G_OBJECT(item), "behavior", flags, NULL);
1273 	}
1274 
1275 	gtk_container_add (GTK_CONTAINER (item), widget);
1276     gdl_dock_add_item (GDL_DOCK (win->dock),
1277                        GDL_DOCK_ITEM (item), placement);
1278 
1279 	if (locked)
1280 		gdl_dock_item_set_default_position(GDL_DOCK_ITEM(item), GDL_DOCK_OBJECT(win->dock));
1281 
1282 	anjuta_window_setup_widget (win, name, widget, item, title, locked);
1283 }
1284 
1285 static void
anjuta_window_add_widget_custom(AnjutaShell * shell,GtkWidget * widget,const char * name,const char * title,const char * stock_id,GtkWidget * label,AnjutaShellPlacement placement,GError ** error)1286 anjuta_window_add_widget_custom (AnjutaShell *shell,
1287                               GtkWidget *widget,
1288                               const char *name,
1289                               const char *title,
1290                               const char   *stock_id,
1291                               GtkWidget *label,
1292                               AnjutaShellPlacement placement,
1293                               GError **error)
1294 {
1295 	AnjutaWindow *win;
1296 	GtkWidget *item;
1297 	GtkWidget *grip;
1298 
1299 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1300 	g_return_if_fail (GTK_IS_WIDGET (widget));
1301 	g_return_if_fail (name != NULL);
1302 	g_return_if_fail (title != NULL);
1303 
1304 	win = ANJUTA_WINDOW (shell);
1305 
1306 	/* Add the widget to dock */
1307 	/* Add the widget to dock */
1308 	if (stock_id == NULL)
1309 		item = gdl_dock_item_new (name, title, GDL_DOCK_ITEM_BEH_NORMAL);
1310 	else
1311 		item = gdl_dock_item_new_with_stock (name, title, stock_id,
1312 											 GDL_DOCK_ITEM_BEH_NORMAL);
1313 
1314 	gtk_container_add (GTK_CONTAINER (item), widget);
1315     gdl_dock_add_item (GDL_DOCK (win->dock),
1316                        GDL_DOCK_ITEM (item), placement);
1317 
1318 	grip = gdl_dock_item_get_grip (GDL_DOCK_ITEM (item));
1319 
1320 	gdl_dock_item_grip_set_label (GDL_DOCK_ITEM_GRIP (grip), label);
1321 
1322 	anjuta_window_setup_widget (win, name, widget, item, title, FALSE);
1323 }
1324 
1325 static void
anjuta_window_remove_widget(AnjutaShell * shell,GtkWidget * widget,GError ** error)1326 anjuta_window_remove_widget (AnjutaShell *shell, GtkWidget *widget,
1327 						  GError **error)
1328 {
1329 	AnjutaWindow *win;
1330 	GtkWidget *dock_item;
1331 
1332 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1333 	g_return_if_fail (GTK_IS_WIDGET (widget));
1334 
1335 	win = ANJUTA_WINDOW (shell);
1336 
1337 	g_return_if_fail (win->widgets != NULL);
1338 
1339 	dock_item = g_object_get_data (G_OBJECT (widget), "dockitem");
1340 	g_return_if_fail (dock_item != NULL);
1341 
1342 	/* Remove the widget from container */
1343 	g_object_ref (widget);
1344 	/* It should call on_widget_remove() and clean up should happen */
1345 	gtk_container_remove (GTK_CONTAINER (dock_item), widget);
1346 	g_object_unref (widget);
1347 	gdl_dock_item_unbind (GDL_DOCK_ITEM(dock_item));
1348 }
1349 
1350 static void
anjuta_window_present_widget(AnjutaShell * shell,GtkWidget * widget,GError ** error)1351 anjuta_window_present_widget (AnjutaShell *shell, GtkWidget *widget,
1352 						   GError **error)
1353 {
1354 	AnjutaWindow *win;
1355 	GdlDockItem *dock_item;
1356 	GtkWidget *parent;
1357 
1358 	g_return_if_fail (ANJUTA_IS_WINDOW (shell));
1359 	g_return_if_fail (GTK_IS_WIDGET (widget));
1360 
1361 	win = ANJUTA_WINDOW (shell);
1362 
1363 	g_return_if_fail (win->widgets != NULL);
1364 
1365 	dock_item = g_object_get_data (G_OBJECT(widget), "dockitem");
1366 	g_return_if_fail (dock_item != NULL);
1367 
1368 	/* Hack to present the dock item if it's in a notebook dock item */
1369 	parent = gtk_widget_get_parent (GTK_WIDGET(dock_item) );
1370 	if (!GDL_DOCK_OBJECT_ATTACHED (dock_item))
1371 	{
1372 		gdl_dock_item_show_item (GDL_DOCK_ITEM (dock_item));
1373 	}
1374 	if (GTK_IS_NOTEBOOK (parent))
1375 	{
1376 		gint pagenum;
1377 		pagenum = gtk_notebook_page_num (GTK_NOTEBOOK (parent), GTK_WIDGET (dock_item));
1378 		gtk_notebook_set_current_page (GTK_NOTEBOOK (parent), pagenum);
1379 	}
1380 
1381 	/* FIXME: If the item is floating, present the window */
1382 	/* FIXME: There is no way to detect if a widget was floating before it was
1383 	detached since it no longer has a parent there is no way to access the
1384 	floating property of the GdlDock structure.*/
1385 }
1386 
1387 static GObject*
anjuta_window_get_object(AnjutaShell * shell,const char * iface_name,GError ** error)1388 anjuta_window_get_object  (AnjutaShell *shell, const char *iface_name,
1389 					    GError **error)
1390 {
1391 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
1392 	g_return_val_if_fail (iface_name != NULL, NULL);
1393 	return anjuta_plugin_manager_get_plugin (ANJUTA_WINDOW (shell)->plugin_manager,
1394 											 iface_name);
1395 }
1396 
1397 static AnjutaStatus*
anjuta_window_get_status(AnjutaShell * shell,GError ** error)1398 anjuta_window_get_status (AnjutaShell *shell, GError **error)
1399 {
1400 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
1401 	return ANJUTA_WINDOW (shell)->status;
1402 }
1403 
1404 static AnjutaUI *
anjuta_window_get_ui(AnjutaShell * shell,GError ** error)1405 anjuta_window_get_ui  (AnjutaShell *shell, GError **error)
1406 {
1407 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
1408 	return ANJUTA_WINDOW (shell)->ui;
1409 }
1410 
1411 static AnjutaPreferences *
anjuta_window_get_preferences(AnjutaShell * shell,GError ** error)1412 anjuta_window_get_preferences  (AnjutaShell *shell, GError **error)
1413 {
1414 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
1415 	return ANJUTA_WINDOW (shell)->preferences;
1416 }
1417 
1418 static AnjutaPluginManager *
anjuta_window_get_plugin_manager(AnjutaShell * shell,GError ** error)1419 anjuta_window_get_plugin_manager  (AnjutaShell *shell, GError **error)
1420 {
1421 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
1422 	return ANJUTA_WINDOW (shell)->plugin_manager;
1423 }
1424 
1425 static AnjutaProfileManager *
anjuta_window_get_profile_manager(AnjutaShell * shell,GError ** error)1426 anjuta_window_get_profile_manager (AnjutaShell *shell, GError **error)
1427 {
1428 	g_return_val_if_fail (ANJUTA_IS_WINDOW (shell), NULL);
1429 	return ANJUTA_WINDOW (shell)->profile_manager;
1430 }
1431 
1432 static void
anjuta_shell_iface_init(AnjutaShellIface * iface)1433 anjuta_shell_iface_init (AnjutaShellIface *iface)
1434 {
1435 	iface->add_widget_full = anjuta_window_add_widget_full;
1436 	iface->add_widget_custom = anjuta_window_add_widget_custom;
1437 	iface->remove_widget = anjuta_window_remove_widget;
1438 	iface->present_widget = anjuta_window_present_widget;
1439 	iface->iconify_dockable_widget = anjuta_window_iconify_dockable_widget;
1440 	iface->hide_dockable_widget = anjuta_window_hide_dockable_widget;
1441 	iface->show_dockable_widget = anjuta_window_show_dockable_widget;
1442 	iface->maximize_widget = anjuta_window_maximize_widget;
1443 	iface->unmaximize = anjuta_window_unmaximize;
1444 	iface->create_window = anjuta_window_create_window;
1445 	iface->add_value = anjuta_window_add_value;
1446 	iface->get_value = anjuta_window_get_value;
1447 	iface->remove_value = anjuta_window_remove_value;
1448 	iface->get_object = anjuta_window_get_object;
1449 	iface->get_status = anjuta_window_get_status;
1450 	iface->get_ui = anjuta_window_get_ui;
1451 	iface->get_preferences = anjuta_window_get_preferences;
1452 	iface->get_plugin_manager = anjuta_window_get_plugin_manager;
1453 	iface->get_profile_manager = anjuta_window_get_profile_manager;
1454 	iface->saving_push = anjuta_window_saving_push;
1455 	iface->saving_pop = anjuta_window_saving_pop;
1456 }
1457 
1458 ANJUTA_TYPE_BEGIN(AnjutaWindow, anjuta_window, GTK_TYPE_APPLICATION_WINDOW);
1459 ANJUTA_TYPE_ADD_INTERFACE(anjuta_shell, ANJUTA_TYPE_SHELL);
1460 ANJUTA_TYPE_END;
1461