1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * bonobo-mdi.c - implementation of a BonoboMDI object
5 * Copyright (C) 2001-2002 Free Software Foundation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
26 * Modified by the gedit Team, 2001-2002. See the AUTHORS file for a
27 * list of people on the gedit Team.
28 * See the ChangeLog files for a list of changes.
35 #include "bonobo-mdi.h"
37 #include <bonobo/bonobo-i18n.h>
39 #include <bonobo/bonobo-dock-layout.h>
40 #include <bonobo/bonobo-ui-util.h>
48 #define BONOBO_MDI_KEY "BonoboMDI"
49 #define BONOBO_MDI_CHILD_KEY "BonoboMDIChild"
50 #define UI_COMPONENT_KEY "UIComponent"
51 #define BOOK_KEY "Book"
52 #define WINDOW_INFO_KEY "BonoboMDIWindowInfo"
54 static void bonobo_mdi_class_init (BonoboMDIClass *);
55 static void bonobo_mdi_instance_init (BonoboMDI *);
56 static void bonobo_mdi_finalize (GObject *);
57 static void child_list_menu_create (BonoboMDI *, BonoboWindow *);
59 static void child_list_activated_cb (BonoboUIComponent *uic, gpointer user_data,
60 const gchar* verbname);
62 void child_list_menu_remove_item(BonoboMDI *, BonoboMDIChild *);
63 void child_list_menu_add_item (BonoboMDI *, BonoboMDIChild *);
65 static void app_create (BonoboMDI *, gchar *, const char *);
66 static void app_clone (BonoboMDI *, BonoboWindow *, const char *);
67 static void app_destroy (BonoboWindow *, BonoboMDI *);
68 static void app_set_view (BonoboMDI *, BonoboWindow *, GtkWidget *);
70 static gboolean app_close_book (BonoboWindow *, GdkEventAny *, BonoboMDI *);
72 static GtkWidget *book_create (BonoboMDI *);
73 static void book_switch_page (GtkNotebook *, GtkNotebookPage *,
75 static gboolean book_motion (GtkWidget *widget, GdkEventMotion *e,
77 static gboolean book_button_press (GtkWidget *widget, GdkEventButton *e,
79 static gboolean book_button_release (GtkWidget *widget, GdkEventButton *e,
81 static void book_add_view (GtkNotebook *, GtkWidget *);
82 static void set_page_by_widget (GtkNotebook *, GtkWidget *);
84 static gboolean toplevel_focus (BonoboWindow *, GdkEventFocus *, BonoboMDI *);
86 static void set_active_view (BonoboMDI *, GtkWidget *);
88 /* convenience functions that call child's "virtual" functions */
89 static GtkWidget *child_set_label (BonoboMDIChild *, GtkWidget *);
91 static void child_name_changed (BonoboMDIChild *mdi_child,
94 static void bonobo_mdi_update_child (BonoboMDI *mdi, BonoboMDIChild *child);
96 static gchar* escape_underscores (const gchar* text);
98 static GtkWidget* get_book_from_window (BonoboWindow *window);
100 static GdkCursor *drag_cursor = NULL;
111 ALL_WINDOWS_DESTROYED,
116 struct _BonoboMDIPrivate
118 GtkPositionType tab_pos;
130 /* Probably only one of these would do, but... redundancy rules ;) */
131 BonoboMDIChild *active_child;
132 GtkWidget *active_view;
133 BonoboWindow *active_window;
135 GList *windows; /* toplevel windows - BonoboWindow widgets */
136 GList *children; /* children - BonoboMDIChild objects*/
138 GSList *registered; /* see comment for bonobo_mdi_(un)register() functions
139 * below for an explanation. */
141 /* Paths for insertion of mdi-child list menu via */
142 gchar *child_list_path;
144 gint default_window_height;
145 gint default_window_width;
148 typedef gboolean (*BonoboMDISignal1) (GObject *, gpointer, gpointer);
149 typedef void (*BonoboMDISignal2) (GObject *, gpointer, gpointer);
151 static GObjectClass *parent_class = NULL;
152 static guint mdi_signals [LAST_SIGNAL] = { 0 };
155 bonobo_mdi_get_type (void)
157 static GType bonobo_mdi_type = 0;
159 if (bonobo_mdi_type == 0)
161 static const GTypeInfo our_info =
163 sizeof (BonoboMDIClass),
164 NULL, /* base_init */
165 NULL, /* base_finalize */
166 (GClassInitFunc) bonobo_mdi_class_init,
167 NULL, /* class_finalize */
168 NULL, /* class_data */
171 (GInstanceInitFunc) bonobo_mdi_instance_init
174 bonobo_mdi_type = g_type_register_static (G_TYPE_OBJECT,
180 return bonobo_mdi_type;
184 bonobo_mdi_class_init (BonoboMDIClass *class)
186 GObjectClass *object_class;
188 object_class = (GObjectClass*) class;
190 object_class->finalize = bonobo_mdi_finalize;
192 mdi_signals[ADD_CHILD] =
193 g_signal_new ("add_child",
194 G_OBJECT_CLASS_TYPE (object_class),
196 G_STRUCT_OFFSET (BonoboMDIClass, add_child),
198 gl_marshal_BOOLEAN__OBJECT,
201 BONOBO_TYPE_MDI_CHILD);
203 mdi_signals[REMOVE_CHILD] =
204 g_signal_new ("remove_child",
205 G_OBJECT_CLASS_TYPE (object_class),
207 G_STRUCT_OFFSET (BonoboMDIClass, remove_child),
209 gl_marshal_BOOLEAN__OBJECT,
212 BONOBO_TYPE_MDI_CHILD);
214 mdi_signals[ADD_VIEW] =
215 g_signal_new ("add_view",
216 G_OBJECT_CLASS_TYPE (object_class),
218 G_STRUCT_OFFSET (BonoboMDIClass, add_view),
220 gl_marshal_BOOLEAN__OBJECT,
225 mdi_signals[REMOVE_VIEW] =
226 g_signal_new ("remove_view",
227 G_OBJECT_CLASS_TYPE (object_class),
229 G_STRUCT_OFFSET (BonoboMDIClass, remove_view),
231 gl_marshal_BOOLEAN__OBJECT,
236 mdi_signals[CHILD_CHANGED] =
237 g_signal_new ("child_changed",
238 G_OBJECT_CLASS_TYPE (object_class),
240 G_STRUCT_OFFSET (BonoboMDIClass, child_changed),
242 g_cclosure_marshal_VOID__OBJECT,
245 BONOBO_TYPE_MDI_CHILD);
247 mdi_signals[VIEW_CHANGED] =
248 g_signal_new ("view_changed",
249 G_OBJECT_CLASS_TYPE (object_class),
251 G_STRUCT_OFFSET(BonoboMDIClass, view_changed),
253 g_cclosure_marshal_VOID__OBJECT,
258 mdi_signals[TOP_WINDOW_CREATED] =
259 g_signal_new ("top_window_created",
260 G_OBJECT_CLASS_TYPE (object_class),
262 G_STRUCT_OFFSET (BonoboMDIClass, top_window_created),
264 g_cclosure_marshal_VOID__OBJECT,
269 mdi_signals[TOP_WINDOW_DESTROY] =
270 g_signal_new ("top_window_destroy",
271 G_OBJECT_CLASS_TYPE (object_class),
273 G_STRUCT_OFFSET (BonoboMDIClass, top_window_destroy),
275 g_cclosure_marshal_VOID__OBJECT,
280 mdi_signals[ALL_WINDOWS_DESTROYED] =
281 g_signal_new ("all_windows_destroyed",
282 G_OBJECT_CLASS_TYPE (object_class),
284 G_STRUCT_OFFSET (BonoboMDIClass, all_windows_destroyed),
286 g_cclosure_marshal_VOID__VOID,
291 class->add_child = NULL;
292 class->remove_child = NULL;
293 class->add_view = NULL;
294 class->remove_view = NULL;
295 class->child_changed = NULL;
296 class->view_changed = NULL;
297 class->top_window_created = NULL;
299 parent_class = gtk_type_class (G_TYPE_OBJECT);
303 bonobo_mdi_finalize (GObject *object)
307 gl_debug (DEBUG_MDI, "");
309 g_return_if_fail (BONOBO_IS_MDI (object));
311 mdi = BONOBO_MDI (object);
312 g_return_if_fail (mdi->priv != NULL);
314 bonobo_mdi_remove_all (mdi, TRUE);
316 if (mdi->priv->child_list_path != NULL)
317 g_free (mdi->priv->child_list_path);
319 if (mdi->priv->mdi_name != NULL)
320 g_free (mdi->priv->mdi_name);
322 if (mdi->priv->title != NULL)
323 g_free (mdi->priv->title);
325 if (mdi->priv->ui_xml != NULL)
326 g_free (mdi->priv->ui_xml);
328 if (mdi->priv->ui_file_name != NULL)
329 g_free (mdi->priv->ui_file_name);
334 if (G_OBJECT_CLASS (parent_class)->finalize)
335 (* G_OBJECT_CLASS (parent_class)->finalize)(object);
337 gl_debug (DEBUG_MDI, "END");
342 bonobo_mdi_instance_init (BonoboMDI *mdi)
344 gl_debug (DEBUG_MDI, "");
346 g_return_if_fail (BONOBO_IS_MDI (mdi));
348 mdi->priv = g_new0 (BonoboMDIPrivate, 1);
349 g_return_if_fail (mdi->priv != NULL);
351 mdi->priv->tab_pos = GTK_POS_TOP;
353 mdi->priv->signal_id = 0;
354 mdi->priv->in_drag = FALSE;
356 mdi->priv->children = NULL;
357 mdi->priv->windows = NULL;
358 mdi->priv->registered = NULL;
360 mdi->priv->active_child = NULL;
361 mdi->priv->active_window = NULL;
362 mdi->priv->active_view = NULL;
364 mdi->priv->ui_xml = NULL;
365 mdi->priv->ui_file_name = NULL;
366 mdi->priv->verbs = NULL;
368 mdi->priv->child_list_path = NULL;
370 gl_debug (DEBUG_MDI, "END");
376 * @mdi_name: Application name as used in filenames and paths.
377 * @title: Title of the application windows.
380 * Creates a new MDI object. @mdi_name and @title are used for
381 * MDI's calling bonobo_window_new ().
384 * A pointer to a new BonoboMDI object.
387 bonobo_mdi_new (const gchar *mdi_name, const gchar *title,
388 gint default_window_width, gint default_window_height)
392 gl_debug (DEBUG_MDI, "");
394 mdi = g_object_new (BONOBO_TYPE_MDI, NULL);
396 mdi->priv->mdi_name = g_strdup (mdi_name);
397 mdi->priv->title = g_strdup (title);
399 mdi->priv->default_window_width = default_window_width;
400 mdi->priv->default_window_height = default_window_height;
402 gl_debug (DEBUG_MDI, "END");
404 return G_OBJECT (mdi);
408 child_set_label (BonoboMDIChild *child, GtkWidget *label)
411 w = BONOBO_MDI_CHILD_GET_CLASS (child)->set_label (child, label, NULL);
417 set_page_by_widget (GtkNotebook *book, GtkWidget *view)
421 i = gtk_notebook_page_num (book, view);
423 if (gtk_notebook_get_current_page (book) != i)
424 gtk_notebook_set_current_page (book, i);
428 child_list_activated_cb (BonoboUIComponent *uic, gpointer user_data, const gchar* verbname)
431 BonoboMDIChild *child = BONOBO_MDI_CHILD (user_data);
432 g_return_if_fail (child != NULL);
434 gl_debug (DEBUG_MDI, "");
436 mdi = BONOBO_MDI (g_object_get_data (G_OBJECT (child), BONOBO_MDI_KEY));
437 g_return_if_fail (mdi != NULL);
439 if (child && (child != mdi->priv->active_child))
441 GList *views = bonobo_mdi_child_get_views (child);
444 bonobo_mdi_set_active_view (mdi, views->data);
446 bonobo_mdi_add_view (mdi, child);
449 gl_debug (DEBUG_MDI, "END");
453 escape_underscores (const gchar* text)
460 g_return_val_if_fail (text != NULL, NULL);
462 length = strlen (text);
464 str = g_string_new ("");
472 next = g_utf8_next_char (p);
477 g_string_append (str, "__");
480 g_string_append_len (str, p, next - p);
487 return g_string_free (str, FALSE);
491 child_list_menu_create (BonoboMDI *mdi, BonoboWindow *win)
494 BonoboUIComponent *ui_component;
496 if (mdi->priv->child_list_path == NULL)
499 ui_component = BONOBO_UI_COMPONENT (
500 g_object_get_data (G_OBJECT (win), UI_COMPONENT_KEY));
502 child = mdi->priv->children;
504 bonobo_ui_component_freeze (ui_component, NULL);
510 gchar *verb_name = NULL;
514 gchar *child_name = bonobo_mdi_child_get_name (BONOBO_MDI_CHILD (child->data));
516 safe_name = g_markup_escape_text (child_name, strlen (child_name));
517 g_return_if_fail (safe_name != NULL);
519 escaped_name = escape_underscores (safe_name);
520 g_return_if_fail (escaped_name != NULL);
522 tip = g_strdup_printf (_("Activate %s"), safe_name);
523 verb_name = g_strdup_printf ("Child_%p", child->data);
524 xml = g_strdup_printf ("<menuitem name=\"%s\" verb=\"%s\""
525 " _label=\"%s\"/>", verb_name, verb_name, escaped_name);
526 cmd = g_strdup_printf ("<cmd name = \"%s\" _label=\"%s\""
527 " _tip=\"%s\"/>", verb_name, escaped_name, tip);
532 g_free (escaped_name);
534 bonobo_ui_component_set_translate (ui_component, mdi->priv->child_list_path, xml, NULL);
535 bonobo_ui_component_set_translate (ui_component, "/commands/", cmd, NULL);
536 bonobo_ui_component_add_verb (ui_component, verb_name, child_list_activated_cb, child->data);
542 child = g_list_next (child);
545 bonobo_ui_component_thaw (ui_component, NULL);
550 child_list_menu_remove_item (BonoboMDI *mdi, BonoboMDIChild *child)
553 gchar *path, *cmd, *verb_name;
555 gl_debug (DEBUG_MDI, "");
557 if(mdi->priv->child_list_path == NULL)
560 win_node = mdi->priv->windows;
562 verb_name = g_strdup_printf ("Child_%p", child);
563 path = g_strdup_printf ("%s%s", mdi->priv->child_list_path, verb_name);
564 cmd = g_strdup_printf ("/commands/%s", verb_name);
568 BonoboUIComponent *ui_component;
570 ui_component = BONOBO_UI_COMPONENT (
571 g_object_get_data (G_OBJECT (win_node->data), UI_COMPONENT_KEY));
573 bonobo_ui_component_remove_verb (ui_component, verb_name);
574 bonobo_ui_component_rm (ui_component, path, NULL);
575 bonobo_ui_component_rm (ui_component, cmd, NULL);
576 win_node = g_list_next (win_node);
583 gl_debug (DEBUG_MDI, "END");
588 child_list_menu_add_item (BonoboMDI *mdi, BonoboMDIChild *child)
591 gchar *child_name, *escaped_name, *safe_name;
592 gchar* xml, *cmd, *verb_name, *tip;
595 if(mdi->priv->child_list_path == NULL)
598 accel_num = g_list_length (mdi->priv->children);
600 win_node = mdi->priv->windows;
602 child_name = bonobo_mdi_child_get_name (child);
604 safe_name = g_markup_escape_text (child_name, strlen (child_name));
605 g_return_if_fail (safe_name != NULL);
607 escaped_name = escape_underscores (safe_name);
608 g_return_if_fail (escaped_name != NULL);
610 verb_name = g_strdup_printf ("Child_%p", child);
612 tip = g_strdup_printf (_("Activate %s"), safe_name);
613 xml = g_strdup_printf ("<menuitem name=\"%s\" verb=\"%s\""
614 " _label=\"%s\"/>", verb_name, verb_name, escaped_name);
617 cmd = g_strdup_printf ("<cmd name = \"%s\" _label=\"%s\""
618 " _tip=\"%s\"/>", verb_name, escaped_name, tip);
620 cmd = g_strdup_printf ("<cmd name = \"%s\" _label=\"%s\""
621 " _tip=\"%s\" accel=\"*Alt*%d\"/>", verb_name,
622 escaped_name, tip, accel_num);
627 BonoboUIComponent *ui_component;
629 ui_component = BONOBO_UI_COMPONENT (
630 g_object_get_data (G_OBJECT (win_node->data), UI_COMPONENT_KEY));
633 bonobo_ui_component_set_translate (ui_component, mdi->priv->child_list_path, xml, NULL);
634 bonobo_ui_component_set_translate (ui_component, "/commands/", cmd, NULL);
635 bonobo_ui_component_add_verb (ui_component, verb_name, child_list_activated_cb, child);
637 win_node = g_list_next (win_node);
641 g_free (escaped_name);
650 book_motion (GtkWidget *widget, GdkEventMotion *e, gpointer data)
654 mdi = BONOBO_MDI (data);
657 drag_cursor = gdk_cursor_new (GDK_HAND2);
659 if (e->window == GTK_NOTEBOOK (widget)->event_window)
661 mdi->priv->in_drag = TRUE;
662 gtk_grab_add (widget);
663 gdk_pointer_grab (widget->window, FALSE,
664 GDK_POINTER_MOTION_MASK |
665 GDK_BUTTON_RELEASE_MASK, NULL,
666 drag_cursor, GDK_CURRENT_TIME);
667 if (mdi->priv->signal_id)
669 g_signal_handler_disconnect (G_OBJECT (widget),
670 mdi->priv->signal_id);
671 mdi->priv->signal_id = 0;
679 book_button_press (GtkWidget *widget, GdkEventButton *e, gpointer data)
683 mdi = BONOBO_MDI (data);
685 if ((e->button == 1) && (e->window == GTK_NOTEBOOK (widget)->event_window))
686 mdi->priv->signal_id = g_signal_connect (
688 "motion_notify_event",
689 G_CALLBACK (book_motion),
696 book_button_release (GtkWidget *widget, GdkEventButton *e, gpointer data)
698 gint x = e->x_root, y = e->y_root;
701 mdi = BONOBO_MDI(data);
703 if (mdi->priv->signal_id)
705 g_signal_handler_disconnect (G_OBJECT (widget), mdi->priv->signal_id);
706 mdi->priv->signal_id = 0;
709 if ((e->button == 1) && mdi->priv->in_drag)
714 GtkWidget *view, *new_book;
715 GtkNotebook *old_book = GTK_NOTEBOOK (widget);
717 mdi->priv->in_drag = FALSE;
718 gdk_pointer_ungrab (GDK_CURRENT_TIME);
719 gtk_grab_remove (widget);
721 window = gdk_window_at_pointer (&x, &y);
723 window = gdk_window_get_toplevel (window);
725 child = mdi->priv->windows;
729 if (window == GTK_WIDGET (child->data)->window)
733 /* page was dragged to another notebook */
735 old_book = GTK_NOTEBOOK(widget);
736 new_book = get_book_from_window (BONOBO_WINDOW (child->data));
738 if (old_book == (GtkNotebook *) new_book)
739 /* page has been dropped on the source notebook */
742 cur_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (old_book));
746 view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (old_book), cur_page);
747 gtk_container_remove (GTK_CONTAINER(old_book), view);
749 book_add_view (GTK_NOTEBOOK (new_book), view);
751 win = bonobo_mdi_get_window_from_view (view);
752 gdk_window_raise (GTK_WIDGET(win)->window);
754 mdi->priv->active_window = win;
756 cur_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (old_book));
760 mdi->priv->active_window = win;
761 win = BONOBO_WINDOW (gtk_widget_get_toplevel (
762 GTK_WIDGET (old_book)));
763 mdi->priv->windows = g_list_remove(mdi->priv->windows, win);
764 gtk_widget_destroy (GTK_WIDGET (win));
767 g_signal_emit (G_OBJECT (mdi),
768 mdi_signals [CHILD_CHANGED],
772 g_signal_emit (G_OBJECT (mdi),
773 mdi_signals [VIEW_CHANGED],
784 if (g_list_length (old_book->children) == 1)
787 /* create a new toplevel */
788 if (old_book->cur_page)
791 int cur_page = gtk_notebook_get_current_page (old_book);
793 view = gtk_notebook_get_nth_page (old_book, cur_page);
795 win = bonobo_mdi_get_window_from_view (view);
797 gtk_window_get_size (GTK_WINDOW (win), &width, &height);
799 gtk_container_remove (GTK_CONTAINER (old_book), view);
801 app_clone (mdi, win, NULL);
803 new_book = book_create (mdi);
805 book_add_view (GTK_NOTEBOOK (new_book), view);
807 gtk_window_set_position (GTK_WINDOW (mdi->priv->active_window), GTK_WIN_POS_MOUSE);
809 gtk_window_set_default_size (GTK_WINDOW (mdi->priv->active_window), width, height);
811 if (!GTK_WIDGET_VISIBLE (mdi->priv->active_window))
812 gtk_widget_show (GTK_WIDGET (mdi->priv->active_window));
820 book_create (BonoboMDI *mdi)
825 gl_debug (DEBUG_MDI, "");
827 g_return_val_if_fail (mdi->priv->active_window != NULL, NULL);
829 vbox = gtk_vbox_new (FALSE, 0);
830 us = gtk_notebook_new ();
832 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (us), mdi->priv->tab_pos);
834 gtk_box_pack_start (GTK_BOX (vbox), us, TRUE, TRUE, 0);
836 gtk_widget_show_all (vbox);
838 bonobo_window_set_contents (mdi->priv->active_window, vbox);
839 g_object_set_data (G_OBJECT (mdi->priv->active_window), BOOK_KEY, us);
841 gtk_widget_add_events (us, GDK_BUTTON1_MOTION_MASK);
843 g_signal_connect (G_OBJECT (us), "switch_page",
844 G_CALLBACK (book_switch_page), mdi);
846 g_signal_connect (G_OBJECT (us), "button_press_event",
847 G_CALLBACK (book_button_press), mdi);
848 g_signal_connect (G_OBJECT (us), "button_release_event",
849 G_CALLBACK (book_button_release), mdi);
851 gtk_notebook_set_scrollable (GTK_NOTEBOOK (us), TRUE);
853 gl_debug (DEBUG_MDI, "END");
859 book_add_view (GtkNotebook *book, GtkWidget *view)
861 BonoboMDIChild *child;
864 gl_debug (DEBUG_MDI, "");
866 child = bonobo_mdi_get_child_from_view (view);
868 title = child_set_label (child, NULL);
870 gtk_notebook_append_page (book, view, title);
872 if (g_list_length (book->children) > 1)
873 set_page_by_widget (book, view);
875 gl_debug (DEBUG_MDI, "END");
879 book_switch_page (GtkNotebook *book, GtkNotebookPage *pg, gint page_num, BonoboMDI *mdi)
884 gl_debug (DEBUG_MDI, "");
886 win = BONOBO_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (book)));
888 page = gtk_notebook_get_nth_page (book, page_num);
892 if (page != mdi->priv->active_view)
893 app_set_view (mdi, win, page);
896 app_set_view (mdi, win, NULL);
898 gl_debug (DEBUG_MDI, "END");
903 get_book_from_window (BonoboWindow *window)
907 g_return_val_if_fail (window != NULL, NULL);
909 book = g_object_get_data (G_OBJECT (window), BOOK_KEY);
911 return (book != NULL) ? GTK_WIDGET (book) : NULL;
915 toplevel_focus (BonoboWindow *win, GdkEventFocus *event, BonoboMDI *mdi)
919 gl_debug (DEBUG_MDI, "");
921 /* updates active_view and active_child when a new toplevel receives focus */
922 g_return_val_if_fail (BONOBO_IS_WINDOW (win), FALSE);
924 mdi->priv->active_window = win;
926 contents = get_book_from_window (win);
928 if (GTK_NOTEBOOK (contents)->cur_page)
933 cur_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (contents));
934 child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (contents), cur_page);
935 set_active_view (mdi, child);
938 set_active_view (mdi, NULL);
940 gl_debug (DEBUG_MDI, "END");
946 app_configure_event_handler (GtkWidget *widget, GdkEventConfigure *event)
948 BonoboMDIWindowInfo *window_info;
950 g_return_val_if_fail (BONOBO_IS_WINDOW (widget), FALSE);
951 g_return_val_if_fail (event != NULL, FALSE);
953 window_info = (BonoboMDIWindowInfo*)
954 g_object_get_data (G_OBJECT (widget), WINDOW_INFO_KEY);
955 g_return_val_if_fail (window_info != NULL, FALSE);
957 window_info->width = event->width;
958 window_info->height = event->height;
964 app_window_state_event_handler (GtkWidget *widget, GdkEventWindowState *event)
966 BonoboMDIWindowInfo *window_info;
968 g_return_val_if_fail (BONOBO_IS_WINDOW (widget), FALSE);
969 g_return_val_if_fail (event != NULL, FALSE);
971 window_info = (BonoboMDIWindowInfo*)
972 g_object_get_data (G_OBJECT (widget), WINDOW_INFO_KEY);
973 g_return_val_if_fail (window_info != NULL, FALSE);
975 window_info->state = event->new_window_state;
982 app_clone (BonoboMDI *mdi, BonoboWindow *win, const char *window_role)
984 gl_debug (DEBUG_MDI, "");
986 app_create (mdi, NULL, window_role);
990 const BonoboMDIWindowInfo *window_info = bonobo_mdi_get_window_info (win);
991 g_return_if_fail (window_info != NULL);
993 if ((window_info->state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
994 gtk_window_maximize (GTK_WINDOW (mdi->priv->active_window));
997 gtk_window_set_default_size (GTK_WINDOW (mdi->priv->active_window),
999 window_info->height);
1001 gtk_window_unmaximize (GTK_WINDOW (mdi->priv->active_window));
1004 if ((window_info->state & GDK_WINDOW_STATE_STICKY ) != 0)
1005 gtk_window_stick (GTK_WINDOW (mdi->priv->active_window));
1007 gtk_window_unstick (GTK_WINDOW (mdi->priv->active_window));
1010 gl_debug (DEBUG_MDI, "END");
1015 app_close_book (BonoboWindow *win, GdkEventAny *event, BonoboMDI *mdi)
1017 BonoboMDIChild *child;
1019 gint handler_ret = TRUE;
1021 gl_debug (DEBUG_MDI, "");
1023 if (g_list_length (mdi->priv->windows) == 1)
1025 if (!bonobo_mdi_remove_all (mdi, FALSE))
1027 gl_debug (DEBUG_MDI, "END1");
1032 mdi->priv->windows = g_list_remove (mdi->priv->windows, win);
1033 gtk_widget_destroy (GTK_WIDGET (win));
1035 /* only emit al_windows_destroyed signal if there are no non-MDI windows registered
1037 if (mdi->priv->registered == NULL)
1038 g_signal_emit (G_OBJECT (mdi), mdi_signals [ALL_WINDOWS_DESTROYED], 0);
1042 GList *children = gtk_container_get_children (
1043 GTK_CONTAINER (get_book_from_window (win)));
1046 if (children == NULL)
1048 mdi->priv->windows = g_list_remove (mdi->priv->windows, win);
1049 gtk_widget_destroy (GTK_WIDGET (win));
1051 gl_debug (DEBUG_MDI, "END2");
1056 /* first check if all the children in this notebook can be removed */
1057 for (li = children; li != NULL; li = li->next)
1062 child = bonobo_mdi_get_child_from_view (view);
1064 node = bonobo_mdi_child_get_views (child);
1068 if (bonobo_mdi_get_window_from_view (node->data) != win)
1076 /* all the views reside in this BonoboWindow */
1077 g_signal_emit (G_OBJECT(mdi),
1078 mdi_signals [REMOVE_CHILD],
1083 if (handler_ret == FALSE)
1085 g_list_free (children);
1087 gl_debug (DEBUG_MDI, "END3");
1094 /* now actually remove all children/views! */
1095 for (li = children; li != NULL; li = li->next)
1099 child = bonobo_mdi_get_child_from_view (view);
1101 /* if this is the last view, remove the child */
1102 if (g_list_length (bonobo_mdi_child_get_views (child)) == 1)
1103 bonobo_mdi_remove_child (mdi, child, TRUE);
1105 bonobo_mdi_remove_view (mdi, view, TRUE);
1108 g_list_free (children);
1111 gl_debug (DEBUG_MDI, "END");
1117 app_set_view (BonoboMDI *mdi, BonoboWindow *win, GtkWidget *view)
1119 gl_debug (DEBUG_MDI, "");
1121 gtk_window_set_title (GTK_WINDOW (win), mdi->priv->title);
1123 set_active_view (mdi, view);
1125 gl_debug (DEBUG_MDI, "END");
1129 app_destroy (BonoboWindow *win, BonoboMDI *mdi)
1131 gl_debug (DEBUG_MDI, "");
1133 if (mdi->priv->active_window == win)
1134 mdi->priv->active_window =
1135 (mdi->priv->windows != NULL) ? BONOBO_WINDOW (mdi->priv->windows->data) : NULL;
1137 g_signal_emit (G_OBJECT (mdi), mdi_signals [TOP_WINDOW_DESTROY], 0, win);
1139 gl_debug (DEBUG_MDI, "END");
1142 /* Generates a unique string for a window role.
1150 static char *hostname;
1157 static char buffer [512];
1159 if ((gethostname (buffer, sizeof (buffer) - 1) == 0) &&
1163 hostname = "localhost";
1166 ret = g_strdup_printf ("bonobo-mdi-window-%d-%d-%d-%ld-%d@%s",
1178 app_create (BonoboMDI *mdi, gchar *layout_string, const char *window_role)
1183 BonoboUIContainer *ui_container = NULL;
1184 BonoboUIComponent *ui_component = NULL;
1185 BonoboMDIWindowInfo *window_info = NULL;
1187 gl_debug (DEBUG_MDI, "");
1189 window = bonobo_window_new (mdi->priv->mdi_name, mdi->priv->title);
1190 g_return_if_fail (window != NULL);
1192 gtk_window_set_default_size (GTK_WINDOW (window),
1193 mdi->priv->default_window_width,
1194 mdi->priv->default_window_height);
1197 gtk_window_set_role (GTK_WINDOW (window), window_role);
1202 gtk_window_set_role (GTK_WINDOW (window), role);
1206 bw = BONOBO_WINDOW (window);
1208 mdi->priv->windows = g_list_append (mdi->priv->windows, window);
1210 g_signal_connect (G_OBJECT (window), "delete_event",
1211 G_CALLBACK (app_close_book), mdi);
1212 g_signal_connect (G_OBJECT (window), "focus_in_event",
1213 G_CALLBACK (toplevel_focus), mdi);
1214 g_signal_connect (G_OBJECT (window), "destroy",
1215 G_CALLBACK (app_destroy), mdi);
1216 g_signal_connect (G_OBJECT (window), "configure_event",
1217 G_CALLBACK (app_configure_event_handler), NULL);
1218 g_signal_connect (G_OBJECT (window), "window_state_event",
1219 G_CALLBACK (app_window_state_event_handler), NULL);
1221 /* Create Container: */
1222 ui_container = bonobo_window_get_ui_container (bw);
1224 config_path = g_strdup_printf ("/%s/UIConfig/kvps", mdi->priv->mdi_name);
1226 bonobo_ui_engine_config_set_path (bonobo_window_get_ui_engine (bw),
1228 g_free (config_path);
1230 /* Create a UI component with which to communicate with the window */
1231 ui_component = bonobo_ui_component_new_default ();
1233 /* Associate the BonoboUIComponent with the container */
1234 bonobo_ui_component_set_container (
1235 ui_component, BONOBO_OBJREF (ui_container), NULL);
1238 if (mdi->priv->ui_xml != NULL)
1240 bonobo_ui_component_set_translate (ui_component,
1241 "/", mdi->priv->ui_xml, NULL);
1244 if (mdi->priv->ui_file_name)
1246 bonobo_ui_util_set_ui (ui_component, "", mdi->priv->ui_file_name,
1247 mdi->priv->mdi_name, NULL);
1250 if (mdi->priv->verbs)
1251 bonobo_ui_component_add_verb_list_with_data (ui_component,
1252 mdi->priv->verbs, mdi);
1254 mdi->priv->active_window = bw;
1255 mdi->priv->active_child = NULL;
1256 mdi->priv->active_view = NULL;
1258 window_info = g_new0 (BonoboMDIWindowInfo, 1);
1260 g_object_set_data (G_OBJECT (bw), UI_COMPONENT_KEY, ui_component);
1261 g_object_set_data_full (G_OBJECT (bw), WINDOW_INFO_KEY, window_info, g_free);
1263 g_signal_emit (G_OBJECT (mdi), mdi_signals [TOP_WINDOW_CREATED], 0, window);
1265 child_list_menu_create (mdi, bw);
1267 gl_debug (DEBUG_MDI, "END");
1271 set_active_view (BonoboMDI *mdi, GtkWidget *view)
1273 BonoboMDIChild *old_child;
1274 GtkWidget *old_view;
1276 gl_debug (DEBUG_MDI, "");
1278 old_child = mdi->priv->active_child;
1279 old_view = mdi->priv->active_view;
1281 mdi->priv->active_view = view;
1284 mdi->priv->active_child = NULL;
1288 mdi->priv->active_child = bonobo_mdi_get_child_from_view (view);
1289 mdi->priv->active_window = bonobo_mdi_get_window_from_view (view);
1291 gtk_widget_grab_focus (GTK_WIDGET (view));
1294 if (view == old_view)
1296 gl_debug (DEBUG_MDI, "END1");
1301 if (mdi->priv->active_child != old_child)
1303 gl_debug (DEBUG_MDI, "Emit child_changed");
1305 g_signal_emit (G_OBJECT (mdi), mdi_signals [CHILD_CHANGED], 0, old_child);
1308 gl_debug (DEBUG_MDI, "Emit view_changed");
1310 g_signal_emit (G_OBJECT (mdi), mdi_signals [VIEW_CHANGED], 0, old_view);
1312 gl_debug (DEBUG_MDI, "END2");
1316 * bonobo_mdi_set_active_view:
1317 * @mdi: A pointer to an MDI object.
1318 * @view: A pointer to the view that is to become the active one.
1321 * Sets the active view to @view. It also raises the window containing it
1322 * and gives it focus.
1325 bonobo_mdi_set_active_view (BonoboMDI *mdi, GtkWidget *view)
1329 gl_debug (DEBUG_MDI, "");
1331 g_return_if_fail (mdi != NULL);
1332 g_return_if_fail (BONOBO_IS_MDI (mdi));
1333 g_return_if_fail (view != NULL);
1334 g_return_if_fail (GTK_IS_WIDGET (view));
1336 set_page_by_widget (GTK_NOTEBOOK (view->parent), view);
1338 window = GTK_WINDOW (bonobo_mdi_get_window_from_view (view));
1340 gtk_window_present (window);
1342 set_active_view (mdi, view);
1344 gl_debug (DEBUG_MDI, "END");
1348 * bonobo_mdi_add_view:
1349 * @mdi: A pointer to a BonoboMDI object.
1350 * @child: A pointer to a child.
1353 * Creates a new view of the child and adds it to the MDI. BonoboMDIChild
1354 * @child has to be added to the MDI with a call to bonobo_mdi_add_child
1355 * before its views are added to the MDI.
1356 * An "add_view" signal is emitted to the MDI after the view has been
1357 * created, but before it is shown and added to the MDI, with a pointer to
1358 * the created view as its parameter. The view is added to the MDI only if
1359 * the signal handler (if it exists) returns %TRUE. If the handler returns
1360 * %FALSE, the created view is destroyed and not added to the MDI.
1363 * %TRUE if adding the view succeeded and %FALSE otherwise.
1366 bonobo_mdi_add_view (BonoboMDI *mdi, BonoboMDIChild *child)
1372 gl_debug (DEBUG_MDI, "");
1374 g_return_val_if_fail (mdi != NULL, FALSE);
1375 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
1376 g_return_val_if_fail (child != NULL, FALSE);
1377 g_return_val_if_fail (BONOBO_IS_MDI_CHILD (child), FALSE);
1379 view = bonobo_mdi_child_add_view (child);
1381 g_return_val_if_fail (view != NULL, FALSE);
1383 g_signal_emit (G_OBJECT (mdi), mdi_signals [ADD_VIEW], 0, view, &ret);
1387 bonobo_mdi_child_remove_view (child, view);
1389 gl_debug (DEBUG_MDI, "END1");
1394 if (mdi->priv->active_window == NULL)
1396 app_create (mdi, NULL, NULL);
1397 gtk_widget_show (GTK_WIDGET (mdi->priv->active_window));
1401 if (!GTK_WIDGET_VISIBLE (view))
1402 gtk_widget_show (view);
1404 book = get_book_from_window (mdi->priv->active_window);
1407 book = book_create (mdi);
1409 book_add_view (GTK_NOTEBOOK (book), view);
1411 /* this reference will compensate the view's unrefing
1412 when removed from its parent later, as we want it to
1413 stay valid until removed from the child with a call
1414 to bonobo_mdi_child_remove_view() */
1415 g_object_ref (G_OBJECT (view));
1416 gtk_object_sink (GTK_OBJECT (view));
1418 g_object_set_data (G_OBJECT (view), BONOBO_MDI_CHILD_KEY, child);
1420 gl_debug (DEBUG_MDI, "END2");
1426 * bonobo_mdi_add_toplevel_view:
1427 * @mdi: A pointer to a BonoboMDI object.
1428 * @child: A pointer to a BonoboMDIChild object to be added to the MDI.
1429 * @window_role: X window role to use for the window, for session-management
1430 * purposes. If this is %NULL, a unique role string will be automatically
1434 * Creates a new view of the child and adds it to the MDI; it behaves the
1435 * same way as bonobo_mdi_add_view in %BONOBO_MDI_MODAL and %BONOBO_MDI_TOPLEVEL
1436 * modes, but in %BONOBO_MDI_NOTEBOOK mode, the view is added in a new
1437 * toplevel window unless the active one has no views in it.
1440 * %TRUE if adding the view succeeded and %FALSE otherwise.
1443 bonobo_mdi_add_toplevel_view (BonoboMDI *mdi, BonoboMDIChild *child, const char *window_role)
1448 gl_debug (DEBUG_MDI, "");
1450 g_return_val_if_fail (mdi != NULL, FALSE);
1451 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
1452 g_return_val_if_fail (child != NULL, FALSE);
1453 g_return_val_if_fail (BONOBO_IS_MDI_CHILD (child), FALSE);
1455 view = bonobo_mdi_child_add_view (child);
1457 g_return_val_if_fail (view != NULL, FALSE);
1459 g_signal_emit (G_OBJECT (mdi), mdi_signals [ADD_VIEW], 0, view, &ret);
1463 bonobo_mdi_child_remove_view (child, view);
1465 gl_debug (DEBUG_MDI, "END1");
1470 bonobo_mdi_open_toplevel (mdi, window_role);
1472 if (!GTK_WIDGET_VISIBLE (view))
1473 gtk_widget_show (view);
1475 book_add_view (GTK_NOTEBOOK (get_book_from_window (mdi->priv->active_window)), view);
1477 /* this reference will compensate the view's unrefing
1478 when removed from its parent later, as we want it to
1479 stay valid until removed from the child with a call
1480 to bonobo_mdi_child_remove_view() */
1481 g_object_ref (G_OBJECT (view));
1482 gtk_object_sink (GTK_OBJECT (view));
1484 g_object_set_data (G_OBJECT (view), BONOBO_MDI_CHILD_KEY, child);
1486 gl_debug (DEBUG_MDI, "END2");
1492 * bonobo_mdi_remove_view:
1493 * @mdi: A pointer to a BonoboMDI object.
1494 * @view: View to remove.
1495 * @force: If TRUE, the "remove_view" signal is not emitted.
1498 * Removes a view from an MDI.
1499 * A "remove_view" signal is emitted to the MDI before actually removing
1500 * view. The view is removed only if the signal handler (if it exists and
1501 * the @force is set to %FALSE) returns %TRUE.
1504 * %TRUE if the view was removed and %FALSE otherwise.
1507 bonobo_mdi_remove_view (BonoboMDI *mdi, GtkWidget *view, gint force)
1510 BonoboWindow *window;
1511 BonoboMDIChild *child;
1514 gboolean was_active_window = FALSE;
1516 gl_debug (DEBUG_MDI, "");
1518 g_return_val_if_fail (mdi != NULL, FALSE);
1519 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
1520 g_return_val_if_fail (view != NULL, FALSE);
1521 g_return_val_if_fail (GTK_IS_WIDGET (view), FALSE);
1524 g_signal_emit (G_OBJECT (mdi), mdi_signals [REMOVE_VIEW], 0, view, &ret);
1528 gl_debug (DEBUG_MDI, "END1");
1533 was_active_window = (view == mdi->priv->active_view);
1535 child = bonobo_mdi_get_child_from_view (view);
1536 window = bonobo_mdi_get_window_from_view (view);
1538 book = get_book_from_window (window);
1539 g_return_val_if_fail (book != NULL, TRUE);
1541 if (g_list_length (GTK_NOTEBOOK (book)->children) == 1)
1542 app_set_view (mdi, window, NULL);
1544 bonobo_mdi_child_remove_view (child, view);
1546 pn = gtk_notebook_page_num (GTK_NOTEBOOK (book), view);
1547 gtk_notebook_remove_page (GTK_NOTEBOOK (book), pn);
1549 if (GTK_NOTEBOOK (book)->cur_page == NULL)
1551 if ((g_list_length (mdi->priv->windows) > 1) ||
1552 (mdi->priv->registered != NULL))
1554 gl_debug (DEBUG_VIEW, "Destroy window");
1556 /* if this is NOT the last toplevel or a registered object
1557 exists, destroy the toplevel */
1558 mdi->priv->windows = g_list_remove (mdi->priv->windows, window);
1559 gtk_widget_destroy (GTK_WIDGET (window));
1561 if (mdi->priv->active_window && was_active_window)
1562 mdi->priv->active_view = bonobo_mdi_get_view_from_window (
1564 mdi->priv->active_window);
1569 pn = gtk_notebook_get_current_page (GTK_NOTEBOOK (book));
1570 app_set_view (mdi, window, gtk_notebook_get_nth_page (GTK_NOTEBOOK (book), pn));
1574 gl_debug (DEBUG_MDI, "END2");
1580 child_name_changed (BonoboMDIChild *mdi_child, gchar* old_name, BonoboMDI *mdi)
1582 bonobo_mdi_update_child (mdi, mdi_child);
1586 * bonobo_mdi_add_child:
1587 * @mdi: A pointer to a BonoboMDI object.
1588 * @child: A pointer to a BonoboMDIChild to add to the MDI.
1591 * Adds a new child to the MDI. No views are added: this has to be done with
1592 * a call to bonobo_mdi_add_view.
1593 * First an "add_child" signal is emitted to the MDI with a pointer to the
1594 * child as its parameter. The child is added to the MDI only if the signal
1595 * handler (if it exists) returns %TRUE. If the handler returns %FALSE, the
1596 * child is not added to the MDI.
1599 * %TRUE if the child was added successfully and %FALSE otherwise.
1602 bonobo_mdi_add_child (BonoboMDI *mdi, BonoboMDIChild *child)
1606 gl_debug (DEBUG_MDI, "");
1608 g_return_val_if_fail (mdi != NULL, FALSE);
1609 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
1610 g_return_val_if_fail (child != NULL, FALSE);
1611 g_return_val_if_fail (BONOBO_IS_MDI_CHILD (child), FALSE);
1613 g_signal_emit (G_OBJECT (mdi), mdi_signals [ADD_CHILD], 0, child, &ret);
1617 gl_debug (DEBUG_MDI, "END1");
1622 bonobo_mdi_child_set_parent (child, G_OBJECT (mdi));
1624 mdi->priv->children = g_list_append (mdi->priv->children, child);
1626 g_signal_connect (G_OBJECT (child), "name_changed",
1627 G_CALLBACK (child_name_changed), mdi);
1629 child_list_menu_add_item (mdi, child);
1631 g_object_set_data (G_OBJECT (child), BONOBO_MDI_KEY, mdi);
1633 gl_debug (DEBUG_MDI, "END2");
1639 * bonobo_mdi_remove_child:
1640 * @mdi: A pointer to a BonoboMDI object.
1641 * @child: Child to remove.
1642 * @force: If TRUE, the "remove_child" signal is not emitted
1645 * Removes a child and all of its views from the MDI.
1646 * A "remove_child" signal is emitted to the MDI with @child as its parameter
1647 * before actually removing the child. The child is removed only if the signal
1648 * handler (if it exists and the @force is set to %FALSE) returns %TRUE.
1651 * %TRUE if the removal was successful and %FALSE otherwise.
1654 bonobo_mdi_remove_child (BonoboMDI *mdi, BonoboMDIChild *child, gint force)
1660 gl_debug (DEBUG_MDI, "");
1662 g_return_val_if_fail (mdi != NULL, FALSE);
1663 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
1664 g_return_val_if_fail (child != NULL, FALSE);
1665 g_return_val_if_fail (BONOBO_IS_MDI_CHILD (child), FALSE);
1667 /* if force is set to TRUE, don't call the remove_child handler (ie there is no way for the
1668 user to stop removal of the child) */
1671 g_signal_emit (G_OBJECT (mdi), mdi_signals [REMOVE_CHILD], 0, child, &ret);
1675 gl_debug (DEBUG_MDI, "END1");
1680 view_node = bonobo_mdi_child_get_views (child);
1684 view = GTK_WIDGET (view_node->data);
1685 view_node = view_node->next;
1686 bonobo_mdi_remove_view (mdi, GTK_WIDGET (view), TRUE);
1689 mdi->priv->children = g_list_remove (mdi->priv->children, child);
1691 child_list_menu_remove_item (mdi, child);
1693 if (child == mdi->priv->active_child)
1694 mdi->priv->active_child = NULL;
1696 bonobo_mdi_child_set_parent (child, NULL);
1698 g_signal_handlers_disconnect_by_func (G_OBJECT (child), G_CALLBACK (child_name_changed), mdi);
1700 g_object_unref (G_OBJECT (child));
1702 gl_debug (DEBUG_MDI, "END2");
1708 * bonobo_mdi_remove_all:
1709 * @mdi: A pointer to a BonoboMDI object.
1710 * @force: If TRUE, the "remove_child" signal is not emitted
1713 * Removes all children and all views from the MDI.
1714 * A "remove_child" signal is emitted to the MDI for each child before
1715 * actually trying to remove any. If signal handlers for all children (if
1716 * they exist and the @force is set to %FALSE) return %TRUE, all children
1717 * and their views are removed and none otherwise.
1720 * %TRUE if the removal was successful and %FALSE otherwise.
1723 bonobo_mdi_remove_all (BonoboMDI *mdi, gint force)
1726 gint handler_ret = TRUE;
1728 gl_debug (DEBUG_MDI, "");
1730 g_return_val_if_fail (mdi != NULL, FALSE);
1731 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
1733 /* first check if removal of any child will be prevented by the
1734 remove_child signal handler */
1737 child_node = mdi->priv->children;
1740 g_signal_emit (G_OBJECT (mdi),
1741 mdi_signals [REMOVE_CHILD],
1746 /* if any of the children may not be removed, none will be */
1747 if (handler_ret == FALSE)
1749 gl_debug (DEBUG_MDI, "END1");
1754 child_node = child_node->next;
1758 /* remove all the children with force arg set to true so that remove_child
1759 handlers are not called again */
1760 while (mdi->priv->children)
1761 bonobo_mdi_remove_child (mdi, BONOBO_MDI_CHILD (mdi->priv->children->data), TRUE);
1763 gl_debug (DEBUG_MDI, "END2");
1769 * bonobo_mdi_open_toplevel:
1770 * @mdi: A pointer to a BonoboMDI object.
1771 * @window_role: X window role to use for the window, for session-management
1772 * purposes. If this is %NULL, a unique role string will be automatically
1776 * Opens a new toplevel window. This is usually used only for opening
1777 * the initial window on startup (just before calling gtkmain()) if no
1778 * windows were open because a session was restored or children were added
1779 * because of command line args).
1782 bonobo_mdi_open_toplevel (BonoboMDI *mdi, const char *window_role)
1784 gl_debug (DEBUG_MDI, "");
1786 g_return_if_fail (mdi != NULL);
1787 g_return_if_fail (BONOBO_IS_MDI (mdi));
1789 app_clone (mdi, mdi->priv->active_window, window_role);
1793 gtk_widget_show (GTK_WIDGET (mdi->priv->active_window));
1795 gl_debug (DEBUG_MDI, "END1");
1799 * bonobo_mdi_update_child:
1800 * @mdi: A pointer to a BonoboMDI object.
1801 * @child: Child to update.
1804 * Updates all notebook labels of @child's views and their window titles
1805 * after its name changes. It is not required if bonobo_mdi_child_set_name()
1806 * is used for setting the child's name.
1809 bonobo_mdi_update_child (BonoboMDI *mdi, BonoboMDIChild *child)
1811 GtkWidget *view, *title;
1814 gchar* child_name, *path, *path_cmd, *tip, *escaped_name;
1816 gl_debug (DEBUG_MDI, "");
1818 g_return_if_fail (mdi != NULL);
1819 g_return_if_fail (BONOBO_IS_MDI (mdi));
1820 g_return_if_fail (child != NULL);
1821 g_return_if_fail (BONOBO_IS_MDI_CHILD (child));
1823 view_node = bonobo_mdi_child_get_views (child);
1827 view = GTK_WIDGET (view_node->data);
1829 title = child_set_label (child, NULL);
1831 gtk_notebook_set_tab_label (GTK_NOTEBOOK (view->parent), view, title);
1833 view_node = g_list_next (view_node);
1836 /* Update child list menus */
1837 if(mdi->priv->child_list_path == NULL)
1839 gl_debug (DEBUG_MDI, "END1");
1844 win_node = mdi->priv->windows;
1846 child_name = bonobo_mdi_child_get_name (child);
1847 escaped_name = escape_underscores (child_name);
1848 path = g_strdup_printf ("%sChild_%p", mdi->priv->child_list_path, child);
1849 path_cmd = g_strdup_printf ("/commands/Child_%p", child);
1850 tip = g_strdup_printf (_("Activate %s"), child_name);
1854 BonoboUIComponent *ui_component;
1856 ui_component = BONOBO_UI_COMPONENT (
1857 g_object_get_data (G_OBJECT (win_node->data), UI_COMPONENT_KEY));
1859 bonobo_ui_component_set_prop (ui_component, path, "label", escaped_name, NULL);
1860 bonobo_ui_component_set_prop (ui_component, path, "tip", tip, NULL);
1862 win_node = g_list_next (win_node);
1865 g_free (escaped_name);
1869 g_free (child_name);
1871 gl_debug (DEBUG_MDI, "END2");
1875 * bonobo_mdi_find_child:
1876 * @mdi: A pointer to a BonoboMDI object.
1877 * @name: A string with a name of the child to find.
1880 * Finds a child named @name.
1883 * A pointer to the BonoboMDIChild object if the child was found and NULL
1887 bonobo_mdi_find_child (BonoboMDI *mdi, const gchar *name)
1891 gl_debug (DEBUG_MDI, "");
1893 g_return_val_if_fail (mdi != NULL, NULL);
1894 g_return_val_if_fail (BONOBO_IS_MDI (mdi), NULL);
1896 child_node = mdi->priv->children;
1899 gchar* child_name = bonobo_mdi_child_get_name (BONOBO_MDI_CHILD (child_node->data));
1901 if (strcmp (child_name, name) == 0)
1903 g_free (child_name);
1905 gl_debug (DEBUG_MDI, "END1");
1907 return BONOBO_MDI_CHILD (child_node->data);
1910 g_free (child_name);
1912 child_node = g_list_next (child_node);
1915 gl_debug (DEBUG_MDI, "END2");
1921 * bonobo_mdi_get_active_child:
1922 * @mdi: A pointer to a BonoboMDI object.
1925 * Returns a pointer to the active BonoboMDIChild object.
1928 * A pointer to the active BonoboMDIChild object. %NULL, if there is none.
1931 bonobo_mdi_get_active_child (BonoboMDI *mdi)
1933 g_return_val_if_fail (mdi != NULL, NULL);
1934 g_return_val_if_fail (BONOBO_IS_MDI (mdi), NULL);
1936 if (mdi->priv->active_view)
1937 return (bonobo_mdi_get_child_from_view (mdi->priv->active_view));
1943 * bonobo_mdi_get_active_view:
1944 * @mdi: A pointer to a BonoboMDI object.
1947 * Returns a pointer to the active view (the one with the focus).
1950 * A pointer to a GtkWidget *.
1953 bonobo_mdi_get_active_view (BonoboMDI *mdi)
1955 g_return_val_if_fail (mdi != NULL, NULL);
1956 g_return_val_if_fail (BONOBO_IS_MDI (mdi), NULL);
1958 return mdi->priv->active_view;
1962 * bonobo_mdi_get_active_window:
1963 * @mdi: A pointer to a BonoboMDI object.
1966 * Returns a pointer to the toplevel window containing the active view.
1969 * A pointer to a BonoboWindow that has the focus.
1972 bonobo_mdi_get_active_window (BonoboMDI *mdi)
1974 g_return_val_if_fail (mdi != NULL, NULL);
1975 g_return_val_if_fail (BONOBO_IS_MDI (mdi), NULL);
1977 return mdi->priv->active_window;
1981 bonobo_mdi_set_ui_template (BonoboMDI *mdi, const gchar *xml, BonoboUIVerb verbs[])
1983 g_return_if_fail (mdi != NULL);
1984 g_return_if_fail (BONOBO_IS_MDI (mdi));
1985 g_return_if_fail (xml != NULL);
1987 if (mdi->priv->ui_xml != NULL)
1988 g_free (mdi->priv->ui_xml);
1990 mdi->priv->ui_xml = g_strdup (xml);
1993 mdi->priv->verbs = verbs;
1997 bonobo_mdi_set_ui_template_file (BonoboMDI *mdi, const gchar *file_name, BonoboUIVerb verbs[])
1999 g_return_if_fail (mdi != NULL);
2000 g_return_if_fail (BONOBO_IS_MDI (mdi));
2001 g_return_if_fail (file_name != NULL);
2003 if (mdi->priv->ui_file_name != NULL)
2004 g_free (mdi->priv->ui_file_name);
2006 mdi->priv->ui_file_name = g_strdup (file_name);
2009 mdi->priv->verbs = verbs;
2013 * bonobo_mdi_set_child_list_path:
2014 * @mdi: A pointer to a BonoboMDI object.
2015 * @path: A menu path where the child list menu should be inserted
2018 * Sets the position for insertion of menu items used to activate the MDI
2019 * children that were added to the MDI. See gnome_app_find_menu_pos for
2020 * details on menu paths. If the path is not set or set to %NULL, these menu
2021 * items aren't going to be inserted in the MDI menu structure. Note that if
2022 * you want all menu items to be inserted in their own submenu, you have to
2023 * create that submenu (and leave it empty, of course).
2026 bonobo_mdi_set_child_list_path (BonoboMDI *mdi, const gchar *path)
2028 g_return_if_fail (mdi != NULL);
2029 g_return_if_fail (BONOBO_IS_MDI (mdi));
2031 if (mdi->priv->child_list_path)
2032 g_free (mdi->priv->child_list_path);
2034 mdi->priv->child_list_path = g_strdup (path);
2038 * bonobo_mdi_register:
2039 * @mdi: A pointer to a BonoboMDI object.
2040 * @object: Object to register.
2043 * Registers GObject @object with MDI.
2044 * This is mostly intended for applications that open other windows besides
2045 * those opened by the MDI and want to continue to run even when no MDI
2046 * windows exist (an example of this would be GIMP's window with tools, if
2047 * the pictures were MDI children). As long as there is an object registered
2048 * with the MDI, the MDI will not destroy itself when the last of its windows
2049 * is closed. If no objects are registered, closing the last MDI window
2050 * results in MDI being destroyed.
2053 bonobo_mdi_register (BonoboMDI *mdi, GObject *object)
2055 if (!g_slist_find (mdi->priv->registered, object))
2056 mdi->priv->registered = g_slist_append (mdi->priv->registered, object);
2060 * bonobo_mdi_unregister:
2061 * @mdi: A pointer to a BonoboMDI object.
2062 * @object: Object to unregister.
2065 * Removes GObject @object from the list of registered objects.
2068 bonobo_mdi_unregister (BonoboMDI *mdi, GObject *object)
2070 mdi->priv->registered = g_slist_remove (mdi->priv->registered, object);
2074 * bonobo_mdi_get_child_from_view:
2075 * @view: A pointer to a GtkWidget.
2078 * Returns a child that @view is a view of.
2081 * A pointer to the BonoboMDIChild the view belongs to.
2084 bonobo_mdi_get_child_from_view (GtkWidget *view)
2086 return BONOBO_MDI_CHILD (g_object_get_data (G_OBJECT(view), BONOBO_MDI_CHILD_KEY));
2090 * bonobo_mdi_get_window_from_view:
2091 * @view: A pointer to a GtkWidget.
2094 * Returns the toplevel window for this view.
2097 * A pointer to the BonoboWindow containg the specified view.
2100 bonobo_mdi_get_window_from_view (GtkWidget *view)
2102 return BONOBO_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
2106 * bonobo_mdi_get_view_from_window:
2107 * @mdi: A pointer to a BonoboMDI object.
2108 * @win: A pointer to a BonoboWindow widget.
2111 * Returns the pointer to the view in the MDI toplevel window @win.
2112 * If the mode is set to %GNOME_MDI_NOTEBOOK, the view in the current
2116 * A pointer to a view.
2119 bonobo_mdi_get_view_from_window (BonoboMDI *mdi, BonoboWindow *win)
2123 gl_debug (DEBUG_MDI, "");
2125 g_return_val_if_fail (mdi != NULL, NULL);
2126 g_return_val_if_fail (BONOBO_IS_MDI (mdi), NULL);
2127 g_return_val_if_fail (win != NULL, NULL);
2128 g_return_val_if_fail (BONOBO_IS_WINDOW (win), NULL);
2130 book = get_book_from_window (win);
2131 g_return_val_if_fail (book != NULL, NULL);
2133 if (GTK_NOTEBOOK (book)->cur_page)
2135 int cur_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (book));
2137 gl_debug (DEBUG_MDI, "END1");
2139 return gtk_notebook_get_nth_page (GTK_NOTEBOOK (book), cur_page);
2143 gl_debug (DEBUG_MDI, "END2");
2150 bonobo_mdi_construct (BonoboMDI *mdi, const gchar* name, const gchar* title,
2151 gint default_window_width, gint default_window_height)
2153 g_return_if_fail (mdi->priv->mdi_name == NULL);
2154 g_return_if_fail (mdi->priv->title == NULL);
2156 g_return_if_fail (name != NULL);
2157 g_return_if_fail (title != NULL);
2159 mdi->priv->mdi_name = g_strdup (name);
2160 mdi->priv->title = g_strdup (title);
2162 mdi->priv->default_window_width = default_window_width;
2163 mdi->priv->default_window_height = default_window_height;
2168 bonobo_mdi_get_children (BonoboMDI *mdi)
2170 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
2172 return mdi->priv->children;
2176 bonobo_mdi_get_windows (BonoboMDI *mdi)
2178 g_return_val_if_fail (BONOBO_IS_MDI (mdi), FALSE);
2180 return mdi->priv->windows;
2186 bonobo_mdi_get_ui_component_from_window (BonoboWindow* win)
2188 return BONOBO_UI_COMPONENT (
2189 g_object_get_data (G_OBJECT (win), UI_COMPONENT_KEY));
2192 const BonoboMDIWindowInfo *
2193 bonobo_mdi_get_window_info (BonoboWindow *win)
2195 return (const BonoboMDIWindowInfo *)
2196 g_object_get_data (G_OBJECT (win), WINDOW_INFO_KEY);