Merge lp:~cimi/overlay-scrollbar/animated-colorization into lp:overlay-scrollbar

Proposed by Andrea Cimitan
Status: Merged
Merged at revision: 188
Proposed branch: lp:~cimi/overlay-scrollbar/animated-colorization
Merge into: lp:overlay-scrollbar
Diff against target: 505 lines (+372/-12)
5 files modified
os/Makefile.am (+1/-0)
os/os-animation.c (+237/-0)
os/os-pager.c (+75/-5)
os/os-private.h (+46/-0)
os/os-scrollbar.c (+13/-7)
To merge this branch: bzr merge lp:~cimi/overlay-scrollbar/animated-colorization
Reviewer Review Type Date Requested Status
Loïc Molinari (community) Approve
Ted Gould (community) Needs Fixing
Review via email: mp+55858@code.launchpad.net

Description of the change

Fade animation to colorize the pager

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

For animations of this kind you really need to not do them with frames
but have them be final end and beginning time based. This is because
the timers aren't guaranteed to be at particular times, so you need to
be robust to that and still ensure the animation doesn't take too long.

  review needsfixing

review: Needs Fixing
187. By Andrea Cimitan

Use fade_id and g_source_remove to avoid crashes on dispose, use g_get_monotonic_time

188. By Andrea Cimitan

Remove g_object_ref and use just g_source_remove

189. By Andrea Cimitan

Using os-animation.c, new animation API by Loic Molinari

190. By Andrea Cimitan

start fixing os_pager_dispose ()

191. By Andrea Cimitan

remove some previous stuff, switching to the animation api

192. By Andrea Cimitan

Merged trunk

193. By Andrea Cimitan

Fix initial animation

194. By Andrea Cimitan

restore end_func optional call for animation

195. By Andrea Cimitan

OsAnimation is now a GObject, thanks Loic for the help

196. By Andrea Cimitan

updated timeout fade with the new code

197. By Andrea Cimitan

add os_animation_set_duration

198. By Andrea Cimitan

Use set_duration

199. By Andrea Cimitan

Fixes crashes due to references

200. By Andrea Cimitan

check for priv->animation != NULL is os_pager_dispose ()

201. By Andrea Cimitan

set source_id to 0 after g_source_remove

