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