<chapter id="gtk-getting-started">
  <title>Getting Started with GTK</title>
  <para>
    GTK is a
    <ulink url="http://en.wikipedia.org/wiki/Widget_toolkit">widget
    toolkit</ulink>. Each user interface created by GTK consists of
    widgets. This is implemented in C using
    <link linkend="gobject">GObject</link>, an object-oriented framework
    for C. Widgets are organized in a hierarchy. 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
    <ulink url="https://glade.gnome.org/">glade</ulink>.
  </para>
  <para>
    GTK is event-driven. The toolkit listens for events such as a click
    on a button, and passes the event to your application.
  </para>
  <para>
    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
    <link linkend="gtk-compiling">Compiling the GTK libraries</link>
    section in this reference.
  </para>
  <sect1>
    <title>Basics</title>
    <para>
      To begin our introduction to GTK, we’ll start with a very simple
      application. This program will create an empty 200 × 200 pixel
      window.
    </para>
    <figure>
      <title>A window</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="window-default.png" />
        </imageobject>
        <textobject><phrase>A window</phrase></textobject>
      </mediaobject>
    </figure>
    <para>
      Create a new file with the following content named
      <literal>example-0.c</literal>.
    </para>
    <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
  GtkWidget *window;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), &quot;Window&quot;);
  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
  gtk_widget_show (window);
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new (&quot;org.gtk.example&quot;, G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, &quot;activate&quot;, G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}
</programlisting>
    <para>
      You can compile the program above with GCC using:
    </para>
    <programlisting>
gcc `pkg-config --cflags gtk4` -o example-0 example-0.c `pkg-config --libs gtk4`
</programlisting>
    <para>
      For more information on how to compile a GTK application, please
      refer to the <link linkend="gtk-compiling">Compiling GTK
      Applications</link> section in this reference.
    </para>
    <para>
      All GTK applications will, of course, include
      <literal>gtk/gtk.h</literal>, which declares functions, types and
      macros required by GTK applications.
    </para>
    <para>
      Even if GTK installs multiple header files, only the top-level
      <literal>gtk/gtk.h</literal> header can be directly included by
      third-party code. The compiler will abort with an error if any
      other header is directly included.
    </para>
    <para>
      In a GTK application, the purpose of the <link linkend="main"><function>main()</function></link> function is to
      create a GtkApplication object and run it. In this example a
      GtkApplication pointer named <literal>app</literal> is declared
      and then initialized using <link linkend="gtk-application-new"><function>gtk_application_new()</function></link>.
    </para>
    <para>
      When creating a GtkApplication, you need to pick an application
      identifier (a name) and pass it to <link linkend="gtk-application-new"><function>gtk_application_new()</function></link> as
      parameter. For this example <literal>org.gtk.example</literal> is
      used. For choosing an identifier for your application, see
      <ulink url="https://wiki.gnome.org/HowDoI/ChooseApplicationID">this
      guide</ulink>. Lastly, <link linkend="gtk-application-new"><function>gtk_application_new()</function></link> takes
      GApplicationFlags as input for your application, if your
      application would have special needs.
    </para>
    <para>
      Next the
      <ulink url="https://wiki.gnome.org/HowDoI/GtkApplication">activate
      signal</ulink> is connected to the <link linkend="activate"><function>activate()</function></link> function above the
      <link linkend="main"><function>main()</function></link> function. The <literal>activate</literal> signal will be
      emitted when your application is launched with <link linkend="g-application-run"><function>g_application_run()</function></link>
      on the line below. The <link linkend="g-application-run"><function>g_application_run()</function></link> call also takes as
      arguments the command line arguments (the <literal>argc</literal>
      count and the <literal>argv</literal> string array). Your
      application can override the command line handling, e.g. to open
      files passed on the commandline.
    </para>
    <para>
      Within <link linkend="g-application-run"><function>g_application_run()</function></link> the activate signal is sent and we then
      proceed into the <link linkend="activate"><function>activate()</function></link> function of the application. This is
      where we construct our GTK window, so that a window is shown when
      the application is launched. The call to
      <link linkend="gtk-application-window-new"><function>gtk_application_window_new()</function></link> will create a new GtkWindow and store
      it inside the <literal>window</literal> pointer. The window will
      have a frame, a title bar, and window controls depending on the
      platform.
    </para>
    <para>
      A window title is set using <link linkend="gtk-window-set-title"><function>gtk_window_set_title()</function></link>. This function
      takes a GtkWindow* pointer and a string as input. As our
      <literal>window</literal> pointer is a GtkWidget pointer, we need
      to cast it to GtkWindow*. But instead of casting
      <literal>window</literal> via <literal>(GtkWindow*)</literal>,
      <literal>window</literal> can be cast using the macro
      <literal><link linkend="GTK-WINDOW:CAPS"><function>GTK_WINDOW()</function></link></literal>. <literal><link linkend="GTK-WINDOW:CAPS"><function>GTK_WINDOW()</function></link></literal>
      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
      <ulink url="https://developer.gnome.org/gobject/stable/gtype-conventions.html">here</ulink>.
    </para>
    <para>
      Finally the window size is set using <link linkend="gtk-window-set-default-size"><function>gtk_window_set_default_size()</function></link>
      and the window is then shown by GTK via <link linkend="gtk-widget-show"><function>gtk_widget_show()</function></link>.
    </para>
    <para>
      When you close the window, by for example pressing the X, the
      <link linkend="g-application-run"><function>g_application_run()</function></link> call returns with a number which is saved
      inside an integer variable named <literal>status</literal>.
      Afterwards, the GtkApplication object is freed from memory with
      <link linkend="g-object-unref"><function>g_object_unref()</function></link>. Finally the status integer is returned and the
      application exits.
    </para>
    <para>
      While the program is running, GTK is receiving
      <emphasis>events</emphasis>. 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, <emphasis>signals</emphasis> 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.
    </para>
    <para>
      The following example is slightly more complex, and tries to
      showcase some of the capabilities of GTK.
    </para>
  </sect1>
  <sect1>
    <title>Hello, World</title>
    <para>
      In the long tradition of programming languages and libraries, this
      example is called <emphasis>Hello, World</emphasis>.
    </para>
    <figure>
      <title>Hello, world</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="hello-world.png" />
        </imageobject>
        <textobject><phrase>Hello, world</phrase></textobject>
      </mediaobject>
    </figure>
    <sect2 id="gtk-getting-started-hello-world">
      <title>Hello World in C</title>
      <para>
        Create a new file with the following content named
        <literal>example-1.c</literal>.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

static void
print_hello (GtkWidget *widget,
             gpointer   data)
{
  g_print (&quot;Hello World\n&quot;);
}

