mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
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
This commit is contained in:
parent
6d3c61856b
commit
aa3020a39e
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user