+static double
+_pos_get(Widget_Data *wd, int *rev, Elm_Flip_Mode *m)
+{
+ Evas_Coord x, y, w, h;
+ double t = 1.0;
+
+ evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
+ switch (wd->intmode)
+ {
+ case ELM_FLIP_INTERACTION_ROTATE:
+ case ELM_FLIP_INTERACTION_CUBE:
+ {
+ if (wd->dir == 0)
+ {
+ if (wd->down_x > 0)
+ t = 1.0 - ((double)wd->x / (double)wd->down_x);
+ *rev = 1;
+ }
+ else if (wd->dir == 1)
+ {
+ if (wd->down_x < w)
+ t = 1.0 - ((double)(w - wd->x) / (double)(w - wd->down_x));
+ }
+ else if (wd->dir == 2)
+ {
+ if (wd->down_y > 0)
+ t = 1.0 - ((double)wd->y / (double)wd->down_y);
+ }
+ else if (wd->dir == 3)
+ {
+ if (wd->down_y < h)
+ t = 1.0 - ((double)(h - wd->y) / (double)(h - wd->down_y));
+ *rev = 1;
+ }
+
+ if (t < 0.0) t = 0.0;
+ else if (t > 1.0) t = 1.0;
+
+ if ((wd->dir == 0) || (wd->dir == 1))
+ {
+ if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
+ *m = ELM_FLIP_ROTATE_Y_CENTER_AXIS;
+ else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
+ {
+ if (*rev)
+ *m = ELM_FLIP_CUBE_LEFT;
+ else
+ *m = ELM_FLIP_CUBE_RIGHT;
+ }
+ }
+ else
+ {
+ if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
+ *m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
+ else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
+ {
+ if (*rev)
+ *m = ELM_FLIP_CUBE_UP;
+ else
+ *m = ELM_FLIP_CUBE_DOWN;
+ }
+ }
+ }
+ default:
+ break;
+ }
+ return t;
+}
+
+static Eina_Bool
+_event_anim(void *data, double pos)
+{
+ Widget_Data *wd = data;
+ double p;
+
+ p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
+ if (wd->finish)
+ {
+ if (wd->dir == 0)
+ wd->x = wd->ox * (1.0 - p);
+ else if (wd->dir == 1)
+ wd->x = wd->ox + ((wd->w - wd->ox) * p);
+ else if (wd->dir == 2)
+ wd->y = wd->oy * (1.0 - p);
+ else if (wd->dir == 3)
+ wd->y = wd->oy + ((wd->h - wd->oy) * p);
+ }
+ else
+ {
+ if (wd->dir == 0)
+ wd->x = wd->ox + ((wd->w - wd->ox) * p);
+ else if (wd->dir == 1)
+ wd->x = wd->ox * (1.0 - p);
+ else if (wd->dir == 2)
+ wd->y = wd->oy + ((wd->h - wd->oy) * p);
+ else if (wd->dir == 3)
+ wd->y = wd->oy * (1.0 - p);
+ }
+ switch (wd->intmode)
+ {
+ case ELM_FLIP_INTERACTION_NONE:
+ break;
+ case ELM_FLIP_INTERACTION_ROTATE:
+ case ELM_FLIP_INTERACTION_CUBE:
+ {
+ Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
+ int rev = 0;
+ p = _pos_get(wd, &rev, &m);
+ _flip_do(wd->obj, p, m, 1, rev);
+ }
+ break;
+ case ELM_FLIP_INTERACTION_PAGE:
+ /*
+ _state_update(st);
+ */
+ break;
+ default:
+ break;
+ }
+ if (pos < 1.0) return ECORE_CALLBACK_RENEW;
+
+ evas_object_map_enable_set(wd->front.content, 0);
+ evas_object_map_enable_set(wd->back.content, 0);
+ // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
+ evas_object_resize(wd->front.content, 0, 0);
+ evas_object_resize(wd->back.content, 0, 0);
+ evas_smart_objects_calculate(evas_object_evas_get(wd->obj));
+ // FIXME: end hack
+ wd->animator = NULL;
+ if (wd->finish) wd->state = !wd->state;
+ _configure(wd->obj);
+ wd->animator = NULL;
+ evas_object_smart_callback_call(wd->obj, SIG_ANIMATE_DONE, NULL);
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_update_job(void *data)
+{
+ Widget_Data *wd = data;
+ double p;
+ Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
+ int rev = 0;
+
+ wd->job = NULL;
+ switch (wd->intmode)
+ {
+ case ELM_FLIP_INTERACTION_ROTATE:
+ case ELM_FLIP_INTERACTION_CUBE:
+ p = _pos_get(wd, &rev, &m);
+ _flip_do(wd->obj, p, m, 1, rev);
+ break;
+ case ELM_FLIP_INTERACTION_PAGE:
+ /*
+ if (_state_update(st))
+ {
+ evas_object_hide(st->front);
+ evas_object_hide(st->back);
+ }
+ */
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+ Evas_Object *fl = data;
+ Widget_Data *wd = elm_widget_data_get(fl);
+ Evas_Event_Mouse_Down *ev = event_info;
+ Evas_Coord x, y, w, h;
+
+ if (!wd) return;
+ if (ev->button != 1) return;
+ if (wd->animator)
+ {
+ ecore_animator_del(wd->animator);
+ wd->animator = NULL;
+ }
+ wd->down = EINA_TRUE;
+ wd->started = EINA_FALSE;
+ evas_object_geometry_get(data, &x, &y, &w, &h);
+ wd->x = ev->canvas.x - x;
+ wd->y = ev->canvas.y - y;
+ wd->w = w;
+ wd->h = h;
+ wd->down_x = wd->x;
+ wd->down_y = wd->y;
+ printf("dn %i %i\n", wd->x, wd->y);
+}
+
+static void
+_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+ Evas_Object *fl = data;
+ Widget_Data *wd = elm_widget_data_get(fl);
+ Evas_Event_Mouse_Up *ev = event_info;
+ Evas_Coord x, y, w, h;
+ double tm = 0.5;
+
+ if (!wd) return;
+ if (ev->button != 1) return;
+ wd->down = 0;
+ evas_object_geometry_get(data, &x, &y, &w, &h);
+ wd->x = ev->canvas.x - x;
+ wd->y = ev->canvas.y - y;
+ wd->w = w;
+ wd->h = h;
+ wd->ox = wd->x;
+ wd->oy = wd->y;
+ printf("up %i %i\n", wd->x, wd->y);
+ if (wd->job)
+ {
+ ecore_job_del(wd->job);
+ wd->job = NULL;
+ }
+ wd->finish = EINA_FALSE;
+ if (wd->dir == 0)
+ {
+ tm = (double)wd->x / (double)wd->w;
+ if (wd->x < (wd->w / 2)) wd->finish = EINA_TRUE;
+ }
+ else if (wd->dir == 1)
+ {
+ if (wd->x > (wd->w / 2)) wd->finish = EINA_TRUE;
+ tm = 1.0 - ((double)wd->x / (double)wd->w);
+ }
+ else if (wd->dir == 2)
+ {
+ if (wd->y < (wd->h / 2)) wd->finish = EINA_TRUE;
+ tm = (double)wd->y / (double)wd->h;
+ }
+ else if (wd->dir == 3)
+ {
+ if (wd->y > (wd->h / 2)) wd->finish = EINA_TRUE;
+ tm = 1.0 - ((double)wd->y / (double)wd->h);
+ }
+ if (tm < 0.01) tm = 0.01;
+ else if (tm > 0.99) tm = 0.99;
+ if (!wd->finish) tm = 1.0 - tm;
+ tm *= 1.0; // FIXME: config for anim time
+ if (wd->animator) ecore_animator_del(wd->animator);
+ wd->animator = ecore_animator_timeline_add(tm, _event_anim, wd);
+ _event_anim(wd, 0.0);
+}
+
+static void
+_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+ Evas_Object *fl = data;
+ Widget_Data *wd = elm_widget_data_get(fl);
+ Evas_Event_Mouse_Move *ev = event_info;
+ Evas_Coord x, y, w, h;
+
+ if (!wd) return;
+ if (!wd->down) return;
+ evas_object_geometry_get(data, &x, &y, &w, &h);
+ wd->x = ev->cur.canvas.x - x;
+ wd->y = ev->cur.canvas.y - y;
+ wd->w = w;
+ wd->h = h;
+ if (!wd->started)
+ {
+ Evas_Coord dx, dy;
+
+ dx = wd->x - wd->down_x;
+ dy = wd->y - wd->down_y;
+ if (((dx * dx) + (dy * dy)) > (_elm_config->finger_size * _elm_config->finger_size / 4))
+ {
+ wd->dir = 0;
+ if ((wd->x > (w / 2)) && (dx < 0) && (abs(dx) > abs(dy))) wd->dir = 0; // left
+ else if ((wd->x < (w / 2)) && (dx >= 0) && (abs(dx) > abs(dy))) wd->dir = 1; // right
+ else if ((wd->y > (h / 2)) && (dy < 0) && (abs(dy) >= abs(dx))) wd->dir = 2; // up
+ else if ((wd->y < (h / 2)) && (dy >= 0) && (abs(dy) >= abs(dx))) wd->dir = 3; // down
+ wd->started = EINA_TRUE;
+ printf("START\n");
+ flip_show_hide(data);
+ evas_smart_objects_calculate(evas_object_evas_get(data));
+ _flip(data);
+ // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
+ evas_object_map_enable_set(wd->front.content, 0);
+ evas_object_map_enable_set(wd->back.content, 0);
+// evas_object_resize(wd->front.content, 0, 0);
+// evas_object_resize(wd->back.content, 0, 0);
+ evas_smart_objects_calculate(evas_object_evas_get(data));
+ _configure(obj);
+ // FIXME: end hack
+ }
+ else return;
+ }
+ printf("mv %i %i\n", wd->x, wd->y);
+ if (wd->job) ecore_job_del(wd->job);
+ wd->job = ecore_job_add(_update_job, wd);
+}
+