Merge lp:~cimi/overlay-scrollbar/animated-colorization into lp:overlay-scrollbar
- animated-colorization
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Loïc Molinari (community) | Approve | ||
Ted Gould (community) | Needs Fixing | ||
Review via email: mp+55858@code.launchpad.net |
Commit message
Description of the change
Fade animation to colorize the pager
To post a comment you must log in.
- 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 |
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