static void
activate (GtkApplication *app,
          gpointer        user_data)
{
  GtkWidget *window;
  GtkWidget *button;
  GtkWidget *box;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), &quot;Window&quot;);
  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
  gtk_window_set_child (GTK_WINDOW (window), box);

  button = gtk_button_new_with_label (&quot;Hello World&quot;);
  g_signal_connect (button, &quot;clicked&quot;, G_CALLBACK (print_hello), NULL);
  g_signal_connect_swapped (button, &quot;clicked&quot;, G_CALLBACK (gtk_window_destroy), window);
  gtk_box_append (GTK_BOX (box), button);

  gtk_widget_show (window);
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new (&quot;org.gtk.example&quot;, G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, &quot;activate&quot;, G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}
</programlisting>
      <para>
        You can compile the program above with GCC using:
      </para>
      <programlisting>
gcc `pkg-config --cflags gtk4` -o example-1 example-1.c `pkg-config --libs gtk4`
</programlisting>
      <para>
        As seen above, example-1.c builds further upon example-0.c by
        adding a button to our window, with the label <quote>Hello
        World</quote>. Two new GtkWidget pointers are declared to
        accomplish this, <literal>button</literal> and
        <literal>box</literal>. The box variable is created to store a
        GtkBox, which is GTK’s way of controlling the size and layout of
        buttons.
      </para>
      <para>
        The GtkBox is created with <link linkend="gtk-box-new"><function>gtk_box_new()</function></link> which takes a
        GtkOrientation enum as parameter. The buttons which this box
        will contain can either be laid out horizontally or vertically.
        This does not matter in this particular case, as we are dealing
        with only one button. After initializing box with the newly
        created GtkBox, the code adds the box widget to the window
        widget using <link linkend="gtk-window-set-child"><function>gtk_window_set_child()</function></link>.
      </para>
      <para>
        Next the <literal>button</literal> variable is initialized in
        similar manner. <link linkend="gtk-button-new-with-label"><function>gtk_button_new_with_label()</function></link> is called which
        returns a GtkButton to be stored in <literal>button</literal>.
        Afterwards <literal>button</literal> is added to our
        <literal>box</literal>.
      </para>
      <para>
        Using <link linkend="g-signal-connect"><function>g_signal_connect()</function></link>, the button is connected to a function
        in our app called <link linkend="print-hello"><function>print_hello()</function></link>, so that when the button is
        clicked, GTK will call this function. As the <link linkend="print-hello"><function>print_hello()</function></link>
        function does not use any data as input, NULL is passed to it.
        <link linkend="print-hello"><function>print_hello()</function></link> calls <link linkend="g-print"><function>g_print()</function></link> with the string <quote>Hello
        World</quote> which will print Hello World in a terminal if the
        GTK application was started from one.
      </para>
      <para>
        After connecting <link linkend="print-hello"><function>print_hello()</function></link>, another signal is connected to
        the <quote>clicked</quote> state of the button using
        <link linkend="g-signal-connect-swapped"><function>g_signal_connect_swapped()</function></link>. This functions is similar to a
        <link linkend="g-signal-connect"><function>g_signal_connect()</function></link> with the difference lying in how the callback
        function is treated. <link linkend="g-signal-connect-swapped"><function>g_signal_connect_swapped()</function></link> 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 <link linkend="gtk-window-destroy"><function>gtk_window_destroy()</function></link> and the
        <literal>window</literal> 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 <link linkend="g-signal-connect"><function>g_signal_connect()</function></link> were used
        to connect the <quote>clicked</quote> signal with
        <link linkend="gtk-window-destroy"><function>gtk_window_destroy()</function></link>, then the function would be called on
        <literal>button</literal> (which would not go well, since the
        function expects a GtkWindow as argument).
      </para>
      <para>
        More information about creating buttons can be found
        <ulink url="https://wiki.gnome.org/HowDoI/Buttons">here</ulink>.
      </para>
      <para>
        The rest of the code in <literal>example-1.c</literal> is
        identical to <literal>example-0.c</literal>. The next section
        will elaborate further on how to add several GtkWidgets to your
        GTK application.
      </para>
    </sect2>
  </sect1>
  <sect1>
    <title>Packing</title>
    <para>
      When creating an application, you’ll want to put more than one
      widget inside a window. When you do so, it becomes important to
      control how each widget is positioned and sized. This is where
      packing comes in.
    </para>
    <para>
      GTK comes with a large variety of <emphasis>layout
      containers</emphasis> whose purpose it is to control the layout of
      the child widgets that are added to them. See
      <link linkend="LayoutContainers">Layout containers</link> for an
      overview.
    </para>
    <para>
      The following example shows how the GtkGrid container lets you
      arrange several buttons:
    </para>
    <figure>
      <title>Grid packing</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="grid-packing.png" />
        </imageobject>
        <textobject><phrase>Grid packing</phrase></textobject>
      </mediaobject>
    </figure>
    <sect2 id="gtk-getting-started-grid-packing">
      <title>Packing buttons</title>
      <para>
        Create a new file with the following content named
        <literal>example-2.c</literal>.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

static void
print_hello (GtkWidget *widget,
             gpointer   data)
{
  g_print (&quot;Hello World\n&quot;);
}

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), &quot;Window&quot;);

  /* Here we construct the container that is going pack our buttons */
  grid = <link linkend="gtk-grid-new"><function>gtk_grid_new()</function></link>;

  /* Pack the container in the window */
  gtk_window_set_child (GTK_WINDOW (window), grid);

  button = gtk_button_new_with_label (&quot;Button 1&quot;);
  g_signal_connect (button, &quot;clicked&quot;, 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 (&quot;Button 2&quot;);
  g_signal_connect (button, &quot;clicked&quot;, 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 (&quot;Quit&quot;);
  g_signal_connect_swapped (button, &quot;clicked&quot;, G_CALLBACK (gtk_window_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);

  gtk_widget_show (window);

}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new (&quot;org.gtk.example&quot;, G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, &quot;activate&quot;, G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}
</programlisting>
      <para>
        You can compile the program above with GCC using:
      </para>
      <programlisting>
gcc `pkg-config --cflags gtk4` -o example-2 example-2.c `pkg-config --libs gtk4`
</programlisting>
    </sect2>
  </sect1>
  <sect1>
    <title>Custom Drawing</title>
    <para>
      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 GtkDrawingArea might be the right widget to use. It offers
      a canvas on which you can draw by connecting to the ::draw signal.
    </para>
    <para>
      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 <link linkend="gtk-widget-queue-draw"><function>gtk_widget_queue_draw()</function></link> or its variants. GTK
      takes care of most of the details by providing a ready-to-use
      cairo context to the ::draw signal handler.
    </para>
    <para>
      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 event controllers.
    </para>
    <figure>
      <title>Drawing</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="drawing.png" />
        </imageobject>
        <textobject><phrase>Drawing</phrase></textobject>
      </mediaobject>
    </figure>
    <sect2 id="gtk-getting-started-drawing">
      <title>Drawing in response to input</title>
      <para>
        Create a new file with the following content named
        <literal>example-4.c</literal>.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

/* 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 void
resize_cb (GtkWidget *widget,
           int        width,
           int        height,
           gpointer   data)
{
  if (surface)
    {
      cairo_surface_destroy (surface);
      surface = NULL;
    }

  if (gtk_native_get_surface (gtk_widget_get_native (widget)))
    {
      surface = gdk_surface_create_similar_surface (gtk_native_get_surface (gtk_widget_get_native (widget)),
                                                   CAIRO_CONTENT_COLOR,
                                                   gtk_widget_get_width (widget),
                                                   gtk_widget_get_height (widget));

      /* Initialize the surface to white */
      <link linkend="clear-surface"><function>clear_surface()</function></link>;
    }
}

