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