gtk+ r21767 - in trunk: . docs/reference/gtk/tmpl gtk gtk/tests
- From: tvb svn gnome org
- To: svn-commits-list gnome org
- Subject: gtk+ r21767 - in trunk: . docs/reference/gtk/tmpl gtk gtk/tests
- Date: Thu, 6 Nov 2008 17:34:31 +0000 (UTC)
Author: tvb
Date: Thu Nov 6 17:34:30 2008
New Revision: 21767
URL: http://svn.gnome.org/viewvc/gtk+?rev=21767&view=rev
Log:
* gtk/gtkmenuitem.c: Made buildable and added support for adding children
of type "submenu"
* gtk/gtkwindow.c: Added support for custom tag "accel-groups" to add GtkAccelGroups
to the window.
* gtk/gtkcontainer.c: Added builder contextual warnings in buildable_add_child()
* gtk/tests/builder.c: Added tests for buildable menus (test that accelerators are
properly connected on stock items, test the menu hierarchy, test permission to
add alien/custom menuitem children).
* docs/reference/gtk/tmpl/gtkbuilder.sgml, docs/reference/gtk/tmpl/gtkwindow.sgml,
docs/reference/gtk/tmpl/gtkmenuitem.sgml: Updated docs for buildable submenus
and accel groups.
Modified:
trunk/ChangeLog
trunk/docs/reference/gtk/tmpl/gtkbuilder.sgml
trunk/docs/reference/gtk/tmpl/gtkmenuitem.sgml
trunk/docs/reference/gtk/tmpl/gtkwindow.sgml
trunk/gtk/gtkcontainer.c
trunk/gtk/gtkmenuitem.c
trunk/gtk/gtkwindow.c
trunk/gtk/tests/builder.c
Modified: trunk/docs/reference/gtk/tmpl/gtkbuilder.sgml
==============================================================================
--- trunk/docs/reference/gtk/tmpl/gtkbuilder.sgml (original)
+++ trunk/docs/reference/gtk/tmpl/gtkbuilder.sgml Thu Nov 6 17:34:30 2008
@@ -212,6 +212,7 @@
respective objects, see
<link linkend="GtkWidget-BUILDER-UI">GtkWidget</link>,
<link linkend="GtkLabel-BUILDER-UI">GtkLabel</link>,
+<link linkend="GtkWindow-BUILDER-UI">GtkWindow</link>,
<link linkend="GtkContainer-BUILDER-UI">GtkContainer</link>,
<link linkend="GtkDialog-BUILDER-UI">GtkDialog</link>,
<link linkend="GtkCellLayout-BUILDER-UI">GtkCellLayout</link>,
@@ -227,6 +228,7 @@
<link linkend="GtkTreeView-BUILDER-UI">GtkTreeView</link>,
<link linkend="GtkUIManager-BUILDER-UI">GtkUIManager</link>,
<link linkend="GtkActionGroup-BUILDER-UI">GtkActionGroup</link>.
+<link linkend="GtkMenuItem-BUILDER-UI">GtkMenuItem</link>.
</para>
</refsect2>
Modified: trunk/docs/reference/gtk/tmpl/gtkmenuitem.sgml
==============================================================================
--- trunk/docs/reference/gtk/tmpl/gtkmenuitem.sgml (original)
+++ trunk/docs/reference/gtk/tmpl/gtkmenuitem.sgml Thu Nov 6 17:34:30 2008
@@ -14,6 +14,24 @@
As it derives from #GtkBin it can hold any valid child widget, altough
only a few are really useful.
</para>
+<refsect2 id="GtkMenuItem-BUILDER-UI">
+<title>GtkMenuItem as GtkBuildable</title>
+<para>
+The GtkMenuItem implementation of the GtkBuildable interface
+supports adding a submenu by specifying "submenu" as the "type"
+attribute of a <child> element.
+</para>
+<example>
+<title>A UI definition fragment with submenus</title>
+<programlisting><![CDATA[
+<object class="GtkMenuItem">
+ <child type="submenu">
+ <object class="GtkMenu"/>
+ </child>
+</object>
+]]></programlisting>
+</example>
+</refsect2>
<!-- ##### SECTION See_Also ##### -->
<para>
Modified: trunk/docs/reference/gtk/tmpl/gtkwindow.sgml
==============================================================================
--- trunk/docs/reference/gtk/tmpl/gtkwindow.sgml (original)
+++ trunk/docs/reference/gtk/tmpl/gtkwindow.sgml Thu Nov 6 17:34:30 2008
@@ -8,6 +8,29 @@
<para>
</para>
+<refsect2 id="GtkWindow-BUILDER-UI">
+<title>GtkWindow as GtkBuildable</title>
+<para>
+The GtkWindow implementation of the GtkBuildable interface supports a
+custom <accel-groups> element, which supports any number of <group>
+elements representing the GtkAccelGroup objects you want to add to your
+window (synonymous with gtk_window_add_accel_group().
+</para>
+<example>
+<title>A UI definition fragment with accel groups</title>
+<programlisting><![CDATA[
+<object class="GtkWindow">
+ <accel-groups>
+ <group name="accelgroup1"/>
+ </accel-groups>
+</object>
+
+...
+
+<object class="GtkAccelGroup" id="accelgroup1"/>
+]]></programlisting>
+</example>
+</refsect2>
<!-- ##### SECTION See_Also ##### -->
<para>
Modified: trunk/gtk/gtkcontainer.c
==============================================================================
--- trunk/gtk/gtkcontainer.c (original)
+++ trunk/gtk/gtkcontainer.c Thu Nov 6 17:34:30 2008
@@ -307,9 +307,17 @@
GObject *child,
const gchar *type)
{
- g_return_if_fail (GTK_IS_WIDGET (child));
-
- gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+ if (type)
+ {
+ GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
+ }
+ else if (GTK_IS_WIDGET (child) && GTK_WIDGET_TOPLEVEL (child) == FALSE)
+ {
+ gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+ }
+ else
+ g_warning ("Cannot add an object of type %s to a container of type %s",
+ g_type_name (G_OBJECT_TYPE (child)), g_type_name (G_OBJECT_TYPE (buildable)));
}
static void
Modified: trunk/gtk/gtkmenuitem.c
==============================================================================
--- trunk/gtk/gtkmenuitem.c (original)
+++ trunk/gtk/gtkmenuitem.c Thu Nov 6 17:34:30 2008
@@ -36,6 +36,7 @@
#include "gtkmenubar.h"
#include "gtkseparatormenuitem.h"
#include "gtkprivate.h"
+#include "gtkbuildable.h"
#include "gtkintl.h"
#include "gtkalias.h"
@@ -113,9 +114,19 @@
static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
+static void gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface);
+static void gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type);
+
static guint menu_item_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM)
+static GtkBuildableIface *parent_buildable_iface;
+
+G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_menu_item_buildable_interface_init))
static void
gtk_menu_item_class_init (GtkMenuItemClass *klass)
@@ -474,6 +485,26 @@
menu_item->submenu = NULL;
}
+static void
+gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+ iface->add_child = gtk_menu_item_buildable_add_child;
+}
+
+static void
+gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ if (type && strcmp (type, "submenu") == 0)
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
+ GTK_WIDGET (child));
+ else
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
/**
* gtk_menu_item_set_submenu:
* @menu_item: a #GtkMenuItem
Modified: trunk/gtk/gtkwindow.c
==============================================================================
--- trunk/gtk/gtkwindow.c (original)
+++ trunk/gtk/gtkwindow.c Thu Nov 6 17:34:30 2008
@@ -310,6 +310,7 @@
static GQuark quark_gtk_window_key_hash = 0;
static GQuark quark_gtk_window_default_icon_pixmap = 0;
static GQuark quark_gtk_window_icon_info = 0;
+static GQuark quark_gtk_buildable_accels = 0;
static GtkBuildableIface *parent_buildable_iface;
@@ -330,6 +331,17 @@
const GValue *value);
static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
GtkBuilder *builder);
+static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data);
+static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data);
G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
@@ -415,6 +427,7 @@
quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
+ quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
gobject_class->dispose = gtk_window_dispose;
gobject_class->finalize = gtk_window_finalize;
@@ -1137,7 +1150,8 @@
parent_buildable_iface = g_type_interface_peek_parent (iface);
iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
iface->parser_finished = gtk_window_buildable_parser_finished;
-
+ iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
+ iface->custom_finished = gtk_window_buildable_custom_finished;
}
static void
@@ -1159,11 +1173,118 @@
GtkBuilder *builder)
{
GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
+ GObject *object;
+ GSList *accels, *l;
if (priv->builder_visible)
gtk_widget_show (GTK_WIDGET (buildable));
- parent_buildable_iface->parser_finished (buildable, builder);
+ accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
+ for (l = accels; l; l = l->next)
+ {
+ object = gtk_builder_get_object (builder, l->data);
+ if (!object)
+ {
+ g_warning ("Unknown accel group %s specified in window %s",
+ (const gchar*)l->data, gtk_buildable_get_name (buildable));
+ continue;
+ }
+ gtk_window_add_accel_group (GTK_WINDOW (buildable),
+ GTK_ACCEL_GROUP (object));
+ g_free (l->data);
+ }
+
+ g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
+
+ parent_buildable_iface->parser_finished (buildable, builder);
+}
+
+typedef struct {
+ GObject *object;
+ GSList *items;
+} GSListSubParserData;
+
+static void
+window_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ guint i;
+ GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+ if (strcmp (element_name, "group") == 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, "accel-groups") == 0)
+ return;
+ else
+ g_warning ("Unsupported tag type for GtkWindow: %s\n",
+ element_name);
+
+}
+
+static const GMarkupParser window_parser =
+ {
+ window_start_element
+ };
+
+static gboolean
+gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data)
+{
+ GSListSubParserData *parser_data;
+
+ if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+ tagname, parser, data))
+ return TRUE;
+
+ if (strcmp (tagname, "accel-groups") == 0)
+ {
+ parser_data = g_slice_new0 (GSListSubParserData);
+ parser_data->items = NULL;
+ parser_data->object = G_OBJECT (buildable);
+
+ *parser = window_parser;
+ *data = parser_data;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_window_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data)
+{
+ GSListSubParserData *data;
+
+ parent_buildable_iface->custom_finished (buildable, builder, child,
+ tagname, user_data);
+
+ if (strcmp (tagname, "accel-groups") != 0)
+ return;
+
+ data = (GSListSubParserData*)user_data;
+
+ g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
+ data->items, (GDestroyNotify) g_slist_free);
+
+ g_slice_free (GSListSubParserData, data);
}
/**
Modified: trunk/gtk/tests/builder.c
==============================================================================
--- trunk/gtk/tests/builder.c (original)
+++ trunk/gtk/tests/builder.c Thu Nov 6 17:34:30 2008
@@ -2282,6 +2282,158 @@
g_object_unref (builder);
}
+GtkWidget *
+get_parent_menubar (GtkWidget *menuitem)
+{
+ GtkMenuShell *menu_shell = (GtkMenuShell *)menuitem->parent;
+ GtkWidget *attach = NULL;
+
+ g_assert (GTK_IS_MENU_SHELL (menu_shell));
+
+ while (menu_shell && !GTK_IS_MENU_BAR (menu_shell))
+ {
+ if (GTK_IS_MENU (menu_shell) &&
+ (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
+ menu_shell = (GtkMenuShell *)attach->parent;
+ else
+ menu_shell = NULL;
+ }
+
+ return menu_shell ? GTK_WIDGET (menu_shell) : NULL;
+}
+
+static void
+test_menus (void)
+{
+ gchar *buffer =
+ "<interface>"
+ " <object class=\"GtkWindow\" id=\"window1\">"
+ " <accel-groups>"
+ " <group name=\"accelgroup1\"/>"
+ " </accel-groups>"
+ " <child>"
+ " <object class=\"GtkVBox\" id=\"vbox1\">"
+ " <property name=\"visible\">True</property>"
+ " <property name=\"orientation\">vertical</property>"
+ " <child>"
+ " <object class=\"GtkMenuBar\" id=\"menubar1\">"
+ " <property name=\"visible\">True</property>"
+ " <child>"
+ " <object class=\"GtkMenuItem\" id=\"menuitem1\">"
+ " <property name=\"visible\">True</property>"
+ " <property name=\"label\" translatable=\"yes\">_File</property>"
+ " <property name=\"use_underline\">True</property>"
+ " <child type=\"submenu\">"
+ " <object class=\"GtkMenu\" id=\"menu1\">"
+ " <property name=\"visible\">True</property>"
+ " <child>"
+ " <object class=\"GtkImageMenuItem\" id=\"imagemenuitem1\">"
+ " <property name=\"label\">gtk-new</property>"
+ " <property name=\"visible\">True</property>"
+ " <property name=\"use_stock\">True</property>"
+ " <property name=\"accel_group\">accelgroup1</property>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ "<object class=\"GtkAccelGroup\" id=\"accelgroup1\"/>"
+ "</interface>";
+
+ gchar *buffer1 =
+ "<interface>"
+ " <object class=\"GtkWindow\" id=\"window1\">"
+ " <accel-groups>"
+ " <group name=\"accelgroup1\"/>"
+ " </accel-groups>"
+ " <child>"
+ " <object class=\"GtkVBox\" id=\"vbox1\">"
+ " <property name=\"visible\">True</property>"
+ " <property name=\"orientation\">vertical</property>"
+ " <child>"
+ " <object class=\"GtkMenuBar\" id=\"menubar1\">"
+ " <property name=\"visible\">True</property>"
+ " <child>"
+ " <object class=\"GtkImageMenuItem\" id=\"imagemenuitem1\">"
+ " <property name=\"visible\">True</property>"
+ " <child>"
+ " <object class=\"GtkLabel\" id=\"custom1\">"
+ " <property name=\"visible\">True</property>"
+ " <property name=\"label\">a label</property>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ " </child>"
+ " </object>"
+ "<object class=\"GtkAccelGroup\" id=\"accelgroup1\"/>"
+ "</interface>";
+ GtkBuilder *builder;
+ GtkWidget *window, *item;
+ GtkAccelGroup *accel_group;
+ GtkWidget *item_accel_label, *sample_accel_label, *sample_menu_item, *custom;
+
+ /* Check that the item has the correct accel label string set
+ */
+ builder = builder_new_from_string (buffer, -1, NULL);
+ window = (GtkWidget *)gtk_builder_get_object (builder, "window1");
+ item = (GtkWidget *)gtk_builder_get_object (builder, "imagemenuitem1");
+ accel_group = (GtkAccelGroup *)gtk_builder_get_object (builder, "accelgroup1");
+
+ gtk_widget_show_all (window);
+
+ sample_menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
+
+ g_assert (GTK_BIN (sample_menu_item)->child);
+ g_assert (GTK_IS_ACCEL_LABEL (GTK_BIN (sample_menu_item)->child));
+ sample_accel_label = GTK_WIDGET (GTK_BIN (sample_menu_item)->child);
+ gtk_widget_show (sample_accel_label);
+
+ g_assert (GTK_BIN (item)->child);
+ g_assert (GTK_IS_ACCEL_LABEL (GTK_BIN (item)->child));
+ item_accel_label = GTK_WIDGET (GTK_BIN (item)->child);
+
+ gtk_accel_label_refetch (GTK_ACCEL_LABEL (sample_accel_label));
+ gtk_accel_label_refetch (GTK_ACCEL_LABEL (item_accel_label));
+
+ g_assert (GTK_ACCEL_LABEL (sample_accel_label)->accel_string != NULL);
+ g_assert (GTK_ACCEL_LABEL (item_accel_label)->accel_string != NULL);
+ g_assert (strcmp (GTK_ACCEL_LABEL (item_accel_label)->accel_string,
+ GTK_ACCEL_LABEL (sample_accel_label)->accel_string) == 0);
+
+ /* Check the menu heirarchy worked here */
+ g_assert (get_parent_menubar (item));
+
+ gtk_widget_destroy (GTK_WIDGET (window));
+ gtk_widget_destroy (sample_menu_item);
+ g_object_unref (builder);
+
+
+ /* Check that we can add alien children to menu items via normal
+ * GtkContainer apis.
+ */
+ builder = builder_new_from_string (buffer1, -1, NULL);
+ window = (GtkWidget *)gtk_builder_get_object (builder, "window1");
+ item = (GtkWidget *)gtk_builder_get_object (builder, "imagemenuitem1");
+ custom = (GtkWidget *)gtk_builder_get_object (builder, "custom1");
+
+ g_assert (custom->parent == item);
+
+ gtk_widget_destroy (GTK_WIDGET (window));
+ g_object_unref (builder);
+
+}
+
+
static void
test_file (const gchar *filename)
{
@@ -2367,6 +2519,7 @@
g_test_add_func ("/Builder/PangoAttributes", test_pango_attributes);
g_test_add_func ("/Builder/Requires", test_requires);
g_test_add_func ("/Builder/AddObjects", test_add_objects);
+ g_test_add_func ("/Builder/Menus", test_menus);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]