[Image Slider] Add the function regarding CLICK event.
[framework/uifw/elementary.git] / src / lib / elm_imageslider.c
1 /* 
2
3 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 
4 */
5 #include <stdio.h>
6 #include <math.h>
7 #include <Elementary.h>
8 #include "elm_priv.h"
9
10 /**
11 * @defgroup Imageslider Imageslider
12 * @ingroup Elementary
13 *
14 * By flicking images on the screen, 
15 * you can see the images in specific path.
16 */
17
18 typedef struct _Widget_Data Widget_Data;
19
20 #define ANI_STEP                                (14 * elm_scale_get())
21 #define ANI_TIME                                (0.005)
22 #define ANI_TIME_MSEC           (12)
23 #define FLICK_TIME_MAX          (200)
24 #define FLICK_WIDTH_MIN (elm_finger_size_get() >> 2)
25 #define MOVE_STEP                       (3)
26 #define STEP_WEIGHT_DEF (1)
27 #define STEP_WEIGHT_MAX (2)
28 #define STEP_WEIGHT_MIN (0)
29 #define MOVING_IMAGE_SIZE       (128)
30 #define MAX_ZOOM_SIZE           (6)
31 #define INTERVAL_WIDTH          (15)
32 #define MULTITOUCHDEVICE        (11)
33
34 enum {
35         BLOCK_LEFT = 0,
36         BLOCK_CENTER,
37         BLOCK_RIGHT,
38         BLOCK_MAX
39 };
40
41 struct _Imageslider_Item 
42 {
43         Evas_Object *obj;
44         const char *photo_file;
45         void (*func)(void *data, Evas_Object *obj, void *event_info);
46         void *data;
47         Evas_Coord x, y, w, h;
48         Evas_Coord ox, oy, ow, oh;
49         int moving : 1;
50 };
51
52 struct _Widget_Data
53 {
54         Evas_Object *ly[BLOCK_MAX];
55         Evas_Object *clip;
56         Eina_List *its;
57         Eina_List *cur;
58         Evas_Coord x, y, w, h;
59         Evas_Object *obj;
60         Ecore_Idler *queue_idler;
61         Ecore_Timer *anim_timer;
62
63         Evas_Coord_Point down_pos;
64         Evas_Coord move_x;
65         Evas_Coord move_y;
66         Evas_Coord dest_x;
67         struct timeval tv;
68         unsigned int timestamp;
69         int step;
70         int move_cnt;
71         int ani_lock : 1;
72         int moving : 1;
73
74         Eina_Bool on_zoom : 1;
75         Eina_Bool on_hold : 1;
76         int dx, dy, mx, my;
77         int mdx, mdy, mmx, mmy;
78         int dratio;
79         int ratio;
80 };
81
82 static const char *widtype = NULL;
83 static const char SIG_CLICKED[] = "clicked";
84
85 static void _del_hook(Evas_Object *obj);
86 static void _theme_hook(Evas_Object *obj);
87 static void _sizing_eval(Evas_Object *obj);
88 static void _imageslider_del_all(Widget_Data *wd);
89 static void _imageslider_move(void *data,Evas *e, Evas_Object *obj, void *event_info);
90 static void _imageslider_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
91 //static void _imageslider_show(Evas_Object *obj);
92 //static void _imageslider_hide(Evas_Object *obj);
93 static void _imageslider_show(void * data, Evas * e, Evas_Object * obj, void * event_info);
94 static void _imageslider_hide(void * data, Evas * e, Evas_Object * obj, void * event_info);
95 static void _imageslider_update(Widget_Data *wd);
96 static void _imageslider_update_pos(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord w);
97 static void _imageslider_update_center_pos(Widget_Data *wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w);
98 static Evas_Object *_imageslider_add_obj(Widget_Data *wd);
99 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left);
100 static void _imageslider_obj_move(Widget_Data *wd, Evas_Coord step);
101 static int _icon_to_image(void *data);
102 static int _check_drag(int state, void *data);
103 static void _check_zoom(void *data);
104 static void _anim(Widget_Data *wd);
105 static int _timer_cb(void *data);
106 static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
107 static void ev_imageslider_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
108 static void ev_imageslider_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
109 static void ev_imageslider_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
110
111
112 static void _del_hook(Evas_Object * obj)
113 {
114         int i;
115         Widget_Data * wd;
116         wd = elm_widget_data_get(obj);
117         
118         fprintf( stderr, "Call imageslider del hook!\n" );
119         
120         if (!wd) return;
121
122         for (i = 0; i < BLOCK_MAX; i++) {
123                 evas_object_del(wd->ly[i]);
124         }
125
126         if (wd->its) {
127                 eina_list_free(wd->its);
128                 wd->its = NULL;
129         }
130
131         if (wd->queue_idler) {
132                 ecore_idler_del(wd->queue_idler);
133                 wd->queue_idler = NULL;         
134         }
135
136         if (wd->anim_timer) {
137                 ecore_timer_del(wd->anim_timer);
138                 wd->anim_timer = NULL;
139         }
140
141         if (wd) free(wd);
142         
143 }
144
145 static void _theme_hook(Evas_Object * obj)
146 {
147         int i;
148         Widget_Data *wd;
149         wd = elm_widget_data_get(obj);
150
151         if (!wd || !wd->ly ) {
152                 return;
153         }
154
155         for (i=0; i < BLOCK_MAX; i++) {
156                 wd->ly[i] = elm_layout_add(obj);
157                 _elm_theme_object_set(obj, wd->ly[i], "imageslider", "base", "default");
158                 elm_widget_resize_object_set(obj, wd->ly[i]);
159                 evas_object_show(wd->ly[i]);                    
160         }
161
162         _sizing_eval(obj);      
163 }
164
165
166 static void _sizing_eval(Evas_Object * obj)
167 {
168         Evas *e;
169         Widget_Data *wd = elm_widget_data_get(obj);
170
171         if (!wd) {
172                 return;
173         }
174
175         e = evas_object_evas_get(wd->obj);
176
177         _imageslider_move(obj, e, obj, NULL);
178         _imageslider_resize(obj, e, obj, NULL);
179
180 }
181
182 static void _imageslider_move(void * data, Evas * e, Evas_Object * obj, void * event_info)
183 {
184         Widget_Data *wd;
185         Evas_Coord x, y;
186
187         if (!data) {
188                 return;
189         }
190         
191         wd = elm_widget_data_get((Evas_Object *) data);
192         if (!wd) {
193                 return;
194         }
195
196         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
197         wd->x = x;
198         wd->y = y;
199         evas_object_move(wd->clip, x, y);
200         
201         _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
202         
203 }
204
205 static void _imageslider_resize(void * data, Evas * e, Evas_Object * obj, void * event_info)
206 {
207         int i;
208         Widget_Data *wd;
209         Evas_Coord w, h;
210
211         if (!data) {
212                 return;
213         }
214                 
215         wd = elm_widget_data_get((Evas_Object *) data);
216         if (!wd || !wd->ly) {
217                 return;         
218         }
219
220         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
221         fprintf( stderr, "%d %d -resize\n" , w, h );
222         wd->w = w;
223         wd->h = h;
224
225         for (i = 0; i < BLOCK_MAX; i++) {
226                 evas_object_resize(wd->ly[i], w, h);
227         }
228
229         evas_object_resize(wd->clip, w, h);
230
231         _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
232         
233 }
234
235
236 //static void _imageslider_show(Evas_Object * obj)
237 static void _imageslider_show(void *data, Evas *e, Evas_Object * obj, void *event_info)
238 {
239         Widget_Data *wd;
240
241         if (!data) {
242                 return;
243         }
244         
245         wd = elm_widget_data_get((Evas_Object *) data);
246         if (!wd) {
247                 return;
248         }
249         
250         evas_object_show(wd->clip);
251 }
252
253 //static void _imageslider_hide(Evas_Object *obj)
254 static void _imageslider_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
255 {
256         Widget_Data *wd;
257
258         if (!data) {
259                 return;
260         }
261         
262         wd = elm_widget_data_get((Evas_Object *) data);
263         if (!wd) {
264                 return;
265         }
266         evas_object_hide(wd->clip);
267 }
268
269 static void _imageslider_del_all(Widget_Data * wd)
270 {
271    
272         int i;
273
274         if (!wd) {
275                 return;
276         }
277
278         for (i = 0; i < BLOCK_MAX; i++) {
279                 evas_object_del(wd->ly[i]);
280         }
281 }
282
283 static void _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w)
284 {
285         evas_object_move(wd->ly[BLOCK_LEFT], x - (w + INTERVAL_WIDTH), y);
286         evas_object_move(wd->ly[BLOCK_CENTER], x, y);
287         evas_object_move(wd->ly[BLOCK_RIGHT], x + (w + INTERVAL_WIDTH), y);
288         evas_render_idle_flush(evas_object_evas_get(wd->obj));
289 }
290
291 static void _imageslider_update_center_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w)
292 {
293         Evas_Object *eo;
294         Evas_Coord ix, iy, iw, ih;
295
296         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
297         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
298
299         if ((ix > 0) || (ix + iw < wd->w)) {
300                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
301 //              edje_freeze();
302 //              evas_event_feed_mouse_cancel(evas_object_evas_get(wd->obj), NULL, NULL);
303 //              evas_event_feed_mouse_down(evas_object_evas_get(wd->obj), 1, EVAS_BUTTON_NONE, NULL, NULL);             
304
305                 _imageslider_update_pos(wd, x, y, w);
306                 wd->on_zoom = EINA_FALSE;
307         }
308 }
309
310 static Evas_Object *_imageslider_add_obj(Widget_Data *wd)
311 {
312         Evas_Object *eo;
313         eo = elm_layout_add(wd->obj);
314         elm_layout_theme_set(eo, "imageslider", "base", "default");
315         elm_widget_resize_object_set(wd->obj, eo);
316 //      evas_object_smart_member_add(eo, wd->obj);
317         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
318         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
319         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
320         evas_object_resize(eo, wd->w, wd->h);
321         evas_object_move(eo, wd->w + INTERVAL_WIDTH, wd->y);
322         evas_object_clip_set(eo, wd->clip);
323         evas_object_show(eo);
324
325         return eo;
326 }
327
328 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left)
329 {
330         if (!left) {
331                 if (wd->ly[BLOCK_LEFT]) {
332                         evas_object_del(wd->ly[BLOCK_LEFT]);
333                         wd->ly[BLOCK_LEFT] = NULL;
334                 }
335
336                 wd->ly[BLOCK_LEFT] = wd->ly[BLOCK_CENTER];
337                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_RIGHT];
338                 wd->ly[BLOCK_RIGHT] = _imageslider_add_obj(wd);
339         } else {
340                 if (wd->ly[BLOCK_RIGHT]) {
341                         evas_object_del(wd->ly[BLOCK_RIGHT]);
342                         wd->ly[BLOCK_RIGHT] = NULL;
343                 }
344
345                 wd->ly[BLOCK_RIGHT]= wd->ly[BLOCK_CENTER];
346                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_LEFT];
347                 wd->ly[BLOCK_LEFT]= _imageslider_add_obj(wd);
348         }
349 }
350
351
352 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step)
353 {
354         if (step > 0) {
355                 wd->cur = eina_list_next(wd->cur);
356                 if (wd->cur == NULL) {
357                         wd->cur = eina_list_last(wd->its);
358                         wd->step = ANI_STEP;
359                 } else {
360                         wd->step = -ANI_STEP;
361                         wd->move_x += wd->w;
362                         _imageslider_obj_shift(wd, 0);
363                 }
364                 wd->moving = 1;         
365         } else if (step < 0) {
366                 wd->cur = eina_list_prev(wd->cur);
367                 if (wd->cur == NULL) {
368                         wd->cur = wd->its;
369                         wd->step = -ANI_STEP;
370                 } else {
371                         wd->step = ANI_STEP;
372                         wd->move_x -= wd->w;
373                         _imageslider_obj_shift(wd, 1);
374                 }
375                 wd->moving = 1;
376         } else {
377                 if (wd->move_x < 0) wd->step = ANI_STEP;
378                 else wd->step = -ANI_STEP;
379                 wd->moving = 0;
380         }
381
382         _imageslider_update(wd);
383 }
384
385 static void ev_imageslider_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
386 {
387         Widget_Data *wd = data;
388         Evas_Event_Mouse_Down *ev = event_info;
389         Evas_Coord ix, iy, iw, ih;
390         Evas_Object *eo = NULL;
391
392         if (wd->ani_lock) return;
393
394         wd->down_pos = ev->canvas;
395         wd->timestamp = ev->timestamp;
396         wd->move_cnt = MOVE_STEP;
397
398         wd->dx = ev->canvas.x;
399         wd->dy = ev->canvas.y;
400         wd->mx = ev->canvas.x;
401         wd->my = ev->canvas.y;
402
403         wd->dratio = 1;
404         wd->ratio = 1;
405
406         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
407         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
408
409         if (iw != wd->w) {
410                 wd->on_zoom = EINA_TRUE;
411                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
412 //              edje_thaw();            
413         }
414
415         fprintf( stderr, "-- down! --\n" );
416
417 }
418
419 static void ev_imageslider_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
420 {
421         Widget_Data *wd = data;
422         Evas_Event_Mouse_Up *ev = event_info;
423         Evas_Coord step;
424         int interval;
425
426         if (wd->ani_lock) return;
427
428         if (wd->on_zoom) {              
429         } else {
430                 step = wd->down_pos.x - ev->canvas.x;
431                 interval = ev->timestamp - wd->timestamp;
432                 if (step == 0 || interval == 0) return;
433
434                 if (interval < FLICK_TIME_MAX) {
435                         if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN) _imageslider_obj_move(wd, 0);
436                         else _imageslider_obj_move(wd, step);
437                 } else {
438                         step = (wd->x - wd->move_x) << 1;
439                         if (step <= wd->w && step >= -(wd->w)) _imageslider_obj_move(wd, 0);
440                         else _imageslider_obj_move(wd, step);
441                 }
442         }
443
444         fprintf( stderr, "-- up! --\n" );
445
446 }
447
448 static void ev_imageslider_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
449 {
450         int idx;
451         Evas_Object *eo;
452         Evas_Coord step;
453         Widget_Data *wd = data;
454         Evas_Event_Mouse_Move *ev = event_info;
455         Elm_Imageslider_Item *it;
456
457         if (wd->ani_lock) return;
458
459         if (wd->move_cnt == MOVE_STEP) {
460                 if (wd->on_hold == EINA_FALSE) {
461                         wd->move_cnt = 0;
462
463                         if (ev->buttons) {
464                                 step = ev->cur.canvas.x - wd->down_pos.x;
465                                 if (step > 0) idx = BLOCK_LEFT;
466                                 else idx = BLOCK_RIGHT;
467
468                                 wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
469                                 wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
470
471                                 if (wd->on_zoom) {
472                                         _imageslider_update_center_pos(wd, wd->move_x, wd->move_y, wd->y, wd->w);
473                                 } else {
474                                         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
475                                 }
476                         }
477                 } else {
478                         wd->mx = ev->cur.canvas.x;
479                         wd->my = ev->cur.canvas.y;
480
481                         wd->ratio = sqrt((wd->mx -wd->mmx)*(wd->mx -wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
482
483                         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
484                         if (eo) {
485                                 it = eina_list_data_get(wd->cur);
486                                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE ) {
487                                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
488                                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
489                                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
490                                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
491                                 }
492                         }                       
493                 }
494         }
495
496         wd->move_cnt++;
497
498 }
499
500
501 static void
502 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
503 {
504         //fprintf(stderr, "[[[ DEBUG ]]]: (EFL) SIGNAL CLICKED!!\n");
505         evas_object_smart_callback_call(data, SIG_CLICKED, NULL);       
506 }
507
508 #if 0 // REMOVED about Multi-touch.
509 static void ev_imageslider_multi_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
510 {
511         Evas_Event_Multi_Down *ev = event_info;
512         Widget_Data *wd = data;
513
514         if (ev->device == MULTITOUCHDEVICE) return;
515
516         wd->on_hold = EINA_TRUE;
517         wd->mdx = ev->canvas.x;
518         wd->mdy = ev->canvas.y;
519         wd->mmx = ev->canvas.x;
520         wd->mmy = ev->canvas.y;
521
522         wd->dratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
523         wd->ratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx)+ (wd->my - wd->mmy)*(wd->my - wd->mmy));
524
525         if (wd->on_zoom){
526                 wd->on_zoom = EINA_FALSE;
527                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.on", "block");
528 //              edje_freeze();
529         }
530 }
531
532 static void ev_imageslider_multi_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
533 {
534         Evas_Event_Multi_Up *ev = event_info;
535         Widget_Data *wd = data;
536         Elm_Imageslider_Item *it;
537
538         if (ev->device == MULTITOUCHDEVICE) return;
539
540         it = eina_list_data_get(wd->cur);
541         it->w = (int)it->w * wd->ratio/wd->dratio;
542         it->h = (int)it->h * wd->ratio/wd->dratio;
543
544         if (it->w != it->ow) {
545                 wd->on_zoom = EINA_TRUE;
546                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
547 //              edje_thaw();
548         } else {
549                 wd->on_zoom = EINA_FALSE;
550         }
551
552         wd->on_hold = EINA_FALSE;
553         wd->mdx = 0;
554         wd->mdy = 0;
555         wd->mmx = 0;
556         wd->mmy = 0;
557         wd->ratio = 0;
558         wd->dratio = 0;
559         
560 }
561
562 static void ev_imageslider_multi_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
563 {
564         Evas_Event_Multi_Move *ev = event_info;
565         Widget_Data *wd = data;
566         Evas_Object *eo = NULL;
567         Elm_Imageslider_Item *it;
568
569         if (ev->device == MULTITOUCHDEVICE) return;
570
571         if ((wd->mdx == 0) && (wd->mdy == 0) && (wd->mmx == 0) && (wd->mmy == 0)) {
572                 wd->mdx = ev->cur.canvas.x;
573                 wd->mdy = ev->cur.canvas.y;
574                 wd->mmx = ev->cur.canvas.x;
575                 wd->mmy = ev->cur.canvas.y;
576
577                 wd->dratio = sqrt((wd->dx - wd->mdx)*(wd->dx - wd->mdx) + (wd->dy - wd->mdy)*(wd->dy - wd->mdy));
578         }
579
580         wd->mmx = ev->cur.canvas.x;
581         wd->mmy = ev->cur.canvas.y;
582         wd->ratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
583
584         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
585
586         if (eo) {
587                 it = eina_list_data_get(wd->cur);
588                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE) {
589                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
590                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
591                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
592                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
593                 }
594         }       
595 }
596
597 #endif // about Multi-touch.
598
599 static inline double time_get(Evas_Coord x, Evas_Coord w)
600 {
601         double time;
602         time = (-sin(x / w) + 1) / 500;
603
604         if (time == 0) time = ANI_TIME;
605         
606         return time;
607 }
608
609 static int _icon_to_image(void *data)
610 {
611         Widget_Data *wd = data;
612         wd->moving = 0;
613         _imageslider_update(wd);
614
615         if (wd->queue_idler) {
616                 ecore_idler_del(wd->queue_idler);
617                 wd->queue_idler = NULL;
618         }
619         return ECORE_CALLBACK_CANCEL;
620 }
621
622 static int _check_drag(int state, void *data)
623 {
624         Widget_Data *wd = data;
625         Elm_Imageslider_Item *it;
626         Evas_Coord ix, iy, iw, ih;
627         double dx, dy = 0;
628         Eina_List *l[BLOCK_MAX];
629         Evas_Object *eo = NULL;
630         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
631         l[BLOCK_CENTER] = wd->cur;
632         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
633
634         it = eina_list_data_get(l[state]);
635
636         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[state]), "swl.photo");
637         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
638         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
639         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
640
641         if ((iw != wd->w) || ((dx != 0 ) || (dy != 0 ))) {
642                 if (wd->ly[state]) {
643                         evas_object_del(wd->ly[state]);
644                         wd->ly[state] = NULL;
645                 }
646                 wd->ly[state] = _imageslider_add_obj(wd);
647         } else {
648                 return 1;
649         }
650
651         return 0;
652 }
653
654
655 static void _check_zoom(void *data)
656 {
657         Widget_Data *wd = data;
658         Elm_Imageslider_Item *it;
659         Evas_Coord ix, iy, iw, ih;
660         double dx, dy = 0;
661         Evas_Object *eo = NULL;
662
663         it = eina_list_data_get(wd->cur);
664
665         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
666         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
667         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
668         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo", &dx, &dy);
669
670         if ((iw != wd->w) || ((dx != 0) || (dy != 0))) {
671                 wd->on_zoom = EINA_TRUE;
672                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.off", "block");
673 //              edje_thaw();
674         } else {
675                 wd->on_zoom = EINA_FALSE;
676                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
677 //              edje_freeze();
678         }
679 }
680
681
682 static int _timer_cb(void *data)
683 {
684         Widget_Data *wd;
685         Elm_Imageslider_Item *it;
686         struct timeval tv;
687         int t;
688         int ret;
689         wd = data;
690         if (wd->ani_lock == 0 ) return 0;
691
692         gettimeofday(&tv, NULL);
693
694         t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
695         gettimeofday(&wd->tv, NULL);
696
697         t = t / ANI_TIME_MSEC;
698         if (t <= STEP_WEIGHT_MIN) t = STEP_WEIGHT_DEF;
699         else if (t >  STEP_WEIGHT_MAX) t = STEP_WEIGHT_MAX;
700
701         wd->move_x += (wd->step) * t;
702
703         if (wd->step < 0 && wd->move_x < wd->x) wd->move_x = wd->x;
704         else if (wd->step > 0 && wd->move_x > wd->x) wd->move_x = wd->x;
705
706         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
707
708         if (wd->move_x == wd->x) {
709                 wd->ani_lock = 0;
710                 if (wd->cur) {
711                         it = eina_list_data_get(wd->cur);
712                         if (it->func) it->func(it->data, wd->obj, it);
713                 }
714                 if (wd->cur) {
715                         it = eina_list_data_get(wd->cur);
716                         evas_object_smart_callback_call(wd->obj, "changed", it);
717                 }
718
719                 ret = _check_drag(BLOCK_LEFT, wd);
720                 ret = _check_drag(BLOCK_RIGHT, wd);
721                 _check_zoom(wd);
722
723                 if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
724
725                 if(wd->anim_timer) {
726                         ecore_timer_del(wd->anim_timer);
727                         wd->anim_timer = NULL;
728                 }
729
730                 return ECORE_CALLBACK_CANCEL;
731         }
732
733         return ECORE_CALLBACK_RENEW;    
734 }
735
736         
737 static void _anim(Widget_Data *wd)
738 {
739         Evas_Coord w;
740
741         if (wd->x == wd->move_x) {
742                 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
743                 return;
744         }
745
746         wd->ani_lock = 1;
747
748         w = wd->move_x;
749         gettimeofday(&wd->tv, NULL);
750
751         if (!wd->anim_timer) {
752                 wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd); 
753         }       
754 }
755
756 static void _imageslider_update(Widget_Data *wd)
757 {
758         int i;
759         Eina_List *l[BLOCK_MAX];
760         Elm_Imageslider_Item *it;
761         Evas_Object *eo;
762
763         if (!wd) {
764                 return;
765         }
766
767         if (!wd->cur) {
768                 _imageslider_del_all(wd);
769                 return;
770         }
771
772         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
773         l[BLOCK_CENTER] = wd->cur;
774         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
775
776         for (i = 0; i < BLOCK_MAX; i++) {
777                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
778                 if (!l[i]) {
779                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
780                         evas_object_del(eo);
781                 } else {
782                         it = eina_list_data_get(l[i]);
783                         if (!it) return;
784
785                         if (!eo) {
786                                 eo = elm_image_add(wd->obj);
787                                 elm_layout_content_set(wd->ly[i], "swl.photo", eo);
788                                 elm_image_prescale_set(eo, wd->w);
789                                 elm_image_file_set(eo, it->photo_file, NULL);
790                                 elm_image_object_size_get(eo, &it->w, &it->h);
791                                 evas_object_geometry_get(eo, &it->ox, &it->oy, &it->ow, &it->oh);
792                                 it->ow = it->w;
793                                 it->oh = it->h;
794                         }
795
796                         if (wd->moving != it->moving) {
797                                 it->moving = wd->moving;
798                                 if (wd->moving) {
799                                         elm_image_prescale_set(eo, MOVING_IMAGE_SIZE);
800                                 } else {
801                                         elm_image_prescale_set(eo, it->w > it->h ? it->w : it->h);
802                                 }
803                         }
804                 }
805         }
806
807         _anim(wd);
808
809 }
810
811
812 /** 
813 * Add an Image Slider widget 
814
815 * @param        parent  The parent object 
816 * @return       The new Image slider object or NULL if it cannot be created 
817
818 * @ingroup Imageslider 
819 */
820 EAPI Evas_Object *
821 elm_imageslider_add(Evas_Object * parent)
822 {
823         int i;
824         Evas_Object *obj = NULL;
825         Widget_Data *wd = NULL;
826         Evas *e;
827
828         if (!parent) {
829                 return NULL;
830         }
831
832         wd = ELM_NEW(Widget_Data);
833         e = evas_object_evas_get(parent);
834         if (e == NULL ) {
835                 return NULL;
836         }
837         
838         obj = elm_widget_add(e);
839         ELM_SET_WIDTYPE(widtype, "imageslider");
840         elm_widget_type_set(obj, "imageslider");
841         elm_widget_sub_object_add(parent, obj);
842         elm_widget_data_set(obj, wd);
843         //wd->parent = parent;
844         elm_widget_del_hook_set(obj, _del_hook);
845         //elm_widget_theme_hook_set(obj, _theme_hook);
846
847         wd->clip = evas_object_rectangle_add(e);
848         
849         for (i=0; i < BLOCK_MAX; i++) {
850                 wd->ly[i] = elm_layout_add(obj);
851                 elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
852                 elm_widget_resize_object_set(obj, wd->ly[i]);
853                 evas_object_smart_member_add(wd->ly[i], obj);
854                 
855                 edje_object_signal_callback_add(elm_layout_edje_get(wd->ly[i]), "elm,photo,clicked", "", _signal_clicked, obj);
856                 
857                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
858                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
859                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
860                 evas_object_clip_set(wd->ly[i], wd->clip);
861                 evas_object_show(wd->ly[i]);                    
862         }
863
864         wd->obj = obj;
865
866         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
867         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
868         evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
869         evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
870         
871         _sizing_eval(obj);
872
873    return obj;  
874 }
875
876
877 /** 
878 * Append an Image Slider item 
879
880 * @param        obj          The Image Slider object 
881 * @param        photo_file   photo file path 
882 * @param        func         callback function 
883 * @param        data         callback data 
884 * @return       The Image Slider item handle or NULL 
885
886 * @ingroup Imageslider 
887 */
888 EAPI Elm_Imageslider_Item *
889 elm_imageslider_item_append(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
890 {
891         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
892         Widget_Data *wd;
893         Elm_Imageslider_Item *it;
894
895         if (!obj || !(wd = elm_widget_data_get(obj))) {
896                 return NULL;
897         }
898
899         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
900         if (!it) return NULL;
901         it->photo_file = eina_stringshare_add(photo_file);
902         it->func = func;
903         it->data = data;
904         it->obj = obj;
905         wd->its = eina_list_append(wd->its, it);
906
907         if (!wd->cur) wd->cur = wd->its;
908
909         _imageslider_update(wd);
910
911         return it; 
912 }
913
914
915 /** 
916 * Prepend Image Slider item 
917
918 * @param        obj          The Image Slider object 
919 * @param        photo_file   photo file path 
920 * @param        func         callback function 
921 * @param        data         callback data 
922 * @return       The imageslider item handle or NULL 
923
924 * @ingroup Imageslider 
925 */
926 EAPI Elm_Imageslider_Item *
927 elm_imageslider_item_prepend(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
928 {
929         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
930         Widget_Data *wd;
931         Elm_Imageslider_Item *it;
932
933         if (!obj || !(wd = elm_widget_data_get(obj))) {
934                 return NULL;
935         }
936
937         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
938         it->photo_file = eina_stringshare_add(photo_file);
939         it->func = func;
940         it->data = data;
941         it->obj = obj;
942         wd->its = eina_list_prepend(wd->its, it );
943
944         if (!wd->cur) wd->cur = wd->its;
945
946         _imageslider_update(wd);
947
948         return it;
949 }
950
951
952
953 /**
954 * Delete the selected Image Slider item
955 *
956 * @param it             The selected Image Slider item handle
957 *
958 * @ingroup Imageslider
959 */
960 EAPI void
961 elm_imageslider_item_del(Elm_Imageslider_Item * it)
962 {
963         Widget_Data *wd;
964         Elm_Imageslider_Item *_it;
965         Eina_List *l;
966
967         if (!it || !(wd = elm_widget_data_get(it->obj))) {
968                 return ;
969         }
970
971         EINA_LIST_FOREACH(wd->its, l, _it) {
972                 if (_it == it ) {
973                         if (l == wd->cur) wd->cur = eina_list_prev(wd->cur);
974                         wd->its = eina_list_remove(wd->its, it);
975                         if (!wd->cur) wd->cur = wd->its;
976                         break;
977                 }
978         }
979
980         _imageslider_update(wd);
981         
982 }
983
984
985 /**
986 * Get the selected Image Slider item
987 *
988 * @param obj            The Image Slider object
989 * @return The selected Image Slider item or NULL
990 *
991 * @ingroup Imageslider
992 */
993 EAPI Elm_Imageslider_Item *
994 elm_imageslider_selected_item_get(Evas_Object * obj)
995 {
996         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
997         Widget_Data *wd;
998
999         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1000                 return NULL;
1001         }
1002
1003         if (!wd->cur) return NULL;
1004
1005         return eina_list_data_get(wd->cur);
1006 }
1007
1008 /**
1009 * Get whether an Image Slider item is selected or not
1010 *
1011 * @param it              the selected Image Slider item
1012 * @return EINA_TRUE or EINA_FALSE
1013 *
1014 * @ingroup Imageslider
1015 */
1016 EAPI Eina_Bool
1017 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
1018 {
1019         Widget_Data *wd;
1020         
1021         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1022                 return EINA_FALSE;
1023         }
1024
1025         if (!wd->cur) return EINA_FALSE;
1026
1027         if (eina_list_data_get(wd->cur) == it ) return EINA_TRUE;
1028         else return EINA_FALSE;
1029         
1030 }
1031
1032 /**
1033 * Set the selected Image Slider item
1034 *
1035 * @param it             The Imaga Slider item
1036 *
1037 * @ingroup Imageslider
1038 */
1039 EAPI void
1040 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
1041 {
1042         int i;
1043         Widget_Data *wd;
1044         Elm_Imageslider_Item *_it;
1045         Eina_List *l;
1046         Evas_Object *eo;
1047
1048         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1049                 return ;
1050         }
1051
1052         EINA_LIST_FOREACH(wd->its, l, _it) {
1053                 if (_it == it ) {
1054                         wd->cur = l;
1055                 }
1056         }
1057
1058         for (i = 0; i < BLOCK_MAX; i++) {
1059                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
1060                 if (eo) {
1061                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
1062                         evas_object_del(eo);
1063                 }
1064         }
1065
1066         _imageslider_update(wd);
1067         
1068 }
1069
1070
1071 /**
1072 * Get the photo file path of given Image Slider item
1073 *
1074 * @param it             The Image Slider item
1075 * @return The photo file path or NULL;
1076 *
1077 * @ingroup Imageslider
1078 */
1079 EAPI const char *
1080 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
1081 {
1082         if (!it) {
1083                 return NULL;
1084         }
1085
1086         return it->photo_file;
1087 }
1088
1089
1090 /**
1091 * Get the previous Image Slider item
1092 *
1093 * @param it             The Image Slider item
1094 * @return The previous Image Slider item or NULL
1095 *
1096 * @ingroup Imageslider
1097 */
1098 EAPI Elm_Imageslider_Item *
1099 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
1100 {
1101         Widget_Data *wd;
1102         Elm_Imageslider_Item *_it;
1103         Eina_List *l;
1104
1105         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1106                 return NULL;
1107         }
1108
1109         EINA_LIST_FOREACH(wd->its, l, _it) {
1110                 if (_it == it) {
1111                         l = eina_list_prev(l);
1112                         if (!l) break;
1113                         return eina_list_data_get(l);
1114                 }
1115         }
1116
1117         return NULL;    
1118 }
1119
1120
1121 /**
1122 * Get the next Image Slider item
1123 *
1124 * @param it             The Image Slider item
1125 * @return The next Image Slider item or NULL
1126 *
1127 * @ingroup Imageslider
1128 */
1129 EAPI Elm_Imageslider_Item *
1130 elm_imageslider_item_next(Elm_Imageslider_Item * it)
1131 {
1132         Widget_Data *wd;
1133         Elm_Imageslider_Item *_it;
1134         Eina_List *l;
1135
1136         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1137                 return NULL;
1138         }
1139
1140         EINA_LIST_FOREACH(wd->its, l, _it) {
1141                 if (_it == it) {
1142                         l = eina_list_next(l);
1143                         if (!l) break;
1144                         return eina_list_data_get(l);
1145                 }
1146         }
1147
1148         return NULL;
1149 }
1150
1151
1152 /**
1153 * Move to the previous Image Slider item
1154 *
1155 * @param obj    The Image Slider object
1156 *
1157 * @ingroup Imageslider
1158 */
1159 EAPI void 
1160 elm_imageslider_prev(Evas_Object * obj)
1161 {
1162         ELM_CHECK_WIDTYPE(obj, widtype);
1163         Widget_Data *wd;
1164         
1165         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1166                 return;
1167         }
1168
1169         if (wd->ani_lock) return;
1170
1171         _imageslider_obj_move(wd, -1);
1172 }
1173
1174
1175 /**
1176 * Move to the next Image Slider item
1177 *
1178 * @param obj The Image Slider object
1179 *
1180 * @ingroup Imageslider
1181 */
1182 EAPI void
1183 elm_imageslider_next(Evas_Object * obj)
1184 {
1185         ELM_CHECK_WIDTYPE(obj, widtype);
1186         Widget_Data *wd;
1187         
1188         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1189                 return;
1190         }
1191
1192         if (wd->ani_lock) return;
1193
1194         _imageslider_obj_move(wd, 1);
1195         
1196 }
1197
1198
1199
1200
1201