</programlisting>
</example>
</simplesect>
+
+ <simplesect>
+ <title>Building UIs</title>
+
+ <para>When construcing a more complicated interface, with dozens
+ or hundreds of widgets, doing all the setup work in C code is
+ cumbersome, and making changes becomes next to impossible.</para>
+
+ <para>Thankfully, GTK+ supports the separation of user interface
+ layout from your business logic, by using UI descriptions in an
+ XML format that can be parsed by the #GtkBuilder class.</para>
+
+ <example>
+ <title>Packing buttons with GtkBuilder</title>
+ <programlisting>
+ <xi:include href="../../../../examples/builder.c" parse="text">
+ <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
+ </xi:include>
+ </programlisting>
+ The builder.ui file looks like this:
+ <programlisting>
+ <xi:include href="../../../../examples/builder.ui" parse="text">
+ <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
+ </xi:include>
+ </programlisting>
+ </example>
+
+ <para>Note that GtkBuilder can also be used to construct objects
+ that are not widgets, such as tree models, adjustments, etc.
+ That is the reason the method we use here is called
+ gtk_builder_get_object() and returns a GObject* instead of a
+ GtkWidget*.</para>
+
+ <para>Normally, you would pass a full path to
+ gtk_builder_add_From_file() to make the execution of your program
+ independent of the current directory. A common location to install
+ UI descriptions and similar data is
+ <filename>/usr/share/<replaceable>appname</replaceable></filename>.
+ </para>
+
+ <para>It is also possible to embed the UI description in the source
+ code as a string and use gtk_builder_add_from_string() to load it.
+ But keeping the UI description in a separate file has several
+ advantages: It is then possible to make minor adjustments to the UI
+ without recompiling your program, and, more importantly, graphical
+ UI editors such as <ulink url="http://glade.gnome.org">glade</ulink>
+ can load the file and allow you to create and modify your UI by
+ point-and-click.</para>
+
+ </simplesect>
</chapter>
window-default \
bloatpad \
grid-packing \
- drawing
+ drawing \
+ builder
+
+EXTRA_DIST = builder.ui
--- /dev/null
+#include <gtk/gtk.h>
+
+static void
+print_hello (GtkWidget *widget,
+ gpointer data)
+{
+ g_print ("Hello World\n");
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ GtkBuilder *builder;
+ GObject *window;
+ GObject *button;
+
+ gtk_init (&argc, &argv);
+
+ /* Construct a GtkBuilder instance and load our UI description */
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_file (builder, "builder.ui", NULL);
+
+ /* Connect signal handlers to the constructed widgets. */
+ window = gtk_builder_get_object (builder, "window");
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ button = gtk_builder_get_object (builder, "button1");
+ g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
+
+ button = gtk_builder_get_object (builder, "button2");
+ g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
+
+ button = gtk_builder_get_object (builder, "quit");
+ g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+
+ gtk_main ();
+
+ return 0;
+}
--- /dev/null
+<interface>
+ <object id="window" class="GtkWindow">
+ <property name="visible">True</property>
+ <property name="title">Grid</property>
+ <property name="border-width">10</property>
+ <child>
+ <object id="grid" class="GtkGrid">
+ <property name="visible">True</property>
+ <child>
+ <object id="button1" class="GtkButton">
+ <property name="visible">True</property>
+ <property name="label">Button 1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object id="button2" class="GtkButton">
+ <property name="visible">True</property>
+ <property name="label">Button 2</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object id="quit" class="GtkButton">
+ <property name="visible">True</property>
+ <property name="label">Quit</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ </packing>
+ </child>
+ </object>
+</interface>