[gtkmm-documentation] Add part of "Building applications" chapter with example code



commit 280d7393b9cc176a851faa32952a7cff59a74ac8
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Sun Oct 9 18:58:09 2016 +0200

    Add part of "Building applications" chapter with example code
    
    * docs/tutorial/C/index-in.docbook: Add the first 3 sections of the "Building
    applications" chapter. It's a C++/gtkmm version of a chapter in the gtk+
    documentation.
    * docs/tutorial/C/figures/buildapp_*.png: New files.
    * docs/tutorial/Makefile.am: Add new image files.
    * configure.ac: Add examples/book/buildapp/Makefile.
    * examples/Makefile.am: Call Makefile in the book/buildapp directory.
    * examples/book/buildapp/*: New directory with many new files.
    Bug #772391

 configure.ac                                       |    1 +
 docs/tutorial/C/figures/buildapp_opening_files.png |  Bin 0 -> 63004 bytes
 .../C/figures/buildapp_populating_window.png       |  Bin 0 -> 8935 bytes
 docs/tutorial/C/figures/buildapp_trivial_app.png   |  Bin 0 -> 5382 bytes
 docs/tutorial/C/index-in.docbook                   |  227 ++++++++++++++++++++
 docs/tutorial/Makefile.am                          |    3 +
 examples/Makefile.am                               |    2 +
 examples/book/buildapp/Makefile.am                 |   64 ++++++
 examples/book/buildapp/README                      |   19 ++
 examples/book/buildapp/step1/Makefile.example      |   28 +++
 examples/book/buildapp/step1/exampleapp.desktop    |    9 +
 examples/book/buildapp/step1/exampleapp.png        |  Bin 0 -> 4117 bytes
 examples/book/buildapp/step1/exampleapplication.cc |   78 +++++++
 examples/book/buildapp/step1/exampleapplication.h  |   42 ++++
 examples/book/buildapp/step1/exampleappwindow.cc   |   26 +++
 examples/book/buildapp/step1/exampleappwindow.h    |   29 +++
 examples/book/buildapp/step1/main.cc               |   27 +++
 examples/book/buildapp/step2/Makefile.example      |   41 ++++
 .../book/buildapp/step2/exampleapp.gresource.xml   |    6 +
 examples/book/buildapp/step2/exampleapplication.cc |  105 +++++++++
 examples/book/buildapp/step2/exampleapplication.h  |    2 +
 examples/book/buildapp/step2/exampleappwindow.cc   |   42 ++++
 examples/book/buildapp/step2/exampleappwindow.h    |   35 +++
 examples/book/buildapp/step2/main.cc               |    2 +
 examples/book/buildapp/step2/window.ui             |   31 +++
 examples/book/buildapp/step3/Makefile.example      |    2 +
 .../book/buildapp/step3/exampleapp.gresource.xml   |    6 +
 examples/book/buildapp/step3/exampleapplication.cc |    2 +
 examples/book/buildapp/step3/exampleapplication.h  |    2 +
 examples/book/buildapp/step3/exampleappwindow.cc   |   74 +++++++
 examples/book/buildapp/step3/exampleappwindow.h    |   36 +++
 examples/book/buildapp/step3/main.cc               |    2 +
 examples/book/buildapp/step3/window.ui             |   31 +++
 33 files changed, 974 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a149ea6..b83385b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,5 +46,6 @@ YELP_HELP_INIT
 
 AC_CONFIG_FILES([Makefile
                  examples/Makefile
+                 examples/book/buildapp/Makefile
                  docs/tutorial/Makefile])
 AC_OUTPUT
diff --git a/docs/tutorial/C/figures/buildapp_opening_files.png 
b/docs/tutorial/C/figures/buildapp_opening_files.png
new file mode 100644
index 0000000..c6bec38
Binary files /dev/null and b/docs/tutorial/C/figures/buildapp_opening_files.png differ
diff --git a/docs/tutorial/C/figures/buildapp_populating_window.png 
b/docs/tutorial/C/figures/buildapp_populating_window.png
new file mode 100644
index 0000000..2ae55bc
Binary files /dev/null and b/docs/tutorial/C/figures/buildapp_populating_window.png differ
diff --git a/docs/tutorial/C/figures/buildapp_trivial_app.png 
b/docs/tutorial/C/figures/buildapp_trivial_app.png
new file mode 100644
index 0000000..33a0bdf
Binary files /dev/null and b/docs/tutorial/C/figures/buildapp_trivial_app.png differ
diff --git a/docs/tutorial/C/index-in.docbook b/docs/tutorial/C/index-in.docbook
index 9488c56..9d64d4f 100644
--- a/docs/tutorial/C/index-in.docbook
+++ b/docs/tutorial/C/index-in.docbook
@@ -87,6 +87,7 @@ name
         <firstname>Kjell</firstname>
         <surname>Ahlstedt</surname>
         <contrib>Parts of the update from gtkmm 2 to gtkmm 3.</contrib>
+        <contrib>Chapter on &quot;Building applications&quot;.</contrib>
       </author>
     </authorgroup>
 
@@ -7770,6 +7771,232 @@ first see a blank window, into which the widgets will be gradually drawn.
 </sect1>
 </chapter>
 
+<chapter id="chapter-building-applications">
+<title>Building applications</title>
+
+<para>
+This chapter is similar to the &quot;Building applications&quot; chapter in the
+<ulink url="https://developer.gnome.org/gtk3/stable/";>GTK+ 3 Reference Manual</ulink>.
+The same application is built, but &gtkmm; is used instead of <application>GTK+</application>.
+</para>
+<para>
+An application consists of a number of files:
+<variablelist>
+  <varlistentry>
+    <term>The binary file</term>
+    <listitem><para>This gets installed in <filename>/usr/bin</filename>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>A desktop file</term>
+    <listitem><para>The desktop file provides important information about the application
+      to the desktop shell, such as its name, icon, D-Bus name, commandline to launch it,
+      etc. It is installed in <filename>/usr/share/applications</filename>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>An icon</term>
+    <listitem><para>The icon gets installed in <filename>/usr/share/icons/hicolor/48x48/apps</filename>,
+      where it will be found regardless of the current theme.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>A settings schema</term>
+    <listitem><para>If the application uses <classname>Gio::Settings</classname>,
+      it will install its schema in <filename>/usr/share/glib-2.0/schemas</filename>,
+      so that tools like dconf-editor can find it.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>Other resources</term>
+    <listitem><para>Other files, such as <classname>Gtk::Builder</classname> ui files,
+      are best loaded from resources stored in the application binary itself. This
+      eliminates the need for most of the files that would traditionally be installed
+      in an application-specific location in <filename>/usr/share</filename>.</para></listitem>
+  </varlistentry>
+</variablelist>
+</para>
+
+<para>
+&gtkmm; includes application support that is built on top of <classname>Gio::Application</classname>.
+In this chapter we'll build a simple application by starting from scratch, adding more
+and more pieces over time. Along the way, we'll learn about <classname>Gtk::Application</classname>,
+<classname>Gtk::Builder</classname>, resources, application menus, settings,
+<classname>Gtk::HeaderBar</classname>, <classname>Gtk::Stack</classname>,
+<classname>Gtk::SearchBar</classname>, <classname>Gtk::ListBox</classname>, and more.
+</para>
+
+<para>
+The full, buildable sources for these examples can be found in the
+<filename>examples/book/buildapp</filename> directory of the
+<application>gtkmm-documentation</application> source distribution, or online in the
+<ulink url="&url_examples_base;buildapp"><application>gtkmm-documentation</application>
+git repository</ulink>. You can build each example separately by using make with the
+<filename>Makefile.example</filename> file. For more information, see the
+<filename>README</filename> included in the <filename>buildapp</filename> directory.
+</para>
+
+<sect1 id="sec-buildapp-trivial-app">
+<title>A trivial application</title>
+
+<para>
+When using <classname>Gtk::Application</classname>, the <function>main()</function> function
+can be very simple. We just call <methodname>Gio::Application::run()</methodname> on an
+instance of our application class.
+</para>
+
+<para>
+All the application logic is in the application class, which is a subclass of
+<classname>Gtk::Application</classname>. Our example does not yet have any interesting
+functionality. All it does is open a window when it is activated without arguments,
+and open the files it is given, if it is started with arguments. (Or rather, our
+application class tries to open the files, but our subclassed application window
+does not yet do what it's told to do.)
+</para>
+
+<para>
+To handle these two cases, we override <methodname>signal_activate()</methodname>'s
+default handler, which gets called when the application is launched without commandline
+arguments, and <methodname>signal_open()</methodname>'s default handler, which gets
+called when the application is launched with commandline arguments.
+</para>
+
+<para><ulink url="&url_refdocs_base_gio;Application.html">Gio::Application Reference</ulink></para>
+
+<para>
+Another important class that is part of the application support in &gtkmm; is
+<classname>Gtk::ApplicationWindow</classname>. It is typically subclassed as well.
+Our subclass does not do anything yet, so we will just get an empty window.
+</para>
+
+<para>
+As part of the initial setup of our application, we also create an icon and a desktop file.
+Note that @bindir@ in the desktop file needs to be replaced with the actual path
+to the binary before this desktop file can be used.
+</para>
+
+<para>
+Here is what we've achieved so far:
+</para>
+
+<figure id="figure-buildapp-trivial-app">
+  <title>A trivial application</title>
+  <screenshot>
+    <graphic format="PNG" fileref="&url_figures_base;buildapp_trivial_app.png"/>
+  </screenshot>
+</figure>
+
+<para>
+This does not look very impressive yet, but our application is already presenting itself
+on the session bus, it has single-instance semantics, and it accepts files as commandline arguments.
+</para>
+
+<para><ulink url="&url_examples_base;buildapp/step1">Source Code</ulink></para> <!-- Insert 
exampleapp.desktop -->
+
+</sect1>
+
+<sect1 id="sec-buildapp-populating-window">
+<title>Populating the window</title>
+
+<para>
+In this step, we use a <classname>Gtk::Builder</classname> instance to associate a
+<classname>Gtk::Builder</classname> ui file with our application window class.
+</para>
+
+<para>
+Our simple ui file puts a <classname>Gtk::HeaderBar</classname> on top of a
+<classname>Gtk::Stack</classname> widget. The header bar contains a
+<classname>Gtk::StackSwitcher</classname>, which is a standalone widget to show a row
+of 'tabs' for the pages of a <classname>Gtk::Stack</classname>. 
+</para>
+
+<para>
+To make use of this file in our application, we revisit our
+<classname>Gtk::ApplicationWindow</classname> subclass, and call
+<methodname>Gtk::Builder::create_from_resource()</methodname> and
+<methodname>Gtk::Builder::get_widget_derived()</methodname> from the
+<methodname>ExampleAppWindow::create()</methodname> method to get an instance of
+our subclassed <classname>Gtk::ApplicationWindow</classname>. See the 
+<link linkend="sec-builder-using-derived-widgets">Using derived widgets</link> section
+for more information about <methodname>get_widget_derived()</methodname>.
+</para>
+
+<para>
+You may have noticed that we use the <methodname>_from_resource()</methodname> variant
+of the method that reads the ui file. Now we need to use <application>GLib</application>'s
+resource functionality to include the ui file in the binary. This is commonly done by
+listing all resources in a .gresource.xml file.
+This file has to be converted into a C source file that will be compiled and linked
+into the application together with the other source files. To do so, we use the
+<application>glib-compile-resources</application> utility:
+<screen>$ glib-compile-resources --target=resources.c --generate-source exampleapp.gresource.xml</screen>
+The <link linkend="sec-gio-resource">Gio::Resource and glib-compile-resources</link>
+section contains more information about resource files.
+</para>
+
+<para>
+Our application now looks like this:
+</para>
+
+<figure id="figure-buildapp-populating-window">
+  <title>Populating the window</title>
+  <screenshot>
+    <graphic format="PNG" fileref="&url_figures_base;buildapp_populating_window.png"/>
+  </screenshot>
+</figure>
+
+<para><ulink url="&url_examples_base;buildapp/step2">Source Code</ulink></para> <!-- Insert 
exampleapp.gresource.xml window.ui -->
+
+</sect1>
+
+<sect1 id="sec-buildapp-opening-files">
+<title>Opening files</title>
+
+<para>
+In this step, we make our application show the contents of all the files that it is
+given on the commandline.
+</para>
+
+<para>
+To this end, we add a data member to our application window and keep a pointer to the
+<classname>Gtk::Stack</classname> there. We get the pointer with a call to
+<methodname>Gtk::Builder::get_widget()</methodname> in the application window's constructor.
+</para>
+
+<para>
+Now we revisit the <methodname>ExampleAppWindow::open_file_view()</methodname> method
+that is called for each commandline argument, and construct a <classname>Gtk::TextView</classname>
+that we then add as a page to the stack.
+</para>
+
+<para>
+Note that we do not have to touch the stack switcher at all. It gets all its information
+from the stack that it belongs to. Here, we are passing the label to show for each file
+as the last argument to the <methodname>Gtk::Stack::add()</methodname> method.
+</para>
+
+<para>
+Our application is beginning to take shape:
+</para>
+
+<figure id="figure-buildapp-opening-files">
+  <title>Opening files</title>
+  <screenshot>
+    <graphic format="PNG" fileref="&url_figures_base;buildapp_opening_files.png"/>
+  </screenshot>
+</figure>
+
+<para><ulink url="&url_examples_base;buildapp/step3">Source Code</ulink></para>
+
+</sect1>
+
+<sect1 id="sec-buildapp-app-menu">
+<title>An application menu</title>
+
+<para>
+To be continued.
+</para>
+
+</sect1>
+
+</chapter>
+
 <chapter id="chapter-contributing">
 <title>Contributing</title>
 
diff --git a/docs/tutorial/Makefile.am b/docs/tutorial/Makefile.am
index d23820c..f3a94a2 100644
--- a/docs/tutorial/Makefile.am
+++ b/docs/tutorial/Makefile.am
@@ -30,6 +30,9 @@ HELP_MEDIA =                                  \
        figures/box_packing1.png                \
        figures/box_packing2.png                \
        figures/box_packing3.png                \
+       figures/buildapp_opening_files.png \
+       figures/buildapp_populating_window.png \
+       figures/buildapp_trivial_app.png \
        figures/buttonbox.png                   \
        figures/buttons.png                     \
        figures/cairo_clock.png                 \
diff --git a/examples/Makefile.am b/examples/Makefile.am
index b1e6c43..8496dac 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,5 +1,7 @@
 ## This file is part of gtkmm-documentation.
 
+SUBDIRS = book/buildapp
+
 AUTOMAKE_OPTIONS = subdir-objects
 
 AM_CPPFLAGS = -I$(top_builddir) $(GTHREAD_CFLAGS) $(GTKMM_CFLAGS)
diff --git a/examples/book/buildapp/Makefile.am b/examples/book/buildapp/Makefile.am
new file mode 100644
index 0000000..e4deeda
--- /dev/null
+++ b/examples/book/buildapp/Makefile.am
@@ -0,0 +1,64 @@
+## This file is part of gtkmm-documentation.
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+AM_CPPFLAGS = $(GTKMM_CFLAGS)
+AM_CXXFLAGS = $(EXAMPLES_WXXFLAGS)
+LDADD       = $(GTKMM_LIBS)
+
+check_PROGRAMS = \
+  step1/exampleapp \
+  step2/exampleapp \
+  step3/exampleapp
+
+dist_noinst_DATA = \
+  README \
+  step1/exampleapp.desktop \
+  step1/exampleapp.png \
+  step1/Makefile.example \
+  $(STEP2_RESOURCES) \
+  step2/Makefile.example \
+  $(STEP3_RESOURCES) \
+  step3/Makefile.example
+
+step1_exampleapp_SOURCES = \
+  step1/exampleapplication.cc \
+  step1/exampleapplication.h \
+  step1/exampleappwindow.cc \
+  step1/exampleappwindow.h \
+  step1/main.cc
+
+step2_exampleapp_SOURCES = \
+  step2/resources.c \
+  step2/exampleapplication.cc \
+  step2/exampleapplication.h \
+  step2/exampleappwindow.cc \
+  step2/exampleappwindow.h \
+  step2/main.cc
+
+step3_exampleapp_SOURCES = \
+  step3/resources.c \
+  step3/exampleapplication.cc \
+  step3/exampleapplication.h \
+  step3/exampleappwindow.cc \
+  step3/exampleappwindow.h \
+  step3/main.cc
+
+MAINTAINERCLEANFILES = \
+  step2/resources.c \
+  step3/resources.c
+
+STEP2_RESOURCES = \
+  step2/exampleapp.gresource.xml \
+  step2/window.ui
+
+step2/resources.c: $(STEP2_RESOURCES)
+       $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(dir $<) --generate-source $<
+
+STEP3_RESOURCES = \
+  step3/exampleapp.gresource.xml \
+  step3/window.ui
+
+step3/resources.c: $(STEP3_RESOURCES)
+       $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(dir $<) --generate-source $<
+
diff --git a/examples/book/buildapp/README b/examples/book/buildapp/README
new file mode 100644
index 0000000..98d2a5b
--- /dev/null
+++ b/examples/book/buildapp/README
@@ -0,0 +1,19 @@
+=== gtkmm-documentation/examples/book/buildapp/step[1-9] ===
+
+== Building the examples ==
+
+The examples in this directory are built with 'make check' alongside the rest of
+the examples in gtkmm-documentation.
+
+The examples in the step[1-9] directories can also be built independently,
+by doing:
+
+  $ cd step1  # or step2, step3, etc.
+  $ make -f Makefile.example
+
+To make gnome-shell use the desktop file and icon for one of the examples
+while running it uninstalled, do the following:
+
+  $ cd step1  # or step2, step3, etc.
+  $ make -f Makefile.example install-desktop-file
+
diff --git a/examples/book/buildapp/step1/Makefile.example b/examples/book/buildapp/step1/Makefile.example
new file mode 100644
index 0000000..8135177
--- /dev/null
+++ b/examples/book/buildapp/step1/Makefile.example
@@ -0,0 +1,28 @@
+CXX ?= g++
+PROGRAM = exampleapp
+CXXFILES = main.cc exampleappwindow.cc exampleapplication.cc
+OBJS = $(CXXFILES:.cc=.o)
+DEPDIR = .deps
+CXXFLAGS = `pkg-config --cflags gtkmm-3.0` -std=c++11 -Wall -g
+LIBS = `pkg-config --libs gtkmm-3.0`
+
+all: $(PROGRAM)
+
+include $(CXXFILES:%.cc=$(DEPDIR)/%.Po)
+
+%.o: %.cc
+       $(CXX) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(CXXFLAGS) $<
+       mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+
+$(PROGRAM): $(OBJS)
+       $(CXX) -o $(PROGRAM) $(OBJS) $(LIBS)
+
+clean:
+       rm -f $(OBJS)
+       rm -f $(PROGRAM)
+
+install-desktop-file:
+       mkdir -p ~/.local/share/applications
+       sed -e "s#@bindir@#$$PWD#" exampleapp.desktop > ~/.local/share/applications/$(PROGRAM).desktop
+       mkdir -p ~/.local/share/icons/hicolor/48x48/apps
+       cp exampleapp.png ~/.local/share/icons/hicolor/48x48/apps
diff --git a/examples/book/buildapp/step1/exampleapp.desktop b/examples/book/buildapp/step1/exampleapp.desktop
new file mode 100644
index 0000000..5c433e1
--- /dev/null
+++ b/examples/book/buildapp/step1/exampleapp.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=Application
+Name=Gtkmm example
+GenericName=Example
+Comment=From the "Programming with gtkmm 3" tutorial
+Icon=exampleapp
+StartupNotify=true
+Exec=@bindir@/exampleapp %U
+Categories=GNOME;GTK;Utility
diff --git a/examples/book/buildapp/step1/exampleapp.png b/examples/book/buildapp/step1/exampleapp.png
new file mode 100644
index 0000000..8beb54e
Binary files /dev/null and b/examples/book/buildapp/step1/exampleapp.png differ
diff --git a/examples/book/buildapp/step1/exampleapplication.cc 
b/examples/book/buildapp/step1/exampleapplication.cc
new file mode 100644
index 0000000..ffe3a79
--- /dev/null
+++ b/examples/book/buildapp/step1/exampleapplication.cc
@@ -0,0 +1,78 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "exampleapplication.h"
+#include "exampleappwindow.h"
+
+ExampleApplication::ExampleApplication()
+: Gtk::Application("org.gtkmm.examples.application", Gio::APPLICATION_HANDLES_OPEN)
+{
+}
+
+Glib::RefPtr<ExampleApplication> ExampleApplication::create()
+{
+  return Glib::RefPtr<ExampleApplication>(new ExampleApplication());
+}
+
+ExampleAppWindow* ExampleApplication::create_appwindow()
+{
+  auto appwindow = new ExampleAppWindow();
+
+  // Make sure that the application runs for as long this window is still open.
+  add_window(*appwindow);
+
+  // Gtk::Application::add_window() connects a signal handler to the window's
+  // signal_hide(). That handler removes the window from the application.
+  // If it's the last window to be removed, the application stops running.
+  // Gtk::Window::set_application() does not connect a signal handler, but is
+  // otherwise equivalent to Gtk::Application::add_window().
+
+  // Delete the window when it is hidden.
+  appwindow->signal_hide().connect(sigc::bind<Gtk::Window*>(sigc::mem_fun(*this,
+    &ExampleApplication::on_hide_window), appwindow));
+
+  return appwindow;
+}
+
+void ExampleApplication::on_activate()
+{
+  // The application has been started, so let's show a window.
+  auto appwindow = create_appwindow();
+  appwindow->present();
+}
+
+void ExampleApplication::on_open(const Gio::Application::type_vec_files& files,
+  const Glib::ustring& /* hint */)
+{
+  // The application has been asked to open some files,
+  // so let's open a new view for each one.
+  ExampleAppWindow* appwindow = nullptr;
+  auto windows = get_windows();
+  if (windows.size() > 0)
+    appwindow = dynamic_cast<ExampleAppWindow*>(windows[0]);
+
+  if (!appwindow)
+    appwindow = create_appwindow();
+
+  for (const auto& file : files)
+    appwindow->open_file_view(file);
+
+  appwindow->present();
+}
+
+void ExampleApplication::on_hide_window(Gtk::Window* window)
+{
+  delete window;
+}
diff --git a/examples/book/buildapp/step1/exampleapplication.h 
b/examples/book/buildapp/step1/exampleapplication.h
new file mode 100644
index 0000000..a4d148e
--- /dev/null
+++ b/examples/book/buildapp/step1/exampleapplication.h
@@ -0,0 +1,42 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTKMM_EXAMPLEAPPLICATION_H
+#define GTKMM_EXAMPLEAPPLICATION_H
+
+#include <gtkmm.h>
+
+class ExampleAppWindow;
+
+class ExampleApplication: public Gtk::Application
+{
+protected:
+  ExampleApplication();
+
+public:
+  static Glib::RefPtr<ExampleApplication> create();
+
+protected:
+  // Override default signal handlers:
+  void on_activate() override;
+  void on_open(const Gio::Application::type_vec_files& files,
+    const Glib::ustring& hint) override;
+
+private:
+  ExampleAppWindow* create_appwindow();
+  void on_hide_window(Gtk::Window* window);
+};
+
+#endif /* GTKMM_EXAMPLEAPPLICATION_H */
diff --git a/examples/book/buildapp/step1/exampleappwindow.cc 
b/examples/book/buildapp/step1/exampleappwindow.cc
new file mode 100644
index 0000000..7e0795f
--- /dev/null
+++ b/examples/book/buildapp/step1/exampleappwindow.cc
@@ -0,0 +1,26 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "exampleappwindow.h"
+
+ExampleAppWindow::ExampleAppWindow()
+: Gtk::ApplicationWindow()
+{
+}
+
+void ExampleAppWindow::open_file_view(const Glib::RefPtr<Gio::File>& /* file */)
+{
+}
+
diff --git a/examples/book/buildapp/step1/exampleappwindow.h b/examples/book/buildapp/step1/exampleappwindow.h
new file mode 100644
index 0000000..d298b8e
--- /dev/null
+++ b/examples/book/buildapp/step1/exampleappwindow.h
@@ -0,0 +1,29 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTKMM_EXAMPLEAPPWINDOW_H_
+#define GTKMM_EXAMPLEAPPWINDOW_H_
+
+#include <gtkmm.h>
+
+class ExampleAppWindow : public Gtk::ApplicationWindow
+{
+public:
+  ExampleAppWindow();
+
+  void open_file_view(const Glib::RefPtr<Gio::File>& file);
+};
+
+#endif /* GTKMM_EXAMPLEAPPWINDOW_H */
diff --git a/examples/book/buildapp/step1/main.cc b/examples/book/buildapp/step1/main.cc
new file mode 100644
index 0000000..ebcb62c
--- /dev/null
+++ b/examples/book/buildapp/step1/main.cc
@@ -0,0 +1,27 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "exampleapplication.h"
+
+int main(int argc, char* argv[])
+{
+  auto application = ExampleApplication::create();
+
+  // Start the application, showing the initial window,
+  // and opening extra views for any files that it is asked to open,
+  // for instance as a command-line parameter.
+  // run() will return when the last window has been closed.
+  return application->run(argc, argv);
+}
diff --git a/examples/book/buildapp/step2/Makefile.example b/examples/book/buildapp/step2/Makefile.example
new file mode 100644
index 0000000..c000213
--- /dev/null
+++ b/examples/book/buildapp/step2/Makefile.example
@@ -0,0 +1,41 @@
+CC ?= gcc
+CXX ?= g++
+PROGRAM = exampleapp
+CXXFILES = main.cc exampleappwindow.cc exampleapplication.cc
+BUILT_SRC = resources.c
+OBJS = $(BUILT_SRC:.c=.o) $(CXXFILES:.cc=.o)
+DEPDIR = .deps
+CXXFLAGS = `pkg-config --cflags gtkmm-3.0` -std=c++11 -Wall -g
+CFLAGS = `pkg-config --cflags gtk+-3.0`
+LIBS = `pkg-config --libs gtkmm-3.0`
+GLIB_COMPILE_RESOURCES = `pkg-config --variable=glib_compile_resources gio-2.0`
+
+all: $(PROGRAM)
+
+include $(CXXFILES:%.cc=$(DEPDIR)/%.Po)
+include $(BUILT_SRC:%.c=$(DEPDIR)/%.Po)
+
+resources.c: exampleapp.gresource.xml window.ui
+       $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(dir $<) --generate-source $<
+
+%.o: %.c
+       $(CC) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(CFLAGS) $<
+       mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+
+%.o: %.cc
+       $(CXX) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(CXXFLAGS) $<
+       mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+
+$(PROGRAM): $(OBJS)
+       $(CXX) -o $(PROGRAM) $(OBJS) $(LIBS)
+
+clean:
+       rm -f $(BUILT_SRC)
+       rm -f $(OBJS)
+       rm -f $(PROGRAM)
+
+install-desktop-file:
+       mkdir -p ~/.local/share/applications
+       sed -e "s#@bindir@#$$PWD#" ../step1/exampleapp.desktop > 
~/.local/share/applications/$(PROGRAM).desktop
+       mkdir -p ~/.local/share/icons/hicolor/48x48/apps
+       cp ../step1/exampleapp.png ~/.local/share/icons/hicolor/48x48/apps
diff --git a/examples/book/buildapp/step2/exampleapp.gresource.xml 
b/examples/book/buildapp/step2/exampleapp.gresource.xml
new file mode 100644
index 0000000..7e7387d
--- /dev/null
+++ b/examples/book/buildapp/step2/exampleapp.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gtkmm/exampleapp">
+    <file preprocess="xml-stripblanks">window.ui</file>
+  </gresource>
+</gresources>
diff --git a/examples/book/buildapp/step2/exampleapplication.cc 
b/examples/book/buildapp/step2/exampleapplication.cc
new file mode 100644
index 0000000..63a5eec
--- /dev/null
+++ b/examples/book/buildapp/step2/exampleapplication.cc
@@ -0,0 +1,105 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "exampleapplication.h"
+#include "exampleappwindow.h"
+#include <iostream>
+#include <exception>
+
+ExampleApplication::ExampleApplication()
+: Gtk::Application("org.gtkmm.examples.application", Gio::APPLICATION_HANDLES_OPEN)
+{
+}
+
+Glib::RefPtr<ExampleApplication> ExampleApplication::create()
+{
+  return Glib::RefPtr<ExampleApplication>(new ExampleApplication());
+}
+
+ExampleAppWindow* ExampleApplication::create_appwindow()
+{
+  auto appwindow = ExampleAppWindow::create();
+
+  // Make sure that the application runs for as long this window is still open.
+  add_window(*appwindow);
+
+  // Gtk::Application::add_window() connects a signal handler to the window's
+  // signal_hide(). That handler removes the window from the application.
+  // If it's the last window to be removed, the application stops running.
+  // Gtk::Window::set_application() does not connect a signal handler, but is
+  // otherwise equivalent to Gtk::Application::add_window().
+
+  // Delete the window when it is hidden.
+  appwindow->signal_hide().connect(sigc::bind<Gtk::Window*>(sigc::mem_fun(*this,
+    &ExampleApplication::on_hide_window), appwindow));
+
+  return appwindow;
+}
+
+void ExampleApplication::on_activate()
+{
+  try
+  {
+    // The application has been started, so let's show a window.
+    auto appwindow = create_appwindow();
+    appwindow->present();
+  }
+  // If create_appwindow() throws an exception (perhaps from Gtk::Builder),
+  // no window has been created, no window has been added to the application,
+  // and therefore the application will stop running.
+  catch (const Glib::Error& ex)
+  {
+    std::cerr << "ExampleApplication::on_activate(): " << ex.what() << std::endl;
+  }
+  catch (const std::exception& ex)
+  {
+    std::cerr << "ExampleApplication::on_activate(): " << ex.what() << std::endl;
+  }
+}
+
+void ExampleApplication::on_open(const Gio::Application::type_vec_files& files,
+  const Glib::ustring& /* hint */)
+{
+  // The application has been asked to open some files,
+  // so let's open a new view for each one.
+  ExampleAppWindow* appwindow = nullptr;
+  auto windows = get_windows();
+  if (windows.size() > 0)
+    appwindow = dynamic_cast<ExampleAppWindow*>(windows[0]);
+
+  try
+  {
+    if (!appwindow)
+      appwindow = create_appwindow();
+
+    for (const auto& file : files)
+      appwindow->open_file_view(file);
+
+    appwindow->present();
+  }
+  catch (const Glib::Error& ex)
+  {
+    std::cerr << "ExampleApplication::on_open(): " << ex.what() << std::endl;
+  }
+  catch (const std::exception& ex)
+  {
+    std::cerr << "ExampleApplication::on_open(): " << ex.what() << std::endl;
+  }
+}
+
+void ExampleApplication::on_hide_window(Gtk::Window* window)
+{
+  delete window;
+}
diff --git a/examples/book/buildapp/step2/exampleapplication.h 
b/examples/book/buildapp/step2/exampleapplication.h
new file mode 100644
index 0000000..c8c7a9a
--- /dev/null
+++ b/examples/book/buildapp/step2/exampleapplication.h
@@ -0,0 +1,2 @@
+#include "../step1/exampleapplication.h"
+// Equal to the corresponding file in step1
diff --git a/examples/book/buildapp/step2/exampleappwindow.cc 
b/examples/book/buildapp/step2/exampleappwindow.cc
new file mode 100644
index 0000000..ac228d5
--- /dev/null
+++ b/examples/book/buildapp/step2/exampleappwindow.cc
@@ -0,0 +1,42 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "exampleappwindow.h"
+#include <stdexcept>
+
+ExampleAppWindow::ExampleAppWindow(BaseObjectType* cobject,
+  const Glib::RefPtr<Gtk::Builder>& refBuilder)
+: Gtk::ApplicationWindow(cobject),
+  m_refBuilder(refBuilder)
+{
+}
+
+//static
+ExampleAppWindow* ExampleAppWindow::create()
+{
+  // Load the Builder file and instantiate its widgets.
+  auto refBuilder = Gtk::Builder::create_from_resource("/org/gtkmm/exampleapp/window.ui");
+
+  ExampleAppWindow* window = nullptr;
+  refBuilder->get_widget_derived("app_window", window);
+  if (!window)
+    throw std::runtime_error("No \"app_window\" object in window.ui");
+
+  return window;
+}
+
+void ExampleAppWindow::open_file_view(const Glib::RefPtr<Gio::File>& /* file */)
+{
+}
diff --git a/examples/book/buildapp/step2/exampleappwindow.h b/examples/book/buildapp/step2/exampleappwindow.h
new file mode 100644
index 0000000..efe47c6
--- /dev/null
+++ b/examples/book/buildapp/step2/exampleappwindow.h
@@ -0,0 +1,35 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTKMM_EXAMPLEAPPWINDOW_H_
+#define GTKMM_EXAMPLEAPPWINDOW_H_
+
+#include <gtkmm.h>
+
+class ExampleAppWindow : public Gtk::ApplicationWindow
+{
+public:
+  ExampleAppWindow(BaseObjectType* cobject,
+    const Glib::RefPtr<Gtk::Builder>& refBuilder);
+
+  static ExampleAppWindow* create();
+
+  void open_file_view(const Glib::RefPtr<Gio::File>& file);
+
+protected:
+  Glib::RefPtr<Gtk::Builder> m_refBuilder;
+};
+
+#endif /* GTKMM_EXAMPLEAPPWINDOW_H */
diff --git a/examples/book/buildapp/step2/main.cc b/examples/book/buildapp/step2/main.cc
new file mode 100644
index 0000000..e55616e
--- /dev/null
+++ b/examples/book/buildapp/step2/main.cc
@@ -0,0 +1,2 @@
+#include "../step1/main.cc"
+// Equal to the corresponding file in step1
diff --git a/examples/book/buildapp/step2/window.ui b/examples/book/buildapp/step2/window.ui
new file mode 100644
index 0000000..5f8e5ba
--- /dev/null
+++ b/examples/book/buildapp/step2/window.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <object class="GtkApplicationWindow" id="app_window">
+    <property name="title" translatable="yes">Example Application</property>
+    <property name="default-width">600</property>
+    <property name="default-height">400</property>
+    <child>
+      <object class="GtkBox" id="content_box">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkHeaderBar" id="header">
+            <property name="visible">True</property>
+            <child type="title">
+              <object class="GtkStackSwitcher" id="tabs">
+                <property name="visible">True</property>
+                <property name="stack">stack</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="visible">True</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/examples/book/buildapp/step3/Makefile.example b/examples/book/buildapp/step3/Makefile.example
new file mode 100644
index 0000000..ca4ef61
--- /dev/null
+++ b/examples/book/buildapp/step3/Makefile.example
@@ -0,0 +1,2 @@
+include ../step2/Makefile.example
+# Equal to the corresponding file in step2
diff --git a/examples/book/buildapp/step3/exampleapp.gresource.xml 
b/examples/book/buildapp/step3/exampleapp.gresource.xml
new file mode 100644
index 0000000..7e7387d
--- /dev/null
+++ b/examples/book/buildapp/step3/exampleapp.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gtkmm/exampleapp">
+    <file preprocess="xml-stripblanks">window.ui</file>
+  </gresource>
+</gresources>
diff --git a/examples/book/buildapp/step3/exampleapplication.cc 
b/examples/book/buildapp/step3/exampleapplication.cc
new file mode 100644
index 0000000..8d1fd96
--- /dev/null
+++ b/examples/book/buildapp/step3/exampleapplication.cc
@@ -0,0 +1,2 @@
+#include "../step2/exampleapplication.cc"
+// Equal to the corresponding file in step2
diff --git a/examples/book/buildapp/step3/exampleapplication.h 
b/examples/book/buildapp/step3/exampleapplication.h
new file mode 100644
index 0000000..c8c7a9a
--- /dev/null
+++ b/examples/book/buildapp/step3/exampleapplication.h
@@ -0,0 +1,2 @@
+#include "../step1/exampleapplication.h"
+// Equal to the corresponding file in step1
diff --git a/examples/book/buildapp/step3/exampleappwindow.cc 
b/examples/book/buildapp/step3/exampleappwindow.cc
new file mode 100644
index 0000000..cab4477
--- /dev/null
+++ b/examples/book/buildapp/step3/exampleappwindow.cc
@@ -0,0 +1,74 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "exampleappwindow.h"
+#include <iostream>
+#include <stdexcept>
+
+ExampleAppWindow::ExampleAppWindow(BaseObjectType* cobject,
+  const Glib::RefPtr<Gtk::Builder>& refBuilder)
+: Gtk::ApplicationWindow(cobject),
+  m_refBuilder(refBuilder),
+  m_stack(nullptr)
+{
+  m_refBuilder->get_widget("stack", m_stack);
+  if (!m_stack)
+    throw std::runtime_error("No \"stack\" object in window.ui");
+}
+
+//static
+ExampleAppWindow* ExampleAppWindow::create()
+{
+  // Load the Builder file and instantiate its widgets.
+  auto refBuilder = Gtk::Builder::create_from_resource("/org/gtkmm/exampleapp/window.ui");
+
+  ExampleAppWindow* window = nullptr;
+  refBuilder->get_widget_derived("app_window", window);
+  if (!window)
+    throw std::runtime_error("No \"app_window\" object in window.ui");
+
+  return window;
+}
+
+void ExampleAppWindow::open_file_view(const Glib::RefPtr<Gio::File>& file)
+{
+  const auto basename = file->get_basename();
+
+  auto scrolled = Gtk::manage(new Gtk::ScrolledWindow());
+  scrolled->set_hexpand(true);
+  scrolled->set_vexpand(true);
+  scrolled->show();
+  auto view = Gtk::manage(new Gtk::TextView());
+  view->set_editable(false);
+  view->set_cursor_visible(false);
+  view->show();
+  scrolled->add(*view);
+  m_stack->add(*scrolled, basename, basename);
+
+  try
+  {
+    char* contents = nullptr;
+    gsize length = 0;
+    
+    file->load_contents(contents, length);
+    view->get_buffer()->set_text(contents, contents+length);
+    g_free(contents);
+  }
+  catch (const Glib::Error& ex)
+  {
+    std::cout << "ExampleAppWindow::open_file_view(\"" << file->get_parse_name()
+      << "\"):\n  " << ex.what() << std::endl;
+  }
+}
diff --git a/examples/book/buildapp/step3/exampleappwindow.h b/examples/book/buildapp/step3/exampleappwindow.h
new file mode 100644
index 0000000..67f5511
--- /dev/null
+++ b/examples/book/buildapp/step3/exampleappwindow.h
@@ -0,0 +1,36 @@
+/* gtkmm example Copyright (C) 2016 gtkmm development team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTKMM_EXAMPLEAPPWINDOW_H_
+#define GTKMM_EXAMPLEAPPWINDOW_H_
+
+#include <gtkmm.h>
+
+class ExampleAppWindow : public Gtk::ApplicationWindow
+{
+public:
+  ExampleAppWindow(BaseObjectType* cobject,
+    const Glib::RefPtr<Gtk::Builder>& refBuilder);
+
+  static ExampleAppWindow* create();
+
+  void open_file_view(const Glib::RefPtr<Gio::File>& file);
+
+protected:
+  Glib::RefPtr<Gtk::Builder> m_refBuilder;
+  Gtk::Stack* m_stack;
+};
+
+#endif /* GTKMM_EXAMPLEAPPWINDOW_H */
diff --git a/examples/book/buildapp/step3/main.cc b/examples/book/buildapp/step3/main.cc
new file mode 100644
index 0000000..e55616e
--- /dev/null
+++ b/examples/book/buildapp/step3/main.cc
@@ -0,0 +1,2 @@
+#include "../step1/main.cc"
+// Equal to the corresponding file in step1
diff --git a/examples/book/buildapp/step3/window.ui b/examples/book/buildapp/step3/window.ui
new file mode 100644
index 0000000..5f8e5ba
--- /dev/null
+++ b/examples/book/buildapp/step3/window.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <object class="GtkApplicationWindow" id="app_window">
+    <property name="title" translatable="yes">Example Application</property>
+    <property name="default-width">600</property>
+    <property name="default-height">400</property>
+    <child>
+      <object class="GtkBox" id="content_box">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkHeaderBar" id="header">
+            <property name="visible">True</property>
+            <child type="title">
+              <object class="GtkStackSwitcher" id="tabs">
+                <property name="visible">True</property>
+                <property name="stack">stack</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="visible">True</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]