[gtk+/composite-templates] gtkmodelmenu: move to new action regime
- From: Juan Pablo Ugarte <jpu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/composite-templates] gtkmodelmenu: move to new action regime
- Date: Fri, 14 Sep 2012 21:14:23 +0000 (UTC)
commit 4a613801a511f63f40ae2a16fe7e146aecec5f73
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Aug 17 23:13:42 2012 -0400
gtkmodelmenu: move to new action regime
Drop the explicit passing of GActionGroup into the GtkMenu(Bar)
constructors and operate from the action context instead.
With GtkMenuItem implementing GtkActionable, this turns out to be pretty
easy (and most of the code can be removed from GtkModelMenuItem,
including the GActionObserver implementation).
gtk/gtkapplicationwindow.c | 2 +-
gtk/gtkmodelmenu.c | 117 +++-------------------
gtk/gtkmodelmenu.h | 3 -
gtk/gtkmodelmenuitem.c | 235 +++++++++++---------------------------------
gtk/gtkmodelmenuitem.h | 2 -
5 files changed, 75 insertions(+), 284 deletions(-)
---
diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c
index 7061309..b869208 100644
--- a/gtk/gtkapplicationwindow.c
+++ b/gtk/gtkapplicationwindow.c
@@ -258,7 +258,7 @@ gtk_application_window_update_menubar (GtkApplicationWindow *window)
g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section));
g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section));
- window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), window->priv->muxer, window->priv->accels);
+ window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), window->priv->accels);
gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window));
gtk_widget_show_all (window->priv->menubar);
g_object_unref (combined);
diff --git a/gtk/gtkmodelmenu.c b/gtk/gtkmodelmenu.c
index 9dd9aa5..390923f 100644
--- a/gtk/gtkmodelmenu.c
+++ b/gtk/gtkmodelmenu.c
@@ -32,7 +32,6 @@
#define MODEL_MENU_WIDGET_DATA "gtk-model-menu-widget-data"
typedef struct {
- GActionObservable *actions;
GMenuModel *model;
GtkAccelGroup *accels;
GtkMenuShell *shell;
@@ -66,8 +65,6 @@ gtk_model_menu_binding_free (gpointer data)
binding->connected = g_slist_delete_link (binding->connected, binding->connected);
}
- if (binding->actions)
- g_object_unref (binding->actions);
g_object_unref (binding->model);
g_slice_free (GtkModelMenuBinding, binding);
@@ -85,12 +82,13 @@ gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding,
{
g_menu_model_get_item_attribute (model, item_index, "label", "s", heading);
gtk_model_menu_binding_append_model (binding, section, FALSE);
+ g_object_unref (section);
}
else
{
GtkMenuItem *item;
- item = gtk_model_menu_item_new (model, item_index, binding->actions, binding->accels);
+ item = gtk_model_menu_item_new (model, item_index, binding->accels);
gtk_menu_shell_append (binding->shell, GTK_WIDGET (item));
gtk_widget_show (GTK_WIDGET (item));
binding->n_items++;
@@ -227,15 +225,14 @@ gtk_model_menu_binding_items_changed (GMenuModel *model,
}
static void
-gtk_model_menu_bind (GtkMenuShell *shell,
- GMenuModel *model,
- gboolean with_separators)
+gtk_model_menu_bind (GtkMenuShell *shell,
+ GMenuModel *model,
+ gboolean with_separators)
{
GtkModelMenuBinding *binding;
binding = g_slice_new (GtkModelMenuBinding);
binding->model = g_object_ref (model);
- binding->actions = NULL;
binding->accels = NULL;
binding->shell = shell;
binding->update_idle = 0;
@@ -247,24 +244,21 @@ gtk_model_menu_bind (GtkMenuShell *shell,
static void
-gtk_model_menu_populate (GtkMenuShell *shell,
- GActionObservable *actions,
- GtkAccelGroup *accels)
+gtk_model_menu_populate (GtkMenuShell *shell,
+ GtkAccelGroup *accels)
{
GtkModelMenuBinding *binding;
binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding");
- binding->actions = g_object_ref (actions);
binding->accels = accels;
gtk_model_menu_binding_populate (binding);
}
GtkWidget *
-gtk_model_menu_create_menu (GMenuModel *model,
- GActionObservable *actions,
- GtkAccelGroup *accels)
+gtk_model_menu_create_menu (GMenuModel *model,
+ GtkAccelGroup *accels)
{
GtkWidget *menu;
@@ -272,69 +266,11 @@ gtk_model_menu_create_menu (GMenuModel *model,
gtk_menu_set_accel_group (GTK_MENU (menu), accels);
gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, TRUE);
- gtk_model_menu_populate (GTK_MENU_SHELL (menu), actions, accels);
+ gtk_model_menu_populate (GTK_MENU_SHELL (menu), accels);
return menu;
}
-static void
-gtk_model_menu_connect_app_window (GtkMenu *menu,
- GtkApplicationWindow *window)
-{
- GActionObservable *actions;
- GtkAccelGroup *accels;
-
- actions = gtk_application_window_get_observable (window);
- accels = gtk_application_window_get_accel_group (window);
-
- gtk_menu_set_accel_group (menu, accels);
- gtk_model_menu_populate (GTK_MENU_SHELL (menu), actions, accels);
-}
-
-static void
-attach_widget_hierarchy_changed (GtkWidget *attach_widget,
- GtkWidget *previous_toplevel,
- gpointer user_data)
-{
- GtkWidget *toplevel;
- GtkMenu *menu = user_data;
-
- toplevel = gtk_widget_get_toplevel (attach_widget);
- if (GTK_IS_APPLICATION_WINDOW (toplevel))
- gtk_model_menu_connect_app_window (menu, GTK_APPLICATION_WINDOW (toplevel));
-}
-
-static void
-notify_attach (GtkMenu *menu,
- GParamSpec *pspec,
- gpointer data)
-{
- GtkWidget *attach_widget, *toplevel;
-
- attach_widget = g_object_get_data (G_OBJECT (menu), MODEL_MENU_WIDGET_DATA);
- if (attach_widget != NULL)
- {
- g_signal_handlers_disconnect_by_func (attach_widget, attach_widget_hierarchy_changed, menu);
- g_object_set_data (G_OBJECT (menu), MODEL_MENU_WIDGET_DATA, NULL);
- }
-
- attach_widget = gtk_menu_get_attach_widget (menu);
- if (!attach_widget)
- return;
-
- toplevel = gtk_widget_get_toplevel (attach_widget);
- if (GTK_IS_APPLICATION_WINDOW (toplevel))
- {
- gtk_model_menu_connect_app_window (menu, GTK_APPLICATION_WINDOW (toplevel));
- }
- else
- {
- g_object_set_data (G_OBJECT (menu), MODEL_MENU_WIDGET_DATA, attach_widget);
- g_signal_connect_object (attach_widget, "hierarchy-changed",
- G_CALLBACK (attach_widget_hierarchy_changed), menu, 0);
- }
-}
-
/**
* gtk_menu_new_from_model:
* @model: a #GMenuModel
@@ -358,46 +294,25 @@ gtk_menu_new_from_model (GMenuModel *model)
menu = gtk_menu_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, TRUE);
- g_signal_connect (menu, "notify::attach-widget",
- G_CALLBACK (notify_attach), NULL);
+ gtk_model_menu_populate (GTK_MENU_SHELL (menu), NULL);
return menu;
}
GtkWidget *
-gtk_model_menu_create_menu_bar (GMenuModel *model,
- GActionObservable *actions,
- GtkAccelGroup *accels)
+gtk_model_menu_create_menu_bar (GMenuModel *model,
+ GtkAccelGroup *accels)
{
GtkWidget *menubar;
menubar = gtk_menu_bar_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, FALSE);
- gtk_model_menu_populate (GTK_MENU_SHELL (menubar), actions, accels);
+ gtk_model_menu_populate (GTK_MENU_SHELL (menubar), accels);
return menubar;
}
-static void
-hierarchy_changed (GtkMenuShell *shell,
- GObject *previous_toplevel,
- gpointer data)
-{
- GtkWidget *toplevel;
- GActionObservable *actions;
- GtkAccelGroup *accels;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
- if (GTK_IS_APPLICATION_WINDOW (toplevel))
- {
- actions = gtk_application_window_get_observable (GTK_APPLICATION_WINDOW (toplevel));
- accels = gtk_application_window_get_accel_group (GTK_APPLICATION_WINDOW (toplevel));
-
- gtk_model_menu_populate (shell, actions, accels);
- }
-}
-
/**
* gtk_menu_bar_new_from_model:
* @model: a #GMenuModel
@@ -422,9 +337,7 @@ gtk_menu_bar_new_from_model (GMenuModel *model)
menubar = gtk_menu_bar_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, FALSE);
-
- g_signal_connect (menubar, "hierarchy-changed",
- G_CALLBACK (hierarchy_changed), NULL);
+ gtk_model_menu_populate (GTK_MENU_SHELL (menubar), NULL);
return menubar;
}
diff --git a/gtk/gtkmodelmenu.h b/gtk/gtkmodelmenu.h
index d2df78f..05654c9 100644
--- a/gtk/gtkmodelmenu.h
+++ b/gtk/gtkmodelmenu.h
@@ -20,19 +20,16 @@
#ifndef __GTK_MODEL_MENU_H__
#define __GTK_MODEL_MENU_H__
-#include <gtk/gactionobservable.h>
#include <gtk/gtkmenushell.h>
#include <gtk/gtkaccelgroup.h>
#include <gio/gio.h>
G_GNUC_INTERNAL
GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel *model,
- GActionObservable *actions,
GtkAccelGroup *accels);
G_GNUC_INTERNAL
GtkWidget * gtk_model_menu_create_menu (GMenuModel *model,
- GActionObservable *actions,
GtkAccelGroup *accels);
#endif /* __GTK_MODEL_MENU_H__ */
diff --git a/gtk/gtkmodelmenuitem.c b/gtk/gtkmodelmenuitem.c
index d07f4d2..07cad70 100644
--- a/gtk/gtkmodelmenuitem.c
+++ b/gtk/gtkmodelmenuitem.c
@@ -22,33 +22,21 @@
#include "gtkmodelmenuitem.h"
#include "gtkaccelmapprivate.h"
+#include "gtkactionhelper.h"
#include "gtkmodelmenu.h"
struct _GtkModelMenuItem
{
GtkCheckMenuItem parent_instance;
-
- GActionGroup *actions;
- const gchar *action_name;
+ GtkActionHelperRole role;
gboolean has_indicator;
- gboolean can_activate;
- GVariant *target;
};
typedef GtkCheckMenuItemClass GtkModelMenuItemClass;
-static void gtk_model_menu_item_observer_iface_init (GActionObserverInterface *iface);
-G_DEFINE_TYPE_WITH_CODE (GtkModelMenuItem, gtk_model_menu_item, GTK_TYPE_CHECK_MENU_ITEM,
- G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_OBSERVER, gtk_model_menu_item_observer_iface_init))
+G_DEFINE_TYPE (GtkModelMenuItem, gtk_model_menu_item, GTK_TYPE_CHECK_MENU_ITEM)
-static void
-gtk_model_menu_item_activate (GtkMenuItem *menu_item)
-{
- GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (menu_item);
-
- if (item->can_activate)
- g_action_group_activate_action (item->actions, item->action_name, item->target);
-}
+#define PROP_ACTION_ROLE 1
static void
gtk_model_menu_item_toggle_size_request (GtkMenuItem *menu_item,
@@ -76,122 +64,9 @@ gtk_model_menu_item_draw_indicator (GtkCheckMenuItem *check_item,
}
static void
-gtk_model_menu_item_set_active (GtkModelMenuItem *item,
- gboolean active)
-{
- GtkCheckMenuItem *checkitem = GTK_CHECK_MENU_ITEM (item);
-
- if (gtk_check_menu_item_get_active (checkitem) != active)
- {
- _gtk_check_menu_item_set_active (checkitem, active);
- g_object_notify (G_OBJECT (checkitem), "active");
- gtk_check_menu_item_toggled (checkitem);
- gtk_widget_queue_draw (GTK_WIDGET (item));
- }
-}
-
-static void
-gtk_model_menu_item_action_added (GActionObserver *observer,
- GActionObservable *observable,
- const gchar *action_name,
- const GVariantType *parameter_type,
- gboolean enabled,
- GVariant *state)
-{
- GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (observer);
-
- /* we can only activate the item if we have the correct type of parameter */
- item->can_activate = (item->target == NULL && parameter_type == NULL) ||
- (item->target != NULL && parameter_type != NULL &&
- g_variant_is_of_type (item->target, parameter_type));
-
- if (item->can_activate)
- {
- if (item->target != NULL && state != NULL)
- {
- /* actions with states and targets are radios */
- gboolean selected;
-
- selected = g_variant_equal (state, item->target);
- gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), TRUE);
- gtk_model_menu_item_set_active (item, selected);
- item->has_indicator = TRUE;
- }
-
- else if (state != NULL && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
- {
- /* boolean state actions without target are checks */
- gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), FALSE);
- gtk_model_menu_item_set_active (item, g_variant_get_boolean (state));
- item->has_indicator = TRUE;
- }
-
- else
- {
- /* stateless items are just plain actions */
- gtk_model_menu_item_set_active (item, FALSE);
- item->has_indicator = FALSE;
- }
-
- gtk_widget_set_sensitive (GTK_WIDGET (item), enabled);
- gtk_widget_queue_resize (GTK_WIDGET (item));
- }
-}
-
-static void
-gtk_model_menu_item_action_enabled_changed (GActionObserver *observer,
- GActionObservable *observable,
- const gchar *action_name,
- gboolean enabled)
-{
- GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (observer);
-
- if (!item->can_activate)
- return;
-
- gtk_widget_set_sensitive (GTK_WIDGET (item), item->can_activate && enabled);
-}
-
-static void
-gtk_model_menu_item_action_state_changed (GActionObserver *observer,
- GActionObservable *observable,
- const gchar *action_name,
- GVariant *state)
-{
- GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (observer);
-
- if (!item->can_activate)
- return;
-
- if (item->target)
- gtk_model_menu_item_set_active (item, g_variant_equal (state, item->target));
-
- else if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
- gtk_model_menu_item_set_active (item, g_variant_get_boolean (state));
-}
-
-static void
-gtk_model_menu_item_action_removed (GActionObserver *observer,
- GActionObservable *observable,
- const gchar *action_name)
-{
- GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (observer);
-
- if (!item->can_activate)
- return;
-
- gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
- gtk_model_menu_item_set_active (item, FALSE);
- item->has_indicator = FALSE;
-
- gtk_widget_queue_resize (GTK_WIDGET (item));
-}
-
-static void
gtk_model_menu_item_setup (GtkModelMenuItem *item,
GMenuModel *model,
gint item_index,
- GActionObservable *actions,
GtkAccelGroup *accels)
{
GMenuAttributeIter *iter;
@@ -201,7 +76,7 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item,
if ((submenu = g_menu_model_get_item_link (model, item_index, "submenu")))
{
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), gtk_model_menu_create_menu (submenu, actions, accels));
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), gtk_model_menu_create_menu (submenu, accels));
g_object_unref (submenu);
}
@@ -212,68 +87,74 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item,
gtk_menu_item_set_label (GTK_MENU_ITEM (item), g_variant_get_string (value, NULL));
else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
- item->action_name = g_variant_get_string (value, NULL);
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (item), g_variant_get_string (value, NULL));
else if (g_str_equal (key, "target"))
- item->target = g_variant_ref (value);
+ gtk_actionable_set_action_target_value (GTK_ACTIONABLE (item), value);
g_variant_unref (value);
}
g_object_unref (iter);
gtk_menu_item_set_use_underline (GTK_MENU_ITEM (item), TRUE);
-
- if (item->action_name)
- {
- const GVariantType *type;
- gboolean enabled;
- GVariant *state;
- gchar *path;
-
- /* observer already causes us to hold a hard ref on the group */
- item->actions = G_ACTION_GROUP (actions);
-
- if (actions)
- {
- g_action_observable_register_observer (actions, item->action_name, G_ACTION_OBSERVER (item));
-
- if (g_action_group_query_action (G_ACTION_GROUP (actions), item->action_name, &enabled, &type, NULL, NULL, &state))
- {
- gtk_model_menu_item_action_added (G_ACTION_OBSERVER (item), actions, item->action_name, type, enabled, state);
- if (state != NULL)
- g_variant_unref (state);
- }
- else
- gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
- }
- else
- gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
-
- path = _gtk_accel_path_for_action (item->action_name, item->target);
- gtk_menu_item_set_accel_path (GTK_MENU_ITEM (item), path);
- g_free (path);
- }
}
static void
-gtk_model_menu_item_finalize (GObject *object)
+gtk_model_menu_item_set_has_indicator (GtkModelMenuItem *item,
+ gboolean has_indicator)
{
- G_OBJECT_CLASS (gtk_model_menu_item_parent_class)
- ->finalize (object);
+ if (has_indicator == item->has_indicator)
+ return;
+
+ item->has_indicator = has_indicator;
+
+ gtk_widget_queue_resize (GTK_WIDGET (item));
}
static void
-gtk_model_menu_item_init (GtkModelMenuItem *item)
+gtk_model_menu_item_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
{
+ GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (object);
+ GtkActionHelperRole role;
+ AtkObject *accessible;
+ AtkRole a11y_role;
+
+ g_assert (prop_id == PROP_ACTION_ROLE);
+
+ role = g_value_get_uint (value);
+
+ if (role == item->role)
+ return;
+
+ gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), role == GTK_ACTION_HELPER_ROLE_RADIO);
+ gtk_model_menu_item_set_has_indicator (item, role != GTK_ACTION_HELPER_ROLE_NORMAL);
+
+ accessible = gtk_widget_get_accessible (GTK_WIDGET (item));
+ switch (role)
+ {
+ case GTK_ACTION_HELPER_ROLE_NORMAL:
+ a11y_role = ATK_ROLE_MENU_ITEM;
+ break;
+
+ case GTK_ACTION_HELPER_ROLE_TOGGLE:
+ a11y_role = ATK_ROLE_CHECK_MENU_ITEM;
+ break;
+
+ case GTK_ACTION_HELPER_ROLE_RADIO:
+ a11y_role = ATK_ROLE_RADIO_MENU_ITEM;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ atk_object_set_role (accessible, a11y_role);
}
static void
-gtk_model_menu_item_observer_iface_init (GActionObserverInterface *iface)
+gtk_model_menu_item_init (GtkModelMenuItem *item)
{
- iface->action_added = gtk_model_menu_item_action_added;
- iface->action_enabled_changed = gtk_model_menu_item_action_enabled_changed;
- iface->action_state_changed = gtk_model_menu_item_action_state_changed;
- iface->action_removed = gtk_model_menu_item_action_removed;
}
static void
@@ -285,23 +166,25 @@ gtk_model_menu_item_class_init (GtkModelMenuItemClass *class)
check_class->draw_indicator = gtk_model_menu_item_draw_indicator;
- item_class->activate = gtk_model_menu_item_activate;
item_class->toggle_size_request = gtk_model_menu_item_toggle_size_request;
- object_class->finalize = gtk_model_menu_item_finalize;
+ object_class->set_property = gtk_model_menu_item_set_property;
+
+ g_object_class_install_property (object_class, PROP_ACTION_ROLE,
+ g_param_spec_uint ("action-role", "action role", "action role",
+ 0, 2, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
}
GtkMenuItem *
gtk_model_menu_item_new (GMenuModel *model,
gint item_index,
- GActionObservable *actions,
GtkAccelGroup *accels)
{
GtkModelMenuItem *item;
item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL);
- gtk_model_menu_item_setup (item, model, item_index, actions, accels);
+ gtk_model_menu_item_setup (item, model, item_index, accels);
return GTK_MENU_ITEM (item);
}
diff --git a/gtk/gtkmodelmenuitem.h b/gtk/gtkmodelmenuitem.h
index c129900..8017e3b 100644
--- a/gtk/gtkmodelmenuitem.h
+++ b/gtk/gtkmodelmenuitem.h
@@ -20,7 +20,6 @@
#ifndef __GTK_MODEL_MENU_ITEM_H__
#define __GTK_MODEL_MENU_ITEM_H__
-#include <gtk/gactionobservable.h>
#include <gtk/gtkcheckmenuitem.h>
#define GTK_TYPE_MODEL_MENU_ITEM (gtk_model_menu_item_get_type ())
@@ -37,7 +36,6 @@ GType gtk_model_menu_item_get_type (void) G
G_GNUC_INTERNAL
GtkMenuItem * gtk_model_menu_item_new (GMenuModel *model,
gint item_index,
- GActionObservable *actions,
GtkAccelGroup *accels);
#endif /* __GTK_MODEL_MENU_ITEM_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]