summaryrefslogtreecommitdiffhomepage
path: root/mixgtk/mixgtk_wm.c
diff options
context:
space:
mode:
Diffstat (limited to 'mixgtk/mixgtk_wm.c')
-rw-r--r--mixgtk/mixgtk_wm.c573
1 files changed, 573 insertions, 0 deletions
diff --git a/mixgtk/mixgtk_wm.c b/mixgtk/mixgtk_wm.c
new file mode 100644
index 0000000..7821d0e
--- /dev/null
+++ b/mixgtk/mixgtk_wm.c
@@ -0,0 +1,573 @@
+/* -*-c-*- -------------- mixgtk_wm.c :
+ * Implementation of the functions declared in mixgtk_wm.h
+ * ------------------------------------------------------------------
+ * $Id: mixgtk_wm.c,v 1.12 2005/09/20 19:43:14 jao Exp $
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <string.h>
+
+#include "mixgtk_wm.h"
+
+#include "mixgtk_widgets.h"
+#include "mixgtk_config.h"
+#include "mixgtk_device.h"
+#include "mixgtk_mixvm.h"
+#include "mixgtk_mixal.h"
+#include "mixgtk_widgets.h"
+#include "mixgtk_cmd_dispatcher.h"
+#include "mixgtk.h"
+
+
+typedef struct window_info_t_
+{
+ mixgtk_dialog_id_t dialog;
+ GtkWidget *widget;
+ GtkCheckMenuItem *menu;
+ const gchar *menu_name;
+ const gchar *config_key;
+ gboolean detached;
+ void (*detach) (void);
+ void (*attach) (void);
+} window_info_t_;
+
+static const gchar *DETACH_YES_ = "Yes";
+static const gchar *DETACH_NO_ = "No";
+static GtkWidget *about_ = NULL;
+
+static GtkContainer *mixvm_container_ = NULL;
+static GtkContainer *mixal_container_ = NULL;
+static GtkContainer *dev_container_ = NULL;
+
+static const gchar *TB_MENU_NAME_ = "show_toolbars";
+static GtkCheckMenuItem *tb_menu_ = NULL;
+static GtkNotebook *notebook_ = NULL;
+
+static mix_vm_t *vm_ = NULL;
+
+static void init_info_ (void);
+static void init_notebook_ (void);
+static void init_dispatcher_ (void);
+static void init_mixvm_ (void);
+static void init_mixal_ (void);
+static void init_dev_ (void);
+static void init_signals_ (void);
+static void init_visibility_ (void);
+static void init_tb_ (void);
+static void init_about_ (void);
+static void init_autosave_ (void);
+static void show_toolbars_ (gboolean show);
+static void add_page_ (GtkWidget *w, mixgtk_window_id_t id);
+static void mixvm_attach_ (void);
+static void mixvm_detach_ (void);
+static void mixal_attach_ (void);
+static void mixal_detach_ (void);
+static void dev_attach_ (void);
+static void dev_detach_ (void);
+static void on_nb_switch_ (GtkNotebook *notebook, GtkWidget *page,
+ guint page_num, gpointer user_data);
+
+static window_info_t_ infos_[] = {
+ {MIXGTK_MIXVM_DIALOG, NULL, NULL, "detach_vm", "MIX.detach",
+ FALSE, mixvm_detach_, mixvm_attach_},
+ {MIXGTK_MIXAL_DIALOG, NULL, NULL, "detach_source", "MIXAL.detach",
+ FALSE, mixal_detach_, mixal_attach_},
+ {MIXGTK_DEVICES_DIALOG, NULL, NULL, "detach_dev", "Devices.detach",
+ FALSE, dev_detach_, dev_attach_}
+};
+
+static size_t INF_NO_ = sizeof (infos_) / sizeof (infos_[0]);
+
+
+gboolean
+mixgtk_wm_init (void)
+{
+ gint k;
+
+ init_info_ ();
+ init_notebook_ ();
+ init_dispatcher_ ();
+ init_mixvm_ ();
+ init_mixal_ ();
+ init_dev_ ();
+
+ for (k = 0; k < INF_NO_; ++k)
+ {
+ if (infos_[k].detached)
+ mixgtk_wm_detach_window (k);
+ else
+ mixgtk_wm_attach_window (k);
+ }
+
+ init_tb_ ();
+ init_about_ ();
+ init_autosave_ ();
+ init_visibility_ ();
+ init_signals_ ();
+
+ return TRUE;
+}
+
+void
+mixgtk_wm_detach_window (mixgtk_window_id_t w)
+{
+ if (w < INF_NO_)
+ {
+ (*(infos_[w].detach)) ();
+ infos_[w].detached = TRUE;
+ gtk_check_menu_item_set_active (infos_[w].menu, TRUE);
+ mixgtk_config_update (infos_[w].config_key, DETACH_YES_);
+ if (infos_[w].widget != NULL) gtk_widget_show (infos_[w].widget);
+ if (gtk_notebook_get_n_pages (notebook_) < 1)
+ gtk_widget_hide (GTK_WIDGET (notebook_));
+ gtk_widget_show (mixgtk_widget_factory_get_dialog (infos_[w].dialog));
+ }
+}
+
+void
+mixgtk_wm_attach_window (mixgtk_window_id_t w)
+{
+ if (w < INF_NO_)
+ {
+ gint page = gtk_notebook_page_num (notebook_, infos_[w].widget);
+
+ gtk_widget_hide (mixgtk_widget_factory_get_dialog (infos_[w].dialog));
+
+ if (page < 0) (*(infos_[w].attach)) ();
+
+ infos_[w].detached = FALSE;
+ gtk_check_menu_item_set_active (infos_[w].menu, FALSE);
+ mixgtk_config_update (infos_[w].config_key, DETACH_NO_);
+ if (gtk_notebook_get_n_pages (notebook_) == 1)
+ gtk_widget_show (GTK_WIDGET (notebook_));
+ }
+}
+
+
+
+/* callbacks */
+void
+on_detach_clicked (GtkWidget *ignored)
+{
+ gint page = gtk_notebook_get_current_page (notebook_);
+ if (page >= 0)
+ {
+ gint k;
+ GtkWidget *w = gtk_notebook_get_nth_page (notebook_, page);
+
+ for (k = 0; k < INF_NO_; ++k)
+ if (infos_[k].widget == w) mixgtk_wm_detach_window (k);
+ }
+}
+
+void
+on_attach_all_clicked ()
+{
+ gint k;
+ for (k = INF_NO_; k > 0; --k)
+ if (infos_[k - 1].detached) mixgtk_wm_attach_window (k - 1);
+}
+
+void
+on_attach_toggled (GtkCheckMenuItem *item)
+{
+ gint k;
+ for (k = 0; k < INF_NO_; ++k)
+ if (item == infos_[k].menu) break;
+ g_return_if_fail (k < INF_NO_);
+ if (item->active) mixgtk_wm_detach_window (k);
+ else mixgtk_wm_attach_window (k);
+ mixgtk_config_update (infos_[k].config_key,
+ (item->active)? DETACH_YES_ : DETACH_NO_);
+}
+
+void
+on_window_hide (GtkWidget *w)
+{
+ gint k;
+ for (k = 0; k < INF_NO_; ++k)
+ if (w == mixgtk_widget_factory_get_dialog (infos_[k].dialog)) break;
+ g_return_if_fail (k < INF_NO_);
+ mixgtk_wm_attach_window (k);
+}
+
+void
+on_show_toolbars_toggled (GtkCheckMenuItem *item)
+{
+ if (item->active != mixgtk_config_show_toolbars ())
+ show_toolbars_ (item->active);
+}
+
+void
+on_widget_attach (GtkWidget *ign, gpointer id)
+{
+ mixgtk_wm_attach_window (GPOINTER_TO_INT (id));
+}
+
+
+/* about box */
+void
+on_about_activate (GtkWidget *w, gpointer data)
+{
+ if (!about_) init_about_ ();
+ gtk_widget_show (about_);
+}
+
+
+static void
+init_info_ (void)
+{
+ gint k;
+ for (k = 0; k < INF_NO_; ++k)
+ {
+ const gchar *txt;
+
+ infos_[k].menu =
+ GTK_CHECK_MENU_ITEM
+ (mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN,
+ infos_[k].menu_name));
+ g_assert (infos_[k].menu != NULL);
+ txt = mixgtk_config_get (infos_[k].config_key);
+ infos_[k].detached = txt && !g_ascii_strcasecmp (txt, DETACH_YES_);
+ }
+}
+
+static void
+init_notebook_ (void)
+{
+ notebook_ =
+ GTK_NOTEBOOK (mixgtk_widget_factory_get (MIXGTK_MAIN,
+ MIXGTK_WIDGET_NOTEBOOK));
+ g_assert (notebook_ != NULL);
+ gtk_widget_show (GTK_WIDGET (notebook_));
+}
+
+static void
+add_page_ (GtkWidget *page, mixgtk_window_id_t id)
+{
+ static const gchar *LABELS[] = {
+ N_("_Virtual machine"), N_("_Source"), N_("_Devices")
+ };
+
+ gint p = 0;
+
+ g_assert (page != NULL);
+ g_assert (id < INF_NO_);
+ g_assert (notebook_ != NULL);
+
+ if (id > MIXGTK_MIXVM_WINDOW)
+ {
+ if (id == MIXGTK_DEVICES_WINDOW)
+ p = gtk_notebook_get_n_pages (notebook_);
+ else
+ p = infos_[MIXGTK_MIXVM_WINDOW].detached ? 0 : 1;
+ }
+
+ gtk_notebook_insert_page (notebook_, page,
+ gtk_label_new_with_mnemonic (LABELS[id]),
+ p);
+ gtk_notebook_set_current_page (notebook_, p);
+ gtk_widget_show (page);
+ gtk_widget_show (GTK_WIDGET (notebook_));
+}
+
+static void
+init_signals_ (void)
+{
+ gint k;
+ for (k = 0; k < INF_NO_; ++k)
+ {
+ GObject *dialog =
+ G_OBJECT (mixgtk_widget_factory_get_dialog (infos_[k].dialog));
+
+ GObject *button =
+ G_OBJECT (mixgtk_widget_factory_get (infos_[k].dialog,
+ MIXGTK_WIDGET_ATTACH_BUTTON));
+
+ g_assert (dialog != NULL);
+ g_assert (button != NULL);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (on_widget_attach), GINT_TO_POINTER (k));
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (on_window_hide), NULL);
+ g_signal_connect (dialog, "destroy_event",
+ G_CALLBACK (on_window_hide), NULL);
+ g_signal_connect (dialog, "delete_event",
+ G_CALLBACK (on_window_hide), NULL);
+ g_signal_connect (G_OBJECT (infos_[k].menu), "toggled",
+ G_CALLBACK (on_attach_toggled), NULL);
+ }
+
+}
+
+static void
+init_visibility_ (void)
+{
+ gint k;
+ for (k = 0; k < INF_NO_; ++k)
+ if (infos_[k].detached)
+ gtk_widget_show (mixgtk_widget_factory_get_dialog (infos_[k].dialog));
+
+ if (gtk_notebook_get_n_pages (notebook_) > 0)
+ gtk_notebook_set_current_page (notebook_, 0);
+
+ gtk_widget_show (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN));
+}
+
+static void
+init_dispatcher_ (void)
+{
+ if (!mixgtk_cmd_dispatcher_init (MIXGTK_MAIN))
+ g_assert (FALSE);
+ vm_ = mixgtk_cmd_dispatcher_get_vm ();
+ g_assert (vm_ != NULL);
+}
+
+static void
+init_mixvm_ (void)
+{
+ GtkContainer *vm =
+ GTK_CONTAINER
+ (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, MIXGTK_WIDGET_MIXVM));
+
+ mixvm_container_ =
+ GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
+ MIXGTK_WIDGET_MIXVM_CONTAINER));
+
+ g_assert (mixvm_container_ != NULL);
+
+ g_assert (vm != NULL);
+ g_object_ref (G_OBJECT (vm));
+ infos_[MIXGTK_MIXVM_WINDOW].widget = GTK_WIDGET (vm);
+
+ mixgtk_mixvm_init (vm_);
+ mixgtk_mixvm_update_vm_widgets ();
+
+ gtk_widget_show (GTK_WIDGET (vm));
+
+}
+
+static void
+init_mixal_ (void)
+{
+ GtkWidget *page = gtk_scrolled_window_new (NULL, NULL);
+ GtkWidget *mixal = mixgtk_mixal_init (vm_);
+
+ g_assert (page != NULL);
+ g_assert (mixal != NULL);
+
+ g_object_ref (page);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_container_add (GTK_CONTAINER (page), mixal);
+
+ infos_[MIXGTK_MIXAL_WINDOW].widget = page;
+
+ mixal_container_ =
+ GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_MIXAL_DIALOG,
+ MIXGTK_WIDGET_MIXAL_CONTAINER));
+
+ g_assert (mixal_container_ != NULL);
+
+ gtk_container_add (mixal_container_, page);
+
+ gtk_widget_show (mixal);
+ gtk_widget_show (page);
+ gtk_widget_show (GTK_WIDGET (mixal_container_));
+}
+
+static void
+init_dev_ (void)
+{
+ GtkWidget *page = gtk_scrolled_window_new (NULL, NULL);
+ GtkWidget *devs = mixgtk_device_init (vm_);
+
+ g_assert (page != NULL);
+ g_assert (devs != NULL);
+
+ g_object_ref (page);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (page), devs);
+
+ infos_[MIXGTK_DEVICES_WINDOW].widget = page;
+
+ dev_container_ =
+ GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_DEVICES_DIALOG,
+ MIXGTK_WIDGET_DEV_CONTAINER));
+
+ g_assert (dev_container_ != NULL);
+
+ gtk_container_add (dev_container_, page);
+
+ gtk_widget_show (devs);
+ gtk_widget_show (page);
+}
+
+static void
+init_tb_ (void)
+{
+ tb_menu_ = GTK_CHECK_MENU_ITEM
+ (mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN,
+ TB_MENU_NAME_));
+ g_assert (tb_menu_ != NULL);
+
+ gtk_check_menu_item_set_active (tb_menu_, mixgtk_config_show_toolbars ());
+ show_toolbars_ (mixgtk_config_show_toolbars ());
+
+ g_signal_connect (G_OBJECT (tb_menu_), "toggled",
+ G_CALLBACK (on_show_toolbars_toggled), NULL);
+}
+
+static void
+show_toolbars_ (gboolean show)
+{
+ static const gchar *HANDLE_NAME = "tb_handle";
+
+ int k;
+
+ GtkWidget *handle =
+ mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN, HANDLE_NAME);
+
+ if (show)
+ gtk_widget_show (handle);
+ else
+ gtk_widget_hide (handle);
+
+ for (k = 0; k < INF_NO_; ++k)
+ {
+ GtkWidget *hd =
+ mixgtk_widget_factory_get_child_by_name (infos_[k].dialog, HANDLE_NAME);
+ if (show) gtk_widget_show (hd); else gtk_widget_hide (hd);
+ }
+
+ mixgtk_config_set_show_toolbars (show);
+}
+
+static void
+init_autosave_ (void)
+{
+#define AUTOSAVE_ITEM_ "save_on_exit"
+
+ GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM
+ (mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN, AUTOSAVE_ITEM_));
+ if (item)
+ {
+ gtk_check_menu_item_set_active (item, mixgtk_config_is_autosave ());
+ }
+}
+
+static void
+init_about_ (void)
+{
+#define VERSION_LABEL_ "version_label"
+#define GPL_TEXT_ "gpl_text"
+ GtkWidget *label;
+ about_ = mixgtk_widget_factory_get_dialog (MIXGTK_ABOUT_DIALOG);
+ g_assert (about_ != NULL);
+ label = mixgtk_widget_factory_get_child_by_name (MIXGTK_ABOUT_DIALOG,
+ VERSION_LABEL_);
+ g_assert (label != NULL);
+ gtk_label_set_text (GTK_LABEL (label), VERSION);
+ gtk_widget_show (label);
+}
+
+static void
+mixvm_attach_ (void)
+{
+ gtk_container_remove (mixvm_container_, infos_[MIXGTK_MIXVM_WINDOW].widget);
+ add_page_ (infos_[MIXGTK_MIXVM_WINDOW].widget, MIXGTK_MIXVM_WINDOW);
+}
+
+static void
+mixvm_detach_ (void)
+{
+ gtk_widget_reparent (infos_[MIXGTK_MIXVM_WINDOW].widget,
+ GTK_WIDGET (mixvm_container_));
+}
+
+static void
+mixal_attach_ (void)
+{
+ static GtkStatusbar *stat = NULL;
+
+ if (stat == NULL)
+ {
+ stat =
+ GTK_STATUSBAR
+ (mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_STATUSBAR));
+ g_assert (stat);
+
+ g_signal_connect (G_OBJECT (notebook_), "switch-page",
+ G_CALLBACK (on_nb_switch_), NULL);
+ }
+
+ mixgtk_mixal_reparent (stat);
+ gtk_container_remove (mixal_container_, infos_[MIXGTK_MIXAL_WINDOW].widget);
+ add_page_ (infos_[MIXGTK_MIXAL_WINDOW].widget, MIXGTK_MIXAL_WINDOW);
+}
+
+static void
+mixal_detach_ (void)
+{
+ static GtkStatusbar *stat = NULL;
+
+ if (stat == NULL)
+ {
+ stat =
+ GTK_STATUSBAR
+ (mixgtk_widget_factory_get (MIXGTK_MIXAL_DIALOG,
+ MIXGTK_WIDGET_MIXAL_STATUSBAR));
+ g_assert (stat);
+ }
+
+ mixgtk_mixal_reparent (stat);
+ gtk_widget_reparent (infos_[MIXGTK_MIXAL_WINDOW].widget,
+ GTK_WIDGET (mixal_container_));
+}
+
+static void
+dev_attach_ (void)
+{
+ gtk_container_remove (dev_container_, infos_[MIXGTK_DEVICES_WINDOW].widget);
+ add_page_ (infos_[MIXGTK_DEVICES_WINDOW].widget, MIXGTK_DEVICES_WINDOW);
+}
+
+static void
+dev_detach_ (void)
+{
+ gtk_widget_reparent (infos_[MIXGTK_DEVICES_WINDOW].widget,
+ GTK_WIDGET (dev_container_));
+}
+
+static void
+on_nb_switch_ (GtkNotebook *notebook, GtkWidget *page,
+ guint page_num, gpointer user_data)
+{
+ if (!(infos_[MIXGTK_MIXAL_WINDOW].detached)
+ && (page != infos_[MIXGTK_MIXAL_WINDOW].widget))
+ mixgtk_mixal_pop_status ();
+}
+
+