GtkMenuTracker: become a proper GObject
Turn GtkMenuTracker into a GObject with "insert" and "remove" signals for the sake of accessibility from language bindings.
This commit is contained in:
@@ -533,7 +533,7 @@ gtk_menu_shell_dispose (GObject *object)
|
||||
{
|
||||
GtkMenuShell *menu_shell = GTK_MENU_SHELL (object);
|
||||
|
||||
g_clear_pointer (&menu_shell->priv->tracker, gtk_menu_tracker_free);
|
||||
g_clear_object (&menu_shell->priv->tracker);
|
||||
gtk_menu_shell_deactivate (menu_shell);
|
||||
|
||||
G_OBJECT_CLASS (gtk_menu_shell_parent_class)->dispose (object);
|
||||
@@ -2225,7 +2225,7 @@ gtk_menu_shell_bind_model (GtkMenuShell *menu_shell,
|
||||
|
||||
muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (menu_shell));
|
||||
|
||||
g_clear_pointer (&menu_shell->priv->tracker, gtk_menu_tracker_free);
|
||||
g_clear_object (&menu_shell->priv->tracker);
|
||||
|
||||
while (menu_shell->priv->children)
|
||||
gtk_container_remove (GTK_CONTAINER (menu_shell), menu_shell->priv->children->data);
|
||||
|
||||
@@ -27,6 +27,8 @@ typedef struct _GtkMenuTrackerSection GtkMenuTrackerSection;
|
||||
|
||||
struct _GtkMenuTracker
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GActionObservable *observable;
|
||||
GtkMenuTrackerInsertFunc insert_func;
|
||||
GtkMenuTrackerRemoveFunc remove_func;
|
||||
@@ -35,6 +37,8 @@ struct _GtkMenuTracker
|
||||
GtkMenuTrackerSection *toplevel;
|
||||
};
|
||||
|
||||
typedef GObjectClass GtkMenuTrackerClass;
|
||||
|
||||
struct _GtkMenuTrackerSection
|
||||
{
|
||||
GMenuModel *model;
|
||||
@@ -47,6 +51,8 @@ struct _GtkMenuTrackerSection
|
||||
gulong handler;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkMenuTracker, gtk_menu_tracker, G_TYPE_OBJECT)
|
||||
|
||||
static GtkMenuTrackerSection * gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
@@ -54,6 +60,38 @@ static GtkMenuTrackerSection * gtk_menu_tracker_section_new (GtkMenuTracker
|
||||
const gchar *action_namespace);
|
||||
static void gtk_menu_tracker_section_free (GtkMenuTrackerSection *section);
|
||||
|
||||
static guint insert_signal, remove_signal;
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_emit_insert (GtkMenuTracker *tracker,
|
||||
GMenuModel *model,
|
||||
gint model_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator,
|
||||
gint offset)
|
||||
{
|
||||
GtkMenuTrackerItem *item;
|
||||
|
||||
item = gtk_menu_tracker_item_new (tracker->observable, model, model_index, action_namespace, is_separator);
|
||||
|
||||
if (tracker->insert_func)
|
||||
(* tracker->insert_func) (item, offset, tracker->user_data);
|
||||
else
|
||||
g_signal_emit (tracker, insert_signal, 0, item, offset);
|
||||
|
||||
g_object_unref (item);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_emit_remove (GtkMenuTracker *tracker,
|
||||
gint offset)
|
||||
{
|
||||
if (tracker->remove_func)
|
||||
(* tracker->remove_func) (offset, tracker->user_data);
|
||||
else
|
||||
g_signal_emit (tracker, remove_signal, 0, offset);
|
||||
}
|
||||
|
||||
static GtkMenuTrackerSection *
|
||||
gtk_menu_tracker_section_find_model (GtkMenuTrackerSection *section,
|
||||
GMenuModel *model,
|
||||
@@ -159,19 +197,13 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section,
|
||||
|
||||
if (should_have_separator > section->has_separator)
|
||||
{
|
||||
/* Add a separator */
|
||||
GtkMenuTrackerItem *item;
|
||||
|
||||
item = gtk_menu_tracker_item_new (tracker->observable, parent_model, parent_index, NULL, TRUE);
|
||||
(* tracker->insert_func) (item, offset, tracker->user_data);
|
||||
g_object_unref (item);
|
||||
|
||||
gtk_menu_tracker_emit_insert (tracker, parent_model, parent_index, NULL, TRUE, offset);
|
||||
section->has_separator = TRUE;
|
||||
}
|
||||
else if (should_have_separator < section->has_separator)
|
||||
{
|
||||
/* Remove a separator */
|
||||
(* tracker->remove_func) (offset, tracker->user_data);
|
||||
gtk_menu_tracker_emit_remove (tracker, offset);
|
||||
section->has_separator = FALSE;
|
||||
}
|
||||
|
||||
@@ -220,7 +252,7 @@ gtk_menu_tracker_remove_items (GtkMenuTracker *tracker,
|
||||
gtk_menu_tracker_section_free (subsection);
|
||||
|
||||
while (n--)
|
||||
(* tracker->remove_func) (offset, tracker->user_data);
|
||||
gtk_menu_tracker_emit_remove (tracker, offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,13 +296,7 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker,
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkMenuTrackerItem *item;
|
||||
|
||||
item = gtk_menu_tracker_item_new (tracker->observable, model, position + n_items,
|
||||
section->action_namespace, FALSE);
|
||||
(* tracker->insert_func) (item, offset, tracker->user_data);
|
||||
g_object_unref (item);
|
||||
|
||||
gtk_menu_tracker_emit_insert (tracker, model, position + n_items, section->action_namespace, FALSE, offset);
|
||||
*change_point = g_slist_prepend (*change_point, NULL);
|
||||
}
|
||||
}
|
||||
@@ -359,6 +385,33 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
|
||||
return section;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_finalize (GObject *object)
|
||||
{
|
||||
GtkMenuTracker *tracker = GTK_MENU_TRACKER (object);
|
||||
|
||||
gtk_menu_tracker_section_free (tracker->toplevel);
|
||||
g_object_unref (tracker->observable);
|
||||
|
||||
G_OBJECT_CLASS (gtk_menu_tracker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_init (GtkMenuTracker *tracker)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_class_init (GtkMenuTrackerClass *class)
|
||||
{
|
||||
class->finalize = gtk_menu_tracker_finalize;
|
||||
|
||||
insert_signal = g_signal_new ("insert", GTK_TYPE_MENU_TRACKER, G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 2, GTK_TYPE_MENU_TRACKER_ITEM, G_TYPE_INT);
|
||||
remove_signal = g_signal_new ("remove", GTK_TYPE_MENU_TRACKER, G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_menu_tracker_new:
|
||||
* @model: the model to flatten
|
||||
@@ -409,6 +462,10 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
|
||||
* When using #GtkMenuTracker there is no need to hold onto @model or
|
||||
* monitor it for changes. The model will be unreffed when
|
||||
* gtk_menu_tracker_free() is called.
|
||||
*
|
||||
* As a bindings-friendly alternative to using this function, you can
|
||||
* create the tracker with g_object_new(), connect to the "insert" and
|
||||
* "remove" signals and then call gtk_menu_tracker_setup().
|
||||
*/
|
||||
GtkMenuTracker *
|
||||
gtk_menu_tracker_new (GActionObservable *observable,
|
||||
@@ -421,7 +478,7 @@ gtk_menu_tracker_new (GActionObservable *observable,
|
||||
{
|
||||
GtkMenuTracker *tracker;
|
||||
|
||||
tracker = g_slice_new (GtkMenuTracker);
|
||||
tracker = g_object_new (GTK_TYPE_MENU_TRACKER, NULL);
|
||||
tracker->observable = g_object_ref (observable);
|
||||
tracker->insert_func = insert_func;
|
||||
tracker->remove_func = remove_func;
|
||||
@@ -434,15 +491,32 @@ gtk_menu_tracker_new (GActionObservable *observable,
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_menu_tracker_free:
|
||||
* gtk_menu_tracker_setup:
|
||||
* @tracker: a #GtkMenuTracker
|
||||
* @observable: the #GActionObservable to use
|
||||
* @model: the model to flatten
|
||||
* @with_separators: if the toplevel should have separators (ie: TRUE
|
||||
* for menus, FALSE for menubars)
|
||||
* @action_namespace: the passed-in action namespace
|
||||
*
|
||||
* Frees the tracker, ...
|
||||
* Sets up the tracker.
|
||||
*
|
||||
* This will typically cause many 'insert' signals to be emitted.
|
||||
*
|
||||
* You can only call this once and you may not call this after using
|
||||
* gtk_menu_tracker_new().
|
||||
*/
|
||||
void
|
||||
gtk_menu_tracker_free (GtkMenuTracker *tracker)
|
||||
gtk_menu_tracker_setup (GtkMenuTracker *tracker,
|
||||
GActionObservable *observable,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace)
|
||||
{
|
||||
gtk_menu_tracker_section_free (tracker->toplevel);
|
||||
g_object_unref (tracker->observable);
|
||||
g_slice_free (GtkMenuTracker, tracker);
|
||||
g_return_if_fail (GTK_IS_MENU_TRACKER (tracker));
|
||||
g_return_if_fail (tracker->toplevel == NULL);
|
||||
|
||||
tracker->observable = g_object_ref (observable);
|
||||
tracker->toplevel = gtk_menu_tracker_section_new (tracker, model, with_separators, 0, action_namespace);
|
||||
gtk_menu_tracker_section_sync_separators (tracker->toplevel, tracker, 0, FALSE, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,17 @@
|
||||
|
||||
#include <gtk/gtkmenutrackeritem.h>
|
||||
|
||||
#define GTK_TYPE_MENU_TRACKER (gtk_menu_tracker_get_type ())
|
||||
#define GTK_MENU_TRACKER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
GTK_TYPE_MENU_TRACKER, GtkMenuTracker))
|
||||
#define GTK_IS_MENU_TRACKER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
GTK_TYPE_MENU_TRACKER))
|
||||
|
||||
typedef struct _GtkMenuTracker GtkMenuTracker;
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType gtk_menu_tracker_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef void (* GtkMenuTrackerInsertFunc) (GtkMenuTrackerItem *item,
|
||||
gint position,
|
||||
gpointer user_data);
|
||||
@@ -44,6 +53,10 @@ GtkMenuTracker * gtk_menu_tracker_new (GActionObservable
|
||||
gpointer user_data);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gtk_menu_tracker_free (GtkMenuTracker *tracker);
|
||||
void gtk_menu_tracker_setup (GtkMenuTracker *tracker,
|
||||
GActionObservable *observer,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace);
|
||||
|
||||
#endif /* __GTK_MENU_TRACKER_H__ */
|
||||
|
||||
Reference in New Issue
Block a user