elm list: Fixed elm_list_scroller_policy_set(). Closed ticket #842.
[framework/uifw/elementary.git] / src / lib / elm_list.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define SWIPE_MOVES 12
5
6 typedef struct _Widget_Data Widget_Data;
7
8 struct _Widget_Data
9 {
10    Evas_Object *scr, *box, *self;
11    Eina_List *items, *selected, *to_delete;
12    Elm_List_Item *last_selected_item;
13    Elm_List_Mode mode;
14    Elm_List_Mode h_mode;
15    Evas_Coord minw[2], minh[2];
16    Eina_Bool scr_minw : 1;
17    Eina_Bool scr_minh : 1;
18    int walking;
19    int movements;
20    struct {
21         Evas_Coord x, y;
22    } history[SWIPE_MOVES];
23    Eina_Bool swipe : 1;
24    Eina_Bool fix_pending : 1;
25    Eina_Bool on_hold : 1;
26    Eina_Bool multi : 1;
27    Eina_Bool always_select : 1;
28    Eina_Bool longpressed : 1;
29    Eina_Bool wasselected : 1;
30 };
31
32 struct _Elm_List_Item
33 {
34    Elm_Widget_Item base;
35    Widget_Data *wd;
36    Eina_List *node;
37    const char *label;
38    Evas_Object *icon, *end;
39    Evas_Smart_Cb func;
40    Ecore_Timer *long_timer;
41    Ecore_Timer *swipe_timer;
42    Eina_Bool deleted : 1;
43    Eina_Bool disabled : 1;
44    Eina_Bool even : 1;
45    Eina_Bool is_even : 1;
46    Eina_Bool is_separator : 1;
47    Eina_Bool fixed : 1;
48    Eina_Bool selected : 1;
49    Eina_Bool highlighted : 1;
50    Eina_Bool dummy_icon : 1;
51    Eina_Bool dummy_end : 1;
52 };
53
54 static const char *widtype = NULL;
55 static void _del_hook(Evas_Object *obj);
56 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
57 static void _theme_hook(Evas_Object *obj);
58 static void _sizing_eval(Evas_Object *obj);
59 static void _disable_hook(Evas_Object *obj);
60 static void _on_focus_hook(void *data, Evas_Object *obj);
61 static void _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source);
62 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
63 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
64 static void _fix_items(Evas_Object *obj);
65 static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
66 static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
67 static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
68 static void _scroll_edge_left(void *data, Evas_Object *scr, void *event_info);
69 static void _scroll_edge_right(void *data, Evas_Object *scr, void *event_info);
70 static void _scroll_edge_top(void *data, Evas_Object *scr, void *event_info);
71 static void _scroll_edge_bottom(void *data, Evas_Object *scr, void *event_info);
72 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
73 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
74 static Eina_Bool _item_single_select_up(Widget_Data *wd);
75 static Eina_Bool _item_single_select_down(Widget_Data *wd);
76 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
77                              Evas_Callback_Type type, void *event_info);
78 static Eina_Bool _deselect_all_items(Widget_Data *wd);
79
80 static const char SIG_ACTIVATED[] = "activated";
81 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
82 static const char SIG_SELECTED[] = "selected";
83 static const char SIG_UNSELECTED[] = "unselected";
84 static const char SIG_LONGPRESSED[] = "longpressed";
85 static const char SIG_SCROLL_EDGE_TOP[] = "scroll,edge,top";
86 static const char SIG_SCROLL_EDGE_BOTTOM[] = "scroll,edge,bottom";
87 static const char SIG_SCROLL_EDGE_LEFT[] = "scroll,edge,left";
88 static const char SIG_SCROLL_EDGE_RIGHT[] = "scroll,edge,right";
89
90 static const Evas_Smart_Cb_Description _signals[] = {
91    {SIG_ACTIVATED, ""},
92    {SIG_CLICKED_DOUBLE, ""},
93    {SIG_SELECTED, ""},
94    {SIG_UNSELECTED, ""},
95    {SIG_LONGPRESSED, ""},
96    {SIG_SCROLL_EDGE_TOP, ""},
97    {SIG_SCROLL_EDGE_BOTTOM, ""},
98    {SIG_SCROLL_EDGE_LEFT, ""},
99    {SIG_SCROLL_EDGE_RIGHT, ""},
100    {NULL, NULL}
101 };
102
103 #define ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ...)                      \
104    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, __VA_ARGS__);             \
105 if (it->deleted)                                                         \
106 {                                                                        \
107    ERR("ERROR: "#it" has been DELETED.\n");                              \
108    return __VA_ARGS__;                                                   \
109 }
110
111 static inline void
112 _elm_list_item_free(Elm_List_Item *it)
113 {
114    evas_object_event_callback_del_full
115       (it->base.view, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
116    evas_object_event_callback_del_full
117       (it->base.view, EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
118    evas_object_event_callback_del_full
119       (it->base.view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, it);
120
121    if (it->icon)
122      evas_object_event_callback_del_full
123         (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
124          _changed_size_hints, it->base.widget);
125
126    if (it->end)
127      evas_object_event_callback_del_full
128         (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
129          _changed_size_hints, it->base.widget);
130
131    eina_stringshare_del(it->label);
132
133    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
134    if (it->long_timer) ecore_timer_del(it->long_timer);
135    if (it->icon) evas_object_del(it->icon);
136    if (it->end) evas_object_del(it->end);
137
138    elm_widget_item_del(it);
139 }
140
141 static Eina_Bool
142 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
143 {
144    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
145    Evas_Event_Key_Down *ev = event_info;
146    Widget_Data *wd = elm_widget_data_get(obj);
147    if (!wd) return EINA_FALSE;
148    if (!wd->items) return EINA_FALSE;
149    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
150    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
151
152    Elm_List_Item *it = NULL;
153    Evas_Coord x = 0;
154    Evas_Coord y = 0;
155    Evas_Coord step_x = 0;
156    Evas_Coord step_y = 0;
157    Evas_Coord v_w = 0;
158    Evas_Coord v_h = 0;
159    Evas_Coord page_x = 0;
160    Evas_Coord page_y = 0;
161
162    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
163    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
164    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
165    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
166
167    /* TODO: fix logic for horizontal mode */
168    if ((!strcmp(ev->keyname, "Left")) ||
169        (!strcmp(ev->keyname, "KP_Left")))
170      {
171         if ((wd->h_mode) &&
172             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
173               (_item_multi_select_up(wd)))
174              || (_item_single_select_up(wd))))
175           {
176              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
177              return EINA_TRUE;
178           }
179         else
180           x -= step_x;
181      }
182    else if ((!strcmp(ev->keyname, "Right")) ||
183             (!strcmp(ev->keyname, "KP_Right")))
184      {
185         if ((wd->h_mode) &&
186             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
187               (_item_multi_select_down(wd)))
188              || (_item_single_select_down(wd))))
189           {
190              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
191              return EINA_TRUE;
192           }
193         else
194           x += step_x;
195      }
196    else if ((!strcmp(ev->keyname, "Up"))  ||
197             (!strcmp(ev->keyname, "KP_Up")))
198      {
199         if ((!wd->h_mode) &&
200             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
201               (_item_multi_select_up(wd)))
202              || (_item_single_select_up(wd))))
203           {
204              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
205              return EINA_TRUE;
206           }
207         else
208           y -= step_y;
209      }
210    else if ((!strcmp(ev->keyname, "Down")) ||
211             (!strcmp(ev->keyname, "KP_Down")))
212      {
213         if ((!wd->h_mode) &&
214             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
215               (_item_multi_select_down(wd)))
216              || (_item_single_select_down(wd))))
217           {
218              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
219              return EINA_TRUE;
220           }
221         else
222           y += step_y;
223      }
224    else if ((!strcmp(ev->keyname, "Home")) ||
225             (!strcmp(ev->keyname, "KP_Home")))
226      {
227         it = eina_list_data_get(wd->items);
228         elm_list_item_bring_in(it);
229         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
230         return EINA_TRUE;
231      }
232    else if ((!strcmp(ev->keyname, "End")) ||
233             (!strcmp(ev->keyname, "KP_End")))
234      {
235         it = eina_list_data_get(eina_list_last(wd->items));
236         elm_list_item_bring_in(it);
237         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
238         return EINA_TRUE;
239      }
240    else if ((!strcmp(ev->keyname, "Prior")) ||
241             (!strcmp(ev->keyname, "KP_Prior")))
242      {
243         if (wd->h_mode)
244           {
245              if (page_x < 0)
246                x -= -(page_x * v_w) / 100;
247              else
248                x -= page_x;
249           }
250         else
251           {
252              if (page_y < 0)
253                y -= -(page_y * v_h) / 100;
254              else
255                y -= page_y;
256           }
257      }
258    else if ((!strcmp(ev->keyname, "Next")) ||
259             (!strcmp(ev->keyname, "KP_Next")))
260      {
261         if (wd->h_mode)
262           {
263              if (page_x < 0)
264                x += -(page_x * v_w) / 100;
265              else
266                x += page_x;
267           }
268         else
269           {
270              if (page_y < 0)
271                y += -(page_y * v_h) / 100;
272              else
273                y += page_y;
274           }
275      }
276    else if (((!strcmp(ev->keyname, "Return")) ||
277             (!strcmp(ev->keyname, "KP_Enter")) ||
278             (!strcmp(ev->keyname, "space")))
279            && (!wd->multi) && (wd->selected))
280      {
281         it = elm_list_selected_item_get(obj);
282         evas_object_smart_callback_call(it->base.widget, SIG_ACTIVATED, it);
283      }
284    else if (!strcmp(ev->keyname, "Escape"))
285      {
286         if (!_deselect_all_items(wd)) return EINA_FALSE;
287         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
288         return EINA_TRUE;
289      }
290    else return EINA_FALSE;
291
292    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
293    elm_smart_scroller_child_pos_set(wd->scr, x, y);
294    return EINA_TRUE;
295 }
296
297 static Eina_Bool
298 _deselect_all_items(Widget_Data *wd)
299 {
300    if (!wd->selected) return EINA_FALSE;
301    while (wd->selected)
302      elm_list_item_selected_set(wd->selected->data, EINA_FALSE);
303
304    return EINA_TRUE;
305 }
306
307 static Eina_Bool
308 _item_multi_select_up(Widget_Data *wd)
309 {
310    if (!wd->selected) return EINA_FALSE;
311    if (!wd->multi) return EINA_FALSE;
312
313    Elm_List_Item *prev = elm_list_item_prev(wd->last_selected_item);
314    if (!prev) return EINA_TRUE;
315
316    if (elm_list_item_selected_get(prev))
317      {
318         elm_list_item_selected_set(wd->last_selected_item, EINA_FALSE);
319         wd->last_selected_item = prev;
320         elm_list_item_show(wd->last_selected_item);
321      }
322    else
323      {
324         elm_list_item_selected_set(prev, EINA_TRUE);
325         elm_list_item_show(prev);
326      }
327    return EINA_TRUE;
328 }
329
330 static Eina_Bool
331 _item_multi_select_down(Widget_Data *wd)
332 {
333    if (!wd->selected) return EINA_FALSE;
334    if (!wd->multi) return EINA_FALSE;
335
336    Elm_List_Item *next = elm_list_item_next(wd->last_selected_item);
337    if (!next) return EINA_TRUE;
338
339    if (elm_list_item_selected_get(next))
340      {
341         elm_list_item_selected_set(wd->last_selected_item, EINA_FALSE);
342         wd->last_selected_item = next;
343         elm_list_item_show(wd->last_selected_item);
344      }
345    else
346      {
347         elm_list_item_selected_set(next, EINA_TRUE);
348         elm_list_item_show(next);
349      }
350    return EINA_TRUE;
351 }
352
353 static Eina_Bool
354 _item_single_select_up(Widget_Data *wd)
355 {
356    Elm_List_Item *prev;
357
358    if (!wd->selected) prev = eina_list_data_get(eina_list_last(wd->items));
359    else prev = elm_list_item_prev(wd->last_selected_item);
360
361    if (!prev) return EINA_FALSE;
362
363    _deselect_all_items(wd);
364
365    elm_list_item_selected_set(prev, EINA_TRUE);
366    elm_list_item_show(prev);
367    return EINA_TRUE;
368 }
369
370 static Eina_Bool
371 _item_single_select_down(Widget_Data *wd)
372 {
373    Elm_List_Item *next;
374
375    if (!wd->selected) next = eina_list_data_get(wd->items);
376    else next = elm_list_item_next(wd->last_selected_item);
377
378    if (!next) return EINA_FALSE;
379
380    _deselect_all_items(wd);
381
382    elm_list_item_selected_set(next, EINA_TRUE);
383    elm_list_item_show(next);
384    return EINA_TRUE;
385 }
386
387 static void
388 _elm_list_process_deletions(Widget_Data *wd)
389 {
390    Elm_List_Item *it;
391
392    wd->walking++; // avoid nested deletion and also _sub_del() fix_items
393
394    EINA_LIST_FREE(wd->to_delete, it)
395      {
396         elm_widget_item_pre_notify_del(it);
397
398         wd->items = eina_list_remove_list(wd->items, it->node);
399         _elm_list_item_free(it);
400      }
401
402    wd->walking--;
403 }
404
405 static inline void
406 _elm_list_walk(Widget_Data *wd)
407 {
408    if (wd->walking < 0)
409      {
410         ERR("ERROR: walking was negative. fixed!\n");
411         wd->walking = 0;
412      }
413    wd->walking++;
414 }
415
416 static inline void
417 _elm_list_unwalk(Widget_Data *wd)
418 {
419    wd->walking--;
420    if (wd->walking < 0)
421      {
422         ERR("ERROR: walking became negative. fixed!\n");
423         wd->walking = 0;
424      }
425
426    if (wd->walking)
427      return;
428
429    if (wd->to_delete)
430      _elm_list_process_deletions(wd);
431
432    if (wd->fix_pending)
433      {
434         wd->fix_pending = EINA_FALSE;
435         _fix_items(wd->self);
436         _sizing_eval(wd->self);
437      }
438 }
439
440 static void
441 _del_pre_hook(Evas_Object *obj)
442 {
443    Widget_Data *wd = elm_widget_data_get(obj);
444    if (!wd) return;
445
446    evas_object_event_callback_del(wd->scr,
447                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
448                                   _changed_size_hints);
449    evas_object_event_callback_del(wd->box,
450                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
451                                   _changed_size_hints);
452 }
453
454 static void
455 _del_hook(Evas_Object *obj)
456 {
457    Widget_Data *wd = elm_widget_data_get(obj);
458    Elm_List_Item *it;
459    Eina_List *n;
460
461    if (!wd) return;
462    if (wd->walking)
463      ERR("ERROR: list deleted while walking.\n");
464
465    _elm_list_walk(wd);
466    EINA_LIST_FOREACH(wd->items, n, it) elm_widget_item_pre_notify_del(it);
467    _elm_list_unwalk(wd);
468    if (wd->to_delete)
469      ERR("ERROR: leaking nodes!\n");
470
471    EINA_LIST_FREE(wd->items, it) _elm_list_item_free(it);
472    eina_list_free(wd->selected);
473    free(wd);
474 }
475
476 static void
477 _show_region_hook(void *data, Evas_Object *obj)
478 {
479    Widget_Data *wd = elm_widget_data_get(data);
480    Evas_Coord x, y, w, h;
481    if (!wd) return;
482    elm_widget_show_region_get(obj, &x, &y, &w, &h);
483    elm_smart_scroller_child_region_set(wd->scr, x, y, w, h);
484 }
485
486 static void
487 _disable_hook(Evas_Object *obj)
488 {
489    Widget_Data *wd = elm_widget_data_get(obj);
490    if (!wd) return;
491    if (elm_widget_disabled_get(obj))
492      {
493         _signal_emit_hook(obj, "elm,state,disabled", "elm");
494         elm_widget_scroll_freeze_push(obj);
495         elm_widget_scroll_hold_push(obj);
496         /* FIXME: if we get to have a way to only un-highlight items
497          * in the future, keeping them selected... */
498         _deselect_all_items(wd);
499      }
500    else
501      {
502         _signal_emit_hook(obj, "elm,state,enabled", "elm");
503         elm_widget_scroll_freeze_pop(obj);
504         elm_widget_scroll_hold_pop(obj);
505      }
506 }
507
508 static void
509 _sizing_eval(Evas_Object *obj)
510 {
511
512    Widget_Data *wd = elm_widget_data_get(obj);
513    if (!wd) return;
514    Evas_Coord  vw, vh, minw, minh, maxw, maxh, w, h, vmw, vmh;
515    double xw, yw;
516
517    evas_object_size_hint_min_get(wd->box, &minw, &minh);
518    evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
519    evas_object_size_hint_weight_get(wd->box, &xw, &yw);
520    if (!wd->scr) return;
521    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
522    if (xw > 0.0)
523      {
524         if ((minw > 0) && (vw < minw)) vw = minw;
525         else if ((maxw > 0) && (vw > maxw)) vw = maxw;
526      }
527    else if (minw > 0) vw = minw;
528    if (yw > 0.0)
529      {
530         if ((minh > 0) && (vh < minh)) vh = minh;
531         else if ((maxh > 0) && (vh > maxh)) vh = maxh;
532      }
533    else if (minh > 0) vh = minh;
534    evas_object_resize(wd->box, vw, vh);
535    w = -1;
536    h = -1;
537    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
538                              &vmw, &vmh);
539    if (wd->scr_minw) w = vmw + minw;
540    if (wd->scr_minh) h = vmh + minh;
541
542    evas_object_size_hint_max_get(obj, &maxw, &maxh);
543    if ((maxw > 0) && (w > maxw))
544      w = maxw;
545    if ((maxh > 0) && (h > maxh))
546      h = maxh;
547
548    evas_object_size_hint_min_set(obj, w, h);
549 }
550
551 static void
552 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
553 {
554    Widget_Data *wd = elm_widget_data_get(obj);
555    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
556                            emission, source);
557 }
558
559 static void
560 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
561 {
562    Widget_Data *wd = elm_widget_data_get(obj);
563    edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
564                                    emission, source, func_cb, data);
565 }
566
567 static void
568 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
569 {
570    Widget_Data *wd = elm_widget_data_get(obj);
571    edje_object_signal_callback_del_full(
572       elm_smart_scroller_edje_object_get(wd->scr),
573       emission, source, func_cb, data);
574 }
575
576 static void
577 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
578 {
579    Widget_Data *wd = elm_widget_data_get(obj);
580    Elm_List_Item *it;
581    Eina_List *n;
582
583    if (!wd) return;
584    if (wd->scr)
585      elm_smart_scroller_mirrored_set(wd->scr, rtl);
586
587    EINA_LIST_FOREACH(wd->items, n, it)
588       edje_object_mirrored_set(it->base.view, rtl);
589 }
590
591 static void
592 _theme_hook(Evas_Object *obj)
593 {
594    Widget_Data *wd = elm_widget_data_get(obj);
595    Elm_List_Item *it;
596    Eina_List *n;
597
598    if (!wd) return;
599    _elm_widget_mirrored_reload(obj);
600    _mirrored_set(obj, elm_widget_mirrored_get(obj));
601
602    if (wd->scr)
603      {
604         Evas_Object *edj;
605         const char *str;
606
607         elm_smart_scroller_object_theme_set(obj, wd->scr, "list", "base",
608                                             elm_widget_style_get(obj));
609         //        edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
610         edj = elm_smart_scroller_edje_object_get(wd->scr);
611         str = edje_object_data_get(edj, "focus_highlight");
612         if ((str) && (!strcmp(str, "on")))
613           elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
614         else
615           elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
616         elm_object_style_set(wd->scr, elm_widget_style_get(obj));
617      }
618    EINA_LIST_FOREACH(wd->items, n, it)
619      {
620         edje_object_scale_set(it->base.view, elm_widget_scale_get(obj) * _elm_config->scale);
621         it->fixed = 0;
622      }
623    _fix_items(obj);
624    _sizing_eval(obj);
625 }
626
627 static void
628 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
629 {
630    Widget_Data *wd = elm_widget_data_get(obj);
631    if (!wd) return;
632    if (elm_widget_focus_get(obj))
633      {
634         edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
635         evas_object_focus_set(wd->self, EINA_TRUE);
636
637         if ((wd->selected) && (!wd->last_selected_item))
638           wd->last_selected_item = eina_list_data_get(wd->selected);
639      }
640    else
641      {
642         edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
643         evas_object_focus_set(wd->self, EINA_FALSE);
644      }
645 }
646
647 static void
648 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
649 {
650    Widget_Data *wd = elm_widget_data_get(data);
651    if (!wd) return;
652    _fix_items(data);
653    _sizing_eval(data);
654 }
655
656 static void
657 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
658 {
659    Widget_Data *wd = elm_widget_data_get(obj);
660    Evas_Object *sub = event_info;
661    const Eina_List *l;
662    Elm_List_Item *it;
663
664    if (!wd) return;
665    if (!sub) abort();
666    if ((sub == wd->box) || (sub == wd->scr)) return;
667
668    EINA_LIST_FOREACH(wd->items, l, it)
669      {
670         if ((sub == it->icon) || (sub == it->end))
671           {
672              if (it->icon == sub) it->icon = NULL;
673              if (it->end == sub) it->end = NULL;
674              evas_object_event_callback_del_full
675              (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints,
676               obj);
677              if (!wd->walking)
678                {
679                   _fix_items(obj);
680                   _sizing_eval(obj);
681                }
682              else
683                wd->fix_pending = EINA_TRUE;
684              break;
685           }
686      }
687 }
688
689 static void
690 _item_highlight(Elm_List_Item *it)
691 {
692    Evas_Object *obj = it->base.widget;
693    Widget_Data *wd = elm_widget_data_get(obj);
694    const char *selectraise;
695
696    if (!wd) return;
697    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
698    if ((it->highlighted) || (it->disabled)) return;
699
700    evas_object_ref(obj);
701    _elm_list_walk(wd);
702
703    edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
704    selectraise = edje_object_data_get(it->base.view, "selectraise");
705    if ((selectraise) && (!strcmp(selectraise, "on")))
706      evas_object_raise(it->base.view);
707    it->highlighted = EINA_TRUE;
708
709    _elm_list_unwalk(wd);
710    evas_object_unref(obj);
711 }
712
713 static void
714 _item_select(Elm_List_Item *it)
715 {
716    Evas_Object *obj = it->base.widget;
717    Widget_Data *wd = elm_widget_data_get(obj);
718
719    if (!wd) return;
720    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
721    if (it->disabled) return;
722    if (it->selected)
723      {
724         if (wd->always_select) goto call;
725         return;
726      }
727    it->selected = EINA_TRUE;
728    wd->selected = eina_list_append(wd->selected, it);
729
730 call:
731    evas_object_ref(obj);
732    _elm_list_walk(wd);
733
734    if (it->func) it->func((void *)it->base.data, it->base.widget, it);
735    evas_object_smart_callback_call(obj, SIG_SELECTED, it);
736    it->wd->last_selected_item = it;
737
738    _elm_list_unwalk(wd);
739    evas_object_unref(obj);
740 }
741
742 static void
743 _item_unselect(Elm_List_Item *it)
744 {
745    Evas_Object *obj = it->base.widget;
746    Widget_Data *wd = elm_widget_data_get(obj);
747    const char *stacking, *selectraise;
748
749    if (!wd) return;
750    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
751    if (!it->highlighted) return;
752
753    evas_object_ref(obj);
754    _elm_list_walk(wd);
755
756    edje_object_signal_emit(it->base.view, "elm,state,unselected", "elm");
757    stacking = edje_object_data_get(it->base.view, "stacking");
758    selectraise = edje_object_data_get(it->base.view, "selectraise");
759    if ((selectraise) && (!strcmp(selectraise, "on")))
760      {
761         if ((stacking) && (!strcmp(stacking, "below")))
762           evas_object_lower(it->base.view);
763      }
764    it->highlighted = EINA_FALSE;
765    if (it->selected)
766      {
767         it->selected = EINA_FALSE;
768         wd->selected = eina_list_remove(wd->selected, it);
769         evas_object_smart_callback_call(it->base.widget, SIG_UNSELECTED, it);
770      }
771
772    _elm_list_unwalk(wd);
773    evas_object_unref(obj);
774 }
775
776 static Eina_Bool
777 _swipe_cancel(void *data)
778 {
779    Elm_List_Item *it = data;
780    Widget_Data *wd = elm_widget_data_get(it->base.widget);
781
782    if (!wd) return ECORE_CALLBACK_CANCEL;
783    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
784    wd->swipe = EINA_FALSE;
785    wd->movements = 0;
786    return ECORE_CALLBACK_RENEW;
787 }
788
789 static void
790 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
791 {
792    Elm_List_Item *it = data;
793    Evas_Object *obj2 = it->base.widget;
794    Widget_Data *wd = elm_widget_data_get(obj2);
795    Evas_Event_Mouse_Move *ev = event_info;
796
797    if (!wd) return;
798    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
799
800    evas_object_ref(obj2);
801    _elm_list_walk(wd);
802
803    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
804      {
805         if (!wd->on_hold)
806           {
807              wd->on_hold = EINA_TRUE;
808              if (it->long_timer)
809                {
810                   ecore_timer_del(it->long_timer);
811                   it->long_timer = NULL;
812                }
813              if (!wd->wasselected)
814                _item_unselect(it);
815           }
816         if (wd->movements == SWIPE_MOVES) wd->swipe = EINA_TRUE;
817         else
818           {
819              wd->history[wd->movements].x = ev->cur.canvas.x;
820              wd->history[wd->movements].y = ev->cur.canvas.y;
821              if (abs((wd->history[wd->movements].x - wd->history[0].x)) > 40)
822                wd->swipe = EINA_TRUE;
823              else
824                wd->movements++;
825           }
826      }
827
828    _elm_list_unwalk(wd);
829    evas_object_unref(obj2);
830 }
831
832 static void
833 _scroll_edge_left(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
834 {
835    Evas_Object *obj = data;
836    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_LEFT, NULL);
837 }
838
839 static void
840 _scroll_edge_right(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
841 {
842    Evas_Object *obj = data;
843    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_RIGHT, NULL);
844 }
845
846 static void
847 _scroll_edge_top(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
848 {
849    Evas_Object *obj = data;
850    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_TOP, NULL);
851 }
852
853 static void
854 _scroll_edge_bottom(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
855 {
856    Evas_Object *obj = data;
857    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_BOTTOM, NULL);
858 }
859
860 static Eina_Bool
861 _long_press(void *data)
862 {
863    Elm_List_Item *it = data;
864    Evas_Object *obj = it->base.widget;
865    Widget_Data *wd = elm_widget_data_get(obj);
866
867    if (!wd) goto end;
868
869    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
870    it->long_timer = NULL;
871    if (it->disabled) goto end;
872
873    wd->longpressed = EINA_TRUE;
874    evas_object_smart_callback_call(it->base.widget, SIG_LONGPRESSED, it);
875
876 end:
877    return ECORE_CALLBACK_CANCEL;
878 }
879
880 static void
881 _swipe(Elm_List_Item *it)
882 {
883    int i, sum = 0;
884    Widget_Data *wd = elm_widget_data_get(it->base.widget);
885
886    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
887    if (!wd) return;
888    wd->swipe = EINA_FALSE;
889    for (i = 0; i < wd->movements; i++)
890      {
891         sum += wd->history[i].x;
892         if (abs(wd->history[0].y - wd->history[i].y) > 10) return;
893      }
894
895    sum /= wd->movements;
896    if (abs(sum - wd->history[0].x) <= 10) return;
897    evas_object_smart_callback_call(it->base.widget, "swipe", it);
898 }
899
900 static void
901 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
902 {
903    Elm_List_Item *it = data;
904    Evas_Object *obj2 = it->base.widget;
905    Widget_Data *wd = elm_widget_data_get(obj2);
906    Evas_Event_Mouse_Down *ev = event_info;
907
908    if (!wd) return;
909    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
910    if (ev->button != 1) return;
911    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
912    else wd->on_hold = EINA_FALSE;
913    if (wd->on_hold) return;
914    wd->wasselected = it->selected;
915
916    evas_object_ref(obj2);
917    _elm_list_walk(wd);
918
919    _item_highlight(it);
920    wd->longpressed = EINA_FALSE;
921    if (it->long_timer) ecore_timer_del(it->long_timer);
922    it->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, it);
923    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
924    it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
925    /* Always call the callbacks last - the user may delete our context! */
926    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
927      {
928         evas_object_smart_callback_call(it->base.widget, SIG_CLICKED_DOUBLE, it);
929         evas_object_smart_callback_call(it->base.widget, SIG_ACTIVATED, it);
930      }
931    wd->swipe = EINA_FALSE;
932    wd->movements = 0;
933
934    _elm_list_unwalk(wd);
935    evas_object_unref(obj2);
936 }
937
938 static void
939 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
940 {
941    Elm_List_Item *it = data;
942    Evas_Object *obj2 = it->base.widget;
943    Widget_Data *wd = elm_widget_data_get(obj2);
944    Evas_Event_Mouse_Up *ev = event_info;
945
946    if (!wd) return;
947    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
948    if (ev->button != 1) return;
949    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
950    else wd->on_hold = EINA_FALSE;
951    wd->longpressed = EINA_FALSE;
952    if (it->long_timer)
953      {
954         ecore_timer_del(it->long_timer);
955         it->long_timer = NULL;
956      }
957    if (it->swipe_timer)
958      {
959         ecore_timer_del(it->swipe_timer);
960         it->swipe_timer = NULL;
961      }
962    if (wd->on_hold)
963      {
964         if (wd->swipe) _swipe(data);
965         wd->on_hold = EINA_FALSE;
966         return;
967      }
968    if (wd->longpressed)
969      {
970         if (!wd->wasselected) _item_unselect(it);
971         wd->wasselected = 0;
972         return;
973      }
974
975    if (it->disabled)
976      return;
977    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
978
979    evas_object_ref(obj2);
980    _elm_list_walk(wd);
981
982    if (wd->multi)
983      {
984         if (!it->selected)
985           {
986              _item_highlight(it);
987              _item_select(it);
988           }
989         else _item_unselect(it);
990      }
991    else
992      {
993         if (!it->selected)
994           {
995              while (wd->selected)
996                _item_unselect(wd->selected->data);
997              _item_highlight(it);
998              _item_select(it);
999           }
1000         else
1001           {
1002              const Eina_List *l, *l_next;
1003              Elm_List_Item *it2;
1004
1005              EINA_LIST_FOREACH_SAFE(wd->selected, l, l_next, it2)
1006                 if (it2 != it) _item_unselect(it2);
1007              _item_highlight(it);
1008              _item_select(it);
1009           }
1010      }
1011
1012    _elm_list_unwalk(wd);
1013    evas_object_unref(obj2);
1014 }
1015
1016 static Elm_List_Item *
1017 _item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1018 {
1019    Widget_Data *wd = elm_widget_data_get(obj);
1020    Elm_List_Item *it;
1021
1022    if (!wd) return NULL;
1023    it = elm_widget_item_new(obj, Elm_List_Item);
1024    it->wd = wd;
1025    it->label = eina_stringshare_add(label);
1026    it->icon = icon;
1027    it->end = end;
1028    it->func = func;
1029    it->base.data = data;
1030    it->base.view = edje_object_add(evas_object_evas_get(obj));
1031    edje_object_mirrored_set(it->base.view, elm_widget_mirrored_get(obj));
1032    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_DOWN,
1033                                   _mouse_down, it);
1034    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_UP,
1035                                   _mouse_up, it);
1036    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_MOVE,
1037                                   _mouse_move, it);
1038    evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1039    evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL);
1040    if (it->icon)
1041      {
1042         elm_widget_sub_object_add(obj, it->icon);
1043         evas_object_event_callback_add(it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1044                                        _changed_size_hints, obj);
1045      }
1046    if (it->end)
1047      {
1048         elm_widget_sub_object_add(obj, it->end);
1049         evas_object_event_callback_add(it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1050                                        _changed_size_hints, obj);
1051      }
1052    return it;
1053 }
1054
1055 static void
1056 _elm_list_mode_set_internal(Widget_Data *wd)
1057 {
1058    if (!wd->scr)
1059      return;
1060
1061    if (wd->mode == ELM_LIST_LIMIT)
1062      {
1063         if (!wd->h_mode)
1064           {
1065              wd->scr_minw = EINA_TRUE;
1066              wd->scr_minh = EINA_FALSE;
1067           }
1068         else
1069           {
1070              wd->scr_minw = EINA_FALSE;
1071              wd->scr_minh = EINA_TRUE;
1072           }
1073      }
1074    else if (wd->mode == ELM_LIST_EXPAND)
1075      {
1076         wd->scr_minw = EINA_TRUE;
1077         wd->scr_minh = EINA_TRUE;
1078      }
1079    else
1080      {
1081         wd->scr_minw = EINA_FALSE;
1082         wd->scr_minh = EINA_FALSE;
1083      }
1084
1085    _sizing_eval(wd->self);
1086 }
1087
1088 static void
1089 _fix_items(Evas_Object *obj)
1090 {
1091    Widget_Data *wd = elm_widget_data_get(obj);
1092    if (!wd) return;
1093    const Eina_List *l;
1094    Elm_List_Item *it;
1095    Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 };
1096    Evas_Coord mw, mh;
1097    int i, redo = 0;
1098    const char *style = elm_widget_style_get(obj);
1099    const char *it_plain = wd->h_mode ? "h_item" : "item";
1100    const char *it_odd = wd->h_mode ? "h_item_odd" : "item_odd";
1101    const char *it_compress = wd->h_mode ? "h_item_compress" : "item_compress";
1102    const char *it_compress_odd = wd->h_mode ? "h_item_compress_odd" : "item_compress_odd";
1103
1104    if (wd->walking)
1105      {
1106         wd->fix_pending = EINA_TRUE;
1107         return;
1108      }
1109
1110    evas_object_ref(obj);
1111    _elm_list_walk(wd); // watch out "return" before unwalk!
1112
1113    EINA_LIST_FOREACH(wd->items, l, it)
1114      {
1115         if (it->deleted) continue;
1116         if (it->icon)
1117           {
1118              evas_object_size_hint_min_get(it->icon, &mw, &mh);
1119              if (mw > minw[0]) minw[0] = mw;
1120              if (mh > minh[0]) minh[0] = mh;
1121           }
1122         if (it->end)
1123           {
1124              evas_object_size_hint_min_get(it->end, &mw, &mh);
1125              if (mw > minw[1]) minw[1] = mw;
1126              if (mh > minh[1]) minh[1] = mh;
1127           }
1128      }
1129
1130    if ((minw[0] != wd->minw[0]) || (minw[1] != wd->minw[1]) ||
1131        (minw[0] != wd->minh[0]) || (minh[1] != wd->minh[1]))
1132      {
1133         wd->minw[0] = minw[0];
1134         wd->minw[1] = minw[1];
1135         wd->minh[0] = minh[0];
1136         wd->minh[1] = minh[1];
1137         redo = 1;
1138      }
1139    i = 0;
1140    EINA_LIST_FOREACH(wd->items, l, it)
1141      {
1142         if (it->deleted)
1143           continue;
1144
1145         it->even = i & 0x1;
1146         if ((it->even != it->is_even) || (!it->fixed) || (redo))
1147           {
1148              const char *stacking;
1149
1150              /* FIXME: separators' themes seem to be b0rked */
1151              if (it->is_separator)
1152                _elm_theme_object_set(obj, it->base.view, "separator",
1153                                      wd->h_mode ? "horizontal" : "vertical",
1154                                      style);
1155              else if (wd->mode == ELM_LIST_COMPRESS)
1156                {
1157                   if (it->even)
1158                     _elm_theme_object_set(obj, it->base.view, "list",
1159                                           it_compress, style);
1160                   else
1161                     _elm_theme_object_set(obj, it->base.view, "list",
1162                                           it_compress_odd, style);
1163                }
1164              else
1165                {
1166                   if (it->even)
1167                     _elm_theme_object_set(obj, it->base.view, "list", it_plain,
1168                                           style);
1169                   else
1170                     _elm_theme_object_set(obj, it->base.view, "list", it_odd,
1171                                           style);
1172                }
1173              stacking = edje_object_data_get(it->base.view, "stacking");
1174              if (stacking)
1175                {
1176                   if (!strcmp(stacking, "below"))
1177                     evas_object_lower(it->base.view);
1178                   else if (!strcmp(stacking, "above"))
1179                     evas_object_raise(it->base.view);
1180                }
1181              edje_object_part_text_set(it->base.view, "elm.text", it->label);
1182
1183              if ((!it->icon) && (minh[0] > 0))
1184                {
1185                   it->icon = evas_object_rectangle_add(evas_object_evas_get(it->base.view));
1186                   evas_object_color_set(it->icon, 0, 0, 0, 0);
1187                   it->dummy_icon = EINA_TRUE;
1188                }
1189              if ((!it->end) && (minh[1] > 0))
1190                {
1191                   it->end = evas_object_rectangle_add(evas_object_evas_get(it->base.view));
1192                   evas_object_color_set(it->end, 0, 0, 0, 0);
1193                   it->dummy_end = EINA_TRUE;
1194                }
1195              if (it->icon)
1196                {
1197                   evas_object_size_hint_min_set(it->icon, minw[0], minh[0]);
1198                   evas_object_size_hint_max_set(it->icon, 99999, 99999);
1199                   edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
1200                }
1201              if (it->end)
1202                {
1203                   evas_object_size_hint_min_set(it->end, minw[1], minh[1]);
1204                   evas_object_size_hint_max_set(it->end, 99999, 99999);
1205                   edje_object_part_swallow(it->base.view, "elm.swallow.end", it->end);
1206                }
1207              if (!it->fixed)
1208                {
1209                   // this may call up user and it may modify the list item
1210                   // but we're safe as we're flagged as walking.
1211                   // just don't process further
1212                   edje_object_message_signal_process(it->base.view);
1213                   if (it->deleted)
1214                     continue;
1215                   mw = mh = -1;
1216                   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1217                   edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
1218                   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1219                   evas_object_size_hint_min_set(it->base.view, mw, mh);
1220                   evas_object_show(it->base.view);
1221                }
1222              if ((it->selected) || (it->highlighted))
1223                {
1224                   const char *selectraise;
1225
1226                   // this may call up user and it may modify the list item
1227                   // but we're safe as we're flagged as walking.
1228                   // just don't process further
1229                   edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
1230                   if (it->deleted)
1231                     continue;
1232
1233                   selectraise = edje_object_data_get(it->base.view, "selectraise");
1234                   if ((selectraise) && (!strcmp(selectraise, "on")))
1235                     evas_object_raise(it->base.view);
1236                }
1237              if (it->disabled)
1238                edje_object_signal_emit(it->base.view, "elm,state,disabled",
1239                                        "elm");
1240
1241              it->fixed = EINA_TRUE;
1242              it->is_even = it->even;
1243           }
1244         i++;
1245      }
1246
1247    mw = 0; mh = 0;
1248    evas_object_size_hint_min_get(wd->box, &mw, &mh);
1249
1250    _elm_list_mode_set_internal(wd);
1251
1252    _elm_list_unwalk(wd);
1253    evas_object_unref(obj);
1254 }
1255
1256 static void
1257 _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1258 {
1259    Widget_Data *wd = elm_widget_data_get(obj);
1260    if (!wd) return;
1261    if (wd->scr)
1262      elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
1263 }
1264
1265 static void
1266 _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1267 {
1268    Widget_Data *wd = elm_widget_data_get(obj);
1269    if (!wd) return;
1270    if (wd->scr)
1271      elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1272 }
1273
1274 static void
1275 _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1276 {
1277    Widget_Data *wd = elm_widget_data_get(obj);
1278    if (!wd) return;
1279    if (wd->scr)
1280      elm_smart_scroller_freeze_set(wd->scr, EINA_TRUE);
1281 }
1282
1283 static void
1284 _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1285 {
1286    Widget_Data *wd = elm_widget_data_get(obj);
1287    if (!wd) return;
1288    if (wd->scr)
1289      elm_smart_scroller_freeze_set(wd->scr, EINA_FALSE);
1290 }
1291
1292 static void
1293 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1294 {
1295    _sizing_eval(data);
1296 }
1297
1298 EAPI Evas_Object *
1299 elm_list_add(Evas_Object *parent)
1300 {
1301    Evas_Object *obj;
1302    Evas *e;
1303    Widget_Data *wd;
1304    Evas_Coord minw, minh;
1305
1306    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1307
1308    ELM_SET_WIDTYPE(widtype, "list");
1309    elm_widget_type_set(obj, "list");
1310    elm_widget_sub_object_add(parent, obj);
1311    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1312    elm_widget_data_set(obj, wd);
1313    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1314    elm_widget_del_hook_set(obj, _del_hook);
1315    elm_widget_theme_hook_set(obj, _theme_hook);
1316    elm_widget_disable_hook_set(obj, _disable_hook);
1317    elm_widget_can_focus_set(obj, EINA_TRUE);
1318    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1319    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
1320    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
1321    elm_widget_event_hook_set(obj, _event_hook);
1322
1323    wd->self = obj;
1324    wd->scr = elm_smart_scroller_add(e);
1325    elm_smart_scroller_widget_set(wd->scr, obj);
1326    elm_widget_resize_object_set(obj, wd->scr);
1327    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1328                                   _changed_size_hints, obj);
1329    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
1330    evas_object_size_hint_min_set(obj, minw, minh);
1331    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1332
1333    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
1334                                        _elm_config->thumbscroll_bounce_enable);
1335
1336    wd->box = elm_box_add(parent);
1337    elm_box_homogeneous_set(wd->box, 1);
1338    evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
1339    evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
1340    elm_widget_on_show_region_hook_set(wd->box, _show_region_hook, obj);
1341    elm_widget_sub_object_add(obj, wd->box);
1342    elm_smart_scroller_child_set(wd->scr, wd->box);
1343    evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1344                                   _changed_size_hints, obj);
1345
1346    evas_object_show(wd->box);
1347
1348    _theme_hook(obj);
1349
1350    wd->mode = ELM_LIST_SCROLL;
1351
1352    evas_object_smart_callback_add(wd->scr, "edge,left", _scroll_edge_left, obj);
1353    evas_object_smart_callback_add(wd->scr, "edge,right", _scroll_edge_right, obj);
1354    evas_object_smart_callback_add(wd->scr, "edge,top", _scroll_edge_top, obj);
1355    evas_object_smart_callback_add(wd->scr, "edge,bottom", _scroll_edge_bottom, obj);
1356
1357    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1358    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1359    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1360    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1361    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1362
1363    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1364
1365    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1366    _sizing_eval(obj);
1367    return obj;
1368 }
1369
1370 EAPI Elm_List_Item *
1371 elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1372 {
1373    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1374    Widget_Data *wd = elm_widget_data_get(obj);
1375    Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1376
1377    wd->items = eina_list_append(wd->items, it);
1378    it->node = eina_list_last(wd->items);
1379    elm_box_pack_end(wd->box, it->base.view);
1380    return it;
1381 }
1382
1383 EAPI Elm_List_Item *
1384 elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1385 {
1386    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1387    Widget_Data *wd = elm_widget_data_get(obj);
1388    Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1389
1390    wd->items = eina_list_prepend(wd->items, it);
1391    it->node = wd->items;
1392    elm_box_pack_start(wd->box, it->base.view);
1393    return it;
1394 }
1395
1396 EAPI Elm_List_Item *
1397 elm_list_item_insert_before(Evas_Object *obj, Elm_List_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1398 {
1399    Widget_Data *wd;
1400    Elm_List_Item *it;
1401
1402    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
1403    if (!before->node) return NULL;
1404    ELM_LIST_ITEM_CHECK_DELETED_RETURN(before, NULL);
1405
1406    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1407    wd = elm_widget_data_get(obj);
1408    if (!wd) return NULL;
1409    it = _item_new(obj, label, icon, end, func, data);
1410    wd->items = eina_list_prepend_relative_list(wd->items, it, before->node);
1411    it->node = before->node->prev;
1412    elm_box_pack_before(wd->box, it->base.view, before->base.view);
1413    return it;
1414 }
1415
1416 EAPI Elm_List_Item *
1417 elm_list_item_insert_after(Evas_Object *obj, Elm_List_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1418 {
1419    Widget_Data *wd;
1420    Elm_List_Item *it;
1421
1422    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
1423    if (!after->node) return NULL;
1424    ELM_LIST_ITEM_CHECK_DELETED_RETURN(after, NULL);
1425
1426    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1427    wd = elm_widget_data_get(obj);
1428    if (!wd) return NULL;
1429    it = _item_new(obj, label, icon, end, func, data);
1430    wd->items = eina_list_append_relative_list(wd->items, it, after->node);
1431    it->node = after->node->next;
1432    elm_box_pack_after(wd->box, it->base.view, after->base.view);
1433    return it;
1434 }
1435
1436 EAPI Elm_List_Item *
1437 elm_list_item_sorted_insert(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func)
1438 {
1439    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1440    Widget_Data *wd = elm_widget_data_get(obj);
1441    Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1442    Eina_List *l;
1443
1444    wd->items = eina_list_sorted_insert(wd->items, cmp_func, it);
1445    l = eina_list_data_find_list(wd->items, it);
1446    l = eina_list_next(l);
1447    if (!l)
1448      {
1449         it->node = eina_list_last(wd->items);
1450         elm_box_pack_end(wd->box, it->base.view);
1451      }
1452    else
1453      {
1454         Elm_List_Item *before = eina_list_data_get(l);
1455         it->node = before->node->prev;
1456         elm_box_pack_before(wd->box, it->base.view, before->base.view);
1457      }
1458    return it;
1459 }
1460
1461 EAPI void
1462 elm_list_clear(Evas_Object *obj)
1463 {
1464    ELM_CHECK_WIDTYPE(obj, widtype);
1465    Widget_Data *wd = elm_widget_data_get(obj);
1466    Elm_List_Item *it;
1467
1468    if (!wd) return;
1469    if (!wd->items) return;
1470
1471    eina_list_free(wd->selected);
1472    wd->selected = NULL;
1473
1474    if (wd->walking > 0)
1475      {
1476         Eina_List *n;
1477
1478         EINA_LIST_FOREACH(wd->items, n, it)
1479           {
1480              if (it->deleted) continue;
1481              it->deleted = EINA_TRUE;
1482              wd->to_delete = eina_list_append(wd->to_delete, it);
1483           }
1484         return;
1485      }
1486
1487    evas_object_ref(obj);
1488    _elm_list_walk(wd);
1489
1490    EINA_LIST_FREE(wd->items, it)
1491      {
1492         elm_widget_item_pre_notify_del(it);
1493         _elm_list_item_free(it);
1494      }
1495
1496    _elm_list_unwalk(wd);
1497
1498    _fix_items(obj);
1499    _sizing_eval(obj);
1500    evas_object_unref(obj);
1501 }
1502
1503 EAPI void
1504 elm_list_go(Evas_Object *obj)
1505 {
1506    ELM_CHECK_WIDTYPE(obj, widtype);
1507    Widget_Data *wd = elm_widget_data_get(obj);
1508    if (!wd) return;
1509    _fix_items(obj);
1510 }
1511
1512 EAPI void
1513 elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi)
1514 {
1515    ELM_CHECK_WIDTYPE(obj, widtype);
1516    Widget_Data *wd = elm_widget_data_get(obj);
1517    if (!wd) return;
1518    wd->multi = multi;
1519 }
1520
1521 EAPI Eina_Bool
1522 elm_list_multi_select_get(const Evas_Object *obj)
1523 {
1524    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1525    Widget_Data *wd = elm_widget_data_get(obj);
1526    if (!wd) return EINA_FALSE;
1527    return wd->multi;
1528 }
1529
1530 EAPI void
1531 elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode)
1532 {
1533    ELM_CHECK_WIDTYPE(obj, widtype);
1534
1535    Widget_Data *wd;
1536
1537    wd = elm_widget_data_get(obj);
1538    if (!wd)
1539      return;
1540    if (wd->mode == mode)
1541      return;
1542    wd->mode = mode;
1543
1544    _elm_list_mode_set_internal(wd);
1545 }
1546
1547 EAPI Elm_List_Mode
1548 elm_list_mode_get(const Evas_Object *obj)
1549 {
1550    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
1551    Widget_Data *wd = elm_widget_data_get(obj);
1552    if (!wd) return ELM_LIST_LAST;
1553    return wd->mode;
1554 }
1555
1556 EAPI void
1557 elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
1558 {
1559    ELM_CHECK_WIDTYPE(obj, widtype);
1560
1561    Widget_Data *wd;
1562    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1563
1564    wd = elm_widget_data_get(obj);
1565    if (!wd)
1566      return;
1567
1568    if (wd->h_mode == horizontal)
1569      return;
1570
1571    wd->h_mode = horizontal;
1572    elm_box_horizontal_set(wd->box, horizontal);
1573
1574    if (horizontal)
1575      {
1576         evas_object_size_hint_weight_set(wd->box, 0.0, EVAS_HINT_EXPAND);
1577         evas_object_size_hint_align_set(wd->box, 0.0, EVAS_HINT_FILL);
1578         elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1579      }
1580    else
1581      {
1582         evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
1583         evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
1584         elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, bounce);
1585      }
1586
1587    _elm_list_mode_set_internal(wd);
1588 }
1589
1590 EAPI Eina_Bool
1591 elm_list_horizontal_get(const Evas_Object *obj)
1592 {
1593    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1594
1595    Widget_Data *wd;
1596
1597    wd = elm_widget_data_get(obj);
1598    if (!wd)
1599      return EINA_FALSE;
1600
1601    return wd->h_mode;
1602 }
1603
1604 EAPI void
1605 elm_list_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select)
1606 {
1607    ELM_CHECK_WIDTYPE(obj, widtype);
1608    Widget_Data *wd = elm_widget_data_get(obj);
1609    if (!wd) return;
1610    wd->always_select = always_select;
1611 }
1612
1613 EAPI Eina_Bool
1614 elm_list_always_select_mode_get(const Evas_Object *obj)
1615 {
1616    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1617    Widget_Data *wd = elm_widget_data_get(obj);
1618    if (!wd) return EINA_FALSE;
1619    return wd->always_select;
1620 }
1621
1622 EAPI const Eina_List *
1623 elm_list_items_get(const Evas_Object *obj)
1624 {
1625    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1626    Widget_Data *wd = elm_widget_data_get(obj);
1627    if (!wd) return NULL;
1628    return wd->items;
1629 }
1630
1631 EAPI Elm_List_Item *
1632 elm_list_selected_item_get(const Evas_Object *obj)
1633 {
1634    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1635    Widget_Data *wd = elm_widget_data_get(obj);
1636    if (!wd) return NULL;
1637    if (wd->selected) return wd->selected->data;
1638    return NULL;
1639 }
1640
1641 EAPI const Eina_List *
1642 elm_list_selected_items_get(const Evas_Object *obj)
1643 {
1644    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1645    Widget_Data *wd = elm_widget_data_get(obj);
1646    if (!wd) return NULL;
1647    return wd->selected;
1648 }
1649
1650 EAPI void
1651 elm_list_item_separator_set(Elm_List_Item *it, Eina_Bool setting)
1652 {
1653    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1654    it->is_separator = !!setting;
1655 }
1656
1657 EAPI Eina_Bool
1658 elm_list_item_separator_get(const Elm_List_Item *it)
1659 {
1660    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
1661    return it->is_separator;
1662 }
1663
1664
1665 EAPI void
1666 elm_list_item_selected_set(Elm_List_Item *it, Eina_Bool selected)
1667 {
1668    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1669    Evas_Object *obj = it->base.widget;
1670    Widget_Data *wd = elm_widget_data_get(obj);
1671    if (!wd) return;
1672
1673    selected = !!selected;
1674    if (it->selected == selected) return;
1675
1676    evas_object_ref(obj);
1677    _elm_list_walk(wd);
1678
1679    if (selected)
1680      {
1681         if (!wd->multi)
1682           {
1683              while (wd->selected)
1684                _item_unselect(wd->selected->data);
1685           }
1686         _item_highlight(it);
1687         _item_select(it);
1688      }
1689    else
1690      _item_unselect(it);
1691
1692    _elm_list_unwalk(wd);
1693    evas_object_unref(obj);
1694 }
1695
1696 EAPI Eina_Bool
1697 elm_list_item_selected_get(const Elm_List_Item *it)
1698 {
1699    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
1700    return it->selected;
1701 }
1702
1703 EAPI void
1704 elm_list_item_show(Elm_List_Item *it)
1705 {
1706    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1707    Widget_Data *wd = elm_widget_data_get(it->base.widget);
1708    Evas_Coord bx, by, bw, bh;
1709    Evas_Coord x, y, w, h;
1710
1711    evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
1712    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
1713    x -= bx;
1714    y -= by;
1715    if (wd->scr)
1716      elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
1717 }
1718
1719 EAPI void
1720 elm_list_item_bring_in(Elm_List_Item *it)
1721 {
1722    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1723    Widget_Data *wd = elm_widget_data_get(it->base.widget);
1724    Evas_Coord bx, by, bw, bh;
1725    Evas_Coord x, y, w, h;
1726
1727    evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
1728    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
1729    x -= bx;
1730    y -= by;
1731    if (wd->scr)
1732      elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
1733 }
1734
1735 EAPI void
1736 elm_list_item_del(Elm_List_Item *it)
1737 {
1738    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1739    Evas_Object *obj = it->base.widget;
1740    Widget_Data *wd = elm_widget_data_get(obj);
1741    if (!wd) return;
1742
1743    if (it->selected) _item_unselect(it);
1744
1745    if (wd->walking > 0)
1746      {
1747         if (it->deleted) return;
1748         it->deleted = EINA_TRUE;
1749         wd->to_delete = eina_list_append(wd->to_delete, it);
1750         return;
1751      }
1752
1753    wd->items = eina_list_remove_list(wd->items, it->node);
1754
1755    evas_object_ref(obj);
1756    _elm_list_walk(wd);
1757
1758    elm_widget_item_pre_notify_del(it);
1759    _elm_list_item_free(it);
1760
1761    _elm_list_unwalk(wd);
1762    evas_object_unref(obj);
1763 }
1764
1765 EAPI void
1766 elm_list_item_del_cb_set(Elm_List_Item *it, Evas_Smart_Cb func)
1767 {
1768    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1769    elm_widget_item_del_cb_set(it, func);
1770 }
1771
1772 EAPI void *
1773 elm_list_item_data_get(const Elm_List_Item *it)
1774 {
1775    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1776    return elm_widget_item_data_get(it);
1777 }
1778
1779 EAPI Evas_Object *
1780 elm_list_item_icon_get(const Elm_List_Item *it)
1781 {
1782    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1783    if (it->dummy_icon) return NULL;
1784    return it->icon;
1785 }
1786
1787 EAPI void
1788 elm_list_item_icon_set(Elm_List_Item *it, Evas_Object *icon)
1789 {
1790    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1791    if (it->icon == icon) return;
1792    if ((it->dummy_icon) && (!icon)) return;
1793    if (it->dummy_icon)
1794      {
1795         evas_object_del(it->icon);
1796         it->dummy_icon = EINA_FALSE;
1797      }
1798    if (!icon)
1799      {
1800         icon = evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
1801         evas_object_color_set(icon, 0, 0, 0, 0);
1802         it->dummy_icon = EINA_TRUE;
1803      }
1804    if (it->icon)
1805      {
1806         evas_object_del(it->icon);
1807         it->icon = NULL;
1808      }
1809    it->icon = icon;
1810    if (it->base.view)
1811      edje_object_part_swallow(it->base.view, "elm.swallow.icon", icon);
1812 }
1813
1814 EAPI Evas_Object *
1815 elm_list_item_end_get(const Elm_List_Item *it)
1816 {
1817    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1818    if (it->dummy_end) return NULL;
1819    return it->end;
1820 }
1821
1822 EAPI void
1823 elm_list_item_end_set(Elm_List_Item *it, Evas_Object *end)
1824 {
1825    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1826    if (it->end == end) return;
1827    if ((it->dummy_end) && (!end)) return;
1828    if (it->dummy_end)
1829      {
1830         evas_object_del(it->end);
1831         it->dummy_icon = EINA_FALSE;
1832      }
1833    if (!end)
1834      {
1835         end = evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
1836         evas_object_color_set(end, 0, 0, 0, 0);
1837         it->dummy_end = EINA_TRUE;
1838      }
1839    if (it->end)
1840      {
1841         evas_object_del(it->end);
1842         it->end = NULL;
1843      }
1844    it->end = end;
1845    if (it->base.view)
1846      edje_object_part_swallow(it->base.view, "elm.swallow.end", end);
1847 }
1848
1849 EAPI Evas_Object *
1850 elm_list_item_base_get(const Elm_List_Item *it)
1851 {
1852    return elm_list_item_object_get(it);
1853 }
1854
1855 EAPI Evas_Object *
1856 elm_list_item_object_get(const Elm_List_Item *it)
1857 {
1858    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1859    return it->base.view;
1860 }
1861
1862 EAPI const char *
1863 elm_list_item_label_get(const Elm_List_Item *it)
1864 {
1865    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1866    return it->label;
1867 }
1868
1869 EAPI void
1870 elm_list_item_label_set(Elm_List_Item *it, const char *text)
1871 {
1872    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1873    if (!eina_stringshare_replace(&it->label, text)) return;
1874    if (it->base.view)
1875      edje_object_part_text_set(it->base.view, "elm.text", it->label);
1876 }
1877
1878 EAPI Elm_List_Item *
1879 elm_list_item_prev(const Elm_List_Item *it)
1880 {
1881    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1882    if (it->node->prev) return it->node->prev->data;
1883    else return NULL;
1884 }
1885
1886 EAPI Elm_List_Item *
1887 elm_list_item_next(const Elm_List_Item *it)
1888 {
1889    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1890    if (it->node->next) return it->node->next->data;
1891    else return NULL;
1892 }
1893
1894 EAPI void
1895 elm_list_item_tooltip_text_set(Elm_List_Item *item, const char *text)
1896 {
1897    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1898    elm_widget_item_tooltip_text_set(item, text);
1899 }
1900
1901 EAPI void
1902 elm_list_item_tooltip_content_cb_set(Elm_List_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
1903 {
1904    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1905    elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
1906 }
1907
1908 EAPI void
1909 elm_list_item_tooltip_unset(Elm_List_Item *item)
1910 {
1911    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1912    elm_widget_item_tooltip_unset(item);
1913 }
1914
1915 EAPI Eina_Bool
1916 elm_list_item_tooltip_size_restrict_disable(Elm_List_Item *item, Eina_Bool disable)
1917 {
1918    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
1919    return elm_widget_item_tooltip_size_restrict_disable(item, disable);
1920 }
1921
1922 EAPI Eina_Bool
1923 elm_list_item_tooltip_size_restrict_disabled_get(const Elm_List_Item *item)
1924 {
1925    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
1926    return elm_widget_item_tooltip_size_restrict_disabled_get(item);
1927 }
1928
1929 EAPI void
1930 elm_list_item_tooltip_style_set(Elm_List_Item *item, const char *style)
1931 {
1932    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1933    elm_widget_item_tooltip_style_set(item, style);
1934 }
1935
1936 EAPI const char *
1937 elm_list_item_tooltip_style_get(const Elm_List_Item *item)
1938 {
1939    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
1940    return elm_widget_item_tooltip_style_get(item);
1941 }
1942
1943 EAPI void
1944 elm_list_item_cursor_set(Elm_List_Item *item, const char *cursor)
1945 {
1946    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1947    elm_widget_item_cursor_set(item, cursor);
1948 }
1949
1950 EAPI const char *
1951 elm_list_item_cursor_get(const Elm_List_Item *item)
1952 {
1953    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
1954    return elm_widget_item_cursor_get(item);
1955 }
1956
1957 EAPI void
1958 elm_list_item_cursor_unset(Elm_List_Item *item)
1959 {
1960    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1961    elm_widget_item_cursor_unset(item);
1962 }
1963
1964 EAPI void
1965 elm_list_item_cursor_style_set(Elm_List_Item *item, const char *style)
1966 {
1967    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1968    elm_widget_item_cursor_style_set(item, style);
1969 }
1970
1971 EAPI const char *
1972 elm_list_item_cursor_style_get(const Elm_List_Item *item)
1973 {
1974    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
1975    return elm_widget_item_cursor_style_get(item);
1976 }
1977
1978 EAPI void
1979 elm_list_item_cursor_engine_only_set(Elm_List_Item *item, Eina_Bool engine_only)
1980 {
1981    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1982    elm_widget_item_cursor_engine_only_set(item, engine_only);
1983 }
1984
1985 EAPI Eina_Bool
1986 elm_list_item_cursor_engine_only_get(const Elm_List_Item *item)
1987 {
1988    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
1989    return elm_widget_item_cursor_engine_only_get(item);
1990 }
1991
1992 EAPI void
1993 elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1994 {
1995    ELM_CHECK_WIDTYPE(obj, widtype);
1996    Widget_Data *wd = elm_widget_data_get(obj);
1997    if (!wd) return;
1998    if (wd->scr)
1999      elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
2000 }
2001
2002 EAPI void
2003 elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
2004 {
2005    ELM_CHECK_WIDTYPE(obj, widtype);
2006    Widget_Data *wd = elm_widget_data_get(obj);
2007    if (!wd) return;
2008    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
2009 }
2010
2011 EAPI void
2012 elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
2013 {
2014    ELM_CHECK_WIDTYPE(obj, widtype);
2015    Widget_Data *wd = elm_widget_data_get(obj);
2016    if ((!wd) || (!wd->scr)) return;
2017    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
2018        (policy_v >= ELM_SCROLLER_POLICY_LAST))
2019      return;
2020    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
2021 }
2022
2023 EAPI void
2024 elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
2025 {
2026    ELM_CHECK_WIDTYPE(obj, widtype);
2027    Widget_Data *wd = elm_widget_data_get(obj);
2028    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
2029    if ((!wd) || (!wd->scr)) return;
2030    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
2031    if (policy_h) *policy_h = (Elm_Scroller_Policy) s_policy_h;
2032    if (policy_v) *policy_v = (Elm_Scroller_Policy) s_policy_v;
2033 }
2034
2035 EAPI void
2036 elm_list_item_disabled_set(Elm_List_Item *it, Eina_Bool disabled)
2037 {
2038    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
2039
2040    if (it->disabled == disabled)
2041      return;
2042
2043    it->disabled = !!disabled;
2044
2045    if (it->disabled)
2046      edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
2047    else
2048      edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
2049 }
2050
2051 EAPI Eina_Bool
2052 elm_list_item_disabled_get(const Elm_List_Item *it)
2053 {
2054    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
2055
2056    return it->disabled;
2057 }