aboutsummaryrefslogtreecommitdiffstats
path: root/shell/e-shell-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/e-shell-window.c')
-rw-r--r--shell/e-shell-window.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c
new file mode 100644
index 0000000000..123a6175c7
--- /dev/null
+++ b/shell/e-shell-window.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-shell-window.c
+ *
+ * Copyright (C) 2003 Ettore Perazzoli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli <ettore@ximian.com>
+ */
+
+/* TODO
+
+ - e_shell_component_maybe_crashed() replacement.
+
+*/
+
+#include <config.h>
+
+#include "e-shell-window.h"
+
+#include "Evolution.h"
+
+#include "e-shell-window-commands.h"
+
+#include <gal/util/e-util.h>
+
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhpaned.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkvbox.h>
+
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-object.h>
+#include <bonobo/bonobo-ui-util.h>
+#include <bonobo/bonobo-widget.h>
+
+#include <string.h>
+
+
+#define PARENT_TYPE gtk_window_get_type ()
+static GtkWindowClass *parent_class = NULL;
+
+
+/* A view for each component. These are all created when EShellWindow is
+ instantiated, but with the widget pointers to NULL and the page number set
+ to -1. When the views are created the first time, the widget pointers as
+ well as the notebook page value get set. */
+struct _ComponentView {
+ char *component_id;
+
+ GNOME_Evolution_Component component_iface;
+
+ GtkWidget *sidebar_widget;
+ GtkWidget *view_widget;
+
+ int notebook_page_num;
+};
+typedef struct _ComponentView ComponentView;
+
+
+struct _EShellWindowPrivate {
+ EShell *shell;
+
+ /* All the ComponentViews. */
+ GSList *component_views;
+
+ /* Notebooks used to switch between components. */
+ GtkWidget *sidebar_notebook;
+ GtkWidget *view_notebook;
+
+ /* Bonobo foo. */
+ BonoboUIComponent *ui_component;
+
+ /* The current view (can be NULL initially). */
+ ComponentView *current_view;
+};
+
+
+/* ComponentView handling. */
+
+static ComponentView *
+component_view_new (const char *id)
+{
+ ComponentView *view = g_new0 (ComponentView, 1);
+
+ view->component_id = g_strdup (id);
+ view->notebook_page_num = -1;
+
+ return view;
+}
+
+static void
+component_view_free (ComponentView *view)
+{
+ g_free (view->component_id);
+ bonobo_object_release_unref (view->component_iface, NULL);
+ g_free (view);
+}
+
+static void
+component_view_deactivate (ComponentView *view)
+{
+ BonoboControlFrame *view_control_frame;
+ BonoboControlFrame *sidebar_control_frame;
+
+ g_return_if_fail (view->sidebar_widget != NULL);
+ g_return_if_fail (view->view_widget != NULL);
+
+ view_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->view_widget));
+ bonobo_control_frame_control_deactivate (view_control_frame);
+
+ sidebar_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->sidebar_widget));
+ bonobo_control_frame_control_deactivate (sidebar_control_frame);
+}
+
+static void
+component_view_activate (ComponentView *view)
+{
+ BonoboControlFrame *view_control_frame;
+ BonoboControlFrame *sidebar_control_frame;
+
+ g_return_if_fail (view->sidebar_widget != NULL);
+ g_return_if_fail (view->view_widget != NULL);
+
+ view_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->view_widget));
+ bonobo_control_frame_control_activate (view_control_frame);
+
+ sidebar_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->sidebar_widget));
+ bonobo_control_frame_control_activate (sidebar_control_frame);
+}
+
+
+/* Utility functions. */
+
+static void
+init_view (EShellWindow *window,
+ ComponentView *view)
+{
+ EShellWindowPrivate *priv = window->priv;
+ Bonobo_UIContainer container;
+ Bonobo_Control sidebar_control;
+ Bonobo_Control view_control;
+ CORBA_Environment ev;
+ int sidebar_notebook_page_num;
+ int view_notebook_page_num;
+
+ g_assert (view->component_iface == CORBA_OBJECT_NIL);
+ g_assert (view->view_widget == NULL);
+ g_assert (view->sidebar_widget == NULL);
+ g_assert (view->notebook_page_num == -1);
+
+ CORBA_exception_init (&ev);
+
+ /* 1. Activate component. (FIXME: Shouldn't do this here.) */
+
+ view->component_iface = bonobo_activation_activate_from_id (view->component_id, 0, NULL, &ev);
+ if (BONOBO_EX (&ev) || view->component_iface == CORBA_OBJECT_NIL) {
+ char *ex_text = bonobo_exception_get_text (&ev);
+ g_warning ("Cannot activate component %s: %s", view->component_id, ex_text);
+ g_free (ex_text);
+
+ view->component_iface = CORBA_OBJECT_NIL;
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ /* 2. Set up view. */
+
+ GNOME_Evolution_Component_createControls (view->component_iface, &sidebar_control, &view_control, &ev);
+ if (BONOBO_EX (&ev)) {
+ g_warning ("Cannot create view for %s", view->component_id);
+
+ /* The rest of the code assumes that the component is valid and can create
+ controls; if this fails something is really wrong in the component
+ (e.g. methods not implemented)... So handle it as if there was no
+ component at all. */
+ bonobo_object_release_unref (view->component_iface, NULL);
+ view->component_iface = CORBA_OBJECT_NIL;
+
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ CORBA_exception_free (&ev);
+
+ container = bonobo_ui_component_get_container (priv->ui_component);
+
+ view->sidebar_widget = bonobo_widget_new_control_from_objref (sidebar_control, container);
+ gtk_widget_show (view->sidebar_widget);
+ bonobo_object_release_unref (sidebar_control, NULL);
+
+ view->view_widget = bonobo_widget_new_control_from_objref (view_control, container);
+ gtk_widget_show (view->view_widget);
+ bonobo_object_release_unref (view_control, NULL);
+
+ gtk_notebook_append_page (GTK_NOTEBOOK (priv->sidebar_notebook), view->sidebar_widget, NULL);
+ gtk_notebook_append_page (GTK_NOTEBOOK (priv->view_notebook), view->view_widget, NULL);
+
+ sidebar_notebook_page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->sidebar_notebook), view->sidebar_widget);
+ view_notebook_page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->view_notebook), view->view_widget);
+
+ /* Since we always add a view page and a sidebar page at the same time... */
+ g_assert (sidebar_notebook_page_num == view_notebook_page_num);
+
+ view->notebook_page_num = view_notebook_page_num;
+
+ /* 3. Switch to the new page. */
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->view_notebook), view_notebook_page_num);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->sidebar_notebook), view_notebook_page_num);
+
+ if (priv->current_view != NULL)
+ component_view_deactivate (priv->current_view);
+ priv->current_view = view;
+ component_view_activate (view);
+}
+
+
+/* Callbacks. */
+
+static void
+component_button_clicked_callback (GtkButton *button,
+ EShellWindow *window)
+{
+ ComponentView *component_view = g_object_get_data (G_OBJECT (button), "ComponentView");
+ EShellWindowPrivate *priv = window->priv;
+
+ g_assert (component_view != NULL);
+
+ if (component_view->sidebar_widget == NULL) {
+ init_view (window, component_view);
+ } else {
+ if (priv->current_view != NULL)
+ component_view_deactivate (priv->current_view);
+ priv->current_view = component_view;
+ component_view_activate (component_view);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->view_notebook), component_view->notebook_page_num);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->sidebar_notebook), component_view->notebook_page_num);
+ }
+}
+
+
+/* Widget layout. */
+
+static GtkWidget *
+create_component_button (EShellWindow *window,
+ ComponentView *component_view)
+{
+ GtkWidget *button;
+ const char *id = component_view->component_id;
+ const char *p, *q;
+ char *label;
+
+ /* FIXME: Need a "name" property on the component or somesuch. */
+
+ p = strrchr (id, '_');
+ if (p == NULL || p == id) {
+ label = g_strdup (id);
+ } else {
+ for (q = p - 1; q != id; q--) {
+ if (*q == '_')
+ break;
+ }
+
+ if (*q != '_') {
+ label = g_strdup (id);
+ } else {
+ label = g_strndup (q + 1, p - q - 1);
+ }
+ }
+
+ button = gtk_button_new_with_label (label);
+
+ g_object_set_data (G_OBJECT (button), "ComponentView", component_view);
+ g_signal_connect (button, "clicked", G_CALLBACK (component_button_clicked_callback), window);
+
+ g_free (label);
+
+ return button;
+}
+
+static void
+setup_widgets (EShellWindow *window)
+{
+ EShellWindowPrivate *priv = window->priv;
+ Bonobo_ServerInfoList *info_list;
+ CORBA_Environment ev;
+ GtkWidget *paned;
+ GtkWidget *sidebar_vbox;
+ GtkWidget *button_box;
+ int i;
+
+ paned = gtk_hpaned_new ();
+ bonobo_window_set_contents (BONOBO_WINDOW (window), paned);
+
+ sidebar_vbox = gtk_vbox_new (FALSE, 6);
+ gtk_paned_pack1 (GTK_PANED (paned), sidebar_vbox, FALSE, FALSE);
+
+ priv->sidebar_notebook = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->sidebar_notebook), FALSE);
+ gtk_box_pack_start (GTK_BOX (sidebar_vbox), priv->sidebar_notebook, TRUE, TRUE, 0);
+
+ priv->view_notebook = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->view_notebook), FALSE);
+ gtk_paned_pack2 (GTK_PANED (paned), priv->view_notebook, TRUE, FALSE);
+
+ button_box = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (sidebar_vbox), button_box, FALSE, FALSE, 0);
+
+ CORBA_exception_init (&ev);
+
+ /* FIXME: Shouldn't be doing this here. */
+
+ info_list = bonobo_activation_query ("repo_ids.has ('IDL:GNOME/Evolution/Component:1.0')", NULL, &ev);
+ if (BONOBO_EX (&ev)) {
+ char *ex_text = bonobo_exception_get_text (&ev);
+ g_warning ("Cannot query for components: %s\n", ex_text);
+ g_free (ex_text);
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ for (i = 0; i < info_list->_length; i++) {
+ ComponentView *component_view = component_view_new (info_list->_buffer[i].iid);
+ GtkWidget *component_button = create_component_button (window, component_view);
+
+ priv->component_views = g_slist_prepend (priv->component_views, component_view);
+
+ gtk_box_pack_start (GTK_BOX (button_box), component_button, FALSE, FALSE, 0);
+ }
+
+ CORBA_free (info_list);
+ CORBA_exception_free (&ev);
+
+ gtk_widget_show_all (paned);
+}
+
+
+/* GObject methods. */
+
+static void
+impl_dispose (GObject *object)
+{
+ EShellWindowPrivate *priv = E_SHELL_WINDOW (object)->priv;
+
+ if (priv->shell != NULL) {
+ g_object_remove_weak_pointer (G_OBJECT (priv->shell), (void **) &priv->shell);
+ priv->shell = NULL;
+ }
+
+ if (priv->ui_component != NULL) {
+ bonobo_object_unref (BONOBO_OBJECT (priv->ui_component));
+ priv->ui_component = NULL;
+ }
+
+ (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+static void
+impl_finalize (GObject *object)
+{
+ EShellWindowPrivate *priv = E_SHELL_WINDOW (object)->priv;
+
+ g_slist_foreach (priv->component_views, (GFunc) component_view_free, NULL);
+ g_slist_free (priv->component_views);
+
+ g_free (priv);
+
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+
+/* Initialization. */
+
+static void
+class_init (EShellWindowClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = impl_dispose;
+ object_class->finalize = impl_finalize;
+
+ parent_class = g_type_class_peek_parent (class);
+}
+
+static void
+init (EShellWindow *shell_window)
+{
+ EShellWindowPrivate *priv = g_new0 (EShellWindowPrivate, 1);
+
+ shell_window->priv = priv;
+}
+
+
+/* Instantiation. */
+
+GtkWidget *
+e_shell_window_new (EShell *shell)
+{
+ EShellWindow *window = g_object_new (e_shell_window_get_type (), NULL);
+ EShellWindowPrivate *priv = window->priv;
+ BonoboUIContainer *ui_container;
+
+ if (bonobo_window_construct (BONOBO_WINDOW (window),
+ bonobo_ui_container_new (),
+ "evolution", "Ximian Evolution") == NULL) {
+ g_object_unref (window);
+ return NULL;
+ }
+
+ window->priv->shell = shell;
+ g_object_add_weak_pointer (G_OBJECT (shell), (void **) &window->priv->shell);
+
+ /* FIXME TODO: Add system_exception signal handling and all the other
+ stuff from e_shell_view_construct(). */
+
+ ui_container = bonobo_window_get_ui_container (BONOBO_WINDOW (window));
+
+ priv->ui_component = bonobo_ui_component_new ("evolution");
+ bonobo_ui_component_set_container (priv->ui_component,
+ bonobo_object_corba_objref (BONOBO_OBJECT (ui_container)),
+ NULL);
+
+ bonobo_ui_util_set_ui (priv->ui_component,
+ PREFIX,
+ EVOLUTION_UIDIR "/evolution.xml",
+ "evolution-1.4", NULL);
+
+ e_shell_window_commands_setup (window);
+
+ setup_widgets (window);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
+
+ return GTK_WIDGET (window);
+}
+
+
+EShell *
+e_shell_window_peek_shell (EShellWindow *window)
+{
+ return window->priv->shell;
+}
+
+
+BonoboUIComponent *
+e_shell_window_peek_bonobo_ui_component (EShellWindow *window)
+{
+ return window->priv->ui_component;
+}
+
+void
+e_shell_window_save_defaults (EShellWindow *window)
+{
+ /* FIXME */
+ g_warning ("e_shell_window_save_defaults() unimplemented");
+}
+
+void
+e_shell_window_show_settings (EShellWindow *window)
+{
+ g_return_if_fail (E_IS_SHELL_WINDOW (window));
+
+ e_shell_show_settings (window->priv->shell, NULL, window);
+}
+
+
+E_MAKE_TYPE (e_shell_window, "EShellWindow", EShellWindow, class_init, init, BONOBO_TYPE_WINDOW)