Merge "[multibuttonentry]CQ:H0100137536- 'item,selected' signal sends 2 times when...
[framework/uifw/elementary.git] / src / lib / elm_imageslider.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <Elementary.h>
4 #include "elm_priv.h"
5
6 typedef struct _Widget_Data Widget_Data;
7
8 #define ANI_STEP (14 * elm_scale_get())
9 #define ANI_TIME (0.005)
10 #define ANI_TIME_MSEC (12)
11 #define CLICK_TIME_MAX (180)
12 #define CLICK_WIDTH_MIN (elm_finger_size_get() >> 1)
13 #define FLICK_TIME_MAX (200)
14 #define FLICK_WIDTH_MIN (elm_finger_size_get() >> 2)
15 #define MOVE_STEP (3)
16 #define STEP_WEIGHT_DEF (1)
17 #define STEP_WEIGHT_MAX (2)
18 #define STEP_WEIGHT_MIN (0)
19 #define MOVING_IMAGE_SIZE (128)
20 #define MAX_ZOOM_SIZE (6)
21 #define INTERVAL_WIDTH (15)
22 #define MULTITOUCHDEVICE (11)
23
24 // Enumeration for layout.
25 enum
26 {
27    BLOCK_LEFT = 0,
28    BLOCK_CENTER,
29    BLOCK_RIGHT,
30    BLOCK_MAX
31 };
32
33 // Image Slider Item.
34 struct _Imageslider_Item
35 {
36    Evas_Object *obj;
37    const char *photo_file;
38    void (*func) (void *data, Evas_Object *obj, void *event_info);
39    void *data;
40 };
41
42 // Image Slider Widget Data.
43 struct _Widget_Data
44 {
45    Evas_Object *ly[BLOCK_MAX];
46    Evas_Object *clip;
47    Eina_List *its;
48    Eina_List *cur;
49    Evas_Coord x, y, w, h;
50    Evas_Object *obj;
51    Ecore_Idler *queue_idler;
52    Ecore_Timer *anim_timer;
53
54    Evas_Coord_Point down_pos;
55    Evas_Coord move_x;
56    Evas_Coord move_y;
57    Evas_Coord dest_x;
58    struct timeval tv;
59    unsigned int timestamp;
60    int step;
61    int move_cnt;
62    int ani_lock:1;
63    int moving:1;
64 };
65
66 // Global value declaration.
67 static const char *widtype = NULL;
68
69 static const char SIG_CLICKED[] = "clicked";
70
71 // Internal function declaration.
72 static void _del_hook(Evas_Object *obj);
73
74 static void _theme_hook(Evas_Object *obj);
75
76 static void _sizing_eval(Evas_Object *obj);
77
78 static void _imageslider_move(void *data, Evas * e, Evas_Object *obj, void *event_info);
79 static void _imageslider_resize(void *data, Evas * e, Evas_Object *obj, void *event_info);
80 static void _imageslider_show(void *data, Evas * e, Evas_Object *obj, void *event_info);
81 static void _imageslider_hide(void *data, Evas * e, Evas_Object *obj, void *event_info);
82 static void _imageslider_update(Widget_Data * wd);
83
84 static void _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w);
85
86 static void _imageslider_obj_shift(Widget_Data * wd, Eina_Bool left);
87
88 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step);
89
90 static Eina_Bool _icon_to_image(void *data);
91
92 static int _check_drag(int state, void *data);
93
94 static void _anim(Widget_Data * wd);
95
96 static Eina_Bool _timer_cb(void *data);
97
98 static void _ev_imageslider_down_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
99 static void _ev_imageslider_up_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
100 static void _ev_imageslider_move_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
101
102 // Whenever the Image Slider item is deleted, Call this funtion.
103 static void
104 _del_hook(Evas_Object *obj)
105 {
106    Widget_Data *wd;
107
108    wd = elm_widget_data_get(obj);
109
110    if (!wd) return;
111
112    if (wd->its)
113      {
114         eina_list_free(wd->its);
115         wd->its = NULL;
116      }
117
118    if (wd->queue_idler)
119      {
120         ecore_idler_del(wd->queue_idler);
121         wd->queue_idler = NULL;
122      }
123
124    if (wd->anim_timer)
125      {
126         ecore_timer_del(wd->anim_timer);
127         wd->anim_timer = NULL;
128      }
129
130    if (wd) free(wd);
131 }
132
133 // Whenever require processing theme, Call this function
134 static void
135 _theme_hook(Evas_Object *obj)
136 {
137    int i = 0;
138    Widget_Data *wd = elm_widget_data_get(obj);
139
140    if (!wd) return;
141
142    for (i = 0; i < BLOCK_MAX; i++)
143      {
144         if (wd->ly[i])
145            elm_layout_theme_set(wd->ly[i], "imageslider", "base",
146                                 elm_object_style_get(obj));
147         evas_object_show(wd->ly[i]);
148      }
149    _imageslider_update(wd);
150    _sizing_eval(obj);
151 }
152
153 // Resize Image Slider item.
154 static void
155 _sizing_eval(Evas_Object *obj)
156 {
157    Evas *e;
158
159    Widget_Data *wd = elm_widget_data_get(obj);
160
161    if (!wd)
162      return;
163
164    e = evas_object_evas_get(wd->obj);
165
166    _imageslider_move(obj, e, obj, NULL);
167    _imageslider_resize(obj, e, obj, NULL);
168 }
169
170 // Whenever MOVE event occurs, Call this function.
171 static void
172 _imageslider_move(void *data, Evas * e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
173 {
174    Widget_Data *wd;
175
176    Evas_Coord x, y;
177
178    if (!data)
179      return;
180
181    wd = elm_widget_data_get((Evas_Object *) data);
182    if (!wd)
183      return;
184
185    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
186    wd->x = x;
187    wd->y = y;
188
189    _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
190 }
191
192 // Whenever RESIZE event occurs, Call this fucntion.
193 static void
194 _imageslider_resize(void *data, Evas * e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
195 {
196    int i;
197
198    Widget_Data *wd;
199
200    Evas_Coord w, h;
201
202    if (!data)
203      return;
204
205    wd = elm_widget_data_get((Evas_Object *) data);
206    if (!wd)
207      return;
208
209    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
210    DBG("%d %d -resize\n", w, h);
211    wd->w = w;
212    wd->h = h;
213
214    for (i = 0; i < BLOCK_MAX; i++)
215      {
216         evas_object_resize(wd->ly[i], w, h);
217      }
218
219    _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
220
221 }
222
223 // Whenever SHOW event occurs, Call this function.
224 static void
225 _imageslider_show(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
226 {
227    Widget_Data *wd;
228
229    if (!data)
230      {
231         return;
232      }
233
234    wd = elm_widget_data_get((Evas_Object *) data);
235    if (!wd) return;
236
237    evas_object_show(wd->clip);
238 }
239
240 // Whenever HIDE event occurs, Call this function.
241 static void
242 _imageslider_hide(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
243 {
244    Widget_Data *wd;
245
246    if (!data) return;
247
248    wd = elm_widget_data_get((Evas_Object *) data);
249    if (!wd) return;
250    evas_object_hide(wd->clip);
251 }
252
253 // Update Image Slider item position.
254 static void
255 _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w)
256 {
257    evas_object_move(wd->ly[BLOCK_LEFT], x - (w + INTERVAL_WIDTH), y);
258    evas_object_move(wd->ly[BLOCK_CENTER], x, y);
259    evas_object_move(wd->ly[BLOCK_RIGHT], x + (w + INTERVAL_WIDTH), y);
260 }
261
262 // Shift next/previous Image Slider item in layouts.
263 static void
264 _imageslider_obj_shift(Widget_Data * wd, Eina_Bool left)
265 {
266    if (!left)
267      {
268         Evas_Object *ly_temp;
269         ly_temp = wd->ly[BLOCK_LEFT];
270         wd->ly[BLOCK_LEFT] = wd->ly[BLOCK_CENTER];
271         wd->ly[BLOCK_CENTER] = wd->ly[BLOCK_RIGHT];
272         wd->ly[BLOCK_RIGHT] = ly_temp;
273         elm_object_part_content_set(wd->ly[BLOCK_RIGHT], "swl.photo", NULL);
274      }
275    else
276      {
277         Evas_Object *ly_temp;
278         ly_temp = wd->ly[BLOCK_RIGHT];
279         wd->ly[BLOCK_RIGHT] = wd->ly[BLOCK_CENTER];
280         wd->ly[BLOCK_CENTER] = wd->ly[BLOCK_LEFT];
281         wd->ly[BLOCK_LEFT] = ly_temp;
282         elm_object_part_content_set(wd->ly[BLOCK_LEFT], "swl.photo", NULL);
283      }
284 }
285
286 // Move the current Image Slider item and update.
287 static void
288 _imageslider_obj_move(Widget_Data * wd, Evas_Coord step)
289 {
290    if (step > 0)
291      {
292         wd->cur = eina_list_next(wd->cur);
293         if (wd->cur == NULL)
294           {
295              wd->cur = eina_list_last(wd->its);
296              wd->step = ANI_STEP;
297           }
298         else
299           {
300              wd->step = -ANI_STEP;
301              wd->move_x += wd->w;
302              _imageslider_obj_shift(wd, EINA_FALSE);
303           }
304         wd->moving = EINA_TRUE;
305      }
306    else if (step < 0)
307      {
308         wd->cur = eina_list_prev(wd->cur);
309         if (wd->cur == NULL)
310           {
311              wd->cur = wd->its;
312              wd->step = -ANI_STEP;
313           }
314         else
315           {
316              wd->step = ANI_STEP;
317              wd->move_x -= wd->w;
318              _imageslider_obj_shift(wd, EINA_TRUE);
319           }
320         wd->moving = EINA_TRUE;
321      }
322    else
323      {
324         if (wd->move_x < 0)
325           wd->step = ANI_STEP;
326         else
327           wd->step = -ANI_STEP;
328         wd->moving = EINA_FALSE;
329      }
330
331    _imageslider_update(wd);
332 }
333
334 // Whenever MOUSE DOWN event occurs, Call this function.
335 static void
336 _ev_imageslider_down_cb(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
337 {
338    Widget_Data *wd = data;
339    Evas_Event_Mouse_Down *ev = event_info;
340
341    if (wd->ani_lock)
342       return;
343
344    wd->down_pos = ev->canvas;
345    wd->timestamp = ev->timestamp;
346    wd->move_cnt = MOVE_STEP;
347 }
348
349 // Whenever MOUSE UP event occurs, Call this function.
350 // And make Click Event also.
351 static void
352 _ev_imageslider_up_cb(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
353 {
354    Widget_Data *wd = data;
355
356    Evas_Event_Mouse_Up *ev = event_info;
357
358    Evas_Coord step;
359
360    int interval;
361
362    if (wd->ani_lock) return;
363
364    step = wd->down_pos.x - ev->canvas.x;
365    interval = ev->timestamp - wd->timestamp;
366    if (step == 0 || interval == 0)
367      {
368         DBG("case1: emit CLICK event\n");
369         evas_object_smart_callback_call(wd->obj, SIG_CLICKED, NULL);
370         return;
371      }
372    if (interval < CLICK_TIME_MAX)
373      {
374         if (step < CLICK_WIDTH_MIN && step > CLICK_WIDTH_MIN)
375           {
376              DBG("case2: emit CLICK event\n");
377              evas_object_smart_callback_call(wd->obj, SIG_CLICKED, NULL);
378              return;
379           }
380      }
381
382    if (interval < FLICK_TIME_MAX)
383      {
384         if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN)
385           {
386              DBG("ev_imageslider_up_cb-black zone (1)\n");
387
388              _imageslider_obj_move(wd, 0);
389           }
390         else
391           {
392              DBG("ev_imageslider_up_cb-black zone (2)\n");
393
394              _imageslider_obj_move(wd, step);
395           }
396
397      }
398    else
399      {
400         step = (wd->x - wd->move_x) << 1;
401         if (step <= wd->w && step >= -(wd->w))
402           {
403              DBG("ev_imageslider_up_cb-white zone (1)\n");
404
405              _imageslider_obj_move(wd, 0);
406           }
407         else
408           {
409              DBG("ev_imageslider_up_cb-white zone (2)\n");
410
411              _imageslider_obj_move(wd, step);
412           }
413      }
414 }
415
416 // Whenever MOUSE MOVE event occurs, Call this
417 static void
418 _ev_imageslider_move_cb(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
419 {
420    int idx = 0;
421    Evas_Coord step;
422    Widget_Data *wd = data;
423    Evas_Event_Mouse_Move *ev = event_info;
424
425    if (wd->ani_lock) return;
426    if (wd->move_cnt == MOVE_STEP)
427      {
428         wd->move_cnt = 0;
429
430         if (ev->buttons)
431           {
432              step = ev->cur.canvas.x - wd->down_pos.x;
433              if (step > 0)
434                idx = BLOCK_LEFT;
435              else
436                idx = BLOCK_RIGHT;
437              wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
438              wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
439              _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
440           }
441      }
442    wd->move_cnt++;
443 }
444
445 static inline double
446 time_get(Evas_Coord x, Evas_Coord w)
447 {
448    double time;
449
450    time = (-sin(x / w) + 1) / 500;
451
452    if (time == 0)
453       time = ANI_TIME;
454
455    return time;
456 }
457
458 static Eina_Bool
459 _icon_to_image(void *data)
460 {
461    Widget_Data *wd = data;
462
463    wd->moving = 0;
464    _imageslider_update(wd);
465
466    if (wd->queue_idler)
467      wd->queue_idler = NULL;
468    return ECORE_CALLBACK_CANCEL;
469 }
470
471 static int
472 _check_drag(int state, void *data)
473 {
474    Widget_Data *wd = data;
475
476    Elm_Imageslider_Item *it;
477
478    Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0;
479
480    double dx = 0, dy = 0;
481
482    Eina_List *l[BLOCK_MAX];
483
484    Evas_Object *eo = NULL;
485
486    l[BLOCK_LEFT] = eina_list_prev(wd->cur);
487    l[BLOCK_CENTER] = wd->cur;
488    l[BLOCK_RIGHT] = eina_list_next(wd->cur);
489
490    it = eina_list_data_get(l[state]);
491
492    eo = elm_object_part_content_get(wd->ly[state], "swl.photo");
493    if (eo)
494      evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
495    edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
496
497    if ((iw != wd->w) || ((dx != 0) || (dy != 0)))
498      {
499         elm_object_part_content_set(wd->ly[state], "swl.photo", NULL);
500      }
501    else
502      return 1;
503
504    return 0;
505 }
506
507 static Eina_Bool
508 _timer_cb(void *data)
509 {
510    Widget_Data *wd;
511
512    Elm_Imageslider_Item *it;
513
514    struct timeval tv;
515
516    int t = 0;
517    int ret = 0;
518
519    wd = data;
520    if (!wd->ani_lock)
521      {
522         if (wd->anim_timer)
523           wd->anim_timer = NULL;
524         return ECORE_CALLBACK_CANCEL;
525      }
526    gettimeofday(&tv, NULL);
527
528    t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
529    gettimeofday(&wd->tv, NULL);
530
531    t = t / ANI_TIME_MSEC;
532    if (t <= STEP_WEIGHT_MIN)
533      t = STEP_WEIGHT_DEF;
534    else if (t > STEP_WEIGHT_MAX)
535      t = STEP_WEIGHT_MAX;
536
537    wd->move_x += (wd->step) * t;
538
539    if (wd->step < 0 && wd->move_x < wd->x)
540      wd->move_x = wd->x;
541    else if (wd->step > 0 && wd->move_x > wd->x)
542      wd->move_x = wd->x;
543
544    _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
545
546    if (wd->move_x == wd->x)
547      {
548         wd->ani_lock = EINA_FALSE;
549         if (wd->cur)
550           {
551              it = eina_list_data_get(wd->cur);
552              if (it->func)
553                it->func(it->data, wd->obj, it);
554           }
555         if (wd->cur)
556           {
557              it = eina_list_data_get(wd->cur);
558              evas_object_smart_callback_call(wd->obj, "changed", it);
559           }
560
561         ret = _check_drag(BLOCK_LEFT, wd);
562         ret = _check_drag(BLOCK_RIGHT, wd);
563
564         if (!wd->queue_idler)
565           wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
566
567         if (wd->anim_timer)
568           wd->anim_timer = NULL;
569
570         return ECORE_CALLBACK_CANCEL;
571      }
572
573    return ECORE_CALLBACK_RENEW;
574 }
575
576 static void
577 _anim(Widget_Data * wd)
578 {
579    Evas_Coord w;
580
581    if (wd->x == wd->move_x)
582      {
583         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
584         return;
585      }
586
587    wd->ani_lock = EINA_TRUE;
588
589    w = wd->move_x;
590    gettimeofday(&wd->tv, NULL);
591
592    if (!wd->anim_timer)
593      wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd);
594 }
595
596 // Update Image Slider Items.
597 static void
598 _imageslider_update(Widget_Data * wd)
599 {
600    int i;
601
602    Eina_List *l[BLOCK_MAX];
603
604    Elm_Imageslider_Item *it;
605
606    Evas_Object *eo;
607
608    if (!wd) return;
609
610    if (!wd->cur) return;
611
612    l[BLOCK_LEFT] = eina_list_prev(wd->cur);
613    l[BLOCK_CENTER] = wd->cur;
614    l[BLOCK_RIGHT] = eina_list_next(wd->cur);
615
616    for (i = 0; i < BLOCK_MAX; i++)
617      {
618         eo = elm_object_part_content_get((const Evas_Object*)wd->ly[i], "swl.photo");
619         if (!l[i])
620           {
621              elm_object_part_content_set(wd->ly[i], "swl.photo", NULL);
622           }
623         else
624           {
625              it = eina_list_data_get(l[i]);
626              if (!it)
627                return;
628
629              if (!eo)
630                {
631                   eo = elm_image_add(wd->obj);
632                   //elm_image_prescale_set(eo, wd->w);
633                   elm_image_file_set(eo, it->photo_file, NULL);
634                   elm_object_part_content_set(wd->ly[i], "swl.photo", eo);
635                }
636           }
637      }
638    _anim(wd);
639 }
640
641 EAPI Evas_Object *
642 elm_imageslider_add(Evas_Object *parent)
643 {
644    int i;
645
646    Evas_Object *obj;
647    Evas *e;
648    Widget_Data *wd;
649
650    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
651
652    ELM_SET_WIDTYPE(widtype, "imageslider");
653    elm_widget_type_set(obj, "imageslider");
654    elm_widget_sub_object_add(parent, obj);
655    elm_widget_data_set(obj, wd);
656    elm_widget_del_hook_set(obj, _del_hook);
657    elm_widget_theme_hook_set(obj, _theme_hook);
658
659    wd->clip = evas_object_rectangle_add(e);
660    elm_widget_sub_object_add(obj, wd->clip);
661    elm_widget_resize_object_set(obj, wd->clip);
662
663    for (i = 0; i < BLOCK_MAX; i++)
664      {
665         wd->ly[i] = elm_layout_add(obj);
666         elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
667         elm_widget_sub_object_add(obj, wd->ly[i]);
668         evas_object_smart_member_add(wd->ly[i], obj);
669
670         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, _ev_imageslider_down_cb, wd);
671         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, _ev_imageslider_up_cb, wd);
672         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, _ev_imageslider_move_cb, wd);
673         evas_object_clip_set(wd->ly[i], wd->clip);
674         evas_object_show(wd->ly[i]);
675      }
676
677    wd->obj = obj;
678    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
679    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
680    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
681    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
682
683    _sizing_eval(obj);
684    return obj;
685 }
686
687 EAPI Elm_Imageslider_Item *
688 elm_imageslider_item_append(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
689 {
690    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
691    Widget_Data *wd;
692
693    Elm_Imageslider_Item *it;
694
695    if (!obj || !(wd = elm_widget_data_get(obj)))
696      return NULL;
697
698    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
699    if (!it)
700       return NULL;
701    it->photo_file = eina_stringshare_add(photo_file);
702    it->func = func;
703    it->data = data;
704    it->obj = obj;
705    wd->its = eina_list_append(wd->its, it);
706
707    if (!wd->cur)
708       wd->cur = wd->its;
709    _imageslider_update(wd);
710    return it;
711 }
712
713 EAPI Elm_Imageslider_Item *
714 elm_imageslider_item_append_relative(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, unsigned int index, void *data)
715 {
716    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
717    Widget_Data *wd;
718
719    Elm_Imageslider_Item *it;
720
721    DBG("New elm_imageslider_item_append_relative()\n");
722
723    if (!obj || !(wd = elm_widget_data_get(obj)))
724      return NULL;
725
726    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
727    if (!it)
728       return NULL;
729
730    it->obj = obj;
731    it->photo_file = eina_stringshare_add(photo_file);
732    it->func = func;
733    it->data = data;
734
735    wd->its = eina_list_append_relative(wd->its, it, eina_list_nth(wd->its,
736                                                                   index - 2));
737
738    if (!wd->cur)
739       wd->cur = wd->its;
740    _imageslider_update(wd);
741    return it;
742 }
743
744 EAPI Elm_Imageslider_Item *
745 elm_imageslider_item_prepend(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
746 {
747    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
748    Widget_Data *wd;
749
750    Elm_Imageslider_Item *it;
751
752    if (!obj || !(wd = elm_widget_data_get(obj)))
753      return NULL;
754
755    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
756    it->photo_file = eina_stringshare_add(photo_file);
757    it->func = func;
758    it->data = data;
759    it->obj = obj;
760    wd->its = eina_list_prepend(wd->its, it);
761    if (!wd->cur)
762       wd->cur = wd->its;
763    _imageslider_update(wd);
764    return it;
765 }
766
767 EAPI void
768 elm_imageslider_item_del(Elm_Imageslider_Item * it)
769 {
770    Widget_Data *wd;
771
772    Elm_Imageslider_Item *_it;
773
774    Eina_List *l;
775
776    if (!it || !(wd = elm_widget_data_get(it->obj)))
777      return;
778
779    EINA_LIST_FOREACH(wd->its, l, _it)
780      {
781         if (_it == it)
782           {
783              if (l == wd->cur)
784                 wd->cur = eina_list_prev(wd->cur);
785              wd->its = eina_list_remove(wd->its, it);
786              if (!wd->cur)
787                 wd->cur = wd->its;
788              break;
789           }
790      }
791    _imageslider_update(wd);
792 }
793
794 EAPI Elm_Imageslider_Item *
795 elm_imageslider_selected_item_get(Evas_Object *obj)
796 {
797    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
798    Widget_Data *wd;
799
800    if (!obj || (!(wd = elm_widget_data_get(obj))))
801      return NULL;
802
803    if (!wd->cur)
804       return NULL;
805
806    return eina_list_data_get(wd->cur);
807 }
808
809 EAPI Eina_Bool
810 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
811 {
812    Widget_Data *wd;
813
814    if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
815      return EINA_FALSE;
816
817    if (!wd->cur)
818       return EINA_FALSE;
819
820    if (eina_list_data_get(wd->cur) == it)
821       return EINA_TRUE;
822    else
823       return EINA_FALSE;
824 }
825
826 EAPI void
827 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
828 {
829    int i;
830
831    Widget_Data *wd;
832
833    Elm_Imageslider_Item *_it;
834
835    Eina_List *l;
836
837    Evas_Object *eo;
838
839    if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
840      return;
841
842    EINA_LIST_FOREACH(wd->its, l, _it)
843      {
844         if (_it == it)
845           wd->cur = l;
846      }
847
848    for (i = 0; i < BLOCK_MAX; i++)
849      {
850        eo = elm_object_part_content_get(wd->ly[i], "swl.photo");
851        if (eo)
852          elm_object_part_content_set(wd->ly[i], "swl.photo", NULL);
853      }
854    _imageslider_update(wd);
855 }
856
857 EAPI const char *
858 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
859 {
860    if (!it) return NULL;
861
862    return it->photo_file;
863 }
864
865 EAPI void
866 elm_imageslider_item_photo_file_set(Elm_Imageslider_Item *it, const char *photo_file)
867 {
868    if (!it) return;
869    ELM_CHECK_WIDTYPE(it->obj, widtype);
870
871    if (photo_file)
872      {
873         eina_stringshare_replace(&(it->photo_file), photo_file);
874         elm_imageslider_item_update(it);
875      }
876 }
877
878 EAPI Elm_Imageslider_Item *
879 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
880 {
881    Widget_Data *wd;
882
883    Elm_Imageslider_Item *_it;
884
885    Eina_List *l;
886
887    if (!it || (!(wd = elm_widget_data_get(it->obj))))
888      return NULL;
889
890    EINA_LIST_FOREACH(wd->its, l, _it)
891      {
892         if (_it == it)
893           {
894              l = eina_list_prev(l);
895              if (!l)
896                break;
897              return eina_list_data_get(l);
898           }
899      }
900    return NULL;
901 }
902
903 EAPI Elm_Imageslider_Item *
904 elm_imageslider_item_next(Elm_Imageslider_Item * it)
905 {
906    Widget_Data *wd;
907
908    Elm_Imageslider_Item *_it;
909
910    Eina_List *l;
911
912    if (!it || (!(wd = elm_widget_data_get(it->obj))))
913      return NULL;
914
915    EINA_LIST_FOREACH(wd->its, l, _it)
916      {
917         if (_it == it)
918           {
919              l = eina_list_next(l);
920              if (!l)
921                break;
922              return eina_list_data_get(l);
923           }
924      }
925    return NULL;
926 }
927
928 EAPI void
929 elm_imageslider_prev(Evas_Object *obj)
930 {
931    ELM_CHECK_WIDTYPE(obj, widtype);
932    Widget_Data *wd;
933
934    if (!obj || (!(wd = elm_widget_data_get(obj))))
935      return;
936    if (wd->ani_lock)
937      return;
938    _imageslider_obj_move(wd, -1);
939 }
940
941 EAPI void
942 elm_imageslider_next(Evas_Object * obj)
943 {
944    ELM_CHECK_WIDTYPE(obj, widtype);
945    Widget_Data *wd;
946
947    if (!obj || (!(wd = elm_widget_data_get(obj))))
948      return;
949    if (wd->ani_lock)
950      return;
951    _imageslider_obj_move(wd, 1);
952 }
953
954 EAPI void
955 elm_imageslider_item_update(Elm_Imageslider_Item *it)
956 {
957    Widget_Data *wd;
958
959    if (!it || (!(wd = elm_widget_data_get(it->obj)))) return;
960    ELM_CHECK_WIDTYPE(it->obj, widtype);
961
962    if (wd->ani_lock) return;
963    if (it == eina_list_data_get(eina_list_prev(wd->cur)))
964      elm_object_part_content_set(wd->ly[BLOCK_LEFT], "swl.photo", NULL);
965    else if (it == eina_list_data_get(wd->cur))
966      elm_object_part_content_set(wd->ly[BLOCK_CENTER], "swl.photo", NULL);
967    else if (it == eina_list_data_get(eina_list_next(wd->cur)))
968      elm_object_part_content_set(wd->ly[BLOCK_RIGHT], "swl.photo", NULL);
969    _imageslider_update(wd);
970 }