aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--shell/ChangeLog71
-rw-r--r--shell/Evolution-ShellComponent.idl1
-rw-r--r--shell/Makefile.am2
-rw-r--r--shell/e-shell-user-creatable-items-handler.c381
-rw-r--r--shell/e-shell-user-creatable-items-handler.h5
-rw-r--r--shell/e-shell-view.c40
-rw-r--r--shell/e-shell-view.h14
-rw-r--r--shell/e-shell.c1
-rw-r--r--shell/evolution-activity-client.c74
-rw-r--r--shell/evolution-shell-component-client.c41
-rw-r--r--shell/evolution-shell-component-client.h14
-rw-r--r--shell/evolution-shell-component.c23
-rw-r--r--shell/evolution-shell-component.h11
-rw-r--r--shell/evolution-storage-listener.h4
-rw-r--r--shell/evolution-test-component.c6
-rw-r--r--widgets/misc/ChangeLog21
-rw-r--r--widgets/misc/e-combo-button.c322
-rw-r--r--widgets/misc/e-combo-button.h14
18 files changed, 744 insertions, 301 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog
index 6bacbf5c27..b5f56f25cc 100644
--- a/shell/ChangeLog
+++ b/shell/ChangeLog
@@ -1,5 +1,76 @@
2002-01-23 Ettore Perazzoli <ettore@ximian.com>
+ * e-shell-user-creatable-items-handler.c: New member `id' in
+ struct `Component'. New member `icon' in struct `MenuItem'.
+ (component_free): Free ->id.
+ (component_new): Renamed from `component_new_from_client'. Get an
+ @id arg and set ->id accordingly.
+ (e_shell_user_creatable_items_handler_add_component): New arg @id.
+ Pass it to `component_new'.
+ (e_shell_user_creatable_items_handler_setup_menus): New arg
+ @current_component_id.
+ (e_shell_user_creatable_items_handler_update_menus): New.
+ (set_current_component): New helper function.
+ (get_component_by_id): New helper function.
+ (add_verbs): Renamed from `add_verbs_to_ui_component()'. Get a
+ @shell_view instead of a @ui_component. Set the SHELL_VIEW_KEY on
+ the ui_component of the shell_view to point to the shell_view
+ itself.
+ (ensure_menu_items): Set item->icon to NULL.
+ (free_menu_items): Unref item->icon.
+ (ensure_menu_xml): Set the icon as well.
+ (get_default_action_for_view): New helper function.
+ (find_menu_item_for_verb): New helper function.
+ (shell_view_view_changed_callback): New callback, set up the label
+ on the "New" button depending on the current component.
+ (e_shell_user_creatable_items_handler_attach_menus): New. For
+ now, do not display the toolbar button yet.
+ (execute_verb): New helper function, splitting out code from
+ `verb_fn'.
+ (verb_fn): Use `execute_verb'.
+ (combo_button_activate_default_callback): Callback for the
+ "activate_default" signal on the EComboButton.
+ (setup_toolbar_button): Connect.
+
+ * evolution-shell-component.c: New member `icon' in
+ `UserCreatableItemType'.
+ (impl__get_userCreatableItemTypes): Put the ->icon in the
+ corba_type as well.
+ (user_creatable_item_type_new): Get a new @icon argument.
+ (evolution_shell_component_add_user_creatable_item): New arg
+ @icon.
+
+ * Evolution-ShellComponent.idl: New member `icon' in struct
+ `UserCreatableItemType'.
+
+ * evolution-test-component.c (register_component): Pass a NULL
+ @icon to `evolution_shell_component_add_user_creatable_item()'.
+
+ * e-shell-view.c (class_init): Add the signal to the class.
+ (e_shell_view_display_uri): Emit "view_changed".
+ (e_shell_view_get_current_component_id): New.
+
+ * evolution-shell-component-client.c: New member `id' in
+ EvolutionShellComponentClientPrivate.
+ (init): Init to NULL.
+ (impl_destroy): Free.
+ (evolution_shell_component_client_new_for_objref): Removed.
+ (evolution_shell_component_client_construct): New arg @id.
+ Initialize ->id from it.
+ (evolution_shell_component_client_get_id): New.
+
+ * e-shell-view.h: New signal "view_changed".
+
+ * evolution-activity-client.c (create_icon_from_pixbuf): Removed.
+ (create_corba_animated_icon_from_pixbuf_array): Removed.
+ (evolution_activity_client_construct): Use
+ `e_new_corba_animated_icon_from_pixbuf_array()' instead.
+
+ * e-shell-icon-utils.h: New.
+ * e-shell-icon-utils.c: New.
+
+2002-01-23 Ettore Perazzoli <ettore@ximian.com>
+
[Patch by Michael Meeks <michael@ximian.com>.]
* e-splash.c (e_splash_set_icon_highlight): g_return if there is
diff --git a/shell/Evolution-ShellComponent.idl b/shell/Evolution-ShellComponent.idl
index 04e45157c9..b5f5095c43 100644
--- a/shell/Evolution-ShellComponent.idl
+++ b/shell/Evolution-ShellComponent.idl
@@ -36,6 +36,7 @@ module Evolution {
string description;
string menuDescription;
char menuShortcut;
+ Icon icon;
};
typedef sequence<UserCreatableItemType> UserCreatableItemTypeList;
diff --git a/shell/Makefile.am b/shell/Makefile.am
index c406707087..465b2a3250 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -77,6 +77,8 @@ eshellinclude_HEADERS = \
libeshell_la_SOURCES = \
$(IDL_GENERATED) \
e-folder-tree.c \
+ e-shell-corba-icon-utils.c \
+ e-shell-corba-icon-utils.h \
evolution-activity-client.c \
evolution-session.c \
evolution-shell-client.c \
diff --git a/shell/e-shell-user-creatable-items-handler.c b/shell/e-shell-user-creatable-items-handler.c
index 4b2554fb66..cafd074605 100644
--- a/shell/e-shell-user-creatable-items-handler.c
+++ b/shell/e-shell-user-creatable-items-handler.c
@@ -26,12 +26,18 @@
#include "e-shell-user-creatable-items-handler.h"
+#include "widgets/misc/e-combo-button.h"
+
#include "e-util/e-corba-utils.h"
#include <gal/util/e-util.h>
#include <bonobo/bonobo-ui-util.h>
+#include <libgnome/gnome-i18n.h>
+
+#include <gtk/gtksignal.h>
+
#include <stdlib.h>
#include <ctype.h>
@@ -41,7 +47,9 @@ static GtkObjectClass *parent_class = NULL;
#define VERB_PREFIX "ShellUserCreatableItemVerb"
-#define SHELL_VIEW_DATA_KEY "EShellUserCreatableItemsHandler:shell_view"
+
+#define SHELL_VIEW_KEY "EShellUserCreatableItemsHandler:shell_view"
+#define COMBO_BUTTON_WIDGET_KEY "EShellUserCreatableItemsHandler:combo_button"
struct _Component {
EvolutionShellComponentClient *component_client;
@@ -50,9 +58,18 @@ struct _Component {
};
typedef struct _Component Component;
+struct _MenuItem {
+ const char *label;
+ char shortcut;
+ char *verb;
+ GdkPixbuf *icon;
+};
+typedef struct _MenuItem MenuItem;
+
struct _EShellUserCreatableItemsHandlerPrivate {
GSList *components; /* Component */
+ GSList *menu_items; /* MenuItem */
char *menu_xml;
};
@@ -60,7 +77,8 @@ struct _EShellUserCreatableItemsHandlerPrivate {
/* Component struct handling. */
static Component *
-component_new_from_client (EvolutionShellComponentClient *client)
+component_new (const char *id,
+ EvolutionShellComponentClient *client)
{
CORBA_Environment ev;
Component *new;
@@ -106,14 +124,8 @@ create_verb_from_component_number_and_type_id (int component_num,
}
-/* Setting up the XML for the menus. */
-
-struct _MenuItem {
- const char *label;
- char shortcut;
- char *verb;
-};
-typedef struct _MenuItem MenuItem;
+/* Setting up menu items for the "File -> New" submenu and the "New" toolbar
+ button. */
static int
item_types_sort_func (const void *a,
@@ -156,51 +168,10 @@ item_types_sort_func (const void *a,
} else {
return +1;
}
-
-}
-
-static char *
-create_xml_from_menu_items (GSList *items)
-{
- GString *xml;
- GSList *p;
- char *str;
-
- xml = g_string_new ("");
-
- g_string_append (xml, "<Root> <menu> <submenu name=\"File\"> <submenu name=\"New\"> <placeholder name=\"NewItems\">");
-
- g_string_append (xml, "<separator/> ");
-
- for (p = items; p != NULL; p = p->next) {
- const MenuItem *item;
- char *encoded_label;
-
- item = (const MenuItem *) p->data;
-
- encoded_label = bonobo_ui_util_encode_str (item->label);
-
- g_string_sprintfa (xml, "<menuitem name=\"New:%s\" verb=\"%s\" label=\"%s\"",
- item->verb, item->verb, encoded_label);
-
- if (item->shortcut != '\0')
- g_string_sprintfa (xml, " accel=\"*Control**Shift*%c\"", item->shortcut);
-
- g_string_append (xml, "/> ");
-
- g_free (encoded_label);
- }
-
- g_string_append (xml, "</placeholder> </submenu> </submenu> </menu> </Root>");
-
- str = xml->str;
- g_string_free (xml, FALSE);
-
- return str;
}
static void
-setup_menu_xml (EShellUserCreatableItemsHandler *handler)
+ensure_menu_items (EShellUserCreatableItemsHandler *handler)
{
EShellUserCreatableItemsHandlerPrivate *priv;
GSList *menu_items;
@@ -208,7 +179,8 @@ setup_menu_xml (EShellUserCreatableItemsHandler *handler)
int component_num;
priv = handler->priv;
- g_assert (priv->menu_xml == NULL);
+ if (priv->menu_items != NULL)
+ return;
menu_items = NULL;
component_num = 0;
@@ -228,6 +200,7 @@ setup_menu_xml (EShellUserCreatableItemsHandler *handler)
item->label = type->menuDescription;
item->shortcut = type->menuShortcut;
item->verb = create_verb_from_component_number_and_type_id (component_num, type->id);
+ item->icon = NULL;
menu_items = g_slist_prepend (menu_items, item);
}
@@ -236,36 +209,154 @@ setup_menu_xml (EShellUserCreatableItemsHandler *handler)
component_num ++;
}
- if (menu_items == NULL) {
- priv->menu_xml = g_strdup ("");
- return;
- }
+ if (menu_items == NULL)
+ priv->menu_items = NULL;
+ else
+ priv->menu_items = g_slist_sort (menu_items, item_types_sort_func);
+}
- menu_items = g_slist_sort (menu_items, item_types_sort_func);
+static void
+free_menu_items (GSList *menu_items)
+{
+ GSList *p;
- priv->menu_xml = create_xml_from_menu_items (menu_items);
+ if (menu_items == NULL)
+ return;
for (p = menu_items; p != NULL; p = p->next) {
MenuItem *item;
item = (MenuItem *) p->data;
g_free (item->verb);
+
+ if (item->icon != NULL)
+ gdk_pixbuf_unref (item->icon);
+
g_free (item);
}
+
g_slist_free (menu_items);
}
+static const MenuItem *
+find_menu_item_for_verb (EShellUserCreatableItemsHandler *handler,
+ const char *verb)
+{
+ EShellUserCreatableItemsHandlerPrivate *priv;
+ GSList *p;
+
+ priv = handler->priv;
+
+ for (p = priv->menu_items; p != NULL; p = p->next) {
+ const MenuItem *item;
+
+ item = (const MenuItem *) p->data;
+ if (strcmp (item->verb, verb) == 0)
+ return item;
+ }
+
+ return NULL;
+}
+
+static const MenuItem *
+get_default_action_for_view (EShellUserCreatableItemsHandler *handler,
+ EShellView *shell_view)
+{
+ EShellUserCreatableItemsHandlerPrivate *priv;
+ const char *view_component_id;
+ const GSList *p;
+ int component_num;
+
+ priv = handler->priv;
+
+ /* FIXME-1.2: This should be based on the folder type not the component
+ that handles it. For this, we are going to have to make the IDL a
+ little more complex. Also, this is a pretty brutal and ugly hack. */
+
+ view_component_id = e_shell_view_get_current_component_id (shell_view);
+
+ for (p = priv->components, component_num = 0; p != NULL; p = p->next, component_num ++) {
+ const Component *component;
+ const GNOME_Evolution_UserCreatableItemType *type;
+ const char *component_id;
+
+ component = (const Component *) p->data;
+ type = & component->type_list->_buffer[0];
+ component_id = evolution_shell_component_client_get_id (component->component_client);
+
+ if (strcmp (component_id, view_component_id) == 0) {
+ const MenuItem *item;
+ char *verb;
+
+ verb = create_verb_from_component_number_and_type_id (component_num, type->id);
+ item = find_menu_item_for_verb (handler, verb);
+ g_free (verb);
+
+ return item;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* The XML description for "File -> New". */
+
+static void
+ensure_menu_xml (EShellUserCreatableItemsHandler *handler)
+{
+ EShellUserCreatableItemsHandlerPrivate *priv;
+ GString *xml;
+ GSList *p;
+
+ priv = handler->priv;
+ if (priv->menu_xml != NULL)
+ return;
+
+ ensure_menu_items (handler);
+
+ xml = g_string_new ("");
+
+ g_string_append (xml, "<placeholder name=\"NewItems\">");
+
+ for (p = priv->menu_items; p != NULL; p = p->next) {
+ const MenuItem *item;
+ char *encoded_label;
+
+ item = (const MenuItem *) p->data;
+
+ encoded_label = bonobo_ui_util_encode_str (item->label);
+
+ g_string_sprintfa (xml, "<menuitem name=\"New:%s\" verb=\"%s\" label=\"%s\"",
+ item->verb, item->verb, encoded_label);
+
+ if (item->shortcut != '\0')
+ g_string_sprintfa (xml, " accel=\"*Control**Shift*%c\"", item->shortcut);
+
+ if (item->icon != NULL)
+ g_string_sprintfa (xml, " pixtype=\"pixbuf\" pixname=\"%s\"",
+ bonobo_ui_util_pixbuf_to_xml (item->icon));
+
+ g_string_append (xml, "/> ");
+
+ g_free (encoded_label);
+ }
+
+ g_string_append (xml, "</placeholder>");
+
+ priv->menu_xml = xml->str;
+ g_string_free (xml, FALSE);
+}
+
/* Verb handling. */
static void
-verb_fn (BonoboUIComponent *ui_component,
- void *data,
- const char *verb_name)
+execute_verb (EShellUserCreatableItemsHandler *handler,
+ EShellView *shell_view,
+ const char *verb_name)
{
- EShellUserCreatableItemsHandler *handler;
EShellUserCreatableItemsHandlerPrivate *priv;
- EShellView *shell_view;
const Component *component;
int component_number;
const char *p;
@@ -273,10 +364,6 @@ verb_fn (BonoboUIComponent *ui_component,
GSList *component_list_item;
int i;
- shell_view = gtk_object_get_data (GTK_OBJECT (ui_component), SHELL_VIEW_DATA_KEY);
- g_assert (E_IS_SHELL_VIEW (shell_view));
-
- handler = E_SHELL_USER_CREATABLE_ITEMS_HANDLER (data);
priv = handler->priv;
p = strchr (verb_name, ':');
@@ -318,15 +405,35 @@ verb_fn (BonoboUIComponent *ui_component,
}
static void
-add_verbs_to_ui_component (EShellUserCreatableItemsHandler *handler,
- BonoboUIComponent *ui_component)
+verb_fn (BonoboUIComponent *ui_component,
+ void *data,
+ const char *verb_name)
+{
+ EShellUserCreatableItemsHandler *handler;
+ EShellView *shell_view;
+
+ shell_view = gtk_object_get_data (GTK_OBJECT (ui_component), SHELL_VIEW_KEY);
+ g_assert (E_IS_SHELL_VIEW (shell_view));
+
+ handler = E_SHELL_USER_CREATABLE_ITEMS_HANDLER (data);
+
+ execute_verb (handler, shell_view, verb_name);
+}
+
+static void
+add_verbs (EShellUserCreatableItemsHandler *handler,
+ EShellView *shell_view)
{
EShellUserCreatableItemsHandlerPrivate *priv;
+ BonoboUIComponent *ui_component;
int component_num;
GSList *p;
priv = handler->priv;
+ ui_component = e_shell_view_get_bonobo_ui_component (shell_view);
+ gtk_object_set_data (GTK_OBJECT (ui_component), SHELL_VIEW_KEY, shell_view);
+
component_num = 0;
for (p = priv->components; p != NULL; p = p->next) {
const Component *component;
@@ -352,6 +459,99 @@ add_verbs_to_ui_component (EShellUserCreatableItemsHandler *handler,
}
+/* The "New" button in the toolbar. */
+
+static void
+combo_button_activate_default_callback (EComboButton *combo_button,
+ void *data)
+{
+ EShellView *shell_view;
+ EShellUserCreatableItemsHandler *handler;
+ const MenuItem *menu_item;
+
+ shell_view = E_SHELL_VIEW (data);
+ handler = e_shell_get_user_creatable_items_handler (e_shell_view_get_shell (shell_view));
+
+ menu_item = get_default_action_for_view (handler, shell_view);
+ execute_verb (handler, shell_view, menu_item->verb);
+}
+
+static void
+setup_toolbar_button (EShellUserCreatableItemsHandler *handler,
+ EShellView *shell_view)
+{
+ EShellUserCreatableItemsHandlerPrivate *priv;
+ BonoboUIComponent *ui_component;
+ GtkWidget *combo_button;
+ GtkWidget *menu;
+ BonoboControl *control;
+
+ priv = handler->priv;
+
+ menu = gtk_menu_new ();
+
+ 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);
+
+ gtk_signal_connect (GTK_OBJECT (combo_button), "activate_default",
+ GTK_SIGNAL_FUNC (combo_button_activate_default_callback),
+ shell_view);
+
+ ui_component = e_shell_view_get_bonobo_ui_component (shell_view);
+ bonobo_window_add_popup (BONOBO_WINDOW (shell_view), GTK_MENU (menu), "/popups/NewPopup");
+
+ control = bonobo_control_new (combo_button);
+
+ bonobo_ui_component_object_set (ui_component, "/Toolbar/NewComboButton",
+ BONOBO_OBJREF (control), NULL);
+
+ gtk_object_set_data (GTK_OBJECT (shell_view), COMBO_BUTTON_WIDGET_KEY, combo_button);
+}
+
+
+/* This handles the menus for a given EShellView. We have to rebuild the menu
+ and set the toolbar button every time the view changes, and clean up when
+ the view is destroyed. */
+
+static void
+shell_view_view_changed_callback (EShellView *shell_view,
+ const char *evolution_path,
+ const char *physical_uri,
+ const char *folder_type,
+ const char *component_id,
+ void *data)
+{
+ EShellUserCreatableItemsHandler *handler;
+ EShellUserCreatableItemsHandlerPrivate *priv;
+ GtkWidget *combo_button_widget;
+ const MenuItem *default_menu_item;
+
+ handler = E_SHELL_USER_CREATABLE_ITEMS_HANDLER (data);
+ priv = handler->priv;
+
+ combo_button_widget = gtk_object_get_data (GTK_OBJECT (shell_view), COMBO_BUTTON_WIDGET_KEY);
+ g_assert (E_IS_COMBO_BUTTON (combo_button_widget));
+
+ default_menu_item = get_default_action_for_view (handler, shell_view);
+ 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);
+ return;
+ }
+
+ gtk_widget_set_sensitive (combo_button_widget, TRUE);
+
+ /* FIXME: This is temporary. We should just always say "New" once we
+ have the icons for all the actions. */
+ e_combo_button_set_label (E_COMBO_BUTTON (combo_button_widget), default_menu_item->label);
+
+ e_combo_button_set_icon (E_COMBO_BUTTON (combo_button_widget), default_menu_item->icon);
+}
+
+
/* GtkObject methods. */
static void
@@ -371,6 +571,8 @@ impl_destroy (GtkObject *object)
g_free (priv->menu_xml);
+ free_menu_items (priv->menu_items);
+
g_free (priv);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@@ -393,6 +595,7 @@ init (EShellUserCreatableItemsHandler *shell_user_creatable_items_handler)
priv = g_new (EShellUserCreatableItemsHandlerPrivate, 1);
priv->components = NULL;
priv->menu_xml = NULL;
+ priv->menu_items = NULL;
shell_user_creatable_items_handler->priv = priv;
}
@@ -410,6 +613,7 @@ e_shell_user_creatable_items_handler_new (void)
void
e_shell_user_creatable_items_handler_add_component (EShellUserCreatableItemsHandler *handler,
+ const char *id,
EvolutionShellComponentClient *shell_component_client)
{
EShellUserCreatableItemsHandlerPrivate *priv;
@@ -422,15 +626,25 @@ e_shell_user_creatable_items_handler_add_component (EShellUserCreatableItemsHan
priv = handler->priv;
g_return_if_fail (priv->menu_xml == NULL);
- priv->components = g_slist_prepend (priv->components, component_new_from_client (shell_component_client));
+ priv->components = g_slist_prepend (priv->components, component_new (id, shell_component_client));
}
+
+/**
+ * e_shell_user_creatable_items_handler_attach_menus:
+ * @handler:
+ * @shell_view:
+ *
+ * Set up the menus and toolbar items for @shell_view. 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.).
+ **/
void
-e_shell_user_creatable_items_handler_setup_menus (EShellUserCreatableItemsHandler *handler,
- EShellView *shell_view)
+e_shell_user_creatable_items_handler_attach_menus (EShellUserCreatableItemsHandler *handler,
+ EShellView *shell_view)
{
- EShellUserCreatableItemsHandlerPrivate *priv;
BonoboUIComponent *ui_component;
+ EShellUserCreatableItemsHandlerPrivate *priv;
g_return_if_fail (handler != NULL);
g_return_if_fail (E_IS_SHELL_USER_CREATABLE_ITEMS_HANDLER (handler));
@@ -439,17 +653,20 @@ e_shell_user_creatable_items_handler_setup_menus (EShellUserCreatableItemsHandle
priv = handler->priv;
- if (priv->menu_xml == NULL)
- setup_menu_xml (handler);
-
- ui_component = e_shell_view_get_bonobo_ui_component (shell_view);
- g_assert (ui_component);
+ /* FIXME: Re-enable this. */
+ if (0) {
+ setup_toolbar_button (handler, shell_view);
+ gtk_signal_connect (GTK_OBJECT (shell_view), "view_changed",
+ GTK_SIGNAL_FUNC (shell_view_view_changed_callback), handler);
+ }
- add_verbs_to_ui_component (handler, ui_component);
+ ensure_menu_xml (handler);
- gtk_object_set_data (GTK_OBJECT (ui_component), SHELL_VIEW_DATA_KEY, shell_view); /* Yuck. */
+ add_verbs (handler, shell_view);
- bonobo_ui_component_set (ui_component, "/", priv->menu_xml, NULL);
+ ui_component = e_shell_view_get_bonobo_ui_component (shell_view);
+ bonobo_ui_component_set (ui_component, "/menu/File/New/NewItems", priv->menu_xml, NULL);
+ bonobo_ui_component_set (ui_component, "/popups/NewPopup", priv->menu_xml, NULL);
}
diff --git a/shell/e-shell-user-creatable-items-handler.h b/shell/e-shell-user-creatable-items-handler.h
index a743e234be..77a3b6b608 100644
--- a/shell/e-shell-user-creatable-items-handler.h
+++ b/shell/e-shell-user-creatable-items-handler.h
@@ -61,10 +61,11 @@ GtkType e_shell_user_creatable_items_handler_get_type
EShellUserCreatableItemsHandler *e_shell_user_creatable_items_handler_new (void);
void e_shell_user_creatable_items_handler_add_component (EShellUserCreatableItemsHandler *handler,
+ const char *id,
EvolutionShellComponentClient *shell_component_client);
-void e_shell_user_creatable_items_handler_setup_menus (EShellUserCreatableItemsHandler *handler,
- EShellView *shell_view);
+void e_shell_user_creatable_items_handler_attach_menus (EShellUserCreatableItemsHandler *handler,
+ EShellView *shell_view);
#ifdef __cplusplus
}
diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c
index 9a9b09bd9c..6545af81bd 100644
--- a/shell/e-shell-view.c
+++ b/shell/e-shell-view.c
@@ -147,6 +147,7 @@ struct _EShellViewPrivate {
enum {
SHORTCUT_BAR_VISIBILITY_CHANGED,
FOLDER_BAR_VISIBILITY_CHANGED,
+ VIEW_CHANGED,
LAST_SIGNAL
};
@@ -1167,6 +1168,18 @@ class_init (EShellViewClass *klass)
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
+ signals[VIEW_CHANGED]
+ = gtk_signal_new ("view_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EShellViewClass, view_changed),
+ e_marshal_NONE__POINTER_POINTER_POINTER_POINTER,
+ GTK_TYPE_NONE, 4,
+ GTK_TYPE_STRING,
+ GTK_TYPE_STRING,
+ GTK_TYPE_STRING,
+ GTK_TYPE_STRING);
+
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
load_images ();
@@ -1407,8 +1420,8 @@ e_shell_view_construct (EShellView *shell_view,
GTK_SIGNAL_FUNC (storage_set_removed_folder_callback), shell_view,
GTK_OBJECT (shell_view));
- e_shell_user_creatable_items_handler_setup_menus (e_shell_get_user_creatable_items_handler (priv->shell),
- shell_view);
+ e_shell_user_creatable_items_handler_attach_menus (e_shell_get_user_creatable_items_handler (priv->shell),
+ shell_view);
return view;
}
@@ -2044,6 +2057,12 @@ e_shell_view_display_uri (EShellView *shell_view,
bonobo_window_thaw (BONOBO_WINDOW (shell_view));
+ gtk_signal_emit (GTK_OBJECT (shell_view), signals[VIEW_CHANGED],
+ e_shell_view_get_current_path (shell_view),
+ e_shell_view_get_current_uri (shell_view),
+ e_shell_view_get_current_folder_type (shell_view),
+ e_shell_view_get_current_component_id (shell_view));
+
return retval;
}
@@ -2269,6 +2288,23 @@ e_shell_view_get_current_folder_type (EShellView *shell_view)
return get_type_for_folder (shell_view, current_path, NULL);
}
+const char *
+e_shell_view_get_current_component_id (EShellView *shell_view)
+{
+ EShellViewPrivate *priv;
+ EFolderTypeRegistry *type_registry;
+ EvolutionShellComponentClient *component_client;
+ const char *current_folder_type;
+
+ priv = shell_view->priv;
+
+ type_registry = e_shell_get_folder_type_registry (priv->shell);
+ current_folder_type = e_shell_view_get_current_folder_type (shell_view);
+ component_client = e_folder_type_registry_get_handler_for_type (type_registry, current_folder_type);
+
+ return evolution_shell_component_client_get_id (component_client);
+}
+
/**
* e_shell_view_save_settings:
diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h
index 9738171b9a..c5ba207e24 100644
--- a/shell/e-shell-view.h
+++ b/shell/e-shell-view.h
@@ -57,8 +57,17 @@ struct _EShellViewClass {
BonoboWindowClass parent_class;
/* Signals. */
- void (* shortcut_bar_visibility_changed) (EShellView *shell_view, gboolean visible);
- void (* folder_bar_visibility_changed) (EShellView *shell_view, gboolean visible);
+
+ void (* shortcut_bar_visibility_changed) (EShellView *shell_view,
+ gboolean visible);
+ void (* folder_bar_visibility_changed) (EShellView *shell_view,
+ gboolean visible);
+
+ void (* view_changed) (EShellView *shell_view,
+ const char *evolution_path,
+ const char *physical_uri,
+ const char *folder_type,
+ const char *component_id);
};
@@ -93,6 +102,7 @@ GtkWidget *e_shell_view_get_appbar (EShellView *shell_vi
const char *e_shell_view_get_current_uri (EShellView *shell_view);
const char *e_shell_view_get_current_physical_uri (EShellView *shell_view);
const char *e_shell_view_get_current_folder_type (EShellView *shell_view);
+const char *e_shell_view_get_current_component_id (EShellView *shell_view);
const char *e_shell_view_get_current_path (EShellView *shell_view);
gboolean e_shell_view_save_settings (EShellView *shell_view,
diff --git a/shell/e-shell.c b/shell/e-shell.c
index abcd11819f..1923226ca0 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -742,6 +742,7 @@ setup_components (EShell *shell,
} else {
e_shell_user_creatable_items_handler_add_component
(priv->user_creatable_items_handler,
+ info->iid,
e_component_registry_get_component_by_id (priv->component_registry, info->iid));
}
diff --git a/shell/evolution-activity-client.c b/shell/evolution-activity-client.c
index 5de8a4c217..6ecea011d7 100644
--- a/shell/evolution-activity-client.c
+++ b/shell/evolution-activity-client.c
@@ -31,6 +31,8 @@
#include "evolution-activity-client.h"
+#include "e-shell-corba-icon-utils.h"
+
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
@@ -78,76 +80,6 @@ struct _EvolutionActivityClientPrivate {
/* Utility functions. */
-/* Create an icon from @pixbuf in @icon_return. */
-static void
-create_icon_from_pixbuf (GdkPixbuf *pixbuf,
- GNOME_Evolution_Icon *icon_return)
-{
- const char *sp;
- CORBA_octet *dp;
- int width, height, total_width, rowstride;
- int i, j;
- gboolean has_alpha;
-
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
-
- if (has_alpha)
- total_width = 4 * width;
- else
- total_width = 3 * width;
-
- icon_return->width = width;
- icon_return->height = height;
- icon_return->hasAlpha = has_alpha;
-
- icon_return->rgbaData._length = icon_return->height * total_width;
- icon_return->rgbaData._maximum = icon_return->rgbaData._length;
- icon_return->rgbaData._buffer = CORBA_sequence_CORBA_octet_allocbuf (icon_return->rgbaData._maximum);
-
- sp = gdk_pixbuf_get_pixels (pixbuf);
- dp = icon_return->rgbaData._buffer;
- for (i = 0; i < height; i ++) {
- for (j = 0; j < total_width; j++)
- *(dp ++) = sp[j];
- sp += rowstride;
- }
-
- CORBA_sequence_set_release (& icon_return->rgbaData, TRUE);
-}
-
-/* Generate an AnimatedIcon from a NULL-terminated @pixbuf_array. */
-static GNOME_Evolution_AnimatedIcon *
-create_corba_animated_icon_from_pixbuf_array (GdkPixbuf **pixbuf_array)
-{
- GNOME_Evolution_AnimatedIcon *animated_icon;
- GdkPixbuf **p;
- int num_frames;
- int i;
-
- num_frames = 0;
- for (p = pixbuf_array; *p != NULL; p++)
- num_frames++;
-
- if (num_frames == 0)
- return NULL;
-
- animated_icon = GNOME_Evolution_AnimatedIcon__alloc ();
-
- animated_icon->_length = num_frames;
- animated_icon->_maximum = num_frames;
- animated_icon->_buffer = CORBA_sequence_GNOME_Evolution_Icon_allocbuf (animated_icon->_maximum);
-
- for (i = 0; i < num_frames; i++)
- create_icon_from_pixbuf (pixbuf_array[i], & animated_icon->_buffer[i]);
-
- CORBA_sequence_set_release (animated_icon, TRUE);
-
- return animated_icon;
-}
-
static gboolean
corba_update_progress (EvolutionActivityClient *activity_client,
const char *information,
@@ -350,7 +282,7 @@ evolution_activity_client_construct (EvolutionActivityClient *activity_client,
return FALSE;
}
- corba_animated_icon = create_corba_animated_icon_from_pixbuf_array (animated_icon);
+ corba_animated_icon = e_new_corba_animated_icon_from_pixbuf_array (animated_icon);
GNOME_Evolution_Activity_operationStarted (activity_interface,
component_id,
diff --git a/shell/evolution-shell-component-client.c b/shell/evolution-shell-component-client.c
index 4b35e2ac7a..574b75ecc8 100644
--- a/shell/evolution-shell-component-client.c
+++ b/shell/evolution-shell-component-client.c
@@ -44,6 +44,8 @@ char *evolution_debug_log;
static BonoboObjectClass *parent_class = NULL;
struct _EvolutionShellComponentClientPrivate {
+ char *id;
+
EvolutionShellComponentClientCallback callback;
void *callback_data;
@@ -298,6 +300,8 @@ impl_destroy (GtkObject *object)
shell_component_client = EVOLUTION_SHELL_COMPONENT_CLIENT (object);
priv = shell_component_client->priv;
+ g_free (priv->id);
+
if (priv->callback != NULL)
dispatch_callback (shell_component_client, EVOLUTION_SHELL_COMPONENT_INTERRUPTED);
@@ -347,6 +351,8 @@ init (EvolutionShellComponentClient *shell_component_client)
priv = g_new (EvolutionShellComponentClientPrivate, 1);
+ priv->id = NULL;
+
priv->listener_interface = CORBA_OBJECT_NIL;
priv->listener_servant = NULL;
@@ -365,12 +371,18 @@ init (EvolutionShellComponentClient *shell_component_client)
void
evolution_shell_component_client_construct (EvolutionShellComponentClient *shell_component_client,
+ const char *id,
CORBA_Object corba_object)
{
+ EvolutionShellComponentClientPrivate *priv;
+
g_return_if_fail (shell_component_client != NULL);
g_return_if_fail (EVOLUTION_IS_SHELL_COMPONENT_CLIENT (shell_component_client));
g_return_if_fail (corba_object != CORBA_OBJECT_NIL);
+ priv = shell_component_client->priv;
+ priv->id = g_strdup (id);
+
bonobo_object_client_construct (BONOBO_OBJECT_CLIENT (shell_component_client),
corba_object);
}
@@ -378,6 +390,7 @@ evolution_shell_component_client_construct (EvolutionShellComponentClient *shell
EvolutionShellComponentClient *
evolution_shell_component_client_new (const char *id)
{
+ EvolutionShellComponentClient *new;
CORBA_Environment ev;
CORBA_Object corba_object;
@@ -392,12 +405,6 @@ evolution_shell_component_client_new (const char *id)
return NULL;
}
-#if 0
- ior = CORBA_ORB_object_to_string (bonobo_orb (), corba_object, &ev);
- g_print ("--- %s %s\n", id, ior);
- CORBA_free (ior);
-#endif
-
CORBA_exception_free (&ev);
if (corba_object == CORBA_OBJECT_NIL) {
@@ -406,20 +413,26 @@ evolution_shell_component_client_new (const char *id)
return NULL;
}
- return evolution_shell_component_client_new_for_objref (corba_object);
+ new = gtk_type_new (evolution_shell_component_client_get_type ());
+ evolution_shell_component_client_construct (new, id, corba_object);
+
+ return new;
}
-EvolutionShellComponentClient *
-evolution_shell_component_client_new_for_objref (const GNOME_Evolution_ShellComponent objref)
+
+/* Properties. */
+
+const char *
+evolution_shell_component_client_get_id (EvolutionShellComponentClient *shell_component_client)
{
- EvolutionShellComponentClient *new;
+ EvolutionShellComponentClientPrivate *priv;
- g_return_val_if_fail (objref != CORBA_OBJECT_NIL, NULL);
+ g_return_val_if_fail (shell_component_client != NULL, NULL);
+ g_return_val_if_fail (EVOLUTION_IS_SHELL_COMPONENT_CLIENT (shell_component_client), NULL);
- new = gtk_type_new (evolution_shell_component_client_get_type ());
- evolution_shell_component_client_construct (new, objref);
+ priv = shell_component_client->priv;
- return new;
+ return priv->id;
}
diff --git a/shell/evolution-shell-component-client.h b/shell/evolution-shell-component-client.h
index bea54f4b35..33b8cd92d3 100644
--- a/shell/evolution-shell-component-client.h
+++ b/shell/evolution-shell-component-client.h
@@ -61,11 +61,15 @@ typedef void (* EvolutionShellComponentClientCallback) (EvolutionShellComponentC
/* Construction. */
-GtkType evolution_shell_component_client_get_type (void);
-void evolution_shell_component_client_construct (EvolutionShellComponentClient *shell_component_client,
- CORBA_Object corba_object);
-EvolutionShellComponentClient *evolution_shell_component_client_new (const char *id);
-EvolutionShellComponentClient *evolution_shell_component_client_new_for_objref (const GNOME_Evolution_ShellComponent objref);
+GtkType evolution_shell_component_client_get_type (void);
+void evolution_shell_component_client_construct (EvolutionShellComponentClient *shell_component_client,
+ const char *id,
+ CORBA_Object corba_object);
+EvolutionShellComponentClient *evolution_shell_component_client_new (const char *id);
+
+/* Properties. */
+
+const char *evolution_shell_component_client_get_id (EvolutionShellComponentClient *shell_component_client);
/* Querying DnD interfaces. */
diff --git a/shell/evolution-shell-component.c b/shell/evolution-shell-component.c
index a253b9278c..0357a20921 100644
--- a/shell/evolution-shell-component.c
+++ b/shell/evolution-shell-component.c
@@ -26,6 +26,8 @@
#include "evolution-shell-component.h"
+#include "e-shell-corba-icon-utils.h"
+
#include <fcntl.h>
#include <glib.h>
@@ -35,8 +37,6 @@
#include <gal/util/e-util.h>
-#include "Evolution.h"
-
#define PING_DELAY 10000
@@ -50,6 +50,7 @@ struct _UserCreatableItemType {
char *description;
char *menu_description;
char menu_shortcut;
+ GdkPixbuf *icon;
};
typedef struct _UserCreatableItemType UserCreatableItemType;
@@ -93,7 +94,8 @@ static UserCreatableItemType *
user_creatable_item_type_new (const char *id,
const char *description,
const char *menu_description,
- char menu_shortcut)
+ char menu_shortcut,
+ GdkPixbuf *icon)
{
UserCreatableItemType *type;
@@ -103,6 +105,11 @@ user_creatable_item_type_new (const char *id,
type->menu_description = g_strdup (menu_description);
type->menu_shortcut = menu_shortcut;
+ if (icon == NULL)
+ type->icon = NULL;
+ else
+ type->icon = gdk_pixbuf_ref (icon);
+
return type;
}
@@ -113,6 +120,9 @@ user_creatable_item_type_free (UserCreatableItemType *type)
g_free (type->description);
g_free (type->menu_description);
+ if (type->icon != NULL)
+ gdk_pixbuf_unref (type->icon);
+
g_free (type);
}
@@ -350,6 +360,8 @@ impl__get_userCreatableItemTypes (PortableServer_Servant servant,
corba_type->description = CORBA_string_dup (type->description);
corba_type->menuDescription = CORBA_string_dup (type->menu_description);
corba_type->menuShortcut = type->menu_shortcut;
+
+ e_store_corba_icon_from_pixbuf (type->icon, & corba_type->icon);
}
CORBA_sequence_set_release (list, TRUE);
@@ -978,7 +990,8 @@ evolution_shell_component_add_user_creatable_item (EvolutionShellComponent *she
const char *id,
const char *description,
const char *menu_description,
- char menu_shortcut)
+ char menu_shortcut,
+ GdkPixbuf *icon)
{
EvolutionShellComponentPrivate *priv;
UserCreatableItemType *type;
@@ -991,7 +1004,7 @@ evolution_shell_component_add_user_creatable_item (EvolutionShellComponent *she
priv = shell_component->priv;
- type = user_creatable_item_type_new (id, description, menu_description, menu_shortcut);
+ type = user_creatable_item_type_new (id, description, menu_description, menu_shortcut, icon);
priv->user_creatable_item_types = g_slist_prepend (priv->user_creatable_item_types, type);
}
diff --git a/shell/evolution-shell-component.h b/shell/evolution-shell-component.h
index 3a3a1cff5e..7f7073572e 100644
--- a/shell/evolution-shell-component.h
+++ b/shell/evolution-shell-component.h
@@ -23,13 +23,15 @@
#ifndef EVOLUTION_SHELL_COMPONENT_H
#define EVOLUTION_SHELL_COMPONENT_H
-#include <bonobo/bonobo-xobject.h>
-#include <bonobo/bonobo-control.h>
-
#include "Evolution.h"
#include "evolution-shell-client.h"
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <bonobo/bonobo-xobject.h>
+#include <bonobo/bonobo-control.h>
+
#ifdef cplusplus
extern "C" {
#pragma }
@@ -181,7 +183,8 @@ void evolution_shell_component_add_user_creatable_item (EvolutionShellComponen
const char *id,
const char *description,
const char *menu_description,
- char menu_shortcut);
+ char menu_shortcut,
+ GdkPixbuf *icon);
const char *evolution_shell_component_result_to_string (EvolutionShellComponentResult result);
diff --git a/shell/evolution-storage-listener.h b/shell/evolution-storage-listener.h
index 084d4acc19..5e13435411 100644
--- a/shell/evolution-storage-listener.h
+++ b/shell/evolution-storage-listener.h
@@ -34,8 +34,8 @@ extern "C" {
#define EVOLUTION_TYPE_STORAGE_LISTENER (evolution_storage_listener_get_type ())
#define EVOLUTION_STORAGE_LISTENER(obj) (GTK_CHECK_CAST ((obj), EVOLUTION_TYPE_STORAGE_LISTENER, EvolutionStorageListener))
#define EVOLUTION_STORAGE_LISTENER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_STORAGE_LISTENER, EvolutionStorageListenerClass))
-#define EVOLUTION_IS_STORAGE_LISTENER(obj) (GTK_CHECK_TYPE ((obj), EVOLUTION_TYPE_STORAGE_LISTENER))
-#define EVOLUTION_IS_STORAGE_LISTENER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_STORAGE_LISTENER))
+#define EVOLUTION_IS_STORAGE_LISTENER(obj) (GTK_CHECK_TYPE ((obj), EVOLUTION_TYPE_STORAGE_LISTENER))
+#define EVOLUTION_IS_STORAGE_LISTENER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_STORAGE_LISTENER))
typedef struct _EvolutionStorageListener EvolutionStorageListener;
diff --git a/shell/evolution-test-component.c b/shell/evolution-test-component.c
index 23358ab6a6..8cf0856b88 100644
--- a/shell/evolution-test-component.c
+++ b/shell/evolution-test-component.c
@@ -312,8 +312,10 @@ register_component (void)
gtk_signal_connect (GTK_OBJECT (shell_component), "owner_unset",
GTK_SIGNAL_FUNC (owner_unset_callback), NULL);
- evolution_shell_component_add_user_creatable_item (shell_component, "Stuff", "New Stuff", "New _Stuff", '\0');
- evolution_shell_component_add_user_creatable_item (shell_component, "MoreStuff", "New More Stuff", "New _More Stuff", 'n');
+ evolution_shell_component_add_user_creatable_item (shell_component, "Stuff",
+ "New Stuff", "New _Stuff", '\0', NULL);
+ evolution_shell_component_add_user_creatable_item (shell_component, "MoreStuff",
+ "New More Stuff", "New _More Stuff", 'n', NULL);
gtk_signal_connect (GTK_OBJECT (shell_component), "user_create_new_item",
GTK_SIGNAL_FUNC (user_create_new_item_callback), NULL);
diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog
index 5fd0471bb5..f59af32bcf 100644
--- a/widgets/misc/ChangeLog
+++ b/widgets/misc/ChangeLog
@@ -1,3 +1,24 @@
+2002-01-23 Ettore Perazzoli <ettore@ximian.com>
+
+ * e-combo-button.c: Remove member `separator' from
+ `EComboButtonPrivate'. New members `icon', `label'.
+ (init): There shall be no separator no more. Init `icon' and
+ `label' to %NULL.
+ (e_combo_button_construct): Set no relief.
+ (e_combo_button_new): Don't get a @menu arg anymore.
+ (e_combo_button_construct): Likewise.
+ (e_combo_button_set_icon): New.
+ (e_combo_button_set_label): New.
+ (e_combo_button_set_menu): New.
+ (impl_clicked): New, overriding the "clicked" method for
+ GtkButton.
+ (class_init): Install.
+ (impl_button_release_event): Removed.
+ (class_init): No need to override ::release_event with this
+ anymore.
+ (impl_released): New, override for the GtkButton::released method.
+ (class_init): Install.
+
2002-01-04 Jeffrey Stedfast <fejj@ximian.com>
* e-charset-picker.c: Added iso-8859-8 (Hebrew; Visual) to the
diff --git a/widgets/misc/e-combo-button.c b/widgets/misc/e-combo-button.c
index 9f5a536ff2..c037586fc6 100644
--- a/widgets/misc/e-combo-button.c
+++ b/widgets/misc/e-combo-button.c
@@ -26,7 +26,6 @@
#include "e-combo-button.h"
-#include <gtk/gtkvseparator.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkmain.h>
@@ -36,17 +35,13 @@
#include <gal/util/e-util.h>
-enum {
- ACTIVATE_DEFAULT,
- LAST_SIGNAL
-};
-
-
struct _EComboButtonPrivate {
+ GdkPixbuf *icon;
+
+ GtkWidget *icon_pixmap;
+ GtkWidget *label;
GtkWidget *arrow_pixmap;
GtkWidget *hbox;
- GtkWidget *separator;
- GtkWidget *label_hbox;
GtkMenu *menu;
@@ -56,7 +51,7 @@ struct _EComboButtonPrivate {
#define SPACING 2
-static char *arrow_xpm[] = {
+static const char *arrow_xpm[] = {
"11 5 2 1",
" c none",
". c #000000000000",
@@ -70,7 +65,82 @@ static char *arrow_xpm[] = {
#define PARENT_TYPE gtk_button_get_type ()
static GtkButtonClass *parent_class = NULL;
-static guint combo_button_signals[LAST_SIGNAL] = { 0 };
+
+enum {
+ ACTIVATE_DEFAULT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+/* Utility functions. */
+
+static GtkWidget *
+create_pixmap_widget_from_pixbuf (GdkPixbuf *pixbuf)
+{
+ GtkWidget *pixmap_widget;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+
+ gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &mask, 128);
+
+ pixmap_widget = gtk_pixmap_new (pixmap, mask);
+
+ gdk_pixmap_unref (pixmap);
+ gdk_bitmap_unref (mask);
+
+ return pixmap_widget;
+}
+
+static GtkWidget *
+create_empty_pixmap_widget (void)
+{
+ GtkWidget *pixmap_widget;
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
+
+ pixmap_widget = create_pixmap_widget_from_pixbuf (pixbuf);
+
+ gdk_pixbuf_unref (pixbuf);
+
+ return pixmap_widget;
+}
+
+static GtkWidget *
+create_arrow_pixmap_widget (void)
+{
+ GtkWidget *pixmap_widget;
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_xpm_data (arrow_xpm);
+
+ pixmap_widget = create_pixmap_widget_from_pixbuf (pixbuf);
+
+ gdk_pixbuf_unref (pixbuf);
+
+ return pixmap_widget;
+}
+
+static void
+set_icon (EComboButton *combo_button,
+ GdkPixbuf *pixbuf)
+{
+ EComboButtonPrivate *priv;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+
+ priv = combo_button->priv;
+
+ priv->icon = gdk_pixbuf_ref (pixbuf);
+
+ gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &mask, 128);
+ gtk_pixmap_set (GTK_PIXMAP (priv->icon_pixmap), pixmap, mask);
+
+ gdk_pixmap_unref (pixmap);
+ gdk_pixmap_unref (mask);
+}
/* Callbacks for the associated menu. */
@@ -140,6 +210,11 @@ impl_destroy (GtkObject *object)
priv->arrow_pixmap = NULL;
}
+ if (priv->icon != NULL) {
+ gdk_pixbuf_unref (priv->icon);
+ priv->icon = NULL;
+ }
+
g_free (priv);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@@ -148,48 +223,6 @@ impl_destroy (GtkObject *object)
/* GtkWidget methods. */
-static void
-impl_realize (GtkWidget *widget)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
- GdkPixmap *arrow_gdk_pixmap;
- GdkBitmap *arrow_gdk_mask;
-
- combo_button = E_COMBO_BUTTON (widget);
- priv = combo_button->priv;
-
- (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
-
- g_assert (priv->arrow_pixmap == NULL);
-
- arrow_gdk_pixmap = gdk_pixmap_create_from_xpm_d (widget->window, &arrow_gdk_mask, NULL, arrow_xpm);
- priv->arrow_pixmap = gtk_pixmap_new (arrow_gdk_pixmap, arrow_gdk_mask);
- gtk_widget_show (priv->arrow_pixmap);
-
- gtk_box_pack_start (GTK_BOX (priv->hbox), priv->arrow_pixmap, FALSE, TRUE, SPACING);
-
- gdk_pixmap_unref (arrow_gdk_pixmap);
- gdk_bitmap_unref (arrow_gdk_mask);
-}
-
-static void
-impl_unrealize (GtkWidget *widget)
-{
- EComboButton *combo_button;
- EComboButtonPrivate *priv;
-
- combo_button = E_COMBO_BUTTON (widget);
- priv = combo_button->priv;
-
- (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
-
- if (priv->arrow_pixmap != NULL) {
- gtk_widget_destroy (priv->arrow_pixmap);
- priv->arrow_pixmap = NULL;
- }
-}
-
static int
impl_button_press_event (GtkWidget *widget,
GdkEventButton *event)
@@ -203,7 +236,7 @@ impl_button_press_event (GtkWidget *widget,
if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
GTK_BUTTON (widget)->button_down = TRUE;
- if (event->x >= priv->separator->allocation.x) {
+ if (event->x >= priv->arrow_pixmap->allocation.x) {
/* User clicked on the right side: pop up the menu. */
gtk_button_pressed (GTK_BUTTON (widget));
@@ -223,18 +256,6 @@ impl_button_press_event (GtkWidget *widget,
}
static int
-impl_button_release_event (GtkWidget *widget,
- GdkEventButton *event)
-{
- if (event->button == 1) {
- gtk_grab_remove (widget);
- gtk_button_released (GTK_BUTTON (widget));
- }
-
- return TRUE;
-}
-
-static int
impl_leave_notify_event (GtkWidget *widget,
GdkEventCrossing *event)
{
@@ -255,38 +276,77 @@ impl_leave_notify_event (GtkWidget *widget,
}
+/* GtkButton methods. */
+
+static void
+impl_released (GtkButton *button)
+{
+ EComboButton *combo_button;
+ EComboButtonPrivate *priv;
+
+ combo_button = E_COMBO_BUTTON (button);
+ priv = combo_button->priv;
+
+ /* Massive cut & paste from GtkButton here... The only change in
+ behavior here is that we want to emit ::activate_default when not
+ the menu hasn't been popped up. */
+
+ if (button->button_down) {
+ int new_state;
+
+ button->button_down = FALSE;
+
+ if (button->in_button) {
+ gtk_button_clicked (button);
+
+ if (! priv->menu_popped_up)
+ gtk_signal_emit (GTK_OBJECT (button), signals[ACTIVATE_DEFAULT]);
+ }
+
+ new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+
+ if (GTK_WIDGET_STATE (button) != new_state) {
+ gtk_widget_set_state (GTK_WIDGET (button), new_state);
+
+ /* We _draw () instead of queue_draw so that if the
+ operation blocks, the label doesn't vanish. */
+ gtk_widget_draw (GTK_WIDGET (button), NULL);
+ }
+ }
+}
+
+
static void
class_init (GtkObjectClass *object_class)
{
GtkWidgetClass *widget_class;
+ GtkButtonClass *button_class;
parent_class = gtk_type_class (PARENT_TYPE);
object_class->destroy = impl_destroy;
widget_class = GTK_WIDGET_CLASS (object_class);
- widget_class->realize = impl_realize;
- widget_class->unrealize = impl_unrealize;
- widget_class->button_press_event = impl_button_press_event;
- widget_class->button_release_event = impl_button_release_event;
- widget_class->leave_notify_event = impl_leave_notify_event;
-
- combo_button_signals[ACTIVATE_DEFAULT] =
- gtk_signal_new ("activate_default",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EComboButtonClass, activate_default),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- gtk_object_class_add_signals (object_class, combo_button_signals, LAST_SIGNAL);
+ widget_class->button_press_event = impl_button_press_event;
+ widget_class->leave_notify_event = impl_leave_notify_event;
+
+ button_class = GTK_BUTTON_CLASS (object_class);
+ button_class->released = impl_released;
+
+ signals[ACTIVATE_DEFAULT] = gtk_signal_new ("activate_default",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EComboButtonClass, activate_default),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
}
static void
init (EComboButton *combo_button)
{
EComboButtonPrivate *priv;
- GtkWidget *label;
priv = g_new (EComboButtonPrivate, 1);
combo_button->priv = priv;
@@ -295,58 +355,106 @@ init (EComboButton *combo_button)
gtk_container_add (GTK_CONTAINER (combo_button), priv->hbox);
gtk_widget_show (priv->hbox);
- priv->label_hbox = gtk_hbox_new (FALSE, SPACING);
- gtk_box_pack_start (GTK_BOX (priv->hbox), priv->label_hbox, TRUE, TRUE, 0);
- gtk_widget_show (priv->label_hbox);
+ priv->icon_pixmap = create_empty_pixmap_widget ();
+ gtk_box_pack_start (GTK_BOX (priv->hbox), priv->icon_pixmap, TRUE, TRUE, 0);
+ gtk_widget_show (priv->icon_pixmap);
- priv->separator = gtk_vseparator_new ();
- gtk_box_pack_start (GTK_BOX (priv->hbox), priv->separator, FALSE, TRUE, SPACING);
- gtk_widget_show (priv->separator);
+ priv->label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (priv->hbox), priv->label, TRUE, TRUE, 0);
+ gtk_widget_show (priv->label);
- label = gtk_label_new ("TEST!!!");
- gtk_container_add (GTK_CONTAINER (priv->label_hbox), label);
- gtk_widget_show (label);
+ priv->arrow_pixmap = create_arrow_pixmap_widget ();
+ gtk_box_pack_start (GTK_BOX (priv->hbox), priv->arrow_pixmap, TRUE, TRUE, 0);
+ gtk_widget_show (priv->arrow_pixmap);
- priv->arrow_pixmap = NULL;
+ priv->icon = NULL;
priv->menu = NULL;
priv->menu_popped_up = FALSE;
}
void
-e_combo_button_construct (EComboButton *combo_button,
- GtkMenu *menu)
+e_combo_button_construct (EComboButton *combo_button)
{
EComboButtonPrivate *priv;
g_return_if_fail (combo_button != NULL);
g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
- g_return_if_fail (menu != NULL);
- g_return_if_fail (GTK_IS_MENU (menu));
priv = combo_button->priv;
g_return_if_fail (priv->menu == NULL);
- priv->menu = menu;
- gtk_menu_attach_to_widget (menu, GTK_WIDGET (combo_button), menu_detacher);
-
- gtk_signal_connect (GTK_OBJECT (menu), "deactivate",
- GTK_SIGNAL_FUNC (menu_deactivate_callback),
- combo_button);
-
GTK_WIDGET_UNSET_FLAGS (combo_button, GTK_CAN_FOCUS);
+
+ gtk_button_set_relief (GTK_BUTTON (combo_button), GTK_RELIEF_NONE);
}
GtkWidget *
-e_combo_button_new (GtkMenu *menu)
+e_combo_button_new (void)
{
- GtkWidget *new;
+ EComboButton *new;
new = gtk_type_new (e_combo_button_get_type ());
+ e_combo_button_construct (new);
- e_combo_button_construct (E_COMBO_BUTTON (new), menu);
+ return GTK_WIDGET (new);
+}
+
+
+void
+e_combo_button_set_icon (EComboButton *combo_button,
+ GdkPixbuf *pixbuf)
+{
+ g_return_if_fail (combo_button != NULL);
+ g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
+ g_return_if_fail (pixbuf != NULL);
+
+ set_icon (combo_button, pixbuf);
+}
+
+void
+e_combo_button_set_label (EComboButton *combo_button,
+ const char *label)
+{
+ EComboButtonPrivate *priv;
+
+ g_return_if_fail (combo_button != NULL);
+ g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
+ g_return_if_fail (label != NULL);
+
+ priv = combo_button->priv;
+
+ if (label == NULL)
+ label = "";
+
+ gtk_label_parse_uline (GTK_LABEL (priv->label), label);
+}
+
+void
+e_combo_button_set_menu (EComboButton *combo_button,
+ GtkMenu *menu)
+{
+ EComboButtonPrivate *priv;
+
+ g_return_if_fail (combo_button != NULL);
+ g_return_if_fail (E_IS_COMBO_BUTTON (combo_button));
+ g_return_if_fail (menu != NULL);
+ g_return_if_fail (GTK_IS_MENU (menu));
- return new;
+ priv = combo_button->priv;
+
+ if (priv->menu != NULL)
+ gtk_menu_detach (priv->menu);
+
+ priv->menu = menu;
+ if (menu == NULL)
+ return;
+
+ gtk_menu_attach_to_widget (menu, GTK_WIDGET (combo_button), menu_detacher);
+
+ gtk_signal_connect (GTK_OBJECT (menu), "deactivate",
+ GTK_SIGNAL_FUNC (menu_deactivate_callback),
+ combo_button);
}
diff --git a/widgets/misc/e-combo-button.h b/widgets/misc/e-combo-button.h
index 7634194427..a0ad8af8f6 100644
--- a/widgets/misc/e-combo-button.h
+++ b/widgets/misc/e-combo-button.h
@@ -30,6 +30,8 @@
#include <gtk/gtkbutton.h>
#include <gtk/gtkmenu.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
#ifdef __cplusplus
extern "C" {
#pragma }
@@ -60,10 +62,16 @@ struct _EComboButtonClass {
};
-GtkType e_combo_button_get_type (void);
-void e_combo_button_construct (EComboButton *combo_button,
+GtkType e_combo_button_get_type (void);
+void e_combo_button_construct (EComboButton *combo_button);
+GtkWidget *e_combo_button_new (void);
+
+void e_combo_button_set_icon (EComboButton *combo_button,
+ GdkPixbuf *pixbuf);
+void e_combo_button_set_label (EComboButton *combo_button,
+ const char *label);
+void e_combo_button_set_menu (EComboButton *combo_button,
GtkMenu *menu);
-GtkWidget *e_combo_button_new (GtkMenu *menu);
#ifdef __cplusplus
}