1 #include <Elementary.h>
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.
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
24 * Signals that you can add callbacks for are:
26 * "animate,done" - when a flip animation is finished
29 typedef struct _Widget_Data Widget_Data;
30 typedef struct _Slice Slice;
31 typedef struct _Vertex2 Vertex2;
32 typedef struct _Vertex3 Vertex3;
37 double u[4], v[4], x[4], y[4], z[4];
53 Ecore_Animator *animator;
57 Evas_Object *event[4];
59 Evas_Object *content, *clip;
62 Evas_Coord down_x, down_y, x, y, ox, oy, w, h;
63 Elm_Flip_Interaction intmode;
65 double dir_hitsize[4];
66 Eina_Bool dir_enabled[4];
67 int slices_w, slices_h;
68 Slice **slices, **slices2;
73 Eina_Bool started : 1;
74 Eina_Bool backflip : 1;
75 Eina_Bool pageflip : 1;
78 static const char *widtype = NULL;
79 static void _del_hook(Evas_Object *obj);
80 static void _theme_hook(Evas_Object *obj);
81 static void _sizing_eval(Evas_Object *obj);
82 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
83 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
85 static void _state_slices_clear(Widget_Data *st);
86 static void _configure(Evas_Object *obj);
88 static const char SIG_ANIMATE_BEGIN[] = "animate,begin";
89 static const char SIG_ANIMATE_DONE[] = "animate,done";
91 static const Evas_Smart_Cb_Description _signals[] = {
92 {SIG_ANIMATE_BEGIN, ""},
93 {SIG_ANIMATE_DONE, ""},
98 _del_hook(Evas_Object *obj)
100 Widget_Data *wd = elm_widget_data_get(obj);
102 if (wd->animator) ecore_animator_del(wd->animator);
103 _state_slices_clear(wd);
108 _theme_hook(Evas_Object *obj)
110 Widget_Data *wd = elm_widget_data_get(obj);
116 _elm_flip_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
118 Widget_Data *wd = elm_widget_data_get(obj);
123 /* Try Focus cycle in subitem */
125 return elm_widget_focus_next_get(wd->front.content, dir, next);
127 return elm_widget_focus_next_get(wd->back.content, dir, next);
132 _sizing_eval(Evas_Object *obj)
134 Widget_Data *wd = elm_widget_data_get(obj);
135 Evas_Coord minw = -1, minh = -1, minw2 = -1, minh2 = -1;
136 Evas_Coord maxw = -1, maxh = -1, maxw2 = -1, maxh2 = -1;
137 int fingx = 0, fingy = 0;
139 if (wd->front.content)
140 evas_object_size_hint_min_get(wd->front.content, &minw, &minh);
141 if (wd->back.content)
142 evas_object_size_hint_min_get(wd->back.content, &minw2, &minh2);
143 if (wd->front.content)
144 evas_object_size_hint_max_get(wd->front.content, &maxw, &maxh);
145 if (wd->back.content)
146 evas_object_size_hint_max_get(wd->back.content, &maxw2, &maxh2);
148 if (minw2 > minw) minw = minw2;
149 if (minh2 > minh) minh = minh2;
150 if ((maxw2 >= 0) && (maxw2 < maxw)) maxw = maxw2;
151 if ((maxh2 >= 0) && (maxh2 < maxh)) maxh = maxh2;
153 if (wd->dir_enabled[0]) fingy++;
154 if (wd->dir_enabled[1]) fingy++;
155 if (wd->dir_enabled[2]) fingx++;
156 if (wd->dir_enabled[3]) fingx++;
158 elm_coords_finger_size_adjust(fingx, &minw, fingy, &minh);
160 evas_object_size_hint_min_set(obj, minw, minh);
161 evas_object_size_hint_max_set(obj, maxw, maxh);
165 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
167 Widget_Data *wd = elm_widget_data_get(data);
173 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
175 Widget_Data *wd = elm_widget_data_get(obj);
176 Evas_Object *sub = event_info;
178 if (sub == wd->front.content)
180 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
181 _changed_size_hints, obj);
182 wd->front.content = NULL;
183 evas_object_hide(wd->front.clip);
186 else if (sub == wd->back.content)
188 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
189 _changed_size_hints, obj);
190 wd->back.content = NULL;
191 evas_object_hide(wd->back.clip);
197 _slice_new(Widget_Data *st __UNUSED__, Evas_Object *obj)
201 sl = calloc(1, sizeof(Slice));
202 if (!sl) return NULL;
203 sl->obj = evas_object_image_add(evas_object_evas_get(obj));
204 elm_widget_sub_object_add(st->obj, sl->obj);
205 evas_object_clip_set(sl->obj, evas_object_clip_get(st->obj));
206 evas_object_smart_member_add(sl->obj, st->obj);
207 evas_object_image_smooth_scale_set(sl->obj, 0);
208 evas_object_pass_events_set(sl->obj, 1);
209 evas_object_image_source_set(sl->obj, obj);
214 _slice_free(Slice *sl)
216 evas_object_del(sl->obj);
221 _slice_apply(Widget_Data *st, Slice *sl,
222 Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__, Evas_Coord w, Evas_Coord h __UNUSED__,
223 Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
230 evas_map_smooth_set(m, 0);
231 for (i = 0; i < 4; i++)
233 evas_map_point_color_set(m, i, 255, 255, 255, 255);
236 int p[4] = { 0, 1, 2, 3 };
237 evas_map_point_coord_set(m, i, ox + sl->x[p[i]], oy + sl->y[p[i]], sl->z[p[i]]);
238 evas_map_point_image_uv_set(m, i, sl->u[p[i]] , sl->v[p[i]]);
240 else if (st->dir == 1)
242 int p[4] = { 1, 0, 3, 2 };
243 evas_map_point_coord_set(m, i, ox + (w - sl->x[p[i]]), oy + sl->y[p[i]], sl->z[p[i]]);
244 evas_map_point_image_uv_set(m, i, ow - sl->u[p[i]] , sl->v[p[i]]);
246 else if (st->dir == 2)
248 int p[4] = { 1, 0, 3, 2 };
249 evas_map_point_coord_set(m, i, ox + sl->y[p[i]], oy + sl->x[p[i]], sl->z[p[i]]);
250 evas_map_point_image_uv_set(m, i, sl->v[p[i]] , sl->u[p[i]]);
252 else if (st->dir == 3)
254 int p[4] = { 0, 1, 2, 3 };
255 evas_map_point_coord_set(m, i, ox + sl->y[p[i]], oy + (w - sl->x[p[i]]), sl->z[p[i]]);
256 evas_map_point_image_uv_set(m, i, sl->v[p[i]] , oh - sl->u[p[i]]);
259 evas_object_map_enable_set(sl->obj, EINA_TRUE);
260 evas_object_image_fill_set(sl->obj, 0, 0, ow, oh);
261 evas_object_map_set(sl->obj, m);
266 _slice_3d(Widget_Data *st __UNUSED__, Slice *sl, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
268 Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
272 // vanishing point is center of page, and focal dist is 1024
273 evas_map_util_3d_perspective(m, x + (w / 2), y + (h / 2), 0, 1024);
274 for (i = 0; i < 4; i++)
277 evas_map_point_coord_get(m, i, &x, &y, &z);
278 evas_map_point_coord_set(m, i, x, y, 0);
280 if (evas_map_util_clockwise_get(m)) evas_object_show(sl->obj);
281 else evas_object_hide(sl->obj);
282 evas_object_map_set(sl->obj, m);
286 _slice_light(Widget_Data *st __UNUSED__, Slice *sl, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
288 Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
292 evas_map_util_3d_lighting(m,
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 // multiply brightness by 1.2 to make lightish bits all white so we dont
299 // add shading where we could otherwise be pure white
300 for (i = 0; i < 4; i++)
304 evas_map_point_color_get(m, i, &r, &g, &b, &a);
305 r = (double)r * 1.2; if (r > 255) r = 255;
306 g = (double)g * 1.2; if (g > 255) g = 255;
307 b = (double)b * 1.2; if (b > 255) b = 255;
308 evas_map_point_color_set(m, i, r, g, b, a);
310 evas_object_map_set(sl->obj, m);
314 _slice_xyz(Widget_Data *st __UNUSED__, Slice *sl,
315 double x1, double y1, double z1,
316 double x2, double y2, double z2,
317 double x3, double y3, double z3,
318 double x4, double y4, double z4)
320 sl->x[0] = x1; sl->y[0] = y1; sl->z[0] = z1;
321 sl->x[1] = x2; sl->y[1] = y2; sl->z[1] = z2;
322 sl->x[2] = x3; sl->y[2] = y3; sl->z[2] = z3;
323 sl->x[3] = x4; sl->y[3] = y4; sl->z[3] = z4;
327 _slice_uv(Widget_Data *st __UNUSED__, Slice *sl,
328 double u1, double v1,
329 double u2, double v2,
330 double u3, double v3,
331 double u4, double v4)
333 sl->u[0] = u1; sl->v[0] = v1;
334 sl->u[1] = u2; sl->v[1] = v2;
335 sl->u[2] = u3; sl->v[2] = v3;
336 sl->u[3] = u4; sl->v[3] = v4;
340 _deform_point(Vertex2 *vi, Vertex3 *vo, double rho, double theta, double A)
346 // theta == cone angle (0 -> PI/2)
347 // A == distance of cone apex from origin
348 // rho == angle of cone from vertical axis (...-PI/2 to PI/2...)
352 d = sqrt((vi->x * vi->x) + pow(vi->y - A, 2));
354 b = asin(vi->x / d) / sin(theta);
357 v1.y = d + A - (r * (1 - cos(b)) * sin(theta));
358 v1.z = r * (1 - cos(b)) * cos(theta);
360 vo->x = (v1.x * cos(rho)) - (v1.z * sin(rho));
362 vo->z = (v1.x * sin(rho)) + (v1.z * cos(rho));
366 _interp_point(Vertex3 *vi1, Vertex3 *vi2, Vertex3 *vo, double v)
368 vo->x = (v * vi2->x) + ((1.0 - v) * vi1->x);
369 vo->y = (v * vi2->y) + ((1.0 - v) * vi1->y);
370 vo->z = (v * vi2->z) + ((1.0 - v) * vi1->z);
374 _state_slices_clear(Widget_Data *st)
381 for (j = 0; j < st->slices_h; j++)
383 for (i = 0; i < st->slices_w; i++)
385 if (st->slices[num]) _slice_free(st->slices[num]);
386 if (st->slices2[num]) _slice_free(st->slices2[num]);
400 _slice_obj_color_sum(Slice *s, int p, int *r, int *g, int *b, int *a)
403 int rr = 0, gg = 0, bb = 0, aa = 0;
406 m = (Evas_Map *)evas_object_map_get(s->obj);
408 evas_map_point_color_get(m, p, &rr, &gg, &bb, &aa);
409 *r += rr; *g += gg; *b += bb; *a += aa;
414 _slice_obj_color_set(Slice *s, int p, int r, int g, int b, int a)
419 m = (Evas_Map *)evas_object_map_get(s->obj);
421 evas_map_point_color_set(m, p, r, g, b, a);
422 evas_object_map_set(s->obj, m);
426 _slice_obj_vert_color_merge(Slice *s1, int p1, Slice *s2, int p2,
427 Slice *s3, int p3, Slice *s4, int p4)
429 int r = 0, g = 0, b = 0, a = 0, n = 0;
431 n += _slice_obj_color_sum(s1, p1, &r, &g, &b, &a);
432 n += _slice_obj_color_sum(s2, p2, &r, &g, &b, &a);
433 n += _slice_obj_color_sum(s3, p3, &r, &g, &b, &a);
434 n += _slice_obj_color_sum(s4, p4, &r, &g, &b, &a);
437 r /= n; g /= n; b /= n; a /= n;
439 _slice_obj_color_set(s1, p1, r, g, b, a);
440 _slice_obj_color_set(s2, p2, r, g, b, a);
441 _slice_obj_color_set(s3, p3, r, g, b, a);
442 _slice_obj_color_set(s4, p4, r, g, b, a);
446 _state_update(Widget_Data *st)
448 Evas_Coord x1, y1, x2, y2, mx, my;
449 Evas_Coord x, y, w, h, ox, oy, ow, oh;
450 int i, j, num, nn, jump, num2;
452 double b, minv = 0.0, minva, mgrad;
453 int gx, gy, gszw, gszh, gw, gh, col, row, nw, nh;
454 double rho, A, theta, perc, percm, n, rhol, Al, thetal;
457 Evas_Object *front, *back;
462 front = st->front.content;
463 back = st->front.content;
467 front = st->back.content;
468 back = st->back.content;
471 evas_object_geometry_get(st->obj, &x, &y, &w, &h);
472 ox = x; oy = y; ow = w; oh = h;
480 // no nothing. left drag is standard
482 else if (st->dir == 1)
487 else if (st->dir == 2)
491 tmp = x1; x1 = y1; y1 = tmp;
492 tmp = x2; x2 = y2; y2 = tmp;
493 tmp = w; w = h; h = tmp;
495 else if (st->dir == 3)
499 tmp = x1; x1 = y1; y1 = tmp;
500 tmp = x2; x2 = y2; y2 = tmp;
501 tmp = w; w = h; h = tmp;
506 if (x2 >= x1) x2 = x1 - 1;
511 else if (mx >= w) mx = w - 1;
513 else if (my >= h) my = h - 1;
515 mgrad = (double)(y1 - y2) / (double)(x1 - x2);
517 if (mx < 1) mx = 1; // quick hack to keep curl line visible
519 if (mgrad == 0.0) // special horizontal case
520 mgrad = 0.001; // quick dirty hack for now
525 b = my + (minv * mx);
527 if ((b >= -5) && (b <= (h + 5)))
529 if (minv > 0.0) // clamp to h
531 minv = (double)(h + 5 - my) / (double)(mx);
532 b = my + (minv * mx);
536 minv = (double)(-5 - my) / (double)(mx);
537 b = my + (minv * mx);
541 perc = (double)x2 / (double)x1;
542 percm = (double)mx / (double)x1;
543 if (perc < 0.0) perc = 0.0;
544 else if (perc > 1.0) perc = 1.0;
545 if (percm < 0.0) percm = 0.0;
546 else if (percm > 1.0) percm = 1.0;
548 minva = atan(minv) / (M_PI / 2);
549 if (minva < 0.0) minva = -minva;
554 if (A < -(h * 20)) A = -h * 20;
558 // rho = is how much the page is turned
560 n = 1.0 - cos(n * M_PI / 2.0);
566 // theta == curliness (how much page culrs in on itself
567 n = sin((1.0 - perc) * M_PI);
571 n = sin((1.0 - perc) * M_PI);
583 if (gszw < 4) gszw = 4;
584 if (gszh < 4) gszh = 4;
586 nw = (w + gszw - 1) / gszw;
587 nh = (h + gszh - 1) / gszh;
588 if ((st->slices_w != nw) || (st->slices_h != nh)) _state_slices_clear(st);
593 st->slices = calloc(st->slices_w * st->slices_h, sizeof(Slice *));
594 if (!st->slices) return 0;
595 st->slices2 = calloc(st->slices_w * st->slices_h, sizeof(Slice *));
604 num = (st->slices_w + 1) * (st->slices_h + 1);
606 tvi = alloca(sizeof(Vertex2) * num);
607 tvo = alloca(sizeof(Vertex3) * num);
608 tvol = alloca(sizeof(Vertex3) * (st->slices_w + 1));
610 for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
615 vil.y = h - ((gx * h) / (w + gszw - 1));
616 _deform_point(&vil, &(tvol[col]), rhol, thetal, Al);
619 n = minva * sin(perc * M_PI);
623 for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
625 for (gy = 0; gy <= (h + gszh - 1); gy += gszh)
630 if (gx > w) vi.x = w;
632 if (gy > h) vi.y = h;
634 _deform_point(&vi, &vo, rho, theta, A);
636 if (gy > h) tvo1.y = h;
638 _interp_point(&vo, &tvo1, &(tvo[num]), n);
643 jump = st->slices_h + 1;
644 for (col = 0, gx = 0; gx < w; gx += gszw, col++)
646 num = st->slices_h * col;
650 if ((gx + gw) > w) gw = w - gx;
652 for (row = 0, gy = 0; gy < h; gy += gszh, row++)
656 if (b > 0) nn = num + st->slices_h - row - 1;
660 if ((gy + gh) > h) gh = h - gy;
662 vo[0] = tvo[num2 + row];
663 vo[1] = tvo[num2 + row + jump];
664 vo[2] = tvo[num2 + row + jump + 1];
665 vo[3] = tvo[num2 + row + 1];
666 #define SWP(a, b) do {typeof(a) vt; vt = (a); (a) = (b); (b) = vt;} while (0)
671 vo[0].y = h - vo[0].y;
672 vo[1].y = h - vo[1].y;
673 vo[2].y = h - vo[2].y;
674 vo[3].y = h - vo[3].y;
681 sl = _slice_new(st, front);
685 vo[0].x, vo[0].y, vo[0].z,
686 vo[1].x, vo[1].y, vo[1].z,
687 vo[2].x, vo[2].y, vo[2].z,
688 vo[3].x, vo[3].y, vo[3].z);
692 gx + gw, gy + gh, gx, gy + gh);
695 gx, h - (gy + gh), gx + gw, h - (gy + gh),
696 gx + gw, h - gy, gx, h - gy);
699 sl = st->slices2[nn];
702 sl = _slice_new(st, back);
703 st->slices2[nn] = sl;
707 vo[1].x, vo[1].y, vo[1].z,
708 vo[0].x, vo[0].y, vo[0].z,
709 vo[3].x, vo[3].y, vo[3].z,
710 vo[2].x, vo[2].y, vo[2].z);
716 gx, gy + gh, gx + gw, gy + gh);
719 gx + gw, h - (gy + gh), gx, h - (gy + gh),
720 gx, h - gy, gx + gw, h - gy);
726 w - (gx + gw), gy, w - (gx), gy,
727 w - (gx), gy + gh, w - (gx + gw), gy + gh);
730 w - (gx + gw), h - (gy + gh), w - (gx), h - (gy + gh),
731 w - (gx), h - gy, w - (gx + gw), h - gy);
737 for (j = 0; j < st->slices_h; j++)
739 for (i = 0; i < st->slices_w; i++)
741 _slice_apply(st, st->slices[num], x, y, w, h, ox, oy, ow, oh);
742 _slice_apply(st, st->slices2[num], x, y, w, h, ox, oy, ow, oh);
743 _slice_light(st, st->slices[num], ox, oy, ow, oh);
744 _slice_light(st, st->slices2[num], ox, oy, ow, oh);
749 for (i = 0; i <= st->slices_w; i++)
751 num = i * st->slices_h;
752 for (j = 0; j <= st->slices_h; j++)
756 s[0] = s[1] = s[2] = s[3] = NULL;
757 if ((i > 0) && (j > 0))
758 s[0] = st->slices[num - 1 - st->slices_h];
759 if ((i < st->slices_w) && (j > 0))
760 s[1] = st->slices[num - 1];
761 if ((i > 0) && (j < st->slices_h))
762 s[2] = st->slices[num - st->slices_h];
763 if ((i < st->slices_w) && (j < st->slices_h))
764 s[3] = st->slices[num];
766 _slice_obj_vert_color_merge(s[0], 2, s[1], 3,
768 else if (st->dir == 1)
769 _slice_obj_vert_color_merge(s[0], 3, s[1], 2,
771 else if (st->dir == 2)
772 _slice_obj_vert_color_merge(s[0], 3, s[1], 2,
774 else if (st->dir == 3)
775 _slice_obj_vert_color_merge(s[0], 2, s[1], 3,
777 s[0] = s[1] = s[2] = s[3] = NULL;
778 if ((i > 0) && (j > 0))
779 s[0] = st->slices2[num - 1 - st->slices_h];
780 if ((i < st->slices_w) && (j > 0))
781 s[1] = st->slices2[num - 1];
782 if ((i > 0) && (j < st->slices_h))
783 s[2] = st->slices2[num - st->slices_h];
784 if ((i < st->slices_w) && (j < st->slices_h))
785 s[3] = st->slices2[num];
787 _slice_obj_vert_color_merge(s[0], 3, s[1], 2,
789 else if (st->dir == 1)
790 _slice_obj_vert_color_merge(s[0], 2, s[1], 3,
792 else if (st->dir == 2)
793 _slice_obj_vert_color_merge(s[0], 2, s[1], 3,
795 else if (st->dir == 3)
796 _slice_obj_vert_color_merge(s[0], 3, s[1], 2,
803 for (i = 0; i < st->slices_w; i++)
805 for (j = 0; j < st->slices_h; j++)
807 _slice_3d(st, st->slices[num], ox, oy, ow, oh);
808 _slice_3d(st, st->slices2[num], ox, oy, ow, oh);
817 _state_end(Widget_Data *st)
819 _state_slices_clear(st);
824 flip_show_hide(Evas_Object *obj)
826 Widget_Data *wd = elm_widget_data_get(obj);
827 if (elm_flip_front_get(obj))
831 if (wd->front.content)
833 evas_object_move(wd->front.content, 4999, 4999);
834 evas_object_show(wd->front.clip);
837 evas_object_hide(wd->front.clip);
838 if (wd->back.content)
839 evas_object_show(wd->back.clip);
841 evas_object_hide(wd->back.clip);
845 if (wd->front.content)
846 evas_object_show(wd->front.clip);
848 evas_object_hide(wd->front.clip);
849 if (wd->back.content)
850 evas_object_hide(wd->back.clip);
852 evas_object_hide(wd->back.clip);
859 if (wd->front.content)
860 evas_object_show(wd->front.clip);
862 evas_object_hide(wd->front.clip);
863 if (wd->back.content)
865 evas_object_move(wd->back.content, 4999, 4999);
866 evas_object_show(wd->back.clip);
869 evas_object_hide(wd->back.clip);
873 if (wd->front.content)
874 evas_object_hide(wd->front.clip);
876 evas_object_hide(wd->front.clip);
877 if (wd->back.content)
878 evas_object_show(wd->back.clip);
880 evas_object_hide(wd->back.clip);
886 _flip_do(Evas_Object *obj, double t, Elm_Flip_Mode mode, int lin, int rev)
888 Evas_Coord x, y, w, h;
891 Evas_Coord cx, cy, px, py, foc;
892 int lx, ly, lz, lr, lg, lb, lar, lag, lab;
893 Widget_Data *wd = elm_widget_data_get(obj);
897 mf = evas_map_new(4);
898 evas_map_smooth_set(mf, 0);
899 mb = evas_map_new(4);
900 evas_map_smooth_set(mb, 0);
902 if (wd->front.content)
904 const char *type = evas_object_type_get(wd->front.content);
906 // FIXME: only handles filled obj
907 if ((type) && (!strcmp(type, "image")))
910 evas_object_image_size_get(wd->front.content, &iw, &ih);
911 evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
912 evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
913 evas_map_point_image_uv_set(mf, 0, 0, 0);
914 evas_map_point_image_uv_set(mf, 1, iw, 0);
915 evas_map_point_image_uv_set(mf, 2, iw, ih);
916 evas_map_point_image_uv_set(mf, 3, 0, ih);
920 evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
921 evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
924 if (wd->back.content)
926 const char *type = evas_object_type_get(wd->back.content);
928 if ((type) && (!strcmp(type, "image")))
931 evas_object_image_size_get(wd->back.content, &iw, &ih);
932 evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
933 evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
934 evas_map_point_image_uv_set(mb, 0, 0, 0);
935 evas_map_point_image_uv_set(mb, 1, iw, 0);
936 evas_map_point_image_uv_set(mb, 2, iw, ih);
937 evas_map_point_image_uv_set(mb, 3, 0, ih);
941 evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
942 evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
946 evas_object_geometry_get(obj, &x, &y, &w, &h);
967 case ELM_FLIP_ROTATE_Y_CENTER_AXIS:
970 if (!lin) pp = (p * p);
972 if (wd->state) deg = 180.0 * p;
973 else deg = 180 + (180.0 * p);
975 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, 0);
976 evas_map_util_3d_rotate(mb, 0.0, 180 + deg, 0.0, cx, cy, 0);
978 case ELM_FLIP_ROTATE_X_CENTER_AXIS:
981 if (!lin) pp = (p * p);
983 if (wd->state) deg = 180.0 * p;
984 else deg = 180 + (180.0 * p);
986 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, 0);
987 evas_map_util_3d_rotate(mb, 180.0 + deg, 0.0, 0.0, cx, cy, 0);
989 case ELM_FLIP_ROTATE_XZ_CENTER_AXIS:
992 if (!lin) pp = (p * p);
994 if (wd->state) deg = 180.0 * p;
995 else deg = 180 + (180.0 * p);
997 evas_map_util_3d_rotate(mf, deg, 0.0, deg, cx, cy, 0);
998 evas_map_util_3d_rotate(mb, 180 + deg, 0.0, 180 + deg, cx, cy, 0);
1000 case ELM_FLIP_ROTATE_YZ_CENTER_AXIS:
1003 if (!lin) pp = (p * p);
1005 if (wd->state) deg = 180.0 * p;
1006 else deg = 180 + (180.0 * p);
1007 if (rev) deg = -deg;
1008 evas_map_util_3d_rotate(mf, 0.0, deg, deg, cx, cy, 0);
1009 evas_map_util_3d_rotate(mb, 0.0, 180.0 + deg, 180.0 + deg, cx, cy, 0);
1011 case ELM_FLIP_CUBE_LEFT:
1014 if (!lin) pp = (p * p);
1019 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
1020 evas_map_util_3d_rotate(mb, 0.0, deg + 90, 0.0, cx, cy, w / 2);
1024 evas_map_util_3d_rotate(mf, 0.0, deg + 90, 0.0, cx, cy, w / 2);
1025 evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
1028 case ELM_FLIP_CUBE_RIGHT:
1031 if (!lin) pp = (p * p);
1036 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
1037 evas_map_util_3d_rotate(mb, 0.0, deg - 90, 0.0, cx, cy, w / 2);
1041 evas_map_util_3d_rotate(mf, 0.0, deg - 90, 0.0, cx, cy, w / 2);
1042 evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
1045 case ELM_FLIP_CUBE_UP:
1047 if (!lin) pp = (p * p);
1052 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1053 evas_map_util_3d_rotate(mb, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1057 evas_map_util_3d_rotate(mf, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1058 evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1061 case ELM_FLIP_CUBE_DOWN:
1064 if (!lin) pp = (p * p);
1069 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1070 evas_map_util_3d_rotate(mb, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1074 evas_map_util_3d_rotate(mf, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1075 evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1078 case ELM_FLIP_PAGE_LEFT:
1080 case ELM_FLIP_PAGE_RIGHT:
1082 case ELM_FLIP_PAGE_UP:
1084 case ELM_FLIP_PAGE_DOWN:
1091 if (wd->front.content)
1093 evas_map_util_3d_lighting(mf, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1094 evas_map_util_3d_perspective(mf, px, py, 0, foc);
1095 evas_object_map_set(wd->front.content, mf);
1096 evas_object_map_enable_set(wd->front.content, 1);
1097 if (evas_map_util_clockwise_get(mf)) evas_object_show(wd->front.clip);
1098 else evas_object_hide(wd->front.clip);
1101 if (wd->back.content)
1103 evas_map_util_3d_lighting(mb, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1104 evas_map_util_3d_perspective(mb, px, py, 0, foc);
1105 evas_object_map_set(wd->back.content, mb);
1106 evas_object_map_enable_set(wd->back.content, 1);
1107 if (evas_map_util_clockwise_get(mb)) evas_object_show(wd->back.clip);
1108 else evas_object_hide(wd->back.clip);
1116 _showhide(Evas_Object *obj)
1118 Widget_Data *wd = elm_widget_data_get(obj);
1119 Evas_Coord x, y, w, h;
1122 evas_object_geometry_get(obj, &x, &y, &w, &h);
1123 if (wd->front.content)
1125 if ((wd->pageflip) && (wd->state))
1127 evas_object_move(wd->front.content, 4999, 4999);
1132 evas_object_move(wd->front.content, x, y);
1134 evas_object_resize(wd->front.content, w, h);
1136 if (wd->back.content)
1138 if ((wd->pageflip) && (!wd->state))
1140 evas_object_move(wd->back.content, 4999, 4999);
1145 evas_object_move(wd->back.content, x, y);
1147 evas_object_resize(wd->back.content, w, h);
1153 _flip(Evas_Object *obj)
1155 Widget_Data *wd = elm_widget_data_get(obj);
1156 double t = ecore_loop_time_get() - wd->start;
1159 if (!wd) return ECORE_CALLBACK_CANCEL;
1160 if (!wd->animator) return ECORE_CALLBACK_CANCEL;
1163 if (t > 1.0) t = 1.0;
1165 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1166 if (wd->mode == ELM_FLIP_PAGE_LEFT)
1169 wd->started = EINA_TRUE;
1170 wd->pageflip = EINA_TRUE;
1173 wd->x = (1.0 - t) * wd->down_x;
1175 flip_show_hide(obj);
1178 else if (wd->mode == ELM_FLIP_PAGE_RIGHT)
1181 wd->started = EINA_TRUE;
1182 wd->pageflip = EINA_TRUE;
1187 flip_show_hide(obj);
1190 else if (wd->mode == ELM_FLIP_PAGE_UP)
1193 wd->started = EINA_TRUE;
1194 wd->pageflip = EINA_TRUE;
1198 wd->y = (1.0 - t) * wd->down_y;
1199 flip_show_hide(obj);
1202 else if (wd->mode == ELM_FLIP_PAGE_DOWN)
1205 wd->started = EINA_TRUE;
1206 wd->pageflip = EINA_TRUE;
1211 flip_show_hide(obj);
1215 _flip_do(obj, t, wd->mode, 0, 0);
1219 wd->pageflip = EINA_FALSE;
1221 evas_object_map_enable_set(wd->front.content, 0);
1222 evas_object_map_enable_set(wd->back.content, 0);
1223 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1224 evas_object_resize(wd->front.content, 0, 0);
1225 evas_object_resize(wd->back.content, 0, 0);
1226 evas_smart_objects_calculate(evas_object_evas_get(obj));
1228 wd->animator = NULL;
1229 wd->state = !wd->state;
1231 flip_show_hide(obj);
1232 evas_object_smart_callback_call(obj, SIG_ANIMATE_DONE, NULL);
1233 return ECORE_CALLBACK_CANCEL;
1235 return ECORE_CALLBACK_RENEW;
1239 _configure(Evas_Object *obj)
1241 Widget_Data *wd = elm_widget_data_get(obj);
1242 Evas_Coord x, y, w, h;
1247 evas_object_geometry_get(obj, &x, &y, &w, &h);
1248 // FIXME: manual flip wont get fixed
1249 if (wd->animator) _flip(obj);
1253 fsize = (double)w * wd->dir_hitsize[0];
1254 elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1255 evas_object_move(wd->event[0], x, y);
1256 evas_object_resize(wd->event[0], w, fsize);
1260 fsize = (double)w * wd->dir_hitsize[1];
1261 elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1262 evas_object_move(wd->event[1], x, y + h - fsize);
1263 evas_object_resize(wd->event[1], w, fsize);
1267 fsize = (double)h * wd->dir_hitsize[2];
1268 elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1269 evas_object_move(wd->event[2], x, y);
1270 evas_object_resize(wd->event[2], fsize, h);
1274 fsize = (double)h * wd->dir_hitsize[3];
1275 elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1276 evas_object_move(wd->event[3], x + w - fsize, y);
1277 evas_object_resize(wd->event[3], fsize, h);
1282 _move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1288 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1294 _animate(void *data)
1300 _pos_get(Widget_Data *wd, int *rev, Elm_Flip_Mode *m)
1302 Evas_Coord x, y, w, h;
1305 evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
1306 switch (wd->intmode)
1308 case ELM_FLIP_INTERACTION_ROTATE:
1309 case ELM_FLIP_INTERACTION_CUBE:
1314 t = 1.0 - ((double)wd->x / (double)wd->down_x);
1317 else if (wd->dir == 1)
1320 t = 1.0 - ((double)(w - wd->x) / (double)(w - wd->down_x));
1322 else if (wd->dir == 2)
1325 t = 1.0 - ((double)wd->y / (double)wd->down_y);
1327 else if (wd->dir == 3)
1330 t = 1.0 - ((double)(h - wd->y) / (double)(h - wd->down_y));
1334 if (t < 0.0) t = 0.0;
1335 else if (t > 1.0) t = 1.0;
1337 if ((wd->dir == 0) || (wd->dir == 1))
1339 if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
1340 *m = ELM_FLIP_ROTATE_Y_CENTER_AXIS;
1341 else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
1344 *m = ELM_FLIP_CUBE_LEFT;
1346 *m = ELM_FLIP_CUBE_RIGHT;
1351 if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
1352 *m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1353 else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
1356 *m = ELM_FLIP_CUBE_UP;
1358 *m = ELM_FLIP_CUBE_DOWN;
1369 _event_anim(void *data, double pos)
1371 Widget_Data *wd = data;
1374 p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
1378 wd->x = wd->ox * (1.0 - p);
1379 else if (wd->dir == 1)
1380 wd->x = wd->ox + ((wd->w - wd->ox) * p);
1381 else if (wd->dir == 2)
1382 wd->y = wd->oy * (1.0 - p);
1383 else if (wd->dir == 3)
1384 wd->y = wd->oy + ((wd->h - wd->oy) * p);
1389 wd->x = wd->ox + ((wd->w - wd->ox) * p);
1390 else if (wd->dir == 1)
1391 wd->x = wd->ox * (1.0 - p);
1392 else if (wd->dir == 2)
1393 wd->y = wd->oy + ((wd->h - wd->oy) * p);
1394 else if (wd->dir == 3)
1395 wd->y = wd->oy * (1.0 - p);
1397 switch (wd->intmode)
1399 case ELM_FLIP_INTERACTION_NONE:
1401 case ELM_FLIP_INTERACTION_ROTATE:
1402 case ELM_FLIP_INTERACTION_CUBE:
1404 Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1406 p = _pos_get(wd, &rev, &m);
1407 _flip_do(wd->obj, p, m, 1, rev);
1410 case ELM_FLIP_INTERACTION_PAGE:
1411 wd->pageflip = EINA_TRUE;
1418 if (pos < 1.0) return ECORE_CALLBACK_RENEW;
1420 wd->pageflip = EINA_FALSE;
1422 evas_object_map_enable_set(wd->front.content, 0);
1423 evas_object_map_enable_set(wd->back.content, 0);
1424 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1425 evas_object_resize(wd->front.content, 0, 0);
1426 evas_object_resize(wd->back.content, 0, 0);
1427 evas_smart_objects_calculate(evas_object_evas_get(wd->obj));
1429 wd->animator = NULL;
1430 if (wd->finish) wd->state = !wd->state;
1431 flip_show_hide(wd->obj);
1432 _configure(wd->obj);
1433 wd->animator = NULL;
1434 evas_object_smart_callback_call(wd->obj, SIG_ANIMATE_DONE, NULL);
1436 return ECORE_CALLBACK_CANCEL;
1440 _update_job(void *data)
1442 Widget_Data *wd = data;
1444 Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1448 switch (wd->intmode)
1450 case ELM_FLIP_INTERACTION_ROTATE:
1451 case ELM_FLIP_INTERACTION_CUBE:
1452 p = _pos_get(wd, &rev, &m);
1453 _flip_do(wd->obj, p, m, 1, rev);
1455 case ELM_FLIP_INTERACTION_PAGE:
1456 wd->pageflip = EINA_TRUE;
1466 _down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1468 Evas_Object *fl = data;
1469 Widget_Data *wd = elm_widget_data_get(fl);
1470 Evas_Event_Mouse_Down *ev = event_info;
1471 Evas_Coord x, y, w, h;
1474 if (ev->button != 1) return;
1475 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1478 ecore_animator_del(wd->animator);
1479 wd->animator = NULL;
1481 wd->down = EINA_TRUE;
1482 wd->started = EINA_FALSE;
1483 evas_object_geometry_get(data, &x, &y, &w, &h);
1484 wd->x = ev->canvas.x - x;
1485 wd->y = ev->canvas.y - y;
1493 _up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1495 Evas_Object *fl = data;
1496 Widget_Data *wd = elm_widget_data_get(fl);
1497 Evas_Event_Mouse_Up *ev = event_info;
1498 Evas_Coord x, y, w, h;
1502 if (ev->button != 1) return;
1503 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1505 evas_object_geometry_get(data, &x, &y, &w, &h);
1506 wd->x = ev->canvas.x - x;
1507 wd->y = ev->canvas.y - y;
1514 ecore_job_del(wd->job);
1517 wd->finish = EINA_FALSE;
1520 tm = (double)wd->x / (double)wd->w;
1521 if (wd->x < (wd->w / 2)) wd->finish = EINA_TRUE;
1523 else if (wd->dir == 1)
1525 if (wd->x > (wd->w / 2)) wd->finish = EINA_TRUE;
1526 tm = 1.0 - ((double)wd->x / (double)wd->w);
1528 else if (wd->dir == 2)
1530 if (wd->y < (wd->h / 2)) wd->finish = EINA_TRUE;
1531 tm = (double)wd->y / (double)wd->h;
1533 else if (wd->dir == 3)
1535 if (wd->y > (wd->h / 2)) wd->finish = EINA_TRUE;
1536 tm = 1.0 - ((double)wd->y / (double)wd->h);
1538 if (tm < 0.01) tm = 0.01;
1539 else if (tm > 0.99) tm = 0.99;
1540 if (!wd->finish) tm = 1.0 - tm;
1541 tm *= 1.0; // FIXME: config for anim time
1542 if (wd->animator) ecore_animator_del(wd->animator);
1543 wd->animator = ecore_animator_timeline_add(tm, _event_anim, wd);
1544 _event_anim(wd, 0.0);
1548 _move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1550 Evas_Object *fl = data;
1551 Widget_Data *wd = elm_widget_data_get(fl);
1552 Evas_Event_Mouse_Move *ev = event_info;
1553 Evas_Coord x, y, w, h;
1556 if (!wd->down) return;
1557 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1558 evas_object_geometry_get(data, &x, &y, &w, &h);
1559 wd->x = ev->cur.canvas.x - x;
1560 wd->y = ev->cur.canvas.y - y;
1567 dx = wd->x - wd->down_x;
1568 dy = wd->y - wd->down_y;
1569 if (((dx * dx) + (dy * dy)) > (_elm_config->finger_size * _elm_config->finger_size / 4))
1572 if ((wd->x > (w / 2)) && (dx < 0) && (abs(dx) > abs(dy))) wd->dir = 0; // left
1573 else if ((wd->x < (w / 2)) && (dx >= 0) && (abs(dx) > abs(dy))) wd->dir = 1; // right
1574 else if ((wd->y > (h / 2)) && (dy < 0) && (abs(dy) >= abs(dx))) wd->dir = 2; // up
1575 else if ((wd->y < (h / 2)) && (dy >= 0) && (abs(dy) >= abs(dx))) wd->dir = 3; // down
1576 wd->started = EINA_TRUE;
1577 if (wd->intmode == ELM_FLIP_INTERACTION_PAGE)
1578 wd->pageflip = EINA_TRUE;
1579 flip_show_hide(data);
1580 evas_smart_objects_calculate(evas_object_evas_get(data));
1582 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1583 evas_object_map_enable_set(wd->front.content, 0);
1584 evas_object_map_enable_set(wd->back.content, 0);
1585 // FIXME: XXX why does this bork interactive flip??
1586 // evas_object_resize(wd->front.content, 0, 0);
1587 // evas_object_resize(wd->back.content, 0, 0);
1588 evas_smart_objects_calculate(evas_object_evas_get(data));
1591 evas_object_smart_callback_call(obj, SIG_ANIMATE_BEGIN, NULL);
1595 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1596 if (wd->job) ecore_job_del(wd->job);
1597 wd->job = ecore_job_add(_update_job, wd);
1601 * Add a new flip to the parent
1603 * @param parent The parent object
1604 * @return The new object or NULL if it cannot be created
1609 elm_flip_add(Evas_Object *parent)
1615 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1617 ELM_SET_WIDTYPE(widtype, "flip");
1618 elm_widget_type_set(obj, "flip");
1619 elm_widget_sub_object_add(parent, obj);
1620 elm_widget_data_set(obj, wd);
1621 elm_widget_del_hook_set(obj, _del_hook);
1622 elm_widget_theme_hook_set(obj, _theme_hook);
1623 elm_widget_focus_next_hook_set(obj, _elm_flip_focus_next_hook);
1624 elm_widget_can_focus_set(obj, EINA_FALSE);
1628 wd->clip = evas_object_rectangle_add(e);
1629 evas_object_static_clip_set(wd->clip, 1);
1630 evas_object_color_set(wd->clip, 255, 255, 255, 255);
1631 evas_object_move(wd->clip, -49999, -49999);
1632 evas_object_resize(wd->clip, 99999, 99999);
1633 elm_widget_sub_object_add(obj, wd->clip);
1634 evas_object_clip_set(wd->clip, evas_object_clip_get(obj));
1635 evas_object_smart_member_add(wd->clip, obj);
1637 wd->front.clip = evas_object_rectangle_add(e);
1638 evas_object_static_clip_set(wd->front.clip, 1);
1639 evas_object_data_set(wd->front.clip, "_elm_leaveme", obj);
1640 evas_object_color_set(wd->front.clip, 255, 255, 255, 255);
1641 evas_object_move(wd->front.clip, -49999, -49999);
1642 evas_object_resize(wd->front.clip, 99999, 99999);
1643 elm_widget_sub_object_add(obj, wd->front.clip);
1644 evas_object_smart_member_add(wd->front.clip, obj);
1645 evas_object_clip_set(wd->front.clip, wd->clip);
1647 wd->back.clip = evas_object_rectangle_add(e);
1648 evas_object_static_clip_set(wd->back.clip, 1);
1649 evas_object_data_set(wd->back.clip, "_elm_leaveme", obj);
1650 evas_object_color_set(wd->back.clip, 255, 255, 255, 255);
1651 evas_object_move(wd->back.clip, -49999, -49999);
1652 evas_object_resize(wd->back.clip, 99999, 99999);
1653 elm_widget_sub_object_add(wd->back.clip, obj);
1654 evas_object_smart_member_add(obj, wd->back.clip);
1655 evas_object_clip_set(wd->back.clip, wd->clip);
1657 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1658 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL);
1659 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
1661 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1664 wd->intmode = ELM_FLIP_INTERACTION_NONE;
1672 * Set the front content of the flip widget.
1674 * Once the content object is set, a previously set one will be deleted.
1675 * If you want to keep that old content object, use the
1676 * elm_flip_content_front_unset() function.
1678 * @param obj The flip object
1679 * @param content The new front content object
1684 elm_flip_content_front_set(Evas_Object *obj, Evas_Object *content)
1686 ELM_CHECK_WIDTYPE(obj, widtype);
1687 Widget_Data *wd = elm_widget_data_get(obj);
1690 if (wd->front.content == content) return;
1691 if (wd->front.content) evas_object_del(wd->back.content);
1692 wd->front.content = content;
1695 elm_widget_sub_object_add(obj, content);
1696 evas_object_smart_member_add(content, obj);
1697 evas_object_clip_set(content, wd->front.clip);
1698 evas_object_event_callback_add(content,
1699 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1700 _changed_size_hints, obj);
1703 // force calc to contents are the right size before transition
1704 evas_smart_objects_calculate(evas_object_evas_get(obj));
1705 flip_show_hide(obj);
1707 if (wd->intmode != ELM_FLIP_INTERACTION_NONE)
1709 for (i = 0; i < 4; i++) evas_object_raise(wd->event[i]);
1714 * Set the back content of the flip widget.
1716 * Once the content object is set, a previously set one will be deleted.
1717 * If you want to keep that old content object, use the
1718 * elm_flip_content_back_unset() function.
1720 * @param obj The flip object
1721 * @param content The new back content object
1726 elm_flip_content_back_set(Evas_Object *obj, Evas_Object *content)
1728 ELM_CHECK_WIDTYPE(obj, widtype);
1729 Widget_Data *wd = elm_widget_data_get(obj);
1732 if (wd->back.content == content) return;
1733 if (wd->back.content) evas_object_del(wd->back.content);
1734 wd->back.content = content;
1737 elm_widget_sub_object_add(obj, content);
1738 evas_object_smart_member_add(content, obj);
1739 evas_object_clip_set(content, wd->back.clip);
1740 evas_object_event_callback_add(content,
1741 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1742 _changed_size_hints, obj);
1745 // force calc to contents are the right size before transition
1746 evas_smart_objects_calculate(evas_object_evas_get(obj));
1747 flip_show_hide(obj);
1749 if (wd->intmode != ELM_FLIP_INTERACTION_NONE)
1751 for (i = 0; i < 4; i++) evas_object_raise(wd->event[i]);
1756 * Get the front content used for the flip
1758 * Return the front content object which is set for this widget.
1760 * @param obj The flip object
1761 * @return The front content object that is being used
1766 elm_flip_content_front_get(const Evas_Object *obj)
1768 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1769 Widget_Data *wd = elm_widget_data_get(obj);
1770 return wd->front.content;
1775 * Get the back content used for the flip
1777 * Return the back content object which is set for this widget.
1779 * @param obj The flip object
1780 * @return The back content object that is being used
1785 elm_flip_content_back_get(const Evas_Object *obj)
1787 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1788 Widget_Data *wd = elm_widget_data_get(obj);
1789 return wd->back.content;
1793 * Unset the front content used for the flip
1795 * Unparent and return the front content object which was set for this widget.
1797 * @param obj The flip object
1798 * @return The front content object that was being used
1803 elm_flip_content_front_unset(Evas_Object *obj)
1805 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1806 Widget_Data *wd = elm_widget_data_get(obj);
1807 if (!wd) return NULL;
1808 if (!wd->front.content) return NULL;
1809 Evas_Object *content = wd->front.content;
1810 evas_object_clip_unset(content);
1811 elm_widget_sub_object_del(obj, content);
1812 evas_object_smart_member_del(content);
1813 wd->front.content = NULL;
1818 * Unset the back content used for the flip
1820 * Unparent and return the back content object which was set for this widget.
1822 * @param obj The flip object
1823 * @return The back content object that was being used
1828 elm_flip_content_back_unset(Evas_Object *obj)
1830 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1831 Widget_Data *wd = elm_widget_data_get(obj);
1832 if (!wd) return NULL;
1833 if (!wd->back.content) return NULL;
1834 Evas_Object *content = wd->back.content;
1835 evas_object_clip_unset(content);
1836 elm_widget_sub_object_del(obj, content);
1837 evas_object_smart_member_del(content);
1838 wd->back.content = NULL;
1843 * Get flip front visibility state
1845 * @param obj The flip object
1846 * @return If front front is showing or not currently
1851 elm_flip_front_get(const Evas_Object *obj)
1853 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1854 Widget_Data *wd = elm_widget_data_get(obj);
1855 if (!wd) return EINA_FALSE;
1860 * Set flip perspective
1862 * @param obj The flip object
1863 * @param foc The coordinate to set the focus on
1864 * @param x The X coordinate
1865 * @param y The Y coordinate
1867 * NOTE: This function currently does nothing.
1872 elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
1874 ELM_CHECK_WIDTYPE(obj, widtype);
1875 Widget_Data *wd = elm_widget_data_get(obj);
1879 // FIXME: add ambient and lighting control
1882 * Runs the flip animation
1884 * @param obj The flip object
1885 * @param mode The mode type
1890 elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode)
1892 ELM_CHECK_WIDTYPE(obj, widtype);
1893 Widget_Data *wd = elm_widget_data_get(obj);
1895 if (!wd->animator) wd->animator = ecore_animator_add(_animate, obj);
1896 flip_show_hide(obj);
1898 wd->start = ecore_loop_time_get();
1899 wd->len = 0.5; // FIXME: make config val
1900 if ((wd->mode == ELM_FLIP_PAGE_LEFT) ||
1901 (wd->mode == ELM_FLIP_PAGE_RIGHT) ||
1902 (wd->mode == ELM_FLIP_PAGE_UP) ||
1903 (wd->mode == ELM_FLIP_PAGE_DOWN))
1904 wd->pageflip = EINA_TRUE;
1905 // force calc to contents are the right size before transition
1906 evas_smart_objects_calculate(evas_object_evas_get(obj));
1908 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1909 evas_object_map_enable_set(wd->front.content, 0);
1910 evas_object_map_enable_set(wd->back.content, 0);
1911 evas_object_resize(wd->front.content, 0, 0);
1912 evas_object_resize(wd->back.content, 0, 0);
1913 evas_smart_objects_calculate(evas_object_evas_get(obj));
1916 evas_object_smart_callback_call(obj, SIG_ANIMATE_BEGIN, NULL);
1920 * Set the interactive flip mode
1922 * @param obj The flip object
1923 * @param mode The interactive flip mode to use
1925 * This sets if the flip should be interactive (allow user to click and
1926 * drag a side of the flip to reveal the back page and cause it to flip).
1927 * By default a flip is not interactive. You may also need to set which
1928 * sides of the flip are "active" for flipping and how much space they use
1929 * (a minimum of a finger size) with elm_flip_interacton_direction_enabled_set()
1930 * and elm_flip_interacton_direction_hitsize_set()
1935 elm_flip_interaction_set(Evas_Object *obj, Elm_Flip_Interaction mode)
1937 ELM_CHECK_WIDTYPE(obj, widtype);
1939 Widget_Data *wd = elm_widget_data_get(obj);
1941 if (wd->intmode == mode) return;
1943 for (i = 0; i < 4; i++)
1945 if (wd->intmode == ELM_FLIP_INTERACTION_NONE)
1949 evas_object_del(wd->event[i]);
1950 wd->event[i] = NULL;
1955 if ((wd->dir_enabled[i]) && (!wd->event[i]))
1957 wd->event[i] = evas_object_rectangle_add(evas_object_evas_get(obj));
1958 elm_widget_sub_object_add(obj, wd->event[i]);
1959 evas_object_clip_set(wd->event[i], evas_object_clip_get(obj));
1960 evas_object_color_set(wd->event[i], 0, 0, 0, 0);
1961 evas_object_show(wd->event[i]);
1962 evas_object_smart_member_add(wd->event[i], obj);
1963 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_DOWN, _down_cb, obj);
1964 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_UP, _up_cb, obj);
1965 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_MOVE, _move_cb, obj);
1974 * Get the interactive flip mode
1976 * @param obj The flip object
1977 * @return The interactive flip mode
1979 * Returns the interactive flip mode set by elm_flip_interaction_set()
1983 EAPI Elm_Flip_Interaction
1984 elm_flip_interaction_get(const Evas_Object *obj)
1986 ELM_CHECK_WIDTYPE(obj, widtype) ELM_FLIP_INTERACTION_NONE;
1987 Widget_Data *wd = elm_widget_data_get(obj);
1988 if (!wd) return ELM_FLIP_INTERACTION_NONE;
1993 * Set which directions of the flip respond to interactive flip
1995 * @param obj The flip object
1996 * @param dir The direction to change
1997 * @param enabled If that direction is enabled or not
1999 * By default all directions are disabled, so you may want to enable the
2000 * desired directions for flipping if you need interactive flipping.
2005 elm_flip_interacton_direction_enabled_set(Evas_Object *obj, Elm_Flip_Direction dir, Eina_Bool enabled)
2007 ELM_CHECK_WIDTYPE(obj, widtype);
2008 Widget_Data *wd = elm_widget_data_get(obj);
2011 enabled = !!enabled;
2012 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
2013 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
2014 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
2015 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
2017 if (wd->dir_enabled[i] == enabled) return;
2018 wd->dir_enabled[i] = enabled;
2019 if (wd->intmode == ELM_FLIP_INTERACTION_NONE) return;
2020 if ((wd->dir_enabled[i]) && (!wd->event[i]))
2022 wd->event[i] = evas_object_rectangle_add(evas_object_evas_get(obj));
2023 elm_widget_sub_object_add(obj, wd->event[i]);
2024 evas_object_clip_set(wd->event[i], evas_object_clip_get(obj));
2025 evas_object_color_set(wd->event[i], 0, 0, 0, 0);
2026 evas_object_show(wd->event[i]);
2027 evas_object_smart_member_add(wd->event[i], obj);
2028 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_DOWN, _down_cb, obj);
2029 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_UP, _up_cb, obj);
2030 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_MOVE, _move_cb, obj);
2032 else if (!(wd->dir_enabled[i]) && (wd->event[i]))
2034 evas_object_del(wd->event[i]);
2035 wd->event[i] = NULL;
2042 * Get the enabled state of that flip direction
2044 * @param obj The flip object
2045 * @param dir The direction to check
2046 * @return If that direction is enabled or not
2048 * Gets the enabled state set by elm_flip_interacton_direction_enabled_set()
2053 elm_flip_interacton_direction_enabled_get(Evas_Object *obj, Elm_Flip_Direction dir)
2055 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2056 Widget_Data *wd = elm_widget_data_get(obj);
2058 if (!wd) return EINA_FALSE;
2059 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
2060 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
2061 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
2062 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
2063 if (i < 0) return EINA_FALSE;
2064 return wd->dir_enabled[i];
2068 * Set the amount of the flip that is sensitive to interactive flip
2070 * @param obj The flip object
2071 * @param dir The direction to modify
2072 * @param hitsize The amount of that dimension (0.0 to 1.0) to use
2077 elm_flip_interacton_direction_hitsize_set(Evas_Object *obj, Elm_Flip_Direction dir, double hitsize)
2079 ELM_CHECK_WIDTYPE(obj, widtype);
2080 Widget_Data *wd = elm_widget_data_get(obj);
2083 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
2084 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
2085 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
2086 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
2088 if (hitsize < 0.0) hitsize = 0.0;
2089 else if (hitsize > 1.0) hitsize = 1.0;
2090 if (wd->dir_hitsize[i] == hitsize) return;
2091 wd->dir_hitsize[i] = hitsize;
2097 * Get the amount of the flip that is sensitive to interactive flip
2099 * @param obj The flip object
2100 * @param dir The direction to check
2101 * @return The size set for that direction
2103 * Returns the amount os sensitive area set by elm_flip_interacton_direction_hitsize_set().
2108 elm_flip_interacton_direction_hitsize_get(Evas_Object *obj, Elm_Flip_Direction dir)
2110 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2111 Widget_Data *wd = elm_widget_data_get(obj);
2113 if (!wd) return 0.0;
2114 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
2115 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
2116 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
2117 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
2118 if (i < 0) return 0.0;
2119 return wd->dir_hitsize[i];