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