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.5
9 /* The amount of zoom to do when "lifting" objects. */
10 #define LIFT_FACTOR 1.3
11 /* The base size of the shadow image. */
12 #define SHADOW_W 118
13 #define SHADOW_H 118
14 
15 static double zoom_out_animation_duration = 0.4;
16 
17 struct _Photo_Object {
18      Evas_Object *ic, *shadow;
19      Evas_Object *hit;
20      Evas_Object *gl;
21      Elm_Transit *zoom_out;
22      /* bx, by - current wanted coordinates of the photo object.
23       * bw, bh - original size of the "ic" object.
24       * dx, dy - Used to indicate the distance between the center point
25       * where we put down our fingers (when started moving the item) to
26       * the coords of the object, so we'll be able to calculate movement
27       * correctly. */
28      Evas_Coord bx, by, bw, bh, dx, dy;
29      /* Because gesture layer only knows the amount of rotation/zoom we do
30       * per gesture, we have to keep the current rotate/zoom factor and the
31       * one that was before we started the gesture. */
32      int base_rotate, rotate;
33      double base_zoom, zoom;
34      double shadow_zoom;
35 };
36 typedef struct _Photo_Object Photo_Object;
37 
38 /* This function applies the information from the Photo_Object to the actual
39  * evas objects. Zoom/rotate factors and etc. */
40 static void
apply_changes(Photo_Object * po)41 apply_changes(Photo_Object *po)
42 {
43    Evas_Map *map;
44 
45    map = evas_map_new(4);
46    evas_map_point_coord_set(map, 0, po->bx, po->by, 0);
47    evas_map_point_coord_set(map, 1, po->bx + po->bw, po->by, 0);
48    evas_map_point_coord_set(map, 2, po->bx + po->bw, po->by + po->bh, 0);
49    evas_map_point_coord_set(map, 3, po->bx, po->by + po->bh, 0);
50    evas_map_point_image_uv_set(map, 0, 0, 0);
51    evas_map_point_image_uv_set(map, 1, po->bw, 0);
52    evas_map_point_image_uv_set(map, 2, po->bw, po->bh);
53    evas_map_point_image_uv_set(map, 3, 0, po->bh);
54    evas_map_util_rotate(map, po->rotate,
55          po->bx + po->bw / 2, po->by + po->bh /2);
56    evas_map_util_zoom(map, po->zoom, po->zoom,
57          po->bx + po->bw / 2, po->by + po->bh /2);
58    evas_object_map_enable_set(po->ic, EINA_TRUE);
59    evas_object_map_set(po->ic, map);
60    evas_object_anti_alias_set(po->ic, EINA_TRUE);
61 
62      {
63         Evas_Map *shadow_map = evas_map_new(4);
64         evas_map_point_coord_set(shadow_map, 0, po->bx, po->by, 0);
65         evas_map_point_coord_set(shadow_map, 1, po->bx + po->bw, po->by, 0);
66         evas_map_point_coord_set(shadow_map, 2, po->bx + po->bw, po->by + po->bh, 0);
67         evas_map_point_coord_set(shadow_map, 3, po->bx, po->by + po->bh, 0);
68         evas_map_point_image_uv_set(shadow_map, 0, 0, 0);
69         evas_map_point_image_uv_set(shadow_map, 1, SHADOW_W, 0);
70         evas_map_point_image_uv_set(shadow_map, 2, SHADOW_W, SHADOW_H);
71         evas_map_point_image_uv_set(shadow_map, 3, 0, SHADOW_H);
72         evas_map_util_rotate(shadow_map, po->rotate,
73               po->bx + po->bw / 2, po->by + po->bh /2);
74         evas_map_util_zoom(shadow_map, po->zoom * po->shadow_zoom,
75               po->zoom * po->shadow_zoom,
76               po->bx + (po->bw / 2), po->by + (po->bh / 2));
77         evas_object_map_enable_set(po->shadow, EINA_TRUE);
78         evas_object_map_set(po->shadow, shadow_map);
79         evas_map_free(shadow_map);
80      }
81 
82    /* Update the position of the hit box */
83      {
84         Evas_Coord minx, miny, maxx, maxy;
85         int i;
86         evas_object_polygon_points_clear(po->hit);
87         evas_map_point_coord_get(map, 0, &minx, &miny, NULL);
88         maxx = minx;
89         maxy = miny;
90         evas_object_polygon_point_add(po->hit, minx, miny);
91         for (i = 1 ; i <= 3 ; i++)
92           {
93              Evas_Coord x, y;
94              evas_map_point_coord_get(map, i, &x, &y, NULL);
95              evas_object_polygon_point_add(po->hit, x, y);
96              if (x < minx)
97                 minx = x;
98              else if (x > maxx)
99                 maxx = x;
100 
101              if (y < miny)
102                 miny = y;
103              else if (y > maxy)
104                 maxy = y;
105           }
106      }
107 
108    evas_object_raise(po->shadow);
109    evas_object_raise(po->ic);
110    evas_object_raise(po->hit);
111    evas_map_free(map);
112 }
113 
114 /* Zoom out animation */
115 static void
zoom_out_animation_operation(void * _po,Elm_Transit * transit EINA_UNUSED,double progress)116 zoom_out_animation_operation(void *_po, Elm_Transit *transit EINA_UNUSED,
117       double progress)
118 {
119    Photo_Object *po = (Photo_Object *) _po;
120    po->zoom = BASE_ZOOM + ((po->base_zoom - BASE_ZOOM) * (1.0 - progress));
121    apply_changes(po);
122 }
123 
124 static void
zoom_out_animation_end(void * _po,Elm_Transit * transit EINA_UNUSED)125 zoom_out_animation_end(void *_po, Elm_Transit *transit EINA_UNUSED)
126 {
127    Photo_Object *po = (Photo_Object *) _po;
128 
129    po->base_zoom = po->zoom = BASE_ZOOM;
130    apply_changes(po);
131 
132    po->zoom_out = NULL;
133 }
134 
135 static Evas_Event_Flags
rotate_move(void * _po,void * event_info)136 rotate_move(void *_po, void *event_info)
137 {
138    Photo_Object *po = (Photo_Object *) _po;
139    Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
140    printf("rotate move <%d,%d> base=<%f> <%f>\n", p->x, p->y, p->base_angle, p->angle);
141    po->rotate = po->base_rotate + (int) p->angle - p->base_angle;
142    if (po->rotate < 0)
143       po->rotate += 360;
144    apply_changes(po);
145    return EVAS_EVENT_FLAG_NONE;
146 }
147 
148 static Evas_Event_Flags
rotate_end(void * _po,void * event_info)149 rotate_end(void *_po, void *event_info)
150 {
151    Photo_Object *po = (Photo_Object *) _po;
152    Elm_Gesture_Rotate_Info *p = (Elm_Gesture_Rotate_Info *) event_info;
153    printf("rotate end/abort <%d,%d> base=<%f> <%f>\n", p->x, p->y, p->base_angle, p->angle);
154    po->base_rotate += (int) p->angle - p->base_angle;
155    if (po->rotate < 0)
156       po->rotate += 360;
157    return EVAS_EVENT_FLAG_NONE;
158 }
159 
160 static Evas_Event_Flags
zoom_start(void * _po,void * event_info)161 zoom_start(void *_po, void *event_info)
162 {
163    Photo_Object *po = (Photo_Object *) _po;
164    Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
165    printf("zoom start <%d,%d> <%f>\n", p->x, p->y, p->zoom);
166 
167    /* If there's an active animator, stop it */
168    if (po->zoom_out)
169      {
170         elm_transit_del(po->zoom_out);
171         po->zoom_out = NULL;
172      }
173 
174    /* Give it a "lift" effect right from the start */
175    po->base_zoom = BASE_ZOOM * LIFT_FACTOR;
176    po->zoom = po->base_zoom;
177    po->shadow_zoom = 1.7;
178 
179    apply_changes(po);
180    return EVAS_EVENT_FLAG_NONE;
181 }
182 
183 static Evas_Event_Flags
zoom_move(void * _po,void * event_info)184 zoom_move(void *_po, void *event_info)
185 {
186    Photo_Object *po = (Photo_Object *) _po;
187    Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
188    printf("zoom move <%d,%d> <%f>\n", p->x, p->y, p->zoom);
189    po->zoom = po->base_zoom * p->zoom;
190    apply_changes(po);
191    return EVAS_EVENT_FLAG_NONE;
192 }
193 
194 static Evas_Event_Flags
zoom_end(void * _po,void * event_info)195 zoom_end(void *_po, void *event_info)
196 {
197    Photo_Object *po = (Photo_Object *) _po;
198    Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
199    printf("zoom end/abort <%d,%d> <%f>\n", p->x, p->y, p->zoom);
200 
201    /* Apply the zoom out animator */
202    po->shadow_zoom = 1.3;
203    po->base_zoom = po->zoom;
204    po->zoom_out = elm_transit_add();
205    elm_transit_duration_set(po->zoom_out, zoom_out_animation_duration);
206    elm_transit_effect_add(po->zoom_out, zoom_out_animation_operation, po, zoom_out_animation_end);
207    elm_transit_go(po->zoom_out);
208    return EVAS_EVENT_FLAG_NONE;
209 }
210 
211 static Evas_Event_Flags
momentum_start(void * _po,void * event_info)212 momentum_start(void *_po, void *event_info)
213 {
214    Photo_Object *po = (Photo_Object *) _po;
215    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
216    printf("momentum_start <%d,%d>\n", p->x2, p->y2);
217 
218    po->dx = p->x2 - po->bx;
219    po->dy = p->y2 - po->by;
220    apply_changes(po);
221 
222    return EVAS_EVENT_FLAG_NONE;
223 }
224 
225 static Evas_Event_Flags
momentum_move(void * _po,void * event_info)226 momentum_move(void *_po, void *event_info)
227 {
228    Photo_Object *po = (Photo_Object *) _po;
229    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
230    printf("momentum move <%d,%d>\n", p->x2, p->y2);
231 
232    po->bx = p->x2 - po->dx;
233    po->by = p->y2 - po->dy;
234    apply_changes(po);
235 
236    return EVAS_EVENT_FLAG_NONE;
237 }
238 
239 static Evas_Event_Flags
momentum_end(void * _po,void * event_info)240 momentum_end(void *_po, void *event_info)
241 {
242    Photo_Object *po = (Photo_Object *) _po;
243    Elm_Gesture_Momentum_Info *p = (Elm_Gesture_Momentum_Info *) event_info;
244    printf("momentum end/abort <%d,%d> <%d,%d>\n", p->x2, p->y2, p->mx, p->my);
245    (void) po;
246    (void) p;
247    /* Make sure middle is in the screen, if not, fix it. */
248      {
249         /* FIXME: Use actual window sizes instead of the hardcoded
250          * values */
251         Evas_Coord mx, my;
252         mx = po->bx + (po->bw / 2);
253         my = po->by + (po->bh / 2);
254         if (mx < 0)
255            po->bx = 0 - (po->bw / 2);
256         else if (mx > 480)
257            po->bx = 480 - (po->bw / 2);
258 
259         if (my < 0)
260            po->by = 0 - (po->bh / 2);
261         else if (my > 800)
262            po->by = 800 - (po->bh / 2);
263      }
264    apply_changes(po);
265 
266    return EVAS_EVENT_FLAG_NONE;
267 }
268 
269 static void
_win_del_req(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)270 _win_del_req(void *data, Evas_Object *obj EINA_UNUSED,
271       void *event_info EINA_UNUSED)
272 {
273    Photo_Object **photo_array = (Photo_Object **) data;
274 
275    if (!photo_array)
276       return;
277 
278    /* The content of the photo object is automatically deleted when the win
279     * is deleted. */
280    for ( ; *photo_array ; photo_array++)
281       free(*photo_array);
282 
283    free(data);
284 }
285 
286 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)287 photo_object_add(Evas_Object *parent, Evas_Object *ic, const char *icon, Evas_Coord x,
288       Evas_Coord y, Evas_Coord w, Evas_Coord h, int angle)
289 {
290    char buf[PATH_MAX];
291    Photo_Object *po;
292    po = calloc(1, sizeof(*po));
293    if (!po) return NULL;
294 
295    po->base_zoom = po->zoom = BASE_ZOOM;
296 
297    if (ic)
298      {
299         po->ic = ic;
300      }
301    else
302      {
303         po->ic = elm_icon_add(parent);
304         elm_image_file_set(po->ic, icon, NULL);
305      }
306 
307    po->bx = x;
308    po->by = y;
309    po->bw = w;
310    po->bh = h;
311 
312    /* Add shadow */
313      {
314         po->shadow = elm_icon_add(po->ic);
315         snprintf(buf, sizeof(buf), "%s/images/pol_shadow.png", elm_app_data_dir_get());
316         elm_image_file_set(po->shadow, buf, NULL);
317         evas_object_resize(po->shadow, SHADOW_W, SHADOW_H);
318         evas_object_show(po->shadow);
319      }
320 
321    po->hit = evas_object_polygon_add(evas_object_evas_get(parent));
322    evas_object_precise_is_inside_set(po->hit, EINA_TRUE);
323    evas_object_repeat_events_set(po->hit, EINA_TRUE);
324    evas_object_color_set(po->hit, 0, 0, 0, 0);
325 
326    evas_object_move(po->ic, 0, 0);
327    evas_object_resize(po->ic, po->bw, po->bh);
328    evas_object_show(po->ic);
329 
330    evas_object_show(po->hit);
331 
332    po->gl = elm_gesture_layer_add(po->ic);
333    elm_gesture_layer_hold_events_set(po->gl, EINA_TRUE);
334    elm_gesture_layer_attach(po->gl, po->hit);
335 
336    /* FIXME: Add a po->rotate start so we take the first angle!!!! */
337    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE, rotate_move, po);
338    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_END, rotate_end, po);
339    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_ABORT, rotate_end, po);
340    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, zoom_start, po);
341    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, zoom_move, po);
342    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END, zoom_end, po);
343    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT, zoom_end, po);
344    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_START, momentum_start, po);
345    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_MOVE, momentum_move, po);
346    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_END, momentum_end, po);
347    elm_gesture_layer_cb_set(po->gl, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_ABORT, momentum_end, po);
348 
349    po->rotate = po->base_rotate = angle;
350    po->shadow_zoom = 1.3;
351 
352    apply_changes(po);
353    return po;
354 }
355 
356 void
test_gesture_layer(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)357 test_gesture_layer(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
358       void *event_info EINA_UNUSED)
359 {
360    Evas_Coord w, h;
361    Evas_Object *win, *bg;
362    char buf[PATH_MAX];
363    int ind = 0;
364    Photo_Object **photo_array;
365    photo_array = calloc(4, sizeof(*photo_array));
366    if (!photo_array) return;
367 
368    w = 480;
369    h = 800;
370 
371    win = elm_win_add(NULL, "gesture-layer", ELM_WIN_BASIC);
372    elm_win_title_set(win, "Gesture Layer");
373    elm_win_autodel_set(win, EINA_TRUE);
374    evas_object_resize(win, w, h);
375 
376    bg = elm_bg_add(win);
377    snprintf(buf, sizeof(buf), "%s/images/wood_01.jpg", elm_app_data_dir_get());
378    elm_bg_file_set(bg, buf, NULL);
379    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
380    elm_win_resize_object_add(win, bg);
381    evas_object_show(bg);
382 
383    snprintf(buf, sizeof(buf), "%s/images/pol_sky.png", elm_app_data_dir_get());
384    photo_array[ind++] = photo_object_add(win, NULL, buf, 200, 200, 365, 400, 0);
385    snprintf(buf, sizeof(buf), "%s/images/pol_twofish.png", elm_app_data_dir_get());
386    photo_array[ind++] = photo_object_add(win, NULL, buf, 40, 300, 365, 400, 45);
387 
388    Evas_Object *en = elm_entry_add(win);
389    elm_object_text_set(en, "<font_size=40>You can use whatever object you want, "
390          "even entries like this.</font_size>");
391    elm_entry_line_wrap_set(en, ELM_WRAP_MIXED);
392 
393    Evas_Object *postit = elm_layout_add(win);
394    snprintf(buf, sizeof(buf), "%s/objects/postit_ent.edj", elm_app_data_dir_get());
395    elm_layout_file_set(postit, buf, "main");
396    elm_object_part_content_set(postit, "ent", en);
397 
398    photo_array[ind++] = photo_object_add(win, postit, NULL, 50, 50, 382, 400, 355);
399 
400    photo_array[ind] = NULL;
401    evas_object_smart_callback_add(win, "delete,request", _win_del_req,
402          photo_array);
403    evas_object_show(win);
404 }
405