f80bd639171b9db07f61bbf28f796d58396aac10
[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 hilighted : 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-hilight 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_hilight(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->hilighted) 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->hilighted = 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->selected)
722      {
723         if (wd->always_select) goto call;
724         return;
725      }
726    it->selected = EINA_TRUE;
727    wd->selected = eina_list_append(wd->selected, it);
728
729 call:
730    evas_object_ref(obj);
731    _elm_list_walk(wd);
732
733    if (it->func) it->func((void *)it->base.data, it->base.widget, it);
734    evas_object_smart_callback_call(obj, SIG_SELECTED, it);
735    it->wd->last_selected_item = it;
736
737    _elm_list_unwalk(wd);
738    evas_object_unref(obj);
739 }
740
741 static void
742 _item_unselect(Elm_List_Item *it)
743 {
744    Evas_Object *obj = it->base.widget;
745    Widget_Data *wd = elm_widget_data_get(obj);
746    const char *stacking, *selectraise;
747
748    if (!wd) return;
749    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
750    if (!it->hilighted) return;
751
752    evas_object_ref(obj);
753    _elm_list_walk(wd);
754
755    edje_object_signal_emit(it->base.view, "elm,state,unselected", "elm");
756    stacking = edje_object_data_get(it->base.view, "stacking");
757    selectraise = edje_object_data_get(it->base.view, "selectraise");
758    if ((selectraise) && (!strcmp(selectraise, "on")))
759      {
760         if ((stacking) && (!strcmp(stacking, "below")))
761           evas_object_lower(it->base.view);
762      }
763    it->hilighted = EINA_FALSE;
764    if (it->selected)
765      {
766         it->selected = EINA_FALSE;
767         wd->selected = eina_list_remove(wd->selected, it);
768         evas_object_smart_callback_call(it->base.widget, SIG_UNSELECTED, it);
769      }
770
771    _elm_list_unwalk(wd);
772    evas_object_unref(obj);
773 }
774
775 static Eina_Bool
776 _swipe_cancel(void *data)
777 {
778    Elm_List_Item *it = data;
779    Widget_Data *wd = elm_widget_data_get(it->base.widget);
780
781    if (!wd) return ECORE_CALLBACK_CANCEL;
782    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
783    wd->swipe = EINA_FALSE;
784    wd->movements = 0;
785    return ECORE_CALLBACK_RENEW;
786 }
787
788 static void
789 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
790 {
791    Elm_List_Item *it = data;
792    Evas_Object *obj2 = it->base.widget;
793    Widget_Data *wd = elm_widget_data_get(obj2);
794    Evas_Event_Mouse_Move *ev = event_info;
795
796    if (!wd) return;
797    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
798
799    evas_object_ref(obj2);
800    _elm_list_walk(wd);
801
802    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
803      {
804         if (!wd->on_hold)
805           {
806              wd->on_hold = EINA_TRUE;
807              if (it->long_timer)
808                {
809                   ecore_timer_del(it->long_timer);
810                   it->long_timer = NULL;
811                }
812              if (!wd->wasselected)
813                _item_unselect(it);
814           }
815         if (wd->movements == SWIPE_MOVES) wd->swipe = EINA_TRUE;
816         else
817           {
818              wd->history[wd->movements].x = ev->cur.canvas.x;
819              wd->history[wd->movements].y = ev->cur.canvas.y;
820              if (abs((wd->history[wd->movements].x - wd->history[0].x)) > 40)
821                wd->swipe = EINA_TRUE;
822              else
823                wd->movements++;
824           }
825      }
826
827    _elm_list_unwalk(wd);
828    evas_object_unref(obj2);
829 }
830
831 static void
832 _scroll_edge_left(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
833 {
834    Evas_Object *obj = data;
835    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_LEFT, NULL);
836 }
837
838 static void
839 _scroll_edge_right(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
840 {
841    Evas_Object *obj = data;
842    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_RIGHT, NULL);
843 }
844
845 static void
846 _scroll_edge_top(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
847 {
848    Evas_Object *obj = data;
849    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_TOP, NULL);
850 }
851
852 static void
853 _scroll_edge_bottom(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
854 {
855    Evas_Object *obj = data;
856    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_BOTTOM, NULL);
857 }
858
859 static Eina_Bool
860 _long_press(void *data)
861 {
862    Elm_List_Item *it = data;
863    Evas_Object *obj = it->base.widget;
864    Widget_Data *wd = elm_widget_data_get(obj);
865
866    if (!wd) goto end;
867
868    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
869    it->long_timer = NULL;
870    if (it->disabled) goto end;
871
872    wd->longpressed = EINA_TRUE;
873    evas_object_smart_callback_call(it->base.widget, SIG_LONGPRESSED, it);
874
875 end:
876    return ECORE_CALLBACK_CANCEL;
877 }
878
879 static void
880 _swipe(Elm_List_Item *it)
881 {
882    int i, sum = 0;
883    Widget_Data *wd = elm_widget_data_get(it->base.widget);
884
885    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
886    if (!wd) return;
887    wd->swipe = EINA_FALSE;
888    for (i = 0; i < wd->movements; i++)
889      {
890         sum += wd->history[i].x;
891         if (abs(wd->history[0].y - wd->history[i].y) > 10) return;
892      }
893
894    sum /= wd->movements;
895    if (abs(sum - wd->history[0].x) <= 10) return;
896    evas_object_smart_callback_call(it->base.widget, "swipe", it);
897 }
898
899 static void
900 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
901 {
902    Elm_List_Item *it = data;
903    Evas_Object *obj2 = it->base.widget;
904    Widget_Data *wd = elm_widget_data_get(obj2);
905    Evas_Event_Mouse_Down *ev = event_info;
906
907    if (!wd) return;
908    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
909    if (ev->button != 1) return;
910    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
911    else wd->on_hold = EINA_FALSE;
912    if (wd->on_hold) return;
913    wd->wasselected = it->selected;
914
915    evas_object_ref(obj2);
916    _elm_list_walk(wd);
917
918    _item_hilight(it);
919    wd->longpressed = EINA_FALSE;
920    if (it->long_timer) ecore_timer_del(it->long_timer);
921    it->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, it);
922    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
923    it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
924    /* Always call the callbacks last - the user may delete our context! */
925    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
926      {
927         evas_object_smart_callback_call(it->base.widget, SIG_CLICKED_DOUBLE, it);
928         evas_object_smart_callback_call(it->base.widget, SIG_ACTIVATED, it);
929      }
930    wd->swipe = EINA_FALSE;
931    wd->movements = 0;
932
933    _elm_list_unwalk(wd);
934    evas_object_unref(obj2);
935 }
936
937 static void
938 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
939 {
940    Elm_List_Item *it = data;
941    Evas_Object *obj2 = it->base.widget;
942    Widget_Data *wd = elm_widget_data_get(obj2);
943    Evas_Event_Mouse_Up *ev = event_info;
944
945    if (!wd) return;
946    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
947    if (ev->button != 1) return;
948    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
949    else wd->on_hold = EINA_FALSE;
950    wd->longpressed = EINA_FALSE;
951    if (it->long_timer)
952      {
953         ecore_timer_del(it->long_timer);
954         it->long_timer = NULL;
955      }
956    if (it->swipe_timer)
957      {
958         ecore_timer_del(it->swipe_timer);
959         it->swipe_timer = NULL;
960      }
961    if (wd->on_hold)
962      {
963         if (wd->swipe) _swipe(data);
964         wd->on_hold = EINA_FALSE;
965         return;
966      }
967    if (wd->longpressed)
968      {
969         if (!wd->wasselected) _item_unselect(it);
970         wd->wasselected = 0;
971         return;
972      }
973
974    if (it->disabled)
975      return;
976    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
977
978    evas_object_ref(obj2);
979    _elm_list_walk(wd);
980
981    if (wd->multi)
982      {
983         if (!it->selected)
984           {
985              _item_hilight(it);
986              _item_select(it);
987           }
988         else _item_unselect(it);
989      }
990    else
991      {
992         if (!it->selected)
993           {
994              while (wd->selected)
995                _item_unselect(wd->selected->data);
996              _item_hilight(it);
997              _item_select(it);
998           }
999         else
1000           {
1001              const Eina_List *l, *l_next;
1002              Elm_List_Item *it2;
1003
1004              EINA_LIST_FOREACH_SAFE(wd->selected, l, l_next, it2)
1005                 if (it2 != it) _item_unselect(it2);
1006              _item_hilight(it);
1007              _item_select(it);
1008           }
1009      }
1010
1011    _elm_list_unwalk(wd);
1012    evas_object_unref(obj2);
1013 }
1014
1015 static Elm_List_Item *
1016 _item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1017 {
1018    Widget_Data *wd = elm_widget_data_get(obj);
1019    Elm_List_Item *it;
1020
1021    if (!wd) return NULL;
1022    it = elm_widget_item_new(obj, Elm_List_Item);
1023    it->wd = wd;
1024    it->label = eina_stringshare_add(label);
1025    it->icon = icon;
1026    it->end = end;
1027    it->func = func;
1028    it->base.data = data;
1029    it->base.view = edje_object_add(evas_object_evas_get(obj));
1030    edje_object_mirrored_set(it->base.view, elm_widget_mirrored_get(obj));
1031    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_DOWN,
1032                                   _mouse_down, it);
1033    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_UP,
1034                                   _mouse_up, it);
1035    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOUSE_MOVE,
1036                                   _mouse_move, it);
1037    evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1038    evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL);
1039    if (it->icon)
1040      {
1041         elm_widget_sub_object_add(obj, it->icon);
1042         evas_object_event_callback_add(it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1043                                        _changed_size_hints, obj);
1044      }
1045    if (it->end)
1046      {
1047         elm_widget_sub_object_add(obj, it->end);
1048         evas_object_event_callback_add(it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1049                                        _changed_size_hints, obj);
1050      }
1051    return it;
1052 }
1053
1054 static void
1055 _elm_list_mode_set_internal(Widget_Data *wd)
1056 {
1057    if (!wd->scr)
1058      return;
1059
1060    if (wd->mode == ELM_LIST_LIMIT)
1061      {
1062         if (!wd->h_mode)
1063           {
1064              wd->scr_minw = EINA_TRUE;
1065              wd->scr_minh = EINA_FALSE;
1066           }
1067         else
1068           {
1069              wd->scr_minw = EINA_FALSE;
1070              wd->scr_minh = EINA_TRUE;
1071           }
1072      }
1073    else if (wd->mode == ELM_LIST_EXPAND)
1074      {
1075         wd->scr_minw = EINA_TRUE;
1076         wd->scr_minh = EINA_TRUE;
1077      }
1078    else
1079      {
1080         wd->scr_minw = EINA_FALSE;
1081         wd->scr_minh = EINA_FALSE;
1082      }
1083
1084    _sizing_eval(wd->self);
1085 }
1086
1087 static void
1088 _fix_items(Evas_Object *obj)
1089 {
1090    Widget_Data *wd = elm_widget_data_get(obj);
1091    if (!wd) return;
1092    const Eina_List *l;
1093    Elm_List_Item *it;
1094    Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 };
1095    Evas_Coord mw, mh;
1096    int i, redo = 0;
1097    const char *style = elm_widget_style_get(obj);
1098    const char *it_plain = wd->h_mode ? "h_item" : "item";
1099    const char *it_odd = wd->h_mode ? "h_item_odd" : "item_odd";
1100    const char *it_compress = wd->h_mode ? "h_item_compress" : "item_compress";
1101    const char *it_compress_odd = wd->h_mode ? "h_item_compress_odd" : "item_compress_odd";
1102
1103    if (wd->walking)
1104      {
1105         wd->fix_pending = EINA_TRUE;
1106         return;
1107      }
1108
1109    evas_object_ref(obj);
1110    _elm_list_walk(wd); // watch out "return" before unwalk!
1111
1112    EINA_LIST_FOREACH(wd->items, l, it)
1113      {
1114         if (it->deleted) continue;
1115         if (it->icon)
1116           {
1117              evas_object_size_hint_min_get(it->icon, &mw, &mh);
1118              if (mw > minw[0]) minw[0] = mw;
1119              if (mh > minh[0]) minh[0] = mh;
1120           }
1121         if (it->end)
1122           {
1123              evas_object_size_hint_min_get(it->end, &mw, &mh);
1124              if (mw > minw[1]) minw[1] = mw;
1125              if (mh > minh[1]) minh[1] = mh;
1126           }
1127      }
1128
1129    if ((minw[0] != wd->minw[0]) || (minw[1] != wd->minw[1]) ||
1130        (minw[0] != wd->minh[0]) || (minh[1] != wd->minh[1]))
1131      {
1132         wd->minw[0] = minw[0];
1133         wd->minw[1] = minw[1];
1134         wd->minh[0] = minh[0];
1135         wd->minh[1] = minh[1];
1136         redo = 1;
1137      }
1138    i = 0;
1139    EINA_LIST_FOREACH(wd->items, l, it)
1140      {
1141         if (it->deleted)
1142           continue;
1143
1144         it->even = i & 0x1;
1145         if ((it->even != it->is_even) || (!it->fixed) || (redo))
1146           {
1147              const char *stacking;
1148
1149              /* FIXME: separators' themes seem to be b0rked */
1150              if (it->is_separator)
1151                _elm_theme_object_set(obj, it->base.view, "separator",
1152                                      wd->h_mode ? "horizontal" : "vertical",
1153                                      style);
1154              else if (wd->mode == ELM_LIST_COMPRESS)
1155                {
1156                   if (it->even)
1157                     _elm_theme_object_set(obj, it->base.view, "list",
1158                                           it_compress, style);
1159                   else
1160                     _elm_theme_object_set(obj, it->base.view, "list",
1161                                           it_compress_odd, style);
1162                }
1163              else
1164                {
1165                   if (it->even)
1166                     _elm_theme_object_set(obj, it->base.view, "list", it_plain,
1167                                           style);
1168                   else
1169                     _elm_theme_object_set(obj, it->base.view, "list", it_odd,
1170                                           style);
1171                }
1172              stacking = edje_object_data_get(it->base.view, "stacking");
1173              if (stacking)
1174                {
1175                   if (!strcmp(stacking, "below"))
1176                     evas_object_lower(it->base.view);
1177                   else if (!strcmp(stacking, "above"))
1178                     evas_object_raise(it->base.view);
1179                }
1180              edje_object_part_text_set(it->base.view, "elm.text", it->label);
1181
1182              if ((!it->icon) && (minh[0] > 0))
1183                {
1184                   it->icon = evas_object_rectangle_add(evas_object_evas_get(it->base.view));
1185                   evas_object_color_set(it->icon, 0, 0, 0, 0);
1186                   it->dummy_icon = EINA_TRUE;
1187                }
1188              if ((!it->end) && (minh[1] > 0))
1189                {
1190                   it->end = evas_object_rectangle_add(evas_object_evas_get(it->base.view));
1191                   evas_object_color_set(it->end, 0, 0, 0, 0);
1192                   it->dummy_end = EINA_TRUE;
1193                }
1194              if (it->icon)
1195                {
1196                   evas_object_size_hint_min_set(it->icon, minw[0], minh[0]);
1197                   evas_object_size_hint_max_set(it->icon, 99999, 99999);
1198                   edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
1199                }
1200              if (it->end)
1201                {
1202                   evas_object_size_hint_min_set(it->end, minw[1], minh[1]);
1203                   evas_object_size_hint_max_set(it->end, 99999, 99999);
1204                   edje_object_part_swallow(it->base.view, "elm.swallow.end", it->end);
1205                }
1206              if (!it->fixed)
1207                {
1208                   // this may call up user and it may modify the list item
1209                   // but we're safe as we're flagged as walking.
1210                   // just don't process further
1211                   edje_object_message_signal_process(it->base.view);
1212                   if (it->deleted)
1213                     continue;
1214                   mw = mh = -1;
1215                   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1216                   edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
1217                   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1218                   evas_object_size_hint_min_set(it->base.view, mw, mh);
1219                   evas_object_show(it->base.view);
1220                }
1221              if ((it->selected) || (it->hilighted))
1222                {
1223                   const char *selectraise;
1224
1225                   // this may call up user and it may modify the list item
1226                   // but we're safe as we're flagged as walking.
1227                   // just don't process further
1228                   edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
1229                   if (it->deleted)
1230                     continue;
1231
1232                   selectraise = edje_object_data_get(it->base.view, "selectraise");
1233                   if ((selectraise) && (!strcmp(selectraise, "on")))
1234                     evas_object_raise(it->base.view);
1235                }
1236              if (it->disabled)
1237                edje_object_signal_emit(it->base.view, "elm,state,disabled",
1238                                        "elm");
1239
1240              it->fixed = EINA_TRUE;
1241              it->is_even = it->even;
1242           }
1243         i++;
1244      }
1245
1246    mw = 0; mh = 0;
1247    evas_object_size_hint_min_get(wd->box, &mw, &mh);
1248
1249    _elm_list_mode_set_internal(wd);
1250
1251    _elm_list_unwalk(wd);
1252    evas_object_unref(obj);
1253 }
1254
1255 static void
1256 _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1257 {
1258    Widget_Data *wd = elm_widget_data_get(obj);
1259    if (!wd) return;
1260    if (wd->scr)
1261      elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
1262 }
1263
1264 static void
1265 _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1266 {
1267    Widget_Data *wd = elm_widget_data_get(obj);
1268    if (!wd) return;
1269    if (wd->scr)
1270      elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1271 }
1272
1273 static void
1274 _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1275 {
1276    Widget_Data *wd = elm_widget_data_get(obj);
1277    if (!wd) return;
1278    if (wd->scr)
1279      elm_smart_scroller_freeze_set(wd->scr, EINA_TRUE);
1280 }
1281
1282 static void
1283 _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1284 {
1285    Widget_Data *wd = elm_widget_data_get(obj);
1286    if (!wd) return;
1287    if (wd->scr)
1288      elm_smart_scroller_freeze_set(wd->scr, EINA_FALSE);
1289 }
1290
1291 static void
1292 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1293 {
1294    _sizing_eval(data);
1295 }
1296
1297 EAPI Evas_Object *
1298 elm_list_add(Evas_Object *parent)
1299 {
1300    Evas_Object *obj;
1301    Evas *e;
1302    Widget_Data *wd;
1303    Evas_Coord minw, minh;
1304
1305    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1306
1307    ELM_SET_WIDTYPE(widtype, "list");
1308    elm_widget_type_set(obj, "list");
1309    elm_widget_sub_object_add(parent, obj);
1310    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1311    elm_widget_data_set(obj, wd);
1312    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1313    elm_widget_del_hook_set(obj, _del_hook);
1314    elm_widget_theme_hook_set(obj, _theme_hook);
1315    elm_widget_disable_hook_set(obj, _disable_hook);
1316    elm_widget_can_focus_set(obj, EINA_TRUE);
1317    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1318    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
1319    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
1320    elm_widget_event_hook_set(obj, _event_hook);
1321
1322    wd->self = obj;
1323    wd->scr = elm_smart_scroller_add(e);
1324    elm_smart_scroller_widget_set(wd->scr, obj);
1325    elm_widget_resize_object_set(obj, wd->scr);
1326    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1327                                   _changed_size_hints, obj);
1328    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
1329    evas_object_size_hint_min_set(obj, minw, minh);
1330    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1331
1332    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
1333                                        _elm_config->thumbscroll_bounce_enable);
1334
1335    wd->box = elm_box_add(parent);
1336    elm_box_homogeneous_set(wd->box, 1);
1337    evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
1338    evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
1339    elm_widget_on_show_region_hook_set(wd->box, _show_region_hook, obj);
1340    elm_widget_sub_object_add(obj, wd->box);
1341    elm_smart_scroller_child_set(wd->scr, wd->box);
1342    evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1343                                   _changed_size_hints, obj);
1344
1345    evas_object_show(wd->box);
1346
1347    _theme_hook(obj);
1348
1349    wd->mode = ELM_LIST_SCROLL;
1350
1351    evas_object_smart_callback_add(wd->scr, "edge,left", _scroll_edge_left, obj);
1352    evas_object_smart_callback_add(wd->scr, "edge,right", _scroll_edge_right, obj);
1353    evas_object_smart_callback_add(wd->scr, "edge,top", _scroll_edge_top, obj);
1354    evas_object_smart_callback_add(wd->scr, "edge,bottom", _scroll_edge_bottom, obj);
1355
1356    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1357    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1358    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1359    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1360    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1361
1362    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1363
1364    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1365    _sizing_eval(obj);
1366    return obj;
1367 }
1368
1369 EAPI Elm_List_Item *
1370 elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1371 {
1372    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1373    Widget_Data *wd = elm_widget_data_get(obj);
1374    Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1375
1376    wd->items = eina_list_append(wd->items, it);
1377    it->node = eina_list_last(wd->items);
1378    elm_box_pack_end(wd->box, it->base.view);
1379    return it;
1380 }
1381
1382 EAPI Elm_List_Item *
1383 elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1384 {
1385    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1386    Widget_Data *wd = elm_widget_data_get(obj);
1387    Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1388
1389    wd->items = eina_list_prepend(wd->items, it);
1390    it->node = wd->items;
1391    elm_box_pack_start(wd->box, it->base.view);
1392    return it;
1393 }
1394
1395 EAPI Elm_List_Item *
1396 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)
1397 {
1398    Widget_Data *wd;
1399    Elm_List_Item *it;
1400
1401    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
1402    if (!before->node) return NULL;
1403    ELM_LIST_ITEM_CHECK_DELETED_RETURN(before, NULL);
1404
1405    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1406    wd = elm_widget_data_get(obj);
1407    if (!wd) return NULL;
1408    it = _item_new(obj, label, icon, end, func, data);
1409    wd->items = eina_list_prepend_relative_list(wd->items, it, before->node);
1410    it->node = before->node->prev;
1411    elm_box_pack_before(wd->box, it->base.view, before->base.view);
1412    return it;
1413 }
1414
1415 EAPI Elm_List_Item *
1416 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)
1417 {
1418    Widget_Data *wd;
1419    Elm_List_Item *it;
1420
1421    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
1422    if (!after->node) return NULL;
1423    ELM_LIST_ITEM_CHECK_DELETED_RETURN(after, NULL);
1424
1425    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1426    wd = elm_widget_data_get(obj);
1427    if (!wd) return NULL;
1428    it = _item_new(obj, label, icon, end, func, data);
1429    wd->items = eina_list_append_relative_list(wd->items, it, after->node);
1430    it->node = after->node->next;
1431    elm_box_pack_after(wd->box, it->base.view, after->base.view);
1432    return it;
1433 }
1434
1435 EAPI Elm_List_Item *
1436 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)
1437 {
1438    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1439    Widget_Data *wd = elm_widget_data_get(obj);
1440    Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1441    Eina_List *l;
1442
1443    wd->items = eina_list_sorted_insert(wd->items, cmp_func, it);
1444    l = eina_list_data_find_list(wd->items, it);
1445    l = eina_list_next(l);
1446    if (!l)
1447      {
1448         it->node = eina_list_last(wd->items);
1449         elm_box_pack_end(wd->box, it->base.view);
1450      }
1451    else
1452      {
1453         Elm_List_Item *before = eina_list_data_get(l);
1454         it->node = before->node->prev;
1455         elm_box_pack_before(wd->box, it->base.view, before->base.view);
1456      }
1457    return it;
1458 }
1459
1460 EAPI void
1461 elm_list_clear(Evas_Object *obj)
1462 {
1463    ELM_CHECK_WIDTYPE(obj, widtype);
1464    Widget_Data *wd = elm_widget_data_get(obj);
1465    Elm_List_Item *it;
1466
1467    if (!wd) return;
1468    if (!wd->items) return;
1469
1470    eina_list_free(wd->selected);
1471    wd->selected = NULL;
1472
1473    if (wd->walking > 0)
1474      {
1475         Eina_List *n;
1476
1477         EINA_LIST_FOREACH(wd->items, n, it)
1478           {
1479              if (it->deleted) continue;
1480              it->deleted = EINA_TRUE;
1481              wd->to_delete = eina_list_append(wd->to_delete, it);
1482           }
1483         return;
1484      }
1485
1486    evas_object_ref(obj);
1487    _elm_list_walk(wd);
1488
1489    EINA_LIST_FREE(wd->items, it)
1490      {
1491         elm_widget_item_pre_notify_del(it);
1492         _elm_list_item_free(it);
1493      }
1494
1495    _elm_list_unwalk(wd);
1496
1497    _fix_items(obj);
1498    _sizing_eval(obj);
1499    evas_object_unref(obj);
1500 }
1501
1502 EAPI void
1503 elm_list_go(Evas_Object *obj)
1504 {
1505    ELM_CHECK_WIDTYPE(obj, widtype);
1506    Widget_Data *wd = elm_widget_data_get(obj);
1507    if (!wd) return;
1508    _fix_items(obj);
1509 }
1510
1511 EAPI void
1512 elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi)
1513 {
1514    ELM_CHECK_WIDTYPE(obj, widtype);
1515    Widget_Data *wd = elm_widget_data_get(obj);
1516    if (!wd) return;
1517    wd->multi = multi;
1518 }
1519
1520 EAPI Eina_Bool
1521 elm_list_multi_select_get(const Evas_Object *obj)
1522 {
1523    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1524    Widget_Data *wd = elm_widget_data_get(obj);
1525    if (!wd) return EINA_FALSE;
1526    return wd->multi;
1527 }
1528
1529 EAPI void
1530 elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode)
1531 {
1532    ELM_CHECK_WIDTYPE(obj, widtype);
1533
1534    Widget_Data *wd;
1535
1536    wd = elm_widget_data_get(obj);
1537    if (!wd)
1538      return;
1539    if (wd->mode == mode)
1540      return;
1541    wd->mode = mode;
1542
1543    _elm_list_mode_set_internal(wd);
1544 }
1545
1546 EAPI Elm_List_Mode
1547 elm_list_mode_get(const Evas_Object *obj)
1548 {
1549    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
1550    Widget_Data *wd = elm_widget_data_get(obj);
1551    if (!wd) return ELM_LIST_LAST;
1552    return wd->mode;
1553 }
1554
1555 EAPI void
1556 elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
1557 {
1558    ELM_CHECK_WIDTYPE(obj, widtype);
1559
1560    Widget_Data *wd;
1561    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1562
1563    wd = elm_widget_data_get(obj);
1564    if (!wd)
1565      return;
1566
1567    if (wd->h_mode == horizontal)
1568      return;
1569
1570    wd->h_mode = horizontal;
1571    elm_box_horizontal_set(wd->box, horizontal);
1572
1573    if (horizontal)
1574      {
1575         evas_object_size_hint_weight_set(wd->box, 0.0, EVAS_HINT_EXPAND);
1576         evas_object_size_hint_align_set(wd->box, 0.0, EVAS_HINT_FILL);
1577         elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1578      }
1579    else
1580      {
1581         evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
1582         evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
1583         elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, bounce);
1584      }
1585
1586    _elm_list_mode_set_internal(wd);
1587 }
1588
1589 EAPI Eina_Bool
1590 elm_list_horizontal_get(const Evas_Object *obj)
1591 {
1592    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1593
1594    Widget_Data *wd;
1595
1596    wd = elm_widget_data_get(obj);
1597    if (!wd)
1598      return EINA_FALSE;
1599
1600    return wd->h_mode;
1601 }
1602
1603 EAPI void
1604 elm_list_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select)
1605 {
1606    ELM_CHECK_WIDTYPE(obj, widtype);
1607    Widget_Data *wd = elm_widget_data_get(obj);
1608    if (!wd) return;
1609    wd->always_select = always_select;
1610 }
1611
1612 EAPI Eina_Bool
1613 elm_list_always_select_mode_get(const Evas_Object *obj)
1614 {
1615    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1616    Widget_Data *wd = elm_widget_data_get(obj);
1617    if (!wd) return EINA_FALSE;
1618    return wd->always_select;
1619 }
1620
1621 EAPI const Eina_List *
1622 elm_list_items_get(const Evas_Object *obj)
1623 {
1624    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1625    Widget_Data *wd = elm_widget_data_get(obj);
1626    if (!wd) return NULL;
1627    return wd->items;
1628 }
1629
1630 EAPI Elm_List_Item *
1631 elm_list_selected_item_get(const Evas_Object *obj)
1632 {
1633    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1634    Widget_Data *wd = elm_widget_data_get(obj);
1635    if (!wd) return NULL;
1636    if (wd->selected) return wd->selected->data;
1637    return NULL;
1638 }
1639
1640 EAPI const Eina_List *
1641 elm_list_selected_items_get(const Evas_Object *obj)
1642 {
1643    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1644    Widget_Data *wd = elm_widget_data_get(obj);
1645    if (!wd) return NULL;
1646    return wd->selected;
1647 }
1648
1649 EAPI void
1650 elm_list_item_separator_set(Elm_List_Item *it, Eina_Bool setting)
1651 {
1652    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1653    it->is_separator = !!setting;
1654 }
1655
1656 EAPI Eina_Bool
1657 elm_list_item_separator_get(const Elm_List_Item *it)
1658 {
1659    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
1660    return it->is_separator;
1661 }
1662
1663
1664 EAPI void
1665 elm_list_item_selected_set(Elm_List_Item *it, Eina_Bool selected)
1666 {
1667    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1668    Evas_Object *obj = it->base.widget;
1669    Widget_Data *wd = elm_widget_data_get(obj);
1670    if (!wd) return;
1671
1672    selected = !!selected;
1673    if (it->selected == selected) return;
1674
1675    evas_object_ref(obj);
1676    _elm_list_walk(wd);
1677
1678    if (selected)
1679      {
1680         if (!wd->multi)
1681           {
1682              while (wd->selected)
1683                _item_unselect(wd->selected->data);
1684           }
1685         _item_hilight(it);
1686         _item_select(it);
1687      }
1688    else
1689      _item_unselect(it);
1690
1691    _elm_list_unwalk(wd);
1692    evas_object_unref(obj);
1693 }
1694
1695 EAPI Eina_Bool
1696 elm_list_item_selected_get(const Elm_List_Item *it)
1697 {
1698    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
1699    return it->selected;
1700 }
1701
1702 EAPI void
1703 elm_list_item_show(Elm_List_Item *it)
1704 {
1705    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1706    Widget_Data *wd = elm_widget_data_get(it->base.widget);
1707    Evas_Coord bx, by, bw, bh;
1708    Evas_Coord x, y, w, h;
1709
1710    evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
1711    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
1712    x -= bx;
1713    y -= by;
1714    if (wd->scr)
1715      elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
1716 }
1717
1718 EAPI void
1719 elm_list_item_bring_in(Elm_List_Item *it)
1720 {
1721    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1722    Widget_Data *wd = elm_widget_data_get(it->base.widget);
1723    Evas_Coord bx, by, bw, bh;
1724    Evas_Coord x, y, w, h;
1725
1726    evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
1727    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
1728    x -= bx;
1729    y -= by;
1730    if (wd->scr)
1731      elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
1732 }
1733
1734 EAPI void
1735 elm_list_item_del(Elm_List_Item *it)
1736 {
1737    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1738    Evas_Object *obj = it->base.widget;
1739    Widget_Data *wd = elm_widget_data_get(obj);
1740    if (!wd) return;
1741
1742    if (it->selected) _item_unselect(it);
1743
1744    if (wd->walking > 0)
1745      {
1746         if (it->deleted) return;
1747         it->deleted = EINA_TRUE;
1748         wd->to_delete = eina_list_append(wd->to_delete, it);
1749         return;
1750      }
1751
1752    wd->items = eina_list_remove_list(wd->items, it->node);
1753
1754    evas_object_ref(obj);
1755    _elm_list_walk(wd);
1756
1757    elm_widget_item_pre_notify_del(it);
1758    _elm_list_item_free(it);
1759
1760    _elm_list_unwalk(wd);
1761    evas_object_unref(obj);
1762 }
1763
1764 EAPI void
1765 elm_list_item_del_cb_set(Elm_List_Item *it, Evas_Smart_Cb func)
1766 {
1767    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1768    elm_widget_item_del_cb_set(it, func);
1769 }
1770
1771 EAPI void *
1772 elm_list_item_data_get(const Elm_List_Item *it)
1773 {
1774    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1775    return elm_widget_item_data_get(it);
1776 }
1777
1778 EAPI Evas_Object *
1779 elm_list_item_icon_get(const Elm_List_Item *it)
1780 {
1781    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1782    if (it->dummy_icon) return NULL;
1783    return it->icon;
1784 }
1785
1786 EAPI void
1787 elm_list_item_icon_set(Elm_List_Item *it, Evas_Object *icon)
1788 {
1789    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1790    if (it->icon == icon) return;
1791    if ((it->dummy_icon) && (!icon)) return;
1792    if (it->dummy_icon)
1793      {
1794         evas_object_del(it->icon);
1795         it->dummy_icon = EINA_FALSE;
1796      }
1797    if (!icon)
1798      {
1799         icon = evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
1800         evas_object_color_set(icon, 0, 0, 0, 0);
1801         it->dummy_icon = EINA_TRUE;
1802      }
1803    if (it->icon)
1804      {
1805         evas_object_del(it->icon);
1806         it->icon = NULL;
1807      }
1808    it->icon = icon;
1809    if (it->base.view)
1810      edje_object_part_swallow(it->base.view, "elm.swallow.icon", icon);
1811 }
1812
1813 EAPI Evas_Object *
1814 elm_list_item_end_get(const Elm_List_Item *it)
1815 {
1816    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1817    if (it->dummy_end) return NULL;
1818    return it->end;
1819 }
1820
1821 EAPI void
1822 elm_list_item_end_set(Elm_List_Item *it, Evas_Object *end)
1823 {
1824    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1825    if (it->end == end) return;
1826    if ((it->dummy_end) && (!end)) return;
1827    if (it->dummy_end)
1828      {
1829         evas_object_del(it->end);
1830         it->dummy_icon = EINA_FALSE;
1831      }
1832    if (!end)
1833      {
1834         end = evas_object_rectangle_add(evas_object_evas_get(it->base.widget));
1835         evas_object_color_set(end, 0, 0, 0, 0);
1836         it->dummy_end = EINA_TRUE;
1837      }
1838    if (it->end)
1839      {
1840         evas_object_del(it->end);
1841         it->end = NULL;
1842      }
1843    it->end = end;
1844    if (it->base.view)
1845      edje_object_part_swallow(it->base.view, "elm.swallow.end", end);
1846 }
1847
1848 EAPI Evas_Object *
1849 elm_list_item_base_get(const Elm_List_Item *it)
1850 {
1851    return elm_list_item_object_get(it);
1852 }
1853
1854 EAPI Evas_Object *
1855 elm_list_item_object_get(const Elm_List_Item *it)
1856 {
1857    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1858    return it->base.view;
1859 }
1860
1861 EAPI const char *
1862 elm_list_item_label_get(const Elm_List_Item *it)
1863 {
1864    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1865    return it->label;
1866 }
1867
1868 EAPI void
1869 elm_list_item_label_set(Elm_List_Item *it, const char *text)
1870 {
1871    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1872    if (!eina_stringshare_replace(&it->label, text)) return;
1873    if (it->base.view)
1874      edje_object_part_text_set(it->base.view, "elm.text", it->label);
1875 }
1876
1877 EAPI Elm_List_Item *
1878 elm_list_item_prev(const Elm_List_Item *it)
1879 {
1880    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1881    if (it->node->prev) return it->node->prev->data;
1882    else return NULL;
1883 }
1884
1885 EAPI Elm_List_Item *
1886 elm_list_item_next(const Elm_List_Item *it)
1887 {
1888    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1889    if (it->node->next) return it->node->next->data;
1890    else return NULL;
1891 }
1892
1893 EAPI void
1894 elm_list_item_tooltip_text_set(Elm_List_Item *item, const char *text)
1895 {
1896    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1897    elm_widget_item_tooltip_text_set(item, text);
1898 }
1899
1900 EAPI void
1901 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)
1902 {
1903    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1904    elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
1905 }
1906
1907 EAPI void
1908 elm_list_item_tooltip_unset(Elm_List_Item *item)
1909 {
1910    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1911    elm_widget_item_tooltip_unset(item);
1912 }
1913
1914 EAPI Eina_Bool
1915 elm_list_item_tooltip_size_restrict_disable(Elm_List_Item *item, Eina_Bool disable)
1916 {
1917    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
1918    return elm_widget_item_tooltip_size_restrict_disable(item, disable);
1919 }
1920
1921 EAPI Eina_Bool
1922 elm_list_item_tooltip_size_restrict_disabled_get(const Elm_List_Item *item)
1923 {
1924    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
1925    return elm_widget_item_tooltip_size_restrict_disabled_get(item);
1926 }
1927
1928 EAPI void
1929 elm_list_item_tooltip_style_set(Elm_List_Item *item, const char *style)
1930 {
1931    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1932    elm_widget_item_tooltip_style_set(item, style);
1933 }
1934
1935 EAPI const char *
1936 elm_list_item_tooltip_style_get(const Elm_List_Item *item)
1937 {
1938    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
1939    return elm_widget_item_tooltip_style_get(item);
1940 }
1941
1942 EAPI void
1943 elm_list_item_cursor_set(Elm_List_Item *item, const char *cursor)
1944 {
1945    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1946    elm_widget_item_cursor_set(item, cursor);
1947 }
1948
1949 EAPI const char *
1950 elm_list_item_cursor_get(const Elm_List_Item *item)
1951 {
1952    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
1953    return elm_widget_item_cursor_get(item);
1954 }
1955
1956 EAPI void
1957 elm_list_item_cursor_unset(Elm_List_Item *item)
1958 {
1959    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1960    elm_widget_item_cursor_unset(item);
1961 }
1962
1963 EAPI void
1964 elm_list_item_cursor_style_set(Elm_List_Item *item, const char *style)
1965 {
1966    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1967    elm_widget_item_cursor_style_set(item, style);
1968 }
1969
1970 EAPI const char *
1971 elm_list_item_cursor_style_get(const Elm_List_Item *item)
1972 {
1973    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, NULL);
1974    return elm_widget_item_cursor_style_get(item);
1975 }
1976
1977 EAPI void
1978 elm_list_item_cursor_engine_only_set(Elm_List_Item *item, Eina_Bool engine_only)
1979 {
1980    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item);
1981    elm_widget_item_cursor_engine_only_set(item, engine_only);
1982 }
1983
1984 EAPI Eina_Bool
1985 elm_list_item_cursor_engine_only_get(const Elm_List_Item *item)
1986 {
1987    ELM_LIST_ITEM_CHECK_DELETED_RETURN(item, EINA_FALSE);
1988    return elm_widget_item_cursor_engine_only_get(item);
1989 }
1990
1991 EAPI void
1992 elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1993 {
1994    ELM_CHECK_WIDTYPE(obj, widtype);
1995    Widget_Data *wd = elm_widget_data_get(obj);
1996    if (!wd) return;
1997    if (wd->scr)
1998      elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
1999 }
2000
2001 EAPI void
2002 elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
2003 {
2004    ELM_CHECK_WIDTYPE(obj, widtype);
2005    Widget_Data *wd = elm_widget_data_get(obj);
2006    if (!wd) return;
2007    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
2008 }
2009
2010 EAPI void
2011 elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
2012 {
2013    ELM_CHECK_WIDTYPE(obj, widtype);
2014    Widget_Data *wd = elm_widget_data_get(obj);
2015    if (!wd) return;
2016    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
2017        (policy_v >= ELM_SCROLLER_POLICY_LAST))
2018      if (wd->scr)
2019        elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
2020 }
2021
2022 EAPI void
2023 elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
2024 {
2025    ELM_CHECK_WIDTYPE(obj, widtype);
2026    Widget_Data *wd = elm_widget_data_get(obj);
2027    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
2028    if ((!wd) || (!wd->scr)) return;
2029    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
2030    if (policy_h) *policy_h = (Elm_Scroller_Policy) s_policy_h;
2031    if (policy_v) *policy_v = (Elm_Scroller_Policy) s_policy_v;
2032 }
2033
2034 EAPI void
2035 elm_list_item_disabled_set(Elm_List_Item *it, Eina_Bool disabled)
2036 {
2037    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
2038
2039    if (it->disabled == disabled)
2040      return;
2041
2042    it->disabled = !!disabled;
2043
2044    if (it->disabled)
2045      edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
2046    else
2047      edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
2048 }
2049
2050 EAPI Eina_Bool
2051 elm_list_item_disabled_get(const Elm_List_Item *it)
2052 {
2053    ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
2054
2055    return it->disabled;
2056 }