[gtk+] GtkContainer: Support focus chain in GtkBuilder
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] GtkContainer: Support focus chain in GtkBuilder
- Date: Tue, 30 Sep 2014 03:59:29 +0000 (UTC)
commit aa3020a39ec2428b6a44e309d64246aa9b8342f9
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Sep 27 00:20:50 2014 -0400
GtkContainer: Support focus chain in GtkBuilder
This adds support for a <focus-chain> element which can be
used to specify a custom focus order for the children of
a container.
https://bugzilla.gnome.org/show_bug.cgi?id=582799
gtk/gtkcontainer.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 119 insertions(+), 8 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 0394a99..11fbdc2 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -221,21 +221,33 @@
* a <packing> element for children, which can contain multiple <property>
* elements that specify child properties for the child.
*
- * An example of child properties in UI definitions:
+ * Since 2.16, child properties can also be marked as translatable using
+ * the same “translatable”, “comments” and “context” attributes that are used
+ * for regular properties.
+ *
+ * Since 3.16, containers can have a <focus-chain> element containing multiple
+ * <widget> elements, one for each child that should be added to the focus
+ * chain. The ”name” attribute gives the id of the widget.
+ *
+ * An example of these properties in UI definitions:
* |[
- * <object class="GtkVBox">
+ * <object class="GtkBox">
* <child>
- * <object class="GtkLabel"/>
+ * <object class="GtkEntry" id="entry1"/>
* <packing>
* <property name="pack-type">start</property>
* </packing>
* </child>
+ * <child>
+ * <object class="GtkEntry" id="entry2"/>
+ * </child>
+ * <focus-chain>
+ * <widget name="entry1"/>
+ * <widget name="entry2"/>
+ * </focus-chain>
* </object>
* ]|
*
- * Since 2.16, child properties can also be marked as translatable using
- * the same “translatable”, “comments” and “context” attributes that are used
- * for regular properties.
*/
@@ -353,6 +365,11 @@ static void gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
GObject *child,
const gchar *tagname,
gpointer *data);
+static void gtk_container_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer data);
static gboolean gtk_container_should_propagate_draw (GtkContainer *container,
GtkWidget *child,
@@ -557,6 +574,7 @@ gtk_container_buildable_init (GtkBuildableIface *iface)
iface->add_child = gtk_container_buildable_add_child;
iface->custom_tag_start = gtk_container_buildable_custom_tag_start;
iface->custom_tag_end = gtk_container_buildable_custom_tag_end;
+ iface->custom_finished = gtk_container_buildable_custom_finished;
}
static void
@@ -727,6 +745,46 @@ static const GMarkupParser attributes_parser =
attributes_text_element,
};
+typedef struct
+ {
+ GSList *items;
+ GObject *object;
+ } FocusChainData;
+
+static void
+focus_chain_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ guint i;
+ FocusChainData *data = (FocusChainData*)user_data;
+
+ if (strcmp (element_name, "widget") == 0)
+ {
+ for (i = 0; names[i]; i++)
+ {
+ if (strcmp (names[i], "name") == 0)
+ data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+ }
+ }
+ else if (strcmp (element_name, "focus-chain") == 0)
+ {
+ return;
+ }
+ else
+ {
+ g_warning ("Unsupported type tag for GtkContainer %s\n", element_name);
+ }
+}
+
+static const GMarkupParser focus_chain_parser =
+ {
+ focus_chain_start_element
+ };
+
static gboolean
gtk_container_buildable_custom_tag_start (GtkBuildable *buildable,
GtkBuilder *builder,
@@ -735,14 +793,14 @@ gtk_container_buildable_custom_tag_start (GtkBuildable *buildable,
GMarkupParser *parser,
gpointer *data)
{
- PackingPropertiesData *parser_data;
-
if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
tagname, parser, data))
return TRUE;
if (child && strcmp (tagname, "packing") == 0)
{
+ PackingPropertiesData *parser_data;
+
parser_data = g_slice_new0 (PackingPropertiesData);
parser_data->string = g_string_new ("");
parser_data->builder = builder;
@@ -754,6 +812,17 @@ gtk_container_buildable_custom_tag_start (GtkBuildable *buildable,
*data = parser_data;
return TRUE;
}
+ else if (!child && strcmp (tagname, "focus-chain") == 0)
+ {
+ FocusChainData *parser_data;
+ parser_data = g_slice_new0 (FocusChainData);
+ parser_data->items = NULL;
+ parser_data->object = G_OBJECT (buildable);
+
+ *parser = focus_chain_parser;
+ *data = parser_data;
+ return TRUE;
+ }
return FALSE;
}
@@ -778,6 +847,48 @@ gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
child, tagname, data);
}
+static void
+gtk_container_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer data)
+{
+ if (strcmp (tagname, "focus-chain") == 0)
+ {
+ FocusChainData *parser_data = (FocusChainData*)data;
+ GSList *l;
+ GList *chain;
+ GObject *object;
+
+ chain = NULL;
+ for (l = parser_data->items; l; l = l->next)
+ {
+ object = gtk_builder_get_object (builder, l->data);
+ if (!object)
+ {
+ g_warning ("Unknown object %s specified in focus-chain for %s",
+ (const gchar*)l->data,
+ gtk_buildable_get_name (GTK_BUILDABLE (parser_data->object)));
+ continue;
+ }
+ chain = g_list_prepend (chain, object);
+ }
+
+ gtk_container_set_focus_chain (GTK_CONTAINER (parser_data->object), chain);
+ g_list_free (chain);
+
+ g_slist_free_full (parser_data->items, g_free);
+ g_slice_free (FocusChainData, parser_data);
+
+ return;
+ }
+
+ if (parent_buildable_iface->custom_finished)
+ parent_buildable_iface->custom_finished (buildable, builder,
+ child, tagname, data);
+}
+
/**
* gtk_container_child_type:
* @container: a #GtkContainer
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]