1#include <gtk/gtk.h>
2#include "pixbufpaintable.h"
3
4struct _PixbufPaintable {
5 GObject parent_instance;
6
7 char *resource_path;
8 GdkPixbufAnimation *anim;
9 GdkPixbufAnimationIter *iter;
10
11 guint timeout;
12};
13
14enum {
15 PROP_RESOURCE_PATH = 1,
16 NUM_PROPERTIES
17};
18
19G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
20static void
21pixbuf_paintable_snapshot (GdkPaintable *paintable,
22 GdkSnapshot *snapshot,
23 double width,
24 double height)
25{
26 PixbufPaintable *self = PIXBUF_PAINTABLE (ptr: paintable);
27 GTimeVal val;
28 GdkPixbuf *pixbuf;
29 GdkTexture *texture;
30
31 g_get_current_time (result: &val);
32 gdk_pixbuf_animation_iter_advance (iter: self->iter, current_time: &val);
33 pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (iter: self->iter);
34 texture = gdk_texture_new_for_pixbuf (pixbuf);
35
36 gdk_paintable_snapshot (paintable: GDK_PAINTABLE (ptr: texture), snapshot, width, height);
37
38 g_object_unref (object: texture);
39}
40G_GNUC_END_IGNORE_DEPRECATIONS;
41
42static int
43pixbuf_paintable_get_intrinsic_width (GdkPaintable *paintable)
44{
45 PixbufPaintable *self = PIXBUF_PAINTABLE (ptr: paintable);
46
47 return gdk_pixbuf_animation_get_width (animation: self->anim);
48}
49
50static int
51pixbuf_paintable_get_intrinsic_height (GdkPaintable *paintable)
52{
53 PixbufPaintable *self = PIXBUF_PAINTABLE (ptr: paintable);
54
55 return gdk_pixbuf_animation_get_height (animation: self->anim);
56}
57
58static void
59pixbuf_paintable_init_interface (GdkPaintableInterface *iface)
60{
61 iface->snapshot = pixbuf_paintable_snapshot;
62 iface->get_intrinsic_width = pixbuf_paintable_get_intrinsic_width;
63 iface->get_intrinsic_height = pixbuf_paintable_get_intrinsic_height;
64}
65
66G_DEFINE_TYPE_WITH_CODE(PixbufPaintable, pixbuf_paintable, G_TYPE_OBJECT,
67 G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
68 pixbuf_paintable_init_interface))
69
70static void
71pixbuf_paintable_init (PixbufPaintable *paintable)
72{
73}
74
75static gboolean
76delay_cb (gpointer data)
77{
78 PixbufPaintable *self = data;
79 int delay;
80
81 delay = gdk_pixbuf_animation_iter_get_delay_time (iter: self->iter);
82 self->timeout = g_timeout_add (interval: delay, function: delay_cb, data: self);
83
84 gdk_paintable_invalidate_contents (paintable: GDK_PAINTABLE (ptr: self));
85
86 return G_SOURCE_REMOVE;
87}
88
89static void
90pixbuf_paintable_set_resource_path (PixbufPaintable *self,
91 const char *resource_path)
92{
93 int delay;
94
95 g_free (mem: self->resource_path);
96 self->resource_path = g_strdup (str: resource_path);
97
98 g_clear_object (&self->anim);
99 self->anim = gdk_pixbuf_animation_new_from_resource (resource_path, NULL);
100 g_clear_object (&self->iter);
101 self->iter = gdk_pixbuf_animation_get_iter (animation: self->anim, NULL);
102
103 delay = gdk_pixbuf_animation_iter_get_delay_time (iter: self->iter);
104 self->timeout = g_timeout_add (interval: delay, function: delay_cb, data: self);
105
106 gdk_paintable_invalidate_contents (paintable: GDK_PAINTABLE (ptr: self));
107
108 g_object_notify (G_OBJECT (self), property_name: "resource-path");
109}
110
111static void
112pixbuf_paintable_set_property (GObject *object,
113 guint prop_id,
114 const GValue *value,
115 GParamSpec *pspec)
116{
117 PixbufPaintable *self = PIXBUF_PAINTABLE (ptr: object);
118
119 switch (prop_id)
120 {
121 case PROP_RESOURCE_PATH:
122 pixbuf_paintable_set_resource_path (self, resource_path: g_value_get_string (value));
123 break;
124
125 default:
126 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
127 }
128}
129
130static void
131pixbuf_paintable_get_property (GObject *object,
132 guint prop_id,
133 GValue *value,
134 GParamSpec *pspec)
135{
136 PixbufPaintable *self = PIXBUF_PAINTABLE (ptr: object);
137
138 switch (prop_id)
139 {
140 case PROP_RESOURCE_PATH:
141 g_value_set_string (value, v_string: self->resource_path);
142 break;
143
144 default:
145 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
146 }
147}
148
149static void
150pixbuf_paintable_dispose (GObject *object)
151{
152 PixbufPaintable *self = PIXBUF_PAINTABLE (ptr: object);
153
154 g_clear_pointer (&self->resource_path, g_free);
155 g_clear_object (&self->anim);
156 g_clear_object (&self->iter);
157 if (self->timeout)
158 {
159 g_source_remove (tag: self->timeout);
160 self->timeout = 0;
161 }
162
163 G_OBJECT_CLASS (pixbuf_paintable_parent_class)->dispose (object);
164}
165
166static void
167pixbuf_paintable_class_init (PixbufPaintableClass *class)
168{
169 GObjectClass *object_class = G_OBJECT_CLASS (class);
170
171 object_class->dispose = pixbuf_paintable_dispose;
172 object_class->get_property = pixbuf_paintable_get_property;
173 object_class->set_property = pixbuf_paintable_set_property;
174
175 g_object_class_install_property (oclass: object_class, property_id: PROP_RESOURCE_PATH,
176 pspec: g_param_spec_string (name: "resource-path", nick: "Resource path", blurb: "Resource path",
177 NULL, flags: G_PARAM_READWRITE));
178
179}
180
181GdkPaintable *
182pixbuf_paintable_new_from_resource (const char *path)
183{
184 return g_object_new (PIXBUF_TYPE_PAINTABLE,
185 first_property_name: "resource-path", path,
186 NULL);
187}
188

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