/* Redraw the screen from the surface. Note that the draw
 * callback receives a ready-to-be-used cairo_t that is already
 * clipped to only draw the exposed areas of the widget
 */
static void
draw_cb (GtkDrawingArea *drawing_area,
         cairo_t        *cr,
         int             width,
         int             height,
         gpointer        data)
{
  cairo_set_source_surface (cr, surface, 0, 0);
  cairo_paint (cr);
}

/* Draw a rectangle on the surface at the given position */
static void
draw_brush (GtkWidget *widget,
            double     x,
            double     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 drawing area. */
  gtk_widget_queue_draw (widget);
}

static double start_x;
static double start_y;

static void
drag_begin (GtkGestureDrag *gesture,
            double          x,
            double          y,
            GtkWidget      *area)
{
  start_x = x;
  start_y = y;

  draw_brush (area, x, y);
}

static void
drag_update (GtkGestureDrag *gesture,
             double          x,
             double          y,
             GtkWidget      *area)
{
  draw_brush (area, start_x + x, start_y + y);
}

static void
drag_end (GtkGestureDrag *gesture,
          double          x,
          double          y,
          GtkWidget      *area)
{
  draw_brush (area, start_x + x, start_y + y);
}

static void
pressed (GtkGestureClick *gesture,
         int              n_press,
         double           x,
         double           y,
         GtkWidget       *area)
{
  <link linkend="clear-surface"><function>clear_surface()</function></link>;
  gtk_widget_queue_draw (area);
}

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;
  GtkGesture *drag;
  GtkGesture *press;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), &quot;Drawing Area&quot;);

  g_signal_connect (window, &quot;destroy&quot;, G_CALLBACK (close_window), NULL);

  frame = gtk_frame_new (NULL);
  gtk_window_set_child (GTK_WINDOW (window), frame);

  drawing_area = <link linkend="gtk-drawing-area-new"><function>gtk_drawing_area_new()</function></link>;
  /* set a minimum size */
  gtk_widget_set_size_request (drawing_area, 100, 100);

  gtk_frame_set_child (GTK_FRAME (frame), drawing_area);

  gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area), draw_cb, NULL, NULL);

  g_signal_connect_after (drawing_area, &quot;resize&quot;, G_CALLBACK (resize_cb), NULL);

  drag = <link linkend="gtk-gesture-drag-new"><function>gtk_gesture_drag_new()</function></link>;
  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
  gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (drag));
  g_signal_connect (drag, &quot;drag-begin&quot;, G_CALLBACK (drag_begin), drawing_area);
  g_signal_connect (drag, &quot;drag-update&quot;, G_CALLBACK (drag_update), drawing_area);
  g_signal_connect (drag, &quot;drag-end&quot;, G_CALLBACK (drag_end), drawing_area);

  press = <link linkend="gtk-gesture-click-new"><function>gtk_gesture_click_new()</function></link>;
  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (press), GDK_BUTTON_SECONDARY);
  gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (press));

  g_signal_connect (press, &quot;pressed&quot;, G_CALLBACK (pressed), drawing_area);

  gtk_widget_show (window);
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new (&quot;org.gtk.example&quot;, G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, &quot;activate&quot;, G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}
</programlisting>
      <para>
        You can compile the program above with GCC using:
      </para>
      <programlisting>
gcc `pkg-config --cflags gtk4` -o example-4 example-4.c `pkg-config --libs gtk4`
</programlisting>
    </sect2>
  </sect1>
  <sect1>
    <title>Building user interfaces</title>
    <para>
      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.
    </para>
    <para>
      Thankfully, GTK supports the separation of user interface layout
      from your business logic, by using UI descriptions in an XML
      format that can be parsed by the GtkBuilder class.&lt;/para&gt;
    </para>
    <sect2>
      <title>Packing buttons with GtkBuilder</title>
      <para>
        Create a new file with the following content named
        <literal>example-3.c</literal>.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;
#include &lt;glib/gstdio.h&gt;

static void
print_hello (GtkWidget *widget,
             gpointer   data)
{
  g_print (&quot;Hello World\n&quot;);
}

static void
quit_cb (GtkWidget *widget, gpointer data)
{
  gboolean *done = data;

  *done = TRUE;

  g_main_context_wakeup (NULL);
}

int
main (int   argc,
      char *argv[])
{
  GtkBuilder *builder;
  GObject *window;
  GObject *button;
  gboolean done = FALSE;

#ifdef GTK_SRCDIR
  g_chdir (GTK_SRCDIR);
#endif

  <link linkend="gtk-init"><function>gtk_init()</function></link>;

  /* Construct a GtkBuilder instance and load our UI description */
  builder = <link linkend="gtk-builder-new"><function>gtk_builder_new()</function></link>;
  gtk_builder_add_from_file (builder, &quot;builder.ui&quot;, NULL);

  /* Connect signal handlers to the constructed widgets. */
  window = gtk_builder_get_object (builder, &quot;window&quot;);
  g_signal_connect (window, &quot;destroy&quot;, G_CALLBACK (quit_cb), &amp;done);

  button = gtk_builder_get_object (builder, &quot;button1&quot;);
  g_signal_connect (button, &quot;clicked&quot;, G_CALLBACK (print_hello), NULL);

  button = gtk_builder_get_object (builder, &quot;button2&quot;);
  g_signal_connect (button, &quot;clicked&quot;, G_CALLBACK (print_hello), NULL);

  button = gtk_builder_get_object (builder, &quot;quit&quot;);
  g_signal_connect (button, &quot;clicked&quot;, G_CALLBACK (quit_cb), &amp;done);

  gtk_widget_show (GTK_WIDGET (window));

  while (!done)
    g_main_context_iteration (NULL, TRUE);

  return 0;
}
</programlisting>
      <para>
        Create a new file with the following content named
        <literal>builder.ui</literal>.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;object id=&quot;window&quot; class=&quot;GtkWindow&quot;&gt;
    &lt;property name=&quot;title&quot;&gt;Grid&lt;/property&gt;
    &lt;child&gt;
      &lt;object id=&quot;grid&quot; class=&quot;GtkGrid&quot;&gt;
        &lt;child&gt;
          &lt;object id=&quot;button1&quot; class=&quot;GtkButton&quot;&gt;
            &lt;property name=&quot;label&quot;&gt;Button 1&lt;/property&gt;
            &lt;layout&gt;
              &lt;property name=&quot;column&quot;&gt;0&lt;/property&gt;
              &lt;property name=&quot;row&quot;&gt;0&lt;/property&gt;
            &lt;/layout&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child&gt;
          &lt;object id=&quot;button2&quot; class=&quot;GtkButton&quot;&gt;
            &lt;property name=&quot;label&quot;&gt;Button 2&lt;/property&gt;
            &lt;layout&gt;
              &lt;property name=&quot;column&quot;&gt;1&lt;/property&gt;
              &lt;property name=&quot;row&quot;&gt;0&lt;/property&gt;
            &lt;/layout&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child&gt;
          &lt;object id=&quot;quit&quot; class=&quot;GtkButton&quot;&gt;
            &lt;property name=&quot;label&quot;&gt;Quit&lt;/property&gt;
            &lt;layout&gt;
              &lt;property name=&quot;column&quot;&gt;0&lt;/property&gt;
              &lt;property name=&quot;row&quot;&gt;1&lt;/property&gt;
              &lt;property name=&quot;column-span&quot;&gt;2&lt;/property&gt;
            &lt;/layout&gt;
          &lt;/object&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
  &lt;/object&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        You can compile the program above with GCC using:
      </para>
      <programlisting>
