elementary: fix slideshow with loop attribute set to false
[framework/uifw/elementary.git] / src / lib / elm_slideshow.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Slideshow Slideshow
6  *
7  * This object display a list of object (generally a list of images) and some actions like
8  * next/previous are used to navigate. The animations are defined in the theme,
9  * consequently new animations can be added without having to update the
10  * applications.
11  *
12  * The slideshow use 2 callbacks to create and delete the objects displayed. When an item
13  * is displayed the function itc->func.get() is called. This function should create the object,
14  * for example the object can be an evas_object_image or a photocam. When an object is no more
15  * displayed the function itc->func.del() is called, the user can delete the dana associated to the item.
16  *
17  * Signals that you can add callbacks for are:
18  *
19  * "changed" - when the slideshow switch to another item
20  */
21
22 typedef struct _Widget_Data Widget_Data;
23
24 struct _Elm_Slideshow_Item
25 {
26    Elm_Widget_Item base;
27
28    Eina_List *l, *l_built;
29
30    const Elm_Slideshow_Item_Class *itc;
31 };
32
33 struct _Widget_Data
34 {
35    Evas_Object *slideshow;
36
37    // list of Elm_Slideshow_Item*
38    Eina_List *items;
39    Eina_List *items_built;
40
41    Elm_Slideshow_Item *current;
42    Elm_Slideshow_Item *previous;
43
44    Eina_List *transitions;
45    const char *transition;
46
47    int count_item_pre_before;
48    int count_item_pre_after;
49    Ecore_Timer *timer;
50    double timeout;
51    Eina_Bool loop:1;
52
53    struct {
54         const char *current;
55         Eina_List *list; //list of const char *
56    } layout;
57 };
58
59 static const char *widtype = NULL;
60 static void _del_hook(Evas_Object *obj);
61 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
62 static void _theme_hook(Evas_Object *obj);
63 static void _sizing_eval(Evas_Object *obj);
64 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
65 static Eina_Bool _timer_cb(void *data);
66 static void _on_focus_hook(void *data, Evas_Object *obj);
67 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
68                              Evas_Callback_Type type, void *event_info);
69
70 static const char SIG_CHANGED[] = "changed";
71
72 static const Evas_Smart_Cb_Description _signals[] = {
73    {SIG_CHANGED, ""},
74    {NULL, NULL}
75 };
76
77 static Eina_Bool
78 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
79 {
80    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
81    Evas_Event_Key_Down *ev = event_info;
82    Widget_Data *wd = elm_widget_data_get(obj);
83    if (!wd) return EINA_FALSE;
84    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
85    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
86    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
87      {
88         elm_slideshow_previous(obj);
89         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
90         return EINA_TRUE;
91      }
92    if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
93      {
94         elm_slideshow_next(obj);
95         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
96         return EINA_TRUE;
97      }
98    if ((!strcmp(ev->keyname, "Return")) ||
99        (!strcmp(ev->keyname, "KP_Enter")) ||
100        (!strcmp(ev->keyname, "space")))
101      {
102         if (wd->timeout)
103           {
104              if (wd->timer)
105                {
106                   ecore_timer_del(wd->timer);
107                   wd->timer = NULL;
108                }
109              else
110                elm_slideshow_timeout_set(obj, wd->timeout);
111           }
112         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
113         return EINA_TRUE;
114      }
115    return EINA_FALSE;
116 }
117
118 static void
119 _del_hook(Evas_Object *obj)
120 {
121    const char *layout;
122    Widget_Data *wd = elm_widget_data_get(obj);
123    if (!wd) return;
124    elm_slideshow_clear(obj);
125    elm_widget_stringlist_free(wd->transitions);
126    if (wd->timer) ecore_timer_del(wd->timer);
127    EINA_LIST_FREE(wd->layout.list, layout)
128       eina_stringshare_del(layout);
129    free(wd);
130 }
131
132 static void
133 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
134 {
135    Widget_Data *wd = elm_widget_data_get(obj);
136    if (!wd) return;
137    if (elm_widget_focus_get(obj))
138      {
139         edje_object_signal_emit(wd->slideshow, "elm,action,focus", "elm");
140         evas_object_focus_set(wd->slideshow, EINA_TRUE);
141      }
142    else
143      {
144         edje_object_signal_emit(wd->slideshow, "elm,action,unfocus", "elm");
145         evas_object_focus_set(wd->slideshow, EINA_FALSE);
146      }
147 }
148
149 static void
150 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
151 {
152    Widget_Data *wd = elm_widget_data_get(obj);
153    if (!wd) return;
154    edje_object_mirrored_set(wd->slideshow, rtl);
155 }
156
157 static void
158 _theme_hook(Evas_Object *obj)
159 {
160    Widget_Data *wd = elm_widget_data_get(obj);
161    if (!wd) return;
162    _elm_widget_mirrored_reload(obj);
163    _mirrored_set(obj, elm_widget_mirrored_get(obj));
164    _elm_theme_object_set(obj, wd->slideshow, "slideshow", "base", elm_widget_style_get(obj));
165    edje_object_scale_set(wd->slideshow, elm_widget_scale_get(obj) *
166                          _elm_config->scale);
167    _sizing_eval(obj);
168 }
169
170 static void
171 _sizing_eval(Evas_Object *obj)
172 {
173    Widget_Data *wd = elm_widget_data_get(obj);
174    Evas_Coord minw = -1, minh = -1;
175    if (!wd) return;
176    edje_object_size_min_calc(wd->slideshow, &minw, &minh);
177    evas_object_size_hint_min_set(obj, minw, minh);
178    evas_object_size_hint_max_set(obj, minw, minh);
179 }
180
181
182 static Elm_Slideshow_Item* _item_prev_get(Elm_Slideshow_Item* item)
183 {
184    Widget_Data *wd = elm_widget_data_get(item->base.widget);
185    Elm_Slideshow_Item* prev = eina_list_data_get(eina_list_prev(item->l));
186    if ((!prev) && (wd->loop))
187      prev = eina_list_data_get(eina_list_last(item->l));
188    return prev;
189 }
190
191 static Elm_Slideshow_Item* _item_next_get(Elm_Slideshow_Item* item)
192 {
193    Widget_Data *wd = elm_widget_data_get(item->base.widget);
194    Elm_Slideshow_Item* next = eina_list_data_get(eina_list_next(item->l));
195    if ((!next) && (wd->loop))
196      next = eina_list_data_get(wd->items);
197    return next;
198 }
199
200 static void
201 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
202 {
203    _sizing_eval(data);
204 }
205
206 static void
207 _sub_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
208 {
209    ;
210 }
211
212 static void
213 _item_realize(Elm_Slideshow_Item *item)
214 {
215    Elm_Slideshow_Item *_item_prev, *_item_next;
216    Evas_Object *obj = item->base.widget;
217    Widget_Data *wd = elm_widget_data_get(obj);
218    int ac, bc, lc;
219
220    if (!wd) return;
221    if ((!item->base.view) && (item->itc->func.get))
222      {
223         item->base.view = item->itc->func.get((void*)item->base.data, obj);
224         evas_object_smart_member_add(item->base.view, obj);
225         item->l_built = eina_list_append(NULL, item);
226         wd->items_built = eina_list_merge(wd->items_built, item->l_built);
227         evas_object_hide(item->base.view);
228      }
229    else if (item->l_built)
230      wd->items_built = eina_list_demote_list(wd->items_built, item->l_built);
231
232    //pre-create previous and next item
233    ac = wd->count_item_pre_after;
234    _item_next = item;
235    bc = wd->count_item_pre_before;
236    _item_prev = item;
237    lc = eina_list_count(wd->items) - 1;
238    while (lc > 0 && ((ac > 0) || (bc > 0)))
239      {
240         if (lc > 0 && ac > 0)
241           {
242              --ac;
243              --lc;
244              if (_item_next)
245                {
246                   _item_next = _item_next_get(_item_next);
247                   if ((_item_next)
248                       && (!_item_next->base.view)
249                       && (_item_next->itc->func.get))
250                     {
251                        _item_next->base.view =
252                           _item_next->itc->func.get(
253                              (void*)_item_next->base.data, obj);
254                        evas_object_smart_member_add(_item_next->base.view, obj);
255                        _item_next->l_built = eina_list_append(NULL, _item_next);
256                        wd->items_built = eina_list_merge(wd->items_built,
257                                                          _item_next->l_built);
258                        evas_object_hide(_item_next->base.view);
259                     }
260                   else if (_item_next && _item_next->l_built)
261                     wd->items_built =
262                        eina_list_demote_list(wd->items_built,
263                                              _item_next->l_built);
264                }
265           }
266
267         if (lc > 0 && bc > 0)
268           {
269              --bc;
270              --lc;
271              if (_item_prev)
272                {
273                   _item_prev = _item_prev_get(_item_prev);
274                   if ((_item_prev)
275                       && (!_item_prev->base.view)
276                       && (_item_prev->itc->func.get))
277                     {
278                        _item_prev->base.view =
279                           _item_prev->itc->func.get(
280                              (void*)_item_prev->base.data, obj);
281                        evas_object_smart_member_add(_item_prev->base.view, obj);
282                        _item_prev->l_built = eina_list_append(NULL, _item_prev);
283                        wd->items_built = eina_list_merge(wd->items_built,
284                                                          _item_prev->l_built);
285                        evas_object_hide(_item_prev->base.view);
286                     }
287                   else if (_item_prev && _item_prev->l_built)
288                     wd->items_built =
289                        eina_list_demote_list(wd->items_built,
290                                              _item_prev->l_built);
291                }
292           }
293      }
294
295    //delete unused items
296    lc = wd->count_item_pre_before + wd->count_item_pre_after + 1;
297    while ((int)eina_list_count(wd->items_built) > lc)
298      {
299         item = eina_list_data_get(wd->items_built);
300         wd->items_built = eina_list_remove_list(wd->items_built,
301                                                 wd->items_built);
302         if (item->itc->func.del)
303           item->itc->func.del((void*)item->base.data, item->base.view);
304         evas_object_del(item->base.view);
305         item->base.view = NULL;
306      }
307 }
308
309 static void
310 _end(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
311 {
312    Elm_Slideshow_Item *item;
313    Widget_Data *wd = elm_widget_data_get(data);
314    if (!wd) return;
315
316    item = wd->previous;
317    if (item)
318      {
319         edje_object_part_unswallow(NULL, item->base.view);
320         evas_object_hide(item->base.view);
321         wd->previous = NULL;
322      }
323
324
325    item = wd->current;
326    if ((!item) || (!item->base.view)) return;
327
328    _item_realize(item);
329    edje_object_part_unswallow(NULL, item->base.view);
330    evas_object_show(item->base.view);
331
332    edje_object_signal_emit(wd->slideshow, "anim,end", "slideshow");
333    edje_object_part_swallow(wd->slideshow, "elm.swallow.1", item->base.view);
334 }
335
336 static Eina_Bool
337 _timer_cb(void *data)
338 {
339    Evas_Object *obj = data;
340    Widget_Data *wd = elm_widget_data_get(obj);
341    if (!wd) return ECORE_CALLBACK_CANCEL;
342    wd->timer = NULL;
343    elm_slideshow_next(obj);
344    return ECORE_CALLBACK_CANCEL;
345 }
346
347 /**
348  * Add a new slideshow to the parent
349  *
350  * @param parent The parent object
351  * @return The new object or NULL if it cannot be created
352  *
353  * @ingroup Slideshow
354  */
355 EAPI Evas_Object *
356 elm_slideshow_add(Evas_Object *parent)
357 {
358    Evas_Object *obj;
359    Evas *e;
360    Widget_Data *wd;
361
362    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
363
364    ELM_SET_WIDTYPE(widtype, "slideshow");
365    elm_widget_type_set(obj, "slideshow");
366    elm_widget_sub_object_add(parent, obj);
367    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
368    elm_widget_data_set(obj, wd);
369    elm_widget_del_hook_set(obj, _del_hook);
370    elm_widget_theme_hook_set(obj, _theme_hook);
371    elm_widget_can_focus_set(obj, EINA_TRUE);
372    elm_widget_event_hook_set(obj, _event_hook);
373
374    wd->current = NULL;
375    wd->previous = NULL;
376
377    wd->slideshow = edje_object_add(e);
378    _elm_theme_object_set(obj, wd->slideshow, "slideshow", "base", "default");
379    evas_object_smart_member_add(wd->slideshow, obj);
380    wd->count_item_pre_before = 2;
381    wd->count_item_pre_after = 2;
382    elm_widget_resize_object_set(obj, wd->slideshow);
383    evas_object_show(wd->slideshow);
384
385    wd->transitions = elm_widget_stringlist_get(edje_object_data_get(wd->slideshow, "transitions"));
386    if (eina_list_count(wd->transitions) > 0)
387      wd->transition = eina_stringshare_add(eina_list_data_get(wd->transitions));
388
389    wd->layout.list = elm_widget_stringlist_get(edje_object_data_get(wd->slideshow, "layouts"));
390    if (eina_list_count(wd->layout.list) > 0)
391      wd->layout.current = eina_list_data_get(wd->layout.list);
392
393    edje_object_signal_callback_add(wd->slideshow, "end", "slideshow", _end, obj);
394
395    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
396    evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
397
398    evas_object_smart_callbacks_descriptions_set(obj, _signals);
399
400    _mirrored_set(obj, elm_widget_mirrored_get(obj));
401    _sizing_eval(obj);
402    return obj;
403 }
404
405 /**
406  * Add an object in the list. The object can be a evas object image or a elm photo for example.
407  *
408  * @param obj The slideshow object
409  * @aram itc Callbacks used to create the object and delete the data associated when the item is deleted.
410  * @param data Data used by the user to identified the item
411  * @return Returns The slideshow item
412  *
413  * @ingroup Slideshow
414  */
415 EAPI Elm_Slideshow_Item*
416 elm_slideshow_item_add(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data)
417 {
418    Elm_Slideshow_Item *item;
419    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
420    Widget_Data *wd = elm_widget_data_get(obj);
421
422    if (!wd) return NULL;
423    item = elm_widget_item_new(obj, Elm_Slideshow_Item);
424    item->base.data = data;
425    item->itc = itc;
426    item->l = eina_list_append(item->l, item);
427
428    wd->items = eina_list_merge(wd->items, item->l);
429
430    if (!wd->current) elm_slideshow_show(item);
431
432    return item;
433 }
434
435 /**
436  * Insert an object in the list. The object can be a evas object image or a elm photo for example.
437  *
438  * @param obj The slideshow object
439  * @aram itc Callbacks used to create the object and delete the data associated when the item is deleted.
440  * @param data Data used by the user to identified the item
441  * @param func The function to compare data
442  * @return Returns The slideshow item
443  *
444  * @ingroup Slideshow
445  */
446 EAPI Elm_Slideshow_Item*
447 elm_slideshow_item_sorted_insert(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data, Eina_Compare_Cb func)
448 {
449    Elm_Slideshow_Item *item;
450    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
451    Widget_Data *wd = elm_widget_data_get(obj);
452
453    if (!wd) return NULL;
454    item = elm_widget_item_new(obj, Elm_Slideshow_Item);
455    item->base.data = data;
456    item->itc = itc;
457    item->l = eina_list_append(item->l, item);
458
459    wd->items = eina_list_sorted_merge(wd->items, item->l, func);
460
461    if (!wd->current) elm_slideshow_show(item);
462
463    return item;
464 }
465
466 /**
467  * Go to the item
468  *
469  * @param obj The slideshow object
470  * @param item The item
471  *
472  * @ingroup Slideshow
473  */
474 EAPI void
475 elm_slideshow_show(Elm_Slideshow_Item *item)
476 {
477    char buf[1024];
478    Elm_Slideshow_Item *next = NULL;
479    Widget_Data *wd;
480    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
481    wd = elm_widget_data_get(item->base.widget);
482    if (!wd)
483      return;
484    if (item == wd->current)
485      return;
486
487    next = item;
488    _end(item->base.widget, item->base.widget, NULL, NULL);
489
490    if (wd->timer) ecore_timer_del(wd->timer);
491    if (wd->timeout > 0.0)
492      wd->timer = ecore_timer_add(wd->timeout, _timer_cb, item->base.widget);
493    _item_realize(next);
494    edje_object_part_swallow(wd->slideshow, "elm.swallow.2", next->base.view);
495    evas_object_show(next->base.view);
496    snprintf(buf, sizeof(buf), "%s,next", wd->transition);
497    edje_object_signal_emit(wd->slideshow, buf, "slideshow");
498    wd->previous = wd->current;
499    wd->current = next;
500    evas_object_smart_callback_call(item->base.widget, SIG_CHANGED, wd->current);
501 }
502
503 /**
504  * Go to the next item
505  *
506  * @param obj The slideshow object
507  *
508  * @ingroup Slideshow
509  */
510 EAPI void
511 elm_slideshow_next(Evas_Object *obj)
512 {
513    char buf[1024];
514    Elm_Slideshow_Item *next = NULL;
515    ELM_CHECK_WIDTYPE(obj, widtype);
516    Widget_Data *wd = elm_widget_data_get(obj);
517
518    if (!wd) return;
519
520    if (wd->current)
521      next = _item_next_get(wd->current);
522
523    if ((!next) || (next == wd->current)) return;
524
525    _end(obj, obj, NULL, NULL);
526
527    if (wd->timer) ecore_timer_del(wd->timer);
528    if (wd->timeout > 0.0)
529      wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
530
531    _item_realize(next);
532
533    edje_object_part_swallow(wd->slideshow, "elm.swallow.2", next->base.view);
534    evas_object_show(next->base.view);
535
536    snprintf(buf, sizeof(buf), "%s,next", wd->transition);
537    edje_object_signal_emit(wd->slideshow, buf, "slideshow");
538
539    wd->previous = wd->current;
540    wd->current = next;
541    evas_object_smart_callback_call(obj, SIG_CHANGED, wd->current);
542 }
543
544 /**
545  * Go to the previous item
546  *
547  * @param obj The slideshow object
548  *
549  * @ingroup Slideshow
550  */
551 EAPI void
552 elm_slideshow_previous(Evas_Object *obj)
553 {
554    char buf[1024];
555    Elm_Slideshow_Item *prev = NULL;
556    ELM_CHECK_WIDTYPE(obj, widtype);
557    Widget_Data *wd = elm_widget_data_get(obj);
558
559    if (!wd) return;
560
561    if (wd->current)
562      prev = _item_prev_get(wd->current);
563
564    if ((!prev) ||  (prev == wd->current)) return;
565
566    _end(obj, obj, NULL, NULL);
567
568    if (wd->timer) ecore_timer_del(wd->timer);
569    if (wd->timeout > 0.0)
570      wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
571
572    _item_realize(prev);
573
574    edje_object_part_swallow(wd->slideshow, "elm.swallow.2", prev->base.view);
575    evas_object_show(prev->base.view);
576
577    snprintf(buf, 1024, "%s,previous", wd->transition);
578    edje_object_signal_emit(wd->slideshow, buf, "slideshow");
579
580    wd->previous = wd->current;
581    wd->current = prev;
582    evas_object_smart_callback_call(obj, SIG_CHANGED, wd->current);
583 }
584
585 /**
586  * Returns the list of transitions available.
587  *
588  * @param obj The slideshow object
589  * @return Returns the list of transitions (list of const char*)
590  *
591  * @ingroup Slideshow
592  */
593 EAPI const Eina_List *
594 elm_slideshow_transitions_get(const Evas_Object *obj)
595 {
596    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
597    Widget_Data *wd = elm_widget_data_get(obj);
598    if (!wd) return NULL;
599    return wd->transitions;
600 }
601
602 /**
603  * Returns the list of layouts available.
604  *
605  * @param obj The slideshow object
606  * @return Returns the list of layout (list of const char*)
607  *
608  * @ingroup Slideshow
609  */
610 EAPI const Eina_List *
611 elm_slideshow_layouts_get(const Evas_Object *obj)
612 {
613    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
614    Widget_Data *wd = elm_widget_data_get(obj);
615    if (!wd) return NULL;
616    return wd->layout.list;
617 }
618
619 /**
620  * Set the transition to use
621  *
622  * @param obj The slideshow object
623  * @param transition the new transition
624  *
625  * @ingroup Slideshow
626  */
627 EAPI void
628 elm_slideshow_transition_set(Evas_Object *obj, const char *transition)
629 {
630    ELM_CHECK_WIDTYPE(obj, widtype);
631    Widget_Data *wd = elm_widget_data_get(obj);
632    if (!wd) return;
633    eina_stringshare_replace(&wd->transition, transition);
634 }
635
636 /**
637  * Returns the transition to use
638  *
639  * @param obj The slideshow object
640  * @return the transition set
641  *
642  * @ingroup Slideshow
643  */
644 EAPI const char *
645 elm_slideshow_transition_get(const Evas_Object *obj)
646 {
647    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
648    Widget_Data *wd = elm_widget_data_get(obj);
649    if (!wd) return NULL;
650    return wd->transition;
651 }
652
653 /**
654  * The slideshow can go to the next item automatically after a few seconds.
655  * This method set the timeout to use. A timeout <=0 disable the timer.
656  *
657  * @param obj The slideshow object
658  * @param timeout The new timeout
659  *
660  * @ingroup Slideshow
661  */
662 EAPI void
663 elm_slideshow_timeout_set(Evas_Object *obj, double timeout)
664 {
665    ELM_CHECK_WIDTYPE(obj, widtype);
666    Widget_Data *wd = elm_widget_data_get(obj);
667    if (!wd) return;
668    wd->timeout = timeout;
669    if (wd->timer) ecore_timer_del(wd->timer);
670    wd->timer = NULL;
671    if (timeout > 0.0)
672      wd->timer = ecore_timer_add(timeout, _timer_cb, obj);
673 }
674
675 /**
676  * Returns the timeout value
677  *
678  * @param obj The slideshow object
679  * @return Returns the timeout
680  *
681  * @ingroup Slideshow
682  */
683 EAPI double
684 elm_slideshow_timeout_get(const Evas_Object *obj)
685 {
686    ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
687    Widget_Data *wd = elm_widget_data_get(obj);
688    if (!wd) return -1.0;
689    return wd->timeout;
690 }
691
692 /**
693  * Set if the first item should follow the last and vice versa
694  *
695  * @param obj The slideshow object
696  * @param loop if EINA_TRUE, the first item will follow the last and vice versa
697  *
698  * @ingroup Slideshow
699  */
700 EAPI void
701 elm_slideshow_loop_set(Evas_Object *obj, Eina_Bool loop)
702 {
703    ELM_CHECK_WIDTYPE(obj, widtype);
704    Widget_Data *wd = elm_widget_data_get(obj);
705    if (!wd) return;
706    wd->loop = loop;
707 }
708
709 /**
710  * Returns the current layout name
711  *
712  * @param obj The slideshow object
713  * @returns Returns the layout name
714  *
715  * @ingroup Slideshow
716  */
717 EAPI const char *
718 elm_slideshow_layout_get(const Evas_Object *obj)
719 {
720    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
721    Widget_Data *wd = elm_widget_data_get(obj);
722    if (!wd) return EINA_FALSE;
723    return wd->layout.current;
724 }
725
726 /**
727  * Set the layout
728  *
729  * @param obj The slideshow object
730  * @param layout the new layout
731  *
732  * @ingroup Slideshow
733  */
734 EAPI void
735 elm_slideshow_layout_set(Evas_Object *obj, const char *layout)
736 {
737    char buf[PATH_MAX];
738    ELM_CHECK_WIDTYPE(obj, widtype);
739    Widget_Data *wd = elm_widget_data_get(obj);
740    if (!wd) return;
741
742    wd->layout.current = layout;
743    snprintf(buf, sizeof(buf), "layout,%s", layout);
744    edje_object_signal_emit(wd->slideshow, buf, "slideshow");
745 }
746
747 /**
748  * Return if the first item should follow the last and vice versa
749  *
750  * @param obj The slideshow object
751  * @returns Returns the loop flag
752  *
753  * @ingroup Slideshow
754  */
755 EAPI Eina_Bool
756 elm_slideshow_loop_get(const Evas_Object *obj)
757 {
758    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
759    Widget_Data *wd = elm_widget_data_get(obj);
760    if (!wd) return EINA_FALSE;
761    return wd->loop;
762 }
763
764 /**
765  * Delete all the items
766  *
767  * @param obj The slideshow object
768  *
769  * @ingroup Slideshow
770  */
771 EAPI void
772 elm_slideshow_clear(Evas_Object *obj)
773 {
774    Elm_Slideshow_Item *item;
775    ELM_CHECK_WIDTYPE(obj, widtype);
776    Widget_Data *wd = elm_widget_data_get(obj);
777    if (!wd) return;
778    wd->previous = NULL;
779    wd->current = NULL;
780    EINA_LIST_FREE(wd->items_built, item)
781      {
782         if (item->itc->func.del)
783           item->itc->func.del((void*)item->base.data, item->base.view);
784         evas_object_del(item->base.view);
785         item->base.view = NULL;
786      }
787
788    EINA_LIST_FREE(wd->items, item)
789      {
790         elm_widget_item_del(item);
791      }
792 }
793
794 /**
795  * Delete the item
796  *
797  * @param item The slideshow item
798  *
799  * @ingroup Slideshow
800  */
801 EAPI void
802 elm_slideshow_item_del(Elm_Slideshow_Item *item)
803 {
804    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
805    Widget_Data *wd = elm_widget_data_get(item->base.widget);
806    if (!wd) return;
807    if (wd->previous == item) wd->previous = NULL;
808    if (wd->current == item)
809      {
810         Eina_List *l = eina_list_data_find_list(wd->items, item);
811         Eina_List *l2 = eina_list_next(l);
812         wd->current = NULL;
813         if (!l2)
814           l2 = eina_list_nth_list(wd->items, eina_list_count(wd->items) - 1);
815         if (l2)
816           elm_slideshow_show(eina_list_data_get(l2));
817      }
818
819    wd->items = eina_list_remove_list(wd->items, item->l);
820    wd->items_built = eina_list_remove_list(wd->items_built, item->l_built);
821
822    if ((item->base.view) && (item->itc->func.del))
823      item->itc->func.del((void*)item->base.data, item->base.view);
824    if (item->base.view)
825      evas_object_del(item->base.view);
826    free(item);
827 }
828
829 /**
830  * Returns the list of items
831  * @param obj The slideshow object
832  * @return Returns the list of items (list of Elm_Slideshow_Item).
833  *
834  * @ingroup Slideshow
835  */
836 EAPI const Eina_List *
837 elm_slideshow_items_get(const Evas_Object *obj)
838 {
839    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
840    Widget_Data *wd = elm_widget_data_get(obj);
841    if (!wd) return NULL;
842    return wd->items;
843 }
844
845 /**
846  * Returns the current item displayed
847  *
848  * @param obj The slideshow object
849  * @return Returns the current item displayed
850  *
851  * @ingroup Slideshow
852  */
853 EAPI Elm_Slideshow_Item *
854 elm_slideshow_item_current_get(const Evas_Object *obj)
855 {
856    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
857    Widget_Data *wd = elm_widget_data_get(obj);
858    if (!wd) return NULL;
859    return wd->current;
860 }
861
862 /**
863  * Returns the evas object associated to an item
864  *
865  * @param item The slideshow item
866  * @return Returns the evas object associated to this item
867  *
868  * @ingroup Slideshow
869  */
870 EAPI Evas_Object *
871 elm_slideshow_item_object_get(const Elm_Slideshow_Item * item)
872 {
873    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
874    return item->base.view;
875 }
876
877 /**
878  * Returns the data associated to an item
879  *
880  * @param item The slideshow item
881  * @return Returns the data associated to this item
882  *
883  * @ingroup Slideshow
884  */
885 EAPI void *
886 elm_slideshow_item_data_get(const Elm_Slideshow_Item * item)
887 {
888    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
889    return elm_widget_item_data_get(item);
890 }
891
892 /**
893  * Returns max amount of cached items before current
894  *
895  * @param obj The slideshow object
896  * @return Returns max amount of cached items
897  *
898  * @ingroup Slideshow
899  */
900 EAPI int
901 elm_slideshow_cache_before_get(const Evas_Object *obj)
902 {
903    ELM_CHECK_WIDTYPE(obj, widtype) -1;
904    Widget_Data *wd = elm_widget_data_get(obj);
905    if (!wd) return -1;
906    return wd->count_item_pre_before;
907 }
908
909 /**
910  * Set max amount of cached items before current
911  *
912  * @param obj The slideshow object
913  * @param count Max amount of cached items
914  *
915  * @ingroup Slideshow
916  */
917 EAPI void
918 elm_slideshow_cache_before_set(Evas_Object *obj, int count)
919 {
920    ELM_CHECK_WIDTYPE(obj, widtype);
921    Widget_Data *wd = elm_widget_data_get(obj);
922    if (!wd) return;
923    if (count < 0) count = 0;
924    wd->count_item_pre_before = count;
925 }
926
927 /**
928  * Returns max amount of cached items after current
929  *
930  * @param obj The slideshow object
931  * @return Returns max amount of cached items
932  *
933  * @ingroup Slideshow
934  */
935 EAPI int
936 elm_slideshow_cache_after_get(const Evas_Object *obj)
937 {
938    ELM_CHECK_WIDTYPE(obj, widtype) -1;
939    Widget_Data *wd = elm_widget_data_get(obj);
940    if (!wd) return -1;
941    return wd->count_item_pre_after;
942 }
943
944 /**
945  * Set max amount of cached items after current
946  *
947  * @param obj The slideshow object
948  * @param count max amount of cached items
949  *
950  * @ingroup Slideshow
951  */
952 EAPI void
953 elm_slideshow_cache_after_set(Evas_Object *obj, int count)
954 {
955    ELM_CHECK_WIDTYPE(obj, widtype);
956    Widget_Data *wd = elm_widget_data_get(obj);
957    if (!wd) return;
958    if (count < 0) count = 0;
959    wd->count_item_pre_after = count;
960 }