aboutsummaryrefslogtreecommitdiffstats
path: root/shell/e-user-creatable-items-handler.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2004-04-09 23:46:00 +0800
committerDan Winship <danw@src.gnome.org>2004-04-09 23:46:00 +0800
commit7f2badb024128819fbb1d2656057c5e476100cd8 (patch)
treec13bcea14f62769857b72307f6eef59f183babaa /shell/e-user-creatable-items-handler.c
parentfabe4f1d8ae42c7bf8f1674c98ef4103e2e53bf0 (diff)
downloadgsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.tar
gsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.tar.gz
gsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.tar.bz2
gsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.tar.lz
gsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.tar.xz
gsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.tar.zst
gsoc2013-evolution-7f2badb024128819fbb1d2656057c5e476100cd8.zip
Change this a lot. Now each component will maintain its own
* e-user-creatable-items-handler.c: Change this a lot. Now each component will maintain its own EUserCreatableItemsHandler and merge the button and menus in and out of the UI as its controls are activated and deactivated. (This lets the connector component display the correct default for the New button). Also, update to the Product Design Team's new organization (separating object types from folder types) * e-shell.c: Remove all creatable_items_handler references * e-shell-window.c (e_shell_window_new): Remove creatable_items_handler reference * Makefile.am: Move e-user-creatable-items-handler from evolution to libeshell, and make libeshell depend on libemiscwidgets (for the combo button) * Evolution-Component.idl: add another field to CreatableItemType so we can distinguish object types from folder types. svn path=/trunk/; revision=25379
Diffstat (limited to 'shell/e-user-creatable-items-handler.c')
-rw-r--r--shell/e-user-creatable-items-handler.c746
1 files changed, 407 insertions, 339 deletions
diff --git a/shell/e-user-creatable-items-handler.c b/shell/e-user-creatable-items-handler.c
index d7e4454cf6..ba6c006c8d 100644
--- a/shell/e-user-creatable-items-handler.c
+++ b/shell/e-user-creatable-items-handler.c
@@ -1,7 +1,7 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-shell-user-creatable-items-handler.c
+/* e-user-creatable-items-handler.c
*
- * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2001-2004 Novell, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -27,10 +27,10 @@
#include "e-user-creatable-items-handler.h"
#include "e-shell-utils.h"
-
-#include "widgets/misc/e-combo-button.h"
+#include "Evolution.h"
#include "e-util/e-corba-utils.h"
+#include "widgets/misc/e-combo-button.h"
#include <gal/util/e-util.h>
@@ -40,6 +40,11 @@
#include <libgnome/gnome-i18n.h>
+#include <gtk/gtkaccelgroup.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkimagemenuitem.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkseparatormenuitem.h>
#include <gtk/gtksignal.h>
#include <gtk/gtktooltips.h>
@@ -52,16 +57,8 @@
static GObjectClass *parent_class = NULL;
-#define VERB_PREFIX "ShellUserCreatableItemVerb"
-
-#define EVOLUTION_MAIL_OAFIID "OAFIID:GNOME_Evolution_Mail_ShellComponent:" BASE_VERSION
-
-#define SHELL_WINDOW_KEY "EUserCreatableItemsHandler:shell_window"
-#define COMBO_BUTTON_WIDGET_KEY "EUserCreatableItemsHandler:combo_button"
-#define TOOLTIPS_KEY "EUserCreatableItemsHandler:tooltips"
-
struct _Component {
- char *id;
+ char *id, *alias;
GNOME_Evolution_Component component;
GNOME_Evolution_CreatableItemTypeList *type_list;
};
@@ -73,23 +70,38 @@ struct _MenuItem {
char shortcut;
char *verb;
char *tooltip;
- char *component_id;
+ char *component;
GdkPixbuf *icon;
};
typedef struct _MenuItem MenuItem;
struct _EUserCreatableItemsHandlerPrivate {
+ /* This component's alias */
+ char *this_component;
+
/* The components that register user creatable items. */
GSList *components; /* Component */
/* The "New ..." menu items. */
- GSList *menu_items; /* MenuItem */
+ GSList *objects; /* MenuItem */
+ GSList *folders; /* MenuItem */
/* The default item (the mailer's "message" item). To be used when the
component in the view we are in doesn't provide a default user
creatable type. This pointer always points to one of the menu items
- in ->menu_items. */
+ in ->objects. */
const MenuItem *default_menu_item;
+
+ char *menu_xml;
+ GtkWidget *new_button, *new_menu;
+ BonoboControl *new_control;
+ GtkTooltips *tooltips;
+ GtkAccelGroup *accel_group;
+};
+
+enum {
+ PROP_THIS_COMPONENT = 1,
+ LAST_PROP
};
@@ -97,6 +109,7 @@ struct _EUserCreatableItemsHandlerPrivate {
static Component *
component_new (const char *id,
+ const char *component_alias,
GNOME_Evolution_Component component)
{
CORBA_Environment ev;
@@ -106,6 +119,7 @@ component_new (const char *id,
new = g_new (Component, 1);
new->id = g_strdup (id);
+ new->alias = g_strdup (component_alias);
new->type_list = GNOME_Evolution_Component__get_userCreatableItems (component, &ev);
if (BONOBO_EX (&ev))
@@ -132,6 +146,7 @@ component_free (Component *component)
Bonobo_Unknown_unref (component->component, &ev);
g_free (component->id);
+ g_free (component->alias);
if (component->type_list != NULL)
CORBA_free (component->type_list);
@@ -141,25 +156,47 @@ component_free (Component *component)
g_free (component);
}
+static const char *component_query =
+ "repo_ids.has ('IDL:GNOME/Evolution/Component:" BASE_VERSION "')";
+
static void
-get_components_from_registry (EUserCreatableItemsHandler *handler,
- EComponentRegistry *registry)
+get_components_from_bonobo (EUserCreatableItemsHandler *handler)
{
- GSList *registry_list = e_component_registry_peek_list (registry);
- GSList *p;
+ Bonobo_ServerInfoList *info_list;
+ Bonobo_ActivationProperty *property;
+ CORBA_Environment ev;
+ char *iid, *alias;
+ GNOME_Evolution_Component corba_component;
+ Component *component;
+ int i;
- for (p = registry_list; p != NULL; p = p->next) {
- EComponentInfo *info = p->data;
- Component *component = NULL;
+ CORBA_exception_init (&ev);
+ info_list = bonobo_activation_query (component_query, 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;
+ }
- e_component_registry_activate (registry, info->id, NULL);
+ for (i = 0; i < info_list->_length; i++) {
+ iid = info_list->_buffer[i].iid;
+ corba_component = bonobo_activation_activate_from_id (iid, Bonobo_ACTIVATION_FLAG_EXISTING_ONLY, NULL, &ev);
+ if (BONOBO_EX (&ev)) {
+ CORBA_exception_free (&ev);
+ continue;
+ }
- if (info->iface != CORBA_OBJECT_NIL)
- component = component_new (info->id, info->iface);
+ property = bonobo_server_info_prop_find (&info_list->_buffer[i],
+ "evolution:component_alias");
+ alias = property ? property->v._u.value_string : "unknown";
- if (component)
- handler->priv->components = g_slist_prepend (handler->priv->components, component);
+ component = component_new (iid, alias, corba_component);
+ handler->priv->components = g_slist_prepend (handler->priv->components, component);
}
+
+ CORBA_free (info_list);
}
@@ -167,22 +204,24 @@ get_components_from_registry (EUserCreatableItemsHandler *handler,
static gboolean
item_is_default (const MenuItem *item,
- const char *component_id)
+ const char *component)
{
- if (component_id == NULL)
+ if (component == NULL)
return FALSE;
- if (strcmp (item->component_id, component_id) == 0)
+ if (strcmp (item->component, component) == 0)
return TRUE;
else
return FALSE;
}
static char *
-create_verb_from_component_number_and_type_id (int component_num,
- const char *type_id)
+create_verb (EUserCreatableItemsHandler *handler,
+ int component_num, const char *type_id)
{
- return g_strdup_printf (VERB_PREFIX ":%d:%s", component_num, type_id);
+ return g_strdup_printf ("EUserCreatableItemsHandler-%s:%d:%s",
+ handler->priv->this_component,
+ component_num, type_id);
}
@@ -193,16 +232,16 @@ static void
ensure_menu_items (EUserCreatableItemsHandler *handler)
{
EUserCreatableItemsHandlerPrivate *priv;
- GSList *menu_items;
+ GSList *objects, *folders;
GSList *p;
int component_num;
const char *default_verb;
priv = handler->priv;
- if (priv->menu_items != NULL)
+ if (priv->objects != NULL)
return;
- menu_items = NULL;
+ objects = folders = NULL;
component_num = 0;
default_verb = NULL;
for (p = priv->components; p != NULL; p = p->next) {
@@ -212,42 +251,46 @@ ensure_menu_items (EUserCreatableItemsHandler *handler)
component = (const Component *) p->data;
if (component->type_list != NULL) {
for (i = 0; i < component->type_list->_length; i ++) {
- const GNOME_Evolution_CreatableItemType *type;
+ const GNOME_Evolution_CreatableItemType *corba_item;
MenuItem *item;
- type = (const GNOME_Evolution_CreatableItemType *) component->type_list->_buffer + i;
+ corba_item = (const GNOME_Evolution_CreatableItemType *) component->type_list->_buffer + i;
item = g_new (MenuItem, 1);
- item->label = type->menuDescription;
- item->shortcut = type->menuShortcut;
- item->verb = create_verb_from_component_number_and_type_id (component_num, type->id);
- item->tooltip = type->tooltip;
- item->component_id = g_strdup (component->id);
-
- if (strcmp (item->component_id, EVOLUTION_MAIL_OAFIID) == 0
- && strcmp (type->id, "message") == 0)
+ item->label = corba_item->menuDescription;
+ item->shortcut = corba_item->menuShortcut;
+ item->verb = create_verb (handler, component_num, corba_item->id);
+ item->tooltip = corba_item->tooltip;
+ item->component = g_strdup (component->alias);
+
+ if (strcmp (item->component, "mail") == 0
+ && strcmp (corba_item->id, "message") == 0)
default_verb = item->verb;
- if (type->iconName == "") {
+ if (corba_item->iconName == "") {
item->icon = NULL;
} else {
- char *icon_path = e_shell_get_icon_path (type->iconName, TRUE);
+ char *icon_path = e_shell_get_icon_path (corba_item->iconName, TRUE);
item->icon = gdk_pixbuf_new_from_file (icon_path, NULL);
g_free (icon_path);
}
- menu_items = g_slist_prepend (menu_items, item);
+ if (corba_item->type == GNOME_Evolution_CREATABLE_OBJECT)
+ objects = g_slist_prepend (objects, item);
+ else
+ folders = g_slist_prepend (folders, item);
}
}
component_num ++;
}
- priv->menu_items = g_slist_reverse (menu_items);
+ priv->objects = g_slist_reverse (objects);
+ priv->folders = g_slist_reverse (folders);
priv->default_menu_item = NULL;
if (default_verb != NULL) {
- for (p = priv->menu_items; p != NULL; p = p->next) {
+ for (p = priv->objects; p != NULL; p = p->next) {
const MenuItem *item;
item = (const MenuItem *) p->data;
@@ -274,7 +317,7 @@ free_menu_items (GSList *menu_items)
if (item->icon != NULL)
g_object_unref (item->icon);
- g_free (item->component_id);
+ g_free (item->component);
g_free (item);
}
@@ -282,24 +325,18 @@ free_menu_items (GSList *menu_items)
}
static const MenuItem *
-get_default_action_for_view (EUserCreatableItemsHandler *handler,
- EShellWindow *window)
+get_default_action_for_view (EUserCreatableItemsHandler *handler)
{
EUserCreatableItemsHandlerPrivate *priv;
- const char *window_component_id;
const GSList *p;
priv = handler->priv;
- window_component_id = e_shell_window_peek_current_component_id (window);
- if (window_component_id == NULL)
- return priv->default_menu_item;
-
- for (p = priv->menu_items; p != NULL; p = p->next) {
+ for (p = priv->objects; p != NULL; p = p->next) {
const MenuItem *item;
item = (const MenuItem *) p->data;
- if (item_is_default (item, window_component_id))
+ if (item_is_default (item, priv->this_component))
return item;
}
@@ -307,163 +344,10 @@ get_default_action_for_view (EUserCreatableItemsHandler *handler,
}
-/* The XML description for "File -> New". */
-
-/* This adds a menu item for @item. If @first is true, the keyboard shortcut
- is going to be "Control-N" instead of whatever the component defines. */
-static void
-append_xml_for_menu_item (GString *xml,
- const MenuItem *item,
- gboolean first)
-{
- char *encoded_label;
- char *encoded_tooltip;
-
- encoded_label = bonobo_ui_util_encode_str (item->label);
- g_string_append_printf (xml, "<menuitem name=\"New:%s\" verb=\"%s\" label=\"%s\"",
- item->verb, item->verb, encoded_label);
-
- if (first)
- g_string_append_printf (xml, " accel=\"*Control*N\"");
- else if (item->shortcut != '\0')
- g_string_append_printf (xml, " accel=\"*Control**Shift*%c\"", item->shortcut);
-
- if (item->icon != NULL) {
- char *icon_xml;
-
- icon_xml = bonobo_ui_util_pixbuf_to_xml (item->icon);
- g_string_append_printf (xml, " pixtype=\"pixbuf\" pixname=\"%s\"", icon_xml);
- g_free (icon_xml);
- }
-
- encoded_tooltip = bonobo_ui_util_encode_str (item->tooltip);
- g_string_append_printf (xml, " tip=\"%s\"", encoded_tooltip);
-
- g_string_append (xml, "/> ");
-
- g_free (encoded_label);
- g_free (encoded_tooltip);
-}
-
-static int
-item_types_sort_func (const void *a,
- const void *b)
-{
- const MenuItem *item_a;
- const MenuItem *item_b;
- const char *p1, *p2;
-
- item_a = (const MenuItem *) a;
- item_b = (const MenuItem *) b;
-
- p1 = item_a->label;
- p2 = item_b->label;
-
- while (*p1 != '\0' && *p2 != '\0') {
- if (*p1 == '_') {
- p1 ++;
- continue;
- }
-
- if (*p2 == '_') {
- p2 ++;
- continue;
- }
-
- if (toupper ((int) *p1) < toupper ((int) *p2))
- return -1;
- else if (toupper ((int) *p1) > toupper ((int) *p2))
- return +1;
-
- p1 ++, p2 ++;
- }
-
- if (*p1 == '\0') {
- if (*p2 == '\0')
- return 0;
- else
- return -1;
- } else {
- return +1;
- }
-}
-
-static char *
-create_menu_xml (EUserCreatableItemsHandler *handler,
- const char *component_id)
-{
- EUserCreatableItemsHandlerPrivate *priv;
- GString *xml;
- GSList *p;
- GSList *non_default_items;
- char *retval;
-
- priv = handler->priv;
-
- ensure_menu_items (handler);
-
- xml = g_string_new ("");
-
- g_string_append (xml, "<placeholder name=\"ComponentItems\">");
- g_string_append (xml, "<placeholder name=\"EUserCreatableItemsPlaceholder\">");
-
- /* 1. Add all the elements that are default for this component. (Note
- that we don't need to do any sorting since the items are already
- sorted alphabetically.) */
-
- if (component_id != NULL) {
- gboolean first = TRUE;
-
- for (p = priv->menu_items; p != NULL; p = p->next) {
- const MenuItem *item;
-
- item = (const MenuItem *) p->data;
- if (item_is_default (item, component_id)) {
- append_xml_for_menu_item (xml, item, first);
- first = FALSE;
- }
- }
- }
-
- /* 2. Add a separator. */
-
- if (component_id != NULL)
- g_string_append_printf (xml,
- "<separator f=\"\" name=\"EUserCreatableItemsHandlerSeparator\"/>");
-
- /* 3. Add the elements that are not default for this component. */
-
- non_default_items = NULL;
- for (p = priv->menu_items; p != NULL; p = p->next) {
- const MenuItem *item;
-
- item = (const MenuItem *) p->data;
- if (! item_is_default (item, component_id))
- non_default_items = g_slist_prepend (non_default_items, (void *) item);
- }
-
- non_default_items = g_slist_sort (non_default_items, item_types_sort_func);
- for (p = non_default_items; p != NULL; p = p->next)
- append_xml_for_menu_item (xml, (const MenuItem *) p->data, FALSE);
- g_slist_free (non_default_items);
-
- /* Done... */
-
- g_string_append (xml, "</placeholder>"); /* EUserCreatableItemsPlaceholder */
- g_string_append (xml, "</placeholder>"); /* ComponentItems */
-
- retval = xml->str;
- g_string_free (xml, FALSE);
-
- return retval;
-}
-
-
/* Verb handling. */
static void
execute_verb (EUserCreatableItemsHandler *handler,
- EShellWindow *window,
const char *verb_name)
{
EUserCreatableItemsHandlerPrivate *priv;
@@ -514,31 +398,22 @@ verb_fn (BonoboUIComponent *ui_component,
void *data,
const char *verb_name)
{
- EUserCreatableItemsHandler *handler;
- EShellWindow *shell_window;
+ EUserCreatableItemsHandler *handler=
+ E_USER_CREATABLE_ITEMS_HANDLER (data);
- shell_window = g_object_get_data (G_OBJECT (ui_component), SHELL_WINDOW_KEY);
- g_assert (E_IS_SHELL_WINDOW (shell_window));
-
- handler = E_USER_CREATABLE_ITEMS_HANDLER (data);
-
- execute_verb (handler, shell_window, verb_name);
+ execute_verb (handler, verb_name);
}
static void
add_verbs (EUserCreatableItemsHandler *handler,
- EShellWindow *window)
+ BonoboUIComponent *ui_component)
{
EUserCreatableItemsHandlerPrivate *priv;
- BonoboUIComponent *ui_component;
int component_num;
GSList *p;
priv = handler->priv;
- ui_component = e_shell_window_peek_bonobo_ui_component (window);
- g_object_set_data (G_OBJECT (ui_component), SHELL_WINDOW_KEY, window);
-
component_num = 0;
for (p = priv->components; p != NULL; p = p->next) {
const Component *component;
@@ -550,8 +425,9 @@ add_verbs (EUserCreatableItemsHandler *handler,
for (i = 0; i < component->type_list->_length; i ++) {
char *verb_name;
- verb_name = create_verb_from_component_number_and_type_id
- (component_num, component->type_list->_buffer[i].id);
+ verb_name = create_verb (handler,
+ component_num,
+ component->type_list->_buffer[i].id);
bonobo_ui_component_add_verb (ui_component, verb_name, verb_fn, handler);
@@ -564,119 +440,298 @@ add_verbs (EUserCreatableItemsHandler *handler,
}
-/* The "New" button in the toolbar. */
+/* Generic menu construction code */
-static void
-combo_button_activate_default_callback (EComboButton *combo_button,
- void *data)
+static int
+item_types_sort_func (const void *a,
+ const void *b)
{
- EShellWindow *shell_window;
- EUserCreatableItemsHandler *handler;
- const MenuItem *menu_item;
+ const MenuItem *item_a;
+ const MenuItem *item_b;
+ const char *p1, *p2;
+
+ item_a = (const MenuItem *) a;
+ item_b = (const MenuItem *) b;
+
+ p1 = item_a->label;
+ p2 = item_b->label;
+
+ while (*p1 != '\0' && *p2 != '\0') {
+ if (*p1 == '_') {
+ p1 ++;
+ continue;
+ }
+
+ if (*p2 == '_') {
+ p2 ++;
+ continue;
+ }
+
+ if (toupper ((int) *p1) < toupper ((int) *p2))
+ return -1;
+ else if (toupper ((int) *p1) > toupper ((int) *p2))
+ return +1;
- shell_window = E_SHELL_WINDOW (data);
- handler = e_shell_peek_user_creatable_items_handler (e_shell_window_peek_shell (shell_window));
+ p1 ++, p2 ++;
+ }
- menu_item = get_default_action_for_view (handler, shell_window);
- execute_verb (handler, shell_window, menu_item->verb);
+ if (*p1 == '\0') {
+ if (*p2 == '\0')
+ return 0;
+ else
+ return -1;
+ } else {
+ return +1;
+ }
}
+typedef void (*EUserCreatableItemsHandlerMenuItemFunc) (EUserCreatableItemsHandler *, gpointer, MenuItem *, gboolean);
+typedef void (*EUserCreatableItemsHandlerSeparatorFunc) (EUserCreatableItemsHandler *, gpointer, int);
+
static void
-setup_toolbar_button (EUserCreatableItemsHandler *handler,
- EShellWindow *window)
+construct_menu (EUserCreatableItemsHandler *handler, gpointer menu,
+ EUserCreatableItemsHandlerMenuItemFunc menu_item_func,
+ EUserCreatableItemsHandlerSeparatorFunc separator_func)
{
EUserCreatableItemsHandlerPrivate *priv;
- BonoboUIComponent *ui_component;
- GtkWidget *combo_button;
- GtkWidget *menu;
- GtkTooltips *tooltips;
- BonoboControl *control;
+ MenuItem *item;
+ GSList *p, *items;
+ gboolean first = TRUE;
priv = handler->priv;
- menu = gtk_menu_new ();
+ /* First add the current component's creatable objects */
+ for (p = priv->objects; p != NULL; p = p->next) {
+ item = p->data;
+ if (item_is_default (item, priv->this_component)) {
+ menu_item_func (handler, menu, item, first);
+ first = FALSE;
+ }
+ }
- combo_button = e_combo_button_new ();
- e_combo_button_set_menu (E_COMBO_BUTTON (combo_button), GTK_MENU (menu));
- e_combo_button_set_label (E_COMBO_BUTTON (combo_button), _("New"));
- gtk_widget_show (combo_button);
+ /* Then its creatable folders */
+ for (p = priv->folders; p != NULL; p = p->next) {
+ item = p->data;
+ if (item_is_default (item, priv->this_component))
+ menu_item_func (handler, menu, item, FALSE);
+ }
- g_signal_connect (combo_button, "activate_default", G_CALLBACK (combo_button_activate_default_callback), window);
+ /* Then a separator */
+ separator_func (handler, menu, 1);
- ui_component = e_shell_window_peek_bonobo_ui_component (window);
- bonobo_window_add_popup (BONOBO_WINDOW (window), GTK_MENU (menu), "/popups/NewPopup");
+ /* Then the objects from other components. */
+ items = NULL;
+ for (p = priv->objects; p != NULL; p = p->next) {
+ item = p->data;
+ if (! item_is_default (item, priv->this_component))
+ items = g_slist_prepend (items, item);
+ }
- control = bonobo_control_new (combo_button);
+ items = g_slist_sort (items, item_types_sort_func);
+ for (p = items; p != NULL; p = p->next)
+ menu_item_func (handler, menu, p->data, FALSE);
+ g_slist_free (items);
- bonobo_ui_component_object_set (ui_component, "/Toolbar/NewComboButton",
- BONOBO_OBJREF (control), NULL);
+ /* Another separator */
+ separator_func (handler, menu, 2);
- bonobo_object_unref (control);
-
- g_object_set_data (G_OBJECT (window), COMBO_BUTTON_WIDGET_KEY, combo_button);
+ /* And finally the folders from other components */
+ items = NULL;
+ for (p = priv->folders; p != NULL; p = p->next) {
+ item = p->data;
+ if (! item_is_default (item, priv->this_component))
+ items = g_slist_prepend (items, item);
+ }
- tooltips = gtk_tooltips_new ();
- g_object_set_data (G_OBJECT (combo_button), TOOLTIPS_KEY, tooltips);
+ items = g_slist_sort (items, item_types_sort_func);
+ for (p = items; p != NULL; p = p->next)
+ menu_item_func (handler, menu, p->data, FALSE);
+ g_slist_free (items);
}
+/* The XML description for "File -> New". */
static void
-update_for_window (EUserCreatableItemsHandler *handler,
- EShellWindow *window)
+xml_menu_item_func (EUserCreatableItemsHandler *handler, gpointer menu,
+ MenuItem *item, gboolean first)
{
- GtkWidget *combo_button_widget;
- GtkTooltips *tooltips;
- BonoboUIComponent *ui_component;
- const MenuItem *default_menu_item;
- char *menu_xml;
+ GString *xml = menu;
+ char *encoded_label;
+ char *encoded_tooltip;
- combo_button_widget = g_object_get_data (G_OBJECT (window), COMBO_BUTTON_WIDGET_KEY);
- g_assert (E_IS_COMBO_BUTTON (combo_button_widget));
+ encoded_label = bonobo_ui_util_encode_str (item->label);
+ g_string_append_printf (xml, "<menuitem name=\"New:%s\" verb=\"%s\" label=\"%s\"",
+ item->verb, item->verb, encoded_label);
- tooltips = g_object_get_data (G_OBJECT (combo_button_widget), TOOLTIPS_KEY);
- g_assert (tooltips != NULL);
+ if (first)
+ g_string_append_printf (xml, " accel=\"*Control*N\"");
+ else if (item->shortcut != '\0')
+ g_string_append_printf (xml, " accel=\"*Control**Shift*%c\"", item->shortcut);
- default_menu_item = get_default_action_for_view (handler, window);
- if (default_menu_item == NULL) {
- gtk_widget_set_sensitive (combo_button_widget, FALSE);
- e_combo_button_set_label (E_COMBO_BUTTON (combo_button_widget), _("New"));
- e_combo_button_set_icon (E_COMBO_BUTTON (combo_button_widget), NULL);
- gtk_tooltips_set_tip (tooltips, combo_button_widget, NULL, NULL);
- return;
+ if (item->icon != NULL) {
+ char *icon_xml;
+
+ icon_xml = bonobo_ui_util_pixbuf_to_xml (item->icon);
+ g_string_append_printf (xml, " pixtype=\"pixbuf\" pixname=\"%s\"", icon_xml);
+ g_free (icon_xml);
}
- gtk_widget_set_sensitive (combo_button_widget, TRUE);
+ encoded_tooltip = bonobo_ui_util_encode_str (item->tooltip);
+ g_string_append_printf (xml, " tip=\"%s\"", encoded_tooltip);
- e_combo_button_set_icon (E_COMBO_BUTTON (combo_button_widget), default_menu_item->icon);
- gtk_tooltips_set_tip (tooltips, combo_button_widget, default_menu_item->tooltip, NULL);
+ g_string_append (xml, "/> ");
- ui_component = e_shell_window_peek_bonobo_ui_component (window);
- bonobo_ui_component_rm (ui_component, "/menu/File/New/ComponentItems/EUserCreatableItemsPlaceholder", NULL);
- bonobo_ui_component_rm (ui_component, "/popups/NewPopup/ComponentItems/EUserCreatableItemsPlaceholder", NULL);
+ g_free (encoded_label);
+ g_free (encoded_tooltip);
+}
+
+static void
+xml_separator_func (EUserCreatableItemsHandler *handler, gpointer menu, int nth)
+{
+ GString *xml = menu;
+
+ g_string_append_printf (xml, "<separator f=\"\" name=\"EUserCreatableItemsHandlerSeparator%d\"/>", nth);
+}
+
+static void
+create_menu_xml (EUserCreatableItemsHandler *handler)
+{
+ GString *xml;
- menu_xml = create_menu_xml (handler, e_shell_window_peek_current_component_id (window));
+ xml = g_string_new ("<placeholder name=\"NewMenu\">");
+ construct_menu (handler, xml, xml_menu_item_func, xml_separator_func);
+ g_string_append (xml, "</placeholder>");
- bonobo_ui_component_set (ui_component, "/menu/File/New", menu_xml, NULL);
- bonobo_ui_component_set (ui_component, "/popups/NewPopup", menu_xml, NULL);
- g_free (menu_xml);
+ handler->priv->menu_xml = xml->str;
+ g_string_free (xml, FALSE);
}
-/* This handles the menus for a given EShellWindow. We have to rebuild the menu
- and set the toolbar button every time the view changes, and clean up when
- the view is destroyed. */
+/* The GtkMenu for the toolbar button. */
+
+static void
+menuitem_activate (GtkMenuItem *item, gpointer data)
+{
+ EUserCreatableItemsHandler *handler = data;
+ const char *verb;
+
+ verb = g_object_get_data (G_OBJECT (item), "EUserCreatableItemsHandler:verb");
+ execute_verb (handler, verb);
+}
+
+static void
+default_activate (EComboButton *combo_button, gpointer data)
+{
+ EUserCreatableItemsHandler *handler = data;
+
+ execute_verb (handler, handler->priv->default_menu_item->verb);
+}
+
+static void
+gtk_menu_item_func (EUserCreatableItemsHandler *handler, gpointer menu,
+ MenuItem *item, gboolean first)
+{
+ GtkWidget *menuitem, *icon;
+
+ menuitem = gtk_image_menu_item_new_with_mnemonic (item->label);
+
+ if (item->icon) {
+ icon = gtk_image_new_from_pixbuf (item->icon);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
+ icon);
+ }
+
+ if (first) {
+ gtk_widget_add_accelerator (menuitem, "activate",
+ handler->priv->accel_group,
+ 'n', GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+ } else {
+ gtk_widget_add_accelerator (menuitem, "activate",
+ handler->priv->accel_group,
+ item->shortcut,
+ GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ GTK_ACCEL_VISIBLE);
+ }
+
+ g_object_set_data (G_OBJECT (menuitem), "EUserCreatableItemsHandler:verb", item->verb);
+ g_signal_connect (menuitem, "activate",
+ G_CALLBACK (menuitem_activate), handler);
+
+ gtk_menu_shell_append (menu, menuitem);
+}
+
+static void
+gtk_separator_func (EUserCreatableItemsHandler *handler, gpointer menu, int nth)
+{
+ gtk_menu_shell_append (menu, gtk_separator_menu_item_new ());
+}
static void
-shell_window_component_changed_callback (EShellWindow *shell_window,
- EUserCreatableItemsHandler *handler)
+setup_toolbar_button (EUserCreatableItemsHandler *handler)
{
- update_for_window (handler, shell_window);
+ EUserCreatableItemsHandlerPrivate *priv;
+ const MenuItem *default_menu_item;
+
+ priv = handler->priv;
+
+ priv->new_button = e_combo_button_new ();
+ priv->new_menu = gtk_menu_new ();
+ priv->accel_group = gtk_accel_group_new ();
+ construct_menu (handler, priv->new_menu,
+ gtk_menu_item_func, gtk_separator_func);
+ gtk_widget_show_all (priv->new_menu);
+ e_combo_button_set_menu (E_COMBO_BUTTON (priv->new_button),
+ GTK_MENU (priv->new_menu));
+ e_combo_button_set_label (E_COMBO_BUTTON (priv->new_button), _("New"));
+ gtk_widget_show (priv->new_button);
+
+ g_signal_connect (priv->new_button, "activate_default",
+ G_CALLBACK (default_activate), handler);
+
+ priv->new_control = bonobo_control_new (priv->new_button);
+
+ default_menu_item = get_default_action_for_view (handler);
+ if (!default_menu_item) {
+ gtk_widget_set_sensitive (priv->new_button, FALSE);
+ return;
+ }
+
+ gtk_widget_set_sensitive (priv->new_button, TRUE);
+
+ e_combo_button_set_icon (E_COMBO_BUTTON (priv->new_button),
+ default_menu_item->icon);
+
+ priv->tooltips = gtk_tooltips_new ();
+ gtk_object_ref (GTK_OBJECT (priv->tooltips));
+ gtk_object_sink (GTK_OBJECT (priv->tooltips));
+ gtk_tooltips_set_tip (priv->tooltips, priv->new_button,
+ default_menu_item->tooltip, NULL);
}
/* GObject methods. */
static void
+impl_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ EUserCreatableItemsHandler *handler =
+ E_USER_CREATABLE_ITEMS_HANDLER (object);
+
+ switch (prop_id) {
+ case PROP_THIS_COMPONENT:
+ handler->priv->this_component = g_value_dup_string (value);
+
+ get_components_from_bonobo (handler);
+ ensure_menu_items (handler);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
impl_dispose (GObject *object)
{
EUserCreatableItemsHandler *handler;
@@ -692,7 +747,21 @@ impl_dispose (GObject *object)
g_slist_free (priv->components);
priv->components = NULL;
-
+ if (priv->new_control) {
+ bonobo_object_unref (priv->new_control);
+ priv->new_control = NULL;
+ }
+
+ if (priv->tooltips) {
+ g_object_unref (priv->tooltips);
+ priv->tooltips = NULL;
+ }
+
+ if (priv->accel_group) {
+ g_object_unref (priv->accel_group);
+ priv->accel_group = NULL;
+ }
+
(* G_OBJECT_CLASS (parent_class)->dispose) (object);
}
@@ -705,7 +774,10 @@ impl_finalize (GObject *object)
handler = E_USER_CREATABLE_ITEMS_HANDLER (object);
priv = handler->priv;
- free_menu_items (priv->menu_items);
+ g_free (priv->this_component);
+
+ free_menu_items (priv->objects);
+ free_menu_items (priv->folders);
g_free (priv);
@@ -718,73 +790,69 @@ class_init (GObjectClass *object_class)
{
parent_class = g_type_class_ref(PARENT_TYPE);
- object_class->dispose = impl_dispose;
- object_class->finalize = impl_finalize;
+ object_class->dispose = impl_dispose;
+ object_class->finalize = impl_finalize;
+ object_class->set_property = impl_set_property;
+
+ g_object_class_install_property (
+ object_class, PROP_THIS_COMPONENT,
+ g_param_spec_string ("this_component", "Component alias",
+ "The component_alias of this component",
+ NULL,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}
static void
-init (EUserCreatableItemsHandler *shell_user_creatable_items_handler)
+init (EUserCreatableItemsHandler *handler)
{
EUserCreatableItemsHandlerPrivate *priv;
- priv = g_new (EUserCreatableItemsHandlerPrivate, 1);
- priv->components = NULL;
- priv->menu_items = NULL;
- priv->default_menu_item = NULL;
+ priv = g_new0 (EUserCreatableItemsHandlerPrivate, 1);
- shell_user_creatable_items_handler->priv = priv;
+ handler->priv = priv;
}
EUserCreatableItemsHandler *
-e_user_creatable_items_handler_new (EComponentRegistry *registry)
+e_user_creatable_items_handler_new (const char *component_alias)
{
- EUserCreatableItemsHandler *new;
-
- new = g_object_new (e_user_creatable_items_handler_get_type (), NULL);
-
- get_components_from_registry (new, registry);
-
- return new;
+ return g_object_new (e_user_creatable_items_handler_get_type (),
+ "this_component", component_alias,
+ NULL);
}
/**
- * e_user_creatable_items_handler_attach_menus:
- * @handler:
- * @shell_window:
+ * e_user_creatable_items_handler_activate:
+ * @handler: the #EUserCreatableItemsHandler
+ * @ui_component: the #BonoboUIComponent to attach to
*
- * Set up the menus and toolbar items for @shell_window. When the shell changes
- * view, the menu and the toolbar item will update automatically (i.e. the
- * actions for the current folder will go on top etc.).
+ * Set up the menus and toolbar items for @ui_component.
**/
void
-e_user_creatable_items_handler_attach_menus (EUserCreatableItemsHandler *handler,
- EShellWindow *window)
+e_user_creatable_items_handler_activate (EUserCreatableItemsHandler *handler,
+ BonoboUIComponent *ui_component)
{
- BonoboUIComponent *ui_component;
EUserCreatableItemsHandlerPrivate *priv;
- char *menu_xml;
g_return_if_fail (E_IS_USER_CREATABLE_ITEMS_HANDLER (handler));
- g_return_if_fail (E_IS_SHELL_WINDOW (window));
+ g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui_component));
priv = handler->priv;
- setup_toolbar_button (handler, window);
- g_signal_connect (window, "component_changed", G_CALLBACK (shell_window_component_changed_callback), handler);
-
- add_verbs (handler, window);
- menu_xml = create_menu_xml (handler, e_shell_window_peek_current_component_id (window));
-
- ui_component = e_shell_window_peek_bonobo_ui_component (window);
- bonobo_ui_component_set (ui_component, "/menu/File/New", menu_xml, NULL);
- bonobo_ui_component_set (ui_component, "/popups/NewPopup", menu_xml, NULL);
+ if (!priv->menu_xml) {
+ create_menu_xml (handler);
+ setup_toolbar_button (handler);
+ add_verbs (handler, ui_component);
+ }
- g_free (menu_xml);
+ bonobo_ui_component_set (ui_component, "/menu/File/New",
+ priv->menu_xml, NULL);
- update_for_window (handler, window);
+ bonobo_ui_component_object_set (ui_component,
+ "/Toolbar/NewComboButton",
+ BONOBO_OBJREF (priv->new_control),
+ NULL);
}
-
E_MAKE_TYPE (e_user_creatable_items_handler, "EUserCreatableItemsHandler", EUserCreatableItemsHandler, class_init, init, PARENT_TYPE)