gcc `pkg-config --cflags gtk4` -o example-3 example-3.c `pkg-config --libs gtk4`
</programlisting>
      <para>
        Note that GtkBuilder can also be used to construct objects that
        are not widgets, such as tree models, adjustments, etc. That is
        the reason the method we use here is called
        <link linkend="gtk-builder-get-object"><function>gtk_builder_get_object()</function></link> and returns a GObject* instead of a
        GtkWidget*.
      </para>
      <para>
        Normally, you would pass a full path to
        <link linkend="gtk-builder-add-from-file"><function>gtk_builder_add_from_file()</function></link> to make the execution of your
        program independent of the current directory. A common location
        to install UI descriptions and similar data is
        <literal>/usr/share/appname</literal>.
      </para>
      <para>
        It is also possible to embed the UI description in the source
        code as a string and use <link linkend="gtk-builder-add-from-string"><function>gtk_builder_add_from_string()</function></link> to load
        it. But keeping the UI description in a separate file has
        several advantages: It is then possible to make minor
        adjustments to the UI without recompiling your program, and,
        more importantly, graphical UI editors such as
        <ulink url="http://glade.gnome.org">glade</ulink> can load the
        file and allow you to create and modify your UI by
        point-and-click.
      </para>
    </sect2>
  </sect1>
  <sect1>
    <title>Building applications</title>
    <para>
      An application consists of a number of files:
    </para>
    <variablelist spacing="compact">
      <varlistentry>
        <term>
          The binary
        </term>
        <listitem>
          <para>
            This gets installed in <literal>/usr/bin</literal>.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>
          A desktop file
        </term>
        <listitem>
          <para>
            The desktop file provides important information about the
            application to
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>
      the desktop shell, such as its name, icon, D-Bus name, commandline
      to launch it, etc. It is installed in
      <literal>/usr/share/applications</literal>. An icon : The icon
      gets installed in
      <literal>/usr/share/icons/hicolor/48x48/apps</literal>, where it
      will be found regardless of the current theme. A settings schema :
      If the application uses GSettings, it will install its schema in
      <literal>/usr/share/glib-2.0/schemas</literal>, so that tools like
      dconf-editor can find it. Other resources : Other files, such as
      GtkBuilder 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 <literal>/usr/share</literal>.
    </para>
    <para>
      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 GtkApplication, templates,
      resources, application menus, settings, GtkHeaderBar, GtkStack,
      GtkSearchBar, GtkListBox, and more.
    </para>
    <para>
      The full, buildable sources for these examples can be found in the
      <literal>examples/</literal> directory of the GTK source
      distribution, or
      <ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples">online</ulink>
      in the GTK git repository. You can build each example separately
      by using make with the <literal>Makefile.example</literal> file.
      For more information, see the <literal>README</literal> included
      in the examples directory.
    </para>
    <sect2>
      <title>A trivial application</title>
      <para>
        When using GtkApplication, the <link linkend="main"><function>main()</function></link> function can be very
        simple. We just call <link linkend="g-application-run"><function>g_application_run()</function></link> and give it an instance
        of our application class.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

#include &quot;exampleapp.h&quot;

int
main (int argc, char *argv[])
{
  return g_application_run (G_APPLICATION (<link linkend="example-app-new"><function>example_app_new()</function></link>), argc, argv);
}
</programlisting>
      <para>
        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.
      </para>
      <para>
        To handle these two cases, we override the <link linkend="activate"><function>activate()</function></link> vfunc,
        which gets called when the application is launched without
        commandline arguments, and the <link linkend="open"><function>open()</function></link> vfunc, which gets called
        when the application is launched with commandline arguments.
      </para>
      <para>
        To learn more about GApplication entry points, consult the GIO
        <ulink url="https://developer.gnome.org/gio/2.36/GApplication.html#GApplication.description">documentation</ulink>.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

#include &quot;exampleapp.h&quot;
#include &quot;exampleappwin.h&quot;

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,
                  int            n_files,
                  const char    *hint)
{
  GList *windows;
  ExampleAppWindow *win;
  int i;

  windows = gtk_application_get_windows (GTK_APPLICATION (app));
  if (windows)
    win = EXAMPLE_APP_WINDOW (windows-&gt;data);
  else
    win = example_app_window_new (EXAMPLE_APP (app));

  for (i = 0; i &lt; 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)-&gt;activate = example_app_activate;
  G_APPLICATION_CLASS (class)-&gt;open = example_app_open;
}

ExampleApp *
example_app_new (void)
{
  return g_object_new (EXAMPLE_APP_TYPE,
                       &quot;application-id&quot;, &quot;org.gtk.exampleapp&quot;,
                       &quot;flags&quot;, G_APPLICATION_HANDLES_OPEN,
                       NULL);
}
</programlisting>
      <para>
        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.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

#include &quot;exampleapp.h&quot;
#include &quot;exampleappwin.h&quot;

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, &quot;application&quot;, app, NULL);
}

void
example_app_window_open (ExampleAppWindow *win,
                         GFile            *file)
{
}
</programlisting>
      <para>
        As part of the initial setup of our application, we also create
        an icon and a desktop file.
      </para>
      <figure>
        <title>An icon</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="exampleapp.png" />
          </imageobject>
          <textobject><phrase>An icon</phrase></textobject>
        </mediaobject>
      </figure>
      <programlisting>
