aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/misc
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2009-01-20 08:05:40 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2009-01-20 08:05:40 +0800
commit22d41a51fae2d18315887b05000cf7facc36e887 (patch)
tree044eaaa852ca31a11ea70ec8bfa33c6df8c01891 /widgets/misc
parent8e546420df08f5fe243aa4227be44915fd79b86b (diff)
downloadgsoc2013-evolution-22d41a51fae2d18315887b05000cf7facc36e887.tar.gz
gsoc2013-evolution-22d41a51fae2d18315887b05000cf7facc36e887.tar.zst
gsoc2013-evolution-22d41a51fae2d18315887b05000cf7facc36e887.zip
Formalize the "no disabled items in popup menus" policy in the form of a
GtkAction subclass called EPopupAction. Migrate all the modules over to using EPopupActions in their popup menus. Add sensitivity management of GtkActions to EMailReader. Not finished. svn path=/branches/kill-bonobo/; revision=37106
Diffstat (limited to 'widgets/misc')
-rw-r--r--widgets/misc/Makefile.am2
-rw-r--r--widgets/misc/e-popup-action.c285
-rw-r--r--widgets/misc/e-popup-action.h95
3 files changed, 382 insertions, 0 deletions
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index e5ddeecc06..ce702ec9fd 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -57,6 +57,7 @@ widgetsinclude_HEADERS = \
e-image-chooser.h \
e-map.h \
e-menu-tool-button.h \
+ e-popup-action.h \
e-preferences-window.h \
e-online-button.h \
e-search-bar.h \
@@ -103,6 +104,7 @@ libemiscwidgets_la_SOURCES = \
e-image-chooser.c \
e-map.c \
e-menu-tool-button.c \
+ e-popup-action.c \
e-preferences-window.c \
e-online-button.c \
e-search-bar.c \
diff --git a/widgets/misc/e-popup-action.c b/widgets/misc/e-popup-action.c
new file mode 100644
index 0000000000..51abc01338
--- /dev/null
+++ b/widgets/misc/e-popup-action.c
@@ -0,0 +1,285 @@
+/*
+ * e-popup-action.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-popup-action.h"
+
+#include <glib/gi18n.h>
+#include "e-util/e-binding.h"
+
+#define E_POPUP_ACTION_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_POPUP_ACTION, EPopupActionPrivate))
+
+enum {
+ PROP_0,
+ PROP_SOURCE
+};
+
+struct _EPopupActionPrivate {
+ GtkAction *source;
+};
+
+static gpointer parent_class;
+
+static void
+popup_action_set_source (EPopupAction *popup_action,
+ GtkAction *source)
+{
+ g_return_if_fail (popup_action->priv->source == NULL);
+ g_return_if_fail (GTK_IS_ACTION (source));
+
+ popup_action->priv->source = g_object_ref (source);
+}
+
+static void
+popup_action_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ popup_action_set_source (
+ E_POPUP_ACTION (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+popup_action_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ g_value_set_object (
+ value, e_popup_action_get_source (
+ E_POPUP_ACTION (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+popup_action_dispose (GObject *object)
+{
+ EPopupActionPrivate *priv;
+
+ priv = E_POPUP_ACTION_GET_PRIVATE (object);
+
+ if (priv->source != NULL) {
+ g_object_unref (priv->source);
+ priv->source = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+popup_action_constructed (GObject *object)
+{
+ EPopupActionPrivate *priv;
+ GObject *source;
+ gchar *icon_name;
+ gchar *label;
+ gchar *stock_id;
+ gchar *tooltip;
+
+ priv = E_POPUP_ACTION_GET_PRIVATE (object);
+
+ source = G_OBJECT (priv->source);
+
+ g_object_get (
+ object, "icon-name", &icon_name, "label", &label,
+ "stock-id", &stock_id, "tooltip", &tooltip, NULL);
+
+ if (label == NULL)
+ e_binding_new (source, "label", object, "label");
+
+ if (tooltip == NULL)
+ e_binding_new (source, "tooltip", object, "tooltip");
+
+ if (icon_name == NULL && stock_id == NULL) {
+ g_free (icon_name);
+ g_free (stock_id);
+
+ g_object_get (
+ source, "icon-name", &icon_name,
+ "stock-id", &stock_id, NULL);
+
+ if (icon_name == NULL) {
+ e_binding_new (
+ source, "icon-name", object, "icon-name");
+ e_binding_new (
+ source, "stock-id", object, "stock-id");
+ } else {
+ e_binding_new (
+ source, "stock-id", object, "stock-id");
+ e_binding_new (
+ source, "icon-name", object, "icon-name");
+ }
+ }
+
+ e_binding_new (source, "sensitive", object, "visible");
+
+ g_free (icon_name);
+ g_free (label);
+ g_free (stock_id);
+ g_free (tooltip);
+}
+
+static void
+popup_action_class_init (EPopupActionClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EPopupActionPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = popup_action_set_property;
+ object_class->get_property = popup_action_get_property;
+ object_class->dispose = popup_action_dispose;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE,
+ g_param_spec_object (
+ "source",
+ _("Source Action"),
+ _("The source action to proxy"),
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+popup_action_init (EPopupAction *popup_action)
+{
+ popup_action->priv = E_POPUP_ACTION_GET_PRIVATE (popup_action);
+}
+
+GType
+e_popup_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EPopupActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) popup_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPopupAction),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) popup_action_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_ACTION, "EPopupAction", &type_info, 0);
+ }
+
+ return type;
+}
+
+EPopupAction *
+e_popup_action_new (const gchar *name,
+ const gchar *label,
+ GtkAction *source)
+{
+ EPopupAction *popup_action;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_ACTION (source), NULL);
+
+ popup_action = g_object_new (
+ E_TYPE_POPUP_ACTION, "name", name,
+ "label", label, "source", source, NULL);
+
+ /* XXX This is a hack to work around the fact that GtkAction's
+ * "label" and "tooltip" properties are not constructor
+ * properties, even though they're supplied upfront.
+ *
+ * See: http://bugzilla.gnome.org/show_bug.cgi?id=568334 */
+ popup_action_constructed (G_OBJECT (popup_action));
+
+ return popup_action;
+}
+
+GtkAction *
+e_popup_action_get_source (EPopupAction *popup_action)
+{
+ g_return_val_if_fail (E_IS_POPUP_ACTION (popup_action), NULL);
+
+ return popup_action->priv->source;
+}
+
+void
+e_action_group_add_popup_actions (GtkActionGroup *action_group,
+ const EPopupActionEntry *entries,
+ guint n_entries)
+{
+ guint ii;
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ for (ii = 0; ii < n_entries; ii++) {
+ EPopupAction *popup_action;
+ GtkAction *source;
+ const gchar *label;
+
+ label = gtk_action_group_translate_string (
+ action_group, entries[ii].label);
+
+ source = gtk_action_group_get_action (
+ action_group, entries[ii].source);
+
+ if (source == NULL) {
+ g_warning (
+ "Source action '%s' not found in "
+ "action group '%s'", entries[ii].source,
+ gtk_action_group_get_name (action_group));
+ continue;
+ }
+
+ popup_action = e_popup_action_new (
+ entries[ii].name, label, source);
+
+ g_signal_connect_swapped (
+ popup_action, "activate",
+ G_CALLBACK (gtk_action_activate),
+ popup_action->priv->source);
+
+ gtk_action_group_add_action (
+ action_group, GTK_ACTION (popup_action));
+
+ g_object_unref (popup_action);
+ }
+}
diff --git a/widgets/misc/e-popup-action.h b/widgets/misc/e-popup-action.h
new file mode 100644
index 0000000000..6000b5a6ec
--- /dev/null
+++ b/widgets/misc/e-popup-action.h
@@ -0,0 +1,95 @@
+/*
+ * e-popup-action.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* A popup action is an action that lives in a popup menu. It proxies an
+ * equivalent action in the main menu, with two differences:
+ *
+ * 1) If the main menu action is insensitive, the popup action is invisible.
+ * 2) The popup action may have a different label than the main menu action.
+ *
+ * To use:
+ *
+ * Create an array of EPopupActionEntry structs. Add the main menu actions
+ * that serve as "sources" for the popup actions to an action group first.
+ * Then pass the same action group and the EPopupActionEntry array to
+ * e_action_group_add_popup_actions() to add popup actions.
+ */
+
+#ifndef E_POPUP_ACTION_H
+#define E_POPUP_ACTION_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_POPUP_ACTION \
+ (e_popup_action_get_type ())
+#define E_POPUP_ACTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_POPUP_ACTION, EPopupAction))
+#define E_POPUP_ACTION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_POPUP_ACTION, EPopupActionClass))
+#define E_IS_POPUP_ACTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_POPUP_ACTION))
+#define E_IS_POPUP_ACTION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_POPUP_ACTION))
+#define E_POPUP_ACTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_POPUP_ACTION, EPopupActionClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPopupAction EPopupAction;
+typedef struct _EPopupActionClass EPopupActionClass;
+typedef struct _EPopupActionPrivate EPopupActionPrivate;
+typedef struct _EPopupActionEntry EPopupActionEntry;
+
+struct _EPopupAction {
+ GtkAction parent;
+ EPopupActionPrivate *priv;
+};
+
+struct _EPopupActionClass {
+ GtkActionClass parent_class;
+};
+
+struct _EPopupActionEntry {
+ const gchar *name;
+ const gchar *label; /* optional: overrides the source action */
+ const gchar *source; /* name of the source action */
+};
+
+GType e_popup_action_get_type (void);
+EPopupAction * e_popup_action_new (const gchar *name,
+ const gchar *label,
+ GtkAction *source);
+GtkAction * e_popup_action_get_source (EPopupAction *popup_action);
+
+void e_action_group_add_popup_actions
+ (GtkActionGroup *action_group,
+ const EPopupActionEntry *entries,
+ guint n_entries);
+
+G_END_DECLS
+
+#endif /* E_POPUP_ACTION_H */