From 22d41a51fae2d18315887b05000cf7facc36e887 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 20 Jan 2009 00:05:40 +0000 Subject: 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 --- widgets/misc/e-popup-action.c | 285 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 widgets/misc/e-popup-action.c (limited to 'widgets/misc/e-popup-action.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 + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-popup-action.h" + +#include +#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); + } +} -- cgit v1.2.3