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