[Desktop Entry]
Type=Application
Name=Example
Icon=exampleapp
StartupNotify=true
Exec=<parameter>bindir</parameter>@/exampleapp
</programlisting>
      <para>
        Note that <literal><parameter>bindir</parameter>@</literal> 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>
        <title>An application</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app1.png" />
          </imageobject>
          <textobject><phrase>An application</phrase></textobject>
        </mediaobject>
      </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>
    </sect2>
    <sect2>
      <title>Populating the window</title>
      <para>
        In this step, we use a GtkBuilder template to associate a
        GtkBuilder ui file with our application window class.
      </para>
      <para>
        Our simple ui file gives the window a title, and puts a GtkStack
        widget as the main content.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;template class=&quot;ExampleAppWindow&quot; parent=&quot;GtkApplicationWindow&quot;&gt;
    &lt;property name=&quot;title&quot; translatable=&quot;yes&quot;&gt;Example Application&lt;/property&gt;
    &lt;property name=&quot;default-width&quot;&gt;600&lt;/property&gt;
    &lt;property name=&quot;default-height&quot;&gt;400&lt;/property&gt;
    &lt;child&gt;
      &lt;object class=&quot;GtkBox&quot; id=&quot;content_box&quot;&gt;
        &lt;property name=&quot;orientation&quot;&gt;vertical&lt;/property&gt;
        &lt;child&gt;
          &lt;object class=&quot;GtkStack&quot; id=&quot;stack&quot;/&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
  &lt;/template&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        To make use of this file in our application, we revisit our
        GtkApplicationWindow subclass, and call
        <link linkend="gtk-widget-class-set-template-from-resource"><function>gtk_widget_class_set_template_from_resource()</function></link> from the class
        init function to set the ui file as template for this class. We
        also add a call to <link linkend="gtk-widget-init-template"><function>gtk_widget_init_template()</function></link> in the instance
        init function to instantiate the template for each instance of
        our class.
      </para>
      <programlisting>
 ...

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),
                                               &quot;/org/gtk/exampleapp/window.ui&quot;);
}

 ...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application2/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        You may have noticed that we used the
        <literal><link linkend="from-resource"><function>_from_resource()</function></link></literal> variant of the function that
        sets a template. Now we need to use
        <ulink url="https://developer.gnome.org/gio/stable/GResource.html">GLib’s
        resource functionality</ulink> to include the ui file in the
        binary. This is commonly done by listing all resources in a
        <literal>.gresource.xml</literal> file, such as this:
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;gresources&gt;
  &lt;gresource prefix=&quot;/org/gtk/exampleapp&quot;&gt;
    &lt;file preprocess=&quot;xml-stripblanks&quot;&gt;window.ui&lt;/file&gt;
  &lt;/gresource&gt;
&lt;/gresources&gt;
</programlisting>
      <para>
        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
        <literal>glib-compile-resources</literal> utility:
      </para>
      <programlisting>
glib-compile-resources exampleapp.gresource.xml --target=resources.c --generate-source
</programlisting>
      <para>
        The gnome module of the meson build system provides the
        <ulink url="https://mesonbuild.com/Gnome-module.html#gnomecompile_resources">gnome.compile_resources()</ulink>
        method for this task.
      </para>
      <para>
        Our application now looks like this:
      </para>
      <figure>
        <title>The application</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app2.png" />
          </imageobject>
          <textobject><phrase>The application</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
    <sect2>
      <title>Opening files</title>
      <para>
        In this step, we make our application show the content of all
        the files that it is given on the commandline.
      </para>
      <para>
        To this end, we add a member to the struct of our application
        window subclass and keep a reference to the GtkStack there. The
        first member of the struct should be the parent type from which
        the class is derived. Here, ExampleAppWindow is derived from
        GtkApplicationWindow. The <link linkend="gtk-widget-class-bind-template-child"><function>gtk_widget_class_bind_template_child()</function></link>
        function arranges things so that after instantiating the
        template, the <literal>stack</literal> member of the struct will
        point to the widget of the same name from the template.
      </para>
      <programlisting>
...

struct _ExampleAppWindow
{
  GtkApplicationWindow parent;

  GtkWidget *stack;
};

G_DEFINE_TYPE (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),
                                               &quot;/org/gtk/exampleapp/window.ui&quot;);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        Now we revisit the <link linkend="example-app-window-open"><function>example_app_window_open()</function></link> function that is
        called for each commandline argument, and construct a
        GtkTextView that we then add as a page to the stack:
      </para>
      <programlisting>
...

void
example_app_window_open (ExampleAppWindow *win,
                         GFile            *file)
{
  char *basename;
  GtkWidget *scrolled, *view;
  char *contents;
  gsize length;

  basename = g_file_get_basename (file);

  scrolled = <link linkend="gtk-scrolled-window-new"><function>gtk_scrolled_window_new()</function></link>;
  gtk_widget_set_hexpand (scrolled, TRUE);
  gtk_widget_set_vexpand (scrolled, TRUE);
  view = <link linkend="gtk-text-view-new"><function>gtk_text_view_new()</function></link>;
  gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
  gtk_stack_add_titled (GTK_STACK (win-&gt;stack), scrolled, basename, basename);

  if (g_file_load_contents (file, NULL, &amp;contents, &amp;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);
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        Lastly, we add a GtkStackSwitcher to the titlebar area in the ui
        file, and we tell it to display information about our stack.
      </para>
      <para>
        The stack switcher gets all its information it needs to display
        tabs from the stack that it belongs to. Here, we are passing the
        label to show for each file as the last argument to the
        <link linkend="gtk-stack-add-titled"><function>gtk_stack_add_titled()</function></link> function.
      </para>
      <para>
        Our application is beginning to take shape:
      </para>
      <figure>
        <title>Application window</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app3.png" />
          </imageobject>
          <textobject><phrase>Application window</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
    <sect2>
      <title>A menu</title>
      <para>
        The menu is shown at the right side of the headerbar. It is
        meant to collect infrequently used actions that affect the whole
        application.
      </para>
      <para>
        Just like the window template, we specify our menu in a ui file,
        and add it as a resource to our binary.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;menu id=&quot;menu&quot;&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Preferences&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;app.preferences&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Quit&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;app.quit&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
  &lt;/menu&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        To make the menu appear, we have to load the ui file and
        associate the resulting menu model with the menu button that
        we’ve added to the headerbar. Since menus work by activating
        GActions, we also have to add a suitable set of actions to our
        application.
      </para>
      <para>
        Adding the actions is best done in the <link linkend="startup"><function>startup()</function></link> vfunc, which is
        guaranteed to be called once for each primary application
        instance:
      </para>
      <programlisting>
...

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[] =
{
  { &quot;preferences&quot;, preferences_activated, NULL, NULL, NULL },
  { &quot;quit&quot;, quit_activated, NULL, NULL, NULL }
};

static void
example_app_startup (GApplication *app)
{
  GtkBuilder *builder;
  GMenuModel *app_menu;
  const char *quit_accels[2] = { &quot;&amp;lt;Ctrl&amp;gt;Q&quot;, NULL };

  G_APPLICATION_CLASS (example_app_parent_class)-&gt;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),
                                         &quot;app.quit&quot;,
                                         quit_accels);
}

