Refresh the tutorial examples

Redo this series of examples from 2013, and adapt it to modern
way of doing things. The biggest differences are that we use
a headerbar right from the start, and don't mention the app
menu.

Fixes: #2730
This commit is contained in:
Matthias Clasen 2020-05-10 21:26:19 -04:00
parent 4de4957aa3
commit d2430c70bd
70 changed files with 285 additions and 1089 deletions

View File

@ -415,9 +415,8 @@
<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 puts a GtkHeaderBar on top of a GtkStack
widget. The header bar contains a GtkStackSwitcher, which is a
standalone widget to show a row of 'tabs' for the pages of a GtkStack.
<para>Our simple ui file gives the window a title, and puts a GtkStack
widget as the main content.
</para>
<informalexample>
@ -572,11 +571,14 @@ example_app_window_open (ExampleAppWindow *win,
<para>(<ulink url="https://gitlab.gnome.org/GNOME/gtk/blob/master/examples/application3/exampleappwin.c">full source</ulink>)</para>
</informalexample>
<para>Note that we did not have to touch the stack switcher
at all. It gets all its information from the stack that it
belongs to. Here, we are passing the label to show for each
file as the last argument to the gtk_stack_add_titled()
function.</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 gtk_stack_add_titled() function.</para>
<para>Our application is beginning to take shape:</para>
@ -590,25 +592,25 @@ example_app_window_open (ExampleAppWindow *win,
</section>
<section>
<title>An application menu</title>
<title>A menu</title>
<para>An application menu is shown by GNOME shell at the top of the
screen. It is meant to collect infrequently used actions that affect
<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 application menu
<para>Just like the window template, we specify our menu
in a ui file, and add it as a resource to our binary.</para>
<informalexample>
<programlisting><xi:include href="@SRC_DIR@/examples/application4/app-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
<programlisting><xi:include href="@SRC_DIR@/examples/application4/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>To associate the app menu with the application, we have to call
gtk_application_set_app_menu(). Since app menus work by activating
GActions, we also have to add a suitable set of actions to our
application.</para>
<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>Both of these tasks are best done in the startup() vfunc,
<para>Adding the actions is best done in the startup() vfunc,
which is guaranteed to be called once for each primary application
instance:</para>
<informalexample>
@ -651,11 +653,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void
@ -799,7 +796,7 @@ preferences_activated (GSimpleAction *action,
<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
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>
@ -1005,35 +1002,6 @@ example_app_window_init (ExampleAppWindow *win)
</mediaobject>
</informalfigure>
</section>
<section>
<title>Header bar</title>
<para>Our application already uses a GtkHeaderBar, but so far it
still gets a 'normal' window titlebar on top of that. This is a
bit redundant, and we will now tell GTK to use the header bar
as replacement for the titlebar. To do so, we move it around to
be a direct child of the window, and set its type to be titlebar.</para>
<informalexample>
<programlisting><xi:include href="@SRC_DIR@/examples/application10/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
</informalexample>
<para>A small extra bonus of using a header bar is that we get
a fallback application menu for free. Here is how the
application now looks, if this fallback is used.</para>
<informalfigure>
<mediaobject>
<imageobject>
<imagedata fileref="getting-started-app10.png" format="PNG"/>
</imageobject>
</mediaobject>
</informalfigure>
<para>If we set up the window icon for our window, the menu button
will use that instead of the generic placeholder icon you see
here.</para>
</section>
</section>
<section>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -1,3 +1,5 @@
Step 1: A trivial application
To make gnome-shell use the desktop file and icon for this example
while running it uninstalled, do the following:

View File

@ -1,35 +0,0 @@
CC ?= gcc
PKGCONFIG = $(shell which pkg-config)
CFLAGS = $(shell $(PKGCONFIG) --cflags gtk4)
LIBS = $(shell $(PKGCONFIG) --libs gtk4)
GLIB_COMPILE_RESOURCES = $(shell $(PKGCONFIG) --variable=glib_compile_resources gio-2.0)
GLIB_COMPILE_SCHEMAS = $(shell $(PKGCONFIG) --variable=glib_compile_schemas gio-2.0)
SRC = exampleapp.c exampleappwin.c exampleappprefs.c main.c
BUILT_SRC = resources.c
OBJS = $(BUILT_SRC:.c=.o) $(SRC:.c=.o)
all: exampleapp
org.gtk.exampleapp.gschema.valid: org.gtk.exampleapp.gschema.xml
$(GLIB_COMPILE_SCHEMAS) --strict --dry-run --schema-file=$< && mkdir -p $(@D) && touch $@
gschemas.compiled: org.gtk.exampleapp.gschema.valid
$(GLIB_COMPILE_SCHEMAS) .
resources.c: exampleapp.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=. --generate-dependencies exampleapp.gresource.xml)
$(GLIB_COMPILE_RESOURCES) exampleapp.gresource.xml --target=$@ --sourcedir=. --generate-source
%.o: %.c
$(CC) -c -o $(@F) $(CFLAGS) $<
exampleapp: $(OBJS) gschemas.compiled
$(CC) -o $(@F) $(OBJS) $(LIBS)
clean:
rm -f org.gtk.exampleapp.gschema.valid
rm -f gschemas.compiled
rm -f $(BUILT_SRC)
rm -f $(OBJS)
rm -f exampleapp

View File

@ -1,114 +0,0 @@
#include <gtk/gtk.h>
#include "exampleapp.h"
#include "exampleappwin.h"
#include "exampleappprefs.h"
struct _ExampleApp
{
GtkApplication parent;
};
G_DEFINE_TYPE(ExampleApp, example_app, GTK_TYPE_APPLICATION);
static void
example_app_init (ExampleApp *app)
{
}
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));
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer app)
{
g_application_quit (G_APPLICATION (app));
}
static GActionEntry app_entries[] =
{
{ "preferences", preferences_activated, NULL, NULL, NULL },
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void
example_app_activate (GApplication *app)
{
ExampleAppWindow *win;
win = example_app_window_new (EXAMPLE_APP (app));
gtk_window_present (GTK_WINDOW (win));
}
static void
example_app_open (GApplication *app,
GFile **files,
gint n_files,
const gchar *hint)
{
GList *windows;
ExampleAppWindow *win;
int i;
windows = gtk_application_get_windows (GTK_APPLICATION (app));
if (windows)
win = EXAMPLE_APP_WINDOW (windows->data);
else
win = example_app_window_new (EXAMPLE_APP (app));
for (i = 0; i < n_files; i++)
example_app_window_open (win, files[i]);
gtk_window_present (GTK_WINDOW (win));
}
static void
example_app_class_init (ExampleAppClass *class)
{
G_APPLICATION_CLASS (class)->startup = example_app_startup;
G_APPLICATION_CLASS (class)->activate = example_app_activate;
G_APPLICATION_CLASS (class)->open = example_app_open;
}
ExampleApp *
example_app_new (void)
{
return g_object_new (EXAMPLE_APP_TYPE,
"application-id", "org.gtk.exampleapp",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
<file preprocess="xml-stripblanks">prefs.ui</file>
</gresource>
</gresources>

View File

@ -1,14 +0,0 @@
#ifndef __EXAMPLEAPP_H
#define __EXAMPLEAPP_H
#include <gtk/gtk.h>
#define EXAMPLE_APP_TYPE (example_app_get_type ())
G_DECLARE_FINAL_TYPE (ExampleApp, example_app, EXAMPLE, APP, GtkApplication)
ExampleApp *example_app_new (void);
#endif /* __EXAMPLEAPP_H */

View File

@ -1,59 +0,0 @@
#include <gtk/gtk.h>
#include "exampleapp.h"
#include "exampleappwin.h"
#include "exampleappprefs.h"
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->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (prefs->settings, "font",
prefs->font, "font",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (prefs->settings, "transition",
prefs->transition, "active-id",
G_SETTINGS_BIND_DEFAULT);
}
static void
example_app_prefs_dispose (GObject *object)
{
ExampleAppPrefs *prefs;
prefs = EXAMPLE_APP_PREFS (object);
g_clear_object (&prefs->settings);
G_OBJECT_CLASS (example_app_prefs_parent_class)->dispose (object);
}
static void
example_app_prefs_class_init (ExampleAppPrefsClass *class)
{
G_OBJECT_CLASS (class)->dispose = example_app_prefs_dispose;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/prefs.ui");
gtk_widget_class_bind_template_child (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, "transient-for", win, "use-header-bar", TRUE, NULL);
}

View File

@ -1,15 +0,0 @@
#ifndef __EXAMPLEAPPPREFS_H
#define __EXAMPLEAPPPREFS_H
#include <gtk/gtk.h>
#include "exampleappwin.h"
#define EXAMPLE_APP_PREFS_TYPE (example_app_prefs_get_type ())
G_DECLARE_FINAL_TYPE (ExampleAppPrefs, example_app_prefs, EXAMPLE, APP_PREFS, GtkDialog)
ExampleAppPrefs *example_app_prefs_new (ExampleAppWindow *win);
#endif /* __EXAMPLEAPPPREFS_H */

View File

@ -1,295 +0,0 @@
#include <gtk/gtk.h>
#include "exampleapp.h"
#include "exampleappwin.h"
struct _ExampleAppWindow
{
GtkApplicationWindow parent;
GSettings *settings;
GtkWidget *stack;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *gears;
GtkWidget *sidebar;
GtkWidget *words;
GtkWidget *lines;
GtkWidget *lines_label;
};
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
static void
search_text_changed (GtkEntry *entry,
ExampleAppWindow *win)
{
const gchar *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->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, &start);
if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
&match_start, &match_end, NULL))
{
gtk_text_buffer_select_range (buffer, &match_start, &match_end);
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
0.0, FALSE, 0.0, 0.0);
}
}
static void
find_word (GtkButton *button,
ExampleAppWindow *win)
{
const gchar *word;
word = gtk_button_get_label (button);
gtk_editable_set_text (GTK_EDITABLE (win->searchentry), word);
}
static void
update_words (ExampleAppWindow *win)
{
GHashTable *strings;
GHashTableIter iter;
GtkWidget *tab, *view, *row;
GtkTextBuffer *buffer;
GtkTextIter start, end;
GList *children, *l;
gchar *word, *key;
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
if (tab == NULL)
return;
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
gtk_text_buffer_get_start_iter (buffer, &start);
while (!gtk_text_iter_is_end (&start))
{
while (!gtk_text_iter_starts_word (&start))
{
if (!gtk_text_iter_forward_char (&start))
goto done;
}
end = start;
if (!gtk_text_iter_forward_word_end (&end))
goto done;
word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
g_hash_table_add (strings, g_utf8_strdown (word, -1));
g_free (word);
start = end;
}
done:
children = gtk_container_get_children (GTK_CONTAINER (win->words));
for (l = children; l; l = l->next)
gtk_container_remove (GTK_CONTAINER (win->words), GTK_WIDGET (l->data));
g_list_free (children);
g_hash_table_iter_init (&iter, strings);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
{
row = gtk_button_new_with_label (key);
g_signal_connect (row, "clicked",
G_CALLBACK (find_word), win);
gtk_container_add (GTK_CONTAINER (win->words), row);
}
g_hash_table_unref (strings);
}
static void
update_lines (ExampleAppWindow *win)
{
GtkWidget *tab, *view;
GtkTextBuffer *buffer;
int count;
gchar *lines;
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
if (tab == NULL)
return;
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
count = gtk_text_buffer_get_line_count (buffer);
lines = g_strdup_printf ("%d", count);
gtk_label_set_text (GTK_LABEL (win->lines), lines);
g_free (lines);
}
static void
visible_child_changed (GObject *stack,
GParamSpec *pspec,
ExampleAppWindow *win)
{
if (gtk_widget_in_destruction (GTK_WIDGET (stack)))
return;
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (win->searchbar), FALSE);
update_words (win);
update_lines (win);
}
static void
words_changed (GObject *sidebar,
GParamSpec *pspec,
ExampleAppWindow *win)
{
update_words (win);
}
static void
example_app_window_init (ExampleAppWindow *win)
{
GtkBuilder *builder;
GMenuModel *menu;
GAction *action;
gtk_widget_init_template (GTK_WIDGET (win));
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
win->stack, "transition-type",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (win->settings, "show-words",
win->sidebar, "reveal-child",
G_SETTINGS_BIND_DEFAULT);
g_object_bind_property (win->search, "active",
win->searchbar, "search-mode-enabled",
G_BINDING_BIDIRECTIONAL);
g_signal_connect (win->sidebar, "notify::reveal-child",
G_CALLBACK (words_changed), win);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
action = g_settings_create_action (win->settings, "show-words");
g_action_map_add_action (G_ACTION_MAP (win), action);
g_object_unref (action);
action = (GAction*) g_property_action_new ("show-lines", win->lines, "visible");
g_action_map_add_action (G_ACTION_MAP (win), action);
g_object_unref (action);
g_object_bind_property (win->lines, "visible",
win->lines_label, "visible",
G_BINDING_DEFAULT);
g_object_set (gtk_settings_get_default (), "gtk-shell-shows-app-menu", FALSE, NULL);
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
}
static void
example_app_window_dispose (GObject *object)
{
ExampleAppWindow *win;
win = EXAMPLE_APP_WINDOW (object);
g_clear_object (&win->settings);
G_OBJECT_CLASS (example_app_window_parent_class)->dispose (object);
}
static void
example_app_window_class_init (ExampleAppWindowClass *class)
{
G_OBJECT_CLASS (class)->dispose = example_app_window_dispose;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines_label);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), visible_child_changed);
}
ExampleAppWindow *
example_app_window_new (ExampleApp *app)
{
return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
}
void
example_app_window_open (ExampleAppWindow *win,
GFile *file)
{
gchar *basename;
GtkWidget *scrolled, *view;
gchar *contents;
gsize length;
GtkTextBuffer *buffer;
GtkTextTag *tag;
GtkTextIter start_iter, end_iter;
basename = g_file_get_basename (file);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_hexpand (scrolled, TRUE);
gtk_widget_set_vexpand (scrolled, TRUE);
view = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
gtk_stack_add_titled (GTK_STACK (win->stack), scrolled, basename, basename);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
{
gtk_text_buffer_set_text (buffer, contents, length);
g_free (contents);
}
tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
g_settings_bind (win->settings, "font",
tag, "font",
G_SETTINGS_BIND_DEFAULT);
gtk_text_buffer_get_start_iter (buffer, &start_iter);
gtk_text_buffer_get_end_iter (buffer, &end_iter);
gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter);
g_free (basename);
gtk_widget_set_sensitive (win->search, TRUE);
update_words (win);
update_lines (win);
}