Revision history for this message
Loïc Molinari (loic.molinari) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'os/Makefile.am'
2--- os/Makefile.am 2011-03-03 15:58:07 +0000
3+++ os/Makefile.am 2011-04-04 16:19:33 +0000
4@@ -9,6 +9,7 @@
5 source_c = \
6 $(srcdir)/os-log.c \
7 $(srcdir)/os-utils.c \
8+ $(srcdir)/os-animation.c \
9 $(srcdir)/os-pager.c \
10 $(srcdir)/os-thumb.c \
11 $(srcdir)/os-scrollbar.c
12
13=== added file 'os/os-animation.c'
14--- os/os-animation.c 1970-01-01 00:00:00 +0000
15+++ os/os-animation.c 2011-04-04 16:19:33 +0000
16@@ -0,0 +1,237 @@
17+/* overlay-scrollbar
18+ *
19+ * Copyright © 2011 Canonical Ltd
20+ *
21+ * This library is free software; you can redistribute it and/or
22+ * modify it under the terms of the GNU Lesser General Public
23+ * License as published by the Free Software Foundation; either
24+ * version 2.1 of the License, or (at your option) any later version.
25+ *
26+ * This library is distributed in the hope that it will be useful,
27+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29+ * Lesser General Public License for more details.
30+ *
31+ * You should have received a copy of the GNU Lesser General Public
32+ * License along with this library; if not, write to the
33+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
34+ * Boston, MA 02110-1301 USA
35+ *
36+ * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
37+ * Loïc Molinari <loic.molinari@canonical.com>
38+ */
39+
40+#ifndef HAVE_CONFIG_H
41+#include "config.h"
42+#endif /* HAVE_CONFIG_H */
43+
44+#include "os-private.h"
45+
46+struct _OsAnimationPrivate {
47+ OsAnimationUpdateFunc update_func;
48+ OsAnimationEndFunc end_func;
49+ gpointer user_data;
50+ gint64 start_time;
51+ gint64 duration;
52+ gint32 rate;
53+ guint32 source_id;
54+};
55+
56+static gboolean os_animation_update_cb (gpointer user_data);
57+static void os_animation_dispose (GObject* object);
58+static void os_animation_finalize (GObject* object);
59+
60+/* Private functions. */
61+
62+static gboolean
63+os_animation_update_cb (gpointer user_data)
64+{
65+ OsAnimation *animation = OS_ANIMATION (user_data);
66+ OsAnimationPrivate *priv = animation->priv;
67+ const gint64 current_time = g_get_monotonic_time ();
68+ const gint64 end_time = priv->start_time + priv->duration;
69+
70+ if (current_time < end_time)
71+ {
72+ /* On-going animation. */
73+ const gfloat diff_time = current_time - priv->start_time;
74+ const gfloat weight = diff_time / priv->duration;
75+
76+ priv->update_func (weight, priv->user_data);
77+
78+ return TRUE;
79+ }
80+ else
81+ {
82+ /* Animation ended. */
83+ priv->update_func (1.0f, priv->user_data);
84+ priv->source_id = 0;
85+
86+ if (priv->end_func != NULL)
87+ priv->end_func (priv->user_data);
88+
89+ return FALSE;
90+ }
91+}
92+
93+/* Type definition. */
94+
95+G_DEFINE_TYPE (OsAnimation, os_animation, G_TYPE_OBJECT);
96+
97+static void
98+os_animation_class_init (OsAnimationClass *class)
99+{
100+ GObjectClass *gobject_class;
101+
102+ gobject_class = G_OBJECT_CLASS (class);
103+
104+ gobject_class->dispose = os_animation_dispose;
105+ gobject_class->finalize = os_animation_finalize;
106+
107+ g_type_class_add_private (gobject_class, sizeof (OsAnimationPrivate));
108+}
109+
110+static void
111+os_animation_init (OsAnimation *animation)
112+{
113+ OsAnimationPrivate *priv;
114+
115+ animation->priv = G_TYPE_INSTANCE_GET_PRIVATE (animation,
116+ OS_TYPE_ANIMATION,
117+ OsAnimationPrivate);
118+ priv = animation->priv;
119+
120+ priv->source_id = 0;
121+}
122+
123+static void
124+os_animation_dispose (GObject* object)
125+{
126+ OsAnimation *animation;
127+ OsAnimationPrivate *priv;
128+
129+ animation = OS_ANIMATION (object);
130+ priv = animation->priv;
131+
132+ if (priv->source_id != 0)
133+ {
134+ g_source_remove (priv->source_id);
135+ priv->source_id = 0;
136+ }
137+
138+ G_OBJECT_CLASS (os_animation_parent_class)->dispose (object);
139+}
140+
141+static void
142+os_animation_finalize (GObject* object)
143+{
144+ G_OBJECT_CLASS (os_animation_parent_class)->finalize (object);
145+}
146+
147+/* Public functions. */
148+
149+/**
150+ * os_animation_new:
151+ * @rate: rate of the update
152+ * @duration: duration of the animation
153+ * @update_func: function to call on update
154+ * @end_func: function to call at the end
155+ * @user_data: pointer to the user data
156+ *
157+ * Creates a new OsAnimation
158+ *
159+ * Returns: the pointer to the #OsAnimation
160+ */
161+OsAnimation*
162+os_animation_new (gint32 rate,
163+ gint32 duration,
164+ OsAnimationUpdateFunc update_func,
165+ OsAnimationEndFunc end_func,
166+ gpointer user_data)
167+{
168+ OsAnimation* animation;
169+ OsAnimationPrivate* priv;
170+
171+ g_return_val_if_fail (rate != 0, NULL);
172+ g_return_val_if_fail (duration != 0, NULL);
173+ g_return_val_if_fail (update_func != NULL, NULL);
174+
175+ animation = g_object_new (OS_TYPE_ANIMATION, NULL);
176+ priv = animation->priv;
177+
178+ priv->update_func = update_func;
179+ priv->end_func = end_func;
180+ priv->user_data = user_data;
181+ priv->duration = (gint64) duration * G_GINT64_CONSTANT (1000);
182+ priv->rate = 1000 / rate;
183+
184+ return animation;
185+}
186+
187+/**
188+ * os_animation_set_duration:
189+ * @animation: a #OsAnimation
190+ * @duration: the new duration
191+ *
192+ * Sets the new duration of the animation
193+ **/
194+void
195+os_animation_set_duration (OsAnimation* animation,
196+ gint32 duration)
197+{
198+ OsAnimationPrivate* priv;
199+
200+ g_return_if_fail (animation != NULL);
201+ g_return_if_fail (duration != 0);
202+
203+ priv = animation->priv;
204+
205+ priv->duration = (gint64) duration * G_GINT64_CONSTANT (1000);
206+}
207+
208+/**
209+ * os_animation_start:
210+ * @animation: a #OsAnimation
211+ *
212+ * Starts the animation
213+ **/
214+void
215+os_animation_start (OsAnimation* animation)
216+{
217+ OsAnimationPrivate* priv;
218+
219+ g_return_if_fail (animation != NULL);
220+
221+ priv = animation->priv;
222+
223+ if (priv->source_id == 0)
224+ {
225+ priv->start_time = g_get_monotonic_time ();
226+ priv->source_id = g_timeout_add (priv->rate, os_animation_update_cb, animation);
227+ }
228+}
229+
230+/**
231+ * os_animation_stop:
232+ * @animation: a #OsAnimation
233+ *
234+ * Stops the animation
235+ **/
236+void
237+os_animation_stop (OsAnimation* animation)
238+{
239+ OsAnimationPrivate* priv;
240+
241+ g_return_if_fail (animation != NULL);
242+
243+ priv = animation->priv;
244+
245+ if (priv->source_id != 0)
246+ {
247+ if (priv->end_func != NULL)
248+ priv->end_func (priv->user_data);
249+
250+ g_source_remove (priv->source_id);
251+ priv->source_id = 0;
252+ }
253+}
254
255=== modified file 'os/os-pager.c'
256--- os/os-pager.c 2011-03-31 17:05:54 +0000
257+++ os/os-pager.c 2011-04-04 16:19:33 +0000
258@@ -28,14 +28,24 @@
259 #include <gdk/gdkx.h>
260 #include "os-private.h"
261
262+/* Rate of the fade */
263+#define RATE_FADE 30
264+
265+/* Duration of the fade-in */
266+#define DURATION_FADE_IN 200
267+
268+/* Duration of the fade-out */
269+#define DURATION_FADE_OUT 400
270
271 struct _OsPagerPrivate {
272 GdkWindow *pager_window;
273 GtkWidget *parent;
274 GdkRectangle mask;
275 GdkRectangle allocation;
276+ OsAnimation *animation;
277 gboolean active;
278 gboolean visible;
279+ gfloat weight;
280 gint width;
281 gint height;
282 };
283@@ -43,6 +53,7 @@
284 static gboolean rectangle_changed (GdkRectangle rectangle1, GdkRectangle rectangle2);
285 static void os_pager_dispose (GObject *object);
286 static void os_pager_finalize (GObject *object);
287+static void os_pager_change_state_cb (gfloat weight, gpointer user_data);
288 static void os_pager_create (OsPager *pager);
289 static void os_pager_draw (OsPager *pager);
290 static void os_pager_mask (OsPager *pager);
291@@ -100,22 +111,57 @@
292 }
293 }
294
295+static void
296+os_pager_change_state_cb (gfloat weight,
297+ gpointer user_data)
298+{
299+ OsPager *pager;
300+ OsPagerPrivate *priv;
301+
302+ pager = OS_PAGER (user_data);
303+
304+ priv = pager->priv;
305+
306+ priv->weight = weight;
307+
308+ os_pager_draw (pager);
309+}
310+
311 /* Draw on the pager. */
312 static void
313 os_pager_draw (OsPager *pager)
314 {
315- OsPagerPrivate *priv;
316+ GdkColor c1, c2, color;
317 GtkStyle *style;
318+ OsPagerPrivate *priv;
319+ gfloat weight;
320
321 priv = pager->priv;
322
323 style = gtk_widget_get_style (priv->parent);
324
325+ if (priv->active == FALSE)
326+ {
327+ c1 = style->base[GTK_STATE_INSENSITIVE];
328+ c2 = style->base[GTK_STATE_SELECTED];
329+ }
330+ else
331+ {
332+ c1 = style->base[GTK_STATE_SELECTED];
333+ c2 = style->base[GTK_STATE_INSENSITIVE];
334+ }
335+
336+ weight = priv->weight;
337+
338+ color.red = weight * c1.red + (1.0 - weight) * c2.red;
339+ color.green = weight * c1.green + (1.0 - weight) * c2.green;
340+ color.blue = weight * c1.blue + (1.0 - weight) * c2.blue;
341+
342+ gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->pager_window), &color, FALSE, TRUE);
343+
344 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
345
346- gdk_window_set_background (priv->pager_window,
347- priv->active ? &style->base[GTK_STATE_SELECTED] :
348- &style->base[GTK_STATE_INSENSITIVE]);
349+ gdk_window_set_background (priv->pager_window, &color);
350
351 gdk_window_clear (priv->pager_window);
352 }
353@@ -177,11 +223,28 @@
354
355 priv->active = FALSE;
356 priv->visible = FALSE;
357+
358+ priv->weight = 1.0f;
359+
360+ priv->animation = os_animation_new (RATE_FADE, DURATION_FADE_OUT,
361+ os_pager_change_state_cb, NULL, pager);
362 }
363
364 static void
365 os_pager_dispose (GObject *object)
366 {
367+ OsPager *pager;
368+ OsPagerPrivate *priv;
369+
370+ pager = OS_PAGER (object);
371+ priv = pager->priv;
372+
373+ if (priv->animation != NULL)
374+ {
375+ g_object_unref (priv->animation);
376+ priv->animation = NULL;
377+ }
378+
379 G_OBJECT_CLASS (os_pager_parent_class)->dispose (object);
380 }
381
382@@ -281,7 +344,12 @@
383 if (priv->parent == NULL)
384 return;
385
386- os_pager_draw (pager);
387+ os_animation_stop (priv->animation);
388+
389+ os_animation_set_duration (priv->animation, priv->active ? DURATION_FADE_IN :
390+ DURATION_FADE_OUT);
391+
392+ os_animation_start (priv->animation);
393 }
394 }
395
396@@ -313,6 +381,8 @@
397 {
398 g_object_ref_sink (priv->parent);
399
400+ priv->weight = 1.0f;
401+
402 os_pager_create (pager);
403 os_pager_draw (pager);
404 os_pager_mask (pager);
405
406=== modified file 'os/os-private.h'
407--- os/os-private.h 2011-03-28 16:17:49 +0000
408+++ os/os-private.h 2011-04-04 16:19:33 +0000
409@@ -93,6 +93,52 @@
410 #define OS_DCHECK(cond)
411 #endif
412
413+/* os-animation.c */
414+
415+#define OS_TYPE_ANIMATION (os_animation_get_type ())
416+#define OS_ANIMATION(obj) \
417+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), OS_TYPE_ANIMATION, OsAnimation))
418+#define OS_ANIMATION_CLASS(klass) \
419+ (G_TYPE_CHECK_CLASS_CAST ((klass), OS_TYPE_ANIMATION, OsAnimationClass))
420+#define OS_IS_ANIMATION(obj) \
421+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OS_TYPE_ANIMATION))
422+#define OS_IS_ANIMATION_CLASS(klass) \
423+ (G_TYPE_CHECK_CLASS_TYPE ((klass), OS_TYPE_ANIMATION))
424+#define OS_ANIMATION_GET_CLASS(obj) \
425+ (G_TYPE_INSTANCE_GET_CLASS ((obj), OS_TYPE_ANIMATION, OsAnimationClass))
426+
427+typedef void (*OsAnimationUpdateFunc) (gfloat weight, gpointer user_data);
428+typedef void (*OsAnimationEndFunc) (gpointer user_data);
429+
430+typedef struct _OsAnimation OsAnimation;
431+typedef struct _OsAnimationPrivate OsAnimationPrivate;
432+typedef struct _OsAnimationClass OsAnimationClass;
433+
434+struct _OsAnimation {
435+ GObject parent_instance;
436+
437+ OsAnimationPrivate *priv;
438+};
439+
440+struct _OsAnimationClass {
441+ GObjectClass parent_class;
442+};
443+
444+GType os_animation_get_type (void);
445+
446+OsAnimation* os_animation_new (gint32 rate,
447+ gint32 duration,
448+ OsAnimationUpdateFunc update_func,
449+ OsAnimationEndFunc end_func,
450+ gpointer user_data);
451+
452+void os_animation_set_duration (OsAnimation* animation,
453+ gint32 duration);
454+
455+void os_animation_start (OsAnimation* animation);
456+
457+void os_animation_stop (OsAnimation* animation);
458+
459 /* os-thumb.c */
460
461 #define OS_TYPE_THUMB (os_thumb_get_type ())
462
463=== modified file 'os/os-scrollbar.c'
464--- os/os-scrollbar.c 2011-04-01 17:22:12 +0000
465+++ os/os-scrollbar.c 2011-04-04 16:19:33 +0000
466@@ -340,7 +340,7 @@
467
468 priv = scrollbar->priv;
469
470- if (priv->can_deactivate_pager)
471+ if (priv->pager != NULL && priv->can_deactivate_pager)
472 os_pager_set_active (OS_PAGER (priv->pager), FALSE);
473 }
474
475@@ -1246,6 +1246,18 @@
476 static void
477 os_scrollbar_dispose (GObject *object)
478 {
479+ OsScrollbar *scrollbar;
480+ OsScrollbarPrivate *priv;
481+
482+ scrollbar = OS_SCROLLBAR (object);
483+ priv = scrollbar->priv;
484+
485+ if (priv->pager != NULL)
486+ {
487+ g_object_unref (priv->pager);
488+ priv->pager = NULL;
489+ }
490+
491 G_OBJECT_CLASS (os_scrollbar_parent_class)->dispose (object);
492 }
493
494@@ -1261,12 +1273,6 @@
495 os_scrollbar_swap_adjustment (scrollbar, NULL);
496 os_scrollbar_swap_thumb (scrollbar, NULL);
497
498- if (priv->pager != NULL)
499- {
500- g_object_unref (priv->pager);
501- priv->pager = NULL;
502- }
503-
504 G_OBJECT_CLASS (os_scrollbar_parent_class)->finalize (object);
505 }
506

Subscribers

People subscribed via source and target branches