1/* Benchmark/Fishbowl
2 *
3 * This demo models the fishbowl demos seen on the web in a GTK way.
4 * It's also a neat little tool to see how fast your computer (or
5 * your GTK version) is.
6 */
7
8#include <gtk/gtk.h>
9
10#include "gtkfishbowl.h"
11#include "gtkgears.h"
12#include "gskshaderpaintable.h"
13
14const char *const css =
15".blurred-button {"
16" box-shadow: 0px 0px 5px 10px rgba(0, 0, 0, 0.5);"
17"}"
18"";
19
20char **icon_names = NULL;
21gsize n_icon_names = 0;
22
23static void
24init_icon_names (GtkIconTheme *theme)
25{
26 if (icon_names)
27 return;
28
29 icon_names = gtk_icon_theme_get_icon_names (self: theme);
30 n_icon_names = g_strv_length (str_array: icon_names);
31}
32
33static const char *
34get_random_icon_name (GtkIconTheme *theme)
35{
36 init_icon_names (theme);
37
38 return icon_names[g_random_int_range(begin: 0, end: n_icon_names)];
39}
40
41/* Can't be static because it's also used in iconscroll.c */
42GtkWidget *
43create_icon (void)
44{
45 GtkWidget *image;
46
47 image = gtk_image_new ();
48 gtk_image_set_icon_size (GTK_IMAGE (image), icon_size: GTK_ICON_SIZE_LARGE);
49 gtk_image_set_from_icon_name (GTK_IMAGE (image),
50 icon_name: get_random_icon_name (theme: gtk_icon_theme_get_for_display (display: gtk_widget_get_display (widget: image))));
51
52 return image;
53}
54
55static GtkWidget *
56create_button (void)
57{
58 return gtk_button_new_with_label (label: "Button");
59}
60
61static GtkWidget *
62create_blurred_button (void)
63{
64 GtkWidget *w = gtk_button_new ();
65
66 gtk_widget_add_css_class (widget: w, css_class: "blurred-button");
67
68 return w;
69}
70
71static GtkWidget *
72create_font_button (void)
73{
74 return gtk_font_button_new ();
75}
76
77static GtkWidget *
78create_level_bar (void)
79{
80 GtkWidget *w = gtk_level_bar_new_for_interval (min_value: 0, max_value: 100);
81
82 gtk_level_bar_set_value (GTK_LEVEL_BAR (w), value: 50);
83
84 /* Force them to be a bit larger */
85 gtk_widget_set_size_request (widget: w, width: 200, height: -1);
86
87 return w;
88}
89
90static GtkWidget *
91create_spinner (void)
92{
93 GtkWidget *w = gtk_spinner_new ();
94
95 gtk_spinner_start (GTK_SPINNER (w));
96
97 return w;
98}
99
100static GtkWidget *
101create_spinbutton (void)
102{
103 GtkWidget *w = gtk_spin_button_new_with_range (min: 0, max: 10, step: 1);
104
105 return w;
106}
107
108static GtkWidget *
109create_label (void)
110{
111 GtkWidget *w = gtk_label_new (str: "pLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.");
112
113 gtk_label_set_wrap (GTK_LABEL (w), TRUE);
114 gtk_label_set_max_width_chars (GTK_LABEL (w), n_chars: 100);
115
116 return w;
117}
118
119static GtkWidget *
120create_video (void)
121{
122 GtkWidget *w = gtk_video_new ();
123
124 gtk_widget_set_size_request (widget: w, width: 64, height: 64);
125 gtk_video_set_loop (self: GTK_VIDEO (ptr: w), TRUE);
126 gtk_video_set_autoplay (self: GTK_VIDEO (ptr: w), TRUE);
127 gtk_video_set_resource (self: GTK_VIDEO (ptr: w), resource_path: "/images/gtk-logo.webm");
128
129 return w;
130}
131
132static GtkWidget *
133create_gears (void)
134{
135 GtkWidget *w = gtk_gears_new ();
136
137 gtk_widget_set_size_request (widget: w, width: 100, height: 100);
138
139 return w;
140}
141
142static GtkWidget *
143create_switch (void)
144{
145 GtkWidget *w = gtk_switch_new ();
146
147 gtk_switch_set_state (GTK_SWITCH (w), TRUE);
148
149 return w;
150}
151
152static gboolean
153update_paintable (GtkWidget *widget,
154 GdkFrameClock *frame_clock,
155 gpointer user_data)
156{
157 GskShaderPaintable *paintable;
158 gint64 frame_time;
159
160 paintable = GSK_SHADER_PAINTABLE (ptr: gtk_picture_get_paintable (self: GTK_PICTURE (ptr: widget)));
161 frame_time = gdk_frame_clock_get_frame_time (frame_clock);
162 gsk_shader_paintable_update_time (self: paintable, time_idx: 0, frame_time);
163
164 return G_SOURCE_CONTINUE;
165}
166
167static GtkWidget *
168create_cogs (void)
169{
170 GtkWidget *picture;
171 static GskGLShader *cog_shader = NULL;
172 GdkPaintable *paintable;
173
174 if (cog_shader == NULL)
175 cog_shader = gsk_gl_shader_new_from_resource (resource_path: "/gltransition/cogs2.glsl");
176 paintable = gsk_shader_paintable_new (g_object_ref (cog_shader), NULL);
177 picture = gtk_picture_new_for_paintable (paintable);
178 gtk_widget_set_size_request (widget: picture, width: 150, height: 75);
179 gtk_widget_add_tick_callback (widget: picture, callback: update_paintable, NULL, NULL);
180
181 return picture;
182}
183
184static void
185mapped (GtkWidget *w)
186{
187 gtk_menu_button_popup (GTK_MENU_BUTTON (w));
188}
189
190static GtkWidget *
191create_menu_button (void)
192{
193 GtkWidget *w = gtk_menu_button_new ();
194 GtkWidget *popover = gtk_popover_new ();
195
196 gtk_popover_set_child (GTK_POPOVER (popover), child: gtk_button_new_with_label (label: "Hey!"));
197 gtk_popover_set_autohide (GTK_POPOVER (popover), FALSE);
198 gtk_menu_button_set_popover (GTK_MENU_BUTTON (w), popover);
199 g_signal_connect (w, "map", G_CALLBACK (mapped), NULL);
200
201 return w;
202}
203
204static const struct {
205 const char *name;
206 GtkWidget * (*create_func) (void);
207} widget_types[] = {
208 { "Icon", create_icon },
209 { "Button", create_button },
210 { "Blurbutton", create_blurred_button },
211 { "Fontbutton", create_font_button },
212 { "Levelbar", create_level_bar },
213 { "Label", create_label },
214 { "Spinner", create_spinner },
215 { "Spinbutton", create_spinbutton },
216 { "Video", create_video },
217 { "Gears", create_gears },
218 { "Switch", create_switch },
219 { "Menubutton", create_menu_button },
220 { "Shader", create_cogs },
221};
222
223static int selected_widget_type = -1;
224static const int N_WIDGET_TYPES = G_N_ELEMENTS (widget_types);
225
226static void
227set_widget_type (GtkFishbowl *fishbowl,
228 int widget_type_index)
229{
230 GtkWidget *window;
231
232 if (widget_type_index == selected_widget_type)
233 return;
234
235 selected_widget_type = widget_type_index;
236
237 gtk_fishbowl_set_creation_func (fishbowl,
238 creation_func: widget_types[selected_widget_type].create_func);
239
240 window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (fishbowl)));
241 gtk_window_set_title (GTK_WINDOW (window),
242 title: widget_types[selected_widget_type].name);
243}
244
245G_MODULE_EXPORT void
246fishbowl_next_button_clicked_cb (GtkButton *source,
247 gpointer user_data)
248{
249 GtkFishbowl *fishbowl = user_data;
250 int new_index;
251
252 if (selected_widget_type + 1 >= N_WIDGET_TYPES)
253 new_index = 0;
254 else
255 new_index = selected_widget_type + 1;
256
257 set_widget_type (fishbowl, widget_type_index: new_index);
258}
259
260G_MODULE_EXPORT void
261fishbowl_prev_button_clicked_cb (GtkButton *source,
262 gpointer user_data)
263{
264 GtkFishbowl *fishbowl = user_data;
265 int new_index;
266
267 if (selected_widget_type - 1 < 0)
268 new_index = N_WIDGET_TYPES - 1;
269 else
270 new_index = selected_widget_type - 1;
271
272 set_widget_type (fishbowl, widget_type_index: new_index);
273}
274
275G_MODULE_EXPORT void
276fishbowl_changes_toggled_cb (GtkToggleButton *button,
277 gpointer user_data)
278{
279 if (gtk_toggle_button_get_active (toggle_button: button))
280 gtk_button_set_icon_name (GTK_BUTTON (button), icon_name: "changes-prevent");
281 else
282 gtk_button_set_icon_name (GTK_BUTTON (button), icon_name: "changes-allow");
283}
284
285G_MODULE_EXPORT char *
286format_header_cb (GObject *object,
287 guint count,
288 double fps)
289{
290 return g_strdup_printf (format: "%u Icons, %.2f fps", count, fps);
291}
292
293GtkWidget *
294do_fishbowl (GtkWidget *do_widget)
295{
296 static GtkWidget *window = NULL;
297 static GtkCssProvider *provider = NULL;
298
299 if (provider == NULL)
300 {
301 provider = gtk_css_provider_new ();
302 gtk_css_provider_load_from_data (css_provider: provider, data: css, length: -1);
303 gtk_style_context_add_provider_for_display (display: gdk_display_get_default (),
304 GTK_STYLE_PROVIDER (provider),
305 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
306 }
307
308 if (!window)
309 {
310 GtkBuilder *builder;
311 GtkWidget *bowl;
312
313 g_type_ensure (GTK_TYPE_FISHBOWL);
314
315 builder = gtk_builder_new_from_resource (resource_path: "/fishbowl/fishbowl.ui");
316 window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
317 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
318
319 bowl = GTK_WIDGET (gtk_builder_get_object (builder, "bowl"));
320 selected_widget_type = -1;
321 set_widget_type (GTK_FISHBOWL (bowl), widget_type_index: 0);
322 gtk_window_set_display (GTK_WINDOW (window),
323 display: gtk_widget_get_display (widget: do_widget));
324
325 gtk_widget_realize (widget: window);
326 g_object_unref (object: builder);
327 }
328
329 if (!gtk_widget_get_visible (widget: window))
330 gtk_widget_show (widget: window);
331 else
332 gtk_window_destroy (GTK_WINDOW (window));
333
334 return window;
335}
336

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