View File

@ -1,16 +0,0 @@
#ifndef __EXAMPLEAPPWIN_H
#define __EXAMPLEAPPWIN_H
#include <gtk/gtk.h>
#include "exampleapp.h"
#define EXAMPLE_APP_WINDOW_TYPE (example_app_window_get_type ())
G_DECLARE_FINAL_TYPE (ExampleAppWindow, example_app_window, EXAMPLE, APP_WINDOW, GtkApplicationWindow)
ExampleAppWindow *example_app_window_new (ExampleApp *app);
void example_app_window_open (ExampleAppWindow *win,
GFile *file);
#endif /* __EXAMPLEAPPWIN_H */

View File

@ -1,14 +0,0 @@
<interface>
<menu id="menu">
<section>
<item>
<attribute name="label" translatable="yes">_Words</attribute>
<attribute name="action">win.show-words</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Lines</attribute>
<attribute name="action">win.show-lines</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -1,16 +0,0 @@
#include <gtk/gtk.h>
#include "exampleapp.h"
int
main (int argc, char *argv[])
{
/* Since this example is running uninstalled,
* we have to help it find its schema. This
* is *not* necessary in properly installed
* application.
*/
g_setenv ("GSETTINGS_SCHEMA_DIR", ".", FALSE);
return g_application_run (G_APPLICATION (example_app_new ()), argc, argv);
}

