4 * Foofone is a quick 3 hour hack to experiment with effects and create a
5 * dummy phone interface. Thats all it is.
7 * Copyright 2007 OpenedHand Ltd
8 * Authored by Matthew Allum <mallum@o-hand.com>
9 * Licensed under the GPL v2 or greater.
13 #include <clutter/clutter.h>
31 ClutterActor *dpy, *dpy_entry;
33 ClutterActor *screen_dialpad, *screen_dial, *dial_label;
34 gboolean dialing_state;
35 ClutterTimeline *dialing_timeline;
39 /* An alpha function that goes from 0->1->0 along a sine. */
41 alpha_sine_func (ClutterAlpha *alpha,
44 ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
45 return sin(clutter_timeline_get_progress (timeline) * M_PI);
50 /* A boolean 'interpolator', switching from 'a' to 'b' when 'progress' = 0.5 */
52 boolean_progress (const GValue *a,
57 gboolean ba = g_value_get_boolean (a);
58 gboolean bb = g_value_get_boolean (b);
59 gboolean res = (progress <= 0.5) ? ba : bb;
60 g_value_set_boolean (retval, res);
65 on_call_deactivate_complete (ClutterTimeline *timeline,
68 App *app = (App*)user_data;
69 /* reset the now hidden dialing screen */
70 clutter_actor_set_rotation (app->screen_dial, CLUTTER_Y_AXIS, 0, 0, 0, 0);
74 call_deactivate (App *app)
77 ClutterAnimation *anim;
80 /* stop the flashing text */
81 clutter_timeline_stop (app->dialing_timeline);
83 /* clear dialpad entry ready */
84 clutter_text_set_text (CLUTTER_TEXT(app->dpy_entry), "");
86 /* rotate screen_dial, and hide it at mid-animation */
87 clutter_actor_set_rotation (app->screen_dial, CLUTTER_Y_AXIS, 0.0, 0.0, 0.0, 0.0);
88 anim = clutter_actor_animate (app->screen_dial, CLUTTER_LINEAR, 150,
89 "rotation-angle-y", -180.0,
92 alpha = clutter_animation_get_alpha (anim);
94 /* reset positions of dialer actors, needed back for flip */
97 clutter_actor_set_position (app->buttons[i]->actor,
98 app->buttons[i]->sx, app->buttons[i]->sy);
99 clutter_actor_set_opacity (app->buttons[i]->actor, 0xff);
101 clutter_actor_set_position (app->dpy, app->dpyx, app->dpyy);
103 /* rotate hidden screen_dialpad, and show it at mid-animation */
104 clutter_actor_set_rotation (app->screen_dialpad, CLUTTER_Y_AXIS, 180.0, 0.0, 0.0, 0.0);
105 clutter_actor_animate_with_alpha (app->screen_dialpad, alpha,
106 "rotation-angle-y", 0.0,
108 "signal-after::completed",
109 G_CALLBACK(on_call_deactivate_complete),
113 app->dialing_state = FALSE;
117 on_call_activate_complete (ClutterActor *actor,
121 ClutterBehaviour *behave;
122 App *app = (App*)user_data;
124 clutter_actor_hide (app->screen_dialpad);
126 /* Setup the pulsing 'calling..' text if need be */
127 if (app->dialing_timeline == NULL)
129 app->dialing_timeline = clutter_timeline_new (1000);
130 clutter_timeline_set_loop (app->dialing_timeline, TRUE);
131 alpha = clutter_alpha_new_full (app->dialing_timeline, ALPHA_SINE);
132 behave = clutter_behaviour_opacity_new (alpha, 0xff, 0);
133 clutter_behaviour_apply (behave, app->dial_label);
135 clutter_timeline_start (app->dialing_timeline);
137 app->dialing_state = TRUE;
141 call_activate (App *app)
145 ClutterAnimation *anim;
148 /* zoom in the dialing window */
149 clutter_actor_set_scale (app->screen_dial, 0.1, 0.1);
150 clutter_actor_set_opacity (app->screen_dial, 0x66);
151 clutter_actor_show_all (app->screen_dial);
153 anim = clutter_actor_animate (app->screen_dial, CLUTTER_EASE_OUT_SINE, 150,
158 alpha = clutter_animation_get_alpha (anim);
160 /* Set up effects to shoot everything offscreen, synchronized with screen_dial animation */
163 clutter_actor_set_position (app->buttons[i]->actor,
165 app->buttons[i]->sy);
170 x = CSW + clutter_actor_get_width (app->buttons[i]->actor) / 2;
171 y = app->buttons[i]->sy;
174 x = -clutter_actor_get_width (app->buttons[i]->actor) / 2;
175 y = app->buttons[i]->sy;
178 x = app->buttons[i]->sx;
180 y = -clutter_actor_get_height (app->buttons[i]->actor) / 2;
182 y = CSH + clutter_actor_get_height (app->buttons[i]->actor) / 2;
186 clutter_actor_animate_with_alpha (app->buttons[i]->actor, alpha,
193 clutter_actor_set_position (app->dpy, app->dpyx, app->dpyy);
194 clutter_actor_animate_with_alpha(app->dpy, alpha,
195 "x", (float)app->dpyx,
196 "y", -clutter_actor_get_height (app->dpy),
197 "signal-after::completed",
198 on_call_activate_complete,
204 on_button_effect_complete (ClutterAnimation *animation,
207 ClutterActor *actor = (ClutterActor*)user_data;
209 /* reset after effect */
210 clutter_actor_set_opacity (actor, 0xff);
211 clutter_actor_set_scale (actor, 1.0, 1.0);
215 button_activate (App *app, Button *b)
217 // Wait for the previous animation to end
218 if (clutter_actor_get_animation (b->actor))
221 clutter_text_insert_text (CLUTTER_TEXT(app->dpy_entry), b->face, -1);
223 clutter_actor_set_opacity (b->actor, 0xff);
224 clutter_actor_set_scale (b->actor, 1.0, 1.0);
225 clutter_actor_animate (b->actor, CLUTTER_LINEAR, 50,
229 "signal-after::completed", on_button_effect_complete, b->actor,
234 on_input (ClutterStage *stage,
238 App *app = (App*)user_data;
240 if (event->type == CLUTTER_BUTTON_PRESS)
242 ClutterActor *actor = clutter_event_get_source (event);
243 const gchar *label = clutter_actor_get_name (actor);
246 if (app->dialing_state == TRUE)
248 call_deactivate(app);
252 /* retrieve button id (stored in the Actor's name) */
255 label_val = atoi(label);
256 if ( label_val < 1 || label_val > 12 )
260 if (label_val == 11) /* 'dial' key */
263 button_activate (app, app->buttons[label_val]);
274 gint i, xpad, ypad, x ,y, xinit, xdpy, ydpy;
275 ClutterActor *button_texture, *a;
276 ClutterColor text_color = { 0xff, 0xff, 0xff, 0xff },
277 rect_color = { 0, 0, 0, 0x99 },
278 black_color = { 0, 0, 0, 0xff };
280 button_texture = clutter_texture_new_from_file ("button.png", NULL);
282 xpad = (CSW-(3*clutter_actor_get_width(button_texture)))/4;
285 y = (CSH - (4 * (ypad + clutter_actor_get_height(button_texture))));
288 * screen_dialpad (group)
290 * +---- (texture:display.png)
291 * +----dpy_entry (text)
292 * +----buttons[0:11]->actor (group)
293 * +---- (texture:button.png)
297 app->screen_dialpad = clutter_group_new();
298 clutter_actor_set_size (app->screen_dialpad, CSW, CSH);
299 clutter_actor_set_anchor_point_from_gravity (app->screen_dialpad, CLUTTER_GRAVITY_CENTER);
300 clutter_actor_set_position (app->screen_dialpad, CSW/2, CSH/2);
302 app->dpy = clutter_group_new();
304 a = clutter_texture_new_from_file ("display.png", NULL);
305 clutter_group_add (CLUTTER_GROUP(app->dpy), a);
306 app->dpyx = xdpy = x;
307 app->dpyy = ydpy = (y - clutter_actor_get_height(app->dpy))/2;
308 clutter_actor_set_position (app->dpy, xdpy, ydpy);
310 clutter_group_add(CLUTTER_GROUP(app->screen_dialpad), app->dpy);
312 app->dpy_entry = clutter_text_new_full ("Sans Bold 32px", "", &text_color);
313 clutter_text_set_editable (CLUTTER_TEXT(app->dpy_entry), TRUE);
314 clutter_actor_set_position (app->dpy_entry, 8, 8);
315 clutter_actor_set_size (app->dpy_entry, clutter_actor_get_width (app->dpy) - 16, 32);
316 clutter_group_add (CLUTTER_GROUP(app->dpy), app->dpy_entry);
323 app->buttons[i] = g_new0(Button, 1);
324 app->buttons[i]->actor = clutter_group_new ();
325 g_snprintf (label, 8, "%d", i+1);
326 clutter_actor_set_name (app->buttons[i]->actor, label);
327 clutter_actor_set_reactive (app->buttons[i]->actor, TRUE);
328 clutter_actor_set_anchor_point_from_gravity (app->buttons[i]->actor,
329 CLUTTER_GRAVITY_CENTER);
334 a = clutter_clone_new(button_texture);
335 clutter_group_add(CLUTTER_GROUP(app->buttons[i]->actor), a);
340 g_snprintf(buf, 8, "#");
343 g_snprintf(buf, 8, "0");
346 g_snprintf(buf, 8, "*");
349 g_snprintf(buf, 8, "%i", i+1);
353 a = clutter_text_new_full("Sans Bold 32px", buf, &text_color);
354 clutter_actor_set_position (a,
355 (clutter_actor_get_width (button_texture) - clutter_actor_get_width (a))/2,
356 (clutter_actor_get_height (button_texture) - clutter_actor_get_height (a))/2);
357 clutter_group_add (CLUTTER_GROUP (app->buttons[i]->actor), a);
359 clutter_group_add (CLUTTER_GROUP (app->screen_dialpad), app->buttons[i]->actor);
361 /* need to remember positions for anim - sucky */
362 app->buttons[i]->sx = x + clutter_actor_get_width (app->buttons[i]->actor)/2;
363 app->buttons[i]->sy = y + clutter_actor_get_height (app->buttons[i]->actor)/2;
364 clutter_actor_set_position (app->buttons[i]->actor,
366 app->buttons[i]->sy);
368 /* Really we should use a Clutter*Box here.. */
372 y += (ypad + clutter_actor_get_height (button_texture));
375 x += (xpad + clutter_actor_get_width(button_texture));
377 app->buttons[i]->face = g_strdup (buf);
382 * +---- (rectangle:black)
383 * +---- (texture:call-background.png)
384 * +---- (rectangle:semi transparent)
385 * +----dial_label (text:"Calling...")
388 app->screen_dial = clutter_group_new();
389 clutter_actor_set_anchor_point_from_gravity (app->screen_dial, CLUTTER_GRAVITY_CENTER);
390 clutter_actor_set_position (app->screen_dial, CSW/2, CSH/2);
392 a = clutter_rectangle_new_with_color (&black_color);
393 clutter_actor_set_size (a, CSW, CSH);
394 clutter_group_add (CLUTTER_GROUP(app->screen_dial), a);
396 a = clutter_texture_new_from_file ("call-background.png", NULL);
397 clutter_group_add (CLUTTER_GROUP(app->screen_dial), a);
399 a = clutter_rectangle_new_with_color (&rect_color);
400 clutter_actor_set_size (a, CSW, CSH/6);
401 clutter_actor_set_position (a, 0, (CSH - (CSH/6))/2);
402 clutter_group_add (CLUTTER_GROUP(app->screen_dial), a);
404 app->dial_label = clutter_text_new_full ("Sans Bold 32px", "Calling...", &text_color);
405 clutter_actor_set_position (app->dial_label, 10, (CSH - (CSH/6))/2 + 10);
406 clutter_group_add (CLUTTER_GROUP (app->screen_dial), app->dial_label);
410 main (int argc, char *argv[])
413 ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
417 clutter_init (&argc, &argv);
419 ALPHA_SINE = clutter_alpha_register_func (alpha_sine_func, NULL);
420 clutter_interval_register_progress_func (G_TYPE_BOOLEAN, boolean_progress);
422 app = g_new0(App, 1);
424 stage = clutter_stage_get_default ();
425 clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
426 clutter_actor_set_size (stage, CSW, CSH);
430 clutter_group_add (CLUTTER_GROUP(stage), app->screen_dial);
431 clutter_group_add (CLUTTER_GROUP(stage), app->screen_dialpad);
433 clutter_actor_hide_all (app->screen_dial);
434 clutter_actor_show_all (stage);
436 g_signal_connect (stage,
438 G_CALLBACK (on_input),
441 printf("\n..Press '*' to dial..\n\n");