1/* Assistant
2 *
3 * Demonstrates a sample multi-step assistant with GtkAssistant. Assistants
4 * are used to divide an operation into several simpler sequential steps,
5 * and to guide the user through these steps.
6 */
7
8#include <gtk/gtk.h>
9
10static GtkWidget *progress_bar = NULL;
11
12static gboolean
13apply_changes_gradually (gpointer data)
14{
15 double fraction;
16
17 /* Work, work, work... */
18 fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress_bar));
19 fraction += 0.05;
20
21 if (fraction < 1.0)
22 {
23 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress_bar), fraction);
24 return G_SOURCE_CONTINUE;
25 }
26 else
27 {
28 /* Close automatically once changes are fully applied. */
29 gtk_window_destroy (GTK_WINDOW (data));
30 return G_SOURCE_REMOVE;
31 }
32}
33
34static void
35on_assistant_apply (GtkWidget *widget, gpointer data)
36{
37 /* Start a timer to simulate changes taking a few seconds to apply. */
38 g_timeout_add (interval: 100, function: apply_changes_gradually, data: widget);
39}
40
41static void
42on_assistant_close_cancel (GtkWidget *widget, gpointer data)
43{
44 gtk_window_destroy (GTK_WINDOW (widget));
45}
46
47static void
48on_assistant_prepare (GtkWidget *widget, GtkWidget *page, gpointer data)
49{
50 int current_page, n_pages;
51 char *title;
52
53 current_page = gtk_assistant_get_current_page (GTK_ASSISTANT (widget));
54 n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (widget));
55
56 title = g_strdup_printf (format: "Sample assistant (%d of %d)", current_page + 1, n_pages);
57 gtk_window_set_title (GTK_WINDOW (widget), title);
58 g_free (mem: title);
59
60 /* The fourth page (counting from zero) is the progress page. The
61 * user clicked Apply to get here so we tell the assistant to commit,
62 * which means the changes up to this point are permanent and cannot
63 * be cancelled or revisited. */
64 if (current_page == 3)
65 gtk_assistant_commit (GTK_ASSISTANT (widget));
66}
67
68static void
69on_entry_changed (GtkWidget *widget, gpointer data)
70{
71 GtkAssistant *assistant = GTK_ASSISTANT (data);
72 GtkWidget *current_page;
73 int page_number;
74 const char *text;
75
76 page_number = gtk_assistant_get_current_page (assistant);
77 current_page = gtk_assistant_get_nth_page (assistant, page_num: page_number);
78 text = gtk_editable_get_text (GTK_EDITABLE (widget));
79
80 if (text && *text)
81 gtk_assistant_set_page_complete (assistant, page: current_page, TRUE);
82 else
83 gtk_assistant_set_page_complete (assistant, page: current_page, FALSE);
84}
85
86static void
87create_page1 (GtkWidget *assistant)
88{
89 GtkWidget *box, *label, *entry;
90
91 box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 12);
92 gtk_widget_set_margin_start (widget: box, margin: 12);
93 gtk_widget_set_margin_end (widget: box, margin: 12);
94 gtk_widget_set_margin_top (widget: box, margin: 12);
95 gtk_widget_set_margin_bottom (widget: box, margin: 12);
96
97 label = gtk_label_new (str: "You must fill out this entry to continue:");
98 gtk_box_append (GTK_BOX (box), child: label);
99
100 entry = gtk_entry_new ();
101 gtk_accessible_update_relation (self: GTK_ACCESSIBLE (ptr: entry),
102 first_relation: GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
103 -1);
104 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
105 gtk_widget_set_valign (widget: entry, align: GTK_ALIGN_CENTER);
106 gtk_box_append (GTK_BOX (box), child: entry);
107 g_signal_connect (G_OBJECT (entry), "changed",
108 G_CALLBACK (on_entry_changed), assistant);
109
110 gtk_assistant_append_page (GTK_ASSISTANT (assistant), page: box);
111 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), page: box, title: "Page 1");
112 gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), page: box, type: GTK_ASSISTANT_PAGE_INTRO);
113}
114
115static void
116create_page2 (GtkWidget *assistant)
117{
118 GtkWidget *box, *checkbutton;
119
120 box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 12);
121 gtk_widget_set_margin_start (widget: box, margin: 12);
122 gtk_widget_set_margin_end (widget: box, margin: 12);
123 gtk_widget_set_margin_top (widget: box, margin: 12);
124 gtk_widget_set_margin_bottom (widget: box, margin: 12);
125
126 checkbutton = gtk_check_button_new_with_label (label: "This is optional data, you may continue "
127 "even if you do not check this");
128 gtk_widget_set_valign (widget: checkbutton, align: GTK_ALIGN_CENTER);
129 gtk_box_append (GTK_BOX (box), child: checkbutton);
130
131 gtk_assistant_append_page (GTK_ASSISTANT (assistant), page: box);
132 gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), page: box, TRUE);
133 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), page: box, title: "Page 2");
134}
135
136static void
137create_page3 (GtkWidget *assistant)
138{
139 GtkWidget *label;
140
141 label = gtk_label_new (str: "This is a confirmation page, press 'Apply' to apply changes");
142
143 gtk_widget_show (widget: label);
144 gtk_assistant_append_page (GTK_ASSISTANT (assistant), page: label);
145 gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), page: label, type: GTK_ASSISTANT_PAGE_CONFIRM);
146 gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), page: label, TRUE);
147 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), page: label, title: "Confirmation");
148}
149
150static void
151create_page4 (GtkWidget *assistant)
152{
153 progress_bar = gtk_progress_bar_new ();
154 gtk_widget_set_halign (widget: progress_bar, align: GTK_ALIGN_FILL);
155 gtk_widget_set_valign (widget: progress_bar, align: GTK_ALIGN_CENTER);
156 gtk_widget_set_hexpand (widget: progress_bar, TRUE);
157 gtk_widget_set_margin_start (widget: progress_bar, margin: 40);
158 gtk_widget_set_margin_end (widget: progress_bar, margin: 40);
159
160 gtk_widget_show (widget: progress_bar);
161 gtk_assistant_append_page (GTK_ASSISTANT (assistant), page: progress_bar);
162 gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), page: progress_bar, type: GTK_ASSISTANT_PAGE_PROGRESS);
163 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), page: progress_bar, title: "Applying changes");
164
165 /* This prevents the assistant window from being
166 * closed while we're "busy" applying changes.
167 */
168 gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), page: progress_bar, FALSE);
169}
170
171GtkWidget*
172do_assistant (GtkWidget *do_widget)
173{
174 static GtkWidget *assistant;
175
176 if (!assistant)
177 {
178 assistant = gtk_assistant_new ();
179
180 gtk_window_set_default_size (GTK_WINDOW (assistant), width: -1, height: 300);
181
182 gtk_window_set_display (GTK_WINDOW (assistant),
183 display: gtk_widget_get_display (widget: do_widget));
184 g_object_add_weak_pointer (G_OBJECT (assistant), weak_pointer_location: (gpointer *)&assistant);
185
186 create_page1 (assistant);
187 create_page2 (assistant);
188 create_page3 (assistant);
189 create_page4 (assistant);
190
191 g_signal_connect (G_OBJECT (assistant), "cancel",
192 G_CALLBACK (on_assistant_close_cancel), NULL);
193 g_signal_connect (G_OBJECT (assistant), "close",
194 G_CALLBACK (on_assistant_close_cancel), NULL);
195 g_signal_connect (G_OBJECT (assistant), "apply",
196 G_CALLBACK (on_assistant_apply), NULL);
197 g_signal_connect (G_OBJECT (assistant), "prepare",
198 G_CALLBACK (on_assistant_prepare), NULL);
199 }
200
201 if (!gtk_widget_get_visible (widget: assistant))
202 gtk_widget_show (widget: assistant);
203 else
204 gtk_window_destroy (GTK_WINDOW (assistant));
205
206 return assistant;
207}
208

source code of gtk/demos/gtk-demo/assistant.c