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 | |
10 | static GtkWidget *progress_bar = NULL; |
11 | |
12 | static gboolean |
13 | apply_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 | |
34 | static void |
35 | on_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 | |
41 | static void |
42 | on_assistant_close_cancel (GtkWidget *widget, gpointer data) |
43 | { |
44 | gtk_window_destroy (GTK_WINDOW (widget)); |
45 | } |
46 | |
47 | static void |
48 | on_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 | |
68 | static void |
69 | on_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 | |
86 | static void |
87 | create_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 | |
115 | static void |
116 | create_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 | |
136 | static void |
137 | create_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 | |
150 | static void |
151 | create_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 | |
171 | GtkWidget* |
172 | do_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 | |