[gtk/docs-gtk-org] Add the Getting Started guide for GTK3



commit 5f592c4e0331e688cc55056b4529f7ad1e1ffd4a
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Fri Mar 11 22:57:52 2022 +0000

    Add the Getting Started guide for GTK3
    
    Port it from the original DocBook, and fix the odd bit of
    text and typos.

 gtk3/gtk/builder.png               |  Bin 0 -> 6241 bytes
 gtk3/gtk/drawing.png               |  Bin 0 -> 3734 bytes
 gtk3/gtk/exampleapp.png            |  Bin 0 -> 4117 bytes
 gtk3/gtk/getting-started-app1.png  |  Bin 0 -> 3004 bytes
 gtk3/gtk/getting-started-app10.png |  Bin 0 -> 167805 bytes
 gtk3/gtk/getting-started-app2.png  |  Bin 0 -> 5718 bytes
 gtk3/gtk/getting-started-app3.png  |  Bin 0 -> 37590 bytes
 gtk3/gtk/getting-started-app4.png  |  Bin 0 -> 211105 bytes
 gtk3/gtk/getting-started-app6.png  |  Bin 0 -> 223488 bytes
 gtk3/gtk/getting-started-app7.png  |  Bin 0 -> 38964 bytes
 gtk3/gtk/getting-started-app8.png  |  Bin 0 -> 58744 bytes
 gtk3/gtk/getting-started-app9.png  |  Bin 0 -> 46932 bytes
 gtk3/gtk/getting_started.md        | 1947 ++++++++++++++++++++++++++++++++++++
 gtk3/gtk/grid-packing.png          |  Bin 0 -> 6881 bytes
 gtk3/gtk/gtk3.toml.in              |   17 +
 gtk3/gtk/hellow-world.png          |  Bin 0 -> 6341 bytes
 gtk3/gtk/window-default.png        |  Bin 0 -> 4199 bytes
 17 files changed, 1964 insertions(+)
