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