static void
example_app_class_init (ExampleAppClass *class)
{
  G_APPLICATION_CLASS (class)-&gt;startup = example_app_startup;
  ...
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application4/exampleapp.c">full
        source</ulink>)
      </para>
      <para>
        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 Ctrl-Q shortcut. The shortcut was added
        with <link linkend="gtk-application-set-accels-for-action"><function>gtk_application_set_accels_for_action()</function></link>.
      </para>
      <para>
        The application menu looks like this:
      </para>
      <figure>
        <title>Application window</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app4.png" />
          </imageobject>
          <textobject><phrase>Application window</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
    <sect2>
      <title>A preference dialog</title>
      <para>
        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.
      </para>
      <para>
        We are going to use GSettings to store our preferences.
        GSettings requires a schema that describes our settings:
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;schemalist&gt;
  &lt;schema path=&quot;/org/gtk/exampleapp/&quot; id=&quot;org.gtk.exampleapp&quot;&gt;
    &lt;key name=&quot;font&quot; type=&quot;s&quot;&gt;
      &lt;default&gt;'Monospace 12'&lt;/default&gt;
      &lt;summary&gt;Font&lt;/summary&gt;
      &lt;description&gt;The font to be used for content.&lt;/description&gt;
    &lt;/key&gt;
    &lt;key name=&quot;transition&quot; type=&quot;s&quot;&gt;
      &lt;choices&gt;
        &lt;choice value='none'/&gt;
        &lt;choice value='crossfade'/&gt;
        &lt;choice value='slide-left-right'/&gt;
      &lt;/choices&gt;
      &lt;default&gt;'none'&lt;/default&gt;
      &lt;summary&gt;Transition&lt;/summary&gt;
      &lt;description&gt;The transition to use when switching tabs.&lt;/description&gt;
    &lt;/key&gt;
  &lt;/schema&gt;
&lt;/schemalist&gt;
</programlisting>
      <para>
        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
        <ulink url="https://developer.gnome.org/gio/2.36/ch31s06.html">macros</ulink>
        to do this in autotools-based projects, and the gnome module of
        the meson build system provides the
        <ulink url="https://mesonbuild.com/Gnome-module.html#gnomecompile_schemas">gnome.compile_schemas()</ulink>
        method for this task.
      </para>
      <para>
        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.
      </para>
      <programlisting>
...

static void
example_app_window_init (ExampleAppWindow *win)
{
  gtk_widget_init_template (GTK_WIDGET (win));
  win-&gt;settings = g_settings_new (&quot;org.gtk.exampleapp&quot;);

  g_settings_bind (win-&gt;settings, &quot;transition&quot;,
                   win-&gt;stack, &quot;transition-type&quot;,
                   G_SETTINGS_BIND_DEFAULT);
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application5/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        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.
      </para>
      <para>
        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.
      </para>
      <para>
        Lets start with the template.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;template class=&quot;ExampleAppPrefs&quot; parent=&quot;GtkDialog&quot;&gt;
    &lt;property name=&quot;title&quot; translatable=&quot;yes&quot;&gt;Preferences&lt;/property&gt;
    &lt;property name=&quot;resizable&quot;&gt;0&lt;/property&gt;
    &lt;property name=&quot;modal&quot;&gt;1&lt;/property&gt;
    &lt;child internal-child=&quot;content_area&quot;&gt;
      &lt;object class=&quot;GtkBox&quot; id=&quot;content_area&quot;&gt;
        &lt;child&gt;
          &lt;object class=&quot;GtkGrid&quot; id=&quot;grid&quot;&gt;
            &lt;property name=&quot;margin-start&quot;&gt;12&lt;/property&gt;
            &lt;property name=&quot;margin-end&quot;&gt;12&lt;/property&gt;
            &lt;property name=&quot;margin-top&quot;&gt;12&lt;/property&gt;
            &lt;property name=&quot;margin-bottom&quot;&gt;12&lt;/property&gt;
            &lt;property name=&quot;row-spacing&quot;&gt;12&lt;/property&gt;
            &lt;property name=&quot;column-spacing&quot;&gt;12&lt;/property&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkLabel&quot; id=&quot;fontlabel&quot;&gt;
                &lt;property name=&quot;label&quot;&gt;_Font:&lt;/property&gt;
                &lt;property name=&quot;use-underline&quot;&gt;1&lt;/property&gt;
                &lt;property name=&quot;mnemonic-widget&quot;&gt;font&lt;/property&gt;
                &lt;property name=&quot;xalign&quot;&gt;1&lt;/property&gt;
                &lt;layout&gt;
                  &lt;property name=&quot;column&quot;&gt;0&lt;/property&gt;
                  &lt;property name=&quot;row&quot;&gt;0&lt;/property&gt;
                &lt;/layout&gt;
              &lt;/object&gt;
            &lt;/child&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkFontButton&quot; id=&quot;font&quot;&gt;
                &lt;layout&gt;
                  &lt;property name=&quot;column&quot;&gt;1&lt;/property&gt;
                  &lt;property name=&quot;row&quot;&gt;0&lt;/property&gt;
                &lt;/layout&gt;
              &lt;/object&gt;
            &lt;/child&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkLabel&quot; id=&quot;transitionlabel&quot;&gt;
                &lt;property name=&quot;label&quot;&gt;_Transition:&lt;/property&gt;
                &lt;property name=&quot;use-underline&quot;&gt;1&lt;/property&gt;
                &lt;property name=&quot;mnemonic-widget&quot;&gt;transition&lt;/property&gt;
                &lt;property name=&quot;xalign&quot;&gt;1&lt;/property&gt;
                &lt;layout&gt;
                  &lt;property name=&quot;column&quot;&gt;0&lt;/property&gt;
                  &lt;property name=&quot;row&quot;&gt;1&lt;/property&gt;
                &lt;/layout&gt;
              &lt;/object&gt;
            &lt;/child&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkComboBoxText&quot; id=&quot;transition&quot;&gt;
                &lt;items&gt;
                  &lt;item translatable=&quot;yes&quot; id=&quot;none&quot;&gt;None&lt;/item&gt;
                  &lt;item translatable=&quot;yes&quot; id=&quot;crossfade&quot;&gt;Fade&lt;/item&gt;
                  &lt;item translatable=&quot;yes&quot; id=&quot;slide-left-right&quot;&gt;Slide&lt;/item&gt;
                &lt;/items&gt;
                &lt;layout&gt;
                  &lt;property name=&quot;column&quot;&gt;1&lt;/property&gt;
                  &lt;property name=&quot;row&quot;&gt;1&lt;/property&gt;
                &lt;/layout&gt;
              &lt;/object&gt;
            &lt;/child&gt;
          &lt;/object&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
  &lt;/template&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        Next comes the dialog subclass.
      </para>
      <programlisting language="c">
#include &lt;gtk/gtk.h&gt;

#include &quot;exampleapp.h&quot;
#include &quot;exampleappwin.h&quot;
#include &quot;exampleappprefs.h&quot;

struct _ExampleAppPrefs
{
  GtkDialog parent;

  GSettings *settings;
  GtkWidget *font;
  GtkWidget *transition;
};

G_DEFINE_TYPE (ExampleAppPrefs, example_app_prefs, GTK_TYPE_DIALOG)

static void
example_app_prefs_init (ExampleAppPrefs *prefs)
{
  gtk_widget_init_template (GTK_WIDGET (prefs));
  prefs-&gt;settings = g_settings_new (&quot;org.gtk.exampleapp&quot;);

  g_settings_bind (prefs-&gt;settings, &quot;font&quot;,
                   prefs-&gt;font, &quot;font&quot;,
                   G_SETTINGS_BIND_DEFAULT);
  g_settings_bind (prefs-&gt;settings, &quot;transition&quot;,
                   prefs-&gt;transition, &quot;active-id&quot;,
                   G_SETTINGS_BIND_DEFAULT);
}

static void
example_app_prefs_dispose (GObject *object)
{
  ExampleAppPrefs *prefs;

  prefs = EXAMPLE_APP_PREFS (object);

  g_clear_object (&amp;prefs-&gt;settings);

  G_OBJECT_CLASS (example_app_prefs_parent_class)-&gt;dispose (object);
}

static void
example_app_prefs_class_init (ExampleAppPrefsClass *class)
{
  G_OBJECT_CLASS (class)-&gt;dispose = example_app_prefs_dispose;

  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
                                               &quot;/org/gtk/exampleapp/prefs.ui&quot;);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppPrefs, font);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppPrefs, transition);
}

