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