Merge "[Imageslider] Implemented Imageslider APIs to set the photo file of an item...
[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, Evas_Object *obj, void *event_info)
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, Evas_Object *obj, void *event_info)
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, Evas_Object *obj, void *event_info)
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, Evas_Object *obj, void *event_info)
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, 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, Evas_Object *obj, void *event_info)
399 {
400    Widget_Data *wd = data;
401
402    Evas_Event_Mouse_Down *ev = event_info;
403
404    Evas_Coord ix, iy, iw, ih;
405
406    Evas_Object *eo = NULL;
407
408    if (wd->ani_lock)
409       return;
410
411    wd->down_pos = ev->canvas;
412    wd->timestamp = ev->timestamp;
413    wd->move_cnt = MOVE_STEP;
414
415    wd->dx = ev->canvas.x;
416    wd->dy = ev->canvas.y;
417    wd->mx = ev->canvas.x;
418    wd->my = ev->canvas.y;
419
420    wd->dratio = 1;
421    wd->ratio = 1;
422
423    eo = (Evas_Object*)elm_layout_content_get((const Evas_Object*)obj, "swl.photo");
424    if (eo)
425       evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
426
427    if (iw != wd->w)
428      {
429         wd->on_zoom = EINA_TRUE;
430         edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
431      }
432
433 }
434
435 // Whenever MOUSE UP event occurs, Call this function.
436 // And make Click Event also.
437 static void
438 _ev_imageslider_up_cb(void *data, Evas * e, Evas_Object *obj, void *event_info)
439 {
440    Widget_Data *wd = data;
441
442    Evas_Event_Mouse_Up *ev = event_info;
443
444    Evas_Coord step;
445
446    int interval;
447
448    if (wd->ani_lock)
449       return;
450
451    if (wd->on_zoom)
452      {
453      }
454    else
455      {
456         step = wd->down_pos.x - ev->canvas.x;
457         interval = ev->timestamp - wd->timestamp;
458         if (step == 0 || interval == 0)
459           {
460              fprintf(stderr, "[[[ DEBUG ]]]: case1: emit CLICK event\n");
461              evas_object_smart_callback_call(wd->obj, SIG_CLICKED, NULL);
462              return;
463           }
464         if (interval < CLICK_TIME_MAX)
465           {
466              if (step < CLICK_WIDTH_MIN && step > CLICK_WIDTH_MIN)
467                {
468                   fprintf(stderr, "[[[ DEBUG ]]]: case2: emit CLICK event\n");
469                   evas_object_smart_callback_call(wd->obj, SIG_CLICKED, NULL);
470                   return;
471                }
472           }
473
474         if (interval < FLICK_TIME_MAX)
475           {
476              if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN)
477                {
478                   fprintf(stderr, "[[[ DEBUG ]]]:_ev_imageslider_up_cb-black zone (1)\n");
479
480                    _imageslider_obj_move(wd, 0);
481                }
482              else
483                {
484                   fprintf(stderr, "[[[ DEBUG ]]]:_ev_imageslider_up_cb-black zone (2)\n");
485
486                   _imageslider_obj_move(wd, step);
487                }
488
489           }
490         else
491           {
492              step = (wd->x - wd->move_x) << 1;
493              if (step <= wd->w && step >= -(wd->w))
494                {
495                   fprintf(stderr, "[[[ DEBUG ]]]:_ev_imageslider_up_cb-white zone (1)\n");
496
497                   _imageslider_obj_move(wd, 0);
498                }
499              else
500                {
501                   fprintf(stderr, "[[[ DEBUG ]]]:_ev_imageslider_up_cb-white zone (2)\n");
502
503                   _imageslider_obj_move(wd, step);
504                }
505           }
506      }
507
508 }
509
510 // Whenever MOUSE MOVE event occurs, Call this API.
511 static void
512 _ev_imageslider_move_cb(void *data, Evas * e, Evas_Object *obj, void *event_info)
513 {
514    int idx;
515
516    Evas_Object *eo;
517
518    Evas_Coord step;
519
520    Widget_Data *wd = data;
521
522    Evas_Event_Mouse_Move *ev = event_info;
523
524    Elm_Imageslider_Item *it;
525
526    if (wd->ani_lock)
527       return;
528
529    if (wd->move_cnt == MOVE_STEP)
530      {
531         if (wd->on_hold == EINA_FALSE)
532           {
533              wd->move_cnt = 0;
534
535              if (ev->buttons)
536                {
537                   step = ev->cur.canvas.x - wd->down_pos.x;
538                   if (step > 0)
539                     idx = BLOCK_LEFT;
540                   else
541                     idx = BLOCK_RIGHT;
542
543                   wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x)); 
544                   wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
545
546                   if (wd->on_zoom)
547                     {
548                        _imageslider_update_center_pos(wd, wd->move_x, wd->move_y, wd->y, wd->w);
549                     }
550                   else
551                     {
552                        _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
553                     }
554                }
555           }
556         else
557           {
558              wd->mx = ev->cur.canvas.x;
559              wd->my = ev->cur.canvas.y;
560
561              wd->ratio =
562              sqrt((wd->mx - wd->mmx) * (wd->mx - wd->mmx) + (wd->my - wd->mmy) * (wd->my - wd->mmy));
563
564              eo = (Evas_Object*)elm_layout_content_get((const Evas_Object*)obj, "swl.photo");
565              if (eo)
566                {
567                   it = eina_list_data_get(wd->cur);
568                   if (((it->w * wd->ratio / wd->dratio) / it->ow) < MAX_ZOOM_SIZE)
569                     {
570                        edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
571                        evas_object_resize(eo, it->w * wd->ratio / wd->dratio, it->h * wd->ratio / wd->dratio);
572                        evas_object_size_hint_min_set(eo, it->w * wd->ratio / wd->dratio, it->h * wd->ratio / wd->dratio);
573                        elm_layout_content_set(obj, "swl.photo", eo);
574                     }
575                }
576           }
577      }
578    wd->move_cnt++;
579
580 }
581
582 #if 0
583 // Whenever CLICK event occurs, Call this API
584 // But, DONOT emit CLICK event.
585 // DO NOT use this callback function. Remove later.
586 static void
587 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
588 {
589    fprintf(stderr, "[[[ DEBUG ]]]: Call the callback function about Click event!, But DONOT emit CLICK event in the callback function!\n");
590 }
591 #endif
592
593 static inline double
594 time_get(Evas_Coord x, Evas_Coord w)
595 {
596    double time;
597
598    time = (-sin(x / w) + 1) / 500;
599
600    if (time == 0)
601       time = ANI_TIME;
602
603    return time;
604 }
605
606 static Eina_Bool
607 _icon_to_image(void *data)
608 {
609    Widget_Data *wd = data;
610
611    wd->moving = 0;
612    _imageslider_update(wd);
613
614    if (wd->queue_idler)
615      {
616         ecore_idler_del(wd->queue_idler);
617         wd->queue_idler = NULL;
618      }
619    return ECORE_CALLBACK_CANCEL;
620 }
621
622 static int
623 _check_drag(int state, void *data)
624 {
625    Widget_Data *wd = data;
626
627    Elm_Imageslider_Item *it;
628
629    Evas_Coord ix, iy, iw, ih;
630
631    double dx, dy = 0;
632
633    Eina_List *l[BLOCK_MAX];
634
635    Evas_Object *eo = NULL;
636
637    l[BLOCK_LEFT] = eina_list_prev(wd->cur);
638    l[BLOCK_CENTER] = wd->cur;
639    l[BLOCK_RIGHT] = eina_list_next(wd->cur);
640
641    it = eina_list_data_get(l[state]);
642
643    eo = (Evas_Object*)elm_layout_content_get(wd->ly[state], "swl.photo");
644    if (eo)
645      evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
646    edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
647
648    if ((iw != wd->w) || ((dx != 0) || (dy != 0)))
649      {
650         elm_layout_content_set(wd->ly[state], "swl.photo", NULL);
651      }
652    else
653      return 1;
654
655    return 0;
656 }
657
658 static void
659 _check_zoom(void *data)
660 {
661    Widget_Data *wd = data;
662
663    Elm_Imageslider_Item *it;
664
665    Evas_Coord ix, iy, iw, ih;
666
667    double dx, dy = 0;
668
669    Evas_Object *eo = NULL;
670
671    it = eina_list_data_get(wd->cur);
672
673    eo = (Evas_Object*)elm_layout_content_get(wd->ly[BLOCK_CENTER], "swl.photo");
674    if (eo)
675       evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
676    evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
677    edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo", &dx, &dy);
678
679    if ((iw != wd->w) || ((dx != 0) || (dy != 0)))
680      {
681         wd->on_zoom = EINA_TRUE;
682         edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.off", "block");
683      }
684    else
685      {
686         wd->on_zoom = EINA_FALSE;
687         edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
688      }
689 }
690
691 static Eina_Bool
692 _timer_cb(void *data)
693 {
694    Widget_Data *wd;
695
696    Elm_Imageslider_Item *it;
697
698    struct timeval tv;
699
700    int t;
701
702    int ret;
703
704    wd = data;
705    if (wd->ani_lock == 0)
706       return 0;
707
708    gettimeofday(&tv, NULL);
709
710    t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
711    gettimeofday(&wd->tv, NULL);
712
713    t = t / ANI_TIME_MSEC;
714    if (t <= STEP_WEIGHT_MIN)
715      t = STEP_WEIGHT_DEF;
716    else if (t > STEP_WEIGHT_MAX)
717      t = STEP_WEIGHT_MAX;
718
719    wd->move_x += (wd->step) * t;
720
721    if (wd->step < 0 && wd->move_x < wd->x)
722      wd->move_x = wd->x;
723    else if (wd->step > 0 && wd->move_x > wd->x)
724      wd->move_x = wd->x;
725
726    _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
727
728    if (wd->move_x == wd->x)
729      {
730         wd->ani_lock = 0;
731         if (wd->cur)
732           {
733              it = eina_list_data_get(wd->cur);
734              if (it->func)
735                it->func(it->data, wd->obj, it);
736           }
737         if (wd->cur)
738           {
739              it = eina_list_data_get(wd->cur);
740              evas_object_smart_callback_call(wd->obj, "changed", it);
741           }
742
743         ret = _check_drag(BLOCK_LEFT, wd);
744         ret = _check_drag(BLOCK_RIGHT, wd);
745         _check_zoom(wd);
746
747         if (!wd->queue_idler)
748           wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
749
750         if (wd->anim_timer)
751           {
752              ecore_timer_del(wd->anim_timer);
753              wd->anim_timer = NULL;
754           }
755
756         return ECORE_CALLBACK_CANCEL;
757      }
758
759    return ECORE_CALLBACK_RENEW;
760 }
761
762 static void
763 _anim(Widget_Data * wd)
764 {
765    Evas_Coord w;
766
767    if (wd->x == wd->move_x)
768      {
769         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
770         return;
771      }
772
773    wd->ani_lock = 1;
774
775    w = wd->move_x;
776    gettimeofday(&wd->tv, NULL);
777
778    if (!wd->anim_timer)
779      wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd);
780 }
781
782 // Update Image Slider Items.
783 static void
784 _imageslider_update(Widget_Data * wd)
785 {
786    int i;
787
788    Eina_List *l[BLOCK_MAX];
789
790    Elm_Imageslider_Item *it;
791
792    Evas_Object *eo;
793
794    if (!wd)
795      return;
796
797    if (!wd->cur) return;
798
799    l[BLOCK_LEFT] = eina_list_prev(wd->cur);
800    l[BLOCK_CENTER] = wd->cur;
801    l[BLOCK_RIGHT] = eina_list_next(wd->cur);
802
803    for (i = 0; i < BLOCK_MAX; i++)
804      {
805         eo = (Evas_Object*)elm_layout_content_get((const Evas_Object*)wd->ly[i], "swl.photo");
806         if (!l[i])
807           {
808              elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
809           }
810         else
811           {
812              it = eina_list_data_get(l[i]);
813              if (!it)
814                return;
815
816              if (!eo)
817                {
818                   eo = elm_image_add(wd->obj);
819                   elm_layout_content_set(wd->ly[i], "swl.photo", eo);
820                   //elm_image_prescale_set(eo, wd->w);
821                   elm_image_file_set(eo, it->photo_file, NULL);
822                   elm_image_object_size_get(eo, &it->w, &it->h);
823                   evas_object_geometry_get(eo, &it->ox, &it->oy, &it->ow, &it->oh);
824                   it->ow = it->w;
825                   it->oh = it->h;
826                   elm_layout_content_set(wd->ly[i], "swl.photo", eo);
827                }
828
829              if (wd->moving != it->moving)
830                {
831                   it->moving = wd->moving;
832                   if (wd->moving)
833                     {
834                        //elm_image_prescale_set(eo, MOVING_IMAGE_SIZE);
835                     }
836                   else
837                     {
838                        //elm_image_prescale_set(eo, it->w > it->h ? it->w : it->h);
839                     }
840                }
841           }
842      }
843
844    _anim(wd);
845 }
846
847 /** 
848 * Add an Image Slider widget 
849
850 * @param        parent  The parent object 
851 * @return       The new Image slider object or NULL if it cannot be created 
852
853 * @ingroup Imageslider 
854 */
855 EAPI Evas_Object *
856 elm_imageslider_add(Evas_Object *parent)
857 {
858    int i;
859
860    Evas_Object *obj = NULL;
861
862    Widget_Data *wd = NULL;
863
864    Evas *e;
865
866    if (!parent)
867      return NULL;
868
869    wd = ELM_NEW(Widget_Data);
870    e = evas_object_evas_get(parent);
871    if (e == NULL) return NULL;
872
873    obj = elm_widget_add(e);
874    ELM_SET_WIDTYPE(widtype, "imageslider");
875    elm_widget_type_set(obj, "imageslider");
876    elm_widget_sub_object_add(parent, obj);
877    elm_widget_data_set(obj, wd);
878    elm_widget_del_hook_set(obj, _del_hook);
879    elm_widget_theme_hook_set(obj, _theme_hook);
880
881    wd->clip = evas_object_rectangle_add(e);
882    elm_widget_resize_object_set(obj, wd->clip);
883
884    for (i = 0; i < BLOCK_MAX; i++)
885      {
886         wd->ly[i] = elm_layout_add(obj);
887         elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
888         elm_widget_sub_object_add(obj, wd->ly[i]);
889         evas_object_smart_member_add(wd->ly[i], obj);
890
891         //edje_object_signal_callback_add(elm_layout_edje_get(wd->ly[i]), "elm,photo,clicked", "", _signal_clicked, obj);
892         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, _ev_imageslider_down_cb, wd);
893         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, _ev_imageslider_up_cb, wd);
894         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, _ev_imageslider_move_cb, wd);
895         evas_object_clip_set(wd->ly[i], wd->clip);
896         evas_object_show(wd->ly[i]);
897      }
898
899    wd->obj = obj;
900
901    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
902    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
903    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
904    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
905
906    _sizing_eval(obj);
907
908    return obj;
909 }
910
911 /** 
912 * Append an Image Slider item 
913
914 * @param        obj          The Image Slider object 
915 * @param        photo_file   photo file path 
916 * @param        func         callback function 
917 * @param        data         callback data 
918 * @return       The Image Slider item handle or NULL 
919
920 * @ingroup Imageslider 
921 */
922 EAPI Elm_Imageslider_Item *
923 elm_imageslider_item_append(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
924 {
925    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
926    Widget_Data *wd;
927
928    Elm_Imageslider_Item *it;
929
930    if (!obj || !(wd = elm_widget_data_get(obj)))
931      return NULL;
932
933    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
934    if (!it)
935       return NULL;
936    it->photo_file = eina_stringshare_add(photo_file);
937    it->func = func;
938    it->data = data;
939    it->obj = obj;
940    wd->its = eina_list_append(wd->its, it);
941
942    if (!wd->cur)
943       wd->cur = wd->its;
944
945    _imageslider_update(wd);
946
947    return it;
948 }
949
950 /**
951 * Insert an Image Slider item into the Image Slider Widget by using the given index.
952 *
953 * @param        obj                     The Image Slider object
954 * @param        photo_file      photo file path
955 * @param        func            callback function
956 * @param        index           required position
957 * @param        data            callback data
958 * @return       The Image Slider item handle or NULL
959 *
960 * @ingroup      Imageslider
961 */
962 EAPI Elm_Imageslider_Item *
963 elm_imageslider_item_append_relative(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, unsigned int index, void *data)
964 {
965    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
966    Widget_Data *wd;
967
968    Elm_Imageslider_Item *it;
969
970    fprintf(stderr, "[[[ DEBUG ]]]:: New elm_imageslider_item_append_relative()\n");
971
972    if (!obj || !(wd = elm_widget_data_get(obj)))
973      return NULL;
974
975    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
976    if (!it)
977       return NULL;
978
979    it->obj = obj;
980    it->photo_file = eina_stringshare_add(photo_file);
981    it->func = func;
982    it->data = data;
983
984    wd->its =
985       eina_list_append_relative(wd->its, it, eina_list_nth(wd->its, index - 2));
986
987    if (!wd->cur)
988       wd->cur = wd->its;
989
990    _imageslider_update(wd);
991
992    return it;
993 }
994
995 /** 
996 * Prepend Image Slider item 
997
998 * @param        obj          The Image Slider object 
999 * @param        photo_file   photo file path 
1000 * @param        func         callback function 
1001 * @param        data         callback data 
1002 * @return       The imageslider item handle or NULL 
1003
1004 * @ingroup Imageslider 
1005 */
1006 EAPI Elm_Imageslider_Item *
1007 elm_imageslider_item_prepend(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
1008 {
1009    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1010    Widget_Data *wd;
1011
1012    Elm_Imageslider_Item *it;
1013
1014    if (!obj || !(wd = elm_widget_data_get(obj)))
1015      return NULL;
1016
1017    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
1018    it->photo_file = eina_stringshare_add(photo_file);
1019    it->func = func;
1020    it->data = data;
1021    it->obj = obj;
1022    wd->its = eina_list_prepend(wd->its, it);
1023
1024    if (!wd->cur)
1025       wd->cur = wd->its;
1026
1027    _imageslider_update(wd);
1028
1029    return it;
1030 }
1031
1032 /**
1033 * Delete the selected Image Slider item
1034 *
1035 * @param it             The selected Image Slider item handle
1036 *
1037 * @ingroup Imageslider
1038 */
1039 EAPI void
1040 elm_imageslider_item_del(Elm_Imageslider_Item * it)
1041 {
1042    Widget_Data *wd;
1043
1044    Elm_Imageslider_Item *_it;
1045
1046    Eina_List *l;
1047
1048    if (!it || !(wd = elm_widget_data_get(it->obj)))
1049      return;
1050
1051    EINA_LIST_FOREACH(wd->its, l, _it)
1052      {
1053         if (_it == it)
1054           {
1055              if (l == wd->cur)
1056                 wd->cur = eina_list_prev(wd->cur);
1057              wd->its = eina_list_remove(wd->its, it);
1058              if (!wd->cur)
1059                 wd->cur = wd->its;
1060              break;
1061           }
1062      }
1063
1064    _imageslider_update(wd);
1065
1066 }
1067
1068 /**
1069 * Get the selected Image Slider item
1070 *
1071 * @param obj            The Image Slider object
1072 * @return The selected Image Slider item or NULL
1073 *
1074 * @ingroup Imageslider
1075 */
1076 EAPI Elm_Imageslider_Item *
1077 elm_imageslider_selected_item_get(Evas_Object *obj)
1078 {
1079    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1080    Widget_Data *wd;
1081
1082    if (!obj || (!(wd = elm_widget_data_get(obj))))
1083      return NULL;
1084
1085    if (!wd->cur)
1086       return NULL;
1087
1088    return eina_list_data_get(wd->cur);
1089 }
1090
1091 /**
1092 * Get whether an Image Slider item is selected or not
1093 *
1094 * @param it              the selected Image Slider item
1095 * @return EINA_TRUE or EINA_FALSE
1096 *
1097 * @ingroup Imageslider
1098 */
1099 EAPI Eina_Bool
1100 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
1101 {
1102    Widget_Data *wd;
1103
1104    if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
1105      return EINA_FALSE;
1106
1107    if (!wd->cur)
1108       return EINA_FALSE;
1109
1110    if (eina_list_data_get(wd->cur) == it)
1111       return EINA_TRUE;
1112    else
1113       return EINA_FALSE;
1114
1115 }
1116
1117 /**
1118 * Set the selected Image Slider item
1119 *
1120 * @param it             The Imaga Slider item
1121 *
1122 * @ingroup Imageslider
1123 */
1124 EAPI void
1125 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
1126 {
1127    int i;
1128
1129    Widget_Data *wd;
1130
1131    Elm_Imageslider_Item *_it;
1132
1133    Eina_List *l;
1134
1135    Evas_Object *eo;
1136
1137    if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
1138      return;
1139
1140    EINA_LIST_FOREACH(wd->its, l, _it)
1141      {
1142         if (_it == it)
1143           wd->cur = l;
1144      }
1145
1146    for (i = 0; i < BLOCK_MAX; i++)
1147      {
1148        eo = (Evas_Object*)elm_layout_content_get(wd->ly[i], "swl.photo");
1149        if (eo)
1150           {
1151              elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
1152           }
1153      }
1154
1155    _imageslider_update(wd);
1156
1157 }
1158
1159 /**
1160 * Get the photo file path of given Image Slider item
1161 *
1162 * @param it             The Image Slider item
1163 * @return The photo file path or NULL;
1164 *
1165 * @ingroup Imageslider
1166 */
1167 EAPI const char *
1168 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
1169 {
1170    if (!it) return NULL;
1171
1172    return it->photo_file;
1173 }
1174
1175 /**
1176 * Sets the photo file path of given Image Slider item
1177 *
1178 * @param it         The Image Slider item
1179 * @param photo_file The photo file path or NULL;
1180 *
1181 * @ingroup Imageslider
1182 */
1183 EAPI void
1184 elm_imageslider_item_photo_file_set(Elm_Imageslider_Item *it, const char *photo_file)
1185 {
1186    if (!it) return;
1187    ELM_CHECK_WIDTYPE(it->obj, widtype);
1188
1189    if (photo_file)
1190      {
1191         eina_stringshare_replace(&(it->photo_file), photo_file);
1192         elm_imageslider_item_update(it);
1193      }
1194 }
1195
1196 /**
1197 * Get the previous Image Slider item
1198 *
1199 * @param it             The Image Slider item
1200 * @return The previous Image Slider item or NULL
1201 *
1202 * @ingroup Imageslider
1203 */
1204 EAPI Elm_Imageslider_Item *
1205 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
1206 {
1207    Widget_Data *wd;
1208
1209    Elm_Imageslider_Item *_it;
1210
1211    Eina_List *l;
1212
1213    if (!it || (!(wd = elm_widget_data_get(it->obj))))
1214      return NULL;
1215
1216    EINA_LIST_FOREACH(wd->its, l, _it)
1217      {
1218         if (_it == it)
1219           {
1220              l = eina_list_prev(l);
1221              if (!l)
1222                break;
1223              return eina_list_data_get(l);
1224           }
1225      }
1226
1227    return NULL;
1228 }
1229
1230 /**
1231 * Get the next Image Slider item
1232 *
1233 * @param it             The Image Slider item
1234 * @return The next Image Slider item or NULL
1235 *
1236 * @ingroup Imageslider
1237 */
1238 EAPI Elm_Imageslider_Item *
1239 elm_imageslider_item_next(Elm_Imageslider_Item * it)
1240 {
1241    Widget_Data *wd;
1242
1243    Elm_Imageslider_Item *_it;
1244
1245    Eina_List *l;
1246
1247    if (!it || (!(wd = elm_widget_data_get(it->obj))))
1248      return NULL;
1249
1250    EINA_LIST_FOREACH(wd->its, l, _it)
1251      {
1252         if (_it == it)
1253           {
1254              l = eina_list_next(l);
1255              if (!l)
1256                break;
1257              return eina_list_data_get(l);
1258           }
1259      }
1260
1261    return NULL;
1262 }
1263
1264 /**
1265 * Move to the previous Image Slider item
1266 *
1267 * @param obj    The Image Slider object
1268 *
1269 * @ingroup Imageslider
1270 */
1271 EAPI void
1272 elm_imageslider_prev(Evas_Object *obj)
1273 {
1274    ELM_CHECK_WIDTYPE(obj, widtype);
1275    Widget_Data *wd;
1276
1277    if (!obj || (!(wd = elm_widget_data_get(obj))))
1278      return;
1279
1280    if (wd->ani_lock)
1281      return;
1282
1283    _imageslider_obj_move(wd, -1);
1284 }
1285
1286 /**
1287 * Move to the next Image Slider item
1288 *
1289 * @param obj The Image Slider object
1290 *
1291 * @ingroup Imageslider
1292 */
1293 EAPI void
1294 elm_imageslider_next(Evas_Object * obj)
1295 {
1296    ELM_CHECK_WIDTYPE(obj, widtype);
1297    Widget_Data *wd;
1298
1299    if (!obj || (!(wd = elm_widget_data_get(obj))))
1300      return;
1301
1302    if (wd->ani_lock)
1303      return;
1304
1305    _imageslider_obj_move(wd, 1);
1306
1307 }
1308
1309 /**
1310 * Updates an Image Slider item
1311 *
1312 * @param it The Image Slider item
1313 *
1314 * @ingroup Imageslider
1315 */
1316 EAPI void
1317 elm_imageslider_item_update(Elm_Imageslider_Item *it)
1318 {
1319    Widget_Data *wd;
1320    int i = 0;
1321
1322    if (!it || (!(wd = elm_widget_data_get(it->obj)))) return;
1323    ELM_CHECK_WIDTYPE(it->obj, widtype);
1324
1325    if (it == eina_list_data_get(eina_list_prev(wd->cur)))
1326      elm_layout_content_set(wd->ly[BLOCK_LEFT], "swl.photo", NULL);
1327    else if (it == eina_list_data_get(wd->cur))
1328      elm_layout_content_set(wd->ly[BLOCK_CENTER], "swl.photo", NULL);
1329    else if (it == eina_list_data_get(eina_list_prev(wd->cur)))
1330      elm_layout_content_set(wd->ly[BLOCK_RIGHT], "swl.photo", NULL);
1331
1332    _imageslider_update(wd);
1333 }