GtkMenuTracker: add new_from_item_submenu()

Creates a menu tracker for the submenu of an existing item, filling in
about half of the parameters for the new tracker from the correct values
in the menuitem.

Add also a "has-submenu" boolean property so implementations can just
use this to check if they should do the submenu, without having to
handle a GMenuModel at all.
This commit is contained in:
Ryan Lortie
2013-05-10 14:45:27 -04:00
parent c2b9d3f5db
commit 26e5e44dc6
5 changed files with 52 additions and 17 deletions

View File

@@ -2088,7 +2088,6 @@ gtk_menu_shell_tracker_insert_func (GtkMenuTrackerItem *item,
{
GtkMenuShell *menu_shell = user_data;
GtkWidget *widget;
GMenuModel *submenu;
if (gtk_menu_tracker_item_get_is_separator (item))
{
@@ -2099,30 +2098,24 @@ gtk_menu_shell_tracker_insert_func (GtkMenuTrackerItem *item,
*/
g_object_bind_property (item, "label", widget, "label", G_BINDING_SYNC_CREATE);
}
else if ((submenu = gtk_menu_tracker_item_get_submenu (item)))
else if (gtk_menu_tracker_item_get_has_submenu (item))
{
GtkActionObservable *observable;
GtkWidget *subwidget;
GtkMenuShell *subshell;
GtkMenuShell *submenu;
widget = gtk_model_menu_item_new ();
g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
/* reuse the observer to reduce the amount of GActionMuxer traffic */
observable = gtk_menu_tracker_item_get_observable (item);
subwidget = gtk_menu_new ();
subshell = GTK_MENU_SHELL (subwidget);
submenu = GTK_MENU_SHELL (gtk_menu_new ());
/* We recurse directly here: we could use an idle instead to
* prevent arbitrary recursion depth. We could also do it
* lazy...
*/
subshell->priv->tracker = gtk_menu_tracker_new (observable, submenu, TRUE,
gtk_menu_tracker_item_get_submenu_namespace (item),
gtk_menu_shell_tracker_insert_func,
gtk_menu_shell_tracker_remove_func,
subwidget);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), subwidget);
submenu->priv->tracker = gtk_menu_tracker_new_for_item_submenu (item,
gtk_menu_shell_tracker_insert_func,
gtk_menu_shell_tracker_remove_func,
submenu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), GTK_WIDGET (submenu));
if (gtk_menu_tracker_item_get_should_request_show (item))
{
@@ -2136,8 +2129,8 @@ gtk_menu_shell_tracker_insert_func (GtkMenuTrackerItem *item,
*
* Note: 'item' is already kept alive from above.
*/
g_signal_connect (subwidget, "show", G_CALLBACK (gtk_menu_shell_submenu_shown), item);
g_signal_connect (subwidget, "hide", G_CALLBACK (gtk_menu_shell_submenu_hidden), item);
g_signal_connect (submenu, "show", G_CALLBACK (gtk_menu_shell_submenu_shown), item);
g_signal_connect (submenu, "hide", G_CALLBACK (gtk_menu_shell_submenu_hidden), item);
}
}
else

View File

@@ -433,6 +433,19 @@ gtk_menu_tracker_new (GtkActionObservable *observable,
return tracker;
}
GtkMenuTracker *
gtk_menu_tracker_new_for_item_submenu (GtkMenuTrackerItem *item,
GtkMenuTrackerInsertFunc insert_func,
GtkMenuTrackerRemoveFunc remove_func,
gpointer user_data)
{
return gtk_menu_tracker_new (gtk_menu_tracker_item_get_observable (item),
gtk_menu_tracker_item_get_submenu (item),
TRUE,
gtk_menu_tracker_item_get_submenu_namespace (item),
insert_func, remove_func, user_data);
}
/*< private >
* gtk_menu_tracker_free:
* @tracker: a #GtkMenuTracker

View File

@@ -42,6 +42,11 @@ GtkMenuTracker * gtk_menu_tracker_new (GtkActi
GtkMenuTrackerRemoveFunc remove_func,
gpointer user_data);
GtkMenuTracker * gtk_menu_tracker_new_for_item_submenu (GtkMenuTrackerItem *item,
GtkMenuTrackerInsertFunc insert_func,
GtkMenuTrackerRemoveFunc remove_func,
gpointer user_data);
void gtk_menu_tracker_free (GtkMenuTracker *tracker);
#endif /* __GTK_MENU_TRACKER_H__ */

View File

@@ -19,6 +19,7 @@ struct _GtkMenuTrackerItem
enum {
PROP_0,
PROP_IS_SEPARATOR,
PROP_HAS_SUBMENU,
PROP_LABEL,
PROP_ICON,
PROP_SENSITIVE,
@@ -73,6 +74,9 @@ gtk_menu_tracker_item_get_property (GObject *object,
case PROP_IS_SEPARATOR:
g_value_set_boolean (value, gtk_menu_tracker_item_get_is_separator (self));
break;
case PROP_HAS_SUBMENU:
g_value_set_boolean (value, gtk_menu_tracker_item_get_has_submenu (self));
break;
case PROP_LABEL:
g_value_set_string (value, gtk_menu_tracker_item_get_label (self));
break;
@@ -134,6 +138,8 @@ gtk_menu_tracker_item_class_init (GtkMenuTrackerItemClass *class)
gtk_menu_tracker_item_pspecs[PROP_IS_SEPARATOR] =
g_param_spec_boolean ("is-separator", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
gtk_menu_tracker_item_pspecs[PROP_HAS_SUBMENU] =
g_param_spec_boolean ("has-submenu", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
gtk_menu_tracker_item_pspecs[PROP_LABEL] =
g_param_spec_string ("label", "", "", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
gtk_menu_tracker_item_pspecs[PROP_ICON] =
@@ -382,6 +388,22 @@ gtk_menu_tracker_item_get_is_separator (GtkMenuTrackerItem *self)
return self->is_separator;
}
gboolean
gtk_menu_tracker_item_get_has_submenu (GtkMenuTrackerItem *self)
{
GMenuModel *link;
link = g_menu_item_get_link (self->item, G_MENU_LINK_SUBMENU);
if (link)
{
g_object_unref (link);
return TRUE;
}
else
return FALSE;
}
const gchar *
gtk_menu_tracker_item_get_label (GtkMenuTrackerItem *self)
{

View File

@@ -52,6 +52,8 @@ GtkActionObservable * gtk_menu_tracker_item_get_observable (GtkMenu
gboolean gtk_menu_tracker_item_get_is_separator (GtkMenuTrackerItem *self);
gboolean gtk_menu_tracker_item_get_has_submenu (GtkMenuTrackerItem *self);
const gchar * gtk_menu_tracker_item_get_label (GtkMenuTrackerItem *self);
GIcon * gtk_menu_tracker_item_get_icon (GtkMenuTrackerItem *self);