1/* Benchmark/Scrolling
2 * #Keywords: GtkScrolledWindow
3 *
4 * This demo scrolls a view with various content.
5 */
6
7#include <gtk/gtk.h>
8
9static guint tick_cb;
10static GtkAdjustment *hadjustment;
11static GtkAdjustment *vadjustment;
12static GtkWidget *window = NULL;
13static GtkWidget *scrolledwindow;
14static int selected;
15
16#define N_WIDGET_TYPES 8
17
18
19static int hincrement = 5;
20static int vincrement = 5;
21
22static gboolean
23scroll_cb (GtkWidget *widget,
24 GdkFrameClock *frame_clock,
25 gpointer data)
26{
27 double value;
28
29 value = gtk_adjustment_get_value (adjustment: vadjustment);
30 if (value + vincrement <= gtk_adjustment_get_lower (adjustment: vadjustment) ||
31 (value + vincrement >= gtk_adjustment_get_upper (adjustment: vadjustment) - gtk_adjustment_get_page_size (adjustment: vadjustment)))
32 vincrement = - vincrement;
33
34 gtk_adjustment_set_value (adjustment: vadjustment, value: value + vincrement);
35
36 value = gtk_adjustment_get_value (adjustment: hadjustment);
37 if (value + hincrement <= gtk_adjustment_get_lower (adjustment: hadjustment) ||
38 (value + hincrement >= gtk_adjustment_get_upper (adjustment: hadjustment) - gtk_adjustment_get_page_size (adjustment: hadjustment)))
39 hincrement = - hincrement;
40
41 gtk_adjustment_set_value (adjustment: hadjustment, value: value + hincrement);
42
43 return G_SOURCE_CONTINUE;
44}
45
46extern GtkWidget *create_icon (void);
47
48static void
49populate_icons (void)
50{
51 GtkWidget *grid;
52 int top, left;
53
54 grid = gtk_grid_new ();
55 gtk_widget_set_halign (widget: grid, align: GTK_ALIGN_CENTER);
56 gtk_widget_set_margin_start (widget: grid, margin: 10);
57 gtk_widget_set_margin_end (widget: grid, margin: 10);
58 gtk_widget_set_margin_top (widget: grid, margin: 10);
59 gtk_widget_set_margin_bottom (widget: grid, margin: 10);
60 gtk_grid_set_row_spacing (GTK_GRID (grid), spacing: 10);
61 gtk_grid_set_column_spacing (GTK_GRID (grid), spacing: 10);
62
63 for (top = 0; top < 100; top++)
64 for (left = 0; left < 15; left++)
65 gtk_grid_attach (GTK_GRID (grid), child: create_icon (), column: left, row: top, width: 1, height: 1);
66
67 hincrement = 0;
68 vincrement = 5;
69
70 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
71 hscrollbar_policy: GTK_POLICY_NEVER,
72 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
73 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: grid);
74}
75
76static char *content;
77static gsize content_len;
78
79extern void fontify (const char *format, GtkTextBuffer *buffer);
80
81static void
82populate_text (gboolean highlight)
83{
84 GtkWidget *textview;
85 GtkTextBuffer *buffer;
86
87 if (!content)
88 {
89 GBytes *bytes;
90
91 bytes = g_resources_lookup_data (path: "/sources/font_features.c", lookup_flags: 0, NULL);
92 content = g_bytes_unref_to_data (bytes, size: &content_len);
93 }
94
95 buffer = gtk_text_buffer_new (NULL);
96 gtk_text_buffer_set_text (buffer, text: content, len: (int)content_len);
97
98 if (highlight)
99 fontify (format: "c", buffer);
100
101 textview = gtk_text_view_new ();
102 gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
103
104 hincrement = 0;
105 vincrement = 5;
106
107 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
108 hscrollbar_policy: GTK_POLICY_NEVER,
109 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
110 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: textview);
111}
112
113static void
114populate_emoji_text (void)
115{
116 GtkWidget *textview;
117 GtkTextBuffer *buffer;
118 GString *s;
119 GtkTextIter iter;
120
121 s = g_string_sized_new (dfl_size: 500 * 30 * 4);
122
123 for (int i = 0; i < 500; i++)
124 {
125 if (i % 2)
126 g_string_append (string: s, val: "<span underline=\"single\" underline_color=\"red\">x</span>");
127 for (int j = 0; j < 30; j++)
128 {
129 g_string_append (string: s, val: "💓");
130 g_string_append (string: s, val: "<span underline=\"single\" underline_color=\"red\">x</span>");
131 }
132 g_string_append (string: s, val: "\n");
133 }
134
135 buffer = gtk_text_buffer_new (NULL);
136 gtk_text_buffer_get_start_iter (buffer, iter: &iter);
137 gtk_text_buffer_insert_markup (buffer, iter: &iter, markup: s->str, len: s->len);
138
139 g_string_free (string: s, TRUE);
140
141 textview = gtk_text_view_new ();
142 gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
143
144 hincrement = 0;
145 vincrement = 5;
146
147 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
148 hscrollbar_policy: GTK_POLICY_NEVER,
149 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
150 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: textview);
151}
152
153static void
154populate_image (void)
155{
156 GtkWidget *image;
157
158 if (!content)
159 {
160 GBytes *bytes;
161
162 bytes = g_resources_lookup_data (path: "/sources/font_features.c", lookup_flags: 0, NULL);
163 content = g_bytes_unref_to_data (bytes, size: &content_len);
164 }
165
166 image = gtk_picture_new_for_resource (resource_path: "/sliding_puzzle/portland-rose.jpg");
167 gtk_picture_set_can_shrink (self: GTK_PICTURE (ptr: image), FALSE);
168
169 hincrement = 5;
170 vincrement = 5;
171
172 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
173 hscrollbar_policy: GTK_POLICY_AUTOMATIC,
174 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
175 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: image);
176}
177
178extern GtkWidget *create_weather_view (void);
179
180static void
181populate_list (void)
182{
183 GtkWidget *list;
184
185 list = create_weather_view ();
186
187 hincrement = 5;
188 vincrement = 0;
189
190 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
191 hscrollbar_policy: GTK_POLICY_AUTOMATIC,
192 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
193 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: list);
194}
195
196extern GtkWidget *create_color_grid (void);
197extern GListModel *gtk_color_list_new (guint size);
198
199static void
200populate_grid (void)
201{
202 GtkWidget *list;
203 GtkNoSelection *selection;
204
205 list = create_color_grid ();
206
207 selection = gtk_no_selection_new (model: gtk_color_list_new (size: 2097152));
208 gtk_grid_view_set_model (GTK_GRID_VIEW (list), model: GTK_SELECTION_MODEL (ptr: selection));
209 g_object_unref (object: selection);
210
211 hincrement = 0;
212 vincrement = 5;
213
214 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
215 hscrollbar_policy: GTK_POLICY_AUTOMATIC,
216 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
217 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: list);
218}
219
220extern GtkWidget *create_ucd_view (GtkWidget *label);
221
222static void
223populate_list2 (void)
224{
225 GtkWidget *list;
226
227 list = create_ucd_view (NULL);
228
229 hincrement = 0;
230 vincrement = 5;
231
232 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
233 hscrollbar_policy: GTK_POLICY_AUTOMATIC,
234 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
235 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), child: list);
236}
237
238static void
239set_widget_type (int type)
240{
241 if (tick_cb)
242 gtk_widget_remove_tick_callback (widget: window, id: tick_cb);
243
244 if (gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (scrolledwindow)))
245 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), NULL);
246
247 selected = type;
248
249 switch (selected)
250 {
251 case 0:
252 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling icons");
253 populate_icons ();
254 break;
255
256 case 1:
257 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling plain text");
258 populate_text (FALSE);
259 break;
260
261 case 2:
262 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling complex text");
263 populate_text (TRUE);
264 break;
265
266 case 3:
267 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling text with Emoji");
268 populate_emoji_text ();
269 break;
270
271 case 4:
272 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling a big image");
273 populate_image ();
274 break;
275
276 case 5:
277 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling a list");
278 populate_list ();
279 break;
280
281 case 6:
282 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling a columned list");
283 populate_list2 ();
284 break;
285
286 case 7:
287 gtk_window_set_title (GTK_WINDOW (window), title: "Scrolling a grid");
288 populate_grid ();
289 break;
290
291 default:
292 g_assert_not_reached ();
293 }
294
295 tick_cb = gtk_widget_add_tick_callback (widget: window, callback: scroll_cb, NULL, NULL);
296}
297
298G_MODULE_EXPORT void
299iconscroll_next_clicked_cb (GtkButton *source,
300 gpointer user_data)
301{
302 int new_index;
303
304 if (selected + 1 >= N_WIDGET_TYPES)
305 new_index = 0;
306 else
307 new_index = selected + 1;
308
309
310 set_widget_type (new_index);
311}
312
313G_MODULE_EXPORT void
314iconscroll_prev_clicked_cb (GtkButton *source,
315 gpointer user_data)
316{
317 int new_index;
318
319 if (selected - 1 < 0)
320 new_index = N_WIDGET_TYPES - 1;
321 else
322 new_index = selected - 1;
323
324 set_widget_type (new_index);
325}
326
327static gboolean
328update_fps (gpointer data)
329{
330 GtkWidget *label = data;
331 GdkFrameClock *frame_clock;
332 double fps;
333 char *str;
334
335 frame_clock = gtk_widget_get_frame_clock (widget: label);
336
337 fps = gdk_frame_clock_get_fps (frame_clock);
338 str = g_strdup_printf (format: "%.2f fps", fps);
339 gtk_label_set_label (GTK_LABEL (label), str);
340 g_free (mem: str);
341
342 return G_SOURCE_CONTINUE;
343}
344
345static void
346remove_timeout (gpointer data)
347{
348 g_source_remove (GPOINTER_TO_UINT (data));
349}
350
351G_MODULE_EXPORT GtkWidget *
352do_iconscroll (GtkWidget *do_widget)
353{
354 if (!window)
355 {
356 GtkBuilder *builder;
357 GtkWidget *label;
358 guint id;
359
360 builder = gtk_builder_new_from_resource (resource_path: "/iconscroll/iconscroll.ui");
361 window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
362 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
363 gtk_window_set_display (GTK_WINDOW (window),
364 display: gtk_widget_get_display (widget: do_widget));
365
366 scrolledwindow = GTK_WIDGET (gtk_builder_get_object (builder, "scrolledwindow"));
367 gtk_widget_realize (widget: window);
368 hadjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "hadjustment"));
369 vadjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "vadjustment"));
370 set_widget_type (0);
371
372 label = GTK_WIDGET (gtk_builder_get_object (builder, "fps_label"));
373 id = g_timeout_add (interval: 500, function: update_fps, data: label);
374 g_object_set_data_full (G_OBJECT (label), key: "timeout",
375 GUINT_TO_POINTER (id), destroy: remove_timeout);
376
377 g_object_unref (object: builder);
378 }
379
380 if (!gtk_widget_get_visible (widget: window))
381 gtk_widget_show (widget: window);
382 else
383 gtk_window_destroy (GTK_WINDOW (window));
384
385 return window;
386}
387

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