176861ee43e0c92d45b495d257bbc074c262afc0
[framework/uifw/elementary.git] / src / lib / elm_flip.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Flip Flip
6  *
7  * This holds 2 content objects: one on the front and one on the back. It
8  * allows you to flip from front to back and vice-versa using various effects.
9  *
10  * Supported flip types:
11  * ELM_FLIP_ROTATE_Y_CENTER_AXIS
12  * ELM_FLIP_ROTATE_X_CENTER_AXIS
13  * ELM_FLIP_ROTATE_XZ_CENTER_AXIS
14  * ELM_FLIP_ROTATE_YZ_CENTER_AXIS
15  * ELM_FLIP_CUBE_LEFT
16  * ELM_FLIP_CUBE_RIGHT
17  * ELM_FLIP_CUBE_UP
18  * ELM_FLIP_CUBE_DOWN
19  *
20  * Signals that you can add callbacks for are:
21  *
22  * "animate,done" - when a flip animation is finished
23  */
24
25 typedef struct _Widget_Data Widget_Data;
26
27 struct _Widget_Data
28 {
29    Ecore_Animator *animator;
30    double start, len;
31    Elm_Flip_Mode mode;
32    Evas_Object *clip;
33    struct {
34         Evas_Object *content, *clip;
35    } front, back;
36    Eina_Bool state : 1;
37 };
38
39 static const char *widtype = NULL;
40 static void _del_hook(Evas_Object *obj);
41 static void _theme_hook(Evas_Object *obj);
42 static void _sizing_eval(Evas_Object *obj);
43 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
44 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
45
46 static void _configure(Evas_Object *obj);
47
48 static const char SIG_ANIMATE_DONE[] = "animate,done";
49
50 static const Evas_Smart_Cb_Description _signals[] = {
51    {SIG_ANIMATE_DONE, ""},
52    {NULL, NULL}
53 };
54
55 static void
56 _del_hook(Evas_Object *obj)
57 {
58    Widget_Data *wd = elm_widget_data_get(obj);
59    if (!wd) return;
60    if (wd->animator) ecore_animator_del(wd->animator);
61    free(wd);
62 }
63
64 static void
65 _theme_hook(Evas_Object *obj)
66 {
67    Widget_Data *wd = elm_widget_data_get(obj);
68    if (!wd) return;
69    _sizing_eval(obj);
70 }
71
72 static Eina_Bool
73 _elm_flip_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
74 {
75    Widget_Data *wd = elm_widget_data_get(obj);
76
77    if (!wd)
78      return EINA_FALSE;
79
80    /* Try Focus cycle in subitem */
81    if (wd->state)
82      return elm_widget_focus_next_get(wd->front.content, dir, next);
83    else
84      return elm_widget_focus_next_get(wd->back.content, dir, next);
85
86 }
87
88 static void
89 _sizing_eval(Evas_Object *obj)
90 {
91    Widget_Data *wd = elm_widget_data_get(obj);
92    Evas_Coord minw = -1, minh = -1, minw2 = -1, minh2 = -1;
93    Evas_Coord maxw = -1, maxh = -1, maxw2 = -1, maxh2 = -1;
94    if (!wd) return;
95    if (wd->front.content)
96      evas_object_size_hint_min_get(wd->front.content, &minw, &minh);
97    if (wd->back.content)
98      evas_object_size_hint_min_get(wd->back.content, &minw2, &minh2);
99    if (wd->front.content)
100      evas_object_size_hint_max_get(wd->front.content, &maxw, &maxh);
101    if (wd->back.content)
102      evas_object_size_hint_max_get(wd->back.content, &maxw2, &maxh2);
103
104    if (minw2 > minw) minw = minw2;
105    if (minh2 > minh) minh = minh2;
106    if ((maxw2 >= 0) && (maxw2 < maxw)) maxw = maxw2;
107    if ((maxh2 >= 0) && (maxh2 < maxh)) maxh = maxh2;
108
109    evas_object_size_hint_min_set(obj, minw, minh);
110    evas_object_size_hint_max_set(obj, maxw, maxh);
111 }
112
113 static void
114 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
115 {
116    Widget_Data *wd = elm_widget_data_get(data);
117    if (!wd) return;
118    _sizing_eval(data);
119 }
120
121 static void
122 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
123 {
124    Widget_Data *wd = elm_widget_data_get(obj);
125    Evas_Object *sub = event_info;
126    if (!wd) return;
127    if (sub == wd->front.content)
128      {
129         evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
130                                             _changed_size_hints, obj);
131         wd->front.content = NULL;
132         evas_object_hide(wd->front.clip);
133         _sizing_eval(obj);
134      }
135    else if (sub == wd->back.content)
136      {
137         evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
138                                             _changed_size_hints, obj);
139         wd->back.content = NULL;
140         evas_object_hide(wd->back.clip);
141         _sizing_eval(obj);
142      }
143 }
144
145 static void
146 flip_show_hide(Evas_Object *obj)
147 {
148    Widget_Data *wd = elm_widget_data_get(obj);
149    if (elm_flip_front_get(obj))
150      {
151         if (wd->front.content)
152           evas_object_show(wd->front.clip);
153         else
154           evas_object_hide(wd->front.clip);
155         if (wd->back.content)
156           evas_object_hide(wd->back.clip);
157         else
158           evas_object_hide(wd->back.clip);
159      }
160    else
161      {
162         if (wd->front.content)
163           evas_object_hide(wd->front.clip);
164         else
165           evas_object_hide(wd->front.clip);
166         if (wd->back.content)
167           evas_object_show(wd->back.clip);
168         else
169           evas_object_hide(wd->back.clip);
170      }
171 }
172
173 static Eina_Bool
174 _flip(Evas_Object *obj)
175 {
176    Widget_Data *wd = elm_widget_data_get(obj);
177    double t = ecore_loop_time_get() - wd->start;
178    Evas_Coord x, y, w, h;
179    double p, deg;
180    Evas_Map *mf, *mb;
181    Evas_Coord cx, cy, px, py, foc;
182    int lx, ly, lz, lr, lg, lb, lar, lag, lab;
183    if (!wd->animator) return ECORE_CALLBACK_CANCEL;
184    t = t / wd->len;
185    if (t > 1.0) t = 1.0;
186
187    if (!wd) return ECORE_CALLBACK_CANCEL;
188
189    mf = evas_map_new(4);
190    evas_map_smooth_set(mf, 0);
191    mb = evas_map_new(4);
192    evas_map_smooth_set(mb, 0);
193
194    if (wd->front.content)
195      {
196         evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
197         evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
198      }
199    if (wd->back.content)
200      {
201         evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
202         evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
203      }
204
205    evas_object_geometry_get(obj, &x, &y, &w, &h);
206
207    cx = x + (w / 2);
208    cy = y + (h / 2);
209
210    px = x + (w / 2);
211    py = y + (h / 2);
212    foc = 2048;
213
214    lx = cx;
215    ly = cy;
216    lz = -10000;
217    lr = 255;
218    lg = 255;
219    lb = 255;
220    lar = 0;
221    lag = 0;
222    lab = 0;
223
224    switch (wd->mode)
225      {
226       case ELM_FLIP_ROTATE_Y_CENTER_AXIS:
227          p = 1.0 - t;
228          p = 1.0 - (p * p);
229          if (wd->state) deg = 180.0 * p;
230          else deg = 180 + (180.0 * p);
231          evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, 0);
232          evas_map_util_3d_rotate(mb, 0.0, deg + 180.0, 0.0, cx, cy, 0);
233          break;
234       case ELM_FLIP_ROTATE_X_CENTER_AXIS:
235          p = 1.0 - t;
236          p = 1.0 - (p * p);
237          if (wd->state) deg = 180.0 * p;
238          else deg = 180 + (180.0 * p);
239          evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, 0);
240          evas_map_util_3d_rotate(mb, deg + 180.0, 0.0, 0.0, cx, cy, 0);
241          break;
242       case ELM_FLIP_ROTATE_XZ_CENTER_AXIS:
243          p = 1.0 - t;
244          p = 1.0 - (p * p);
245          if (wd->state) deg = 180.0 * p;
246          else deg = 180 + (180.0 * p);
247          evas_map_util_3d_rotate(mf, deg, 0.0, deg, cx, cy, 0);
248          evas_map_util_3d_rotate(mb, deg + 180.0, 0.0, deg + 180.0, cx, cy, 0);
249          break;
250       case ELM_FLIP_ROTATE_YZ_CENTER_AXIS:
251          p = 1.0 - t;
252          p = 1.0 - (p * p);
253          if (wd->state) deg = 180.0 * p;
254          else deg = 180 + (180.0 * p);
255          evas_map_util_3d_rotate(mf, 0.0, deg, deg, cx, cy, 0);
256          evas_map_util_3d_rotate(mb, 0.0, deg + 180.0, deg + 180.0, cx, cy, 0);
257          break;
258       case ELM_FLIP_CUBE_LEFT:
259          p = 1.0 - t;
260          p = 1.0 - (p * p);
261          deg = -90.0 * p;
262          if (wd->state)
263            {
264               evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
265               evas_map_util_3d_rotate(mb, 0.0, deg + 90, 0.0, cx, cy, w / 2);
266            }
267          else
268            {
269               evas_map_util_3d_rotate(mf, 0.0, deg + 90, 0.0, cx, cy, w / 2);
270               evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
271            }
272          break;
273       case ELM_FLIP_CUBE_RIGHT:
274          p = 1.0 - t;
275          p = 1.0 - (p * p);
276          deg = 90.0 * p;
277          if (wd->state)
278            {
279               evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
280               evas_map_util_3d_rotate(mb, 0.0, deg - 90, 0.0, cx, cy, w / 2);
281            }
282          else
283            {
284               evas_map_util_3d_rotate(mf, 0.0, deg - 90, 0.0, cx, cy, w / 2);
285               evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
286            }
287          break;
288       case ELM_FLIP_CUBE_UP:
289          p = 1.0 - t;
290          p = 1.0 - (p * p);
291          deg = -90.0 * p;
292          if (wd->state)
293            {
294               evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
295               evas_map_util_3d_rotate(mb, deg + 90, 0.0, 0.0, cx, cy, h / 2);
296            }
297          else
298            {
299               evas_map_util_3d_rotate(mf, deg + 90, 0.0, 0.0, cx, cy, h / 2);
300               evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
301            }
302          break;
303       case ELM_FLIP_CUBE_DOWN:
304          p = 1.0 - t;
305          p = 1.0 - (p * p);
306          deg = 90.0 * p;
307          if (wd->state)
308            {
309               evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
310               evas_map_util_3d_rotate(mb, deg - 90, 0.0, 0.0, cx, cy, h / 2);
311            }
312          else
313            {
314               evas_map_util_3d_rotate(mf, deg - 90, 0.0, 0.0, cx, cy, h / 2);
315               evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
316            }
317          break;
318       default:
319          break;
320      }
321
322
323    if (wd->front.content)
324      {
325         evas_map_util_3d_lighting(mf, lx, ly, lz, lr, lg, lb, lar, lag, lab);
326         evas_map_util_3d_perspective(mf, px, py, 0, foc);
327         evas_object_map_set(wd->front.content, mf);
328         evas_object_map_enable_set(wd->front.content, 1);
329         if (evas_map_util_clockwise_get(mf)) evas_object_show(wd->front.clip);
330         else evas_object_hide(wd->front.clip);
331      }
332
333    if (wd->back.content)
334      {
335         evas_map_util_3d_lighting(mb, lx, ly, lz, lr, lg, lb, lar, lag, lab);
336         evas_map_util_3d_perspective(mb, px, py, 0, foc);
337         evas_object_map_set(wd->back.content, mb);
338         evas_object_map_enable_set(wd->back.content, 1);
339         if (evas_map_util_clockwise_get(mb)) evas_object_show(wd->back.clip);
340         else evas_object_hide(wd->back.clip);
341      }
342
343    evas_map_free(mf);
344    evas_map_free(mb);
345
346    if (t >= 1.0)
347      {
348         evas_object_map_enable_set(wd->front.content, 0);
349         evas_object_map_enable_set(wd->back.content, 0);
350         // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
351         evas_object_resize(wd->front.content, 0, 0);
352         evas_object_resize(wd->back.content, 0, 0);
353         evas_smart_objects_calculate(evas_object_evas_get(obj));
354         // FIXME: end hack
355         wd->animator = NULL;
356         wd->state = !wd->state;
357         _configure(obj);
358         evas_object_smart_callback_call(obj, SIG_ANIMATE_DONE, NULL);
359         return ECORE_CALLBACK_CANCEL;
360      }
361    return ECORE_CALLBACK_RENEW;
362 }
363
364 static void
365 _configure(Evas_Object *obj)
366 {
367    Widget_Data *wd = elm_widget_data_get(obj);
368    Evas_Coord x, y, w, h;
369    if (!wd) return;
370    evas_object_geometry_get(obj, &x, &y, &w, &h);
371    if (wd->front.content)
372      {
373         if (!wd->animator)
374           evas_object_move(wd->front.content, x, y);
375         evas_object_resize(wd->front.content, w, h);
376      }
377    if (wd->back.content)
378      {
379         if (!wd->animator)
380           evas_object_move(wd->back.content, x, y);
381         evas_object_resize(wd->back.content, w, h);
382      }
383    _flip(obj);
384 }
385
386 static void
387 _move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
388 {
389    _configure(obj);
390 }
391
392 static void
393 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
394 {
395    _configure(obj);
396 }
397
398 static Eina_Bool
399 _animate(void *data)
400 {
401    return _flip(data);
402 }
403
404 /**
405  * Add a new flip to the parent
406  *
407  * @param parent The parent object
408  * @return The new object or NULL if it cannot be created
409  *
410  * @ingroup Flip
411  */
412 EAPI Evas_Object *
413 elm_flip_add(Evas_Object *parent)
414 {
415    Evas_Object *obj;
416    Evas *e;
417    Widget_Data *wd;
418
419    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
420
421    ELM_SET_WIDTYPE(widtype, "flip");
422    elm_widget_type_set(obj, "flip");
423    elm_widget_sub_object_add(parent, obj);
424    elm_widget_data_set(obj, wd);
425    elm_widget_del_hook_set(obj, _del_hook);
426    elm_widget_theme_hook_set(obj, _theme_hook);
427    elm_widget_focus_next_hook_set(obj, _elm_flip_focus_next_hook);
428    elm_widget_can_focus_set(obj, EINA_FALSE);
429
430    wd->clip = evas_object_rectangle_add(e);
431    evas_object_static_clip_set(wd->clip, 1);
432    evas_object_color_set(wd->clip, 255, 255, 255, 255);
433    evas_object_move(wd->clip, -49999, -49999);
434    evas_object_resize(wd->clip, 99999, 99999);
435    elm_widget_sub_object_add(obj, wd->clip);
436    evas_object_clip_set(wd->clip, evas_object_clip_get(obj));
437    evas_object_smart_member_add(wd->clip, obj);
438
439    wd->front.clip = evas_object_rectangle_add(e);
440    evas_object_static_clip_set(wd->front.clip, 1);
441    evas_object_data_set(wd->front.clip, "_elm_leaveme", obj);
442    evas_object_color_set(wd->front.clip, 255, 255, 255, 255);
443    evas_object_move(wd->front.clip, -49999, -49999);
444    evas_object_resize(wd->front.clip, 99999, 99999);
445    elm_widget_sub_object_add(obj, wd->front.clip);
446    evas_object_smart_member_add(wd->front.clip, obj);
447    evas_object_clip_set(wd->front.clip, wd->clip);
448
449    wd->back.clip = evas_object_rectangle_add(e);
450    evas_object_static_clip_set(wd->back.clip, 1);
451    evas_object_data_set(wd->back.clip, "_elm_leaveme", obj);
452    evas_object_color_set(wd->back.clip, 255, 255, 255, 255);
453    evas_object_move(wd->back.clip, -49999, -49999);
454    evas_object_resize(wd->back.clip, 99999, 99999);
455    elm_widget_sub_object_add(wd->back.clip, obj);
456    evas_object_smart_member_add(obj, wd->back.clip);
457    evas_object_clip_set(wd->back.clip, wd->clip);
458
459    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
460    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL);
461    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
462
463    evas_object_smart_callbacks_descriptions_set(obj, _signals);
464
465    wd->state = 1;
466
467    _sizing_eval(obj);
468
469    return obj;
470 }
471
472 /**
473  * Set the front content of the flip widget.
474  *
475  * Once the content object is set, a previously set one will be deleted.
476  * If you want to keep that old content object, use the
477  * elm_flip_content_front_unset() function.
478  *
479  * @param obj The flip object
480  * @param content The new front content object
481  *
482  * @ingroup Flip
483  */
484 EAPI void
485 elm_flip_content_front_set(Evas_Object *obj, Evas_Object *content)
486 {
487    ELM_CHECK_WIDTYPE(obj, widtype);
488    Widget_Data *wd = elm_widget_data_get(obj);
489    if (!wd) return;
490    if (wd->front.content == content) return;
491    if (wd->front.content) evas_object_del(wd->back.content);
492    wd->front.content = content;
493    if (content)
494      {
495         elm_widget_sub_object_add(obj, content);
496         evas_object_smart_member_add(content, obj);
497         evas_object_clip_set(content, wd->front.clip);
498         evas_object_event_callback_add(content,
499                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
500                                        _changed_size_hints, obj);
501         _sizing_eval(obj);
502      }
503    // force calc to contents are the right size before transition
504    evas_smart_objects_calculate(evas_object_evas_get(obj));
505    flip_show_hide(obj);
506    _configure(obj);
507 }
508
509 /**
510  * Set the back content of the flip widget.
511  *
512  * Once the content object is set, a previously set one will be deleted.
513  * If you want to keep that old content object, use the
514  * elm_flip_content_back_unset() function.
515  *
516  * @param obj The flip object
517  * @param content The new back content object
518  *
519  * @ingroup Flip
520  */
521 EAPI void
522 elm_flip_content_back_set(Evas_Object *obj, Evas_Object *content)
523 {
524    ELM_CHECK_WIDTYPE(obj, widtype);
525    Widget_Data *wd = elm_widget_data_get(obj);
526    if (!wd) return;
527    if (wd->back.content == content) return;
528    if (wd->back.content) evas_object_del(wd->back.content);
529    wd->back.content = content;
530    if (content)
531      {
532         elm_widget_sub_object_add(obj, content);
533         evas_object_smart_member_add(content, obj);
534         evas_object_clip_set(content, wd->back.clip);
535         evas_object_event_callback_add(content,
536                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
537                                        _changed_size_hints, obj);
538         _sizing_eval(obj);
539      }
540    // force calc to contents are the right size before transition
541    evas_smart_objects_calculate(evas_object_evas_get(obj));
542    flip_show_hide(obj);
543    _configure(obj);
544 }
545
546 /**
547  * Get the front content used for the flip
548  *
549  * Return the front content object which is set for this widget.
550  *
551  * @param obj The flip object
552  * @return The front content object that is being used
553  *
554  * @ingroup Flip
555  */
556 EAPI Evas_Object *
557 elm_flip_content_front_get(const Evas_Object *obj)
558 {
559    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
560    Widget_Data *wd = elm_widget_data_get(obj);
561    return wd->front.content;
562 }
563
564
565 /**
566  * Get the back content used for the flip
567  *
568  * Return the back content object which is set for this widget.
569  *
570  * @param obj The flip object
571  * @return The back content object that is being used
572  *
573  * @ingroup Flip
574  */
575 EAPI Evas_Object *
576 elm_flip_content_back_get(const Evas_Object *obj)
577 {
578    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
579    Widget_Data *wd = elm_widget_data_get(obj);
580    return wd->back.content;
581 }
582
583 /**
584  * Unset the front content used for the flip
585  *
586  * Unparent and return the front content object which was set for this widget.
587  *
588  * @param obj The flip object
589  * @return The front content object that was being used
590  *
591  * @ingroup Flip
592  */
593 EAPI Evas_Object *
594 elm_flip_content_front_unset(Evas_Object *obj)
595 {
596    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
597    Widget_Data *wd = elm_widget_data_get(obj);
598    if (!wd) return NULL;
599    if (!wd->front.content) return NULL;
600    Evas_Object *content = wd->front.content;
601    evas_object_clip_unset(content);
602    elm_widget_sub_object_del(obj, content);
603    evas_object_smart_member_del(content);
604    wd->front.content = NULL;
605    return content;
606 }
607
608 /**
609  * Unset the back content used for the flip
610  *
611  * Unparent and return the back content object which was set for this widget.
612  *
613  * @param obj The flip object
614  * @return The back content object that was being used
615  *
616  * @ingroup Flip
617  */
618 EAPI Evas_Object *
619 elm_flip_content_back_unset(Evas_Object *obj)
620 {
621    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
622    Widget_Data *wd = elm_widget_data_get(obj);
623    if (!wd) return NULL;
624    if (!wd->back.content) return NULL;
625    Evas_Object *content = wd->back.content;
626    evas_object_clip_unset(content);
627    elm_widget_sub_object_del(obj, content);
628    evas_object_smart_member_del(content);
629    wd->back.content = NULL;
630    return content;
631 }
632
633 /**
634  * Get flip front visibility state
635  *
636  * @param obj The flip object
637  * @return If front front is showing or not currently
638  *
639  * @ingroup Flip
640  */
641 EAPI Eina_Bool
642 elm_flip_front_get(const Evas_Object *obj)
643 {
644    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
645    Widget_Data *wd = elm_widget_data_get(obj);
646    if (!wd) return EINA_FALSE;
647    return wd->state;
648 }
649
650 /**
651  * Set flip perspective
652  *
653  * @param obj The flip object
654  * @param foc The coordinate to set the focus on
655  * @param x The X coordinate
656  * @param y The Y coordinate
657  *
658  * NOTE: This function currently does nothing.
659  *
660  * @ingroup Flip
661  */
662 EAPI void
663 elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
664 {
665    ELM_CHECK_WIDTYPE(obj, widtype);
666    Widget_Data *wd = elm_widget_data_get(obj);
667    if (!wd) return;
668 }
669
670 /**
671  * Runs the flip animation
672  *
673  * @param obj The flip object
674  * @param mode The mode type.  Currently accepted modes are:
675  *
676  * ELM_FLIP_ROTATE_Y_CENTER_AXIS
677  * ELM_FLIP_ROTATE_X_CENTER_AXIS
678  * ELM_FLIP_ROTATE_XZ_CENTER_AXIS
679  * ELM_FLIP_ROTATE_YZ_CENTER_AXIS
680  * ELM_FLIP_CUBE_LEFT
681  * ELM_FLIP_CUBE_RIGHT
682  * ELM_FLIP_CUBE_UP
683  * ELM_FLIP_CUBE_DOWN
684  * 
685  * FIXME: add - ELM_FLIP_CUBE_UP
686  * FIXME: add - ELM_FLIP_CUBE_DOWN
687  *
688  * @ingroup Flip
689  */
690 EAPI void
691 elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode)
692 {
693    ELM_CHECK_WIDTYPE(obj, widtype);
694    Widget_Data *wd = elm_widget_data_get(obj);
695    if (!wd) return;
696    if (!wd->animator) wd->animator = ecore_animator_add(_animate, obj);
697    flip_show_hide(obj);
698    wd->mode = mode;
699    wd->start = ecore_loop_time_get();
700    wd->len = 0.5;
701    // force calc to contents are the right size before transition
702    evas_smart_objects_calculate(evas_object_evas_get(obj));
703    _flip(obj);
704    // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
705    evas_object_map_enable_set(wd->front.content, 0);
706    evas_object_map_enable_set(wd->back.content, 0);
707    evas_object_resize(wd->front.content, 0, 0);
708    evas_object_resize(wd->back.content, 0, 0);
709    evas_smart_objects_calculate(evas_object_evas_get(obj));
710    _configure(obj);
711    // FIXME: end hack
712 }