1 #include <Elementary.h>
4 typedef struct _Widget_Data Widget_Data;
5 typedef struct _Slice Slice;
6 typedef struct _Vertex2 Vertex2;
7 typedef struct _Vertex3 Vertex3;
12 double u[4], v[4], x[4], y[4], z[4];
28 Ecore_Animator *animator;
32 Evas_Object *event[4];
35 Evas_Object *content, *clip;
38 Evas_Coord down_x, down_y, x, y, ox, oy, w, h;
39 Elm_Flip_Interaction intmode;
41 double dir_hitsize[4];
42 Eina_Bool dir_enabled[4];
43 int slices_w, slices_h;
44 Slice **slices, **slices2;
49 Eina_Bool started : 1;
50 Eina_Bool backflip : 1;
51 Eina_Bool pageflip : 1;
54 static const char *widtype = NULL;
55 static void _del_hook(Evas_Object *obj);
56 static void _theme_hook(Evas_Object *obj);
57 static void _sizing_eval(Evas_Object *obj);
58 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
59 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
61 static void _state_slices_clear(Widget_Data *wd);
62 static void _configure(Evas_Object *obj);
64 static const char SIG_ANIMATE_BEGIN[] = "animate,begin";
65 static const char SIG_ANIMATE_DONE[] = "animate,done";
67 static const Evas_Smart_Cb_Description _signals[] = {
68 {SIG_ANIMATE_BEGIN, ""},
69 {SIG_ANIMATE_DONE, ""},
74 _del_hook(Evas_Object *obj)
76 Widget_Data *wd = elm_widget_data_get(obj);
78 if (wd->animator) ecore_animator_del(wd->animator);
79 _state_slices_clear(wd);
84 _theme_hook(Evas_Object *obj)
86 Widget_Data *wd = elm_widget_data_get(obj);
92 _elm_flip_focus_next_hook(const Evas_Object *obj,
93 Elm_Focus_Direction dir, Evas_Object **next)
95 Widget_Data *wd = elm_widget_data_get(obj);
96 if (!wd) return EINA_FALSE;
98 /* Try Focus cycle in subitem */
100 return elm_widget_focus_next_get(wd->front.content, dir, next);
102 return elm_widget_focus_next_get(wd->back.content, dir, next);
106 _sizing_eval(Evas_Object *obj)
108 Widget_Data *wd = elm_widget_data_get(obj);
109 Evas_Coord minw = -1, minh = -1, minw2 = -1, minh2 = -1;
110 Evas_Coord maxw = -1, maxh = -1, maxw2 = -1, maxh2 = -1;
111 int fingx = 0, fingy = 0;
113 if (wd->front.content)
114 evas_object_size_hint_min_get(wd->front.content, &minw, &minh);
115 if (wd->back.content)
116 evas_object_size_hint_min_get(wd->back.content, &minw2, &minh2);
117 if (wd->front.content)
118 evas_object_size_hint_max_get(wd->front.content, &maxw, &maxh);
119 if (wd->back.content)
120 evas_object_size_hint_max_get(wd->back.content, &maxw2, &maxh2);
122 if (minw2 > minw) minw = minw2;
123 if (minh2 > minh) minh = minh2;
124 if ((maxw2 >= 0) && (maxw2 < maxw)) maxw = maxw2;
125 if ((maxh2 >= 0) && (maxh2 < maxh)) maxh = maxh2;
127 if (wd->dir_enabled[0]) fingy++;
128 if (wd->dir_enabled[1]) fingy++;
129 if (wd->dir_enabled[2]) fingx++;
130 if (wd->dir_enabled[3]) fingx++;
132 elm_coords_finger_size_adjust(fingx, &minw, fingy, &minh);
134 evas_object_size_hint_min_set(obj, minw, minh);
135 evas_object_size_hint_max_set(obj, maxw, maxh);
139 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
141 Widget_Data *wd = elm_widget_data_get(data);
147 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
149 Widget_Data *wd = elm_widget_data_get(obj);
150 Evas_Object *sub = event_info;
152 if (sub == wd->front.content)
154 evas_object_event_callback_del_full(sub,
155 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
156 _changed_size_hints, obj);
157 wd->front.content = NULL;
158 evas_object_hide(wd->front.clip);
161 else if (sub == wd->back.content)
163 evas_object_event_callback_del_full(sub,
164 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
165 _changed_size_hints, obj);
166 wd->back.content = NULL;
167 evas_object_hide(wd->back.clip);
173 _slice_new(Widget_Data *wd, Evas_Object *obj)
177 sl = calloc(1, sizeof(Slice));
178 if (!sl) return NULL;
179 sl->obj = evas_object_image_add(evas_object_evas_get(obj));
180 elm_widget_sub_object_add(wd->obj, sl->obj);
181 evas_object_clip_set(sl->obj, evas_object_clip_get(wd->obj));
182 evas_object_smart_member_add(sl->obj, wd->obj);
183 evas_object_image_smooth_scale_set(sl->obj, EINA_FALSE);
184 evas_object_pass_events_set(sl->obj, EINA_TRUE);
185 evas_object_image_source_set(sl->obj, obj);
190 _slice_free(Slice *sl)
192 evas_object_del(sl->obj);
197 _slice_apply(Widget_Data *wd, Slice *sl, Evas_Coord x __UNUSED__,
198 Evas_Coord y __UNUSED__, Evas_Coord w, Evas_Coord h __UNUSED__,
199 Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
206 evas_map_smooth_set(m, EINA_FALSE);
207 for (i = 0; i < 4; i++)
209 evas_map_point_color_set(m, i, 255, 255, 255, 255);
212 int p[4] = { 0, 1, 2, 3 };
213 evas_map_point_coord_set(m, i, ox + sl->x[p[i]], oy + sl->y[p[i]],
215 evas_map_point_image_uv_set(m, i, sl->u[p[i]] , sl->v[p[i]]);
217 else if (wd->dir == 1)
219 int p[4] = { 1, 0, 3, 2 };
220 evas_map_point_coord_set(m, i, ox + (w - sl->x[p[i]]),
221 oy + sl->y[p[i]], sl->z[p[i]]);
222 evas_map_point_image_uv_set(m, i, ow - sl->u[p[i]], sl->v[p[i]]);
224 else if (wd->dir == 2)
226 int p[4] = { 1, 0, 3, 2 };
227 evas_map_point_coord_set(m, i, ox + sl->y[p[i]], oy + sl->x[p[i]],
229 evas_map_point_image_uv_set(m, i, sl->v[p[i]] , sl->u[p[i]]);
231 else/* if (wd->dir == 3) will be this anyway */
233 int p[4] = { 0, 1, 2, 3 };
234 evas_map_point_coord_set(m, i, ox + sl->y[p[i]],
235 oy + (w - sl->x[p[i]]), sl->z[p[i]]);
236 evas_map_point_image_uv_set(m, i, sl->v[p[i]] , oh - sl->u[p[i]]);
239 evas_object_map_enable_set(sl->obj, EINA_TRUE);
240 evas_object_image_fill_set(sl->obj, 0, 0, ow, oh);
241 evas_object_map_set(sl->obj, m);
246 _slice_3d(Widget_Data *wd __UNUSED__, Slice *sl, Evas_Coord x, Evas_Coord y,
247 Evas_Coord w, Evas_Coord h)
249 Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
253 // vanishing point is center of page, and focal dist is 1024
254 evas_map_util_3d_perspective(m, x + (w / 2), y + (h / 2), 0, 1024);
255 for (i = 0; i < 4; i++)
257 Evas_Coord xx, yy, zz;
258 evas_map_point_coord_get(m, i, &xx, &yy, &zz);
259 evas_map_point_coord_set(m, i, xx, yy, 0);
261 if (evas_map_util_clockwise_get(m)) evas_object_show(sl->obj);
262 else evas_object_hide(sl->obj);
263 evas_object_map_set(sl->obj, m);
267 _slice_light(Widget_Data *wd __UNUSED__, Slice *sl, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
269 Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
273 evas_map_util_3d_lighting(m,
275 // (centered over page 10 * h toward camera)
276 x + (w / 2) , y + (h / 2) , -10000,
277 255, 255, 255, // light color
278 0 , 0 , 0); // ambient minimum
279 // multiply brightness by 1.2 to make lightish bits all white so we dont
280 // add shading where we could otherwise be pure white
281 for (i = 0; i < 4; i++)
285 evas_map_point_color_get(m, i, &r, &g, &b, &a);
286 r = (double)r * 1.2; if (r > 255) r = 255;
287 g = (double)g * 1.2; if (g > 255) g = 255;
288 b = (double)b * 1.2; if (b > 255) b = 255;
289 evas_map_point_color_set(m, i, r, g, b, a);
291 evas_object_map_set(sl->obj, m);
295 _slice_xyz(Widget_Data *wd __UNUSED__, Slice *sl,
296 double xx1, double yy1, double zz1,
297 double xx2, double yy2, double zz2,
298 double xx3, double yy3, double zz3,
299 double xx4, double yy4, double zz4)
301 sl->x[0] = xx1; sl->y[0] = yy1; sl->z[0] = zz1;
302 sl->x[1] = xx2; sl->y[1] = yy2; sl->z[1] = zz2;
303 sl->x[2] = xx3; sl->y[2] = yy3; sl->z[2] = zz3;
304 sl->x[3] = xx4; sl->y[3] = yy4; sl->z[3] = zz4;
308 _slice_uv(Widget_Data *wd __UNUSED__, Slice *sl,
309 double u1, double v1,
310 double u2, double v2,
311 double u3, double v3,
312 double u4, double v4)
314 sl->u[0] = u1; sl->v[0] = v1;
315 sl->u[1] = u2; sl->v[1] = v2;
316 sl->u[2] = u3; sl->v[2] = v3;
317 sl->u[3] = u4; sl->v[3] = v4;
321 _deform_point(Vertex2 *vi, Vertex3 *vo, double rho, double theta, double A)
327 // theta == cone angle (0 -> PI/2)
328 // A == distance of cone apex from origin
329 // rho == angle of cone from vertical axis (...-PI/2 to PI/2...)
333 d = sqrt((vi->x * vi->x) + pow(vi->y - A, 2));
335 b = asin(vi->x / d) / sin(theta);
338 v1.y = d + A - (r * (1 - cos(b)) * sin(theta));
339 v1.z = r * (1 - cos(b)) * cos(theta);
341 vo->x = (v1.x * cos(rho)) - (v1.z * sin(rho));
343 vo->z = (v1.x * sin(rho)) + (v1.z * cos(rho));
347 _interp_point(Vertex3 *vi1, Vertex3 *vi2, Vertex3 *vo, double v)
349 vo->x = (v * vi2->x) + ((1.0 - v) * vi1->x);
350 vo->y = (v * vi2->y) + ((1.0 - v) * vi1->y);
351 vo->z = (v * vi2->z) + ((1.0 - v) * vi1->z);
355 _state_slices_clear(Widget_Data *wd)
362 for (j = 0; j < wd->slices_h; j++)
364 for (i = 0; i < wd->slices_w; i++)
366 if (wd->slices[num]) _slice_free(wd->slices[num]);
367 if (wd->slices2[num]) _slice_free(wd->slices2[num]);
381 _slice_obj_color_sum(Slice *s, int p, int *r, int *g, int *b, int *a)
384 int rr = 0, gg = 0, bb = 0, aa = 0;
387 m = (Evas_Map *)evas_object_map_get(s->obj);
389 evas_map_point_color_get(m, p, &rr, &gg, &bb, &aa);
390 *r += rr; *g += gg; *b += bb; *a += aa;
395 _slice_obj_color_set(Slice *s, int p, int r, int g, int b, int a)
400 m = (Evas_Map *) evas_object_map_get(s->obj);
402 evas_map_point_color_set(m, p, r, g, b, a);
403 evas_object_map_set(s->obj, m);
407 _slice_obj_vert_color_merge(Slice *s1, int p1, Slice *s2, int p2,
408 Slice *s3, int p3, Slice *s4, int p4)
410 int r = 0, g = 0, b = 0, a = 0, n = 0;
412 n += _slice_obj_color_sum(s1, p1, &r, &g, &b, &a);
413 n += _slice_obj_color_sum(s2, p2, &r, &g, &b, &a);
414 n += _slice_obj_color_sum(s3, p3, &r, &g, &b, &a);
415 n += _slice_obj_color_sum(s4, p4, &r, &g, &b, &a);
418 r /= n; g /= n; b /= n; a /= n;
420 _slice_obj_color_set(s1, p1, r, g, b, a);
421 _slice_obj_color_set(s2, p2, r, g, b, a);
422 _slice_obj_color_set(s3, p3, r, g, b, a);
423 _slice_obj_color_set(s4, p4, r, g, b, a);
427 _state_update(Widget_Data *wd)
429 Evas_Coord xx1, yy1, xx2, yy2, mx, my;
430 Evas_Coord x, y, w, h, ox, oy, ow, oh;
431 int i, j, num, nn, jump, num2;
433 double b, minv = 0.0, minva, mgrad;
434 int gx, gy, gszw, gszh, gw, gh, col, row, nw, nh;
435 double rho, A, theta, perc, percm, n, rhol, Al, thetal;
437 Evas_Object *front, *back;
439 wd->backflip = EINA_TRUE;
442 front = wd->front.content;
443 back = wd->front.content;
447 front = wd->back.content;
448 back = wd->back.content;
451 evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
452 ox = x; oy = y; ow = w; oh = h;
460 // no nothing. left drag is standard
462 else if (wd->dir == 1)
467 else if (wd->dir == 2)
471 tmp = xx1; xx1 = yy1; yy1 = tmp;
472 tmp = xx2; xx2 = yy2; yy2 = tmp;
473 tmp = w; w = h; h = tmp;
475 else/* if (wd->dir == 3) will be this anyway */
479 tmp = xx1; xx1 = yy1; yy1 = tmp;
480 tmp = xx2; xx2 = yy2; yy2 = tmp;
481 tmp = w; w = h; h = tmp;
486 if (xx2 >= xx1) xx2 = xx1 - 1;
487 mx = (xx1 + xx2) / 2;
488 my = (yy1 + yy2) / 2;
491 else if (mx >= w) mx = w - 1;
493 else if (my >= h) my = h - 1;
495 mgrad = (double)(yy1 - yy2) / (double)(xx1 - xx2);
497 if (mx < 1) mx = 1; // quick hack to keep curl line visible
499 if (mgrad == 0.0) // special horizontal case
500 mgrad = 0.001; // quick dirty hack for now
505 b = my + (minv * mx);
507 if ((b >= -5) && (b <= (h + 5)))
509 if (minv > 0.0) // clamp to h
511 minv = (double)(h + 5 - my) / (double)(mx);
512 b = my + (minv * mx);
516 minv = (double)(-5 - my) / (double)(mx);
517 b = my + (minv * mx);
521 perc = (double)xx2 / (double)xx1;
522 percm = (double)mx / (double)xx1;
523 if (perc < 0.0) perc = 0.0;
524 else if (perc > 1.0) perc = 1.0;
525 if (percm < 0.0) percm = 0.0;
526 else if (percm > 1.0) percm = 1.0;
528 minva = atan(minv) / (M_PI / 2);
529 if (minva < 0.0) minva = -minva;
534 if (A < -(h * 20)) A = -h * 20;
538 // rho = is how much the page is turned
540 n = 1.0 - cos(n * M_PI / 2.0);
546 // theta == curliness (how much page culrs in on itself
547 n = sin((1.0 - perc) * M_PI);
551 n = sin((1.0 - perc) * M_PI);
561 if (gszw < 4) gszw = 4;
562 if (gszh < 4) gszh = 4;
564 nw = (w + gszw - 1) / gszw;
565 nh = (h + gszh - 1) / gszh;
566 if ((wd->slices_w != nw) || (wd->slices_h != nh)) _state_slices_clear(wd);
571 wd->slices = calloc(wd->slices_w * wd->slices_h, sizeof(Slice *));
572 if (!wd->slices) return 0;
573 wd->slices2 = calloc(wd->slices_w * wd->slices_h, sizeof(Slice *));
582 num = (wd->slices_w + 1) * (wd->slices_h + 1);
584 tvo = alloca(sizeof(Vertex3) * num);
585 tvol = alloca(sizeof(Vertex3) * (wd->slices_w + 1));
587 for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
592 vil.y = h - ((gx * h) / (w + gszw - 1));
593 _deform_point(&vil, &(tvol[col]), rhol, thetal, Al);
596 n = minva * sin(perc * M_PI);
600 for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
602 for (gy = 0; gy <= (h + gszh - 1); gy += gszh)
607 if (gx > w) vi.x = w;
609 if (gy > h) vi.y = h;
611 _deform_point(&vi, &vo, rho, theta, A);
613 if (gy > h) tvo1.y = h;
615 _interp_point(&vo, &tvo1, &(tvo[num]), n);
620 jump = wd->slices_h + 1;
621 for (col = 0, gx = 0; gx < w; gx += gszw, col++)
623 num = wd->slices_h * col;
627 if ((gx + gw) > w) gw = w - gx;
629 for (row = 0, gy = 0; gy < h; gy += gszh, row++)
633 if (b > 0) nn = num + wd->slices_h - row - 1;
637 if ((gy + gh) > h) gh = h - gy;
639 vo[0] = tvo[num2 + row];
640 vo[1] = tvo[num2 + row + jump];
641 vo[2] = tvo[num2 + row + jump + 1];
642 vo[3] = tvo[num2 + row + 1];
643 #define SWP(a, b) do {typeof(a) vt; vt = (a); (a) = (b); (b) = vt;} while (0)
648 vo[0].y = h - vo[0].y;
649 vo[1].y = h - vo[1].y;
650 vo[2].y = h - vo[2].y;
651 vo[3].y = h - vo[3].y;
658 sl = _slice_new(wd, front);
662 vo[0].x, vo[0].y, vo[0].z,
663 vo[1].x, vo[1].y, vo[1].z,
664 vo[2].x, vo[2].y, vo[2].z,
665 vo[3].x, vo[3].y, vo[3].z);
668 gx, gy, gx + gw, gy, gx + gw, gy + gh, gx, gy + gh);
671 gx, h - (gy + gh), gx + gw, h - (gy + gh), gx + gw,
675 sl = wd->slices2[nn];
678 sl = _slice_new(wd, back);
679 wd->slices2[nn] = sl;
683 vo[1].x, vo[1].y, vo[1].z,
684 vo[0].x, vo[0].y, vo[0].z,
685 vo[3].x, vo[3].y, vo[3].z,
686 vo[2].x, vo[2].y, vo[2].z);
690 _slice_uv(wd, sl, gx + gw, gy, gx, gy, gx, gy + gh, gx + gw,
693 _slice_uv(wd, sl, gx + gw, h - (gy + gh), gx, h - (gy + gh),
694 gx, h - gy, gx + gw, h - gy);
699 _slice_uv(wd, sl, w - (gx + gw), gy, w - (gx), gy, w - (gx),
700 gy + gh, w - (gx + gw), gy + gh);
702 _slice_uv(wd, sl, w - (gx + gw), h - (gy + gh), w - (gx),
703 h - (gy + gh), w - (gx), h - gy, w - (gx + gw),
709 for (num = 0; num < wd->slices_h * wd->slices_w; num++)
711 _slice_apply(wd, wd->slices[num], x, y, w, h, ox, oy, ow, oh);
712 _slice_apply(wd, wd->slices2[num], x, y, w, h, ox, oy, ow, oh);
713 _slice_light(wd, wd->slices[num], ox, oy, ow, oh);
714 _slice_light(wd, wd->slices2[num], ox, oy, ow, oh);
717 for (i = 0; i <= wd->slices_w; i++)
719 num = i * wd->slices_h;
720 for (j = 0; j <= wd->slices_h; j++)
722 Slice *s[4] = { NULL }, *s2[4] = { NULL };
724 if ((i > 0) && (j > 0))
725 s[0] = wd->slices[num - 1 - wd->slices_h],
726 s2[0] = wd->slices2[num - 1 - wd->slices_h];
727 if ((i < wd->slices_w) && (j > 0))
728 s[1] = wd->slices[num - 1],
729 s2[1] = wd->slices2[num - 1];
730 if ((i > 0) && (j < wd->slices_h))
731 s[2] = wd->slices[num - wd->slices_h],
732 s2[2] = wd->slices2[num - wd->slices_h];
733 if ((i < wd->slices_w) && (j < wd->slices_h))
734 s[3] = wd->slices[num],
735 s2[3] = wd->slices2[num];
739 _slice_obj_vert_color_merge(s[0], 2, s[1], 3, s[2], 1, s[3], 0);
740 _slice_obj_vert_color_merge(s2[0], 3, s2[1], 2, s2[2], 0, s2[3], 1);
743 _slice_obj_vert_color_merge(s[0], 3, s[1], 2, s[2], 0, s[3], 1);
744 _slice_obj_vert_color_merge(s2[0], 2, s2[1], 3, s2[2], 1, s2[3], 0);
747 _slice_obj_vert_color_merge(s[0], 3, s[1], 2, s[2], 0, s[3], 1);
748 _slice_obj_vert_color_merge(s2[0], 2, s2[1], 3, s2[2], 1, s2[3], 0);
751 _slice_obj_vert_color_merge(s[0], 2, s[1], 3, s[2], 1, s[3], 0);
752 _slice_obj_vert_color_merge(s2[0], 3, s2[1], 2, s2[2], 0, s2[3], 1);
758 for (num = 0; num < wd->slices_h * wd->slices_w; num++)
760 _slice_3d(wd, wd->slices[num], ox, oy, ow, oh);
761 _slice_3d(wd, wd->slices2[num], ox, oy, ow, oh);
768 _state_end(Widget_Data *wd)
770 _state_slices_clear(wd);
775 flip_show_hide(Evas_Object *obj)
777 Widget_Data *wd = elm_widget_data_get(obj);
778 if (elm_flip_front_visible_get(obj))
782 if (wd->front.content)
784 evas_object_move(wd->front.content, 4999, 4999);
785 evas_object_show(wd->front.clip);
788 evas_object_hide(wd->front.clip);
789 if (wd->back.content)
790 evas_object_show(wd->back.clip);
792 evas_object_hide(wd->back.clip);
796 if (wd->front.content)
797 evas_object_show(wd->front.clip);
799 evas_object_hide(wd->front.clip);
800 evas_object_hide(wd->back.clip);
807 if (wd->front.content)
808 evas_object_show(wd->front.clip);
810 evas_object_hide(wd->front.clip);
811 if (wd->back.content)
813 evas_object_move(wd->back.content, 4999, 4999);
814 evas_object_show(wd->back.clip);
817 evas_object_hide(wd->back.clip);
821 if (wd->front.content)
822 evas_object_hide(wd->front.clip);
824 evas_object_hide(wd->front.clip);
825 if (wd->back.content)
826 evas_object_show(wd->back.clip);
828 evas_object_hide(wd->back.clip);
834 _flip_do(Evas_Object *obj, double t, Elm_Flip_Mode mode, int lin, int rev)
836 Evas_Coord x, y, w, h;
839 Evas_Coord cx, cy, px, py, foc;
840 int lx, ly, lz, lr, lg, lb, lar, lag, lab;
841 Widget_Data *wd = elm_widget_data_get(obj);
845 mf = evas_map_new(4);
846 evas_map_smooth_set(mf, EINA_FALSE);
847 mb = evas_map_new(4);
848 evas_map_smooth_set(mb, EINA_FALSE);
850 if (wd->front.content)
852 const char *type = evas_object_type_get(wd->front.content);
854 // FIXME: only handles filled obj
855 if ((type) && (!strcmp(type, "image")))
858 evas_object_image_size_get(wd->front.content, &iw, &ih);
859 evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
860 evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
861 evas_map_point_image_uv_set(mf, 0, 0, 0);
862 evas_map_point_image_uv_set(mf, 1, iw, 0);
863 evas_map_point_image_uv_set(mf, 2, iw, ih);
864 evas_map_point_image_uv_set(mf, 3, 0, ih);
868 evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
869 evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
872 if (wd->back.content)
874 const char *type = evas_object_type_get(wd->back.content);
876 if ((type) && (!strcmp(type, "image")))
879 evas_object_image_size_get(wd->back.content, &iw, &ih);
880 evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
881 evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
882 evas_map_point_image_uv_set(mb, 0, 0, 0);
883 evas_map_point_image_uv_set(mb, 1, iw, 0);
884 evas_map_point_image_uv_set(mb, 2, iw, ih);
885 evas_map_point_image_uv_set(mb, 3, 0, ih);
889 evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
890 evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
894 evas_object_geometry_get(obj, &x, &y, &w, &h);
915 case ELM_FLIP_ROTATE_Y_CENTER_AXIS:
918 if (!lin) pp = (p * p);
920 if (wd->state) deg = 180.0 * p;
921 else deg = 180 + (180.0 * p);
923 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, 0);
924 evas_map_util_3d_rotate(mb, 0.0, 180 + deg, 0.0, cx, cy, 0);
926 case ELM_FLIP_ROTATE_X_CENTER_AXIS:
929 if (!lin) pp = (p * p);
931 if (wd->state) deg = 180.0 * p;
932 else deg = 180 + (180.0 * p);
934 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, 0);
935 evas_map_util_3d_rotate(mb, 180.0 + deg, 0.0, 0.0, cx, cy, 0);
937 case ELM_FLIP_ROTATE_XZ_CENTER_AXIS:
940 if (!lin) pp = (p * p);
942 if (wd->state) deg = 180.0 * p;
943 else deg = 180 + (180.0 * p);
945 evas_map_util_3d_rotate(mf, deg, 0.0, deg, cx, cy, 0);
946 evas_map_util_3d_rotate(mb, 180 + deg, 0.0, 180 + deg, cx, cy, 0);
948 case ELM_FLIP_ROTATE_YZ_CENTER_AXIS:
951 if (!lin) pp = (p * p);
953 if (wd->state) deg = 180.0 * p;
954 else deg = 180 + (180.0 * p);
956 evas_map_util_3d_rotate(mf, 0.0, deg, deg, cx, cy, 0);
957 evas_map_util_3d_rotate(mb, 0.0, 180.0 + deg, 180.0 + deg, cx, cy, 0);
959 case ELM_FLIP_CUBE_LEFT:
962 if (!lin) pp = (p * p);
967 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
968 evas_map_util_3d_rotate(mb, 0.0, deg + 90, 0.0, cx, cy, w / 2);
972 evas_map_util_3d_rotate(mf, 0.0, deg + 90, 0.0, cx, cy, w / 2);
973 evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
976 case ELM_FLIP_CUBE_RIGHT:
979 if (!lin) pp = (p * p);
984 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
985 evas_map_util_3d_rotate(mb, 0.0, deg - 90, 0.0, cx, cy, w / 2);
989 evas_map_util_3d_rotate(mf, 0.0, deg - 90, 0.0, cx, cy, w / 2);
990 evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
993 case ELM_FLIP_CUBE_UP:
996 if (!lin) pp = (p * p);
1001 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1002 evas_map_util_3d_rotate(mb, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1006 evas_map_util_3d_rotate(mf, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1007 evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1010 case ELM_FLIP_CUBE_DOWN:
1013 if (!lin) pp = (p * p);
1018 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1019 evas_map_util_3d_rotate(mb, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1023 evas_map_util_3d_rotate(mf, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1024 evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1027 case ELM_FLIP_PAGE_LEFT:
1029 case ELM_FLIP_PAGE_RIGHT:
1031 case ELM_FLIP_PAGE_UP:
1033 case ELM_FLIP_PAGE_DOWN:
1040 if (wd->front.content)
1042 evas_map_util_3d_lighting(mf, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1043 evas_map_util_3d_perspective(mf, px, py, 0, foc);
1044 evas_object_map_set(wd->front.content, mf);
1045 evas_object_map_enable_set(wd->front.content, 1);
1046 if (evas_map_util_clockwise_get(mf)) evas_object_show(wd->front.clip);
1047 else evas_object_hide(wd->front.clip);
1050 if (wd->back.content)
1052 evas_map_util_3d_lighting(mb, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1053 evas_map_util_3d_perspective(mb, px, py, 0, foc);
1054 evas_object_map_set(wd->back.content, mb);
1055 evas_object_map_enable_set(wd->back.content, 1);
1056 if (evas_map_util_clockwise_get(mb)) evas_object_show(wd->back.clip);
1057 else evas_object_hide(wd->back.clip);
1065 _showhide(Evas_Object *obj)
1067 Widget_Data *wd = elm_widget_data_get(obj);
1068 Evas_Coord x, y, w, h;
1071 evas_object_geometry_get(obj, &x, &y, &w, &h);
1072 if (wd->front.content)
1074 if ((wd->pageflip) && (wd->state))
1076 evas_object_move(wd->front.content, 4999, 4999);
1081 evas_object_move(wd->front.content, x, y);
1083 evas_object_resize(wd->front.content, w, h);
1085 if (wd->back.content)
1087 if ((wd->pageflip) && (!wd->state))
1089 evas_object_move(wd->back.content, 4999, 4999);
1094 evas_object_move(wd->back.content, x, y);
1096 evas_object_resize(wd->back.content, w, h);
1102 _flip(Evas_Object *obj)
1104 Widget_Data *wd = elm_widget_data_get(obj);
1105 double t = ecore_loop_time_get() - wd->start;
1108 if (!wd) return ECORE_CALLBACK_CANCEL;
1109 if (!wd->animator) return ECORE_CALLBACK_CANCEL;
1112 if (t > 1.0) t = 1.0;
1114 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1115 if (wd->mode == ELM_FLIP_PAGE_LEFT)
1118 wd->started = EINA_TRUE;
1119 wd->pageflip = EINA_TRUE;
1122 wd->x = (1.0 - t) * wd->down_x;
1124 flip_show_hide(obj);
1127 else if (wd->mode == ELM_FLIP_PAGE_RIGHT)
1130 wd->started = EINA_TRUE;
1131 wd->pageflip = EINA_TRUE;
1136 flip_show_hide(obj);
1139 else if (wd->mode == ELM_FLIP_PAGE_UP)
1142 wd->started = EINA_TRUE;
1143 wd->pageflip = EINA_TRUE;
1147 wd->y = (1.0 - t) * wd->down_y;
1148 flip_show_hide(obj);
1151 else if (wd->mode == ELM_FLIP_PAGE_DOWN)
1154 wd->started = EINA_TRUE;
1155 wd->pageflip = EINA_TRUE;
1160 flip_show_hide(obj);
1164 _flip_do(obj, t, wd->mode, 0, 0);
1168 wd->pageflip = EINA_FALSE;
1170 evas_object_map_enable_set(wd->front.content, 0);
1171 evas_object_map_enable_set(wd->back.content, 0);
1172 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1173 evas_object_resize(wd->front.content, 0, 0);
1174 evas_object_resize(wd->back.content, 0, 0);
1175 evas_smart_objects_calculate(evas_object_evas_get(obj));
1177 wd->animator = NULL;
1178 wd->state = !wd->state;
1180 flip_show_hide(obj);
1181 evas_object_smart_callback_call(obj, SIG_ANIMATE_DONE, NULL);
1182 return ECORE_CALLBACK_CANCEL;
1184 return ECORE_CALLBACK_RENEW;
1188 _configure(Evas_Object *obj)
1190 Widget_Data *wd = elm_widget_data_get(obj);
1191 Evas_Coord x, y, w, h;
1196 evas_object_geometry_get(obj, &x, &y, &w, &h);
1197 // FIXME: manual flip wont get fixed
1198 if (wd->animator) _flip(obj);
1202 fsize = (double)w * wd->dir_hitsize[0];
1203 elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1204 evas_object_move(wd->event[0], x, y);
1205 evas_object_resize(wd->event[0], w, fsize);
1209 fsize = (double)w * wd->dir_hitsize[1];
1210 elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1211 evas_object_move(wd->event[1], x, y + h - fsize);
1212 evas_object_resize(wd->event[1], w, fsize);
1216 fsize = (double)h * wd->dir_hitsize[2];
1217 elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1218 evas_object_move(wd->event[2], x, y);
1219 evas_object_resize(wd->event[2], fsize, h);
1223 fsize = (double)h * wd->dir_hitsize[3];
1224 elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1225 evas_object_move(wd->event[3], x + w - fsize, y);
1226 evas_object_resize(wd->event[3], fsize, h);
1231 _move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1237 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1243 _animate(void *data)
1249 _pos_get(Widget_Data *wd, int *rev, Elm_Flip_Mode *m)
1251 Evas_Coord x, y, w, h;
1254 evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
1255 switch (wd->intmode)
1257 case ELM_FLIP_INTERACTION_ROTATE:
1258 case ELM_FLIP_INTERACTION_CUBE:
1263 t = 1.0 - ((double)wd->x / (double)wd->down_x);
1266 else if (wd->dir == 1)
1269 t = 1.0 - ((double)(w - wd->x) / (double)(w - wd->down_x));
1271 else if (wd->dir == 2)
1274 t = 1.0 - ((double)wd->y / (double)wd->down_y);
1276 else if (wd->dir == 3)
1279 t = 1.0 - ((double)(h - wd->y) / (double)(h - wd->down_y));
1283 if (t < 0.0) t = 0.0;
1284 else if (t > 1.0) t = 1.0;
1286 if ((wd->dir == 0) || (wd->dir == 1))
1288 if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
1289 *m = ELM_FLIP_ROTATE_Y_CENTER_AXIS;
1290 else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
1293 *m = ELM_FLIP_CUBE_LEFT;
1295 *m = ELM_FLIP_CUBE_RIGHT;
1300 if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
1301 *m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1302 else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
1305 *m = ELM_FLIP_CUBE_UP;
1307 *m = ELM_FLIP_CUBE_DOWN;
1318 _event_anim(void *data, double pos)
1320 Widget_Data *wd = data;
1323 p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
1327 wd->x = wd->ox * (1.0 - p);
1328 else if (wd->dir == 1)
1329 wd->x = wd->ox + ((wd->w - wd->ox) * p);
1330 else if (wd->dir == 2)
1331 wd->y = wd->oy * (1.0 - p);
1332 else if (wd->dir == 3)
1333 wd->y = wd->oy + ((wd->h - wd->oy) * p);
1338 wd->x = wd->ox + ((wd->w - wd->ox) * p);
1339 else if (wd->dir == 1)
1340 wd->x = wd->ox * (1.0 - p);
1341 else if (wd->dir == 2)
1342 wd->y = wd->oy + ((wd->h - wd->oy) * p);
1343 else if (wd->dir == 3)
1344 wd->y = wd->oy * (1.0 - p);
1346 switch (wd->intmode)
1348 case ELM_FLIP_INTERACTION_NONE:
1350 case ELM_FLIP_INTERACTION_ROTATE:
1351 case ELM_FLIP_INTERACTION_CUBE:
1353 Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1355 p = _pos_get(wd, &rev, &m);
1356 _flip_do(wd->obj, p, m, 1, rev);
1359 case ELM_FLIP_INTERACTION_PAGE:
1360 wd->pageflip = EINA_TRUE;
1367 if (pos < 1.0) return ECORE_CALLBACK_RENEW;
1369 wd->pageflip = EINA_FALSE;
1371 evas_object_map_enable_set(wd->front.content, 0);
1372 evas_object_map_enable_set(wd->back.content, 0);
1373 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1374 evas_object_resize(wd->front.content, 0, 0);
1375 evas_object_resize(wd->back.content, 0, 0);
1376 evas_smart_objects_calculate(evas_object_evas_get(wd->obj));
1378 wd->animator = NULL;
1379 if (wd->finish) wd->state = !wd->state;
1380 flip_show_hide(wd->obj);
1381 _configure(wd->obj);
1382 wd->animator = NULL;
1383 evas_object_smart_callback_call(wd->obj, SIG_ANIMATE_DONE, NULL);
1385 return ECORE_CALLBACK_CANCEL;
1389 _update_job(void *data)
1391 Widget_Data *wd = data;
1393 Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1397 switch (wd->intmode)
1399 case ELM_FLIP_INTERACTION_ROTATE:
1400 case ELM_FLIP_INTERACTION_CUBE:
1401 p = _pos_get(wd, &rev, &m);
1402 _flip_do(wd->obj, p, m, 1, rev);
1404 case ELM_FLIP_INTERACTION_PAGE:
1405 wd->pageflip = EINA_TRUE;
1415 _down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1417 Evas_Object *fl = data;
1418 Widget_Data *wd = elm_widget_data_get(fl);
1419 Evas_Event_Mouse_Down *ev = event_info;
1420 Evas_Coord x, y, w, h;
1423 if (ev->button != 1) return;
1424 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1427 ecore_animator_del(wd->animator);
1428 wd->animator = NULL;
1430 wd->down = EINA_TRUE;
1431 wd->started = EINA_FALSE;
1432 evas_object_geometry_get(data, &x, &y, &w, &h);
1433 wd->x = ev->canvas.x - x;
1434 wd->y = ev->canvas.y - y;
1442 _up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1444 Evas_Object *fl = data;
1445 Widget_Data *wd = elm_widget_data_get(fl);
1446 Evas_Event_Mouse_Up *ev = event_info;
1447 Evas_Coord x, y, w, h;
1451 if (ev->button != 1) return;
1452 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1454 evas_object_geometry_get(data, &x, &y, &w, &h);
1455 wd->x = ev->canvas.x - x;
1456 wd->y = ev->canvas.y - y;
1463 ecore_job_del(wd->job);
1466 wd->finish = EINA_FALSE;
1469 tm = (double)wd->x / (double)wd->w;
1470 if (wd->x < (wd->w / 2)) wd->finish = EINA_TRUE;
1472 else if (wd->dir == 1)
1474 if (wd->x > (wd->w / 2)) wd->finish = EINA_TRUE;
1475 tm = 1.0 - ((double)wd->x / (double)wd->w);
1477 else if (wd->dir == 2)
1479 if (wd->y < (wd->h / 2)) wd->finish = EINA_TRUE;
1480 tm = (double)wd->y / (double)wd->h;
1482 else if (wd->dir == 3)
1484 if (wd->y > (wd->h / 2)) wd->finish = EINA_TRUE;
1485 tm = 1.0 - ((double)wd->y / (double)wd->h);
1487 if (tm < 0.01) tm = 0.01;
1488 else if (tm > 0.99) tm = 0.99;
1489 if (!wd->finish) tm = 1.0 - tm;
1490 tm *= 1.0; // FIXME: config for anim time
1491 if (wd->animator) ecore_animator_del(wd->animator);
1492 wd->animator = ecore_animator_timeline_add(tm, _event_anim, wd);
1493 _event_anim(wd, 0.0);
1497 _move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1499 Evas_Object *fl = data;
1500 Widget_Data *wd = elm_widget_data_get(fl);
1501 Evas_Event_Mouse_Move *ev = event_info;
1502 Evas_Coord x, y, w, h;
1505 if (!wd->down) return;
1506 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1507 evas_object_geometry_get(data, &x, &y, &w, &h);
1508 wd->x = ev->cur.canvas.x - x;
1509 wd->y = ev->cur.canvas.y - y;
1516 dx = wd->x - wd->down_x;
1517 dy = wd->y - wd->down_y;
1518 if (((dx * dx) + (dy * dy)) >
1519 (_elm_config->finger_size * _elm_config->finger_size / 4))
1522 if ((wd->x > (w / 2)) &&
1523 (dx < 0) && (abs(dx) > abs(dy)))
1524 wd->dir = 0; // left
1525 else if ((wd->x < (w / 2)) && (dx >= 0) &&
1526 (abs(dx) > abs(dy)))
1527 wd->dir = 1; // right
1528 else if ((wd->y > (h / 2)) && (dy < 0) && (abs(dy) >= abs(dx)))
1530 else if ((wd->y < (h / 2)) && (dy >= 0) && (abs(dy) >= abs(dx)))
1531 wd->dir = 3; // down
1532 wd->started = EINA_TRUE;
1533 if (wd->intmode == ELM_FLIP_INTERACTION_PAGE)
1534 wd->pageflip = EINA_TRUE;
1535 flip_show_hide(data);
1536 evas_smart_objects_calculate(evas_object_evas_get(data));
1538 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1539 evas_object_map_enable_set(wd->front.content, EINA_FALSE);
1540 evas_object_map_enable_set(wd->back.content, EINA_FALSE);
1541 // FIXME: XXX why does this bork interactive flip??
1542 // evas_object_resize(wd->front.content, 0, 0);
1543 // evas_object_resize(wd->back.content, 0, 0);
1544 evas_smart_objects_calculate(evas_object_evas_get(data));
1547 evas_object_smart_callback_call(obj, SIG_ANIMATE_BEGIN, NULL);
1551 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1552 if (wd->job) ecore_job_del(wd->job);
1553 wd->job = ecore_job_add(_update_job, wd);
1557 _flip_content_front_set(Evas_Object *obj, Evas_Object *content)
1559 Widget_Data *wd = elm_widget_data_get(obj);
1564 if (wd->front.content == content) return;
1565 if (wd->front.content) evas_object_del(wd->front.content);
1566 wd->front.content = content;
1569 elm_widget_sub_object_add(obj, content);
1570 evas_object_smart_member_add(content, obj);
1571 evas_object_clip_set(content, wd->front.clip);
1572 evas_object_event_callback_add(content,
1573 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1574 _changed_size_hints, obj);
1578 // force calc to contents are the right size before transition
1579 evas_smart_objects_calculate(evas_object_evas_get(obj));
1580 flip_show_hide(obj);
1582 if (wd->intmode != ELM_FLIP_INTERACTION_NONE)
1584 for (i = 0; i < 4; i++) evas_object_raise(wd->event[i]);
1589 _flip_content_back_set(Evas_Object *obj, Evas_Object *content)
1591 Widget_Data *wd = elm_widget_data_get(obj);
1595 if (wd->back.content == content) return;
1596 if (wd->back.content) evas_object_del(wd->back.content);
1597 wd->back.content = content;
1600 elm_widget_sub_object_add(obj, content);
1601 evas_object_smart_member_add(content, obj);
1602 evas_object_clip_set(content, wd->back.clip);
1603 evas_object_event_callback_add(content,
1604 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1605 _changed_size_hints, obj);
1609 // force calc to contents are the right size before transition
1610 evas_smart_objects_calculate(evas_object_evas_get(obj));
1611 flip_show_hide(obj);
1613 if (wd->intmode != ELM_FLIP_INTERACTION_NONE)
1615 for (i = 0; i < 4; i++) evas_object_raise(wd->event[i]);
1619 static Evas_Object *
1620 _content_front_unset(Evas_Object *obj)
1622 Widget_Data *wd = elm_widget_data_get(obj);
1623 if ((!wd) || (!wd->front.content)) return NULL;
1625 Evas_Object *content = wd->front.content;
1626 evas_object_clip_unset(content);
1627 elm_widget_sub_object_del(obj, content);
1628 evas_object_event_callback_del_full(content,
1629 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1630 _changed_size_hints, obj);
1631 evas_object_smart_member_del(content);
1632 wd->front.content = NULL;
1636 static Evas_Object *
1637 _content_back_unset(Evas_Object *obj)
1639 Widget_Data *wd = elm_widget_data_get(obj);
1640 if ((!wd) || (!wd->back.content)) return NULL;
1642 Evas_Object *content = wd->back.content;
1643 evas_object_clip_unset(content);
1644 elm_widget_sub_object_del(obj, content);
1645 evas_object_event_callback_del_full(content,
1646 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1647 _changed_size_hints, obj);
1648 evas_object_smart_member_del(content);
1649 wd->back.content = NULL;
1654 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
1656 ELM_CHECK_WIDTYPE(obj, widtype);
1658 if (!part || !strcmp(part, "front"))
1659 _flip_content_front_set(obj, content);
1660 else if (!strcmp(part, "back"))
1661 _flip_content_back_set(obj, content);
1664 static Evas_Object *
1665 _content_get_hook(const Evas_Object *obj, const char *part)
1667 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1668 Widget_Data *wd = elm_widget_data_get(obj);
1669 if (!wd) return NULL;
1671 if (!part || !strcmp(part, "front"))
1672 return wd->front.content;
1673 else if (!strcmp(part, "back"))
1674 return wd->back.content;
1679 static Evas_Object *
1680 _content_unset_hook(Evas_Object *obj, const char *part)
1682 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1684 if (!part || !strcmp(part, "front"))
1685 return _content_front_unset(obj);
1686 else if (!strcmp(part, "back"))
1687 return _content_back_unset(obj);
1693 elm_flip_add(Evas_Object *parent)
1699 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1701 ELM_SET_WIDTYPE(widtype, "flip");
1702 elm_widget_type_set(obj, "flip");
1703 elm_widget_sub_object_add(parent, obj);
1704 elm_widget_data_set(obj, wd);
1705 elm_widget_del_hook_set(obj, _del_hook);
1706 elm_widget_theme_hook_set(obj, _theme_hook);
1707 elm_widget_focus_next_hook_set(obj, _elm_flip_focus_next_hook);
1708 elm_widget_can_focus_set(obj, EINA_FALSE);
1709 elm_widget_content_set_hook_set(obj, _content_set_hook);
1710 elm_widget_content_get_hook_set(obj, _content_get_hook);
1711 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1715 wd->clip = evas_object_rectangle_add(e);
1716 evas_object_static_clip_set(wd->clip, EINA_TRUE);
1717 evas_object_color_set(wd->clip, 255, 255, 255, 255);
1718 evas_object_move(wd->clip, -49999, -49999);
1719 evas_object_resize(wd->clip, 99999, 99999);
1720 elm_widget_sub_object_add(obj, wd->clip);
1721 evas_object_clip_set(wd->clip, evas_object_clip_get(obj));
1722 evas_object_smart_member_add(wd->clip, obj);
1724 wd->front.clip = evas_object_rectangle_add(e);
1725 evas_object_static_clip_set(wd->front.clip, EINA_TRUE);
1726 evas_object_data_set(wd->front.clip, "_elm_leaveme", obj);
1727 evas_object_color_set(wd->front.clip, 255, 255, 255, 255);
1728 evas_object_move(wd->front.clip, -49999, -49999);
1729 evas_object_resize(wd->front.clip, 99999, 99999);
1730 elm_widget_sub_object_add(obj, wd->front.clip);
1731 evas_object_smart_member_add(wd->front.clip, obj);
1732 evas_object_clip_set(wd->front.clip, wd->clip);
1734 wd->back.clip = evas_object_rectangle_add(e);
1735 evas_object_static_clip_set(wd->back.clip, EINA_TRUE);
1736 evas_object_data_set(wd->back.clip, "_elm_leaveme", obj);
1737 evas_object_color_set(wd->back.clip, 255, 255, 255, 255);
1738 evas_object_move(wd->back.clip, -49999, -49999);
1739 evas_object_resize(wd->back.clip, 99999, 99999);
1740 elm_widget_sub_object_add(wd->back.clip, obj);
1741 evas_object_smart_member_add(obj, wd->back.clip);
1742 evas_object_clip_set(wd->back.clip, wd->clip);
1744 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1745 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL);
1746 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
1747 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1748 _changed_size_hints, obj);;
1750 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1752 wd->state = EINA_TRUE;
1753 wd->intmode = ELM_FLIP_INTERACTION_NONE;
1761 elm_flip_front_visible_get(const Evas_Object *obj)
1763 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1764 Widget_Data *wd = elm_widget_data_get(obj);
1765 if (!wd) return EINA_FALSE;
1770 elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
1772 ELM_CHECK_WIDTYPE(obj, widtype);
1773 Widget_Data *wd = elm_widget_data_get(obj);
1777 // FIXME: add ambient and lighting control
1780 elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode)
1782 ELM_CHECK_WIDTYPE(obj, widtype);
1783 Widget_Data *wd = elm_widget_data_get(obj);
1785 if (!wd->animator) wd->animator = ecore_animator_add(_animate, obj);
1786 flip_show_hide(obj);
1788 wd->start = ecore_loop_time_get();
1789 wd->len = 0.5; // FIXME: make config val
1790 if ((wd->mode == ELM_FLIP_PAGE_LEFT) ||
1791 (wd->mode == ELM_FLIP_PAGE_RIGHT) ||
1792 (wd->mode == ELM_FLIP_PAGE_UP) ||
1793 (wd->mode == ELM_FLIP_PAGE_DOWN))
1794 wd->pageflip = EINA_TRUE;
1795 // force calc to contents are the right size before transition
1796 evas_smart_objects_calculate(evas_object_evas_get(obj));
1798 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1799 evas_object_map_enable_set(wd->front.content, 0);
1800 evas_object_map_enable_set(wd->back.content, 0);
1801 evas_object_resize(wd->front.content, 0, 0);
1802 evas_object_resize(wd->back.content, 0, 0);
1803 evas_smart_objects_calculate(evas_object_evas_get(obj));
1806 evas_object_smart_callback_call(obj, SIG_ANIMATE_BEGIN, NULL);
1810 elm_flip_interaction_set(Evas_Object *obj, Elm_Flip_Interaction mode)
1812 ELM_CHECK_WIDTYPE(obj, widtype);
1814 Widget_Data *wd = elm_widget_data_get(obj);
1816 if (wd->intmode == mode) return;
1818 for (i = 0; i < 4; i++)
1820 if (wd->intmode == ELM_FLIP_INTERACTION_NONE)
1824 evas_object_del(wd->event[i]);
1825 wd->event[i] = NULL;
1830 if ((wd->dir_enabled[i]) && (!wd->event[i]))
1832 Evas *e = evas_object_evas_get(obj);
1833 wd->event[i] = evas_object_rectangle_add(e);
1834 elm_widget_sub_object_add(obj, wd->event[i]);
1835 evas_object_clip_set(wd->event[i], evas_object_clip_get(obj));
1836 evas_object_color_set(wd->event[i], 0, 0, 0, 0);
1837 evas_object_show(wd->event[i]);
1838 evas_object_smart_member_add(wd->event[i], obj);
1839 evas_object_event_callback_add(wd->event[i],
1840 EVAS_CALLBACK_MOUSE_DOWN,
1842 evas_object_event_callback_add(wd->event[i],
1843 EVAS_CALLBACK_MOUSE_UP,
1845 evas_object_event_callback_add(wd->event[i],
1846 EVAS_CALLBACK_MOUSE_MOVE,
1855 EAPI Elm_Flip_Interaction
1856 elm_flip_interaction_get(const Evas_Object *obj)
1858 ELM_CHECK_WIDTYPE(obj, widtype) ELM_FLIP_INTERACTION_NONE;
1859 Widget_Data *wd = elm_widget_data_get(obj);
1860 if (!wd) return ELM_FLIP_INTERACTION_NONE;
1865 elm_flip_interaction_direction_enabled_set(Evas_Object *obj, Elm_Flip_Direction dir, Eina_Bool enabled)
1867 ELM_CHECK_WIDTYPE(obj, widtype);
1868 Widget_Data *wd = elm_widget_data_get(obj);
1871 enabled = !!enabled;
1872 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1873 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1874 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1875 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1877 if (wd->dir_enabled[i] == enabled) return;
1878 wd->dir_enabled[i] = enabled;
1879 if (wd->intmode == ELM_FLIP_INTERACTION_NONE) return;
1880 if ((wd->dir_enabled[i]) && (!wd->event[i]))
1882 wd->event[i] = evas_object_rectangle_add(evas_object_evas_get(obj));
1883 elm_widget_sub_object_add(obj, wd->event[i]);
1884 evas_object_clip_set(wd->event[i], evas_object_clip_get(obj));
1885 evas_object_color_set(wd->event[i], 0, 0, 0, 0);
1886 evas_object_show(wd->event[i]);
1887 evas_object_smart_member_add(wd->event[i], obj);
1888 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_DOWN,
1890 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_UP,
1892 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_MOVE,
1895 else if (!(wd->dir_enabled[i]) && (wd->event[i]))
1897 evas_object_del(wd->event[i]);
1898 wd->event[i] = NULL;
1905 elm_flip_interaction_direction_enabled_get(Evas_Object *obj, Elm_Flip_Direction dir)
1907 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1908 Widget_Data *wd = elm_widget_data_get(obj);
1910 if (!wd) return EINA_FALSE;
1911 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1912 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1913 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1914 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1915 if (i < 0) return EINA_FALSE;
1916 return wd->dir_enabled[i];
1920 elm_flip_interaction_direction_hitsize_set(Evas_Object *obj, Elm_Flip_Direction dir, double hitsize)
1922 ELM_CHECK_WIDTYPE(obj, widtype);
1923 Widget_Data *wd = elm_widget_data_get(obj);
1926 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1927 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1928 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1929 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1931 if (hitsize < 0.0) hitsize = 0.0;
1932 else if (hitsize > 1.0) hitsize = 1.0;
1933 if (wd->dir_hitsize[i] == hitsize) return;
1934 wd->dir_hitsize[i] = hitsize;
1940 elm_flip_interaction_direction_hitsize_get(Evas_Object *obj, Elm_Flip_Direction dir)
1942 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1943 Widget_Data *wd = elm_widget_data_get(obj);
1945 if (!wd) return 0.0;
1946 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1947 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1948 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1949 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1950 if (i < 0) return 0.0;
1951 return wd->dir_hitsize[i];