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