1Title: Getting Started with GTK
2Slug: gtk-getting-started
3
4GTK is a [widget toolkit](http://en.wikipedia.org/wiki/Widget_toolkit).
5Each user interface created by GTK consists of widgets. This is implemented
6in C using [GObject](#gobject), an object-oriented framework for C. Widgets
7are organized in a hierarchy. The window widget is the main container.
8The user interface is then built by adding buttons, drop-down menus, input
9fields, and other widgets to the window. If you are creating complex user
10interfaces it is recommended to use GtkBuilder and its GTK-specific markup
11description language, instead of assembling the interface manually. You can
12also use a visual user interface editor, like [glade](https://glade.gnome.org/).
13
14GTK is event-driven. The toolkit listens for events such as a click
15on a button, and passes the event to your application.
16
17This chapter contains some tutorial information to get you started with
18GTK programming. It assumes that you have GTK, its dependencies and a C
19compiler installed and ready to use. If you need to build GTK itself first,
20refer to the [Compiling the GTK libraries](#gtk-compiling) section in this
21reference.
22
23## Basics
24
25To begin our introduction to GTK, we'll start with a very simple
26application. This program will create an empty 200 × 200 pixel
27window.
28
29![A window](window-default.png)
30
31Create a new file with the following content named `example-0.c`.
32
33```c
34#include <gtk/gtk.h>
35
36static void
37activate (GtkApplication* app,
38          gpointer        user_data)
39{
40  GtkWidget *window;
41
42  window = gtk_application_window_new (app);
43  gtk_window_set_title (GTK_WINDOW (window), "Window");
44  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
45  gtk_widget_show (window);
46}
47
48int
49main (int    argc,
50      char **argv)
51{
52  GtkApplication *app;
53  int status;
54
55  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
56  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
57  status = g_application_run (G_APPLICATION (app), argc, argv);
58  g_object_unref (app);
59
60  return status;
61}
62```
63
64You can compile the program above with GCC using:
65
66```
67gcc $( pkg-config --cflags gtk4 ) -o example-0 example-0.c $( pkg-config --libs gtk4 )
68```
69
70For more information on how to compile a GTK application, please
71refer to the [Compiling GTK Applications](#gtk-compiling)
72section in this reference.
73
74All GTK applications will, of course, include `gtk/gtk.h`, which declares
75functions, types and macros required by GTK applications.
76
77Even if GTK installs multiple header files, only the top-level `gtk/gtk.h`
78header can be directly included by third-party code. The compiler will abort
79with an error if any other header is directly included.
80
81In a GTK application, the purpose of the `main()` function is to create a
82[class@Gtk.Application] object and run it. In this example a
83[class@Gtk.Application] pointer named `app` is declared and then initialized
84using `gtk_application_new()`.
85
86When creating a [class@Gtk.Application], you need to pick an application
87identifier (a name) and pass it to [ctor@Gtk.Application.new] as parameter. For
88this example `org.gtk.example` is used. For choosing an identifier for your
89application, see [this guide](https://wiki.gnome.org/HowDoI/ChooseApplicationID).
90Lastly, [ctor@Gtk.Application.new] takes `GApplicationFlags` as input
91for your application, if your application would have special needs.
92
93Next the [activate signal](https://wiki.gnome.org/HowDoI/GtkApplication) is
94connected to the activate() function above the `main()` function. The `activate`
95signal will be emitted when your application is launched with `g_application_run()`
96on the line below. The `g_application_run()` call also takes as arguments the
97command line arguments (the `argc` count and the `argv` string array).
98Your application can override the command line handling, e.g. to open
99files passed on the commandline.
100
101Within `g_application_run()` the activate signal is sent and we then proceed
102into the activate() function of the application. This is where we construct
103our GTK window, so that a window is shown when the application is launched.
104The call to [ctor@Gtk.ApplicationWindow.new] will create a new
105[class@Gtk.ApplicationWindow] and store it inside the `window` pointer. The
106window will have a frame, a title bar, and window controls depending on the
107platform.
108
109A window title is set using [method@Gtk.Window.set_title]. This function
110takes a `GtkWindow` pointer and a string as input. As our `window` pointer
111is a `GtkWidget` pointer, we need to cast it to `GtkWindow`; instead of
112casting `window` via a typical C cast like `(GtkWindow*)`, `window` can be
113cast using the macro `GTK_WINDOW()`. `GTK_WINDOW()` will check if the
114pointer is an instance of the `GtkWindow` class, before casting, and emit a
115warning if the check fails. More information about this convention can be
116found [here](https://developer.gnome.org/gobject/stable/gtype-conventions.html).
117
118Finally the window size is set using [method@Gtk.Window.set_default_size]
119and the window is then shown by GTK via [method@Gtk.Widget.show].
120
121When you close the window, by (for example) pressing the X button, the
122`g_application_run()` call returns with a number which is saved inside an
123integer variable named `status`. Afterwards, the `GtkApplication` object is
124freed from memory with `g_object_unref()`. Finally the status integer is
125returned and the application exits.
126
127While the program is running, GTK is receiving _events_. These are typically
128input events caused by the user interacting with your program, but also things
129like messages from the window manager or other applications. GTK processes
130these and as a result, _signals_ may be emitted on your widgets. Connecting
131handlers for these signals is how you normally make your program do something
132in response to user input.
133
134The following example is slightly more complex, and tries to
135showcase some of the capabilities of GTK.
136
137## Hello, World
138
139In the long tradition of programming languages and libraries,
140this example is called *Hello, World*.
141
142![Hello, world](hello-world.png)
143
144### Hello World in C
145
146Create a new file with the following content named `example-1.c`.
147
148```c
149#include <gtk/gtk.h>
150
151static void
152print_hello (GtkWidget *widget,
153             gpointer   data)
154{
155  g_print ("Hello World\n");
156}
157
158static void
159activate (GtkApplication *app,
160          gpointer        user_data)
161{
162  GtkWidget *window;
163  GtkWidget *button;
164
165  window = gtk_application_window_new (app);
166  gtk_window_set_title (GTK_WINDOW (window), "Window");
167  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
168
169  button = gtk_button_new_with_label ("Hello World");
170  gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
171  gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
172
173  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
174  g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
175
176  gtk_window_set_child (GTK_WINDOW (window), button);
177
178  gtk_widget_show (window);
179}
180
181int
182main (int    argc,
183      char **argv)
184{
185  GtkApplication *app;
186  int status;
187
188  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
189  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
190  status = g_application_run (G_APPLICATION (app), argc, argv);
191  g_object_unref (app);
192
193  return status;
194}
195
196```
197
198You can compile the program above with GCC using:
199
200```
201gcc $( pkg-config --cflags gtk4 ) -o example-1 example-1.c $( pkg-config --libs gtk4 )
202```
203
204As seen above, `example-1.c` builds further upon `example-0.c` by adding a
205button to our window, with the label "Hello World". Two new `GtkWidget`
206pointers are declared to accomplish this, `button` and `box`. The box
207variable is created to store a [class@Gtk.Box], which is GTK's way of
208controlling the size and layout of buttons.
209
210The `GtkBox` widget is created with [ctor@Gtk.Box.new], which takes a
211[enum@Gtk.Orientation] enumeration value as parameter. The buttons which
212this box will contain can either be laid out horizontally or vertically.
213This does not matter in this particular case, as we are dealing with only
214one button. After initializing box with the newly created `GtkBox`, the code
215adds the box widget to the window widget using [method@Gtk.Window.set_child].
216
217Next the `button` variable is initialized in similar manner.
218[ctor@Gtk.Button.new_with_label] is called which returns a
219[class@Gtk.Button] to be stored in `button`. Afterwards `button` is added to
220our `box`.
221
222Using `g_signal_connect()`, the button is connected to a function in our app called
223`print_hello()`, so that when the button is clicked, GTK will call this function.
224As the `print_hello()` function does not use any data as input, `NULL` is passed
225to it. `print_hello()` calls `g_print()` with the string "Hello World" which will
226print Hello World in a terminal if the GTK application was started from one.
227
228After connecting `print_hello()`, another signal is connected to the "clicked"
229state of the button using `g_signal_connect_swapped()`. This functions is similar
230to a `g_signal_connect()`, with the difference lying in how the callback function
231is treated; `g_signal_connect_swapped()` allows you to specify what the callback
232function should take as parameter by letting you pass it as data. In this case
233the function being called back is [method@Gtk.Window.destroy] and the `window` pointer
234is passed to it. This has the effect that when the button is clicked, the whole
235GTK window is destroyed. In contrast if a normal `g_signal_connect()` were used
236to connect the "clicked" signal with [method@Gtk.Window.destroy], then the function
237would be called on `button` (which would not go well, since the function expects
238a `GtkWindow` as argument).
239
240More information about creating buttons can be found
241[here](https://wiki.gnome.org/HowDoI/Buttons).
242
243The rest of the code in `example-1.c` is identical to `example-0.c`. The next
244section will elaborate further on how to add several GtkWidgets to your GTK
245application.
246
247## Packing
248
249When creating an application, you'll want to put more than one widget inside
250a window. When you do so, it becomes important to control how each widget is
251positioned and sized. This is where packing comes in.
252
253GTK comes with a large variety of _layout containers_ whose purpose it
254is to control the layout of the child widgets that are added to them.
255See [Layout containers](#LayoutContainers) for an overview.
256
257The following example shows how the GtkGrid container lets you
258arrange several buttons:
259
260![Grid packing](grid-packing.png)
261
262### Packing buttons
263
264Create a new file with the following content named `example-2.c`.
265
266```c
267#include <gtk/gtk.h>
268
269static void
270print_hello (GtkWidget *widget,
271             gpointer   data)
272{
273  g_print ("Hello World\n");
274}
275
276static void
277activate (GtkApplication *app,
278          gpointer        user_data)
279{
280  GtkWidget *window;
281  GtkWidget *grid;
282  GtkWidget *button;
283
284  /* create a new window, and set its title */
285  window = gtk_application_window_new (app);
286  gtk_window_set_title (GTK_WINDOW (window), "Window");
287
288  /* Here we construct the container that is going pack our buttons */
289  grid = gtk_grid_new ();
290
291  /* Pack the container in the window */
292  gtk_window_set_child (GTK_WINDOW (window), grid);
293
294  button = gtk_button_new_with_label ("Button 1");
295  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
296
297  /* Place the first button in the grid cell (0, 0), and make it fill
298   * just 1 cell horizontally and vertically (ie no spanning)
299   */
300  gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
301
302  button = gtk_button_new_with_label ("Button 2");
303  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
304
305  /* Place the second button in the grid cell (1, 0), and make it fill
306   * just 1 cell horizontally and vertically (ie no spanning)
307   */
308  gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
309
310  button = gtk_button_new_with_label ("Quit");
311  g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
312
313  /* Place the Quit button in the grid cell (0, 1), and make it
314   * span 2 columns.
315   */
316  gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 2, 1);
317
318  gtk_widget_show (window);
319
320}
321
322int
323main (int    argc,
324      char **argv)
325{
326  GtkApplication *app;
327  int status;
328
329  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
330  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
331  status = g_application_run (G_APPLICATION (app), argc, argv);
332  g_object_unref (app);
333
334  return status;
335}
336```
337
338You can compile the program above with GCC using:
339
340```
341gcc $( pkg-config --cflags gtk4 ) -o example-2 example-2.c $( pkg-config --libs gtk4 )
342```
343
344## Custom Drawing
345
346Many widgets, like buttons, do all their drawing themselves. You just tell
347them the label you want to see, and they figure out what font to use, draw
348the button outline and focus rectangle, etc. Sometimes, it is necessary to
349do some custom drawing. In that case, a [class@Gtk.DrawingArea] might be the right
350widget to use. It offers a canvas on which you can draw by setting its
351draw function.
352
353The contents of a widget often need to be partially or fully redrawn, e.g.
354when another window is moved and uncovers part of the widget, or when the
355window containing it is resized. It is also possible to explicitly cause a
356widget to be redrawn, by calling [method@Gtk.Widget.queue_draw]. GTK takes
357care of most of the details by providing a ready-to-use cairo context to the
358draw function.
359
360The following example shows how to use a draw function with GtkDrawingArea.
361It is a bit more complicated than the previous examples, since it also
362demonstrates input event handling with event controllers.
363
364![Drawing](drawing.png)
365
366### Drawing in response to input
367
368Create a new file with the following content named `example-4.c`.
369
370```c
371#include <gtk/gtk.h>
372
373/* Surface to store current scribbles */
374static cairo_surface_t *surface = NULL;
375
376static void
377clear_surface (void)
378{
379  cairo_t *cr;
380
381  cr = cairo_create (surface);
382
383  cairo_set_source_rgb (cr, 1, 1, 1);
384  cairo_paint (cr);
385
386  cairo_destroy (cr);
387}
388
389/* Create a new surface of the appropriate size to store our scribbles */
390static void
391resize_cb (GtkWidget *widget,
392           int        width,
393           int        height,
394           gpointer   data)
395{
396  if (surface)
397    {
398      cairo_surface_destroy (surface);
399      surface = NULL;
400    }
401
402  if (gtk_native_get_surface (gtk_widget_get_native (widget)))
403    {
404      surface = gdk_surface_create_similar_surface (gtk_native_get_surface (gtk_widget_get_native (widget)),
405                                                   CAIRO_CONTENT_COLOR,
406                                                   gtk_widget_get_width (widget),
407                                                   gtk_widget_get_height (widget));
408
409      /* Initialize the surface to white */
410      clear_surface ();
411    }
412}
413
414/* Redraw the screen from the surface. Note that the draw
415 * callback receives a ready-to-be-used cairo_t that is already
416 * clipped to only draw the exposed areas of the widget
417 */
418static void
419draw_cb (GtkDrawingArea *drawing_area,
420         cairo_t        *cr,
421         int             width,
422         int             height,
423         gpointer        data)
424{
425  cairo_set_source_surface (cr, surface, 0, 0);
426  cairo_paint (cr);
427}
428
429/* Draw a rectangle on the surface at the given position */
430static void
431draw_brush (GtkWidget *widget,
432            double     x,
433            double     y)
434{
435  cairo_t *cr;
436
437  /* Paint to the surface, where we store our state */
438  cr = cairo_create (surface);
439
440  cairo_rectangle (cr, x - 3, y - 3, 6, 6);
441  cairo_fill (cr);
442
443  cairo_destroy (cr);
444
445  /* Now invalidate the drawing area. */
446  gtk_widget_queue_draw (widget);
447}
448
449static double start_x;
450static double start_y;
451
452static void
453drag_begin (GtkGestureDrag *gesture,
454            double          x,
455            double          y,
456            GtkWidget      *area)
457{
458  start_x = x;
459  start_y = y;
460
461  draw_brush (area, x, y);
462}
463
464static void
465drag_update (GtkGestureDrag *gesture,
466             double          x,
467             double          y,
468             GtkWidget      *area)
469{
470  draw_brush (area, start_x + x, start_y + y);
471}
472
473static void
474drag_end (GtkGestureDrag *gesture,
475          double          x,
476          double          y,
477          GtkWidget      *area)
478{
479  draw_brush (area, start_x + x, start_y + y);
480}
481
482static void
483pressed (GtkGestureClick *gesture,
484         int              n_press,
485         double           x,
486         double           y,
487         GtkWidget       *area)
488{
489  clear_surface ();
490  gtk_widget_queue_draw (area);
491}
492
493static void
494close_window (void)
495{
496  if (surface)
497    cairo_surface_destroy (surface);
498}
499
500static void
501activate (GtkApplication *app,
502          gpointer        user_data)
503{
504  GtkWidget *window;
505  GtkWidget *frame;
506  GtkWidget *drawing_area;
507  GtkGesture *drag;
508  GtkGesture *press;
509
510  window = gtk_application_window_new (app);
511  gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");
512
513  g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
514
515  frame = gtk_frame_new (NULL);
516  gtk_window_set_child (GTK_WINDOW (window), frame);
517
518  drawing_area = gtk_drawing_area_new ();
519  /* set a minimum size */
520  gtk_widget_set_size_request (drawing_area, 100, 100);
521
522  gtk_frame_set_child (GTK_FRAME (frame), drawing_area);
523
524  gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area), draw_cb, NULL, NULL);
525
526  g_signal_connect_after (drawing_area, "resize", G_CALLBACK (resize_cb), NULL);
527
528  drag = gtk_gesture_drag_new ();
529  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
530  gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (drag));
531  g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), drawing_area);
532  g_signal_connect (drag, "drag-update", G_CALLBACK (drag_update), drawing_area);
533  g_signal_connect (drag, "drag-end", G_CALLBACK (drag_end), drawing_area);
534
535  press = gtk_gesture_click_new ();
536  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (press), GDK_BUTTON_SECONDARY);
537  gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (press));
538
539  g_signal_connect (press, "pressed", G_CALLBACK (pressed), drawing_area);
540
541  gtk_widget_show (window);
542}
543
544int
545main (int    argc,
546      char **argv)
547{
548  GtkApplication *app;
549  int status;
550
551  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
552  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
553  status = g_application_run (G_APPLICATION (app), argc, argv);
554  g_object_unref (app);
555
556  return status;
557}
558```
559
560You can compile the program above with GCC using:
561
562```
563gcc $( pkg-config --cflags gtk4 ) -o example-4 example-4.c $( pkg-config --libs gtk4 )
564```
565
566## Building user interfaces
567
568When constructing a more complicated user interface, with dozens
569or hundreds of widgets, doing all the setup work in C code is
570cumbersome, and making changes becomes next to impossible.
571
572Thankfully, GTK supports the separation of user interface
573layout from your business logic, by using UI descriptions in an
574XML format that can be parsed by the [class@Gtk.Builder] class.
575
576### Packing buttons with GtkBuilder
577
578Create a new file with the following content named `example-3.c`.
579
580```c
581#include <gtk/gtk.h>
582#include <glib/gstdio.h>
583
584static void
585print_hello (GtkWidget *widget,
586             gpointer   data)
587{
588  g_print ("Hello World\n");
589}
590
591static void
592quit_cb (GtkWindow *window)
593{
594  gtk_window_close (window);
595}
596
597static void
598activate (GtkApplication *app,
599          gpointer        user_data)
600{
601  /* Construct a GtkBuilder instance and load our UI description */
602  GtkBuilder *builder = gtk_builder_new ();
603  gtk_builder_add_from_file (builder, "builder.ui", NULL);
604
605  /* Connect signal handlers to the constructed widgets. */
606  GObject *window = gtk_builder_get_object (builder, "window");
607  gtk_window_set_application (GTK_WINDOW (window), app);
608
609  GObject *button = gtk_builder_get_object (builder, "button1");
610  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
611
612  button = gtk_builder_get_object (builder, "button2");
613  g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
614
615  button = gtk_builder_get_object (builder, "quit");
616  g_signal_connect_swapped (button, "clicked", G_CALLBACK (quit_cb), window);
617
618  gtk_widget_show (GTK_WIDGET (window));
619
620  /* We do not need the builder any more */
621  g_object_unref (builder);
622}
623
624int
625main (int   argc,
626      char *argv[])
627{
628#ifdef GTK_SRCDIR
629  g_chdir (GTK_SRCDIR);
630#endif
631
632  GtkApplication *app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
633  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
634
635  int status = g_application_run (G_APPLICATION (app), argc, argv);
636  g_object_unref (app);
637
638  return status;
639}
640```
641
642Create a new file with the following content named `builder.ui`.
643
644```xml
645<?xml version="1.0" encoding="UTF-8"?>
646<interface>
647  <object id="window" class="GtkWindow">
648    <property name="title">Grid</property>
649    <child>
650      <object id="grid" class="GtkGrid">
651        <child>
652          <object id="button1" class="GtkButton">
653            <property name="label">Button 1</property>
654            <layout>
655              <property name="column">0</property>
656              <property name="row">0</property>
657            </layout>
658          </object>
659        </child>
660        <child>
661          <object id="button2" class="GtkButton">
662            <property name="label">Button 2</property>
663            <layout>
664              <property name="column">1</property>
665              <property name="row">0</property>
666            </layout>
667          </object>
668        </child>
669        <child>
670          <object id="quit" class="GtkButton">
671            <property name="label">Quit</property>
672            <layout>
673              <property name="column">0</property>
674              <property name="row">1</property>
675              <property name="column-span">2</property>
676            </layout>
677          </object>
678        </child>
679      </object>
680    </child>
681  </object>
682</interface>
683```
684
685You can compile the program above with GCC using:
686
687```
688gcc $( pkg-config --cflags gtk4 ) -o example-3 example-3.c $( pkg-config --libs gtk4 )
689```
690
691Note that `GtkBuilder` can also be used to construct objects that are
692not widgets, such as tree models, adjustments, etc. That is the reason
693the method we use here is called [method@Gtk.Builder.get_object] and returns
694a `GObject` instead of a `GtkWidget`.
695
696Normally, you would pass a full path to [method@Gtk.Builder.add_from_file] to
697make the execution of your program independent of the current directory.
698A common location to install UI descriptions and similar data is
699`/usr/share/appname`.
700
701It is also possible to embed the UI description in the source code as a
702string and use [method@Gtk.Builder.add_from_string] to load it. But keeping the
703UI description in a separate file has several advantages: It is then possible
704to make minor adjustments to the UI without recompiling your program, and,
705more importantly, graphical UI editors such as [Glade](http://glade.gnome.org)
706can load the file and allow you to create and modify your UI by point-and-click.
707
708## Building applications
709
710An application consists of a number of files:
711
712The binary
713 : This gets installed in `/usr/bin`.
714
715A desktop file
716 : The desktop file provides important information about the application to
717   the desktop shell, such as its name, icon, D-Bus name, commandline to launch
718   it, etc. It is installed in `/usr/share/applications`.
719
720An icon
721 : The icon gets installed in `/usr/share/icons/hicolor/48x48/apps`, where it
722   will be found regardless of the current theme.
723
724A settings schema
725 : If the application uses GSettings, it will install its schema in
726   `/usr/share/glib-2.0/schemas`, so that tools like dconf-editor can find it.
727
728Other resources
729 : Other files, such as GtkBuilder ui files, are best loaded from
730   resources stored in the application binary itself. This eliminates the
731   need for most of the files that would traditionally be installed in
732   an application-specific location in `/usr/share`.
733
734GTK includes application support that is built on top of `GApplication`. In this
735tutorial we'll build a simple application by starting from scratch, adding more
736and more pieces over time. Along the way, we'll learn about [class@Gtk.Application],
737templates, resources, application menus, settings, [class@Gtk.HeaderBar], [class@Gtk.Stack],
738[class@Gtk.SearchBar], [class@Gtk.ListBox], and more.
739
740The full, buildable sources for these examples can be found in the
741`examples` directory of the GTK source distribution, or
742[online](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples) in the GTK
743source code repository. You can build each example separately by using make
744with the `Makefile.example` file. For more information, see the `README`
745included in the examples directory.
746
747### A trivial application
748
749When using `GtkApplication`, the `main()` function can be very simple. We just call
750`g_application_run()` and give it an instance of our application class.
751
752```c
753#include <gtk/gtk.h>
754
755#include "exampleapp.h"
756
757int
758main (int argc, char *argv[])
759{
760  return g_application_run (G_APPLICATION (example_app_new ()), argc, argv);
761}
762```
763
764All the application logic is in the application class, which is a subclass of
765GtkApplication. Our example does not yet have any interesting functionality.
766All it does is open a window when it is activated without arguments, and open
767the files it is given, if it is started with arguments.
768
769To handle these two cases, we override the activate() vfunc, which gets
770called when the application is launched without commandline arguments, and
771the `open()` virtual function, which gets called when the application is
772launched with commandline arguments.
773
774To learn more about `GApplication` entry points, consult the GIO
775[documentation](https://developer.gnome.org/gio/stable/GApplication.html#GApplication.description).
776
777```c
778#include <gtk/gtk.h>
779
780#include "exampleapp.h"
781#include "exampleappwin.h"
782
783struct _ExampleApp
784{
785  GtkApplication parent;
786};
787
788G_DEFINE_TYPE(ExampleApp, example_app, GTK_TYPE_APPLICATION);
789
790static void
791example_app_init (ExampleApp *app)
792{
793}
794
795static void
796example_app_activate (GApplication *app)
797{
798  ExampleAppWindow *win;
799
800  win = example_app_window_new (EXAMPLE_APP (app));
801  gtk_window_present (GTK_WINDOW (win));
802}
803
804static void
805example_app_open (GApplication  *app,
806                  GFile        **files,
807                  int            n_files,
808                  const char    *hint)
809{
810  GList *windows;
811  ExampleAppWindow *win;
812  int i;
813
814  windows = gtk_application_get_windows (GTK_APPLICATION (app));
815  if (windows)
816    win = EXAMPLE_APP_WINDOW (windows->data);
817  else
818    win = example_app_window_new (EXAMPLE_APP (app));
819
820  for (i = 0; i < n_files; i++)
821    example_app_window_open (win, files[i]);
822
823  gtk_window_present (GTK_WINDOW (win));
824}
825
826static void
827example_app_class_init (ExampleAppClass *class)
828{
829  G_APPLICATION_CLASS (class)->activate = example_app_activate;
830  G_APPLICATION_CLASS (class)->open = example_app_open;
831}
832
833ExampleApp *
834example_app_new (void)
835{
836  return g_object_new (EXAMPLE_APP_TYPE,
837                       "application-id", "org.gtk.exampleapp",
838                       "flags", G_APPLICATION_HANDLES_OPEN,
839                       NULL);
840}
841```
842
843Another important class that is part of the application support in GTK is
844`GtkApplicationWindow`. It is typically subclassed as well. Our subclass does
845not do anything yet, so we will just get an empty window.
846
847```c
848#include <gtk/gtk.h>
849
850#include "exampleapp.h"
851#include "exampleappwin.h"
852
853struct _ExampleAppWindow
854{
855  GtkApplicationWindow parent;
856};
857
858G_DEFINE_TYPE(ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW);
859
860static void
861example_app_window_init (ExampleAppWindow *app)
862{
863}
864
865static void
866example_app_window_class_init (ExampleAppWindowClass *class)
867{
868}
869
870ExampleAppWindow *
871example_app_window_new (ExampleApp *app)
872{
873  return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
874}
875
876void
877example_app_window_open (ExampleAppWindow *win,
878                         GFile            *file)
879{
880}
881```
882
883As part of the initial setup of our application, we also
884create an icon and a desktop file.
885
886![An icon](exampleapp.png)
887
888```
889[Desktop Entry]
890Type=Application
891Name=Example
892Icon=exampleapp
893StartupNotify=true
894Exec=@bindir@/exampleapp
895```
896
897Note that `@bindir@` needs to be replaced with the actual path to the binary
898before this desktop file can be used.
899
900Here is what we've achieved so far:
901
902![An application](getting-started-app1.png)
903
904This does not look very impressive yet, but our application is already
905presenting itself on the session bus, it has single-instance semantics,
906and it accepts files as commandline arguments.
907
908### Populating the window
909
910In this step, we use a GtkBuilder template to associate a
911GtkBuilder ui file with our application window class.
912
913Our simple ui file gives the window a title, and puts a GtkStack
914widget as the main content.
915
916```xml
917<?xml version="1.0" encoding="UTF-8"?>
918<interface>
919  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
920    <property name="title" translatable="yes">Example Application</property>
921    <property name="default-width">600</property>
922    <property name="default-height">400</property>
923    <child>
924      <object class="GtkBox" id="content_box">
925        <property name="orientation">vertical</property>
926        <child>
927          <object class="GtkStack" id="stack"/>
928        </child>
929      </object>
930    </child>
931  </template>
932</interface>
933```
934
935To make use of this file in our application, we revisit our
936`GtkApplicationWindow` subclass, and call
937`gtk_widget_class_set_template_from_resource()` from the class init
938function to set the ui file as template for this class. We also
939add a call to `gtk_widget_init_template()` in the instance init
940function to instantiate the template for each instance of our
941class.
942
943```c
944 ...
945
946static void
947example_app_window_init (ExampleAppWindow *win)
948{
949  gtk_widget_init_template (GTK_WIDGET (win));
950}
951
952static void
953example_app_window_class_init (ExampleAppWindowClass *class)
954{
955  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
956                                               "/org/gtk/exampleapp/window.ui");
957}
958
959 ...
960```
961
962([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application2/exampleappwin.c))
963
964You may have noticed that we used the `_from_resource()` variant of the function
965that sets a template. Now we need to use
966[GLib's resource functionality](https://developer.gnome.org/gio/stable/GResource.html)
967to include the ui file in the binary. This is commonly done by listing all resources
968in a `.gresource.xml` file, such as this:
969
970```c
971<?xml version="1.0" encoding="UTF-8"?>
972<gresources>
973  <gresource prefix="/org/gtk/exampleapp">
974    <file preprocess="xml-stripblanks">window.ui</file>
975  </gresource>
976</gresources>
977```
978
979This file has to be converted into a C source file that will be compiled and linked
980into the application together with the other source files. To do so, we use the
981`glib-compile-resources` utility:
982
983```
984glib-compile-resources exampleapp.gresource.xml --target=resources.c --generate-source
985```
986
987The gnome module of the [Meson build system](https://mesonbuild.com)
988provides the [gnome.compile_resources()](https://mesonbuild.com/Gnome-module.html#gnomecompile_resources)
989method for this task.
990
991Our application now looks like this:
992
993![The application](getting-started-app2.png)
994
995### Opening files
996
997In this step, we make our application show the content of all the files
998that it is given on the commandline.
999
1000To this end, we add a member to the struct of our application window subclass
1001and keep a reference to the `GtkStack` there. The first member of the struct
1002should be the parent type from which the class is derived. Here,
1003`ExampleAppWindow` is derived from `GtkApplicationWindow`. The
1004`gtk_widget_class_bind_template_child()` function arranges things so that after
1005instantiating the template, the `stack` member of the struct will point to the
1006widget of the same name from the template.
1007
1008```c
1009...
1010
1011struct _ExampleAppWindow
1012{
1013  GtkApplicationWindow parent;
1014
1015  GtkWidget *stack;
1016};
1017
1018G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
1019
1020...
1021
1022static void
1023example_app_window_class_init (ExampleAppWindowClass *class)
1024{
1025  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
1026                                               "/org/gtk/exampleapp/window.ui");
1027  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
1028}
1029
1030...
1031```
1032
1033([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c))
1034
1035Now we revisit the `example_app_window_open()` function that is called for each
1036commandline argument, and construct a GtkTextView that we then add as a page
1037to the stack:
1038
1039```c
1040...
1041
1042void
1043example_app_window_open (ExampleAppWindow *win,
1044                         GFile            *file)
1045{
1046  char *basename;
1047  GtkWidget *scrolled, *view;
1048  char *contents;
1049  gsize length;
1050
1051  basename = g_file_get_basename (file);
1052
1053  scrolled = gtk_scrolled_window_new ();
1054  gtk_widget_set_hexpand (scrolled, TRUE);
1055  gtk_widget_set_vexpand (scrolled, TRUE);
1056  view = gtk_text_view_new ();
1057  gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
1058  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
1059  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
1060  gtk_stack_add_titled (GTK_STACK (win->stack), scrolled, basename, basename);
1061
1062  if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
1063    {
1064      GtkTextBuffer *buffer;
1065
1066      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
1067      gtk_text_buffer_set_text (buffer, contents, length);
1068      g_free (contents);
1069    }
1070
1071  g_free (basename);
1072}
1073
1074...
1075```
1076
1077([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c))
1078
1079Lastly, we add a [class@Gtk.StackSwitcher] to the titlebar area in the UI file, and we
1080tell it to display information about our stack.
1081
1082The stack switcher gets all its information it needs to display tabs from
1083the stack that it belongs to. Here, we are passing the label to show for
1084each file as the last argument to the [method@Gtk.Stack.add_titled]
1085function.
1086
1087Our application is beginning to take shape:
1088
1089![Application window](getting-started-app3.png)
1090
1091### A menu
1092
1093The menu is shown at the right side of the headerbar. It is meant to collect
1094infrequently used actions that affect the whole application.
1095
1096Just like the window template, we specify our menu in a ui file, and add it
1097as a resource to our binary.
1098
1099```xml
1100<?xml version="1.0" encoding="UTF-8"?>
1101<interface>
1102  <menu id="menu">
1103    <section>
1104      <item>
1105        <attribute name="label" translatable="yes">_Preferences</attribute>
1106        <attribute name="action">app.preferences</attribute>
1107      </item>
1108    </section>
1109    <section>
1110      <item>
1111        <attribute name="label" translatable="yes">_Quit</attribute>
1112        <attribute name="action">app.quit</attribute>
1113      </item>
1114    </section>
1115  </menu>
1116</interface>
1117```
1118
1119To make the menu appear, we have to load the ui file and associate the
1120resulting menu model with the menu button that we've added to the headerbar.
1121Since menus work by activating GActions, we also have to add a suitable set
1122of actions to our application.
1123
1124Adding the actions is best done in the startup() vfunc, which is guaranteed
1125to be called once for each primary application instance:
1126
1127```c
1128...
1129
1130static void
1131preferences_activated (GSimpleAction *action,
1132                       GVariant      *parameter,
1133                       gpointer       app)
1134{
1135}
1136
1137static void
1138quit_activated (GSimpleAction *action,
1139                GVariant      *parameter,
1140                gpointer       app)
1141{
1142  g_application_quit (G_APPLICATION (app));
1143}
1144
1145static GActionEntry app_entries[] =
1146{
1147  { "preferences", preferences_activated, NULL, NULL, NULL },
1148  { "quit", quit_activated, NULL, NULL, NULL }
1149};
1150
1151static void
1152example_app_startup (GApplication *app)
1153{
1154  GtkBuilder *builder;
1155  GMenuModel *app_menu;
1156  const char *quit_accels[2] = { "&lt;Ctrl&gt;Q", NULL };
1157
1158  G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
1159
1160  g_action_map_add_action_entries (G_ACTION_MAP (app),
1161                                   app_entries, G_N_ELEMENTS (app_entries),
1162                                   app);
1163  gtk_application_set_accels_for_action (GTK_APPLICATION (app),
1164                                         "app.quit",
1165                                         quit_accels);
1166}
1167
1168static void
1169example_app_class_init (ExampleAppClass *class)
1170{
1171  G_APPLICATION_CLASS (class)->startup = example_app_startup;
1172  ...
1173}
1174
1175...
1176```
1177
1178([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application4/exampleapp.c))
1179
1180Our preferences menu item does not do anything yet, but the Quit menu item
1181is fully functional. Note that it can also be activated by the usual Ctrl-Q
1182shortcut. The shortcut was added with `gtk_application_set_accels_for_action()`.
1183
1184The application menu looks like this:
1185
1186![Application window](getting-started-app4.png)
1187
1188### A preference dialog
1189
1190A typical application will have a some preferences that should be remembered
1191from one run to the next. Even for our simple example application, we may
1192want to change the font that is used for the content.
1193
1194We are going to use `GSettings` to store our preferences. `GSettings` requires
1195a schema that describes our settings:
1196
1197```xml
1198<?xml version="1.0" encoding="UTF-8"?>
1199<schemalist>
1200  <schema path="/org/gtk/exampleapp/" id="org.gtk.exampleapp">
1201    <key name="font" type="s">
1202      <default>'Monospace 12'</default>
1203      <summary>Font</summary>
1204      <description>The font to be used for content.</description>
1205    </key>
1206    <key name="transition" type="s">
1207      <choices>
1208        <choice value='none'/>
1209        <choice value='crossfade'/>
1210        <choice value='slide-left-right'/>
1211      </choices>
1212      <default>'none'</default>
1213      <summary>Transition</summary>
1214      <description>The transition to use when switching tabs.</description>
1215    </key>
1216  </schema>
1217</schemalist>
1218```
1219
1220Before we can make use of this schema in our application, we need to compile
1221it into the binary form that GSettings expects. GIO provides
1222[macros](https://developer.gnome.org/gio/2.36/ch31s06.html) to do this in
1223autotools-based projects, and the gnome module of the Meson build system
1224provides the [gnome.compile_schemas()](https://mesonbuild.com/Gnome-module.html#gnomecompile_schemas)
1225method for this task.
1226
1227Next, we need to connect our settings to the widgets that they are supposed
1228to control. One convenient way to do this is to use `GSettings` bind
1229functionality to bind settings keys to object properties, as we do here
1230for the transition setting.
1231
1232```c
1233...
1234
1235static void
1236example_app_window_init (ExampleAppWindow *win)
1237{
1238  gtk_widget_init_template (GTK_WIDGET (win));
1239  win->settings = g_settings_new ("org.gtk.exampleapp");
1240
1241  g_settings_bind (win->settings, "transition",
1242                   win->stack, "transition-type",
1243                   G_SETTINGS_BIND_DEFAULT);
1244}
1245
1246...
1247```
1248
1249([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application5/exampleappwin.c))
1250
1251The code to connect the font setting is a little more involved, since there
1252is no simple object property that it corresponds to, so we are not going to
1253go into that here.
1254
1255At this point, the application will already react if you change one of the
1256settings, e.g. using the `gsettings` command line tool. Of course, we expect
1257the application to provide a preference dialog for these. So lets do that
1258now. Our preference dialog will be a subclass of [class@Gtk.Dialog], and
1259we'll use the same techniques that we've already seen: templates, private
1260structs, settings bindings.
1261
1262Lets start with the template.
1263
1264```xml
1265<?xml version="1.0" encoding="UTF-8"?>
1266<interface>
1267  <template class="ExampleAppPrefs" parent="GtkDialog">
1268    <property name="title" translatable="yes">Preferences</property>
1269    <property name="resizable">0</property>
1270    <property name="modal">1</property>
1271    <child internal-child="content_area">
1272      <object class="GtkBox" id="content_area">
1273        <child>
1274          <object class="GtkGrid" id="grid">
1275            <property name="margin-start">12</property>
1276            <property name="margin-end">12</property>
1277            <property name="margin-top">12</property>
1278            <property name="margin-bottom">12</property>
1279            <property name="row-spacing">12</property>
1280            <property name="column-spacing">12</property>
1281            <child>
1282              <object class="GtkLabel" id="fontlabel">
1283                <property name="label">_Font:</property>
1284                <property name="use-underline">1</property>
1285                <property name="mnemonic-widget">font</property>
1286                <property name="xalign">1</property>
1287                <layout>
1288                  <property name="column">0</property>
1289                  <property name="row">0</property>
1290                </layout>
1291              </object>
1292            </child>
1293            <child>
1294              <object class="GtkFontButton" id="font">
1295                <layout>
1296                  <property name="column">1</property>
1297                  <property name="row">0</property>
1298                </layout>
1299              </object>
1300            </child>
1301            <child>
1302              <object class="GtkLabel" id="transitionlabel">
1303                <property name="label">_Transition:</property>
1304                <property name="use-underline">1</property>
1305                <property name="mnemonic-widget">transition</property>
1306                <property name="xalign">1</property>
1307                <layout>
1308                  <property name="column">0</property>
1309                  <property name="row">1</property>
1310                </layout>
1311              </object>
1312            </child>
1313            <child>
1314              <object class="GtkComboBoxText" id="transition">
1315                <items>
1316                  <item translatable="yes" id="none">None</item>
1317                  <item translatable="yes" id="crossfade">Fade</item>
1318                  <item translatable="yes" id="slide-left-right">Slide</item>
1319                </items>
1320                <layout>
1321                  <property name="column">1</property>
1322                  <property name="row">1</property>
1323                </layout>
1324              </object>
1325            </child>
1326          </object>
1327        </child>
1328      </object>
1329    </child>
1330  </template>
1331</interface>
1332```
1333
1334Next comes the dialog subclass.
1335
1336```c
1337#include <gtk/gtk.h>
1338
1339#include "exampleapp.h"
1340#include "exampleappwin.h"
1341#include "exampleappprefs.h"
1342
1343struct _ExampleAppPrefs
1344{
1345  GtkDialog parent;
1346
1347  GSettings *settings;
1348  GtkWidget *font;
1349  GtkWidget *transition;
1350};
1351
1352G_DEFINE_TYPE (ExampleAppPrefs, example_app_prefs, GTK_TYPE_DIALOG)
1353
1354static void
1355example_app_prefs_init (ExampleAppPrefs *prefs)
1356{
1357  gtk_widget_init_template (GTK_WIDGET (prefs));
1358  prefs->settings = g_settings_new ("org.gtk.exampleapp");
1359
1360  g_settings_bind (prefs->settings, "font",
1361                   prefs->font, "font",
1362                   G_SETTINGS_BIND_DEFAULT);
1363  g_settings_bind (prefs->settings, "transition",
1364                   prefs->transition, "active-id",
1365                   G_SETTINGS_BIND_DEFAULT);
1366}
1367
1368static void
1369example_app_prefs_dispose (GObject *object)
1370{
1371  ExampleAppPrefs *prefs;
1372
1373  prefs = EXAMPLE_APP_PREFS (object);
1374
1375  g_clear_object (&prefs->settings);
1376
1377  G_OBJECT_CLASS (example_app_prefs_parent_class)->dispose (object);
1378}
1379
1380static void
1381example_app_prefs_class_init (ExampleAppPrefsClass *class)
1382{
1383  G_OBJECT_CLASS (class)->dispose = example_app_prefs_dispose;
1384
1385  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
1386                                               "/org/gtk/exampleapp/prefs.ui");
1387  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppPrefs, font);
1388  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppPrefs, transition);
1389}
1390
1391ExampleAppPrefs *
1392example_app_prefs_new (ExampleAppWindow *win)
1393{
1394  return g_object_new (EXAMPLE_APP_PREFS_TYPE, "transient-for", win, "use-header-bar", TRUE, NULL);
1395}
1396```
1397
1398Now we revisit the `preferences_activated()` function in our application
1399class, and make it open a new preference dialog.
1400
1401```c
1402...
1403
1404static void
1405preferences_activated (GSimpleAction *action,
1406                       GVariant      *parameter,
1407                       gpointer       app)
1408{
1409  ExampleAppPrefs *prefs;
1410  GtkWindow *win;
1411
1412  win = gtk_application_get_active_window (GTK_APPLICATION (app));
1413  prefs = example_app_prefs_new (EXAMPLE_APP_WINDOW (win));
1414  gtk_window_present (GTK_WINDOW (prefs));
1415}
1416
1417...
1418```
1419
1420([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application6/exampleapp.c))
1421
1422After all this work, our application can now show a preference dialog
1423like this:
1424
1425![Preference dialog](getting-started-app6.png)
1426
1427### Adding a search bar
1428
1429We continue to flesh out the functionality of our application. For now, we
1430add search. GTK supports this with [class@Gtk.SearchEntry] and
1431[class@Gtk.SearchBar]. The search bar is a widget that can slide in from the
1432top to present a search entry.
1433
1434We add a toggle button to the header bar, which can be used to slide out
1435the search bar below the header bar.
1436
1437```xml
1438<?xml version="1.0" encoding="UTF-8"?>
1439<interface>
1440  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
1441    <property name="title" translatable="yes">Example Application</property>
1442    <property name="default-width">600</property>
1443    <property name="default-height">400</property>
1444    <child type="titlebar">
1445      <object class="GtkHeaderBar" id="header">
1446        <child type="title">
1447          <object class="GtkStackSwitcher" id="tabs">
1448            <property name="stack">stack</property>
1449          </object>
1450        </child>
1451        <child type="end">
1452          <object class="GtkMenuButton" id="gears">
1453            <property name="direction">none</property>
1454          </object>
1455        </child>
1456        <child type="end">
1457          <object class="GtkToggleButton" id="search">
1458            <property name="sensitive">0</property>
1459            <property name="icon-name">edit-find-symbolic</property>
1460          </object>
1461        </child>
1462      </object>
1463    </child>
1464    <child>
1465      <object class="GtkBox" id="content_box">
1466        <property name="orientation">vertical</property>
1467        <child>
1468          <object class="GtkSearchBar" id="searchbar">
1469            <child>
1470              <object class="GtkSearchEntry" id="searchentry">
1471                <signal name="search-changed" handler="search_text_changed"/>
1472              </object>
1473            </child>
1474          </object>
1475        </child>
1476        <child>
1477          <object class="GtkStack" id="stack">
1478            <signal name="notify::visible-child" handler="visible_child_changed"/>
1479          </object>
1480        </child>
1481      </object>
1482    </child>
1483  </template>
1484</interface>
1485```
1486
1487Implementing the search needs quite a few code changes that we are not
1488going to completely go over here. The central piece of the search
1489implementation is a signal handler that listens for text changes in
1490the search entry.
1491
1492```c
1493...
1494
1495static void
1496search_text_changed (GtkEntry         *entry,
1497                     ExampleAppWindow *win)
1498{
1499  const char *text;
1500  GtkWidget *tab;
1501  GtkWidget *view;
1502  GtkTextBuffer *buffer;
1503  GtkTextIter start, match_start, match_end;
1504
1505  text = gtk_editable_get_text (GTK_EDITABLE (entry));
1506
1507  if (text[0] == '\0')
1508    return;
1509
1510  tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
1511  view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
1512  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
1513
1514  /* Very simple-minded search implementation */
1515  gtk_text_buffer_get_start_iter (buffer, &start);
1516  if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
1517                                    &match_start, &match_end, NULL))
1518    {
1519      gtk_text_buffer_select_range (buffer, &match_start, &match_end);
1520      gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
1521                                    0.0, FALSE, 0.0, 0.0);
1522    }
1523}
1524
1525static void
1526example_app_window_init (ExampleAppWindow *win)
1527{
1528
1529...
1530
1531  gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
1532
1533...
1534
1535}
1536
1537...
1538```
1539
1540([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application7/exampleappwin.c))
1541
1542With the search bar, our application now looks like this:
1543
1544![A search bar](getting-started-app7.png)
1545
1546### Adding a side bar
1547
1548As another piece of functionality, we are adding a sidebar, which demonstrates
1549[class@Gtk.MenuButton], [class@Gtk.Revealer] and [class@Gtk.ListBox].
1550
1551```xml
1552<?xml version="1.0" encoding="UTF-8"?>
1553<interface>
1554  <template class="ExampleAppWindow" parent="GtkApplicationWindow">
1555    <property name="title" translatable="yes">Example Application</property>
1556    <property name="default-width">600</property>
1557    <property name="default-height">400</property>
1558    <child type="titlebar">
1559      <object class="GtkHeaderBar" id="header">
1560        <child type="title">
1561          <object class="GtkStackSwitcher" id="tabs">
1562            <property name="stack">stack</property>
1563          </object>
1564        </child>
1565        <child type="end">
1566          <object class="GtkToggleButton" id="search">
1567            <property name="sensitive">0</property>
1568            <property name="icon-name">edit-find-symbolic</property>
1569          </object>
1570        </child>
1571        <child type="end">
1572          <object class="GtkMenuButton" id="gears">
1573            <property name="direction">none</property>
1574          </object>
1575        </child>
1576      </object>
1577    </child>
1578    <child>
1579      <object class="GtkBox" id="content_box">
1580        <property name="orientation">vertical</property>
1581        <child>
1582          <object class="GtkSearchBar" id="searchbar">
1583            <child>
1584              <object class="GtkSearchEntry" id="searchentry">
1585                <signal name="search-changed" handler="search_text_changed"/>
1586              </object>
1587            </child>
1588          </object>
1589        </child>
1590        <child>
1591          <object class="GtkBox" id="hbox">
1592            <child>
1593              <object class="GtkRevealer" id="sidebar">
1594                <property name="transition-type">slide-right</property>
1595                <child>
1596                  <object class="GtkScrolledWindow" id="sidebar-sw">
1597                    <property name="hscrollbar-policy">never</property>
1598                    <child>
1599                      <object class="GtkListBox" id="words">
1600                        <property name="selection-mode">none</property>
1601                      </object>
1602                    </child>
1603                  </object>
1604                </child>
1605              </object>
1606            </child>
1607            <child>
1608              <object class="GtkStack" id="stack">
1609                <signal name="notify::visible-child" handler="visible_child_changed"/>
1610              </object>
1611            </child>
1612          </object>
1613        </child>
1614      </object>
1615    </child>
1616  </template>
1617</interface>
1618```
1619
1620The code to populate the sidebar with buttons for the words found in each
1621file is a little too involved to go into here. But we'll look at the code
1622to add a checkbutton for the new feature to the menu.
1623
1624```xml
1625<?xml version="1.0" encoding="UTF-8"?>
1626<interface>
1627  <menu id="menu">
1628    <section>
1629      <item>
1630        <attribute name="label" translatable="yes">_Words</attribute>
1631        <attribute name="action">win.show-words</attribute>
1632      </item>
1633      <item>
1634        <attribute name="label" translatable="yes">_Preferences</attribute>
1635        <attribute name="action">app.preferences</attribute>
1636      </item>
1637    </section>
1638    <section>
1639      <item>
1640        <attribute name="label" translatable="yes">_Quit</attribute>
1641        <attribute name="action">app.quit</attribute>
1642      </item>
1643    </section>
1644  </menu>
1645</interface>
1646```
1647
1648To connect the menuitem to the show-words setting, we use
1649a `GAction` corresponding to the given `GSettings` key.
1650
1651```c
1652...
1653
1654static void
1655example_app_window_init (ExampleAppWindow *win)
1656{
1657
1658...
1659
1660  builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
1661  menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
1662  gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->gears), menu);
1663  g_object_unref (builder);
1664
1665  action = g_settings_create_action (priv->settings, "show-words");
1666  g_action_map_add_action (G_ACTION_MAP (win), action);
1667  g_object_unref (action);
1668}
1669
1670...
1671```
1672
1673([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application8/exampleappwin.c))
1674
1675What our application looks like now:
1676
1677![A sidebar](getting-started-app8.png)
1678
1679### Properties
1680
1681Widgets and other objects have many useful properties.
1682
1683Here we show some ways to use them in new and flexible ways, by wrapping
1684them in actions with `GPropertyAction` or by binding them with `GBinding`.
1685
1686To set this up, we add two labels to the header bar in our window template,
1687named `lines_label` and `lines`, and bind them to struct members in the
1688private struct, as we've seen a couple of times by now.
1689
1690We add a new "Lines" menu item to the gears menu, which triggers the
1691show-lines action:
1692
1693```xml
1694<?xml version="1.0" encoding="UTF-8"?>
1695<interface>
1696  <menu id="menu">
1697    <section>
1698      <item>
1699        <attribute name="label" translatable="yes">_Words</attribute>
1700        <attribute name="action">win.show-words</attribute>
1701      </item>
1702      <item>
1703        <attribute name="label" translatable="yes">_Lines</attribute>
1704        <attribute name="action">win.show-lines</attribute>
1705      </item>
1706      <item>
1707        <attribute name="label" translatable="yes">_Preferences</attribute>
1708        <attribute name="action">app.preferences</attribute>
1709      </item>
1710    </section>
1711    <section>
1712      <item>
1713        <attribute name="label" translatable="yes">_Quit</attribute>
1714        <attribute name="action">app.quit</attribute>
1715      </item>
1716    </section>
1717  </menu>
1718</interface>
1719```
1720
1721To make this menu item do something, we create a property action for the
1722visible property of the `lines` label, and add it to the actions of the
1723window. The effect of this is that the visibility of the label gets toggled
1724every time the action is activated.
1725
1726Since we want both labels to appear and disappear together, we bind
1727the visible property of the `lines_label` widget to the same property
1728of the `lines` widget.
1729
1730```c
1731...
1732
1733static void
1734example_app_window_init (ExampleAppWindow *win)
1735{
1736  ...
1737
1738  action = (GAction*) g_property_action_new ("show-lines", win->lines, "visible");
1739  g_action_map_add_action (G_ACTION_MAP (win), action);
1740  g_object_unref (action);
1741
1742  g_object_bind_property (win->lines, "visible",
1743                          win->lines_label, "visible",
1744                          G_BINDING_DEFAULT);
1745}
1746
1747...
1748```
1749
1750([full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application9/exampleappwin.c))
1751
1752We also need a function that counts the lines of the currently active tab,
1753and updates the `lines` label. See the [full source](https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application9/exampleappwin.c)
1754if you are interested in the details.
1755
1756This brings our example application to this appearance:
1757
1758![Full application](getting-started-app9.png)
1759