1/* Paintable/Emblems
2 *
3 * This demo shows how GdkPaintable can be used to
4 * overlay an emblem on top of an icon. The emblem
5 * can either be another icon, or an arbitrary
6 * paintable.
7 */
8
9#include <gtk/gtk.h>
10
11#include "paintable.h"
12
13static GtkWidget *window = NULL;
14
15#define DEMO_TYPE_ICON (demo_icon_get_type ())
16G_DECLARE_FINAL_TYPE (DemoIcon, demo_icon, DEMO, ICON, GObject)
17
18struct _DemoIcon
19{
20 GObject parent_instance;
21
22 GdkPaintable *icon;
23 GdkPaintable *emblem;
24 GdkPaintableFlags flags;
25};
26
27struct _DemoIconClass
28{
29 GObjectClass parent_class;
30};
31
32void
33demo_icon_snapshot (GdkPaintable *paintable,
34 GtkSnapshot *snapshot,
35 double width,
36 double height)
37{
38 DemoIcon *self = DEMO_ICON (ptr: paintable);
39
40 gdk_paintable_snapshot (paintable: self->icon, snapshot, width, height);
41 gtk_snapshot_save (snapshot);
42 gtk_snapshot_translate (snapshot, point: &GRAPHENE_POINT_INIT (0.5 * width, 0));
43 gdk_paintable_snapshot (paintable: self->emblem, snapshot, width: 0.5 * width, height: 0.5 * height);
44 gtk_snapshot_restore (snapshot);
45}
46
47static GdkPaintableFlags
48demo_icon_get_flags (GdkPaintable *paintable)
49{
50 DemoIcon *self = DEMO_ICON (ptr: paintable);
51
52 return self->flags;
53}
54
55static void
56demo_icon_paintable_init (GdkPaintableInterface *iface)
57{
58 iface->snapshot = demo_icon_snapshot;
59 iface->get_flags = demo_icon_get_flags;
60}
61
62G_DEFINE_TYPE_WITH_CODE (DemoIcon, demo_icon, G_TYPE_OBJECT,
63 G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
64 demo_icon_paintable_init))
65
66static void
67demo_icon_dispose (GObject *object)
68{
69 DemoIcon *self = DEMO_ICON (ptr: object);
70
71 g_signal_handlers_disconnect_by_func (self->emblem,
72 gdk_paintable_invalidate_contents,
73 self);
74
75 g_clear_object (&self->icon);
76 g_clear_object (&self->emblem);
77
78 G_OBJECT_CLASS (demo_icon_parent_class)->dispose (object);
79}
80
81static void
82demo_icon_class_init (DemoIconClass *klass)
83{
84 GObjectClass *object_class = G_OBJECT_CLASS (klass);
85
86 object_class->dispose = demo_icon_dispose;
87}
88
89static void
90demo_icon_init (DemoIcon *self)
91{
92 self->flags = GDK_PAINTABLE_STATIC_SIZE | GDK_PAINTABLE_STATIC_CONTENTS;
93}
94
95GdkPaintable *
96demo_icon_new_with_paintable (const char *icon_name,
97 GdkPaintable *emblem)
98{
99 GtkIconTheme *theme;
100 GtkIconPaintable *icon;
101 DemoIcon *self;
102
103 theme = gtk_icon_theme_get_for_display (display: gdk_display_get_default ());
104
105 icon = gtk_icon_theme_lookup_icon (self: theme,
106 icon_name, NULL,
107 size: 128, scale: 1,
108 direction: GTK_TEXT_DIR_LTR, flags: 0);
109
110 self = g_object_new (DEMO_TYPE_ICON, NULL);
111
112 self->icon = GDK_PAINTABLE (ptr: icon);
113 self->emblem = emblem;
114
115 if ((gdk_paintable_get_flags (paintable: emblem) & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
116 {
117 self->flags &= ~GDK_PAINTABLE_STATIC_CONTENTS;
118
119 g_signal_connect_swapped (emblem, "invalidate-contents",
120 G_CALLBACK (gdk_paintable_invalidate_contents), self);
121 }
122
123 return GDK_PAINTABLE (ptr: self);
124}
125
126GdkPaintable *
127demo_icon_new (const char *icon_name,
128 const char *emblem_name)
129{
130 GtkIconTheme *theme;
131 GtkIconPaintable *emblem;
132
133 theme = gtk_icon_theme_get_for_display (display: gdk_display_get_default ());
134
135 emblem = gtk_icon_theme_lookup_icon (self: theme,
136 icon_name: emblem_name, NULL,
137 size: 128, scale: 1,
138 direction: GTK_TEXT_DIR_LTR, flags: 0);
139
140 return GDK_PAINTABLE (ptr: demo_icon_new_with_paintable (icon_name,
141 emblem: GDK_PAINTABLE (ptr: emblem)));
142}
143
144GtkWidget *
145do_paintable_emblem (GtkWidget *do_widget)
146{
147 GdkPaintable *icon;
148 GtkWidget *grid;
149 GtkWidget *image;
150
151 if (!window)
152 {
153 window = gtk_window_new ();
154 gtk_window_set_display (GTK_WINDOW (window),
155 display: gtk_widget_get_display (widget: do_widget));
156 gtk_window_set_title (GTK_WINDOW (window), title: "Paintable — Emblems");
157 gtk_window_set_default_size (GTK_WINDOW (window), width: 300, height: 200);
158 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
159
160 grid = gtk_grid_new ();
161
162 icon = demo_icon_new (icon_name: "folder", emblem_name: "starred");
163 image = gtk_image_new_from_paintable (paintable: icon);
164 gtk_widget_set_hexpand (widget: image, TRUE);
165 gtk_widget_set_vexpand (widget: image, TRUE);
166 gtk_grid_attach (GTK_GRID (grid), child: image, column: 0, row: 0, width: 1, height: 1);
167
168 icon = demo_icon_new_with_paintable (icon_name: "drive-multidisk",
169 emblem: gtk_nuclear_animation_new (FALSE));
170 image = gtk_image_new_from_paintable (paintable: icon);
171 gtk_widget_set_hexpand (widget: image, TRUE);
172 gtk_widget_set_vexpand (widget: image, TRUE);
173 gtk_grid_attach (GTK_GRID (grid), child: image, column: 1, row: 0, width: 1, height: 1);
174
175 gtk_window_set_child (GTK_WINDOW (window), child: grid);
176 g_object_unref (object: icon);
177 }
178
179 if (!gtk_widget_get_visible (widget: window))
180 gtk_widget_show (widget: window);
181 else
182 gtk_window_destroy (GTK_WINDOW (window));
183
184 return window;
185}
186
187

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