[gtk+/wip/gtkmenutrackeritem: 3/3] GtkMenuTracker: become a proper GObject
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/gtkmenutrackeritem: 3/3] GtkMenuTracker: become a proper GObject
- Date: Wed, 8 May 2013 14:25:18 +0000 (UTC)
commit df502861bd09ef269c5ed2edd95ac55852bee06e
Author: Ryan Lortie <desrt desrt ca>
Date: Wed May 8 10:20:34 2013 -0400
GtkMenuTracker: become a proper GObject
Turn GtkMenuTracker into a GObject with "insert" and "remove" signals
for the sake of accessibility from language bindings.
gtk/gtkmenushell.c | 4 +-
gtk/gtkmenutracker.c | 120 ++++++++++++++++++++++++++++++++++++++++----------
gtk/gtkmenutracker.h | 15 ++++++-
3 files changed, 113 insertions(+), 26 deletions(-)
---
diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c
index c244ab1..cd683ba 100644
--- a/gtk/gtkmenushell.c
+++ b/gtk/gtkmenushell.c
@@ -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);
@@ -2214,7 +2214,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);
diff --git a/gtk/gtkmenutracker.c b/gtk/gtkmenutracker.c
index 764b93c..d5f55f0 100644
--- a/gtk/gtkmenutracker.c
+++ b/gtk/gtkmenutracker.c
@@ -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
+ *
+ * Sets up the tracker.
+ *
+ * This will typically cause many 'insert' signals to be emitted.
*
- * Frees the tracker, ...
+ * 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);
}
diff --git a/gtk/gtkmenutracker.h b/gtk/gtkmenutracker.h
index 51c5a7b..c679fa8 100644
--- a/gtk/gtkmenutracker.h
+++ b/gtk/gtkmenutracker.h
@@ -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__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]