2 #include "elementary_config.h"
4 #include <Elementary.h>
5 #ifndef ELM_LIB_QUICKLAUNCH
7 /* We zoom out to this value so we'll be able to use map and have a nice
8 * resolution when zooming in. */
11 /* The amount of zoom to do when "lifting" objects. */
12 #define LIFT_FACTOR 1.3
13 /* The base size of the shadow image. */
16 //#define RAD2DEG(x) ((x) * 57.295779513)
18 #define MOMENTUM_FACTOR 30
19 #define MOMENTUM_FRICTION 1000
20 #define ROTATE_MOMENTUM_FRICTION 30
21 #define ZOOM_MOMENTUM_FRICTION 8
23 struct _Photo_Object {
24 Evas_Object *ic, *shadow;
28 /* 3 transit object to implement momentum animation */
29 Elm_Transit *zoom_momentum;
30 Ecore_Animator *rot_timer;
31 Ecore_Animator *mom_timer;
34 /* bx, by - current wanted coordinates of the photo object.
35 * bw, bh - original size of the "ic" object.
36 * dx, dy - Used to indicate the distance between the center point
37 * m_dx, m_dy - momentum delta to apply with momentum transit
38 * where we put down our fingers (when started moving the item) to
39 * the coords of the object, so we'll be able to calculate movement
41 Evas_Coord bx, by, bw, bh, dx, dy, m_dx, m_dy;
42 /* Because gesture layer only knows the amount of rotation/zoom we do
43 * per gesture, we have to keep the current rotate/zoom factor and the
44 * one that was before we started the gesture. */
45 int base_rotate, rotate; /* base - initial angle */
46 double mx, my; /* momentum on x, y */
47 double mom_x_acc, mom_y_acc;
48 double rot_momentum, zoom_mom;
51 double base_zoom, zoom;
54 typedef struct _Photo_Object Photo_Object;
57 /* This function applies the information from the Photo_Object to the actual
58 * evas objects. Zoom/rotate factors and etc. */
60 apply_changes(Photo_Object *po)
64 map = evas_map_new(4);
65 evas_map_point_coord_set(map, 0, po->bx, po->by, 0);
66 evas_map_point_coord_set(map, 1, po->bx + po->bw, po->by, 0);
67 evas_map_point_coord_set(map, 2, po->bx + po->bw, po->by + po->bh, 0);
68 evas_map_point_coord_set(map, 3, po->bx, po->by + po->bh, 0);
69 evas_map_point_image_uv_set(map, 0, 0, 0);
70 evas_map_point_image_uv_set(map, 1, po->bw, 0);
71 evas_map_point_image_uv_set(map, 2, po->bw, po->bh);
72 evas_map_point_image_uv_set(map, 3, 0, po->bh);
73 evas_map_util_rotate(map, po->rotate,
74 po->bx + po->bw / 2, po->by + po->bh /2);
75 evas_map_util_zoom(map, po->zoom, po->zoom,
76 po->bx + po->bw / 2, po->by + po->bh /2);
77 evas_object_map_enable_set(po->ic, EINA_TRUE);
78 evas_object_map_set(po->ic, map);
81 Evas_Map *shadow_map = evas_map_new(4);
82 evas_map_point_coord_set(shadow_map, 0, po->bx, po->by, 0);
83 evas_map_point_coord_set(shadow_map, 1, po->bx + po->bw, po->by, 0);
84 evas_map_point_coord_set(shadow_map, 2,
85 po->bx + po->bw, po->by + po->bh, 0);
86 evas_map_point_coord_set(shadow_map, 3, po->bx, po->by + po->bh, 0);
87 evas_map_point_image_uv_set(shadow_map, 0, 0, 0);
88 evas_map_point_image_uv_set(shadow_map, 1, SHADOW_W, 0);
89 evas_map_point_image_uv_set(shadow_map, 2, SHADOW_W, SHADOW_H);
90 evas_map_point_image_uv_set(shadow_map, 3, 0, SHADOW_H);
91 evas_map_util_rotate(shadow_map, po->rotate,
92 po->bx + po->bw / 2, po->by + po->bh /2);
93 evas_map_util_zoom(shadow_map, po->zoom * po->shadow_zoom,
94 po->zoom * po->shadow_zoom,
95 po->bx + (po->bw / 2), po->by + (po->bh / 2));
96 evas_object_map_enable_set(po->shadow, EINA_TRUE);
97 evas_object_map_set(po->shadow, shadow_map);
98 evas_map_free(shadow_map);
101 /* Update the position of the hit box */
103 Evas_Coord minx, miny, maxx, maxy;
105 evas_object_polygon_points_clear(po->hit);
106 evas_map_point_coord_get(map, 0, &minx, &miny, NULL);
109 evas_object_polygon_point_add(po->hit, minx, miny);
110 for (i = 1 ; i <= 3 ; i++)
113 evas_map_point_coord_get(map, i, &x, &y, NULL);
114 evas_object_polygon_point_add(po->hit, x, y);
127 evas_object_raise(po->shadow);
128 evas_object_raise(po->ic);
129 evas_object_raise(po->hit);
133 /* Zoom momentum animation */
135 zoom_momentum_animation_operation(void *_po, Elm_Transit *transit __UNUSED__,
138 Photo_Object *po = (Photo_Object *) _po;
139 double time_prog = po->zoom_mom_time * progress;
140 double zoom_fric = ZOOM_MOMENTUM_FRICTION;
142 if (po->zoom_mom > 0)
145 /* Current = rot0 + (rotv0 * t) + (a * t^2 / 2) */
146 po->zoom = po->base_zoom +
147 ((po->zoom_mom * time_prog) +
148 (zoom_fric * (time_prog * time_prog) / 2));
149 printf("%f = %f + (%f + %f)\n", po->zoom, po->base_zoom,
150 (po->zoom_mom * time_prog),
151 (zoom_fric * (time_prog * time_prog) / 2));
153 if (po->zoom < MIN_ZOOM)
160 zoom_momentum_animation_end(void *_po, Elm_Transit *transit __UNUSED__)
162 Photo_Object *po = (Photo_Object *) _po;
163 po->base_zoom = po->zoom;
164 po->zoom_momentum = NULL;
167 /* Rotate momentum animation */
169 rotate_momentum_animation_operation(void *_po)
171 Eina_Bool rc = ECORE_CALLBACK_RENEW;
172 int deg_friction = ROTATE_MOMENTUM_FRICTION;
173 Photo_Object *po = (Photo_Object *) _po;
174 po->rot_progress += ecore_animator_frametime_get();
175 if (po->rot_progress > po->rot_tot_time)
177 po->rot_timer = NULL;
178 po->rot_progress = po->rot_tot_time;
179 rc = ECORE_CALLBACK_CANCEL;
182 if (po->rot_momentum > 0)
185 /* Current = rot0 + (rotv0 * t) + (a * t^2 / 2) */
186 po->rotate = po->base_rotate -
187 ((po->rot_momentum * po->rot_progress) +
188 (deg_friction * (po->rot_progress * po->rot_progress) / 2));
189 po->rotate = (po->rotate % 360);
192 printf("%d = %d - (%f + %f)\n", po->rotate, po->base_rotate,
193 (po->rot_momentum * po->rot_progress),
194 (deg_friction * (po->rot_progress * po->rot_progress) / 2));
196 if (rc == ECORE_CALLBACK_CANCEL)
198 po->base_rotate = po->rotate;
199 printf("%s po->rotate=<%d>\n", __func__, po->rotate);
207 pic_obj_keep_inframe(void *_po)
208 { /* Make sure middle is in the screen, if not, fix it. */
209 /* FIXME: Use actual window sizes instead of the hardcoded
211 Photo_Object *po = (Photo_Object *) _po;
214 mx = po->bx + (po->bw / 2);
215 my = po->by + (po->bh / 2);
217 po->bx = 0 - (po->bw / 2);
219 po->bx = 480 - (po->bw / 2);
222 po->by = 0 - (po->bw / 2);
224 po->by = 800 - (po->bh / 2);
227 static Evas_Event_Flags
228 rotate_start(void *_po, void *event_info)
230 Photo_Object *po = (Photo_Object *) _po;
231 Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
232 printf("rotate start <%d,%d> po->rotate=<%d> base=<%f> p->angle=<%f>\n", p->x, p->y, po->rotate,
233 p->base_angle, p->angle);
235 /* If there's an active animator, stop it */
238 po->base_rotate = po->rotate;
239 ecore_animator_del(po->rot_timer);
240 po->rot_timer = NULL;
243 return EVAS_EVENT_FLAG_NONE;
246 static Evas_Event_Flags
247 rotate_move(void *_po, void *event_info)
249 Photo_Object *po = (Photo_Object *) _po;
250 Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
251 printf("rotate move <%d,%d> base=<%f> <%f> m=<%f>\n", p->x, p->y,
252 p->base_angle, p->angle, p->momentum);
253 po->rotate = po->base_rotate + (int) (p->angle - p->base_angle);
258 return EVAS_EVENT_FLAG_NONE;
261 static Evas_Event_Flags
262 rotate_end(void *_po, void *event_info)
264 Photo_Object *po = (Photo_Object *) _po;
265 Elm_Gesture_Rotate_Info *r_info = (Elm_Gesture_Rotate_Info *) event_info;
266 printf("rotate end <%d,%d> base=<%f> <%f> m=<%f>\n", r_info->x, r_info->y,
267 r_info->base_angle, r_info->angle, r_info->momentum);
271 po->base_rotate = po->rotate;
273 /* Apply the rotate-momentum */
274 po->rot_tot_time = fabs(r_info->momentum) / ROTATE_MOMENTUM_FRICTION;
275 po->rot_momentum = r_info->momentum;
276 po->rot_progress = 0.0;
277 if (po->rot_momentum)
279 po->rot_timer = ecore_animator_add(rotate_momentum_animation_operation, po);
281 return EVAS_EVENT_FLAG_NONE;
284 static Evas_Event_Flags
285 rotate_abort(void *_po, void *event_info)
287 Photo_Object *po = (Photo_Object *) _po;
288 Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
289 printf("rotate abort <%d,%d> base=<%f> <%f>\n", p->x, p->y,
290 p->base_angle, p->angle);
291 po->base_rotate = po->rotate;
295 return EVAS_EVENT_FLAG_NONE;
298 static Evas_Event_Flags
299 zoom_start(void *_po, void *event_info)
301 Photo_Object *po = (Photo_Object *) _po;
302 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
303 printf("zoom start <%d,%d> <%f>\n", p->x, p->y, p->zoom);
305 /* If there's an active animator, stop it */
306 if (po->zoom_momentum)
308 elm_transit_del(po->zoom_momentum);
309 po->zoom_momentum = NULL;
312 return EVAS_EVENT_FLAG_NONE;
315 static Evas_Event_Flags
316 zoom_move(void *_po, void *event_info)
318 Photo_Object *po = (Photo_Object *) _po;
319 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
320 printf("zoom move <%d,%d> <%f> momentum=<%f>\n", p->x, p->y, p->zoom, p->momentum);
321 po->zoom = po->base_zoom * p->zoom;
323 return EVAS_EVENT_FLAG_NONE;
326 static Evas_Event_Flags
327 zoom_end(void *_po, void *event_info)
329 Photo_Object *po = (Photo_Object *) _po;
330 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
331 printf("zoom end/abort <%d,%d> <%f> momentum=<%f>\n", p->x, p->y,
332 p->zoom, p->momentum);
334 /* Apply the zoom-momentum or zoom out animator */
335 double tot_time = fabs(p->momentum) / ZOOM_MOMENTUM_FRICTION;
336 po->zoom_mom_time = tot_time;
337 po->zoom_mom = p->momentum;
338 po->base_zoom = po->zoom;
341 po->zoom_momentum = elm_transit_add();
342 elm_transit_duration_set(po->zoom_momentum,
344 elm_transit_effect_add(po->zoom_momentum,
345 zoom_momentum_animation_operation, po,
346 zoom_momentum_animation_end);
347 elm_transit_go(po->zoom_momentum);
350 return EVAS_EVENT_FLAG_NONE;
353 static Evas_Event_Flags
354 momentum_start(void *_po, void *event_info)
356 Photo_Object *po = (Photo_Object *) _po;
357 Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
358 printf("momentum_start po->rotate=<%d> <%d,%d>\n", po->rotate, p->x2, p->y2);
360 /* If there's an active animator, stop it */
363 ecore_animator_del(po->mom_timer);
364 po->mom_timer = NULL;
367 po->dx = p->x2 - po->bx;
368 po->dy = p->y2 - po->by;
371 return EVAS_EVENT_FLAG_NONE;
374 static Evas_Event_Flags
375 momentum_move(void *_po, void *event_info)
377 Photo_Object *po = (Photo_Object *) _po;
378 Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
379 printf("momentum move <%d,%d> fingers=<%d> mx,my=<%d,%d>\n", p->x2, p->y2, p->n, p->mx, p->my);
381 po->bx = p->x2 - po->dx;
382 po->by = p->y2 - po->dy;
385 return EVAS_EVENT_FLAG_NONE;
388 /* Momentum animation */
390 momentum_animation_operation(void *_po)
392 Photo_Object *po = (Photo_Object *) _po;
393 Eina_Bool rc = ECORE_CALLBACK_RENEW;
394 Evas_Coord x = po->bx;
395 Evas_Coord y = po->by;
396 po->mom_tot_time -= ecore_animator_frametime_get();
397 if (po->mom_tot_time <= 0)
399 po->mom_timer = NULL;
400 rc = ECORE_CALLBACK_CANCEL;
403 /* x = v0t + 0.5at^2 */
404 po->bx += ((po->mx * po->mom_tot_time) +
405 (0.5 * po->mom_x_acc * (po->mom_tot_time * po->mom_tot_time)));
407 po->by += ((po->my * po->mom_tot_time) +
408 (0.5 * po->mom_y_acc * (po->mom_tot_time * po->mom_tot_time)));
410 printf("%s prev_bx-new_bx,y=(%d,%d)\n", __func__, x-po->bx, y-po->by);
411 if (rc == ECORE_CALLBACK_CANCEL)
412 pic_obj_keep_inframe(po);
418 static Evas_Event_Flags
419 momentum_end(void *_po, void *event_info)
421 Photo_Object *po = (Photo_Object *) _po;
422 Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
423 printf("momentum end x2,y2=<%d,%d> mx,my=<%d,%d>\n", p->x2, p->y2, p->mx, p->my);
424 pic_obj_keep_inframe(po);
426 /* Make up some total-time for the movement */
427 po->mom_tot_time = sqrt((p->mx * p->mx) + (p->my * p->my))
430 if (po->mom_tot_time)
431 { /* Compute acceleration for both compenents, and launch timer */
432 po->mom_x_acc = (p->mx) / po->mom_tot_time; /* a = (v-v0) / t */
433 po->mom_y_acc = (p->my) / po->mom_tot_time; /* a = (v-v0) / t */
434 po->mom_x_acc /= MOMENTUM_FACTOR;
435 po->mom_y_acc /= MOMENTUM_FACTOR;
436 po->mom_timer = ecore_animator_add(momentum_animation_operation, po);
439 return EVAS_EVENT_FLAG_NONE;
442 static Evas_Event_Flags
443 momentum_abort(void *_po, void *event_info)
445 Photo_Object *po = (Photo_Object *) _po;
446 Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
447 printf("momentum abort <%d,%d> <%d,%d>\n", p->x2, p->y2, p->mx, p->my);
448 pic_obj_keep_inframe(po);
451 return EVAS_EVENT_FLAG_NONE;
455 _win_del_req(void *data, Evas_Object *obj __UNUSED__,
456 void *event_info __UNUSED__)
458 Photo_Object **photo_array = (Photo_Object **) data;
463 /* The content of the photo object is automatically deleted when the win
465 for ( ; *photo_array ; photo_array++)
472 static Photo_Object *
473 photo_object_add(Evas_Object *parent, Evas_Object *ic, const char *icon,
474 Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, int angle)
478 po = calloc(1, sizeof(*po));
479 po->base_zoom = po->zoom = BASE_ZOOM;
487 po->ic = elm_icon_add(parent);
488 elm_image_file_set(po->ic, icon, NULL);
498 po->shadow = elm_icon_add(po->ic);
499 snprintf(buf, sizeof(buf), "%s/images/pol_shadow.png", elm_app_data_dir_get());
500 elm_image_file_set(po->shadow, buf, NULL);
501 evas_object_resize(po->shadow, SHADOW_W, SHADOW_H);
502 evas_object_show(po->shadow);
505 po->hit = evas_object_polygon_add(evas_object_evas_get(parent));
506 evas_object_precise_is_inside_set(po->hit, EINA_TRUE);
507 evas_object_repeat_events_set(po->hit, EINA_TRUE);
508 evas_object_color_set(po->hit, 0, 0, 0, 0);
510 evas_object_move(po->ic, 0, 0);
511 evas_object_resize(po->ic, po->bw, po->bh);
512 evas_object_show(po->ic);
514 evas_object_show(po->hit);
516 po->gl = elm_gesture_layer_add(po->ic);
517 elm_gesture_layer_hold_events_set(po->gl, EINA_TRUE);
518 elm_gesture_layer_attach(po->gl, po->hit);
520 /* FIXME: Add a po->rotate start so we take the first angle!!!! */
521 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
522 ELM_GESTURE_STATE_START, momentum_start, po);
523 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
524 ELM_GESTURE_STATE_MOVE, momentum_move, po);
525 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
526 ELM_GESTURE_STATE_END, momentum_end, po);
527 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
528 ELM_GESTURE_STATE_ABORT, momentum_abort, po);
530 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
531 ELM_GESTURE_STATE_START, zoom_start, po);
532 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
533 ELM_GESTURE_STATE_MOVE, zoom_move, po);
534 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
535 ELM_GESTURE_STATE_END, zoom_end, po);
536 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
537 ELM_GESTURE_STATE_ABORT, zoom_end, po);
539 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
540 ELM_GESTURE_STATE_START, rotate_start, po);
541 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
542 ELM_GESTURE_STATE_MOVE, rotate_move, po);
543 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
544 ELM_GESTURE_STATE_END, rotate_end, po);
545 elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
546 ELM_GESTURE_STATE_ABORT, rotate_abort, po);
548 po->rotate = po->base_rotate = angle;
549 po->shadow_zoom = 1.3;
556 test_gesture_layer3(void *data __UNUSED__, Evas_Object *obj __UNUSED__,
557 void *event_info __UNUSED__)
560 Evas_Object *win, *bg;
563 Photo_Object **photo_array;
564 photo_array = calloc(sizeof(*photo_array), 4);
569 win = elm_win_add(NULL, "gesture-layer3", ELM_WIN_BASIC);
570 elm_win_title_set(win, "Gesture Layer 3");
571 elm_win_autodel_set(win, EINA_TRUE);
572 evas_object_resize(win, w, h);
574 bg = elm_bg_add(win);
575 snprintf(buf, sizeof(buf), "%s/images/wood_01.jpg", elm_app_data_dir_get());
576 elm_bg_file_set(bg, buf, NULL);
577 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
578 elm_win_resize_object_add(win, bg);
579 evas_object_show(bg);
581 snprintf(buf, sizeof(buf), "%s/images/pol_sky.png", elm_app_data_dir_get());
582 photo_array[ind++] = photo_object_add(win, NULL, buf, 50, 200, 365, 400, 0);
584 photo_array[ind] = NULL;
585 evas_object_smart_callback_add(win, "delete,request", _win_del_req,
587 evas_object_show(win);