View File

@ -1,14 +0,0 @@
app10_resources = gnome.compile_resources('exampleapp10 resources',
'exampleapp.gresource.xml',
source_dir: '.')
app10_schemas = gnome.compile_schemas()
executable('exampleapp10',
'main.c',
'exampleapp.c',
'exampleappwin.c',
'exampleappprefs.c',
app10_resources,
app10_schemas,
dependencies: libgtk_dep)

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema path="/org/gtk/exampleapp/" id="org.gtk.exampleapp">
<key name="font" type="s">
<default>'Monospace 12'</default>
<summary>Font</summary>
<description>The font to be used for content.</description>
</key>
<key name="transition" type="s">
<choices>
<choice value='none'/>
<choice value='crossfade'/>
<choice value='slide-left-right'/>
</choices>
<default>'none'</default>
<summary>Transition</summary>
<description>The transition to use when switching tabs.</description>
</key>
<key name="show-words" type="b">
<default>false</default>
<summary>Show words</summary>
<description>Whether to show a word list in the sidebar</description>
</key>
</schema>
</schemalist>

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppPrefs" parent="GtkDialog">
<property name="title" translatable="yes">Preferences</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<child internal-child="vbox">
<object class="GtkBox" id="vbox">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="row-spacing">12</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="fontlabel">
<property name="label">_Font:</property>
<property name="use-underline">1</property>
<property name="mnemonic-widget">font</property>
<property name="xalign">1</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkFontButton" id="font">
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="transitionlabel">
<property name="label">_Transition:</property>
<property name="use-underline">1</property>
<property name="mnemonic-widget">transition</property>
<property name="xalign">1</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="transition">
<items>
<item translatable="yes" id="none">None</item>
<item translatable="yes" id="crossfade">Fade</item>
<item translatable="yes" id="slide-left-right">Slide</item>
</items>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child>
<object class="GtkLabel" id="lines_label">
<property name="visible">0</property>
<property name="label" translatable="yes">Lines:</property>
</object>
</child>
<child>
<object class="GtkLabel" id="lines">
<property name="visible">0</property>
</object>
</child>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
<style>
<class name="image-button"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchBar" id="searchbar">
<child>
<object class="GtkSearchEntry" id="searchentry">
<signal name="search-changed" handler="search_text_changed"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="hbox">
<child>
<object class="GtkRevealer" id="sidebar">
<property name="transition-type">slide-right</property>
<child>
<object class="GtkScrolledWindow" id="sidebar-sw">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListBox" id="words">
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
<signal name="notify::visible-child" handler="visible_child_changed"/>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@ -0,0 +1 @@
Step 2: Populating the window

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
@ -6,15 +7,6 @@
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack"/>
</child>