ExampleAppPrefs *
example_app_prefs_new (ExampleAppWindow *win)
{
  return g_object_new (EXAMPLE_APP_PREFS_TYPE, &quot;transient-for&quot;, win, &quot;use-header-bar&quot;, TRUE, NULL);
}
</programlisting>
      <para>
        Now we revisit the <literal><link linkend="preferences-activated"><function>preferences_activated()</function></link></literal>
        function in our application class, and make it open a new
        preference dialog.
      </para>
      <programlisting>
...

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));
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application6/exampleapp.c">full
        source</ulink>)
      </para>
      <para>
        After all this work, our application can now show a preference
        dialog like this:
      </para>
      <figure>
        <title>Preference dialog</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app6.png" />
          </imageobject>
          <textobject><phrase>Preference dialog</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
    <sect2>
      <title>Adding a search bar</title>
      <para>
        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 to present a search entry.
      </para>
      <para>
        We add a toggle button to the header bar, which can be used to
        slide out the search bar below the header bar.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;template class=&quot;ExampleAppWindow&quot; parent=&quot;GtkApplicationWindow&quot;&gt;
    &lt;property name=&quot;title&quot; translatable=&quot;yes&quot;&gt;Example Application&lt;/property&gt;
    &lt;property name=&quot;default-width&quot;&gt;600&lt;/property&gt;
    &lt;property name=&quot;default-height&quot;&gt;400&lt;/property&gt;
    &lt;child type=&quot;titlebar&quot;&gt;
      &lt;object class=&quot;GtkHeaderBar&quot; id=&quot;header&quot;&gt;
        &lt;child type=&quot;title&quot;&gt;
          &lt;object class=&quot;GtkStackSwitcher&quot; id=&quot;tabs&quot;&gt;
            &lt;property name=&quot;stack&quot;&gt;stack&lt;/property&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child type=&quot;end&quot;&gt;
          &lt;object class=&quot;GtkMenuButton&quot; id=&quot;gears&quot;&gt;
            &lt;property name=&quot;direction&quot;&gt;none&lt;/property&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child type=&quot;end&quot;&gt;
          &lt;object class=&quot;GtkToggleButton&quot; id=&quot;search&quot;&gt;
            &lt;property name=&quot;sensitive&quot;&gt;0&lt;/property&gt;
            &lt;property name=&quot;icon-name&quot;&gt;edit-find-symbolic&lt;/property&gt;
          &lt;/object&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
    &lt;child&gt;
      &lt;object class=&quot;GtkBox&quot; id=&quot;content_box&quot;&gt;
        &lt;property name=&quot;orientation&quot;&gt;vertical&lt;/property&gt;
        &lt;child&gt;
          &lt;object class=&quot;GtkSearchBar&quot; id=&quot;searchbar&quot;&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkSearchEntry&quot; id=&quot;searchentry&quot;&gt;
                &lt;signal name=&quot;search-changed&quot; handler=&quot;search_text_changed&quot;/&gt;
              &lt;/object&gt;
            &lt;/child&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child&gt;
          &lt;object class=&quot;GtkStack&quot; id=&quot;stack&quot;&gt;
            &lt;signal name=&quot;notify::visible-child&quot; handler=&quot;visible_child_changed&quot;/&gt;
          &lt;/object&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
  &lt;/template&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        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.
      </para>
      <programlisting>
...

static void
search_text_changed (GtkEntry         *entry,
                     ExampleAppWindow *win)
{
  const char *text;
  GtkWidget *tab;
  GtkWidget *view;
  GtkTextBuffer *buffer;
  GtkTextIter start, match_start, match_end;

  text = gtk_editable_get_text (GTK_EDITABLE (entry));

  if (text[0] == '\0')
    return;

  tab = gtk_stack_get_visible_child (GTK_STACK (win-&gt;stack));
  view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));

  /* Very simple-minded search implementation */
  gtk_text_buffer_get_start_iter (buffer, &amp;start);
  if (gtk_text_iter_forward_search (&amp;start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
                                    &amp;match_start, &amp;match_end, NULL))
    {
      gtk_text_buffer_select_range (buffer, &amp;match_start, &amp;match_end);
      gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &amp;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);

