1 #ifdef HAVE_CONFIG_H
2 #include "elementary_config.h"
3 #endif
4 #include <Elementary.h>
5 
6 /* We zoom out to this value so we'll be able to use map and have a nice
7  * resolution when zooming in. */
8 #define BASE_ZOOM 0.8
9 #define MIN_ZOOM 0.4
10 /* The amount of zoom to do when "lifting" objects. */
11 #define LIFT_FACTOR 1.3
12 /* The base size of the shadow image. */
13 #define SHADOW_W 118
14 #define SHADOW_H 118
15 //#define RAD2DEG(x) ((x) * 57.295779513)
16 
17 #define MOMENTUM_FACTOR 30
18 #define MOMENTUM_FRICTION 1000
19 #define ROTATE_MOMENTUM_FRICTION 30
20 #define ZOOM_MOMENTUM_FRICTION 8
21 
22 struct _Photo_Object {
23      Evas_Object *ic, *shadow;
24      Evas_Object *hit;
25      Evas_Object *gl;
26 
27      /* 3 transit object to implement momentum animation */
28      Elm_Transit *zoom_momentum;
29      Ecore_Animator *rot_timer;
30      Ecore_Animator *mom_timer;
31      double rot_tot_time;
32      double rot_progress;
33      /* bx, by - current wanted coordinates of the photo object.
34       * bw, bh - original size of the "ic" object.
35       * dx, dy - Used to indicate the distance between the center point
36       * m_dx, m_dy - momentum delta to apply with momentum transit
37       * where we put down our fingers (when started moving the item) to
38       * the coords of the object, so we'll be able to calculate movement
39       * correctly. */
40      Evas_Coord bx, by, bw, bh, dx, dy, m_dx, m_dy;
41      /* Because gesture layer only knows the amount of rotation/zoom we do
42       * per gesture, we have to keep the current rotate/zoom factor and the
43       * one that was before we started the gesture. */
44      int base_rotate, rotate;  /* base - initial angle */
45      double mx, my; /* momentum on x, y */
46      double mom_x_acc, mom_y_acc;
47      double rot_momentum, zoom_mom;
48      double mom_tot_time;
49      double zoom_mom_time;
50      double base_zoom, zoom;
51      double shadow_zoom;
52 };
53 typedef struct _Photo_Object Photo_Object;
54 
55 /* This function applies the information from the Photo_Object to the actual
56  * evas objects. Zoom/rotate factors and etc. */
57 static void
apply_changes(Photo_Object * po)58 apply_changes(Photo_Object *po)
59 {
60    Evas_Map *map;
61 
62    map = evas_map_new(4);
63    evas_map_point_coord_set(map, 0, po->bx, po->by, 0);
64    evas_map_point_coord_set(map, 1, po->bx + po->bw, po->by, 0);
65    evas_map_point_coord_set(map, 2, po->bx + po->bw, po->by + po->bh, 0);
66    evas_map_point_coord_set(map, 3, po->bx, po->by + po->bh, 0);
67    evas_map_point_image_uv_set(map, 0, 0, 0);
68    evas_map_point_image_uv_set(map, 1, po->bw, 0);
69    evas_map_point_image_uv_set(map, 2, po->bw, po->bh);
70    evas_map_point_image_uv_set(map, 3, 0, po->bh);
71    evas_map_util_rotate(map, po->rotate,
72          po->bx + po->bw / 2, po->by + po->bh /2);
73    evas_map_util_zoom(map, po->zoom, po->zoom,
74          po->bx + po->bw / 2, po->by + po->bh /2);
75    evas_object_map_enable_set(po->ic, EINA_TRUE);
76    evas_object_map_set(po->ic, map);
77 
78      {
79         Evas_Map *shadow_map = evas_map_new(4);
80         evas_map_point_coord_set(shadow_map, 0, po->bx, po->by, 0);
81         evas_map_point_coord_set(shadow_map, 1, po->bx + po->bw, po->by, 0);
82         evas_map_point_coord_set(shadow_map, 2,
83               po->bx + po->bw, po->by + po->bh, 0);
84         evas_map_point_coord_set(shadow_map, 3, po->bx, po->by + po->bh, 0);
85         evas_map_point_image_uv_set(shadow_map, 0, 0, 0);
86         evas_map_point_image_uv_set(shadow_map, 1, SHADOW_W, 0);
87         evas_map_point_image_uv_set(shadow_map, 2, SHADOW_W, SHADOW_H);
88         evas_map_point_image_uv_set(shadow_map, 3, 0, SHADOW_H);
89         evas_map_util_rotate(shadow_map, po->rotate,
90               po->bx + po->bw / 2, po->by + po->bh /2);
91         evas_map_util_zoom(shadow_map, po->zoom * po->shadow_zoom,
92               po->zoom * po->shadow_zoom,
93               po->bx + (po->bw / 2), po->by + (po->bh / 2));
94         evas_object_map_enable_set(po->shadow, EINA_TRUE);
95         evas_object_map_set(po->shadow, shadow_map);
96         evas_map_free(shadow_map);
97      }
98 
99    /* Update the position of the hit box */
100      {
101         Evas_Coord minx, miny, maxx, maxy;
102         int i;
103         evas_object_polygon_points_clear(po->hit);
104         evas_map_point_coord_get(map, 0, &minx, &miny, NULL);
105         maxx = minx;
106         maxy = miny;
107         evas_object_polygon_point_add(po->hit, minx, miny);
108         for (i = 1 ; i <= 3 ; i++)
109           {
110              Evas_Coord x, y;
111              evas_map_point_coord_get(map, i, &x, &y, NULL);
112              evas_object_polygon_point_add(po->hit, x, y);
113              if (x < minx)
114                 minx = x;
115              else if (x > maxx)
116                 maxx = x;
117 
118              if (y < miny)
119                 miny = y;
120              else if (y > maxy)
121                 maxy = y;
122           }
123      }
124 
125    evas_object_raise(po->shadow);
126    evas_object_raise(po->ic);
127    evas_object_raise(po->hit);
128    evas_map_free(map);
129 }
130 
131 /* Zoom momentum animation */
132 static void
zoom_momentum_animation_operation(void * _po,Elm_Transit * transit EINA_UNUSED,double progress)133 zoom_momentum_animation_operation(void *_po, Elm_Transit *transit EINA_UNUSED,
134       double progress)
135 {
136    Photo_Object *po = (Photo_Object *) _po;
137    double time_prog = po->zoom_mom_time * progress;
138    double zoom_fric = ZOOM_MOMENTUM_FRICTION;
139 
140    if (po->zoom_mom > 0)
141      zoom_fric *= -1;
142 
143    /* Current = rot0 + (rotv0 * t) + (a * t^2 / 2) */
144    po->zoom = po->base_zoom +
145       ((po->zoom_mom * time_prog) +
146       (zoom_fric * (time_prog * time_prog) / 2));
147    printf("%f = %f + (%f + %f)\n", po->zoom, po->base_zoom,
148          (po->zoom_mom * time_prog),
149          (zoom_fric * (time_prog * time_prog) / 2));
150 
151    if (po->zoom < MIN_ZOOM)
152      po->zoom = MIN_ZOOM;
153 
154    apply_changes(po);
155 }
156 
157 static void
zoom_momentum_animation_end(void * _po,Elm_Transit * transit EINA_UNUSED)158 zoom_momentum_animation_end(void *_po, Elm_Transit *transit EINA_UNUSED)
159 {
160    Photo_Object *po = (Photo_Object *) _po;
161    po->base_zoom = po->zoom;
162    po->zoom_momentum = NULL;
163 }
164 
165 /* Rotate momentum animation */
166 static Eina_Bool
rotate_momentum_animation_operation(void * _po)167 rotate_momentum_animation_operation(void *_po)
168 {
169    Eina_Bool rc = ECORE_CALLBACK_RENEW;
170    int deg_friction = ROTATE_MOMENTUM_FRICTION;
171    Photo_Object *po = (Photo_Object *) _po;
172    po->rot_progress += ecore_animator_frametime_get();
173    if (po->rot_progress > po->rot_tot_time)
174      {
175         po->rot_timer = NULL;
176         po->rot_progress = po->rot_tot_time;
177         rc = ECORE_CALLBACK_CANCEL;
178      }
179 
180    if (po->rot_momentum > 0)
181      deg_friction *= -1;
182 
183    /* Current = rot0 + (rotv0 * t) + (a * t^2 / 2) */
184    po->rotate = po->base_rotate -
185       ((po->rot_momentum * po->rot_progress) +
186       (deg_friction * (po->rot_progress * po->rot_progress) / 2));
187    po->rotate = (po->rotate % 360);
188    if (po->rotate < 0)
189      po->rotate += 360;
190    printf("%d = %d - (%f + %f)\n", po->rotate, po->base_rotate,
191          (po->rot_momentum * po->rot_progress),
192          (deg_friction * (po->rot_progress * po->rot_progress) / 2));
193 
194    if (rc == ECORE_CALLBACK_CANCEL)
195      {
196         po->base_rotate = po->rotate;
197         printf("%s po->rotate=<%d>\n", __func__, po->rotate);
198      }
199 
200    apply_changes(po);
201    return rc;
202 }
203 
204 static void
pic_obj_keep_inframe(void * _po)205 pic_obj_keep_inframe(void *_po)
206 {  /* Make sure middle is in the screen, if not, fix it. */
207    /* FIXME: Use actual window sizes instead of the hardcoded
208     * values */
209    Photo_Object *po = (Photo_Object *) _po;
210 
211    Evas_Coord mx, my;
212    mx = po->bx + (po->bw / 2);
213    my = po->by + (po->bh / 2);
214    if (mx < 0)
215      po->bx = 0 - (po->bw / 2);
216    else if (mx > 480)
217      po->bx = 480 - (po->bw / 2);
218 
219    if (my < 0)
220      po->by = 0 - (po->bh / 2);
221    else if (my > 800)
222      po->by = 800 - (po->bh / 2);
223 }
224 
225 static Evas_Event_Flags
rotate_start(void * _po,void * event_info)226 rotate_start(void *_po, void *event_info)
227 {
228    Photo_Object *po = (Photo_Object *) _po;
229    Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
230    printf("rotate start <%d,%d> po->rotate=<%d> base=<%f> p->angle=<%f>\n", p->x, p->y, po->rotate,
231          p->base_angle, p->angle);
232 
233    /* If there's an active animator, stop it */
234    if (po->rot_timer)
235      {
236         po->base_rotate = po->rotate;
237         ecore_animator_del(po->rot_timer);
238         po->rot_timer = NULL;
239      }
240 
241    return EVAS_EVENT_FLAG_NONE;
242 }
243 
244 static Evas_Event_Flags
rotate_move(void * _po,void * event_info)245 rotate_move(void *_po, void *event_info)
246 {
247    Photo_Object *po = (Photo_Object *) _po;
248    Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
249    printf("rotate move <%d,%d> base=<%f> <%f> m=<%f>\n", p->x, p->y,
250          p->base_angle, p->angle, p->momentum);
251    po->rotate = po->base_rotate + (int) (p->angle - p->base_angle);
252 
253    if (po->rotate < 0)
254       po->rotate += 360;
255    apply_changes(po);
256    return EVAS_EVENT_FLAG_NONE;
257 }
258 
259 static Evas_Event_Flags
rotate_end(void * _po,void * event_info)260 rotate_end(void *_po, void *event_info)
261 {
262    Photo_Object *po = (Photo_Object *) _po;
263    Elm_Gesture_Rotate_Info *r_info = (Elm_Gesture_Rotate_Info *) event_info;
264    printf("rotate end <%d,%d> base=<%f> <%f> m=<%f>\n", r_info->x, r_info->y,
265          r_info->base_angle, r_info->angle, r_info->momentum);
266    if (po->rotate < 0)
267       po->rotate += 360;
268 
269    po->base_rotate = po->rotate;
270 
271    /* Apply the rotate-momentum */
272    po->rot_tot_time = fabs(r_info->momentum) / ROTATE_MOMENTUM_FRICTION;
273    po->rot_momentum = r_info->momentum;
274    po->rot_progress = 0.0;
275    if (EINA_DBL_NONZERO(po->rot_momentum))
276      {
277         po->rot_timer = ecore_animator_add(rotate_momentum_animation_operation, po);
278      }
279    return EVAS_EVENT_FLAG_NONE;
280 }
281 
282 static Evas_Event_Flags
rotate_abort(void * _po,void * event_info)283 rotate_abort(void *_po, void *event_info)
284 {
285    Photo_Object *po = (Photo_Object *) _po;
286    Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
287    printf("rotate abort <%d,%d> base=<%f> <%f>\n", p->x, p->y,
288          p->base_angle, p->angle);
289    po->base_rotate = po->rotate;
290    if (po->rotate < 0)
291       po->rotate += 360;
292 
293    return EVAS_EVENT_FLAG_NONE;
294 }
295 
296 static Evas_Event_Flags
zoom_start(void * _po,void * event_info)297 zoom_start(void *_po, void *event_info)
298 {
299    Photo_Object *po = (Photo_Object *) _po;
300    Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
301    printf("zoom start <%d,%d> <%f>\n", p->x, p->y, p->zoom);
302 
303    /* If there's an active animator, stop it */
304    if (po->zoom_momentum)
305      {
306         elm_transit_del(po->zoom_momentum);
307         po->zoom_momentum = NULL;
308      }
309 
310    return EVAS_EVENT_FLAG_NONE;
311 }
312 
313 static Evas_Event_Flags
zoom_move(void * _po,void * event_info)314 zoom_move(void *_po, void *event_info)
315 {
316    Photo_Object *po = (Photo_Object *) _po;
317    Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
318    printf("zoom move <%d,%d> <%f> momentum=<%f>\n", p->x, p->y, p->zoom, p->momentum);
319    po->zoom = po->base_zoom * p->zoom;
320    apply_changes(po);
321    return EVAS_EVENT_FLAG_NONE;
322 }
323 
324 static Evas_Event_Flags
zoom_end(void * _po,void * event_info)325 zoom_end(void *_po, void *event_info)
326 {
327    Photo_Object *po = (Photo_Object *) _po;
328    Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
329    printf("zoom end/abort <%d,%d> <%f> momentum=<%f>\n", p->x, p->y,
330          p->zoom, p->momentum);
331 
332    /* Apply the zoom-momentum or zoom out animator */
333    double tot_time = fabs(p->momentum) / ZOOM_MOMENTUM_FRICTION;
334    po->zoom_mom_time = tot_time;
335    po->zoom_mom = p->momentum;
336    po->base_zoom = po->zoom;
337    if (EINA_DBL_NONZERO(po->zoom_mom))
338      {
339         po->zoom_momentum = elm_transit_add();
340         elm_transit_duration_set(po->zoom_momentum,
341               tot_time);
342         elm_transit_effect_add(po->zoom_momentum,
343               zoom_momentum_animation_operation, po,
344               zoom_momentum_animation_end);
345         elm_transit_go(po->zoom_momentum);
346      }
347 
348    return EVAS_EVENT_FLAG_NONE;
349 }
350 
351 static Evas_Event_Flags
momentum_start(void * _po,void * event_info)352 momentum_start(void *_po, void *event_info)
353 {
354    Photo_Object *po = (Photo_Object *) _po;
355    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
356    printf("momentum_start po->rotate=<%d> <%d,%d>\n", po->rotate, p->x2, p->y2);
357 
358    /* If there's an active animator, stop it */
359    if (po->mom_timer)
360      {
361         ecore_animator_del(po->mom_timer);
362         po->mom_timer = NULL;
363      }
364 
365    po->dx = p->x2 - po->bx;
366    po->dy = p->y2 - po->by;
367    apply_changes(po);
368 
369    return EVAS_EVENT_FLAG_NONE;
370 }
371 
372 static Evas_Event_Flags
momentum_move(void * _po,void * event_info)373 momentum_move(void *_po, void *event_info)
374 {
375    Photo_Object *po = (Photo_Object *) _po;
376    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
377    printf("momentum move <%d,%d> fingers=<%d> mx,my=<%d,%d>\n", p->x2, p->y2, p->n, p->mx, p->my);
378 
379    po->bx = p->x2 - po->dx;
380    po->by = p->y2 - po->dy;
381    apply_changes(po);
382 
383    return EVAS_EVENT_FLAG_NONE;
384 }
385 
386 /* Momentum animation */
387 static Eina_Bool
momentum_animation_operation(void * _po)388 momentum_animation_operation(void *_po)
389 {
390    Photo_Object *po = (Photo_Object *) _po;
391    Eina_Bool rc = ECORE_CALLBACK_RENEW;
392    Evas_Coord x = po->bx;
393    Evas_Coord y = po->by;
394    po->mom_tot_time -= ecore_animator_frametime_get();
395    if (po->mom_tot_time <= 0)
396      {
397         po->mom_timer = NULL;
398         rc = ECORE_CALLBACK_CANCEL;
399      }
400 
401    /* x = v0t + 0.5at^2 */
402    po->bx += ((po->mx * po->mom_tot_time) +
403          (0.5 * po->mom_x_acc * (po->mom_tot_time * po->mom_tot_time)));
404 
405    po->by += ((po->my * po->mom_tot_time) +
406          (0.5 * po->mom_y_acc * (po->mom_tot_time * po->mom_tot_time)));
407 
408    printf("%s prev_bx-new_bx,y=(%d,%d)\n", __func__, x-po->bx, y-po->by);
409    if (rc == ECORE_CALLBACK_CANCEL)
410      pic_obj_keep_inframe(po);
411 
412    apply_changes(po);
413    return rc;
414 }
415 
416 static Evas_Event_Flags
momentum_end(void * _po,void * event_info)417 momentum_end(void *_po, void *event_info)
418 {
419    Photo_Object *po = (Photo_Object *) _po;
420    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
421    printf("momentum end x2,y2=<%d,%d> mx,my=<%d,%d>\n", p->x2, p->y2, p->mx, p->my);
422    pic_obj_keep_inframe(po);
423    apply_changes(po);
424    /* Make up some total-time for the movement */
425    po->mom_tot_time = sqrt((p->mx * p->mx) + (p->my * p->my))
426       / MOMENTUM_FRICTION;
427 
428    if (EINA_DBL_NONZERO(po->mom_tot_time))
429      {  /* Compute acceleration for both compenents, and launch timer */
430         po->mom_x_acc = (p->mx) / po->mom_tot_time; /* a = (v-v0) / t */
431         po->mom_y_acc = (p->my) / po->mom_tot_time; /* a = (v-v0) / t */
432         po->mom_x_acc /= MOMENTUM_FACTOR;
433         po->mom_y_acc /= MOMENTUM_FACTOR;
434         po->mom_timer = ecore_animator_add(momentum_animation_operation, po);
435      }
436 
437    return EVAS_EVENT_FLAG_NONE;
438 }
439 
440 static Evas_Event_Flags
momentum_abort(void * _po,void * event_info)441 momentum_abort(void *_po, void *event_info)
442 {
443    Photo_Object *po = (Photo_Object *) _po;
444    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
445    printf("momentum abort <%d,%d> <%d,%d>\n", p->x2, p->y2, p->mx, p->my);
446    pic_obj_keep_inframe(po);
447    apply_changes(po);
448 
449    return EVAS_EVENT_FLAG_NONE;
450 }
451 
452 static void
_win_del_req(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)453 _win_del_req(void *data, Evas_Object *obj EINA_UNUSED,
454       void *event_info EINA_UNUSED)
455 {
456    Photo_Object **photo_array = (Photo_Object **) data;
457 
458    if (!photo_array)
459       return;
460 
461    /* The content of the photo object is automatically deleted when the win
462     * is deleted. */
463    for ( ; *photo_array ; photo_array++)
464       free(*photo_array);
465 
466    free(data);
467 }
468 
469 static Photo_Object *
photo_object_add(Evas_Object * parent,Evas_Object * ic,const char * icon,Evas_Coord x,Evas_Coord y,Evas_Coord w,Evas_Coord h,int angle)470 photo_object_add(Evas_Object *parent, Evas_Object *ic, const char *icon,
471       Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, int angle)
472 {
473    char buf[PATH_MAX];
474    Photo_Object *po;
475    po = calloc(1, sizeof(*po));
476    if (!po) return NULL;
477 
478    po->base_zoom = po->zoom = BASE_ZOOM;
479 
480    if (ic)
481      {
482         po->ic = ic;
483      }
484    else
485      {
486         po->ic = elm_icon_add(parent);
487         elm_image_file_set(po->ic, icon, NULL);
488      }
489 
490    po->bx = x;
491    po->by = y;
492    po->bw = w;
493    po->bh = h;
494 
495    /* Add shadow */
496      {
497         po->shadow = elm_icon_add(po->ic);
498         snprintf(buf, sizeof(buf), "%s/images/pol_shadow.png", elm_app_data_dir_get());
499         elm_image_file_set(po->shadow, buf, NULL);
500         evas_object_resize(po->shadow, SHADOW_W, SHADOW_H);
501         evas_object_show(po->shadow);
502      }
503 
504    po->hit = evas_object_polygon_add(evas_object_evas_get(parent));
505    evas_object_precise_is_inside_set(po->hit, EINA_TRUE);
506    evas_object_repeat_events_set(po->hit, EINA_TRUE);
507    evas_object_color_set(po->hit, 0, 0, 0, 0);
508 
509    evas_object_move(po->ic, 0, 0);
510    evas_object_resize(po->ic, po->bw, po->bh);
511    evas_object_show(po->ic);
512 
513    evas_object_show(po->hit);
514 
515    po->gl = elm_gesture_layer_add(po->ic);
516    elm_gesture_layer_hold_events_set(po->gl, EINA_TRUE);
517    elm_gesture_layer_attach(po->gl, po->hit);
518 
519    /* FIXME: Add a po->rotate start so we take the first angle!!!! */
520    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
521          ELM_GESTURE_STATE_START, momentum_start, po);
522    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
523          ELM_GESTURE_STATE_MOVE, momentum_move, po);
524    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
525          ELM_GESTURE_STATE_END, momentum_end, po);
526    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM,
527          ELM_GESTURE_STATE_ABORT, momentum_abort, po);
528 
529    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
530          ELM_GESTURE_STATE_START, zoom_start, po);
531    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
532          ELM_GESTURE_STATE_MOVE, zoom_move, po);
533    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
534          ELM_GESTURE_STATE_END, zoom_end, po);
535    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM,
536          ELM_GESTURE_STATE_ABORT, zoom_end, po);
537 
538    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
539          ELM_GESTURE_STATE_START, rotate_start, po);
540    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
541          ELM_GESTURE_STATE_MOVE, rotate_move, po);
542    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
543          ELM_GESTURE_STATE_END, rotate_end, po);
544    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE,
545          ELM_GESTURE_STATE_ABORT, rotate_abort, po);
546 
547    po->rotate = po->base_rotate = angle;
548    po->shadow_zoom = 1.3;
549 
550    apply_changes(po);
551    return po;
552 }
553 
554 void
test_gesture_layer3(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)555 test_gesture_layer3(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
556       void *event_info EINA_UNUSED)
557 {
558    Evas_Coord w, h;
559    Evas_Object *win, *bg;
560    char buf[PATH_MAX];
561    int ind = 0;
562    Photo_Object **photo_array;
563    photo_array = calloc(4, sizeof(*photo_array));
564    if (!photo_array) return;
565 
566    w = 480;
567    h = 800;
568 
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);
573 
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);
580 
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);
583 
584    photo_array[ind] = NULL;
585    evas_object_smart_callback_add(win, "delete,request", _win_del_req,
586          photo_array);
587    evas_object_show(win);
588 }
589