View File

@ -0,0 +1 @@
Step 3: Opening files, add a stack switcher

View File

@ -1,20 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack"/>
</child>

View File

@ -0,0 +1 @@
Step 4: Add a menu

View File

@ -39,8 +39,6 @@ static GActionEntry app_entries[] =
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
@ -51,11 +49,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void

View File

@ -2,6 +2,6 @@
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
</gresource>
</gresources>

View File

@ -8,6 +8,7 @@ struct _ExampleAppWindow
GtkApplicationWindow parent;
GtkWidget *stack;
GtkWidget *gears;
};
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
@ -15,7 +16,15 @@ G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW
static void
example_app_window_init (ExampleAppWindow *win)
{
GtkBuilder *builder;
GMenuModel *menu;
gtk_widget_init_template (GTK_WIDGET (win));
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
}
static void
@ -24,6 +33,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
}
ExampleAppWindow *

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="appmenu">
<menu id="menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>

View File

@ -1,20 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack"/>
</child>

View File

@ -39,8 +39,6 @@ static GActionEntry app_entries[] =
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
@ -51,11 +49,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void

View File

@ -2,6 +2,6 @@
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
</gresource>
</gresources>

View File

@ -9,6 +9,7 @@ struct _ExampleAppWindow
GSettings *settings;
GtkWidget *stack;
GtkWidget *gears;
};
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
@ -16,9 +17,17 @@ G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW
static void
example_app_window_init (ExampleAppWindow *win)
{
gtk_widget_init_template (GTK_WIDGET (win));
win->settings = g_settings_new ("org.gtk.exampleapp");
GtkBuilder *builder;
GMenuModel *menu;
gtk_widget_init_template (GTK_WIDGET (win));
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
win->stack, "transition-type",
G_SETTINGS_BIND_DEFAULT);
@ -44,6 +53,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
}
ExampleAppWindow *

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="appmenu">
<menu id="menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>

