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