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