---
diff --git a/gtk3/gtk/builder.png b/gtk3/gtk/builder.png
new file mode 100644
index 0000000000..7f6dbde18d
Binary files /dev/null and b/gtk3/gtk/builder.png differ
diff --git a/gtk3/gtk/drawing.png b/gtk3/gtk/drawing.png
new file mode 100644
index 0000000000..298a3f7e27
Binary files /dev/null and b/gtk3/gtk/drawing.png differ
diff --git a/gtk3/gtk/exampleapp.png b/gtk3/gtk/exampleapp.png
new file mode 100644
index 0000000000..8beb54eae4
Binary files /dev/null and b/gtk3/gtk/exampleapp.png differ
diff --git a/gtk3/gtk/getting-started-app1.png b/gtk3/gtk/getting-started-app1.png
new file mode 100644
index 0000000000..bf33a44ad3
Binary files /dev/null and b/gtk3/gtk/getting-started-app1.png differ
diff --git a/gtk3/gtk/getting-started-app10.png b/gtk3/gtk/getting-started-app10.png
new file mode 100644
index 0000000000..ba52b19459
Binary files /dev/null and b/gtk3/gtk/getting-started-app10.png differ
diff --git a/gtk3/gtk/getting-started-app2.png b/gtk3/gtk/getting-started-app2.png
new file mode 100644
index 0000000000..ca4c0e1e4c
Binary files /dev/null and b/gtk3/gtk/getting-started-app2.png differ
diff --git a/gtk3/gtk/getting-started-app3.png b/gtk3/gtk/getting-started-app3.png
new file mode 100644
index 0000000000..164ae62c80
Binary files /dev/null and b/gtk3/gtk/getting-started-app3.png differ
diff --git a/gtk3/gtk/getting-started-app4.png b/gtk3/gtk/getting-started-app4.png
new file mode 100644
index 0000000000..99d05913c2
Binary files /dev/null and b/gtk3/gtk/getting-started-app4.png differ
diff --git a/gtk3/gtk/getting-started-app6.png b/gtk3/gtk/getting-started-app6.png
new file mode 100644
index 0000000000..0e89713af5
Binary files /dev/null and b/gtk3/gtk/getting-started-app6.png differ
diff --git a/gtk3/gtk/getting-started-app7.png b/gtk3/gtk/getting-started-app7.png
new file mode 100644
index 0000000000..1490a1b3dc
Binary files /dev/null and b/gtk3/gtk/getting-started-app7.png differ
diff --git a/gtk3/gtk/getting-started-app8.png b/gtk3/gtk/getting-started-app8.png
new file mode 100644
index 0000000000..00ff9b5554
Binary files /dev/null and b/gtk3/gtk/getting-started-app8.png differ
diff --git a/gtk3/gtk/getting-started-app9.png b/gtk3/gtk/getting-started-app9.png
new file mode 100644
index 0000000000..472da3e081
Binary files /dev/null and b/gtk3/gtk/getting-started-app9.png differ
diff --git a/gtk3/gtk/getting_started.md b/gtk3/gtk/getting_started.md
new file mode 100644
index 0000000000..02b8e7a196
--- /dev/null
+++ b/gtk3/gtk/getting_started.md
@@ -0,0 +1,1947 @@
+Title: Getting Started with GTK
+
+GTK is a widget toolkit. Each user interface created by GTK consists of
+widgets. This is implemented in C using GObject, an object-oriented
+framework for C. Widgets are organized in a hierachy. The window widget is
+the main container. The user interface is then built by adding buttons,
+drop-down menus, input fields, and other widgets to the window. If you are
+creating complex user interfaces it is recommended to use GtkBuilder and its
+GTK-specific markup description language, instead of assembling the
+interface manually. You can also use a visual user interface editor, like
+Glade.
+
+GTK is event-driven. The toolkit listens for events such as a click on a
+button, and passes the event to your application.
+
+This chapter contains some tutorial information to get you started with GTK
+programming. It assumes that you have GTK, its dependencies and a C compiler
+installed and ready to use. If you need to build GTK itself first, refer to
+the Compiling the GTK libraries section in this reference.
+
+## Basics
+
+To begin our introduction to GTK, we'll start with a simple signal-based Gtk
+application. This program will create an empty 200×200 pixel window.
+
+Save the following code as a file named `example-0.c`:
+
+```c
+#include <gtk/gtk.h>
+
+static void
+activate (GtkApplication* app,
+          gpointer        user_data)
+{
+  GtkWidget *window;
+
+  window = gtk_application_window_new (app);
+  gtk_window_set_title (GTK_WINDOW (window), "Window");
+  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
+  gtk_widget_show_all (window);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  GtkApplication *app;
+  int status;
+
+  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
+  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+  status = g_application_run (G_APPLICATION (app), argc, argv);
+  g_object_unref (app);
+
+  return status;
+}
+```
+
+You can compile the program above with GCC using:
+
+```
+gcc `pkg-config --cflags gtk+-3.0` -o example-0 example-0.c `pkg-config --libs gtk+-3.0`
+```
+
+![](window-default.png)
+
+For more information on how to compile a GTK application, please refer to
+the [Compiling GTK Applications](compiling.html) section.
+
+All GTK applications must include the `gtk/gtk.h` header, which declares
+functions, types and macros required by GTK applications. Even if GTK
+installs multiple header files, only the top level `gtk/gtk.h` header can be
+directly included by third party code. The compiler will abort with an error
+if any other header is directly included.
+
+In a GTK application, the purpose of the `main()` function is to create a
+[`class@Gtk.Application`] object and run it. In this example a
+`GtkApplication` pointer named `app` is called and then initialized using
+[ctor Gtk Application new].
+
+When creating a `GtkApplication` you need to pick an application identifier
+(a name) and input to `gtk_application_new()` as parameter. For this example
+`org.gtk.example` is used but for choosing an identifier for your
+application see [the corresponding tutorial on the GNOME developer
+documentation website](https://developer.gnome.org/documentation/tutorials/application-id.html).
+Lastly `gtk_application_new()` takes a [flags@Gio.ApplicationFlags] as input
+for your application, if your application would have special needs.
+
+Next the [signal@Gio.Application::activate] signal is connected to the
+`activate()` function defined above the `main()` function. The `activate`
+signal will be sent when your application is launched with
+[method Gio Application run] on the line below. The `g_application_run()`
+function also takes as arguments the pointers to the command line arguments
+counter and string array; this allows GTK to parse specific command line
+arguments that control the behavior of GTK itself.
+
+Within `g_application_run()`, the `activate` signal is emitted and we then
+proceed into the `activate()` function of the application. Inside the
+`activate()` function we want to construct our GTK window, so that a window
+is shown when the application is launched. The call to
+[ctor Gtk ApplicationWindow new] will create a new [class@Gtk.Window] and
+store it inside the `window` pointer. The window will have a frame, a title
+bar, and window controls depending on the platform.
+
+A window title is set using [`method@Gtk.Window.set_title`]. This function
+takes a `GtkWindow` pointer and a string as input. As our window pointer is
+a `GtkWidget` pointer, we need to cast it to `GtkWindow`. But instead of
+casting `window` via the typical C cast `(GtkWindow *)`, window can be cast
+using the macro `GTK_WINDOW()`. `GTK_WINDOW()` will check if the pointer is
+an instance of the `GtkWindow` class, before casting, and emit a warning if
+the check fails. More information about this convention can be found in [the
+GObject documentation](https://docs.gtk.org/gobject/concepts.html#conventions).
+
+Finally the window size is set using [`method@Gtk.Window.set_default_size`]
+and the window is then shown by GTK via [`method@Gtk.Widget.show_all`].
+
+When you exit the window, by for example pressing the X, the
+`g_application_run()` function returns with a number which is saved inside
+an integer named `status`. Afterwards, the `GtkApplication` object is freed
+from memory with [method@GObject.Object.unref]. Finally the status integer
+is returned and the GTK application exits.
+
+While the program is running, GTK is receiving events. These are typically
+input events caused by the user interacting with your program, but also
+things like messages from the window manager or other applications. GTK
+processes these and as a result, signals may be emitted on your widgets.
+Connecting handlers for these signals is how you normally make your program
+do something in response to user input.
+
+The following example is slightly more complex, and tries to showcase some
+of the capabilities of GTK.
+
+In the long tradition of programming languages and libraries, it is called
+*Hello, World*.
+
+Save the following code as a file named `example-1.c`:
+
+```c
+#include <gtk/gtk.h>
+
+static void
+print_hello (GtkWidget *widget,
+             gpointer   data)
+{
+  g_print ("Hello World\n");
+}
+
+static void
+activate (GtkApplication *app,
+          gpointer        user_data)
+{
+  GtkWidget *window;
+  GtkWidget *button;
+  GtkWidget *button_box;
+
+  window = gtk_application_window_new (app);
+  gtk_window_set_title (GTK_WINDOW (window), "Window");
+  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
+
+  button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_container_add (GTK_CONTAINER (window), button_box);
+
+  button = gtk_button_new_with_label ("Hello World");
+  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
+  gtk_container_add (GTK_CONTAINER (button_box), button);
+
+  gtk_widget_show_all (window);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  GtkApplication *app;
+  int status;
+
+  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
+  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+  status = g_application_run (G_APPLICATION (app), argc, argv);
+  g_object_unref (app);
+
+  return status;
+}
+```
+
+You can compile the program above with GCC using:
+
+```
+gcc `pkg-config --cflags gtk+-3.0` -o example-1 example-1.c `pkg-config --libs gtk+-3.0`
+```
+
+![](hello-world.png)
+
+As seen above, `example-1.c` builds further upon `example-0.c` by adding a
+button to our window, with the label "Hello World". Two new `GtkWidget`
+pointers are declared to accomplish this, `button` and `button_box`. The
+`button_box` variable is created to store a [class@Gtk.ButtonBox] which is
+GTK's way of controlling the size and layout of buttons. The `GtkButtonBox`
+is created and assigned to [`ctor Gtk ButtonBox new`] which takes a
+[enum@Gtk.Orientation] enumeration as parameter. The buttons which this box
+will contain can either be stored horizontally or vertically but this does
+not matter in this particular case as we are dealing with only one button.
+After initializing `button_box` with horizontal orientation, the code adds
+the `button_box` widget to the window widget using
+[method Gtk Container add].
+
+Next the `button` variable is initialized in similar manner.
+[`ctor@Gtk.Button.new_with_label`] is called which returns a
+[class@Gtk.Button] to be stored inside `button`. Afterwards `button` is
+added to our `button_box`. Using [`func@GObject.signal_connect`] the button
+is connected to a function in our app called `print_hello()`, so that when
+the button is clicked, GTK will call this function. As the `print_hello()`
+function does not use any data as input, `NULL` is passed to it.
+`print_hello()` calls `g_print()` with the string "Hello World" which will
+print Hello World in a terminal if the GTK application was started from one.
+
+After connecting `print_hello()`, another signal is connected to the
+`clicked` signal of the button using
+[`func@GObject.signal_connect_swapped`]. This functions is similar to
+`g_signal_connect()` with the difference lying in how the callback function
+is treated. `g_signal_connect_swapped()` allows you to specify what the
+callback function should take as parameter by letting you pass it as data.
+In this case the function being called back is `gtk_widget_destroy()` and
+the window pointer is passed to it. This has the effect that when the button
+is clicked, the whole GTK window is destroyed. In contrast, if a normal
+`g_signal_connect()` were used to connect the `clicked` signal with
+`gtk_widget_destroy()`, then the button itself would have been destroyed,
+not the window.
+
+The rest of the code in `example-1.c` is identical to `example-0.c`.
+
+The next section will elaborate further on how to add several widgets to
+your GTK application.
+
+## Packing
+
+When creating an application, you'll want to put more than one widget inside
+a window. When you want to put more than one widget into a window, it
+becomes important to control how each widget is positioned and sized. This
+is where packing comes in.
+
+GTK comes with a large variety of layout containers whose purpose it is to
+control the layout of the child widgets that are added to them.
+
+The following example shows how the [class Gtk Grid] container lets you
+arrange several buttons. 
+
+Save the following code as a file named `example-2.c`:
+
+```c
+#include <gtk/gtk.h>
+
+static void
+print_hello (GtkWidget *widget,
+             gpointer   data)
+{
+  g_print ("Hello World\n");
+}
+
+static void
+activate (GtkApplication *app,
+          gpointer        user_data)
+{
+  GtkWidget *window;
+  GtkWidget *grid;
+  GtkWidget *button;
+
+  /* create a new window, and set its title */
+  window = gtk_application_window_new (app);
+  gtk_window_set_title (GTK_WINDOW (window), "Window");
+  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+  /* Here we construct the container that is going pack our buttons */
+  grid = gtk_grid_new ();
+
+  /* Pack the container in the window */
+  gtk_container_add (GTK_CONTAINER (window), grid);
+
+  button = gtk_button_new_with_label ("Button 1");
+  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
+
+  /* Place the first button in the grid cell (0, 0), and make it fill
+   * just 1 cell horizontally and vertically (ie no spanning)
+   */
+  gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
+
+  button = gtk_button_new_with_label ("Button 2");
+  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
+
+  /* Place the second button in the grid cell (1, 0), and make it fill
+   * just 1 cell horizontally and vertically (ie no spanning)
+   */
+  gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
+
+  button = gtk_button_new_with_label ("Quit");
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
+
+  /* Place the Quit button in the grid cell (0, 1), and make it
+   * span 2 columns.
+   */
+  gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 2, 1);
+
+  /* Now that we are done packing our widgets, we show them all
+   * in one go, by calling gtk_widget_show_all() on the window.
+   * This call recursively calls gtk_widget_show() on all widgets
+   * that are contained in the window, directly or indirectly.
+   */
+  gtk_widget_show_all (window);
+
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  GtkApplication *app;
+  int status;
+
+  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
+  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+  status = g_application_run (G_APPLICATION (app), argc, argv);
+  g_object_unref (app);
+
+  return status;
+}
+```
+
+You can compile the program above with GCC using:
+
+```
+gcc `pkg-config --cflags gtk+-3.0` -o example-2 example-2.c `pkg-config --libs gtk+-3.0`
+```
+
+![](grid-packing.png)
+
+## Building user interfaces
+
+When constructing a more complicated user interface, with dozens or hundreds
+of widgets, doing all the setup work in C code is cumbersome, and making
+changes becomes next to impossible.
+
+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 [class@Gtk.Builder] class.
+
+Save the following XML as a file named `builder.ui`:
+
+```xml
+<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>
+```
+
+Save the following code as a file named `example-3.c`:
+
+```c
+#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;
+  GError *error = NULL;
+
+  gtk_init (&argc, &argv);
+
+  /* Construct a GtkBuilder instance and load our UI description */
+  builder = gtk_builder_new ();
+  if (gtk_builder_add_from_file (builder, "builder.ui", &error) == 0)
+    {
+      g_printerr ("Error loading file: %s\n", error->message);
+      g_clear_error (&error);
+      return 1;
+    }
+
+  /* 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;
+}
+```
+
+You can compile the program above with GCC using:
+
+```
+gcc `pkg-config --cflags gtk+-3.0` -o example-3 example-3.c `pkg-config --libs gtk+-3.0`
+```
+
+![](builder.png)
+
+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 [`method@Gtk.Builder.get_object`] and returns a
+`GObject` instead of a `GtkWidget`.
+
+`GtkBuilder` will load the file from the current directory; for installed
+applications, you can pass a full path to
+[`method@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 `/usr/share/appname`, but it will require
+installing the file separately from your binary.
+
+It is also possible to embed the UI description in the source code as a
+string and use [`method@Gtk.Builder.add_from_string`] to load it; 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 Glade can load
+the file and allow you to create and modify your UI by point-and-click.
+
+It is possible to have the UI description as a separate file during
+development, and then embed it in the compiled executable at build time by
+using [struct@Gio.Resource].
+
+## Building applications
+
+A GTK application consists of a number of files:
+
+A binary:
+  The main executable of your application; it typically is installed in the
+  binaries directory, e.g. `/usr/bin`.
+
+A desktop file:
+  The desktop file provides important information about the application to the
+  desktop shell, such as its name, icon, D-Bus name, command line to launch it,
+  etc. It is typically installed in `/usr/share/applications`.
+
+An icon:
+  The icon gets installed in the "hicolor" icon theme directory, e.g.
+  `/usr/share/icons/hicolor/48x48/apps`, where it will be found regardless of
+  the current icon theme.
+
+A settings schema:
+  If the application uses [class@Gio.Settings], it will install its schema in
+  `/usr/share/glib-2.0/schemas` and run `glib-compile-schemas` to ensure
+  that the schema can be used.
+
+Other resources:
+  Other files, such as `GtkBuilder` UI definition 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 `/usr/share`.
+
+GTK includes application support that is built on top of `GApplication`. In
+this tutorial we'll build a simple application by starting from scratch,
+adding more and more pieces over time. Along the way, we'll learn about
+[class@Gtk.Application], templates, resources, application menus, settings,
+[class@Gtk.HeaderBar], [class@Gtk.Stack], [class@Gtk.SearchBar],
+[class@Gtk.ListBox], and more.
+
+The full, buildable sources for these examples can be found in the
+`examples` directory of the GTK source distribution, or online in the GTK
+Git repository. You can build each example separately by using make with the
+`Makefile.example` file. For more information, see the `README` included in
+the `examples` directory.
+
+### A trivial application
+
+When using `GtkApplication`, the `main()` function can be very simple. We
+just call `g_application_run()` and give it an instance of our application
+class.
+
+```c
+#include <gtk/gtk.h>
+
+#include "exampleapp.h"
+
+int
+main (int argc, char *argv[])
+{
+  return g_application_run (G_APPLICATION (example_app_new ()), argc, argv);
+}
+```
+
+All the application logic is in the application class, which is a subclass
+of `GtkApplication`. 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.
+
+To handle these two cases, we override the `activate()` virtual function,
+which gets called when the application is launched without commandline
+arguments; and the `open()` virtual function, which gets called when the
+application is launched with command line arguments.
+
+To learn more about `GApplication` entry points, consult the GIO
+documentation.
+
+```c
+#include <gtk/gtk.h>
+
+#include "exampleapp.h"
+#include "exampleappwin.h"
+
+struct _ExampleApp
+{
+  GtkApplication parent;
+};
+
+G_DEFINE_TYPE(ExampleApp, example_app, GTK_TYPE_APPLICATION);
+
+static void
+example_app_init (ExampleApp *app)
+{
+}
+
+static void
+example_app_activate (GApplication *app)
+{
+  ExampleAppWindow *win;
+
+  win = example_app_window_new (EXAMPLE_APP (app));
+  gtk_window_present (GTK_WINDOW (win));
+}
+
+static void
+example_app_open (GApplication  *app,
+                  GFile        **files,
+                  gint           n_files,
+                  const gchar   *hint)
+{
+  GList *windows;
+  ExampleAppWindow *win;
+  int i;
+
+  windows = gtk_application_get_windows (GTK_APPLICATION (app));
+  if (windows)
+    win = EXAMPLE_APP_WINDOW (windows->data);
+  else
+    win = example_app_window_new (EXAMPLE_APP (app));
+
+  for (i = 0; i < n_files; i++)
+    example_app_window_open (win, files[i]);
+
+  gtk_window_present (GTK_WINDOW (win));
+}
+
+static void
+example_app_class_init (ExampleAppClass *class)
+{
+  G_APPLICATION_CLASS (class)->activate = example_app_activate;
+  G_APPLICATION_CLASS (class)->open = example_app_open;
+}
+
+ExampleApp *
+example_app_new (void)
+{
+  return g_object_new (EXAMPLE_APP_TYPE,
+                       "application-id", "org.gtk.exampleapp",
+                       "flags", G_APPLICATION_HANDLES_OPEN,
+                       NULL);
+}
+```
+
+Another important class that is part of the application support in GTK is
+`GtkApplicationWindow`. It is typically subclassed as well. Our subclass
+does not do anything yet, so we will just get an empty window.
+
+```c
+#include <gtk/gtk.h>
+
+#include "exampleapp.h"
+#include "exampleappwin.h"
+
+struct _ExampleAppWindow
+{
+  GtkApplicationWindow parent;
+};
+
+G_DEFINE_TYPE(ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW);
+
+static void
+example_app_window_init (ExampleAppWindow *app)
+{
+}
+
+static void
+example_app_window_class_init (ExampleAppWindowClass *class)
+{
+}
+
+ExampleAppWindow *
+example_app_window_new (ExampleApp *app)
+{
+  return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
+}
+
+void
+example_app_window_open (ExampleAppWindow *win,
+                         GFile            *file)
+{
+}
+```
+
+As part of the initial setup of our application, we also create an icon and
+a desktop file:
+
+![](exampleapp.png)
+
+```
+[Desktop Entry]
+Type=Application
+Name=Example
+Icon=exampleapp
+StartupNotify=true
+Exec=@bindir@/exampleapp
+```
+
+Note that `@bindir@` needs to be replaced with the actual path to the binary
+before this desktop file can be used.
+
+Here is what we've achieved so far:
+
+![](getting-started-app1.png)
+
+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.
+
+### Populating the window
+
+In this step, we use a GtkBuilder template to associate a GtkBuilder ui file
+with our application window class.
+
+Our simple ui file puts a GtkHeaderBar on top of a GtkStack widget. The
+header bar contains a GtkStackSwitcher, which is a standalone widget to show
+a row of 'tabs' for the pages of a GtkStack.
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
+    <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>
+  </template>
+</interface>
+```
+
+To make use of this file in our application, we revisit our
+`GtkApplicationWindow` subclass, and call
+`gtk_widget_class_set_template_from_resource()` from the class init function
+to set the ui file as template for this class. We also add a call to
+`gtk_widget_init_template()` in the instance init function to instantiate the
+template for each instance of our class.
+
+```c
+// ...
+
+static void
+example_app_window_init (ExampleAppWindow *win)
+{
+  gtk_widget_init_template (GTK_WIDGET (win));
+}
+
+static void
+example_app_window_class_init (ExampleAppWindowClass *class)
+{
+  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
+                                               "/org/gtk/exampleapp/window.ui");
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application2/exampleappwin.c))
+
+You may have noticed that we used the `_from_resource()` variant of the
+function that sets a template. Now we need to use GLib's resource
+functionality to include the ui file in the binary. This is commonly done by
+listing all resources in a `.gresource.xml` file, such as this:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gtk/exampleapp">
+    <file preprocess="xml-stripblanks">window.ui</file>
+  </gresource>
+</gresources>
+```
+
+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 `glib-compile-resources` utility:
+
+    glib-compile-resources exampleapp.gresource.xml --target=resources.c --generate-source
+
+Our application now looks like this:
+
+![](getting-started-app2.png)
+
+### Opening files
+
+In this step, we make our application show the content of all the files that
+it is given on the commandline.
+
+To this end, we add a private struct to our application window subclass and
+keep a reference to the `GtkStack` there. The
+`gtk_widget_class_bind_template_child_private()` function arranges things so
+that after instantiating the template, the stack member of the private
+struct will point to the widget of the same name from the template.
+
+```c
+// ...
+
+struct _ExampleAppWindowPrivate
+{
+  GtkWidget *stack;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
+
+...
+
+static void
+example_app_window_class_init (ExampleAppWindowClass *class)
+{
+  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
+                                               "/org/gtk/exampleapp/window.ui");
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class),
+                                                ExampleAppWindow,
+                                               stack);
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application3/exampleappwin.c))
+
+Now we revisit the `example_app_window_open()` function that is called for
+each commandline argument, and construct a `GtkTextView` that we then add as a
+page to the stack:
+
+```c
+// ...
+
+void
+example_app_window_open (ExampleAppWindow *win,
+                         GFile            *file)
+{
+  ExampleAppWindowPrivate *priv;
+  gchar *basename;
+  GtkWidget *scrolled, *view;
+  gchar *contents;
+  gsize length;
+
+  priv = example_app_window_get_instance_private (win);
+  basename = g_file_get_basename (file);
+
+  scrolled = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_show (scrolled);
+  gtk_widget_set_hexpand (scrolled, TRUE);
+  gtk_widget_set_vexpand (scrolled, TRUE);
+  view = gtk_text_view_new ();
+  gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
+  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
+  gtk_widget_show (view);
+  gtk_container_add (GTK_CONTAINER (scrolled), view);
+  gtk_stack_add_titled (GTK_STACK (priv->stack), scrolled, basename, basename);
+
+  if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
+    {
+      GtkTextBuffer *buffer;
+
+      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+      gtk_text_buffer_set_text (buffer, contents, length);
+      g_free (contents);
+    }
+
+  g_free (basename);
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application3/exampleappwin.c))
+
+Note that we did 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
+`gtk_stack_add_titled()` function.
+
+Our application is beginning to take shape:
+
+![](getting-started-app3.png)
+
+### An application menu
+
+An application menu is shown by GNOME shell at the top of the screen. It is
+meant to collect infrequently used actions that affect the whole
+application.
+
+Just like the window template, we specify our application menu in a ui file,
+and add it as a resource to our binary.
+
+```xml
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <menu id="appmenu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Preferences</attribute>
+        <attribute name="action">app.preferences</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Quit</attribute>
+        <attribute name="action">app.quit</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
+```
+
+To associate the app menu with the application, we have to call
+`gtk_application_set_app_menu()`. Since app menus work by activating `GAction`s,
+we also have to add a suitable set of actions to our application.
+
+Both of these tasks are best done in the `startup()` virtual function, which
+is guaranteed to be called once for each primary application instance:
+
+```c
+// ...
+
+static void
+preferences_activated (GSimpleAction *action,
+                       GVariant      *parameter,
+                       gpointer       app)
+{
+}
+
+static void
+quit_activated (GSimpleAction *action,
+                GVariant      *parameter,
+                gpointer       app)
+{
+  g_application_quit (G_APPLICATION (app));
+}
+
+static GActionEntry app_entries[] =
+{
+  { "preferences", preferences_activated, NULL, NULL, NULL },
+  { "quit", quit_activated, NULL, NULL, NULL }
+};
+
+static void
+example_app_startup (GApplication *app)
+{
+  GtkBuilder *builder;
+  GMenuModel *app_menu;
+  const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
+
+  G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
+
+  g_action_map_add_action_entries (G_ACTION_MAP (app),
+                                   app_entries, G_N_ELEMENTS (app_entries),
+                                   app);
+  gtk_application_set_accels_for_action (GTK_APPLICATION (app),
+                                         "app.quit",
+                                         quit_accels);
+
+  builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
+  app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
+  gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
+  g_object_unref (builder);
+}
+
+static void
+example_app_class_init (ExampleAppClass *class)
+{
+  G_APPLICATION_CLASS (class)->startup = example_app_startup;
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application4/exampleapp.c))
+
+Our preferences menu item does not do anything yet, but the *Quit* menu item
+is fully functional. Note that it can also be activated by the usual
+<kbd>Ctrl</kbd>+<kbd>Q</kbd> shortcut. The shortcut was added with
+`gtk_application_set_accels_for_action()`.
+
+The application menu looks like this:
+
+![](getting-started-app4.png)
+
+### A preference dialog
+
+A typical application will have a some preferences that should be remembered
+from one run to the next. Even for our simple example application, we may
+want to change the font that is used for the content.
+
+We are going to use GSettings to store our preferences. GSettings requires a
+schema that describes our settings:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+  <schema path="/org/gtk/exampleapp/" id="org.gtk.exampleapp">
+    <key name="font" type="s">
+      <default>'Monospace 12'</default>
+      <summary>Font</summary>
+      <description>The font to be used for content.</description>
+    </key>
+    <key name="transition" type="s">
+      <choices>
+        <choice value='none'/>
+        <choice value='crossfade'/>
+        <choice value='slide-left-right'/>
+      </choices>
+      <default>'none'</default>
+      <summary>Transition</summary>
+      <description>The transition to use when switching tabs.</description>
+    </key>
+  </schema>
+</schemalist>
+```
+
+Before we can make use of this schema in our application, we need to compile
+it into the binary form that GSettings expects. GIO provides macros to do
+this in Autotools-based projects, whereas Meson provides the same
+functionality through the `gnome` module.
+
+Next, we need to connect our settings to the widgets that they are supposed
+to control. One convenient way to do this is to use GSettings bind
+functionality to bind settings keys to object properties, as we do here for
+the transition setting.
+
+```c
+// ...
+
+static void
+example_app_window_init (ExampleAppWindow *win)
+{
+  ExampleAppWindowPrivate *priv;
+
+  priv = example_app_window_get_instance_private (win);
+  gtk_widget_init_template (GTK_WIDGET (win));
+  priv->settings = g_settings_new ("org.gtk.exampleapp");
+
+  g_settings_bind (priv->settings, "transition",
+                   priv->stack, "transition-type",
+                   G_SETTINGS_BIND_DEFAULT);
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application5/exampleappwin.c))
+
+The code to connect the font setting is a little more involved, since there
+is no simple object property that it corresponds to, so we are not going to
+go into that here.
+
+At this point, the application will already react if you change one of the
+settings, e.g. using the gsettings commandline tool. Of course, we expect
+the application to provide a preference dialog for these. So lets do that
+now. Our preference dialog will be a subclass of `GtkDialog`, and we'll use
+the same techniques that we've already seen: templates, private structs,
+settings bindings.
+
+Lets start with the template:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="ExampleAppPrefs" parent="GtkDialog">
+    <property name="title" translatable="yes">Preferences</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="vbox">
+        <child>
+          <object class="GtkGrid" id="grid">
+            <property name="visible">True</property>
+            <property name="margin">6</property>
+            <property name="row-spacing">12</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="fontlabel">
+                <property name="visible">True</property>
+                <property name="label">_Font:</property>
+                <property name="use-underline">True</property>
+                <property name="mnemonic-widget">font</property>
+                <property name="xalign">1</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFontButton" id="font">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="transitionlabel">
+                <property name="visible">True</property>
+                <property name="label">_Transition:</property>
+                <property name="use-underline">True</property>
+                <property name="mnemonic-widget">transition</property>
+                <property name="xalign">1</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="transition">
+                <property name="visible">True</property>
+                <items>
+                  <item translatable="yes" id="none">None</item>
+                  <item translatable="yes" id="crossfade">Fade</item>
+                  <item translatable="yes" id="slide-left-right">Slide</item>
+                </items>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
+```
+
+Next comes the dialog class:
+
+```c
+#include <gtk/gtk.h>
+
+#include "exampleapp.h"
+#include "exampleappwin.h"
+#include "exampleappprefs.h"
+
+struct _ExampleAppPrefs
+{
+  GtkDialog parent;
+};
+
+typedef struct _ExampleAppPrefsPrivate ExampleAppPrefsPrivate;
+
+struct _ExampleAppPrefsPrivate
+{
+  GSettings *settings;
+  GtkWidget *font;
+  GtkWidget *transition;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(ExampleAppPrefs, example_app_prefs, GTK_TYPE_DIALOG)
+
+static void
+example_app_prefs_init (ExampleAppPrefs *prefs)
+{
+  ExampleAppPrefsPrivate *priv;
+
+  priv = example_app_prefs_get_instance_private (prefs);
+  gtk_widget_init_template (GTK_WIDGET (prefs));
+  priv->settings = g_settings_new ("org.gtk.exampleapp");
+
+  g_settings_bind (priv->settings, "font",
+                   priv->font, "font",
+                   G_SETTINGS_BIND_DEFAULT);
+  g_settings_bind (priv->settings, "transition",
+                   priv->transition, "active-id",
+                   G_SETTINGS_BIND_DEFAULT);
+}
+
+static void
+example_app_prefs_dispose (GObject *object)
+{
+  ExampleAppPrefsPrivate *priv;
+
+  priv = example_app_prefs_get_instance_private (EXAMPLE_APP_PREFS (object));
+  g_clear_object (&priv->settings);
+
+  G_OBJECT_CLASS (example_app_prefs_parent_class)->dispose (object);
+}
+
+static void
+example_app_prefs_class_init (ExampleAppPrefsClass *class)
+{
+  G_OBJECT_CLASS (class)->dispose = example_app_prefs_dispose;
+
+  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
+                                               "/org/gtk/exampleapp/prefs.ui");
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppPrefs, font);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppPrefs, transition);
+}
+
+ExampleAppPrefs *
+example_app_prefs_new (ExampleAppWindow *win)
+{
+  return g_object_new (EXAMPLE_APP_PREFS_TYPE, "transient-for", win, "use-header-bar", TRUE, NULL);
+}
+```
+
+Now we revisit the `preferences_activated()` function in our application
+class, and make it open a new preference dialog:
+
+```c
+// ...
+
+static void
+preferences_activated (GSimpleAction *action,
+                       GVariant      *parameter,
+                       gpointer       app)
+{
+  ExampleAppPrefs *prefs;
+  GtkWindow *win;
+
+  win = gtk_application_get_active_window (GTK_APPLICATION (app));
+  prefs = example_app_prefs_new (EXAMPLE_APP_WINDOW (win));
+  gtk_window_present (GTK_WINDOW (prefs));
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application6/exampleapp.c))
+
+After all this work, our application can now show a preference dialog like this:
+
+![](getting-started-app6.png)
+
+### Adding a search bar
+
+We continue to flesh out the functionality of our application. For now, we
+add search. GTK supports this with `GtkSearchEntry` and `GtkSearchBar`. The
+search bar is a widget that can slide in from the top of a container to
+present a search entry.
+
+We add a toggle button to the header bar, which can be used to slide out the
+search bar below the header bar.
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
+    <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>
+            <child>
+              <object class="GtkToggleButton" id="search">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+                <child>
+                  <object class="GtkImage" id="search-icon">
+                    <property name="visible">True</property>
+                    <property name="icon-name">edit-find-symbolic</property>
+                    <property name="icon-size">1</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkSearchBar" id="searchbar">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkSearchEntry" id="searchentry">
+                <signal name="search-changed" handler="search_text_changed"/>
+                <property name="visible">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="stack">
+            <signal name="notify::visible-child" handler="visible_child_changed"/>
+            <property name="visible">True</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
+```
+
+Implementing the search needs quite a few code changes that we are not going
+to completely go over here. The central piece of the search implementation
+is a signal handler that listens for text changes in the search entry:
+
+```c
+// ...
+
+static void
+search_text_changed (GtkEntry         *entry,
+                     ExampleAppWindow *win)
+{
+  ExampleAppWindowPrivate *priv;
+  const gchar *text;
+  GtkWidget *tab;
+  GtkWidget *view;
+  GtkTextBuffer *buffer;
+  GtkTextIter start, match_start, match_end;
+
+  text = gtk_entry_get_text (entry);
+
+  if (text[0] == '\0')
+    return;
+
+  priv = example_app_window_get_instance_private (win);
+
+  tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack));
+  view = gtk_bin_get_child (GTK_BIN (tab));
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+  /* Very simple-minded search implementation */
+  gtk_text_buffer_get_start_iter (buffer, &start);
+  if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
+                                    &match_start, &match_end, NULL))
+    {
+      gtk_text_buffer_select_range (buffer, &match_start, &match_end);
+      gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
+                                    0.0, FALSE, 0.0, 0.0);
+    }
+}
+
+static void
+example_app_window_init (ExampleAppWindow *win)
+{
+  // ...
+
+  gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
+
+  // ...
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application7/exampleappwin.c))
+
+With the search bar, our application now looks like this:
+
+![](getting-started-app7.png)
+
+### Adding a side bar
+
+As another piece of functionality, we are adding a sidebar, which
+demonstrates `GtkMenuButton`, `GtkRevealer` and `GtkListBox`.
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
+    <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>
+            <child>
+              <object class="GtkToggleButton" id="search">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+                <child>
+                  <object class="GtkImage" id="search-icon">
+                    <property name="visible">True</property>
+                    <property name="icon-name">edit-find-symbolic</property>
+                    <property name="icon-size">1</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkMenuButton" id="gears">
+                <property name="visible">True</property>
+                <property name="direction">none</property>
+                <property name="use-popover">True</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkSearchBar" id="searchbar">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkSearchEntry" id="searchentry">
+                <signal name="search-changed" handler="search_text_changed"/>
+                <property name="visible">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkBox" id="hbox">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkRevealer" id="sidebar">
+                <property name="visible">True</property>
+                <property name="transition-type">slide-right</property>
+                <child>
+                 <object class="GtkScrolledWindow" id="sidebar-sw">
+                   <property name="visible">True</property>
+                   <property name="hscrollbar-policy">never</property>
+                   <property name="vscrollbar-policy">automatic</property>
+                   <child>
+                     <object class="GtkListBox" id="words">
+                       <property name="visible">True</property>
+                       <property name="selection-mode">none</property>
+                     </object>
+                   </child>
+                 </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkStack" id="stack">
+                <signal name="notify::visible-child" handler="visible_child_changed"/>
+                <property name="visible">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
+```
+
+The code to populate the sidebar with buttons for the words found in each
+file is a little too involved to go into here. But we'll look at the code to
+add the gears menu.
+
+As expected by now, the gears menu is specified in a `GtkBuilder` UI file:
+
+```xml
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <menu id="menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Words</attribute>
+        <attribute name="action">win.show-words</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
+```
+
+To connect the menuitem to the show-words setting, we use a `GAction`
+corresponding to the given `GSettings` key.
+
+```c
+// ...
+
+static void
+example_app_window_init (ExampleAppWindow *win)
+{
+  // ...
+
+  builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
+  menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
+  gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->gears), menu);
+  g_object_unref (builder);
+
+  action = g_settings_create_action (priv->settings, "show-words");
+  g_action_map_add_action (G_ACTION_MAP (win), action);
+  g_object_unref (action);
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application8/exampleappwin.c))
+
+What our application looks like now:
+
+![](getting-started-app8.png)
+
+### Properties
+
+Widgets and other objects have many useful properties.
+
+Here we show some ways to use them in new and flexible ways, by wrapping
+them in actions with `GPropertyAction` or by binding them with `GBinding`.
+
+To set this up, we add two labels to the header bar in our window template,
+named `lines_label` and `lines`, and bind them to struct members in the
+private struct, as we've seen a couple of times by now.
+
+We add a new "Lines" menu item to the gears menu, which triggers the
+`show-lines` action:
+
+```xml
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <menu id="menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Words</attribute>
+        <attribute name="action">win.show-words</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Lines</attribute>
+        <attribute name="action">win.show-lines</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
+```
+
+To make this menu item do something, we create a property action for the
+visible property of the `lines` label, and add it to the actions of the
+window. The effect of this is that the visibility of the label gets toggled
+every time the action is activated.
+
+Since we want both labels to appear and disappear together, we bind the
+visible property of the `lines_label` widget to the same property of the
+`lines` widget.
+
+```c
+// ...
+
+static void
+example_app_window_init (ExampleAppWindow *win)
+{
+  // ...
+
+  action = (GAction*) g_property_action_new ("show-lines", priv->lines, "visible");
+  g_action_map_add_action (G_ACTION_MAP (win), action);
+  g_object_unref (action);
+
+  g_object_bind_property (priv->lines, "visible",
+                          priv->lines_label, "visible",
+                          G_BINDING_DEFAULT);
+}
+
+// ...
+```
+
+([Full source](https://gitlab.gnome.org/GNOME/gtk/blob/gtk-3-22/examples/application9/exampleappwin.c))
+
+We also need a function that counts the lines of the currently active tab,
+and updates the `lines` label. See the full source if you are interested in
+the details.
+
+This brings our example application to this appearance:
+
+![](getting-started-app9.png)
+
+### Header bar
+
+Our application already uses a `GtkHeaderBar`, but so far it still gets a
+'normal' window titlebar on top of that. This is a bit redundant, and we
+will now tell GTK to use the header bar as replacement for the titlebar. To
+do so, we move it around to be a direct child of the window, and set its
+type to be `titlebar`.
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
+    <property name="title" translatable="yes">Example Application</property>
+    <property name="default-width">600</property>
+    <property name="default-height">400</property>
+        <child type="titlebar">
+          <object class="GtkHeaderBar" id="header">
+            <property name="visible">True</property>
+            <property name="show-close-button">True</property>
+            <child>
+              <object class="GtkLabel" id="lines_label">
+                <property name="visible">False</property>
+                <property name="label" translatable="yes">Lines:</property>
+              </object>
+              <packing>
+                <property name="pack-type">start</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="lines">
+                <property name="visible">False</property>
+              </object>
+              <packing>
+                <property name="pack-type">start</property>
+              </packing>
+            </child>
+            <child type="title">
+              <object class="GtkStackSwitcher" id="tabs">
+                <property name="visible">True</property>
+                <property name="stack">stack</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkToggleButton" id="search">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+                <child>
+                  <object class="GtkImage" id="search-icon">
+                    <property name="visible">True</property>
+                    <property name="icon-name">edit-find-symbolic</property>
+                    <property name="icon-size">1</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkMenuButton" id="gears">
+                <property name="visible">True</property>
+                <property name="direction">none</property>
+                <property name="use-popover">True</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+    <child>
+      <object class="GtkBox" id="content_box">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkSearchBar" id="searchbar">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkSearchEntry" id="searchentry">
+                <signal name="search-changed" handler="search_text_changed"/>
+                <property name="visible">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkBox" id="hbox">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkRevealer" id="sidebar">
+                <property name="visible">True</property>
+                <property name="transition-type">slide-right</property>
+                <child>
+                 <object class="GtkScrolledWindow" id="sidebar-sw">
+                   <property name="visible">True</property>
+                   <property name="hscrollbar-policy">never</property>
+                   <property name="vscrollbar-policy">automatic</property>
+                   <child>
+                     <object class="GtkListBox" id="words">
+                       <property name="visible">True</property>
+                       <property name="selection-mode">none</property>
+                     </object>
+                   </child>
+                 </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkStack" id="stack">
+                <signal name="notify::visible-child" handler="visible_child_changed"/>
+                <property name="visible">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
+```
+
+A small extra bonus of using a header bar is that we get a fallback
+application menu for free. Here is how the application now looks, if this
+fallback is used:
+
+![](getting-started-app10.png)
+
+If we set up the window icon for our window, the menu button will use that
+instead of the generic placeholder icon you see here.
+
+## Custom drawing
+
+Many widgets, like buttons, do all their drawing themselves. You just tell
+them the label you want to see, and they figure out what font to use, draw
+the button outline and focus rectangle, etc. Sometimes, it is necessary to
+do some custom drawing. In that case, a [class@Gtk.DrawingArea] might be the right
+widget to use. It offers a canvas on which you can draw by connecting to the
+[signal@Gtk.Widget::draw] signal.
+
+The contents of a widget often need to be partially or fully redrawn, e.g.
+when another window is moved and uncovers part of the widget, or when the
+window containing it is resized. It is also possible to explicitly cause
+part or all of the widget to be redrawn, by calling [`method@Gtk.Widget.queue_draw`]
+or its variants. GTK takes care of most of the details by providing a
+ready-to-use Cairo context to the `draw` signal handler.
+
+The following example shows a `draw` signal handler. It is a bit more
+complicated than the previous examples, since it also demonstrates input
+event handling by means of [`signal@Gtk.Widget::button-press-event`] and
+[`signal@Gtk.Widget::motion-notify-event`] signal handlers.
+
+![](drawing.png)
+
+Save the following example in a file name `example-4.c`:
+
+```c
+#include <gtk/gtk.h>
+
+/* Surface to store current scribbles */
+static cairo_surface_t *surface = NULL;
+
+static void
+clear_surface (void)
+{
+  cairo_t *cr;
+
+  cr = cairo_create (surface);
+
+  cairo_set_source_rgb (cr, 1, 1, 1);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+}
+
+/* Create a new surface of the appropriate size to store our scribbles */
+static gboolean
+configure_event_cb (GtkWidget         *widget,
+                    GdkEventConfigure *event,
+                    gpointer           data)
+{
+  if (surface)
+    cairo_surface_destroy (surface);
+
+  surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+                                               CAIRO_CONTENT_COLOR,
+                                               gtk_widget_get_allocated_width (widget),
+                                               gtk_widget_get_allocated_height (widget));
+
+  /* Initialize the surface to white */
+  clear_surface ();
+
+  /* We've handled the configure event, no need for further processing. */
+  return TRUE;
+}
+
+/* Redraw the screen from the surface. Note that the ::draw
+ * signal receives a ready-to-be-used cairo_t that is already
+ * clipped to only draw the exposed areas of the widget
+ */
+static gboolean
+draw_cb (GtkWidget *widget,
+         cairo_t   *cr,
+         gpointer   data)
+{
+  cairo_set_source_surface (cr, surface, 0, 0);
+  cairo_paint (cr);
+
+  return FALSE;
+}
+
+/* Draw a rectangle on the surface at the given position */
+static void
+draw_brush (GtkWidget *widget,
+            gdouble    x,
+            gdouble    y)
+{
+  cairo_t *cr;
+
+  /* Paint to the surface, where we store our state */
+  cr = cairo_create (surface);
+
+  cairo_rectangle (cr, x - 3, y - 3, 6, 6);
+  cairo_fill (cr);
+
+  cairo_destroy (cr);
+
+  /* Now invalidate the affected region of the drawing area. */
+  gtk_widget_queue_draw_area (widget, x - 3, y - 3, 6, 6);
+}
+
+/* Handle button press events by either drawing a rectangle
+ * or clearing the surface, depending on which button was pressed.
+ * The ::button-press signal handler receives a GdkEventButton
+ * struct which contains this information.
+ */
+static gboolean
+button_press_event_cb (GtkWidget      *widget,
+                       GdkEventButton *event,
+                       gpointer        data)
+{
+  /* paranoia check, in case we haven't gotten a configure event */
+  if (surface == NULL)
+    return FALSE;
+
+  if (event->button == GDK_BUTTON_PRIMARY)
+    {
+      draw_brush (widget, event->x, event->y);
+    }
+  else if (event->button == GDK_BUTTON_SECONDARY)
+    {
+      clear_surface ();
+      gtk_widget_queue_draw (widget);
+    }
+
+  /* We've handled the event, stop processing */
+  return TRUE;
+}
+
+/* Handle motion events by continuing to draw if button 1 is
+ * still held down. The ::motion-notify signal handler receives
+ * a GdkEventMotion struct which contains this information.
+ */
+static gboolean
+motion_notify_event_cb (GtkWidget      *widget,
+                        GdkEventMotion *event,
+                        gpointer        data)
+{
+  /* paranoia check, in case we haven't gotten a configure event */
+  if (surface == NULL)
+    return FALSE;
+
+  if (event->state & GDK_BUTTON1_MASK)
+    draw_brush (widget, event->x, event->y);
+
+  /* We've handled it, stop processing */
+  return TRUE;
+}
+
+static void
+close_window (void)
+{
+  if (surface)
+    cairo_surface_destroy (surface);
+}
+
+static void
+activate (GtkApplication *app,
+          gpointer        user_data)
+{
+  GtkWidget *window;
+  GtkWidget *frame;
+  GtkWidget *drawing_area;
+
+  window = gtk_application_window_new (app);
+  gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");
+
+  g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
+
+  gtk_container_set_border_width (GTK_CONTAINER (window), 8);
+
+  frame = gtk_frame_new (NULL);
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  gtk_container_add (GTK_CONTAINER (window), frame);
+
+  drawing_area = gtk_drawing_area_new ();
+  /* set a minimum size */
+  gtk_widget_set_size_request (drawing_area, 100, 100);
+
+  gtk_container_add (GTK_CONTAINER (frame), drawing_area);
+
+  /* Signals used to handle the backing surface */
+  g_signal_connect (drawing_area, "draw",
+                    G_CALLBACK (draw_cb), NULL);
+  g_signal_connect (drawing_area,"configure-event",
+                    G_CALLBACK (configure_event_cb), NULL);
+
+  /* Event signals */
+  g_signal_connect (drawing_area, "motion-notify-event",
+                    G_CALLBACK (motion_notify_event_cb), NULL);
+  g_signal_connect (drawing_area, "button-press-event",
+                    G_CALLBACK (button_press_event_cb), NULL);
+
+  /* Ask to receive events the drawing area doesn't normally
+   * subscribe to. In particular, we need to ask for the
+   * button press and motion notify events that want to handle.
+   */
+  gtk_widget_set_events (drawing_area, gtk_widget_get_events (drawing_area)
+                                     | GDK_BUTTON_PRESS_MASK
+                                     | GDK_POINTER_MOTION_MASK);
+
+  gtk_widget_show_all (window);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  GtkApplication *app;
+  int status;
+
+  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
+  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+  status = g_application_run (G_APPLICATION (app), argc, argv);
+  g_object_unref (app);
+
+  return status;
+}
+```
+
+You can compile the program above with GCC using:
+
+    gcc `pkg-config --cflags gtk+-3.0` -o example-4 example-4.c `pkg-config --libs gtk+-3.0`
diff --git a/gtk3/gtk/grid-packing.png b/gtk3/gtk/grid-packing.png
new file mode 100644
index 0000000000..3ce46ff7f5
Binary files /dev/null and b/gtk3/gtk/grid-packing.png differ
diff --git a/gtk3/gtk/gtk3.toml.in b/gtk3/gtk/gtk3.toml.in
index c74f912db1..78a077fb0b 100644
--- a/gtk3/gtk/gtk3.toml.in
+++ b/gtk3/gtk/gtk3.toml.in
@@ -50,6 +50,7 @@ content_files = [
   "building.md",
   "compiling.md",
   "running.md",
+  "getting_started.md",
   "drawing-model.md",
   "input-handling.md",
   "key-bindings.md",
@@ -76,6 +77,22 @@ content_files = [
 content_images = [
   "gtk-logo.svg",
 
+  "builder.png",
+  "drawing.png",
+  "exampleapp.png",
+  "getting-started-app1.png",
+  "getting-started-app2.png",
+  "getting-started-app3.png",
+  "getting-started-app4.png",
+  "getting-started-app6.png",
+  "getting-started-app7.png",
+  "getting-started-app8.png",
+  "getting-started-app9.png",
+  "getting-started-app10.png",
+  "grid-packing.png",
+  "hellow-world.png",
+  "window-default.png",
+
   "images/cell-renderer-properties.png",
   "images/renderer.png",
   "images/treepath.png",
diff --git a/gtk3/gtk/hellow-world.png b/gtk3/gtk/hellow-world.png
new file mode 100644
index 0000000000..2f290051e7
Binary files /dev/null and b/gtk3/gtk/hellow-world.png differ
diff --git a/gtk3/gtk/window-default.png b/gtk3/gtk/window-default.png
new file mode 100644
index 0000000000..6e2b1464c4
Binary files /dev/null and b/gtk3/gtk/window-default.png differ


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