diff options
author | Ryan Lortie <desrt@desrt.ca> | 2014-01-04 02:25:43 -0500 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2014-01-08 14:21:18 -0500 |
commit | 2b1aa12f01f382652a3b6b9c7e51959dde194143 (patch) | |
tree | e876e84ade9f3c592c2d238e832b836b7c116a0d /gtk/gtkmenutrackeritem.c | |
parent | 8efb1404cbdeedfaf894c219fcae9dbdd1986fa2 (diff) | |
download | gtk+-2b1aa12f01f382652a3b6b9c7e51959dde194143.tar.gz |
GtkMenuTrackerItem: add an internal 'visible' flag
Add an internal API for checking if a GtkMenuTrackerItem is visible,
along with a signal for reporting changes in that flag. The item will
become invisible in situations according to the new hidden-when=''
attribute, which can be set to 'action-disabled' or 'action-missing'.
This new flag doesn't actually do anything yet, and none of the
consumers of GtkMenuTracker do anything with it (nor should they). A
followup patch will address the issue.
https://bugzilla.gnome.org/show_bug.cgi?id=688421
Diffstat (limited to 'gtk/gtkmenutrackeritem.c')
-rw-r--r-- | gtk/gtkmenutrackeritem.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/gtk/gtkmenutrackeritem.c b/gtk/gtkmenutrackeritem.c index d81c9de8e5..fdda28f9fb 100644 --- a/gtk/gtkmenutrackeritem.c +++ b/gtk/gtkmenutrackeritem.c @@ -97,8 +97,14 @@ struct _GtkMenuTrackerItem guint toggled : 1; guint submenu_shown : 1; guint submenu_requested : 1; + guint hidden_when : 2; + guint is_visible : 1; }; +#define HIDDEN_NEVER 0 +#define HIDDEN_WHEN_MISSING 1 +#define HIDDEN_WHEN_DISABLED 2 + enum { PROP_0, PROP_IS_SEPARATOR, @@ -115,6 +121,7 @@ enum { }; static GParamSpec *gtk_menu_tracker_item_pspecs[N_PROPS]; +static guint gtk_menu_tracker_visibility_changed_signal; static void gtk_menu_tracker_item_init_observer_iface (GtkActionObserverInterface *iface); G_DEFINE_TYPE_WITH_CODE (GtkMenuTrackerItem, gtk_menu_tracker_item, G_TYPE_OBJECT, @@ -239,6 +246,46 @@ gtk_menu_tracker_item_class_init (GtkMenuTrackerItemClass *class) g_param_spec_boolean ("submenu-shown", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); g_object_class_install_properties (class, N_PROPS, gtk_menu_tracker_item_pspecs); + + gtk_menu_tracker_visibility_changed_signal = g_signal_new ("visibility-changed", GTK_TYPE_MENU_TRACKER_ITEM, + G_SIGNAL_RUN_FIRST, 0, NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, + 1, G_TYPE_BOOLEAN); +} + +/* This syncs up the visibility for the hidden-when='' case. We call it + * from the action observer functions on changes to the action group and + * on initialisation (via the action observer functions that are invoked + * at that time). + */ +static void +gtk_menu_tracker_item_update_visibility (GtkMenuTrackerItem *self) +{ + gboolean visible; + + switch (self->hidden_when) + { + case HIDDEN_NEVER: + visible = TRUE; + break; + + case HIDDEN_WHEN_MISSING: + visible = self->can_activate; + break; + + case HIDDEN_WHEN_DISABLED: + visible = self->sensitive; + break; + + default: + g_assert_not_reached (); + } + + if (visible != self->is_visible) + { + self->is_visible = visible; + g_signal_emit (self, gtk_menu_tracker_visibility_changed_signal, 0, visible); + } } static void @@ -294,6 +341,12 @@ gtk_menu_tracker_item_action_added (GtkActionObserver *observer, if (action_target) g_variant_unref (action_target); + + /* In case of hidden-when='', we want to Wait until after refreshing + * all of the properties to emit the signal that will cause the + * tracker to expose us (to prevent too much thrashing). + */ + gtk_menu_tracker_item_update_visibility (self); } static void @@ -313,6 +366,8 @@ gtk_menu_tracker_item_action_enabled_changed (GtkActionObserver *observer, self->sensitive = enabled; g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SENSITIVE]); + + gtk_menu_tracker_item_update_visibility (self); } static void @@ -368,6 +423,11 @@ gtk_menu_tracker_item_action_removed (GtkActionObserver *observer, self->toggled = FALSE; self->role = GTK_MENU_TRACKER_ITEM_ROLE_NORMAL; + /* Backwards from adding: we want to remove ourselves from the menu + * -before- thrashing the properties. + */ + gtk_menu_tracker_item_update_visibility (self); + g_object_freeze_notify (G_OBJECT (self)); if (was_sensitive) @@ -413,6 +473,7 @@ _gtk_menu_tracker_item_new (GtkActionObservable *observable, { GtkMenuTrackerItem *self; const gchar *action_name; + const gchar *hidden_when; g_return_val_if_fail (GTK_IS_ACTION_OBSERVABLE (observable), NULL); g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL); @@ -423,6 +484,23 @@ _gtk_menu_tracker_item_new (GtkActionObservable *observable, self->observable = g_object_ref (observable); self->is_separator = is_separator; + if (!is_separator && g_menu_item_get_attribute (self->item, "hidden-when", "&s", &hidden_when)) + { + if (g_str_equal (hidden_when, "action-disabled")) + self->hidden_when = HIDDEN_WHEN_DISABLED; + else if (g_str_equal (hidden_when, "action-missing")) + self->hidden_when = HIDDEN_WHEN_MISSING; + + /* Ignore other values -- this code may be running in context of a + * desktop shell or the like and should not spew criticals due to + * application bugs... + * + * Note: if we just set a hidden-when state, but don't get the + * action_name below then our visibility will be FALSE forever. + * That's to be expected since the action is missing... + */ + } + if (!is_separator && g_menu_item_get_attribute (self->item, "action", "&s", &action_name)) { GActionGroup *group = G_ACTION_GROUP (observable); @@ -803,3 +881,15 @@ gtk_menu_tracker_item_request_submenu_shown (GtkMenuTrackerItem *self, else gtk_menu_tracker_item_set_submenu_shown (self, shown); } + +gboolean +_gtk_menu_tracker_item_is_visible (GtkMenuTrackerItem *self) +{ + return self->is_visible; +} + +gboolean +_gtk_menu_tracker_item_may_disappear (GtkMenuTrackerItem *self) +{ + return self->hidden_when != HIDDEN_NEVER; +} |