View File

@ -1,20 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack"/>
</child>

View File

@ -46,8 +46,6 @@ static GActionEntry app_entries[] =
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
@ -58,11 +56,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void

View File

@ -2,7 +2,7 @@
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
<file preprocess="xml-stripblanks">prefs.ui</file>
</gresource>
</gresources>

View File

@ -9,6 +9,7 @@ struct _ExampleAppWindow
GSettings *settings;
GtkWidget *stack;
GtkWidget *gears;
};
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
@ -16,7 +17,16 @@ G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW
static void
example_app_window_init (ExampleAppWindow *win)
{
GtkBuilder *builder;
GMenuModel *menu;
gtk_widget_init_template (GTK_WIDGET (win));
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
@ -44,6 +54,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
}
ExampleAppWindow *

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="appmenu">
<menu id="menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>

View File

@ -4,16 +4,16 @@
<property name="title" translatable="yes">Preferences</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<child internal-child="vbox">
<object class="GtkBox" id="vbox">
<child internal-child="content_area">
<object class="GtkBox" id="content_area">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="row-spacing">12</property>
<property name="column-spacing">6</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkLabel" id="fontlabel">
<property name="label">_Font:</property>

View File

@ -1,20 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack"/>
</child>

View File

@ -0,0 +1 @@
Step 7: A search bar

