Initial Import
[profile/ivi/clutter-toys.git] / attic / woohaa / wh-busy.c
1 #include <glib.h>
2 #include "wh-busy.h"
3
4 #define CSW() CLUTTER_STAGE_WIDTH()
5 #define CSH() CLUTTER_STAGE_HEIGHT()
6
7 #define WOOHAA_TYPE_BEHAVIOUR_BUSY (clutter_behaviour_busy_get_type ())
8
9 #define WOOHAA_BEHAVIOUR_BUSY(obj) \
10   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
11   WOOHAA_TYPE_BEHAVIOUR_BUSY, WoohaaBehaviourBusy))
12
13 #define WOOHAA_BEHAVIOUR_BUSY_CLASS(klass) \
14   (G_TYPE_CHECK_CLASS_CAST ((klass), \
15   WOOHAA_TYPE_BEHAVIOUR_BUSY, WoohaaBehaviourBusyClass))
16
17 #define CLUTTER_IS_BEHAVIOUR_BUSY(obj) \
18   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
19   WOOHAA_TYPE_BEHAVIOUR_BUSY))
20
21 #define CLUTTER_IS_BEHAVIOUR_BUSY_CLASS(klass) \
22   (G_TYPE_CHECK_CLASS_TYPE ((klass), \
23   WOOHAA_TYPE_BEHAVIOUR_BUSY))
24
25 #define WOOHAA_BEHAVIOUR_BUSY_GET_CLASS(obj) \
26   (G_TYPE_INSTANCE_GET_CLASS ((obj), \
27   WOOHAA_TYPE_BEHAVIOUR_BUSY, WoohaaBehaviourBusyClass))
28
29 typedef struct _WoohaaBehaviourBusy        WoohaaBehaviourBusy;
30 typedef struct _WoohaaBehaviourBusyClass   WoohaaBehaviourBusyClass;
31  
32 struct _WoohaaBehaviourBusy
33 {
34   ClutterBehaviour parent;
35   WoohaaBusy      *busy;
36 };
37
38 struct _WoohaaBehaviourBusyClass
39 {
40   ClutterBehaviourClass   parent_class;
41 };
42
43 GType clutter_behaviour_busy_get_type (void) G_GNUC_CONST;
44
45 G_DEFINE_TYPE (WoohaaBehaviourBusy, clutter_behaviour_busy, CLUTTER_TYPE_BEHAVIOUR);
46
47 static ClutterBehaviour*
48 clutter_behaviour_busy_new (WoohaaBusy *menu, ClutterAlpha *alpha);
49
50 static void
51 clutter_behaviour_alpha_notify (ClutterBehaviour *behave,
52                                 guint32           alpha_value);
53
54 enum
55 {
56   PROP_0,
57   PROP_LABEL
58 };
59
60 struct _WoohaaBusyPrivate
61 {
62   ClutterActor     *spinner;
63   ClutterActor     *label;
64   gchar            *label_text;
65   ClutterTimeline  *timeline;
66   guint             spinner_alpha;
67 };
68
69 G_DEFINE_TYPE (WoohaaBusy, woohaa_busy, CLUTTER_TYPE_ACTOR);
70
71 static void
72 woohaa_busy_dispose (GObject *object)
73 {
74   WoohaaBusy        *self;
75   WoohaaBusyPrivate *priv; 
76
77   self = WOOHAA_BUSY(object); 
78   priv = self->priv;
79
80   G_OBJECT_CLASS (woohaa_busy_parent_class)->dispose (object);
81 }
82
83 static void
84 woohaa_busy_finalize (GObject *object)
85 {
86   WoohaaBusy        *self;
87   WoohaaBusyPrivate *priv; 
88
89   self = WOOHAA_BUSY(object); 
90   priv = self->priv;
91
92   G_OBJECT_CLASS (woohaa_busy_parent_class)->finalize (object);
93 }
94
95 static void
96 woohaa_busy_show_cb (ClutterActor *actor, ClutterTimeline *timeline)
97 {
98   clutter_timeline_start (timeline);
99 }
100
101 static void
102 woohaa_busy_hide_cb (ClutterActor *actor, ClutterTimeline *timeline)
103 {
104   clutter_timeline_stop (timeline);
105   clutter_actor_set_opacity (CLUTTER_ACTOR (actor), 0xFF);
106 }
107
108 static void
109 newframe_cb (ClutterTimeline *timeline, 
110              gint             frame_num, 
111              ClutterActor    *spinner)
112 {
113   gint x, y;
114
115   clutter_actor_get_position (spinner, &x, &y);
116   clutter_actor_set_position (spinner, x + 10 , y + 10);
117
118   clutter_actor_set_rotation (spinner, 
119                               CLUTTER_Z_AXIS,
120                               (float)frame_num * 4.0,
121                               clutter_actor_get_width (spinner) / 2,
122                               clutter_actor_get_height (spinner) / 2,
123                               0);
124 }
125
126 static void
127 woohaa_busy_paint (ClutterActor *actor)
128 {
129   WoohaaBusyPrivate *priv = (WOOHAA_BUSY (actor))->priv;
130
131   clutter_actor_paint (priv->spinner);
132   clutter_actor_paint (priv->label);
133 }
134
135 static void
136 woohaa_busy_get_preferred_width  (ClutterActor          *actor,
137                                   ClutterUnit            for_height,
138                                   ClutterUnit           *min_width_p,
139                                   ClutterUnit           *natural_width_p)
140 {
141   *min_width_p = CLUTTER_UNITS_FROM_INT (100);
142   *natural_width_p = CLUTTER_UNITS_FROM_INT (500);
143 }
144
145 static void
146 woohaa_busy_get_preferred_height (ClutterActor          *actor,
147                                   ClutterUnit            for_width,
148                                   ClutterUnit           *min_height_p,
149                                   ClutterUnit           *natural_height_p)
150 {
151   *min_height_p = CLUTTER_UNITS_FROM_INT (100);
152   *natural_height_p = CLUTTER_UNITS_FROM_INT (500);
153 }
154
155 static void
156 woohaa_busy_allocate (ClutterActor *actor, 
157                       const ClutterActorBox *box,
158                       gboolean absolute_origin_changed)
159 {
160   WoohaaBusyPrivate *priv = (WOOHAA_BUSY (actor))->priv;
161   ClutterUnit min_width, spinner_natural_width, label_natural_width;
162   ClutterUnit min_height, spinner_natural_height, label_natural_height;
163   ClutterActorBox spinner_box, label_box;
164   
165   /* query spinner width and height */
166   clutter_actor_get_preferred_width (priv->spinner, 
167                                      box->y2 - box->y1,
168                                      &min_width,
169                                      &spinner_natural_width);
170   clutter_actor_get_preferred_height (priv->spinner, 
171                                       box->x2 - box->x1,
172                                       &min_height,
173                                       &spinner_natural_height);
174
175   /* query label width and height */
176   clutter_actor_get_preferred_width (priv->label, 
177                                      box->y2 - box->y1,
178                                      &min_width,
179                                      &label_natural_width);
180   clutter_actor_get_preferred_height (priv->label, 
181                                       box->x2 - box->x1,
182                                       &min_height,
183                                       &label_natural_height);
184
185   spinner_box.x1 = CLUTTER_UNITS_FROM_INT (CSW()/2) - spinner_natural_width/2;
186   spinner_box.y1 = CLUTTER_UNITS_FROM_INT (CSH()/2) 
187     - spinner_natural_height/2 
188     - label_natural_height/2  
189     + (priv->spinner_alpha * 100);
190   spinner_box.x2 = spinner_box.x1 + spinner_natural_width;
191   spinner_box.y2 = spinner_box.y1 + spinner_natural_height;
192
193   label_box.x1 = CLUTTER_UNITS_FROM_INT (CSW()/2) - label_natural_width/2;
194   label_box.y1 = CLUTTER_UNITS_FROM_INT (CSH()/2) 
195     - spinner_natural_height/2 
196     - label_natural_height/2  
197     + spinner_natural_height;
198   label_box.x2 = label_box.x1 + label_natural_width;
199   label_box.y2 = label_box.y1 + label_natural_height;
200
201   clutter_actor_allocate (priv->spinner, 
202                           &spinner_box, 
203                           absolute_origin_changed);
204
205   clutter_actor_allocate (priv->label, 
206                           &label_box, 
207                           absolute_origin_changed);
208
209   CLUTTER_ACTOR_CLASS (woohaa_busy_parent_class)->
210           allocate (actor, box, absolute_origin_changed);
211 }
212
213 static void
214 woohaa_busy_set_property (GObject      *object, 
215                           guint         prop_id,
216                           const GValue *value, 
217                           GParamSpec   *pspec)
218 {
219   WoohaaBusy        *busy;
220   WoohaaBusyPrivate *priv;
221
222   busy = WOOHAA_BUSY(object);
223   priv = busy->priv;
224
225   switch (prop_id) 
226     {
227     case PROP_LABEL:
228       if (priv->label_text)
229         g_free (priv->label_text);
230       priv->label_text = g_strdup(g_value_get_string (value));
231       clutter_label_set_text (CLUTTER_LABEL (priv->label), priv->label_text);
232       break;
233     default:
234       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
235       break;
236     }
237 }
238
239 static void
240 woohaa_busy_get_property (GObject    *object, 
241                           guint       prop_id,
242                           GValue     *value, 
243                           GParamSpec *pspec)
244 {
245   WoohaaBusy        *busy;
246   WoohaaBusyPrivate *priv;
247
248   busy = WOOHAA_BUSY(object);
249   priv = busy->priv;
250
251   switch (prop_id) 
252     {
253     case PROP_LABEL:
254       g_value_set_string (value, priv->label_text);
255       break;
256     default:
257       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
258       break;
259     } 
260 }
261
262 static void
263 woohaa_busy_class_init (WoohaaBusyClass *klass)
264 {
265   GObjectClass *object_class     = G_OBJECT_CLASS (klass);
266   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
267   
268   g_type_class_add_private (klass, sizeof (WoohaaBusyPrivate));
269
270   object_class->dispose      = woohaa_busy_dispose;
271   object_class->finalize     = woohaa_busy_finalize;
272   object_class->set_property = woohaa_busy_set_property;
273   object_class->get_property = woohaa_busy_get_property;
274
275   actor_class->get_preferred_width = woohaa_busy_get_preferred_width;
276   actor_class->get_preferred_height = woohaa_busy_get_preferred_height;
277   actor_class->allocate = woohaa_busy_allocate;
278   actor_class->paint    = woohaa_busy_paint;
279
280   g_object_class_install_property 
281     (object_class, PROP_LABEL,
282      g_param_spec_string ("label",
283                           "Label Text",
284                           "Label Text",
285                           NULL,
286                           G_PARAM_READWRITE));
287
288 }
289
290 static void
291 woohaa_busy_init (WoohaaBusy *woohaa_busy)
292 {
293   WoohaaBusyPrivate   *priv;
294   gchar               *font;
295   ClutterColor grey = { 0x72, 0x9f, 0xcf, 0xff};
296
297   woohaa_busy->priv = priv =
298     G_TYPE_INSTANCE_GET_PRIVATE (woohaa_busy,
299                                  WOOHAA_TYPE_BUSY,
300                                  WoohaaBusyPrivate);
301
302   priv->timeline = clutter_timeline_new (90, 20);
303   clutter_timeline_set_loop (priv->timeline, TRUE);
304
305   priv->spinner = clutter_texture_new_from_file (PKGDATADIR "/spinner.svg", 
306                                                  NULL);
307   clutter_actor_set_position 
308     (priv->spinner, 
309      (CSW() - clutter_actor_get_width (priv->spinner))/2,
310      (CSH() - clutter_actor_get_height (priv->spinner))/2);
311   clutter_actor_show (priv->spinner);
312
313   priv->label_text = g_strdup("One moment please...");
314   font = g_strdup_printf("Sans %ipx", (CSH()/6)/2);
315   priv->label = clutter_label_new_full (font, priv->label_text,  &grey);
316   clutter_actor_set_position (priv->label,
317                               (CSW() - clutter_actor_get_width (priv->label))/2,
318                               CSH() - (3*clutter_actor_get_height (priv->label)));  
319   clutter_actor_show (priv->label);
320
321   clutter_actor_set_parent (priv->spinner, CLUTTER_ACTOR (woohaa_busy));
322   clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (woohaa_busy));
323
324   g_signal_connect (priv->timeline, 
325                     "new-frame", 
326                     G_CALLBACK (newframe_cb), 
327                     priv->spinner);
328
329   g_signal_connect (woohaa_busy,
330                     "show",
331                     G_CALLBACK (woohaa_busy_show_cb),
332                     priv->timeline);
333   g_signal_connect (woohaa_busy,
334                     "hide",
335                     G_CALLBACK (woohaa_busy_hide_cb),
336                     priv->timeline);
337 }
338
339 void 
340 fade_complete_cb (ClutterActor *actor, gpointer data)
341 {
342   clutter_actor_hide(actor);
343 }
344
345 void
346 woohaa_busy_fade_out (WoohaaBusy *busy, gint timeout)
347 {
348   ClutterEffectTemplate *template;
349   ClutterTimeline *timeline;
350
351   timeline = clutter_timeline_new_for_duration (timeout);
352   template = clutter_effect_template_new (timeline, CLUTTER_ALPHA_SINE_INC);
353
354   clutter_effect_fade (template,
355                        CLUTTER_ACTOR (busy),
356                        0,
357                        fade_complete_cb,
358                        NULL);
359 }
360
361 void
362 woohaa_busy_fade_in (WoohaaBusy *busy, gint timeout)
363 {
364   ClutterEffectTemplate *template;
365   ClutterTimeline *timeline;
366
367   timeline = clutter_timeline_new_for_duration (timeout);
368   template = clutter_effect_template_new (timeline, CLUTTER_ALPHA_SINE_INC);
369
370   clutter_actor_set_opacity (CLUTTER_ACTOR (busy), 0);
371   clutter_actor_show (CLUTTER_ACTOR (busy));
372
373   clutter_effect_fade (template,
374                        CLUTTER_ACTOR (busy),
375                        0xFF,
376                        NULL,
377                        NULL);
378 }
379
380 void
381 woohaa_busy_bounce (WoohaaBusy *busy)
382 {
383   WoohaaBusyPrivate *priv;
384   ClutterTimeline *timeline;
385   ClutterAlpha *alpha;
386   ClutterGeometry geo;
387   ClutterBehaviour *behave;
388   priv = busy->priv;
389
390   timeline = clutter_timeline_new_for_duration (500);
391   alpha = clutter_alpha_new_full (timeline, CLUTTER_ALPHA_SINE, NULL, NULL);
392
393   behave = clutter_behaviour_busy_new (busy, alpha);
394
395   clutter_timeline_start (timeline);
396
397   clutter_actor_get_geometry (CLUTTER_ACTOR (busy), &geo);
398 }
399
400 ClutterActor*
401 woohaa_busy_new (void)
402 {
403   return g_object_new (WOOHAA_TYPE_BUSY, NULL);
404 }
405
406 /* Custom Behavior */
407
408 static void
409 clutter_behaviour_alpha_notify (ClutterBehaviour *behave,
410                                 guint32           alpha_value)
411 {
412   WoohaaBusy *busy;
413
414   busy = (WOOHAA_BEHAVIOUR_BUSY (behave))->busy;
415   
416   busy->priv->spinner_alpha = alpha_value;
417   clutter_actor_queue_relayout (CLUTTER_ACTOR (busy));
418 }
419
420 static void
421 clutter_behaviour_busy_class_init (WoohaaBehaviourBusyClass *klass)
422 {
423   ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass);
424
425   behave_class->alpha_notify = clutter_behaviour_alpha_notify;
426 }
427
428 static void
429 clutter_behaviour_busy_init (WoohaaBehaviourBusy *self)
430 {
431 }
432
433 static ClutterBehaviour*
434 clutter_behaviour_busy_new (WoohaaBusy *busy, ClutterAlpha *alpha)
435 {
436   WoohaaBehaviourBusy *busy_behave;
437
438   busy_behave = g_object_new (WOOHAA_TYPE_BEHAVIOUR_BUSY, 
439                               "alpha", alpha, NULL);
440   busy_behave->busy  = busy;
441
442   return CLUTTER_BEHAVIOUR(busy_behave);
443 }