...

}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application7/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        With the search bar, our application now looks like this:
      </para>
      <figure>
        <title>A search bar</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app7.png" />
          </imageobject>
          <textobject><phrase>A search bar</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
    <sect2>
      <title>Adding a side bar</title>
      <para>
        As another piece of functionality, we are adding a sidebar,
        which demonstrates GtkMenuButton, GtkRevealer and GtkListBox.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;template class=&quot;ExampleAppWindow&quot; parent=&quot;GtkApplicationWindow&quot;&gt;
    &lt;property name=&quot;title&quot; translatable=&quot;yes&quot;&gt;Example Application&lt;/property&gt;
    &lt;property name=&quot;default-width&quot;&gt;600&lt;/property&gt;
    &lt;property name=&quot;default-height&quot;&gt;400&lt;/property&gt;
    &lt;child type=&quot;titlebar&quot;&gt;
      &lt;object class=&quot;GtkHeaderBar&quot; id=&quot;header&quot;&gt;
        &lt;child type=&quot;title&quot;&gt;
          &lt;object class=&quot;GtkStackSwitcher&quot; id=&quot;tabs&quot;&gt;
            &lt;property name=&quot;stack&quot;&gt;stack&lt;/property&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child type=&quot;end&quot;&gt;
          &lt;object class=&quot;GtkToggleButton&quot; id=&quot;search&quot;&gt;
            &lt;property name=&quot;sensitive&quot;&gt;0&lt;/property&gt;
            &lt;property name=&quot;icon-name&quot;&gt;edit-find-symbolic&lt;/property&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child type=&quot;end&quot;&gt;
          &lt;object class=&quot;GtkMenuButton&quot; id=&quot;gears&quot;&gt;
            &lt;property name=&quot;direction&quot;&gt;none&lt;/property&gt;
          &lt;/object&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
    &lt;child&gt;
      &lt;object class=&quot;GtkBox&quot; id=&quot;content_box&quot;&gt;
        &lt;property name=&quot;orientation&quot;&gt;vertical&lt;/property&gt;
        &lt;child&gt;
          &lt;object class=&quot;GtkSearchBar&quot; id=&quot;searchbar&quot;&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkSearchEntry&quot; id=&quot;searchentry&quot;&gt;
                &lt;signal name=&quot;search-changed&quot; handler=&quot;search_text_changed&quot;/&gt;
              &lt;/object&gt;
            &lt;/child&gt;
          &lt;/object&gt;
        &lt;/child&gt;
        &lt;child&gt;
          &lt;object class=&quot;GtkBox&quot; id=&quot;hbox&quot;&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkRevealer&quot; id=&quot;sidebar&quot;&gt;
                &lt;property name=&quot;transition-type&quot;&gt;slide-right&lt;/property&gt;
                &lt;child&gt;
                  &lt;object class=&quot;GtkScrolledWindow&quot; id=&quot;sidebar-sw&quot;&gt;
                    &lt;property name=&quot;hscrollbar-policy&quot;&gt;never&lt;/property&gt;
                    &lt;child&gt;
                      &lt;object class=&quot;GtkListBox&quot; id=&quot;words&quot;&gt;
                        &lt;property name=&quot;selection-mode&quot;&gt;none&lt;/property&gt;
                      &lt;/object&gt;
                    &lt;/child&gt;
                  &lt;/object&gt;
                &lt;/child&gt;
              &lt;/object&gt;
            &lt;/child&gt;
            &lt;child&gt;
              &lt;object class=&quot;GtkStack&quot; id=&quot;stack&quot;&gt;
                &lt;signal name=&quot;notify::visible-child&quot; handler=&quot;visible_child_changed&quot;/&gt;
              &lt;/object&gt;
            &lt;/child&gt;
          &lt;/object&gt;
        &lt;/child&gt;
      &lt;/object&gt;
    &lt;/child&gt;
  &lt;/template&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        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 a checkbutton for the new feature
        to the menu.
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;menu id=&quot;menu&quot;&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Words&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;win.show-words&lt;/attribute&gt;
      &lt;/item&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Preferences&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;app.preferences&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Quit&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;app.quit&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
  &lt;/menu&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        To connect the menuitem to the show-words setting, we use a
        GAction corresponding to the given GSettings key.
      </para>
      <programlisting>
...

static void
example_app_window_init (ExampleAppWindow *win)
{

...

  builder = gtk_builder_new_from_resource (&quot;/org/gtk/exampleapp/gears-menu.ui&quot;);
  menu = G_MENU_MODEL (gtk_builder_get_object (builder, &quot;menu&quot;));
  gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv-&gt;gears), menu);
  g_object_unref (builder);

  action = g_settings_create_action (priv-&gt;settings, &quot;show-words&quot;);
  g_action_map_add_action (G_ACTION_MAP (win), action);
  g_object_unref (action);
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application8/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        What our application looks like now:
      </para>
      <figure>
        <title>A sidebar</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app8.png" />
          </imageobject>
          <textobject><phrase>A sidebar</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
    <sect2>
      <title>Properties</title>
      <para>
        Widgets and other objects have many useful properties.
      </para>
      <para>
        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.
      </para>
      <para>
        To set this up, we add two labels to the header bar in our
        window template, named <literal>lines_label</literal> and
        <literal>lines</literal>, and bind them to struct members in the
        private struct, as we’ve seen a couple of times by now.
      </para>
      <para>
        We add a new <quote>Lines</quote> menu item to the gears menu,
        which triggers the show-lines action:
      </para>
      <programlisting language="xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;interface&gt;
  &lt;menu id=&quot;menu&quot;&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Words&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;win.show-words&lt;/attribute&gt;
      &lt;/item&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Lines&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;win.show-lines&lt;/attribute&gt;
      &lt;/item&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Preferences&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;app.preferences&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name=&quot;label&quot; translatable=&quot;yes&quot;&gt;_Quit&lt;/attribute&gt;
        &lt;attribute name=&quot;action&quot;&gt;app.quit&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
  &lt;/menu&gt;
&lt;/interface&gt;
</programlisting>
      <para>
        To make this menu item do something, we create a property action
        for the visible property of the <literal>lines</literal> 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.
      </para>
      <para>
        Since we want both labels to appear and disappear together, we
        bind the visible property of the <literal>lines_label</literal>
        widget to the same property of the <literal>lines</literal>
        widget.
      </para>
      <programlisting>
...

static void
example_app_window_init (ExampleAppWindow *win)
{
  ...

  action = (GAction*) g_property_action_new (&quot;show-lines&quot;, win-&gt;lines, &quot;visible&quot;);
  g_action_map_add_action (G_ACTION_MAP (win), action);
  g_object_unref (action);

  g_object_bind_property (win-&gt;lines, &quot;visible&quot;,
                          win-&gt;lines_label, &quot;visible&quot;,
                          G_BINDING_DEFAULT);
}

...
</programlisting>
      <para>
        (<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application9/exampleappwin.c">full
        source</ulink>)
      </para>
      <para>
        We also need a function that counts the lines of the currently
        active tab, and updates the <literal>lines</literal> label. See
        the
        <ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application9/exampleappwin.c">full
        source</ulink> if you are interested in the details.
      </para>
      <para>
        This brings our example application to this appearance:
      </para>
      <figure>
        <title>Full application</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="getting-started-app9.png" />
          </imageobject>
          <textobject><phrase>Full application</phrase></textobject>
        </mediaobject>
      </figure>
    </sect2>
  </sect1>
</chapter>