View File

@ -1,16 +0,0 @@
<interface>
<menu id="appmenu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -46,8 +46,6 @@ static GActionEntry app_entries[] =
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
@ -58,11 +56,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void

View File

@ -2,7 +2,7 @@
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
<file preprocess="xml-stripblanks">prefs.ui</file>
</gresource>
</gresources>

View File

@ -9,6 +9,7 @@ struct _ExampleAppWindow
GSettings *settings;
GtkWidget *stack;
GtkWidget *gears;
GtkWidget *search;
GtkWidget *searchbar;
};
@ -59,7 +60,16 @@ visible_child_changed (GObject *stack,
static void
example_app_window_init (ExampleAppWindow *win)
{
GtkBuilder *builder;
GMenuModel *menu;
gtk_widget_init_template (GTK_WIDGET (win));
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
@ -92,6 +102,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="appmenu">
<menu id="menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>

View File

@ -4,16 +4,16 @@
<property name="title" translatable="yes">Preferences</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<child internal-child="vbox">
<object class="GtkBox" id="vbox">
<child internal-child="content_area">
<object class="GtkBox" id="content_area">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="row-spacing">12</property>
<property name="column-spacing">6</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkLabel" id="fontlabel">
<property name="label">_Font:</property>

View File

@ -4,24 +4,30 @@
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSearchBar" id="searchbar">
<child>

View File

@ -0,0 +1 @@
Step 8: Adding a sidebar

View File

@ -1,16 +0,0 @@
<interface>
<menu id="appmenu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -46,8 +46,6 @@ static GActionEntry app_entries[] =
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
@ -58,11 +56,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void

View File

@ -2,7 +2,6 @@
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
<file preprocess="xml-stripblanks">prefs.ui</file>
</gresource>

View File

@ -9,10 +9,10 @@ struct _ExampleAppWindow
GSettings *settings;
GtkWidget *stack;
GtkWidget *gears;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *gears;
GtkWidget *sidebar;
GtkWidget *words;
};
@ -143,6 +143,12 @@ example_app_window_init (ExampleAppWindow *win)
GAction *action;
gtk_widget_init_template (GTK_WIDGET (win));
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
@ -160,11 +166,6 @@ example_app_window_init (ExampleAppWindow *win)
g_signal_connect (win->sidebar, "notify::reveal-child",
G_CALLBACK (words_changed), win);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
action = g_settings_create_action (win->settings, "show-words");
g_action_map_add_action (G_ACTION_MAP (win), action);
g_object_unref (action);
@ -191,10 +192,10 @@ example_app_window_class_init (ExampleAppWindowClass *class)
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="menu">
<section>
@ -5,6 +6,16 @@
<attribute name="label" translatable="yes">_Words</attribute>
<attribute name="action">win.show-words</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -4,16 +4,16 @@
<property name="title" translatable="yes">Preferences</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<child internal-child="vbox">
<object class="GtkBox" id="vbox">
<child internal-child="content_area">
<object class="GtkBox" id="content_area">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="row-spacing">12</property>
<property name="column-spacing">6</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkLabel" id="fontlabel">
<property name="label">_Font:</property>

View File

@ -4,32 +4,30 @@
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
<style>
<class name="image-button"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSearchBar" id="searchbar">
<child>

View File

@ -0,0 +1 @@
Step 9: Using properties

View File

@ -1,16 +0,0 @@
<interface>
<menu id="appmenu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -46,8 +46,6 @@ static GActionEntry app_entries[] =
static void
example_app_startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *app_menu;
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
@ -58,11 +56,6 @@ example_app_startup (GApplication *app)
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"app.quit",
quit_accels);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
g_object_unref (builder);
}
static void

