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