1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_PART_PROTECTED
7 
8 #include <Elementary.h>
9 #include "elm_priv.h"
10 #include "efl_ui_widget_flip.h"
11 #include "elm_widget_container.h"
12 
13 #include "efl_ui_flip_part.eo.h"
14 #include "elm_part_helper.h"
15 
16 #define MY_CLASS EFL_UI_FLIP_CLASS
17 #define MY_CLASS_NAME "Efl.Ui.Flip"
18 
19 static const char SIG_ANIMATE_BEGIN[] = "animate,begin";
20 static const char SIG_ANIMATE_DONE[] = "animate,done";
21 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
22    {SIG_ANIMATE_BEGIN, ""},
23    {SIG_ANIMATE_DONE, ""},
24    {NULL, NULL}
25 };
26 
27 static Eina_Bool _flip(Evas_Object *obj);
28 
29 static void _update_front_back(Eo *obj, Efl_Ui_Flip_Data *sd);
30 
31 static void
_slice_free(Slice * sl)32 _slice_free(Slice *sl)
33 {
34    evas_object_del(sl->obj);
35    free(sl);
36 }
37 
38 static void
_state_slices_clear(Efl_Ui_Flip_Data * sd)39 _state_slices_clear(Efl_Ui_Flip_Data *sd)
40 {
41    int i, j, num;
42 
43    if (sd->slices)
44      {
45         num = 0;
46         for (j = 0; j < sd->slices_h; j++)
47           {
48              for (i = 0; i < sd->slices_w; i++)
49                {
50                   if (sd->slices[num]) _slice_free(sd->slices[num]);
51                   if (sd->slices2[num]) _slice_free(sd->slices2[num]);
52                   num++;
53                }
54           }
55 
56         free(sd->slices);
57         free(sd->slices2);
58         sd->slices = NULL;
59         sd->slices2 = NULL;
60      }
61 
62    sd->slices_w = 0;
63    sd->slices_h = 0;
64 }
65 
66 static void
_sizing_eval(Evas_Object * obj)67 _sizing_eval(Evas_Object *obj)
68 {
69    Evas_Coord minw = -1, minh = -1, minw2 = -1, minh2 = -1;
70    int fingx = 0, fingy = 0;
71    Eina_Size2D max = EINA_SIZE2D(-1, -1), max2 = EINA_SIZE2D(-1, -1);
72 
73    EFL_UI_FLIP_DATA_GET(obj, sd);
74 
75    if (sd->front.content)
76      evas_object_size_hint_combined_min_get(sd->front.content, &minw, &minh);
77    if (sd->back.content)
78      evas_object_size_hint_combined_min_get(sd->back.content, &minw2, &minh2);
79    if (sd->front.content)
80      max = efl_gfx_hint_size_combined_max_get(sd->front.content);
81    if (sd->back.content)
82      max2 = efl_gfx_hint_size_combined_max_get(sd->back.content);
83 
84    if (minw2 > minw) minw = minw2;
85    if (minh2 > minh) minh = minh2;
86    if ((max2.w >= 0) && (max2.w < max.w)) max.w = max2.w;
87    if ((max2.h >= 0) && (max2.h < max.h)) max.h = max2.h;
88 
89    if (sd->dir_enabled[ELM_FLIP_DIRECTION_UP]) fingy++;
90    if (sd->dir_enabled[ELM_FLIP_DIRECTION_DOWN]) fingy++;
91    if (sd->dir_enabled[ELM_FLIP_DIRECTION_LEFT]) fingx++;
92    if (sd->dir_enabled[ELM_FLIP_DIRECTION_RIGHT]) fingx++;
93 
94    elm_coords_finger_size_adjust(fingx, &minw, fingy, &minh);
95 
96    efl_gfx_hint_size_restricted_min_set(obj, EINA_SIZE2D(minw, minh));
97    efl_gfx_hint_size_restricted_max_set(obj, max);
98 }
99 
100 EOLIAN static Eina_Error
_efl_ui_flip_efl_ui_widget_theme_apply(Eo * obj,Efl_Ui_Flip_Data * sd EINA_UNUSED)101 _efl_ui_flip_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Flip_Data *sd EINA_UNUSED)
102 {
103    Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
104    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
105    if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
106 
107    _sizing_eval(obj);
108 
109    return int_ret;
110 }
111 
112 static void
_changed_size_hints_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)113 _changed_size_hints_cb(void *data,
114                        Evas *e EINA_UNUSED,
115                        Evas_Object *obj EINA_UNUSED,
116                        void *event_info EINA_UNUSED)
117 {
118    _sizing_eval(data);
119 }
120 
121 EOLIAN static Eina_Bool
_efl_ui_flip_efl_ui_widget_widget_sub_object_add(Eo * obj,Efl_Ui_Flip_Data * _pd EINA_UNUSED,Evas_Object * sobj)122 _efl_ui_flip_efl_ui_widget_widget_sub_object_add(Eo *obj, Efl_Ui_Flip_Data *_pd EINA_UNUSED, Evas_Object *sobj)
123 {
124    Eina_Bool int_ret = EINA_FALSE;
125 
126    if (evas_object_data_get(sobj, "elm-parent") == obj)
127      return EINA_TRUE;
128 
129    int_ret = elm_widget_sub_object_add(efl_super(obj, MY_CLASS), sobj);
130    if (!int_ret) return EINA_FALSE;
131 
132    evas_object_data_set(sobj, "_elm_leaveme", sobj);
133    evas_object_smart_member_add(sobj, obj);
134    evas_object_event_callback_add
135      (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb, obj);
136    evas_object_lower(sobj);
137 
138    return EINA_TRUE;
139 }
140 
141 EOLIAN static Eina_Bool
_efl_ui_flip_efl_ui_widget_widget_sub_object_del(Eo * obj,Efl_Ui_Flip_Data * sd,Evas_Object * sobj)142 _efl_ui_flip_efl_ui_widget_widget_sub_object_del(Eo *obj, Efl_Ui_Flip_Data *sd, Evas_Object *sobj)
143 {
144    Eina_Bool int_ret = EINA_FALSE;
145 
146 
147    int_ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj);
148    if (!int_ret) return EINA_FALSE;
149 
150    if (sobj == sd->front.content)
151      {
152         evas_object_data_del(sobj, "_elm_leaveme");
153         sd->front.content = NULL;
154         evas_object_hide(sd->front.clip);
155      }
156    else if (sobj == sd->back.content)
157      {
158         evas_object_data_del(sobj, "_elm_leaveme");
159         sd->back.content = NULL;
160         evas_object_hide(sd->back.clip);
161      }
162 
163    evas_object_smart_member_del(sobj);
164    evas_object_clip_unset(sobj);
165 
166    evas_object_event_callback_del_full
167      (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb, obj);
168    _sizing_eval(obj);
169 
170    return EINA_TRUE;
171 }
172 
173 static Slice *
_slice_new(Evas_Object * container_obj,Evas_Object * obj)174 _slice_new(Evas_Object *container_obj,
175            Evas_Object *obj)
176 {
177    Slice *sl;
178 
179    sl = calloc(1, sizeof(Slice));
180    if (!sl) return NULL;
181 
182    sl->obj = evas_object_image_add(evas_object_evas_get(obj));
183 
184    evas_object_smart_member_add(sl->obj, container_obj);
185 
186    evas_object_image_smooth_scale_set(sl->obj, EINA_FALSE);
187    evas_object_pass_events_set(sl->obj, EINA_TRUE);
188    evas_object_image_source_set(sl->obj, obj);
189 
190    return sl;
191 }
192 
193 static void
_slice_apply(Efl_Ui_Flip_Data * sd,Slice * sl,Evas_Coord x EINA_UNUSED,Evas_Coord y EINA_UNUSED,Evas_Coord w,Evas_Coord h EINA_UNUSED,Evas_Coord ox,Evas_Coord oy,Evas_Coord ow,Evas_Coord oh)194 _slice_apply(Efl_Ui_Flip_Data *sd,
195              Slice *sl,
196              Evas_Coord x EINA_UNUSED,
197              Evas_Coord y EINA_UNUSED,
198              Evas_Coord w,
199              Evas_Coord h EINA_UNUSED,
200              Evas_Coord ox,
201              Evas_Coord oy,
202              Evas_Coord ow,
203              Evas_Coord oh)
204 {
205    static Evas_Map *m = NULL;
206    int i;
207 
208    if (!m) m = evas_map_new(4);
209    if (!m) return;
210 
211    evas_map_smooth_set(m, EINA_FALSE);
212    for (i = 0; i < 4; i++)
213      {
214         evas_map_point_color_set(m, i, 255, 255, 255, 255);
215         if (sd->dir == ELM_FLIP_DIRECTION_LEFT)
216           {
217              int p[4] = { 0, 1, 2, 3 };
218              evas_map_point_coord_set(m, i, ox + sl->x[p[i]], oy + sl->y[p[i]],
219                                       sl->z[p[i]]);
220              evas_map_point_image_uv_set(m, i, sl->u[p[i]], sl->v[p[i]]);
221           }
222         else if (sd->dir == ELM_FLIP_DIRECTION_RIGHT)
223           {
224              int p[4] = { 1, 0, 3, 2 };
225              evas_map_point_coord_set(m, i, ox + (w - sl->x[p[i]]),
226                                       oy + sl->y[p[i]], sl->z[p[i]]);
227              evas_map_point_image_uv_set(m, i, ow - sl->u[p[i]], sl->v[p[i]]);
228           }
229         else if (sd->dir == ELM_FLIP_DIRECTION_UP)
230           {
231              int p[4] = { 1, 0, 3, 2 };
232              evas_map_point_coord_set(m, i, ox + sl->y[p[i]], oy + sl->x[p[i]],
233                                       sl->z[p[i]]);
234              evas_map_point_image_uv_set(m, i, sl->v[p[i]], sl->u[p[i]]);
235           }
236         else /* if (sd->dir == 3) will be this anyway */
237           {
238              int p[4] = { 0, 1, 2, 3 };
239              evas_map_point_coord_set(m, i, ox + sl->y[p[i]],
240                                       oy + (w - sl->x[p[i]]), sl->z[p[i]]);
241              evas_map_point_image_uv_set(m, i, sl->v[p[i]], oh - sl->u[p[i]]);
242           }
243      }
244 
245    evas_object_map_enable_set(sl->obj, EINA_TRUE);
246    evas_object_image_fill_set(sl->obj, 0, 0, ow, oh);
247    evas_object_map_set(sl->obj, m);
248 }
249 
250 static void
_slice_3d(Efl_Ui_Flip_Data * sd EINA_UNUSED,Slice * sl,Evas_Coord x,Evas_Coord y,Evas_Coord w,Evas_Coord h)251 _slice_3d(Efl_Ui_Flip_Data *sd EINA_UNUSED,
252           Slice *sl,
253           Evas_Coord x,
254           Evas_Coord y,
255           Evas_Coord w,
256           Evas_Coord h)
257 {
258    Evas_Map *m = evas_map_dup(evas_object_map_get(sl->obj));
259    int i;
260 
261    if (!m) return;
262 
263    // vanishing point is center of page, and focal dist is 1024
264    evas_map_util_3d_perspective(m, x + (w / 2), y + (h / 2), 0, 1024);
265    for (i = 0; i < 4; i++)
266      {
267         Evas_Coord xx, yy;
268         evas_map_point_coord_get(m, i, &xx, &yy, NULL);
269         evas_map_point_coord_set(m, i, xx, yy, 0);
270      }
271 
272    if (evas_map_util_clockwise_get(m)) evas_object_show(sl->obj);
273    else evas_object_hide(sl->obj);
274 
275    evas_object_map_set(sl->obj, m);
276    evas_map_free(m);
277 }
278 
279 static void
_slice_light(Efl_Ui_Flip_Data * sd EINA_UNUSED,Slice * sl,Evas_Coord x,Evas_Coord y,Evas_Coord w,Evas_Coord h)280 _slice_light(Efl_Ui_Flip_Data *sd EINA_UNUSED,
281              Slice *sl,
282              Evas_Coord x,
283              Evas_Coord y,
284              Evas_Coord w,
285              Evas_Coord h)
286 {
287    Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
288    int i;
289 
290    if (!m) return;
291 
292    evas_map_util_3d_lighting(m,
293      /* light position
294       * (centered over page 10 * h toward camera) */
295                              x + (w / 2), y + (h / 2), -10000,
296                              255, 255, 255, // light color
297                              0, 0, 0);   // ambient minimum
298 
299    // multiply brightness by 1.2 to make lightish bits all white so we don't
300    // add shading where we could otherwise be pure white
301    for (i = 0; i < 4; i++)
302      {
303         int r, g, b, a;
304 
305         evas_map_point_color_get(m, i, &r, &g, &b, &a);
306         r = (double)r * 1.2; if (r > 255) r = 255;
307         g = (double)g * 1.2; if (g > 255) g = 255;
308         b = (double)b * 1.2; if (b > 255) b = 255;
309         evas_map_point_color_set(m, i, r, g, b, a);
310      }
311 
312    evas_object_map_set(sl->obj, m);
313 }
314 
315 static void
_slice_xyz(Efl_Ui_Flip_Data * sd EINA_UNUSED,Slice * sl,double xx1,double yy1,double zz1,double xx2,double yy2,double zz2,double xx3,double yy3,double zz3,double xx4,double yy4,double zz4)316 _slice_xyz(Efl_Ui_Flip_Data *sd EINA_UNUSED,
317            Slice *sl,
318            double xx1,
319            double yy1,
320            double zz1,
321            double xx2,
322            double yy2,
323            double zz2,
324            double xx3,
325            double yy3,
326            double zz3,
327            double xx4,
328            double yy4,
329            double zz4)
330 {
331    sl->x[0] = xx1; sl->y[0] = yy1; sl->z[0] = zz1;
332    sl->x[1] = xx2; sl->y[1] = yy2; sl->z[1] = zz2;
333    sl->x[2] = xx3; sl->y[2] = yy3; sl->z[2] = zz3;
334    sl->x[3] = xx4; sl->y[3] = yy4; sl->z[3] = zz4;
335 }
336 
337 static void
_slice_uv(Efl_Ui_Flip_Data * sd EINA_UNUSED,Slice * sl,double u1,double v1,double u2,double v2,double u3,double v3,double u4,double v4)338 _slice_uv(Efl_Ui_Flip_Data *sd EINA_UNUSED,
339           Slice *sl,
340           double u1,
341           double v1,
342           double u2,
343           double v2,
344           double u3,
345           double v3,
346           double u4,
347           double v4)
348 {
349    sl->u[0] = u1; sl->v[0] = v1;
350    sl->u[1] = u2; sl->v[1] = v2;
351    sl->u[2] = u3; sl->v[2] = v3;
352    sl->u[3] = u4; sl->v[3] = v4;
353 }
354 
355 static void
_deform_point(Vertex2 * vi,Vertex3 * vo,double rho,double theta,double A)356 _deform_point(Vertex2 *vi,
357               Vertex3 *vo,
358               double rho,
359               double theta,
360               double A)
361 {
362    // ^Y
363    // |
364    // |    X
365    // +---->
366    // theta == cone angle (0 -> PI/2)
367    // A     == distance of cone apex from origin
368    // rho   == angle of cone from vertical axis (...-PI/2 to PI/2...)
369    Vertex3 v1;
370    double d, r, b;
371 
372    d = sqrt((vi->x * vi->x) + pow(vi->y - A, 2));
373    r = d * sin(theta);
374    b = asin(vi->x / d) / sin(theta);
375 
376    v1.x = r * sin(b);
377    v1.y = d + A - (r * (1 - cos(b)) * sin(theta));
378    v1.z = r * (1 - cos(b)) * cos(theta);
379 
380    vo->x = (v1.x * cos(rho)) - (v1.z * sin(rho));
381    vo->y = v1.y;
382    vo->z = (v1.x * sin(rho)) + (v1.z * cos(rho));
383 }
384 
385 static void
_interp_point(Vertex3 * vi1,Vertex3 * vi2,Vertex3 * vo,double v)386 _interp_point(Vertex3 *vi1,
387               Vertex3 *vi2,
388               Vertex3 *vo,
389               double v)
390 {
391    vo->x = (v * vi2->x) + ((1.0 - v) * vi1->x);
392    vo->y = (v * vi2->y) + ((1.0 - v) * vi1->y);
393    vo->z = (v * vi2->z) + ((1.0 - v) * vi1->z);
394 }
395 
396 static int
_slice_obj_color_sum(Slice * s,int p,int * r,int * g,int * b,int * a)397 _slice_obj_color_sum(Slice *s,
398                      int p,
399                      int *r,
400                      int *g,
401                      int *b,
402                      int *a)
403 {
404    Evas_Map *m;
405    int rr = 0, gg = 0, bb = 0, aa = 0;
406 
407    if (!s) return 0;
408 
409    m = (Evas_Map *)evas_object_map_get(s->obj);
410    if (!m) return 0;
411 
412    evas_map_point_color_get(m, p, &rr, &gg, &bb, &aa);
413    *r += rr; *g += gg; *b += bb; *a += aa;
414 
415    return 1;
416 }
417 
418 static void
_slice_obj_color_set(Slice * s,int p,int r,int g,int b,int a)419 _slice_obj_color_set(Slice *s,
420                      int p,
421                      int r,
422                      int g,
423                      int b,
424                      int a)
425 {
426    Evas_Map *m;
427 
428    if (!s) return;
429 
430    m = (Evas_Map *)evas_object_map_get(s->obj);
431    if (!m) return;
432 
433    evas_map_point_color_set(m, p, r, g, b, a);
434    evas_object_map_set(s->obj, m);
435 }
436 
437 static void
_slice_obj_vert_color_merge(Slice * s1,int p1,Slice * s2,int p2,Slice * s3,int p3,Slice * s4,int p4)438 _slice_obj_vert_color_merge(Slice *s1,
439                             int p1,
440                             Slice *s2,
441                             int p2,
442                             Slice *s3,
443                             int p3,
444                             Slice *s4,
445                             int p4)
446 {
447    int r = 0, g = 0, b = 0, a = 0, n = 0;
448 
449    n += _slice_obj_color_sum(s1, p1, &r, &g, &b, &a);
450    n += _slice_obj_color_sum(s2, p2, &r, &g, &b, &a);
451    n += _slice_obj_color_sum(s3, p3, &r, &g, &b, &a);
452    n += _slice_obj_color_sum(s4, p4, &r, &g, &b, &a);
453 
454    if (n < 1) return;
455    r /= n; g /= n; b /= n; a /= n;
456 
457    _slice_obj_color_set(s1, p1, r, g, b, a);
458    _slice_obj_color_set(s2, p2, r, g, b, a);
459    _slice_obj_color_set(s3, p3, r, g, b, a);
460    _slice_obj_color_set(s4, p4, r, g, b, a);
461 }
462 
463 static int
_state_update(Evas_Object * obj)464 _state_update(Evas_Object *obj)
465 {
466    Efl_Ui_Flip_Data *sd = efl_data_scope_get(obj, MY_CLASS);
467    Slice *sl;
468    Vertex3 *tvo, *tvol;
469    Evas_Object *front, *back;
470    int i, j, num, nn, jump, num2;
471    double b, minv = 0.0, minva, mgrad;
472    Evas_Coord xx1, yy1, xx2, yy2, mx, my;
473    Evas_Coord x, y, w, h, ox, oy, ow, oh;
474    int gx, gy, gszw, gszh, gw, gh, col, row, nw, nh;
475    double rho, A, theta, perc, n, rhol, Al, thetal;
476 
477    sd->backflip = EINA_TRUE;
478    if (sd->state)
479      {
480         front = sd->front.content;
481         back = sd->front.content;
482      }
483    else
484      {
485         front = sd->back.content;
486         back = sd->back.content;
487      }
488 
489    evas_object_geometry_get(obj, &x, &y, &w, &h);
490    ox = x; oy = y; ow = w; oh = h;
491    xx1 = sd->down_x;
492    yy1 = sd->down_y;
493    xx2 = sd->x;
494    yy2 = sd->y;
495 
496    if (sd->dir == ELM_FLIP_DIRECTION_LEFT)
497      {
498         // no nothing. left drag is standard
499      }
500    else if (sd->dir == ELM_FLIP_DIRECTION_RIGHT)
501      {
502         xx1 = (w - 1) - xx1;
503         xx2 = (w - 1) - xx2;
504      }
505    else if (sd->dir == ELM_FLIP_DIRECTION_UP)
506      {
507         Evas_Coord tmp;
508 
509         tmp = xx1; xx1 = yy1; yy1 = tmp;
510         tmp = xx2; xx2 = yy2; yy2 = tmp;
511         tmp = w; w = h; h = tmp;
512      }
513    else /* if (sd->dir == 3) will be this anyway */
514      {
515         Evas_Coord tmp;
516 
517         tmp = xx1; xx1 = yy1; yy1 = tmp;
518         tmp = xx2; xx2 = yy2; yy2 = tmp;
519         tmp = w; w = h; h = tmp;
520         xx1 = (w - 1) - xx1;
521         xx2 = (w - 1) - xx2;
522      }
523 
524    if (xx2 >= xx1) xx2 = xx1 - 1;
525    mx = (xx1 + xx2) / 2;
526    my = (yy1 + yy2) / 2;
527 
528    if (mx < 0) mx = 0;
529    else if (mx >= w)
530      mx = w - 1;
531    if (my < 0) my = 0;
532    else if (my >= h)
533      my = h - 1;
534 
535    mgrad = (double)(yy1 - yy2) / (double)(xx1 - xx2);
536 
537    if (mx < 1) mx = 1;  // quick hack to keep curl line visible
538 
539    if (EINA_DBL_EQ(mgrad, 0.0)) // special horizontal case
540      mgrad = 0.001;  // quick dirty hack for now
541    // else
542    {
543       minv = 1.0 / mgrad;
544       // y = (m * x) + b
545       b = my + (minv * mx);
546    }
547    if ((b >= -5) && (b <= (h + 5)))
548      {
549         if (minv > 0.0) // clamp to h
550           {
551              minv = (double)(h + 5 - my) / (double)(mx);
552              b = my + (minv * mx);
553           }
554         else // clamp to 0
555           {
556              minv = (double)(-5 - my) / (double)(mx);
557              b = my + (minv * mx);
558           }
559      }
560 
561    perc = (double)xx2 / (double)xx1;
562    if (perc < 0.0) perc = 0.0;
563    else if (perc > 1.0)
564      perc = 1.0;
565 
566    minva = atan(minv) / (M_PI / 2);
567    if (minva < 0.0) minva = -minva;
568 
569    // A = apex of cone
570    if (b <= 0) A = b;
571    else A = h - b;
572    if (A < -(h * 20)) A = -h * 20;
573    //--//
574    Al = -5;
575 
576    // rho = is how much the page is turned
577    n = 1.0 - perc;
578    n = 1.0 - cos(n * M_PI / 2.0);
579    n = n * n;
580    rho = -(n * M_PI);
581    //--//
582    rhol = -(n * M_PI);
583 
584    // theta == curliness (how much page curls in on itself
585    n = sin((1.0 - perc) * M_PI);
586    n = n * 1.2;
587    theta = 7.86 + n;
588    //--//
589    n = sin((1.0 - perc) * M_PI);
590    n = 1.0 - n;
591    n = n * n;
592    n = 1.0 - n;
593    thetal = 7.86 + n;
594 
595    nw = 16;
596    nh = 16;
597    gszw = w / nw;
598    gszh = h / nh;
599    if (gszw < 4) gszw = 4;
600    if (gszh < 4) gszh = 4;
601 
602    nw = (w + gszw - 1) / gszw;
603    nh = (h + gszh - 1) / gszh;
604    if ((sd->slices_w != nw) || (sd->slices_h != nh)) _state_slices_clear(sd);
605    sd->slices_w = nw;
606    sd->slices_h = nh;
607    if (!sd->slices)
608      {
609         sd->slices = calloc(sd->slices_w * sd->slices_h, sizeof(Slice *));
610         if (!sd->slices) return 0;
611         sd->slices2 = calloc(sd->slices_w * sd->slices_h, sizeof(Slice *));
612         if (!sd->slices2)
613           {
614              ELM_SAFE_FREE(sd->slices, free);
615              return 0;
616           }
617      }
618 
619    num = (sd->slices_w + 1) * (sd->slices_h + 1);
620 
621    tvo = alloca(sizeof(Vertex3) * num);
622    tvol = alloca(sizeof(Vertex3) * (sd->slices_w + 1));
623 
624    for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
625      {
626         Vertex2 vil;
627 
628         vil.x = gx;
629         vil.y = h - ((gx * h) / (w + gszw - 1));
630         _deform_point(&vil, &(tvol[col]), rhol, thetal, Al);
631      }
632 
633    n = minva * sin(perc * M_PI);
634    n = n * n;
635 
636    num = 0;
637    for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
638      {
639         for (gy = 0; gy <= (h + gszh - 1); gy += gszh)
640           {
641              Vertex2 vi;
642              Vertex3 vo, tvo1;
643 
644              if (gx > w) vi.x = w;
645              else vi.x = gx;
646              if (gy > h) vi.y = h;
647              else vi.y = gy;
648              _deform_point(&vi, &vo, rho, theta, A);
649              tvo1 = tvol[col];
650              if (gy > h) tvo1.y = h;
651              else tvo1.y = gy;
652              _interp_point(&vo, &tvo1, &(tvo[num]), n);
653              num++;
654           }
655      }
656 
657    jump = sd->slices_h + 1;
658    for (col = 0, gx = 0; gx < w; gx += gszw, col++)
659      {
660         num = sd->slices_h * col;
661         num2 = jump * col;
662 
663         gw = gszw;
664         if ((gx + gw) > w) gw = w - gx;
665 
666         for (row = 0, gy = 0; gy < h; gy += gszh, row++)
667           {
668              Vertex3 vo[4];
669 
670              memset(vo, 0, sizeof (vo));
671 
672              if (b > 0) nn = num + sd->slices_h - row - 1;
673              else nn = num + row;
674 
675              gh = gszh;
676              if ((gy + gh) > h) gh = h - gy;
677 
678              vo[0] = tvo[num2 + row];
679              vo[1] = tvo[num2 + row + jump];
680              vo[2] = tvo[num2 + row + jump + 1];
681              vo[3] = tvo[num2 + row + 1];
682 
683 #define SWP(a, b)   \
684   do {              \
685        typeof(a)vt; \
686        vt = (a);    \
687        (a) = (b);   \
688        (b) = vt;    \
689     } while (0)
690 
691              if (b > 0)
692                {
693                   SWP(vo[0], vo[3]);
694                   SWP(vo[1], vo[2]);
695                   vo[0].y = h - vo[0].y;
696                   vo[1].y = h - vo[1].y;
697                   vo[2].y = h - vo[2].y;
698                   vo[3].y = h - vo[3].y;
699                }
700 
701              // FRONT
702              sl = sd->slices[nn];
703              if (!sl)
704                {
705                   sl = _slice_new(obj, front);
706                   if (!sl) return 0;
707                   sd->slices[nn] = sl;
708                }
709              _slice_xyz(sd, sl,
710                         vo[0].x, vo[0].y, vo[0].z,
711                         vo[1].x, vo[1].y, vo[1].z,
712                         vo[2].x, vo[2].y, vo[2].z,
713                         vo[3].x, vo[3].y, vo[3].z);
714              if (b <= 0)
715                _slice_uv(sd, sl,
716                          gx, gy, gx + gw, gy, gx + gw, gy + gh, gx, gy + gh);
717              else
718                _slice_uv(sd, sl,
719                          gx, h - (gy + gh), gx + gw, h - (gy + gh), gx + gw,
720                          h - gy, gx, h - gy);
721 
722              // BACK
723              sl = sd->slices2[nn];
724              if (!sl)
725                {
726                   sl = _slice_new(obj, back);
727                   if (!sl) return 0;
728                   sd->slices2[nn] = sl;
729                }
730 
731              _slice_xyz(sd, sl,
732                         vo[1].x, vo[1].y, vo[1].z,
733                         vo[0].x, vo[0].y, vo[0].z,
734                         vo[3].x, vo[3].y, vo[3].z,
735                         vo[2].x, vo[2].y, vo[2].z);
736              if (sd->backflip)
737                {
738                   if (b <= 0)
739                     _slice_uv(sd, sl, gx + gw, gy, gx, gy, gx, gy + gh, gx + gw,
740                               gy + gh);
741                   else
742                     _slice_uv(sd, sl, gx + gw, h - (gy + gh), gx, h - (gy + gh),
743                               gx, h - gy, gx + gw, h - gy);
744                }
745              else
746                {
747                   if (b <= 0)
748                     _slice_uv(sd, sl, w - (gx + gw), gy, w - (gx), gy, w - (gx),
749                               gy + gh, w - (gx + gw), gy + gh);
750                   else
751                     _slice_uv(sd, sl, w - (gx + gw), h - (gy + gh), w - (gx),
752                               h - (gy + gh), w - (gx), h - gy, w - (gx + gw),
753                               h - gy);
754                }
755           }
756      }
757 
758    for (num = 0; num < sd->slices_h * sd->slices_w; num++)
759      {
760         _slice_apply(sd, sd->slices[num], x, y, w, h, ox, oy, ow, oh);
761         _slice_apply(sd, sd->slices2[num], x, y, w, h, ox, oy, ow, oh);
762         _slice_light(sd, sd->slices[num], ox, oy, ow, oh);
763         _slice_light(sd, sd->slices2[num], ox, oy, ow, oh);
764      }
765 
766    for (i = 0; i <= sd->slices_w; i++)
767      {
768         num = i * sd->slices_h;
769         for (j = 0; j <= sd->slices_h; j++)
770           {
771              Slice *s[4] = { NULL }, *s2[4] = { NULL };
772 
773              if ((i > 0) && (j > 0))
774                s[0] = sd->slices[num - 1 - sd->slices_h],
775                s2[0] = sd->slices2[num - 1 - sd->slices_h];
776              if ((i < sd->slices_w) && (j > 0))
777                s[1] = sd->slices[num - 1],
778                s2[1] = sd->slices2[num - 1];
779              if ((i > 0) && (j < sd->slices_h))
780                s[2] = sd->slices[num - sd->slices_h],
781                s2[2] = sd->slices2[num - sd->slices_h];
782              if ((i < sd->slices_w) && (j < sd->slices_h))
783                s[3] = sd->slices[num],
784                s2[3] = sd->slices2[num];
785              switch (sd->dir)
786                {
787                 case ELM_FLIP_DIRECTION_LEFT:
788                   _slice_obj_vert_color_merge
789                     (s[0], 2, s[1], 3, s[2], 1, s[3], 0);
790                   _slice_obj_vert_color_merge
791                     (s2[0], 3, s2[1], 2, s2[2], 0, s2[3], 1);
792                   break;
793 
794                 case ELM_FLIP_DIRECTION_RIGHT:
795                   _slice_obj_vert_color_merge
796                     (s[0], 3, s[1], 2, s[2], 0, s[3], 1);
797                   _slice_obj_vert_color_merge
798                     (s2[0], 2, s2[1], 3, s2[2], 1, s2[3], 0);
799                   break;
800 
801                 case ELM_FLIP_DIRECTION_UP:
802                   _slice_obj_vert_color_merge
803                     (s[0], 3, s[1], 2, s[2], 0, s[3], 1);
804                   _slice_obj_vert_color_merge
805                     (s2[0], 2, s2[1], 3, s2[2], 1, s2[3], 0);
806                   break;
807 
808                 default:
809                   _slice_obj_vert_color_merge
810                     (s[0], 2, s[1], 3, s[2], 1, s[3], 0);
811                   _slice_obj_vert_color_merge
812                     (s2[0], 3, s2[1], 2, s2[2], 0, s2[3], 1);
813                }
814              num++;
815           }
816      }
817 
818    for (num = 0; num < sd->slices_h * sd->slices_w; num++)
819      {
820         _slice_3d(sd, sd->slices[num], ox, oy, ow, oh);
821         _slice_3d(sd, sd->slices2[num], ox, oy, ow, oh);
822      }
823 
824    return 1;
825 }
826 
827 static void
_cross_fade_update(Evas_Object * obj,double t)828 _cross_fade_update(Evas_Object *obj, double t)
829 {
830    int ca, cb;
831    Evas_Object *aclip, *bclip;
832    Eina_Bool front;
833    double s;
834    EFL_UI_FLIP_DATA_GET(obj, sd);
835    front = sd->next_state;
836 
837    s = sin(t * M_PI_2);  // fade in sinusoidally
838    t = s * s;
839    ca = 255 * t;
840    if (ca < 0) ca = 0;
841    if (ca > 255) ca = 255;
842 
843    cb = sqrt(255 * 255 - ca * ca);
844    if (cb < 0) cb = 0;
845    if (cb > 255) cb = 255;
846 
847    if (front)
848      {
849          aclip = sd->front.clip;
850          bclip = sd->back.clip;
851      }
852    else
853      {
854          aclip = sd->back.clip;
855          bclip = sd->front.clip;
856      }
857 
858    evas_object_color_set(aclip, ca, ca, ca, ca);
859    evas_object_color_set(bclip, cb, cb, cb, cb);
860 }
861 
862 static void
_state_end(Efl_Ui_Flip_Data * sd)863 _state_end(Efl_Ui_Flip_Data *sd)
864 {
865    _state_slices_clear(sd);
866 }
867 
868 static void
_flip_show_hide(Evas_Object * obj)869 _flip_show_hide(Evas_Object *obj)
870 {
871    EFL_UI_FLIP_DATA_GET(obj, sd);
872    if (elm_flip_front_visible_get(obj))
873      {
874         if (sd->pageflip)
875           {
876              if (sd->front.content)
877                {
878                   evas_object_move(sd->front.content, 4999, 4999);
879                   evas_object_show(sd->front.clip);
880                }
881              else
882                evas_object_hide(sd->front.clip);
883              if (sd->back.content)
884                evas_object_show(sd->back.clip);
885              else
886                evas_object_hide(sd->back.clip);
887           }
888         else
889           {
890              if (sd->front.content)
891                evas_object_show(sd->front.clip);
892              else
893                evas_object_hide(sd->front.clip);
894              evas_object_hide(sd->back.clip);
895           }
896      }
897    else
898      {
899         if (sd->pageflip)
900           {
901              if (sd->front.content)
902                evas_object_show(sd->front.clip);
903              else
904                evas_object_hide(sd->front.clip);
905              if (sd->back.content)
906                {
907                   evas_object_move(sd->back.content, 4999, 4999);
908                   evas_object_show(sd->back.clip);
909                }
910              else
911                evas_object_hide(sd->back.clip);
912           }
913         else
914           {
915              evas_object_hide(sd->front.clip);
916              if (sd->back.content)
917                evas_object_show(sd->back.clip);
918              else
919                evas_object_hide(sd->back.clip);
920           }
921      }
922 }
923 
924 static void
_map_uv_set(Evas_Object * obj,Evas_Map * map)925 _map_uv_set(Evas_Object *obj, Evas_Map *map)
926 {
927    Evas_Coord x, y, w, h;
928 
929    // FIXME: only handles filled obj
930    if (efl_isa(obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS) &&
931        !evas_object_image_source_get(obj))
932      {
933         int iw, ih;
934         evas_object_image_size_get(obj, &iw, &ih);
935         evas_object_geometry_get(obj, &x, &y, &w, &h);
936         evas_map_util_points_populate_from_geometry(map, x, y, w, h, 0);
937         evas_map_point_image_uv_set(map, 0, 0, 0);
938         evas_map_point_image_uv_set(map, 1, iw, 0);
939         evas_map_point_image_uv_set(map, 2, iw, ih);
940         evas_map_point_image_uv_set(map, 3, 0, ih);
941      }
942    else
943      {
944         evas_object_geometry_get(obj, &x, &y, &w, &h);
945         evas_map_util_points_populate_from_geometry(map, x, y, w, h, 0);
946      }
947 }
948 
949 static void
_flip_do(Evas_Object * obj,double t,Elm_Flip_Mode mode,int lin,int rev)950 _flip_do(Evas_Object *obj,
951          double t,
952          Elm_Flip_Mode mode,
953          int lin,
954          int rev)
955 {
956    double p, deg, pp;
957    Evas_Map *mf, *mb;
958    Evas_Coord x, y, w, h;
959    Evas_Coord cx, cy, px, py, foc;
960    int lx, ly, lz, lr, lg, lb, lar, lag, lab;
961 
962    EFL_UI_FLIP_DATA_GET(obj, sd);
963 
964    mf = evas_map_new(4);
965    evas_map_smooth_set(mf, EINA_FALSE);
966    mb = evas_map_new(4);
967    evas_map_smooth_set(mb, EINA_FALSE);
968 
969    if (sd->front.content)
970      _map_uv_set(sd->front.content, mf);
971    if (sd->back.content)
972      _map_uv_set(sd->back.content, mb);
973 
974    evas_object_geometry_get(obj, &x, &y, &w, &h);
975 
976    cx = x + (w / 2);
977    cy = y + (h / 2);
978 
979    px = x + (w / 2);
980    py = y + (h / 2);
981    foc = 2048;
982 
983    lx = cx;
984    ly = cy;
985    lz = -10000;
986    lr = 255;
987    lg = 255;
988    lb = 255;
989    lar = 0;
990    lag = 0;
991    lab = 0;
992 
993    switch (mode)
994      {
995       case ELM_FLIP_ROTATE_Y_CENTER_AXIS:
996         p = 1.0 - t;
997         pp = p;
998         if (!lin) pp = (p * p);
999         p = 1.0 - pp;
1000         if (sd->state) deg = 180.0 * p;
1001         else deg = 180 + (180.0 * p);
1002         if (rev) deg = -deg;
1003         evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, 0);
1004         evas_map_util_3d_rotate(mb, 0.0, 180 + deg, 0.0, cx, cy, 0);
1005         break;
1006 
1007       case ELM_FLIP_ROTATE_X_CENTER_AXIS:
1008         p = 1.0 - t;
1009         pp = p;
1010         if (!lin) pp = (p * p);
1011         p = 1.0 - pp;
1012         if (sd->state) deg = 180.0 * p;
1013         else deg = 180 + (180.0 * p);
1014         if (rev) deg = -deg;
1015         evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, 0);
1016         evas_map_util_3d_rotate(mb, 180.0 + deg, 0.0, 0.0, cx, cy, 0);
1017         break;
1018 
1019       case ELM_FLIP_ROTATE_XZ_CENTER_AXIS:
1020         p = 1.0 - t;
1021         pp = p;
1022         if (!lin) pp = (p * p);
1023         p = 1.0 - pp;
1024         if (sd->state) deg = 180.0 * p;
1025         else deg = 180 + (180.0 * p);
1026         if (rev) deg = -deg;
1027         evas_map_util_3d_rotate(mf, deg, 0.0, deg, cx, cy, 0);
1028         evas_map_util_3d_rotate(mb, 180 + deg, 0.0, 180 + deg, cx, cy, 0);
1029         break;
1030 
1031       case ELM_FLIP_ROTATE_YZ_CENTER_AXIS:
1032         p = 1.0 - t;
1033         pp = p;
1034         if (!lin) pp = (p * p);
1035         p = 1.0 - pp;
1036         if (sd->state) deg = 180.0 * p;
1037         else deg = 180 + (180.0 * p);
1038         if (rev) deg = -deg;
1039         evas_map_util_3d_rotate(mf, 0.0, deg, deg, cx, cy, 0);
1040         evas_map_util_3d_rotate(mb, 0.0, 180.0 + deg, 180.0 + deg, cx, cy, 0);
1041         break;
1042 
1043       case ELM_FLIP_CUBE_LEFT:
1044         p = 1.0 - t;
1045         pp = p;
1046         if (!lin) pp = (p * p);
1047         p = 1.0 - pp;
1048         deg = -90.0 * p;
1049         if (sd->state)
1050           {
1051              evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
1052              evas_map_util_3d_rotate(mb, 0.0, deg + 90, 0.0, cx, cy, w / 2);
1053           }
1054         else
1055           {
1056              evas_map_util_3d_rotate(mf, 0.0, deg + 90, 0.0, cx, cy, w / 2);
1057              evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
1058           }
1059         break;
1060 
1061       case ELM_FLIP_CUBE_RIGHT:
1062         p = 1.0 - t;
1063         pp = p;
1064         if (!lin) pp = (p * p);
1065         p = 1.0 - pp;
1066         deg = 90.0 * p;
1067         if (sd->state)
1068           {
1069              evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
1070              evas_map_util_3d_rotate(mb, 0.0, deg - 90, 0.0, cx, cy, w / 2);
1071           }
1072         else
1073           {
1074              evas_map_util_3d_rotate(mf, 0.0, deg - 90, 0.0, cx, cy, w / 2);
1075              evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
1076           }
1077         break;
1078 
1079       case ELM_FLIP_CUBE_UP:
1080         p = 1.0 - t;
1081         pp = p;
1082         if (!lin) pp = (p * p);
1083         p = 1.0 - pp;
1084         deg = -90.0 * p;
1085         if (sd->state)
1086           {
1087              evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1088              evas_map_util_3d_rotate(mb, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1089           }
1090         else
1091           {
1092              evas_map_util_3d_rotate(mf, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1093              evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1094           }
1095         break;
1096 
1097       case ELM_FLIP_CUBE_DOWN:
1098         p = 1.0 - t;
1099         pp = p;
1100         if (!lin) pp = (p * p);
1101         p = 1.0 - pp;
1102         deg = 90.0 * p;
1103         if (sd->state)
1104           {
1105              evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1106              evas_map_util_3d_rotate(mb, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1107           }
1108         else
1109           {
1110              evas_map_util_3d_rotate(mf, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1111              evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1112           }
1113         break;
1114 
1115       case ELM_FLIP_PAGE_LEFT:
1116         break;
1117 
1118       case ELM_FLIP_PAGE_RIGHT:
1119         break;
1120 
1121       case ELM_FLIP_PAGE_UP:
1122         break;
1123 
1124       case ELM_FLIP_PAGE_DOWN:
1125         break;
1126 
1127       default:
1128         break;
1129      }
1130 
1131    if (sd->front.content)
1132      {
1133         evas_map_util_3d_lighting(mf, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1134         evas_map_util_3d_perspective(mf, px, py, 0, foc);
1135         evas_object_map_set(sd->front.content, mf);
1136         evas_object_map_enable_set(sd->front.content, EINA_TRUE);
1137         if (evas_map_util_clockwise_get(mf)) evas_object_show(sd->front.clip);
1138         else evas_object_hide(sd->front.clip);
1139      }
1140 
1141    if (sd->back.content)
1142      {
1143         evas_map_util_3d_lighting(mb, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1144         evas_map_util_3d_perspective(mb, px, py, 0, foc);
1145         evas_object_map_set(sd->back.content, mb);
1146         evas_object_map_enable_set(sd->back.content, EINA_TRUE);
1147         if (evas_map_util_clockwise_get(mb)) evas_object_show(sd->back.clip);
1148         else evas_object_hide(sd->back.clip);
1149      }
1150 
1151    evas_map_free(mf);
1152    evas_map_free(mb);
1153 }
1154 
1155 static void
_show_hide(Evas_Object * obj)1156 _show_hide(Evas_Object *obj)
1157 {
1158    EFL_UI_FLIP_DATA_GET(obj, sd);
1159    Evas_Coord x, y, w, h;
1160    if (!sd) return;
1161 
1162    evas_object_geometry_get(obj, &x, &y, &w, &h);
1163    if (sd->front.content)
1164      {
1165         if ((sd->pageflip) && (sd->state))
1166           {
1167              evas_object_move(sd->front.content, 4999, 4999);
1168           }
1169         else
1170           {
1171              if (!sd->animator)
1172                evas_object_move(sd->front.content, x, y);
1173           }
1174         evas_object_resize(sd->front.content, w, h);
1175      }
1176    if (sd->back.content)
1177      {
1178         if ((sd->pageflip) && (!sd->state))
1179           {
1180              evas_object_move(sd->back.content, 4999, 4999);
1181           }
1182         else
1183           {
1184              if (!sd->animator)
1185                evas_object_move(sd->back.content, x, y);
1186           }
1187         evas_object_resize(sd->back.content, w, h);
1188      }
1189 }
1190 
1191 static void
_configure(Evas_Object * obj)1192 _configure(Evas_Object *obj)
1193 {
1194    Evas_Coord x, y, w, h;
1195    Evas_Coord fsize;
1196 
1197    EFL_UI_FLIP_DATA_GET(obj, sd);
1198    _show_hide(obj);
1199    evas_object_geometry_get(obj, &x, &y, &w, &h);
1200    // FIXME: manual flip wont get fixed
1201    if (sd->animator) _flip(obj);
1202 
1203    if (sd->event[0])
1204      {
1205         fsize = (double)w * sd->dir_hitsize[0];
1206         elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1207         evas_object_geometry_set(sd->event[0], x, y, w, fsize);
1208      }
1209    if (sd->event[1])
1210      {
1211         fsize = (double)w * sd->dir_hitsize[1];
1212         elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1213         evas_object_geometry_set(sd->event[1], x, y + h - fsize, w, fsize);
1214      }
1215    if (sd->event[2])
1216      {
1217         fsize = (double)h * sd->dir_hitsize[2];
1218         elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1219         evas_object_geometry_set(sd->event[2], x, y, fsize, h);
1220      }
1221    if (sd->event[3])
1222      {
1223         fsize = (double)h * sd->dir_hitsize[3];
1224         elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1225         evas_object_geometry_set(sd->event[3], x + w - fsize, y, fsize, h);
1226      }
1227 }
1228 
1229 static Eina_Bool
_flip(Evas_Object * obj)1230 _flip(Evas_Object *obj)
1231 {
1232    double t;
1233    Evas_Coord w, h;
1234 
1235    EFL_UI_FLIP_DATA_GET(obj, sd);
1236 
1237    t = ecore_loop_time_get() - sd->start;
1238 
1239    if (!sd->animator) return ECORE_CALLBACK_CANCEL;
1240 
1241    t = t / sd->len;
1242    if (t > 1.0) t = 1.0;
1243    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1244    if (!sd->manual)
1245      {
1246         if (sd->mode == ELM_FLIP_PAGE_LEFT)
1247           {
1248              sd->dir = ELM_FLIP_DIRECTION_LEFT;
1249              sd->started = EINA_TRUE;
1250              sd->pageflip = EINA_TRUE;
1251              sd->down_x = w - 1;
1252              sd->down_y = h / 2;
1253              sd->x = (1.0 - t) * sd->down_x;
1254              sd->y = sd->down_y;
1255              _flip_show_hide(obj);
1256              _state_update(obj);
1257           }
1258         else if (sd->mode == ELM_FLIP_PAGE_RIGHT)
1259           {
1260              sd->dir = ELM_FLIP_DIRECTION_RIGHT;
1261              sd->started = EINA_TRUE;
1262              sd->pageflip = EINA_TRUE;
1263              sd->down_x = 0;
1264              sd->down_y = h / 2;
1265              sd->x = (t) * w;
1266              sd->y = sd->down_y;
1267              _flip_show_hide(obj);
1268              _state_update(obj);
1269           }
1270         else if (sd->mode == ELM_FLIP_PAGE_UP)
1271           {
1272              sd->dir = ELM_FLIP_DIRECTION_UP;
1273              sd->started = EINA_TRUE;
1274              sd->pageflip = EINA_TRUE;
1275              sd->down_x = w / 2;
1276              sd->down_y = h - 1;
1277              sd->x = sd->down_x;
1278              sd->y = (1.0 - t) * sd->down_y;
1279              _flip_show_hide(obj);
1280              _state_update(obj);
1281           }
1282         else if (sd->mode == ELM_FLIP_PAGE_DOWN)
1283           {
1284              sd->dir = ELM_FLIP_DIRECTION_DOWN;
1285              sd->started = EINA_TRUE;
1286              sd->pageflip = EINA_TRUE;
1287              sd->down_x = w / 2;
1288              sd->down_y = 0;
1289              sd->x = sd->down_x;
1290              sd->y = (t) * h;
1291              _flip_show_hide(obj);
1292              _state_update(obj);
1293           }
1294         else if (sd->mode == ELM_FLIP_CROSS_FADE)
1295           {
1296              sd->dir = 0;
1297              sd->started = EINA_TRUE;
1298              sd->pageflip = EINA_FALSE;
1299              _cross_fade_update(obj, t);
1300           }
1301         else
1302           _flip_do(obj, t, sd->mode, 0, 0);
1303      }
1304 
1305    if (t >= 1.0)
1306      {
1307 #if 0 // this breaks manual flipping. :/
1308         if (sd->state == sd->next_state)
1309           {
1310              /* it was flipped while flipping, do it again */
1311              sd->start = ecore_loop_time_get();
1312              sd->state = !sd->next_state;
1313              return ECORE_CALLBACK_RENEW;
1314           }
1315 #endif
1316         sd->pageflip = EINA_FALSE;
1317         _state_end(sd);
1318         evas_object_map_enable_set(sd->front.content, EINA_FALSE);
1319         evas_object_map_enable_set(sd->back.content, EINA_FALSE);
1320         // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1321         evas_object_resize(sd->front.content, 0, 0);
1322         evas_object_resize(sd->back.content, 0, 0);
1323         evas_smart_objects_calculate(evas_object_evas_get(obj));
1324         // FIXME: end hack
1325         sd->animator = NULL;
1326         if (((sd->manual) && (sd->finish)) || (!sd->manual))
1327           sd->state = sd->next_state;
1328         _configure(obj);
1329         _flip_show_hide(obj);
1330 
1331         if (sd->mode == ELM_FLIP_CROSS_FADE)
1332           {
1333              // Make the content fully opaque again
1334              evas_object_color_set(sd->front.clip, 255, 255, 255, 255);
1335              evas_object_color_set(sd->back.clip, 255, 255, 255, 255);
1336           }
1337 
1338         efl_event_callback_legacy_call(obj, EFL_UI_FLIP_EVENT_ANIMATE_DONE, NULL);
1339 
1340         // update the new front and back object.
1341         _update_front_back(obj, sd);
1342 
1343         return ECORE_CALLBACK_CANCEL;
1344      }
1345 
1346    return ECORE_CALLBACK_RENEW;
1347 }
1348 
1349 /* we have to have move/resize info up-to-date on those events. it
1350  * happens that smarts callbacks on them happen before we have the new
1351  * values, so using event callbacks instead */
1352 static void
_on_move(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1353 _on_move(void *data EINA_UNUSED,
1354          Evas *e EINA_UNUSED,
1355          Evas_Object *obj,
1356          void *event_info EINA_UNUSED)
1357 {
1358    _configure(obj);
1359 }
1360 
1361 static void
_on_resize(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1362 _on_resize(void *data EINA_UNUSED,
1363            Evas *e EINA_UNUSED,
1364            Evas_Object *obj,
1365            void *event_info EINA_UNUSED)
1366 {
1367    _configure(obj);
1368 }
1369 
1370 static Eina_Bool
_animate(void * data)1371 _animate(void *data)
1372 {
1373    return _flip(data);
1374 }
1375 
1376 static double
_pos_get(Evas_Object * obj,Efl_Ui_Flip_Data * sd,int * rev,Elm_Flip_Mode * m)1377 _pos_get(Evas_Object *obj,
1378          Efl_Ui_Flip_Data *sd,
1379          int *rev,
1380          Elm_Flip_Mode *m)
1381 {
1382    Evas_Coord x, y, w, h;
1383    double t = 1.0;
1384 
1385    evas_object_geometry_get(obj, &x, &y, &w, &h);
1386    switch (sd->intmode)
1387      {
1388       case EFL_UI_FLIP_INTERACTION_ROTATE:
1389       case EFL_UI_FLIP_INTERACTION_CUBE:
1390       {
1391          if (sd->dir == ELM_FLIP_DIRECTION_LEFT)
1392            {
1393               if (sd->down_x > 0)
1394                 t = 1.0 - ((double)sd->x / (double)sd->down_x);
1395               *rev = 1;
1396            }
1397          else if (sd->dir == ELM_FLIP_DIRECTION_RIGHT)
1398            {
1399               if (sd->down_x < w)
1400                 t = 1.0 - ((double)(w - sd->x) / (double)(w - sd->down_x));
1401            }
1402          else if (sd->dir == ELM_FLIP_DIRECTION_UP)
1403            {
1404               if (sd->down_y > 0)
1405                 t = 1.0 - ((double)sd->y / (double)sd->down_y);
1406            }
1407          else if (sd->dir == ELM_FLIP_DIRECTION_DOWN)
1408            {
1409               if (sd->down_y < h)
1410                 t = 1.0 - ((double)(h - sd->y) / (double)(h - sd->down_y));
1411               *rev = 1;
1412            }
1413 
1414          if (t < 0.0) t = 0.0;
1415          else if (t > 1.0)
1416            t = 1.0;
1417 
1418          if ((sd->dir == ELM_FLIP_DIRECTION_LEFT) ||
1419              (sd->dir == ELM_FLIP_DIRECTION_RIGHT))
1420            {
1421               if (sd->intmode == EFL_UI_FLIP_INTERACTION_ROTATE)
1422                 *m = ELM_FLIP_ROTATE_Y_CENTER_AXIS;
1423               else if (sd->intmode == EFL_UI_FLIP_INTERACTION_CUBE)
1424                 {
1425                    if (*rev)
1426                      *m = ELM_FLIP_CUBE_LEFT;
1427                    else
1428                      *m = ELM_FLIP_CUBE_RIGHT;
1429                 }
1430            }
1431          else
1432            {
1433               if (sd->intmode == EFL_UI_FLIP_INTERACTION_ROTATE)
1434                 *m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1435               else if (sd->intmode == EFL_UI_FLIP_INTERACTION_CUBE)
1436                 {
1437                    if (*rev)
1438                      *m = ELM_FLIP_CUBE_UP;
1439                    else
1440                      *m = ELM_FLIP_CUBE_DOWN;
1441                 }
1442            }
1443       }
1444 
1445       default:
1446         break;
1447      }
1448    return t;
1449 }
1450 
1451 static Eina_Bool
_event_anim(void * data,double pos)1452 _event_anim(void *data,
1453             double pos)
1454 {
1455    Efl_Ui_Flip_Data *sd = data;
1456    double p;
1457 
1458    p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
1459    if (sd->finish)
1460      {
1461         if (sd->dir == ELM_FLIP_DIRECTION_LEFT)
1462           sd->x = sd->ox * (1.0 - p);
1463         else if (sd->dir == ELM_FLIP_DIRECTION_RIGHT)
1464           sd->x = sd->ox + ((sd->w - sd->ox) * p);
1465         else if (sd->dir == ELM_FLIP_DIRECTION_UP)
1466           sd->y = sd->oy * (1.0 - p);
1467         else if (sd->dir == ELM_FLIP_DIRECTION_DOWN)
1468           sd->y = sd->oy + ((sd->h - sd->oy) * p);
1469      }
1470    else
1471      {
1472         if (sd->dir == ELM_FLIP_DIRECTION_LEFT)
1473           sd->x = sd->ox + ((sd->w - sd->ox) * p);
1474         else if (sd->dir == ELM_FLIP_DIRECTION_RIGHT)
1475           sd->x = sd->ox * (1.0 - p);
1476         else if (sd->dir == ELM_FLIP_DIRECTION_UP)
1477           sd->y = sd->oy + ((sd->h - sd->oy) * p);
1478         else if (sd->dir == ELM_FLIP_DIRECTION_DOWN)
1479           sd->y = sd->oy * (1.0 - p);
1480      }
1481    switch (sd->intmode)
1482      {
1483       case EFL_UI_FLIP_INTERACTION_NONE:
1484         break;
1485 
1486       case EFL_UI_FLIP_INTERACTION_ROTATE:
1487       case EFL_UI_FLIP_INTERACTION_CUBE:
1488           {
1489              Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1490              int rev = 0;
1491              p = _pos_get(sd->obj, sd, &rev, &m);
1492              _flip_do(sd->obj, p, m, 1, rev);
1493           }
1494         break;
1495 
1496       case EFL_UI_FLIP_INTERACTION_PAGE:
1497         sd->pageflip = EINA_TRUE;
1498         _configure(sd->obj);
1499         _state_update(sd->obj);
1500         break;
1501 
1502       default:
1503         break;
1504      }
1505    if (pos < 1.0) return ECORE_CALLBACK_RENEW;
1506 
1507    sd->pageflip = EINA_FALSE;
1508    _state_end(sd);
1509    evas_object_map_enable_set(sd->front.content, EINA_FALSE);
1510    evas_object_map_enable_set(sd->back.content, EINA_FALSE);
1511    // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1512    evas_object_resize(sd->front.content, 0, 0);
1513    evas_object_resize(sd->back.content, 0, 0);
1514    evas_smart_objects_calculate
1515      (evas_object_evas_get(sd->obj));
1516    // FIXME: end hack
1517    sd->animator = NULL;
1518    if (sd->finish) sd->state = sd->next_state;
1519    _flip_show_hide(sd->obj);
1520    _configure(sd->obj);
1521    sd->animator = NULL;
1522    efl_event_callback_legacy_call
1523      (sd->obj, EFL_UI_FLIP_EVENT_ANIMATE_DONE, NULL);
1524 
1525    return ECORE_CALLBACK_CANCEL;
1526 }
1527 
1528 static void
_update_job(void * data)1529 _update_job(void *data)
1530 {
1531    Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1532    Evas_Object *obj = data;
1533    Efl_Ui_Flip_Data *sd = efl_data_scope_get(obj, MY_CLASS);
1534    int rev = 0;
1535    double p;
1536 
1537    sd->job = NULL;
1538    switch (sd->intmode)
1539      {
1540       case EFL_UI_FLIP_INTERACTION_ROTATE:
1541       case EFL_UI_FLIP_INTERACTION_CUBE:
1542         p = _pos_get(obj, sd, &rev, &m);
1543         _flip_do(obj, p, m, 1, rev);
1544         break;
1545 
1546       case EFL_UI_FLIP_INTERACTION_PAGE:
1547         sd->pageflip = EINA_TRUE;
1548         _configure(obj);
1549         _state_update(obj);
1550         break;
1551 
1552       default:
1553         break;
1554      }
1555 }
1556 
1557 static void
_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1558 _down_cb(void *data,
1559          Evas *e EINA_UNUSED,
1560          Evas_Object *obj EINA_UNUSED,
1561          void *event_info)
1562 {
1563    Evas_Event_Mouse_Down *ev = event_info;
1564    Evas_Object *fl = data;
1565    Evas_Coord x, y, w, h;
1566 
1567    EFL_UI_FLIP_DATA_GET(fl, sd);
1568 
1569    if (ev->button != 1) return;
1570    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1571    ELM_SAFE_FREE(sd->animator, ecore_animator_del);
1572    sd->mouse_down = EINA_TRUE;
1573    sd->started = EINA_FALSE;
1574    evas_object_geometry_get(data, &x, &y, &w, &h);
1575    sd->x = ev->canvas.x - x;
1576    sd->y = ev->canvas.y - y;
1577    sd->w = w;
1578    sd->h = h;
1579    sd->down_x = sd->x;
1580    sd->down_y = sd->y;
1581 }
1582 
1583 static void
_up_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1584 _up_cb(void *data,
1585        Evas *e EINA_UNUSED,
1586        Evas_Object *obj EINA_UNUSED,
1587        void *event_info)
1588 {
1589    Evas_Event_Mouse_Up *ev = event_info;
1590    Evas_Object *fl = data;
1591    Evas_Coord x, y, w, h;
1592    double tm = 0.5;
1593 
1594    EFL_UI_FLIP_DATA_GET(fl, sd);
1595 
1596    if (ev->button != 1) return;
1597    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1598    sd->mouse_down = EINA_FALSE;
1599    if (!sd->started) return;
1600    evas_object_geometry_get(data, &x, &y, &w, &h);
1601    sd->x = ev->canvas.x - x;
1602    sd->y = ev->canvas.y - y;
1603    sd->w = w;
1604    sd->h = h;
1605    sd->ox = sd->x;
1606    sd->oy = sd->y;
1607    ELM_SAFE_FREE(sd->job, ecore_job_del);
1608    sd->finish = EINA_FALSE;
1609    if (sd->dir == ELM_FLIP_DIRECTION_LEFT)
1610      {
1611         tm = (double)sd->x / (double)sd->w;
1612         if (sd->x < (sd->w / 2)) sd->finish = EINA_TRUE;
1613      }
1614    else if (sd->dir == ELM_FLIP_DIRECTION_RIGHT)
1615      {
1616         if (sd->x > (sd->w / 2)) sd->finish = EINA_TRUE;
1617         tm = 1.0 - ((double)sd->x / (double)sd->w);
1618      }
1619    else if (sd->dir == ELM_FLIP_DIRECTION_UP)
1620      {
1621         if (sd->y < (sd->h / 2)) sd->finish = EINA_TRUE;
1622         tm = (double)sd->y / (double)sd->h;
1623      }
1624    else if (sd->dir == ELM_FLIP_DIRECTION_DOWN)
1625      {
1626         if (sd->y > (sd->h / 2)) sd->finish = EINA_TRUE;
1627         tm = 1.0 - ((double)sd->y / (double)sd->h);
1628      }
1629    if (tm < 0.01) tm = 0.01;
1630    else if (tm > 0.99) tm = 0.99;
1631    if (!sd->finish) tm = 1.0 - tm;
1632    else sd->next_state = !sd->state;
1633    tm *= 1.0; // FIXME: config for anim time
1634    ecore_animator_del(sd->animator);
1635    sd->animator = ecore_evas_animator_timeline_add(fl, tm, _event_anim, sd);
1636    sd->len = tm;
1637    sd->start = ecore_loop_time_get();
1638    sd->manual = EINA_TRUE;
1639    _event_anim(sd, 0.0);
1640 }
1641 
1642 static void
_move_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1643 _move_cb(void *data,
1644          Evas *e EINA_UNUSED,
1645          Evas_Object *obj EINA_UNUSED,
1646          void *event_info)
1647 {
1648    Evas_Event_Mouse_Move *ev = event_info;
1649    Evas_Object *fl = data;
1650    Evas_Coord x, y, w, h;
1651 
1652    EFL_UI_FLIP_DATA_GET(fl, sd);
1653    if (!sd->mouse_down) return;
1654    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1655    evas_object_geometry_get(data, &x, &y, &w, &h);
1656    sd->x = ev->cur.canvas.x - x;
1657    sd->y = ev->cur.canvas.y - y;
1658    sd->w = w;
1659    sd->h = h;
1660    if (!sd->started)
1661      {
1662         Evas_Coord dx, dy;
1663 
1664         dx = sd->x - sd->down_x;
1665         dy = sd->y - sd->down_y;
1666         if (((dx * dx) + (dy * dy)) >
1667             (_elm_config->finger_size * _elm_config->finger_size / 4))
1668           {
1669              if ((sd->x > (w / 2)) &&
1670                  (dx < 0) && (abs(dx) > abs(dy)))
1671                {
1672                   sd->dir = ELM_FLIP_DIRECTION_LEFT;
1673                   if (!sd->dir_enabled[ELM_FLIP_DIRECTION_LEFT]) return;
1674                }
1675              else if ((sd->x < (w / 2)) && (dx >= 0) &&
1676                       (abs(dx) > abs(dy)))
1677                {
1678                   sd->dir = ELM_FLIP_DIRECTION_RIGHT;
1679                   if (!sd->dir_enabled[ELM_FLIP_DIRECTION_RIGHT]) return;
1680                }
1681              else if ((sd->y > (h / 2)) && (dy < 0) && (abs(dy) >= abs(dx)))
1682                {
1683                   sd->dir = ELM_FLIP_DIRECTION_UP;
1684                   if (!sd->dir_enabled[ELM_FLIP_DIRECTION_UP]) return;
1685                }
1686              else if ((sd->y < (h / 2)) && (dy >= 0) && (abs(dy) >= abs(dx)))
1687                {
1688                   sd->dir = ELM_FLIP_DIRECTION_DOWN;
1689                   if (!sd->dir_enabled[ELM_FLIP_DIRECTION_DOWN]) return;
1690                }
1691              else return;
1692 
1693              sd->started = EINA_TRUE;
1694              if (sd->intmode == EFL_UI_FLIP_INTERACTION_PAGE)
1695                sd->pageflip = EINA_TRUE;
1696              _flip_show_hide(data);
1697              evas_smart_objects_calculate(evas_object_evas_get(data));
1698              _flip(data);
1699              // FIXME: hack around evas rendering bug (only fix makes
1700              // evas bitch-slow)
1701              evas_object_map_enable_set(sd->front.content, EINA_FALSE);
1702              evas_object_map_enable_set(sd->back.content, EINA_FALSE);
1703 // FIXME: XXX why does this bork interactive flip??
1704 //             evas_object_resize(sd->front.content, 0, 0);
1705 //             evas_object_resize(sd->back.content, 0, 0);
1706              evas_smart_objects_calculate(evas_object_evas_get(data));
1707              _configure(fl);
1708              // FIXME: end hack
1709              efl_event_callback_legacy_call(fl, EFL_UI_FLIP_EVENT_ANIMATE_BEGIN, NULL);
1710           }
1711         else return;
1712      }
1713 
1714    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1715    ecore_job_del(sd->job);
1716    sd->job = ecore_job_add(_update_job, fl);
1717 }
1718 
1719 static Eina_Bool
_flip_content_set(Evas_Object * obj,Evas_Object * content,Eina_Bool front)1720 _flip_content_set(Evas_Object *obj,
1721                   Evas_Object *content,
1722                   Eina_Bool front)
1723 {
1724    int i;
1725    Evas_Object **cont;
1726 
1727    EFL_UI_FLIP_DATA_GET(obj, sd);
1728 
1729    cont = front ? &(sd->front.content) : &(sd->back.content);
1730 
1731    if (*cont == content) return EINA_TRUE;
1732 
1733    evas_object_del(*cont);
1734    *cont = content;
1735 
1736    if (content)
1737      {
1738         elm_widget_sub_object_add(obj, content);
1739         //evas_object_smart_member_add(content, obj);
1740         evas_object_clip_set
1741           (content, front ? sd->front.clip : sd->back.clip);
1742         if (efl_isa(content, EFL_UI_WIDGET_CLASS) && sd->state != front)
1743           elm_widget_tree_unfocusable_set(content, EINA_TRUE);
1744      }
1745 
1746    // force calc to contents are the right size before transition
1747    evas_smart_objects_calculate(evas_object_evas_get(obj));
1748    //evas_object_smart_calculate(obj);
1749    _flip_show_hide(obj);
1750    _configure(obj);
1751    _sizing_eval(obj);
1752 
1753    if (sd->intmode != EFL_UI_FLIP_INTERACTION_NONE)
1754      {
1755         for (i = 0; i < 4; i++)
1756           evas_object_raise(sd->event[i]);
1757      }
1758 
1759    return EINA_TRUE;
1760 }
1761 
1762 static Evas_Object *
_flip_content_unset(Evas_Object * obj,Eina_Bool front)1763 _flip_content_unset(Evas_Object *obj,
1764                     Eina_Bool front)
1765 {
1766    Evas_Object *content;
1767    Evas_Object **cont;
1768 
1769    EFL_UI_FLIP_DATA_GET(obj, sd);
1770 
1771    cont = front ? &(sd->front.content) : &(sd->back.content);
1772 
1773    if (!*cont) return NULL;
1774 
1775    content = *cont;
1776    _elm_widget_sub_object_redirect_to_top(obj, content);
1777 
1778    return content;
1779 }
1780 
1781 static Eina_Bool
_efl_ui_flip_content_set(Eo * obj,Efl_Ui_Flip_Data * _pd EINA_UNUSED,const char * part,Evas_Object * content)1782 _efl_ui_flip_content_set(Eo *obj, Efl_Ui_Flip_Data *_pd EINA_UNUSED, const char *part, Evas_Object *content)
1783 {
1784    if (!part || !strcmp(part, "front"))
1785       return _flip_content_set(obj, content, EINA_TRUE);
1786    else if (!strcmp(part, "back"))
1787       return _flip_content_set(obj, content, EINA_FALSE);
1788    return EINA_FALSE;
1789 }
1790 
1791 static Evas_Object*
_efl_ui_flip_content_get(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * sd,const char * part)1792 _efl_ui_flip_content_get(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *sd, const char *part)
1793 {
1794    if (!part || !strcmp(part, "front"))
1795       return sd->front.content;
1796    else if (!strcmp(part, "back"))
1797       return sd->back.content;
1798    return NULL;
1799 }
1800 
1801 static Evas_Object*
_efl_ui_flip_content_unset(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * _pd EINA_UNUSED,const char * part)1802 _efl_ui_flip_content_unset(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *_pd EINA_UNUSED, const char *part)
1803 {
1804    if (!part || !strcmp(part, "front"))
1805       return _flip_content_unset(obj, EINA_TRUE);
1806    else if (!strcmp(part, "back"))
1807       return _flip_content_unset(obj, EINA_FALSE);
1808    return NULL;
1809 }
1810 
1811 EOLIAN static void
_efl_ui_flip_efl_canvas_group_group_add(Eo * obj,Efl_Ui_Flip_Data * priv)1812 _efl_ui_flip_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Flip_Data *priv)
1813 {
1814    efl_canvas_group_add(efl_super(obj, MY_CLASS));
1815 
1816    priv->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
1817    evas_object_static_clip_set(priv->clip, EINA_TRUE);
1818    evas_object_geometry_set(priv->clip, -49999, -49999, 99999, 99999);
1819    evas_object_smart_member_add(priv->clip, obj);
1820 
1821    priv->front.clip = evas_object_rectangle_add(evas_object_evas_get(obj));
1822    evas_object_static_clip_set(priv->front.clip, EINA_TRUE);
1823    evas_object_data_set(priv->front.clip, "_elm_leaveme", obj);
1824    evas_object_geometry_set(priv->front.clip, -49999, -49999, 99999, 99999);
1825    evas_object_smart_member_add(priv->front.clip, obj);
1826    evas_object_clip_set(priv->front.clip, priv->clip);
1827 
1828    priv->back.clip = evas_object_rectangle_add(evas_object_evas_get(obj));
1829    evas_object_static_clip_set(priv->back.clip, EINA_TRUE);
1830    evas_object_data_set(priv->back.clip, "_elm_leaveme", obj);
1831    evas_object_geometry_set(priv->back.clip, -49999, -49999, 99999, 99999);
1832    evas_object_smart_member_add(priv->back.clip, obj);
1833    evas_object_clip_set(priv->back.clip, priv->clip);
1834 
1835    evas_object_event_callback_add
1836      (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb, obj);
1837 
1838    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _on_resize, NULL);
1839    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1840 
1841    priv->state = EINA_TRUE;
1842    priv->next_state = EINA_TRUE;
1843    priv->intmode = EFL_UI_FLIP_INTERACTION_NONE;
1844 
1845    elm_widget_can_focus_set(obj, EINA_FALSE);
1846 }
1847 
1848 EOLIAN static void
_efl_ui_flip_efl_canvas_group_group_del(Eo * obj,Efl_Ui_Flip_Data * sd)1849 _efl_ui_flip_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Flip_Data *sd)
1850 {
1851    ecore_animator_del(sd->animator);
1852    _state_slices_clear(sd);
1853 
1854    efl_canvas_group_del(efl_super(obj, MY_CLASS));
1855 }
1856 
1857 EOLIAN static Eo *
_efl_ui_flip_efl_object_constructor(Eo * obj,Efl_Ui_Flip_Data * sd)1858 _efl_ui_flip_efl_object_constructor(Eo *obj, Efl_Ui_Flip_Data *sd)
1859 {
1860    obj = efl_constructor(efl_super(obj, MY_CLASS));
1861    sd->obj = obj;
1862 
1863    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
1864    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PAGE_TAB_LIST);
1865 
1866    return obj;
1867 }
1868 
1869 EOLIAN static Eina_Bool
_efl_ui_flip_front_visible_get(const Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * sd)1870 _efl_ui_flip_front_visible_get(const Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *sd)
1871 {
1872    return sd->state;
1873 }
1874 
1875 EAPI void
elm_flip_perspective_set(Evas_Object * obj,Evas_Coord foc EINA_UNUSED,Evas_Coord x EINA_UNUSED,Evas_Coord y EINA_UNUSED)1876 elm_flip_perspective_set(Evas_Object *obj,
1877                          Evas_Coord foc EINA_UNUSED,
1878                          Evas_Coord x EINA_UNUSED,
1879                          Evas_Coord y EINA_UNUSED)
1880 {
1881    EFL_UI_FLIP_CHECK(obj);
1882 }
1883 
1884 // FIXME: add ambient and lighting control
1885 
1886 static void
_internal_elm_flip_go_to(Evas_Object * obj,Efl_Ui_Flip_Data * sd,Eina_Bool front,Elm_Flip_Mode mode)1887 _internal_elm_flip_go_to(Evas_Object *obj,
1888                 Efl_Ui_Flip_Data *sd,
1889                 Eina_Bool front,
1890                 Elm_Flip_Mode mode)
1891 {
1892    if (!sd->animator) sd->animator = ecore_evas_animator_add(obj, _animate, obj);
1893 
1894    sd->mode = mode;
1895    sd->start = ecore_loop_time_get();
1896    sd->next_state = front;
1897    sd->len = 0.5; // FIXME: make config val
1898    sd->manual = EINA_FALSE;
1899    if ((sd->mode == ELM_FLIP_PAGE_LEFT) ||
1900        (sd->mode == ELM_FLIP_PAGE_RIGHT) ||
1901        (sd->mode == ELM_FLIP_PAGE_UP) ||
1902        (sd->mode == ELM_FLIP_PAGE_DOWN))
1903      sd->pageflip = EINA_TRUE;
1904    // force calc to contents are the right size before transition
1905    evas_smart_objects_calculate(evas_object_evas_get(obj));
1906 
1907    if (sd->mode == ELM_FLIP_CROSS_FADE)
1908      {
1909         // Convention: a is fading in, b is fading out
1910         Evas_Object *a, *b;
1911         if (front)
1912           {
1913              a = sd->front.content;
1914              b = sd->back.content;
1915           }
1916         else
1917           {
1918              a = sd->back.content;
1919              b = sd->front.content;
1920           }
1921 
1922         // Stack fade-in content on top of fade-out content
1923         if (a && b) evas_object_stack_above(a, b);
1924 
1925         evas_object_show(sd->front.clip);
1926         evas_object_show(sd->back.clip);
1927      }
1928    else
1929      {
1930         _flip_show_hide(obj);
1931      }
1932 
1933    _flip(obj);
1934    // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1935    evas_object_map_enable_set(sd->front.content, EINA_FALSE);
1936    evas_object_map_enable_set(sd->back.content, EINA_FALSE);
1937    evas_object_resize(sd->front.content, 0, 0);
1938    evas_object_resize(sd->back.content, 0, 0);
1939    evas_smart_objects_calculate(evas_object_evas_get(obj));
1940    _configure(obj);
1941    // FIXME: end hack
1942 
1943    efl_event_callback_legacy_call(obj, EFL_UI_FLIP_EVENT_ANIMATE_BEGIN, NULL);
1944 
1945    // set focus to the content object when flip go to is called
1946    if (elm_object_focus_get(obj))
1947      {
1948         if (front) elm_object_focus_set(sd->front.content, EINA_TRUE);
1949         else elm_object_focus_set(sd->back.content, EINA_TRUE);
1950      }
1951 
1952    if (sd->front.content && efl_isa(sd->front.content, EFL_UI_WIDGET_CLASS))
1953      elm_widget_tree_unfocusable_set(sd->front.content, !front);
1954    if (sd->back.content && efl_isa(sd->back.content, EFL_UI_WIDGET_CLASS))
1955      elm_widget_tree_unfocusable_set(sd->back.content, front);
1956 
1957 
1958 }
1959 
1960 EOLIAN static void
_efl_ui_flip_go_to(Eo * obj,Efl_Ui_Flip_Data * sd,Eina_Bool front,Efl_Ui_Flip_Mode mode)1961 _efl_ui_flip_go_to(Eo *obj, Efl_Ui_Flip_Data *sd, Eina_Bool front, Efl_Ui_Flip_Mode mode)
1962 {
1963    if (sd->next_state == front) return;
1964 
1965    _internal_elm_flip_go_to(obj, sd, front, (Elm_Flip_Mode)mode);
1966 }
1967 
1968 EOLIAN static void
_efl_ui_flip_go(Eo * obj,Efl_Ui_Flip_Data * sd,Efl_Ui_Flip_Mode mode)1969 _efl_ui_flip_go(Eo *obj, Efl_Ui_Flip_Data *sd, Efl_Ui_Flip_Mode mode)
1970 {
1971    _internal_elm_flip_go_to(obj, sd, !sd->state, (Elm_Flip_Mode)mode);
1972 }
1973 
1974 static void
_event_rect_create(Eo * obj,Efl_Ui_Flip_Data * sd,int i)1975 _event_rect_create(Eo *obj, Efl_Ui_Flip_Data *sd, int i)
1976 {
1977    Evas_Object *clip;
1978    Evas *e;
1979 
1980    if (sd->event[i]) return;
1981 
1982    e = evas_object_evas_get(obj);
1983    sd->event[i] = evas_object_rectangle_add(e);
1984 
1985    clip = evas_object_clip_get(obj);
1986    evas_object_data_set(sd->event[i], "_elm_leaveme", obj);
1987    evas_object_clip_set(sd->event[i], clip);
1988    evas_object_color_set(sd->event[i], 0, 0, 0, 0);
1989    evas_object_show(sd->event[i]);
1990    evas_object_smart_member_add(sd->event[i], obj);
1991    evas_object_event_callback_add
1992      (sd->event[i], EVAS_CALLBACK_MOUSE_DOWN, _down_cb, obj);
1993    evas_object_event_callback_add
1994      (sd->event[i], EVAS_CALLBACK_MOUSE_UP, _up_cb, obj);
1995    evas_object_event_callback_add
1996      (sd->event[i], EVAS_CALLBACK_MOUSE_MOVE, _move_cb, obj);
1997 }
1998 
1999 EOLIAN static void
_efl_ui_flip_interaction_set(Eo * obj,Efl_Ui_Flip_Data * sd,Efl_Ui_Flip_Interaction mode)2000 _efl_ui_flip_interaction_set(Eo *obj, Efl_Ui_Flip_Data *sd, Efl_Ui_Flip_Interaction mode)
2001 {
2002    int i;
2003 
2004 
2005    if (sd->intmode == mode) return;
2006    sd->intmode = mode;
2007 
2008    for (i = 0; i < 4; i++)
2009      {
2010         if (sd->intmode == EFL_UI_FLIP_INTERACTION_NONE)
2011           ELM_SAFE_FREE(sd->event[i], evas_object_del);
2012         else if (sd->dir_enabled[i])
2013           {
2014              int area = (i & 0x2) | (i ^ 0x1);
2015              if (sd->dir_hitsize[area] >= 0.0)
2016                _event_rect_create(obj, sd, area);
2017           }
2018      }
2019 
2020    _sizing_eval(obj);
2021    _configure(obj);
2022 }
2023 
2024 EOLIAN static Efl_Ui_Flip_Interaction
_efl_ui_flip_interaction_get(const Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * sd)2025 _efl_ui_flip_interaction_get(const Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *sd)
2026 {
2027    return sd->intmode;
2028 }
2029 
2030 static Efl_Ui_Layout_Orientation
_flip_dir_to_efl_ui_dir(Elm_Flip_Direction dir)2031 _flip_dir_to_efl_ui_dir(Elm_Flip_Direction dir)
2032 {
2033    switch (dir)
2034      {
2035       case ELM_FLIP_DIRECTION_RIGHT: return EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL;
2036       case ELM_FLIP_DIRECTION_DOWN: return EFL_UI_LAYOUT_ORIENTATION_VERTICAL | EFL_UI_LAYOUT_ORIENTATION_INVERTED;
2037       case ELM_FLIP_DIRECTION_LEFT: return EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL | EFL_UI_LAYOUT_ORIENTATION_INVERTED;
2038       case ELM_FLIP_DIRECTION_UP: return EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
2039      }
2040    ERR("Invalid value for Elm_Flip_Direction: %d", (int) dir);
2041    return EFL_UI_LAYOUT_ORIENTATION_DEFAULT;
2042 }
2043 
2044 static Elm_Flip_Direction
_efl_ui_dir_to_flip_dir(Efl_Ui_Layout_Orientation dir)2045 _efl_ui_dir_to_flip_dir(Efl_Ui_Layout_Orientation dir)
2046 {
2047    switch ((int)dir) // The cast silences warnings about missing enum values and non-existing case labels
2048      {
2049       case EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL:
2050         return ELM_FLIP_DIRECTION_RIGHT;
2051       case EFL_UI_LAYOUT_ORIENTATION_VERTICAL | EFL_UI_LAYOUT_ORIENTATION_INVERTED:
2052         return ELM_FLIP_DIRECTION_DOWN;
2053       case EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL | EFL_UI_LAYOUT_ORIENTATION_INVERTED:
2054         return ELM_FLIP_DIRECTION_LEFT;
2055       case EFL_UI_LAYOUT_ORIENTATION_VERTICAL:
2056       case EFL_UI_LAYOUT_ORIENTATION_DEFAULT:
2057         return ELM_FLIP_DIRECTION_UP;
2058      }
2059    ERR("Invalid value for Efl_Ui_Layout_Orientation: %d", (int) dir);
2060    return ELM_FLIP_DIRECTION_UP;
2061 }
2062 
2063 EOLIAN static void
_efl_ui_flip_interaction_direction_enabled_set(Eo * obj,Efl_Ui_Flip_Data * sd,Efl_Ui_Layout_Orientation dir,Eina_Bool enabled)2064 _efl_ui_flip_interaction_direction_enabled_set(Eo *obj, Efl_Ui_Flip_Data *sd, Efl_Ui_Layout_Orientation dir, Eina_Bool enabled)
2065 {
2066    int i = _efl_ui_dir_to_flip_dir(dir);
2067    int area;
2068 
2069    enabled = !!enabled;
2070    if (sd->dir_enabled[i] == enabled) return;
2071    sd->dir_enabled[i] = enabled;
2072    if (sd->intmode == EFL_UI_FLIP_INTERACTION_NONE) return;
2073 
2074    area = (i & 0x2) | (i ^ 0x1); // up <-> down, left <-> right
2075    if (enabled && (sd->dir_hitsize[area] >= 0.0))
2076      _event_rect_create(obj, sd, area);
2077    else if (!enabled && (sd->dir_hitsize[area] <= 0.0))
2078      // Delete this hit area as it has the default hitsize (0)
2079      ELM_SAFE_FREE(sd->event[area], evas_object_del);
2080 
2081    _sizing_eval(obj);
2082    _configure(obj);
2083 }
2084 
2085 EOLIAN static Eina_Bool
_efl_ui_flip_interaction_direction_enabled_get(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * sd,Efl_Ui_Layout_Orientation dir)2086 _efl_ui_flip_interaction_direction_enabled_get(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *sd, Efl_Ui_Layout_Orientation dir)
2087 {
2088    return sd->dir_enabled[_efl_ui_dir_to_flip_dir(dir)];
2089 }
2090 
2091 EOLIAN static void
_efl_ui_flip_interaction_direction_hitsize_set(Eo * obj,Efl_Ui_Flip_Data * sd,Efl_Ui_Layout_Orientation dir,double hitsize)2092 _efl_ui_flip_interaction_direction_hitsize_set(Eo *obj, Efl_Ui_Flip_Data *sd, Efl_Ui_Layout_Orientation dir, double hitsize)
2093 {
2094    int i = _efl_ui_dir_to_flip_dir(dir);
2095 
2096 
2097    if (hitsize < 0.0)
2098      hitsize = -1.0;
2099    else if (hitsize > 1.0)
2100      hitsize = 1.0;
2101 
2102    if (EINA_DBL_EQ(sd->dir_hitsize[i], hitsize)) return;
2103    sd->dir_hitsize[i] = hitsize;
2104 
2105    if (hitsize >= 0.0)
2106      _event_rect_create(obj, sd, i);
2107    else
2108      ELM_SAFE_FREE(sd->event[i], evas_object_del);
2109 
2110    _sizing_eval(obj);
2111    _configure(obj);
2112 }
2113 
2114 static void
_update_front_back(Eo * obj,Efl_Ui_Flip_Data * pd)2115 _update_front_back(Eo *obj, Efl_Ui_Flip_Data *pd)
2116 {
2117    int count, index;
2118    Efl_Gfx_Entity *content;
2119 
2120    count = eina_list_count(pd->content_list);
2121    if (count <= 2) return;
2122 
2123    // update the next state object
2124    content = _flip_content_unset(obj, !pd->state);
2125    evas_object_hide(content);
2126    content = pd->state ? pd->front.content : pd->back.content;
2127    index = eina_list_data_idx(pd->content_list, content);
2128    index = (index == count-1) ? 0 : index + 1;
2129    content = eina_list_nth(pd->content_list, index);
2130    evas_object_show(content);
2131    _flip_content_set(obj, content, !pd->state);
2132 }
2133 
2134 static void
_content_added(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * content)2135 _content_added(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *content)
2136 {
2137    elm_widget_sub_object_add(obj, content);
2138 
2139    if (!pd->front.content)
2140      {
2141         _flip_content_set(obj, content, EINA_TRUE);
2142         return;
2143      }
2144    if (!pd->back.content)
2145      {
2146         _flip_content_set(obj, content, EINA_FALSE);
2147         return;
2148      }
2149 }
2150 
2151 static void
_content_removed(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * content)2152 _content_removed(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *content)
2153 {
2154    Efl_Gfx_Entity *back_face, *cur_face, *face;
2155    int index, count;
2156    Eina_Bool state;
2157 
2158    elm_widget_sub_object_del(obj, content);
2159    // if its not the front or back object just return.
2160    if ((pd->front.content != content) ||
2161        (pd->back.content != content))
2162      return;
2163 
2164    cur_face = pd->state ? pd->front.content : pd->back.content;
2165    back_face = pd->state ? pd->back.content : pd->front.content;
2166 
2167    if (cur_face == content)
2168      {
2169         face = back_face;
2170         state = EINA_TRUE;
2171      }
2172    else
2173      {
2174         face = cur_face;
2175         state = EINA_FALSE;
2176      }
2177 
2178    _flip_content_unset(obj, state);
2179 
2180    count = eina_list_count(pd->content_list);
2181    if (count == 1) return;
2182 
2183    _flip_content_unset(obj, state);
2184    index = eina_list_data_idx(pd->content_list, face);
2185    index = (index == count-1) ? 0 : index + 1;
2186    _flip_content_set(obj, eina_list_nth(pd->content_list, index), state);
2187 }
2188 
2189 EOLIAN static double
_efl_ui_flip_interaction_direction_hitsize_get(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * sd,Efl_Ui_Layout_Orientation dir)2190 _efl_ui_flip_interaction_direction_hitsize_get(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *sd, Efl_Ui_Layout_Orientation dir)
2191 {
2192    int i = _efl_ui_dir_to_flip_dir(dir);
2193 
2194    return sd->dir_hitsize[i];
2195 }
2196 
2197 EOLIAN static Eina_Iterator *
_efl_ui_flip_efl_container_content_iterate(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * pd)2198 _efl_ui_flip_efl_container_content_iterate(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *pd)
2199 {
2200    return eina_list_iterator_new(pd->content_list);
2201 }
2202 
2203 EOLIAN static int
_efl_ui_flip_efl_container_content_count(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * pd)2204 _efl_ui_flip_efl_container_content_count(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *pd)
2205 {
2206    return eina_list_count(pd->content_list);
2207 }
2208 
2209 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_unpack(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj)2210 _efl_ui_flip_efl_pack_unpack(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj)
2211 {
2212    pd->content_list = eina_list_remove(pd->content_list, subobj);
2213    pd->content_list = eina_list_remove(pd->content_list, subobj);
2214    _content_removed(obj, pd, subobj);
2215    return EINA_TRUE;
2216 }
2217 
2218 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_pack(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj)2219 _efl_ui_flip_efl_pack_pack(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj)
2220 {
2221    pd->content_list = eina_list_remove(pd->content_list, subobj);
2222    pd->content_list = eina_list_append(pd->content_list, subobj);
2223    _content_added(obj, pd, subobj);
2224    return EINA_TRUE;
2225 }
2226 
2227 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_linear_pack_begin(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj)2228 _efl_ui_flip_efl_pack_linear_pack_begin(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj)
2229 {
2230    pd->content_list = eina_list_remove(pd->content_list, subobj);
2231    pd->content_list = eina_list_prepend(pd->content_list, subobj);
2232    _content_added(obj, pd, subobj);
2233 
2234    return EINA_TRUE;
2235 }
2236 
2237 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_linear_pack_end(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj)2238 _efl_ui_flip_efl_pack_linear_pack_end(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj)
2239 {
2240    pd->content_list = eina_list_remove(pd->content_list, subobj);
2241    pd->content_list = eina_list_append(pd->content_list, subobj);
2242    _content_added(obj, pd, subobj);
2243    return EINA_TRUE;
2244 }
2245 
2246 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_linear_pack_before(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj,const Efl_Gfx_Entity * existing)2247 _efl_ui_flip_efl_pack_linear_pack_before(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj, const Efl_Gfx_Entity *existing)
2248 {
2249    pd->content_list = eina_list_remove(pd->content_list, subobj);
2250    pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
2251    _content_added(obj, pd, subobj);
2252    return EINA_TRUE;
2253 }
2254 
2255 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_linear_pack_after(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj,const Efl_Gfx_Entity * existing)2256 _efl_ui_flip_efl_pack_linear_pack_after(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj, const Efl_Gfx_Entity *existing)
2257 {
2258    pd->content_list = eina_list_remove(pd->content_list, subobj);
2259    pd->content_list = eina_list_append_relative(pd->content_list, subobj, existing);
2260    _content_added(obj, pd, subobj);
2261    return EINA_TRUE;
2262 }
2263 
2264 EOLIAN static Eina_Bool
_efl_ui_flip_efl_pack_linear_pack_at(Eo * obj,Efl_Ui_Flip_Data * pd,Efl_Gfx_Entity * subobj,int index)2265 _efl_ui_flip_efl_pack_linear_pack_at(Eo *obj, Efl_Ui_Flip_Data *pd, Efl_Gfx_Entity *subobj, int index)
2266 {
2267    Efl_Gfx_Entity *existing = NULL;
2268    existing = eina_list_nth(pd->content_list, index);
2269    pd->content_list = eina_list_remove(pd->content_list, subobj);
2270    pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
2271    _content_added(obj, pd, subobj);
2272    return EINA_TRUE;
2273 }
2274 
2275 EOLIAN static Efl_Gfx_Entity *
_efl_ui_flip_efl_pack_linear_pack_content_get(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * pd,int index)2276 _efl_ui_flip_efl_pack_linear_pack_content_get(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *pd, int index)
2277 {
2278    return eina_list_nth(pd->content_list, index);
2279 }
2280 
2281 EOLIAN static Efl_Gfx_Entity *
_efl_ui_flip_efl_pack_linear_pack_unpack_at(Eo * obj,Efl_Ui_Flip_Data * pd,int index)2282 _efl_ui_flip_efl_pack_linear_pack_unpack_at(Eo *obj, Efl_Ui_Flip_Data *pd, int index)
2283 {
2284    Efl_Gfx_Entity *content = eina_list_nth(pd->content_list ,index);
2285 
2286    pd->content_list = eina_list_remove(pd->content_list, content);
2287    _content_removed(obj, pd, content);
2288    return content;
2289 }
2290 
2291 EOLIAN static int
_efl_ui_flip_efl_pack_linear_pack_index_get(Eo * obj EINA_UNUSED,Efl_Ui_Flip_Data * pd,const Efl_Gfx_Entity * subobj)2292 _efl_ui_flip_efl_pack_linear_pack_index_get(Eo *obj EINA_UNUSED, Efl_Ui_Flip_Data *pd, const Efl_Gfx_Entity *subobj)
2293 {
2294    return eina_list_data_idx(pd->content_list, (void *)subobj);
2295 }
2296 
2297 EAPI void
elm_flip_interaction_direction_hitsize_set(Efl_Ui_Flip * obj,Elm_Flip_Direction dir,double hitsize)2298 elm_flip_interaction_direction_hitsize_set(Efl_Ui_Flip *obj, Elm_Flip_Direction dir, double hitsize)
2299 {
2300    Efl_Ui_Layout_Orientation uidir = _flip_dir_to_efl_ui_dir(dir);
2301    efl_ui_flip_interaction_direction_hitsize_set(obj, uidir, hitsize);
2302 }
2303 
2304 EAPI double
elm_flip_interaction_direction_hitsize_get(Efl_Ui_Flip * obj,Elm_Flip_Direction dir)2305 elm_flip_interaction_direction_hitsize_get(Efl_Ui_Flip *obj, Elm_Flip_Direction dir)
2306 {
2307    Efl_Ui_Layout_Orientation uidir = _flip_dir_to_efl_ui_dir(dir);
2308    return efl_ui_flip_interaction_direction_hitsize_get(obj, uidir);
2309 }
2310 
2311 EOAPI void
elm_flip_interaction_direction_enabled_set(Efl_Ui_Flip * obj,Elm_Flip_Direction dir,Eina_Bool enabled)2312 elm_flip_interaction_direction_enabled_set(Efl_Ui_Flip *obj, Elm_Flip_Direction dir, Eina_Bool enabled)
2313 {
2314    Efl_Ui_Layout_Orientation uidir = _flip_dir_to_efl_ui_dir(dir);
2315    efl_ui_flip_interaction_direction_enabled_set(obj, uidir, enabled);
2316 }
2317 
2318 EOAPI Eina_Bool
elm_flip_interaction_direction_enabled_get(Efl_Ui_Flip * obj,Elm_Flip_Direction dir)2319 elm_flip_interaction_direction_enabled_get(Efl_Ui_Flip *obj, Elm_Flip_Direction dir)
2320 {
2321    Efl_Ui_Layout_Orientation uidir = _flip_dir_to_efl_ui_dir(dir);
2322    return efl_ui_flip_interaction_direction_enabled_get(obj, uidir);
2323 }
2324 
2325 /* Efl.Part begin */
2326 
2327 static Eina_Bool
_part_is_efl_ui_flip_entry_part(const Eo * obj EINA_UNUSED,const char * part)2328 _part_is_efl_ui_flip_entry_part(const Eo *obj EINA_UNUSED, const char *part)
2329 {
2330    return ((eina_streq(part, "front")) || (eina_streq(part, "back")));
2331 }
2332 
ELM_PART_OVERRIDE_PARTIAL(efl_ui_flip,EFL_UI_FLIP,Efl_Ui_Flip_Data,_part_is_efl_ui_flip_entry_part)2333 ELM_PART_OVERRIDE_PARTIAL(efl_ui_flip, EFL_UI_FLIP, Efl_Ui_Flip_Data, _part_is_efl_ui_flip_entry_part)
2334 ELM_PART_OVERRIDE_CONTENT_SET(efl_ui_flip, EFL_UI_FLIP, Efl_Ui_Flip_Data)
2335 ELM_PART_OVERRIDE_CONTENT_GET(efl_ui_flip, EFL_UI_FLIP, Efl_Ui_Flip_Data)
2336 ELM_PART_OVERRIDE_CONTENT_UNSET(efl_ui_flip, EFL_UI_FLIP, Efl_Ui_Flip_Data)
2337 ELM_PART_CONTENT_DEFAULT_GET(efl_ui_flip, "front")
2338 #include "efl_ui_flip_part.eo.c"
2339 
2340 /* Efl.Part end */
2341 
2342 /* Internal EO APIs and hidden overrides */
2343 
2344 #define EFL_UI_FLIP_EXTRA_OPS \
2345    ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_flip), \
2346    EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_flip)
2347 
2348 #include "efl_ui_flip.eo.c"
2349 #include "efl_ui_flip_eo.legacy.c"
2350 
2351 #include "efl_ui_flip_legacy_eo.h"
2352 
2353 #define MY_CLASS_NAME_LEGACY "elm_flip"
2354 
2355 static void
2356 _efl_ui_flip_legacy_class_constructor(Efl_Class *klass)
2357 {
2358    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2359 }
2360 
2361 EOLIAN static Eo *
_efl_ui_flip_legacy_efl_object_constructor(Eo * obj,void * pd EINA_UNUSED)2362 _efl_ui_flip_legacy_efl_object_constructor(Eo *obj, void *pd EINA_UNUSED)
2363 {
2364    obj = efl_constructor(efl_super(obj, EFL_UI_FLIP_LEGACY_CLASS));
2365    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
2366    return obj;
2367 }
2368 
2369 EAPI Evas_Object *
elm_flip_add(Evas_Object * parent)2370 elm_flip_add(Evas_Object *parent)
2371 {
2372    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
2373    return elm_legacy_add(EFL_UI_FLIP_LEGACY_CLASS, parent);
2374 }
2375 
2376 #include "efl_ui_flip_legacy_eo.c"
2377