View File

@ -2,7 +2,6 @@
<gresources>
<gresource prefix="/org/gtk/exampleapp">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">app-menu.ui</file>
<file preprocess="xml-stripblanks">gears-menu.ui</file>
<file preprocess="xml-stripblanks">prefs.ui</file>
</gresource>

View File

@ -9,10 +9,10 @@ struct _ExampleAppWindow
GSettings *settings;
GtkWidget *stack;
GtkWidget *gears;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *gears;
GtkWidget *sidebar;
GtkWidget *words;
GtkWidget *lines;
@ -168,6 +168,12 @@ example_app_window_init (ExampleAppWindow *win)
GAction *action;
gtk_widget_init_template (GTK_WIDGET (win));
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
win->settings = g_settings_new ("org.gtk.exampleapp");
g_settings_bind (win->settings, "transition",
@ -185,11 +191,6 @@ example_app_window_init (ExampleAppWindow *win)
g_signal_connect (win->sidebar, "notify::reveal-child",
G_CALLBACK (words_changed), win);
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
g_object_unref (builder);
action = g_settings_create_action (win->settings, "show-words");
g_action_map_add_action (G_ACTION_MAP (win), action);
g_object_unref (action);
@ -224,10 +225,10 @@ example_app_window_class_init (ExampleAppWindowClass *class)
"/org/gtk/exampleapp/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines);

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="menu">
<section>
@ -9,6 +10,16 @@
<attribute name="label" translatable="yes">_Lines</attribute>
<attribute name="action">win.show-lines</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -4,16 +4,16 @@
<property name="title" translatable="yes">Preferences</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<child internal-child="vbox">
<object class="GtkBox" id="vbox">
<child internal-child="content_area">
<object class="GtkBox" id="content_area">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="row-spacing">12</property>
<property name="column-spacing">6</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkLabel" id="fontlabel">
<property name="label">_Font:</property>

View File

@ -4,43 +4,41 @@
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child>
<object class="GtkLabel" id="lines_label">
<property name="visible">0</property>
<property name="label" translatable="yes">Lines:</property>
</object>
</child>
<child>
<object class="GtkLabel" id="lines">
<property name="visible">0</property>
</object>
</child>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar" id="header">
<child>
<object class="GtkLabel" id="lines_label">
<property name="visible">0</property>
<property name="label" translatable="yes">Lines:</property>
</object>
</child>
<child>
<object class="GtkLabel" id="lines">
<property name="visible">0</property>
</object>
</child>
<child type="title">
<object class="GtkStackSwitcher" id="tabs">
<property name="stack">stack</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gears">
<property name="direction">none</property>
<style>
<class name="image-button"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSearchBar" id="searchbar">
<child>

View File

@ -31,4 +31,3 @@ subdir('application6')
subdir('application7')
subdir('application8')
subdir('application9')
subdir('application10')