[focus] When an object has focus_chain manager, it should return its own next object...
[framework/uifw/elementary.git] / src / lib / elm_list.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_list.h"
4
5 EAPI const char ELM_LIST_SMART_NAME[] = "elm_list";
6
7 static const char SIG_ACTIVATED[] = "activated";
8 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
9 static const char SIG_SELECTED[] = "selected";
10 static const char SIG_UNSELECTED[] = "unselected";
11 static const char SIG_LONGPRESSED[] = "longpressed";
12 static const char SIG_EDGE_TOP[] = "edge,top";
13 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
14 static const char SIG_EDGE_LEFT[] = "edge,left";
15 static const char SIG_EDGE_RIGHT[] = "edge,right";
16 static const char SIG_LANG_CHANGED[] = "language,changed";
17 static const char SIG_SWIPE[] = "swipe";
18 static const char SIG_HIGHLIGHTED[] = "highlighted";
19 static const char SIG_UNHIGHLIGHTED[] = "unhighlighted";
20 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
21    {SIG_ACTIVATED, ""},
22    {SIG_CLICKED_DOUBLE, ""},
23    {SIG_SELECTED, ""},
24    {SIG_UNSELECTED, ""},
25    {SIG_LONGPRESSED, ""},
26    {SIG_EDGE_TOP, ""},
27    {SIG_EDGE_BOTTOM, ""},
28    {SIG_EDGE_LEFT, ""},
29    {SIG_EDGE_RIGHT, ""},
30    {SIG_LANG_CHANGED, ""},
31    {SIG_SWIPE, ""},
32    {SIG_HIGHLIGHTED, ""},
33    {SIG_UNHIGHLIGHTED, ""},
34    {NULL, NULL}
35 };
36
37 static const Evas_Smart_Interface *_smart_interfaces[] =
38 {
39    (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
40 };
41
42 static void _size_hints_changed_cb(void *, Evas *, Evas_Object *, void *);
43 static void _mouse_up_cb(void *, Evas *, Evas_Object *, void *);
44 static void _mouse_down_cb(void *, Evas *, Evas_Object *, void *);
45 static void _mouse_move_cb(void *, Evas *, Evas_Object *, void *);
46 static void _items_fix(Evas_Object *);
47
48 EVAS_SMART_SUBCLASS_IFACE_NEW
49   (ELM_LIST_SMART_NAME, _elm_list, Elm_List_Smart_Class,
50    Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks,
51    _smart_interfaces);
52
53 static inline void
54 _elm_list_item_free(Elm_List_Item *it)
55 {
56    evas_object_event_callback_del_full
57      (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, it);
58    evas_object_event_callback_del_full
59      (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, it);
60    evas_object_event_callback_del_full
61      (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, it);
62
63    if (it->icon)
64      evas_object_event_callback_del_full
65        (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
66        _size_hints_changed_cb, WIDGET(it));
67
68    if (it->end)
69      evas_object_event_callback_del_full
70        (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
71        _size_hints_changed_cb, WIDGET(it));
72
73    eina_stringshare_del(it->label);
74
75    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
76    it->swipe_timer = NULL;
77    if (it->long_timer) ecore_timer_del(it->long_timer);
78    it->long_timer = NULL;
79    if (it->icon) evas_object_del(it->icon);
80    if (it->end) evas_object_del(it->end);
81 }
82
83 static Eina_Bool
84 _item_multi_select_up(Elm_List_Smart_Data *sd)
85 {
86    Elm_Object_Item *prev;
87
88    if (!sd->selected) return EINA_FALSE;
89    if (!sd->multi) return EINA_FALSE;
90
91    prev = elm_list_item_prev(sd->last_selected_item);
92    if (!prev) return EINA_TRUE;
93
94    if (elm_list_item_selected_get(prev))
95      {
96         elm_list_item_selected_set(sd->last_selected_item, EINA_FALSE);
97         sd->last_selected_item = prev;
98         elm_list_item_show(sd->last_selected_item);
99      }
100    else
101      {
102         elm_list_item_selected_set(prev, EINA_TRUE);
103         elm_list_item_show(prev);
104      }
105    return EINA_TRUE;
106 }
107
108 static Eina_Bool
109 _item_multi_select_down(Elm_List_Smart_Data *sd)
110 {
111    Elm_Object_Item *next;
112
113    if (!sd->selected) return EINA_FALSE;
114    if (!sd->multi) return EINA_FALSE;
115
116    next = elm_list_item_next(sd->last_selected_item);
117    if (!next) return EINA_TRUE;
118
119    if (elm_list_item_selected_get(next))
120      {
121         elm_list_item_selected_set(sd->last_selected_item, EINA_FALSE);
122         sd->last_selected_item = next;
123         elm_list_item_show(sd->last_selected_item);
124      }
125    else
126      {
127         elm_list_item_selected_set(next, EINA_TRUE);
128         elm_list_item_show(next);
129      }
130    return EINA_TRUE;
131 }
132
133 static Eina_Bool
134 _all_items_unselect(Elm_List_Smart_Data *sd)
135 {
136    if (!sd->selected) return EINA_FALSE;
137
138    while (sd->selected)
139      elm_list_item_selected_set
140        ((Elm_Object_Item *)sd->selected->data, EINA_FALSE);
141
142    return EINA_TRUE;
143 }
144
145 static Eina_Bool
146 _item_single_select_up(Elm_List_Smart_Data *sd)
147 {
148    Elm_Object_Item *prev;
149
150    if (!sd->selected) prev = eina_list_data_get(eina_list_last(sd->items));
151    else
152      {
153         prev = elm_list_item_prev(sd->last_selected_item);
154         while (prev)
155           {
156              if (!elm_object_item_disabled_get(prev)) break;
157              prev = elm_list_item_prev(prev);
158           }
159      }
160    if (!prev) return EINA_FALSE;
161
162    _all_items_unselect(sd);
163
164    elm_list_item_selected_set(prev, EINA_TRUE);
165    elm_list_item_show(prev);
166
167    return EINA_TRUE;
168 }
169
170 static Eina_Bool
171 _item_single_select_down(Elm_List_Smart_Data *sd)
172 {
173    Elm_Object_Item *next;
174
175    if (!sd->selected) next = eina_list_data_get(sd->items);
176    else
177      {
178         next = elm_list_item_next(sd->last_selected_item);
179         while (next)
180           {
181              if (!elm_object_item_disabled_get(next)) break;
182              next = elm_list_item_next(next);
183           }
184      }
185    if (!next) return EINA_FALSE;
186
187    _all_items_unselect(sd);
188
189    elm_list_item_selected_set(next, EINA_TRUE);
190    elm_list_item_show(next);
191
192    return EINA_TRUE;
193 }
194
195 static Eina_Bool
196 _elm_list_smart_event(Evas_Object *obj,
197                       Evas_Object *src __UNUSED__,
198                       Evas_Callback_Type type,
199                       void *event_info)
200 {
201    Evas_Coord x = 0;
202    Evas_Coord y = 0;
203    Evas_Coord v_w = 0;
204    Evas_Coord v_h = 0;
205    Evas_Coord step_x = 0;
206    Evas_Coord step_y = 0;
207    Evas_Coord page_x = 0;
208    Evas_Coord page_y = 0;
209    Elm_List_Item *it = NULL;
210    Evas_Event_Key_Down *ev = event_info;
211
212    ELM_LIST_DATA_GET(obj, sd);
213
214    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
215    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
216    if (!sd->items) return EINA_FALSE;
217    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
218
219    sd->s_iface->content_pos_get(obj, &x, &y);
220    sd->s_iface->step_size_get(obj, &step_x, &step_y);
221    sd->s_iface->page_size_get(obj, &page_x, &page_y);
222    sd->s_iface->content_viewport_size_get(obj, &v_w, &v_h);
223
224    /* TODO: fix logic for horizontal mode */
225    if ((!strcmp(ev->keyname, "Left")) ||
226        ((!strcmp(ev->keyname, "KP_Left")) && !ev->string))
227      {
228         if ((sd->h_mode) &&
229             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
230               (_item_multi_select_up(sd)))
231              || (_item_single_select_up(sd))))
232           {
233              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
234              return EINA_TRUE;
235           }
236         else
237           x -= step_x;
238      }
239    else if ((!strcmp(ev->keyname, "Right")) ||
240             ((!strcmp(ev->keyname, "KP_Right")) && !ev->string))
241      {
242         if ((sd->h_mode) &&
243             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
244               (_item_multi_select_down(sd)))
245              || (_item_single_select_down(sd))))
246           {
247              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
248              return EINA_TRUE;
249           }
250         else
251           x += step_x;
252      }
253    else if ((!strcmp(ev->keyname, "Up")) ||
254             ((!strcmp(ev->keyname, "KP_Up")) && !ev->string))
255      {
256         if ((!sd->h_mode) &&
257             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
258               (_item_multi_select_up(sd)))
259              || (_item_single_select_up(sd))))
260           {
261              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
262              return EINA_TRUE;
263           }
264         else
265           y -= step_y;
266      }
267    else if ((!strcmp(ev->keyname, "Down")) ||
268             ((!strcmp(ev->keyname, "KP_Down")) && !ev->string))
269      {
270         if ((!sd->h_mode) &&
271             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
272               (_item_multi_select_down(sd)))
273              || (_item_single_select_down(sd))))
274           {
275              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
276              return EINA_TRUE;
277           }
278         else
279           y += step_y;
280      }
281    else if ((!strcmp(ev->keyname, "Home")) ||
282             ((!strcmp(ev->keyname, "KP_Home")) && !ev->string))
283      {
284         it = eina_list_data_get(sd->items);
285         elm_list_item_bring_in((Elm_Object_Item *)it);
286         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
287         return EINA_TRUE;
288      }
289    else if ((!strcmp(ev->keyname, "End")) ||
290             ((!strcmp(ev->keyname, "KP_End")) && !ev->string))
291      {
292         it = eina_list_data_get(eina_list_last(sd->items));
293         elm_list_item_bring_in((Elm_Object_Item *)it);
294         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
295         return EINA_TRUE;
296      }
297    else if ((!strcmp(ev->keyname, "Prior")) ||
298             ((!strcmp(ev->keyname, "KP_Prior")) && !ev->string))
299      {
300         if (sd->h_mode)
301           {
302              if (page_x < 0)
303                x -= -(page_x * v_w) / 100;
304              else
305                x -= page_x;
306           }
307         else
308           {
309              if (page_y < 0)
310                y -= -(page_y * v_h) / 100;
311              else
312                y -= page_y;
313           }
314      }
315    else if ((!strcmp(ev->keyname, "Next")) ||
316             ((!strcmp(ev->keyname, "KP_Next")) && !ev->string))
317      {
318         if (sd->h_mode)
319           {
320              if (page_x < 0)
321                x += -(page_x * v_w) / 100;
322              else
323                x += page_x;
324           }
325         else
326           {
327              if (page_y < 0)
328                y += -(page_y * v_h) / 100;
329              else
330                y += page_y;
331           }
332      }
333    else if (((!strcmp(ev->keyname, "Return")) ||
334              (!strcmp(ev->keyname, "KP_Enter")) ||
335              (!strcmp(ev->keyname, "space")))
336             && (!sd->multi) && (sd->selected))
337      {
338         it = (Elm_List_Item *)elm_list_selected_item_get(obj);
339         if (it) evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
340      }
341    else if (!strcmp(ev->keyname, "Escape"))
342      {
343         if (!_all_items_unselect(sd)) return EINA_FALSE;
344         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
345         return EINA_TRUE;
346      }
347    else return EINA_FALSE;
348
349    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
350    sd->s_iface->content_pos_set(obj, x, y, EINA_TRUE);
351
352    return EINA_TRUE;
353 }
354
355 static Eina_Bool
356 _elm_list_smart_translate(Evas_Object *obj)
357 {
358    evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
359
360    return EINA_TRUE;
361 }
362
363 static void
364 _elm_list_deletions_process(Elm_List_Smart_Data *sd)
365 {
366    Elm_List_Item *it;
367
368    sd->walking++; // avoid nested deletion and also _sub_del() items_fix
369
370    EINA_LIST_FREE (sd->to_delete, it)
371      {
372         sd->items = eina_list_remove_list(sd->items, it->node);
373
374         /* issuing free because of "locking" item del pre hook */
375         _elm_list_item_free(it);
376         elm_widget_item_free(it);
377      }
378
379    sd->walking--;
380 }
381
382 static void
383 _elm_list_smart_sizing_eval(Evas_Object *obj)
384 {
385    Evas_Coord vw = 0, vh = 0;
386    Evas_Coord minw, minh, maxw, maxh, w, h, vmw, vmh;
387    double xw, yw;
388
389    ELM_LIST_DATA_GET(obj, sd);
390
391    /* parent class' early call */
392    if (!sd->s_iface) return;
393
394    evas_object_size_hint_min_get(sd->box, &minw, &minh);
395    evas_object_size_hint_max_get(sd->box, &maxw, &maxh);
396    evas_object_size_hint_weight_get(sd->box, &xw, &yw);
397
398    sd->s_iface->content_viewport_size_get(obj, &vw, &vh);
399    if (xw > 0.0)
400      {
401         if ((minw > 0) && (vw < minw)) vw = minw;
402         else if ((maxw > 0) && (vw > maxw))
403           vw = maxw;
404      }
405    else if (minw > 0)
406      vw = minw;
407    if (yw > 0.0)
408      {
409         if ((minh > 0) && (vh < minh)) vh = minh;
410         else if ((maxh > 0) && (vh > maxh))
411           vh = maxh;
412      }
413    else if (minh > 0)
414      vh = minh;
415
416    evas_object_resize(sd->box, vw, vh);
417    w = -1;
418    h = -1;
419
420    edje_object_size_min_calc
421      (ELM_WIDGET_DATA(sd)->resize_obj, &vmw, &vmh);
422
423    if (sd->scr_minw) w = vmw + minw;
424    if (sd->scr_minh) h = vmh + minh;
425
426    evas_object_size_hint_max_get(obj, &maxw, &maxh);
427    if ((maxw > 0) && (w > maxw))
428      w = maxw;
429    if ((maxh > 0) && (h > maxh))
430      h = maxh;
431
432    evas_object_size_hint_min_set(obj, w, h);
433 }
434
435 static void
436 _elm_list_content_min_limit_cb(Evas_Object *obj,
437                                Eina_Bool w,
438                                Eina_Bool h)
439 {
440    ELM_LIST_DATA_GET(obj, sd);
441
442    sd->scr_minw = !!w;
443    sd->scr_minh = !!h;
444
445    elm_layout_sizing_eval(obj);
446 }
447
448 static void
449 _elm_list_mode_set_internal(Elm_List_Smart_Data *sd)
450 {
451    if (sd->mode == ELM_LIST_LIMIT)
452      {
453         if (!sd->h_mode)
454           {
455              sd->scr_minw = EINA_TRUE;
456              sd->scr_minh = EINA_FALSE;
457           }
458         else
459           {
460              sd->scr_minw = EINA_FALSE;
461              sd->scr_minh = EINA_TRUE;
462           }
463      }
464    else if (sd->mode == ELM_LIST_EXPAND)
465      {
466         sd->scr_minw = EINA_TRUE;
467         sd->scr_minh = EINA_TRUE;
468      }
469    else
470      {
471         sd->scr_minw = EINA_FALSE;
472         sd->scr_minh = EINA_FALSE;
473      }
474
475    elm_layout_sizing_eval(ELM_WIDGET_DATA(sd)->obj);
476 }
477
478 static inline void
479 _elm_list_walk(Elm_List_Smart_Data *sd)
480 {
481    if (sd->walking < 0)
482      {
483         ERR("ERROR: walking was negative. fixed!\n");
484         sd->walking = 0;
485      }
486    sd->walking++;
487 }
488
489 static inline void
490 _elm_list_unwalk(Elm_List_Smart_Data *sd)
491 {
492    sd->walking--;
493    if (sd->walking < 0)
494      {
495         ERR("ERROR: walking became negative. fixed!\n");
496         sd->walking = 0;
497      }
498
499    if (sd->walking)
500      return;
501
502    if (sd->to_delete)
503      _elm_list_deletions_process(sd);
504
505    if (sd->fix_pending)
506      {
507         sd->fix_pending = EINA_FALSE;
508         _items_fix(ELM_WIDGET_DATA(sd)->obj);
509         elm_layout_sizing_eval(ELM_WIDGET_DATA(sd)->obj);
510      }
511 }
512
513 static void
514 _items_fix(Evas_Object *obj)
515 {
516    Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 };
517    const Eina_List *l;
518    Elm_List_Item *it;
519    Evas_Coord mw, mh;
520    int i, redo = 0;
521
522    const char *style;
523    const char *it_odd;
524    const char *it_plain;
525    const char *it_compress;
526    const char *it_compress_odd;
527
528    ELM_LIST_DATA_GET(obj, sd);
529
530    style = elm_widget_style_get(obj);
531    it_plain = sd->h_mode ? "h_item" : "item";
532    it_odd = sd->h_mode ? "h_item_odd" : "item_odd";
533    it_compress = sd->h_mode ? "h_item_compress" : "item_compress";
534    it_compress_odd = sd->h_mode ? "h_item_compress_odd" : "item_compress_odd";
535
536    if (sd->walking)
537      {
538         sd->fix_pending = EINA_TRUE;
539         return;
540      }
541
542    evas_object_ref(obj);
543    _elm_list_walk(sd); // watch out "return" before unwalk!
544
545    EINA_LIST_FOREACH(sd->items, l, it)
546      {
547         if (it->deleted) continue;
548         if (it->icon)
549           {
550              evas_object_size_hint_min_get(it->icon, &mw, &mh);
551              if (mw > minw[0]) minw[0] = mw;
552              if (mh > minh[0]) minh[0] = mh;
553           }
554         if (it->end)
555           {
556              evas_object_size_hint_min_get(it->end, &mw, &mh);
557              if (mw > minw[1]) minw[1] = mw;
558              if (mh > minh[1]) minh[1] = mh;
559           }
560      }
561
562    if ((minw[0] != sd->minw[0]) || (minw[1] != sd->minw[1]) ||
563        (minh[0] != sd->minh[0]) || (minh[1] != sd->minh[1]))
564      {
565         sd->minw[0] = minw[0];
566         sd->minw[1] = minw[1];
567         sd->minh[0] = minh[0];
568         sd->minh[1] = minh[1];
569         redo = 1;
570      }
571
572    i = 0;
573    EINA_LIST_FOREACH(sd->items, l, it)
574      {
575         if (it->deleted)
576           continue;
577
578         it->even = i & 0x1;
579         if ((it->even != it->is_even) || (!it->fixed) || (redo))
580           {
581              const char *stacking;
582
583              /* FIXME: separators' themes seem to be b0rked */
584              if (it->is_separator)
585                elm_widget_theme_object_set
586                  (obj, VIEW(it), "separator", sd->h_mode ?
587                  "horizontal" : "vertical", style);
588              else if (sd->mode == ELM_LIST_COMPRESS)
589                {
590                   if (it->even)
591                     elm_widget_theme_object_set
592                       (obj, VIEW(it), "list", it_compress, style);
593                   else
594                     elm_widget_theme_object_set
595                       (obj, VIEW(it), "list", it_compress_odd, style);
596                }
597              else
598                {
599                   if (it->even)
600                     elm_widget_theme_object_set
601                       (obj, VIEW(it), "list", it_plain, style);
602                   else
603                     elm_widget_theme_object_set
604                       (obj, VIEW(it), "list", it_odd, style);
605                }
606              stacking = edje_object_data_get(VIEW(it), "stacking");
607              if (stacking)
608                {
609                   if (!strcmp(stacking, "below"))
610                     evas_object_lower(VIEW(it));
611                   else if (!strcmp(stacking, "above"))
612                     evas_object_raise(VIEW(it));
613                }
614              edje_object_part_text_escaped_set
615                (VIEW(it), "elm.text", it->label);
616
617              if ((!it->icon) && (minh[0] > 0))
618                {
619                   it->icon = evas_object_rectangle_add
620                       (evas_object_evas_get(VIEW(it)));
621                   evas_object_color_set(it->icon, 0, 0, 0, 0);
622                   it->dummy_icon = EINA_TRUE;
623                }
624              if ((!it->end) && (minh[1] > 0))
625                {
626                   it->end = evas_object_rectangle_add
627                       (evas_object_evas_get(VIEW(it)));
628                   evas_object_color_set(it->end, 0, 0, 0, 0);
629                   it->dummy_end = EINA_TRUE;
630                }
631              if (it->icon)
632                {
633                   evas_object_size_hint_min_set(it->icon, minw[0], minh[0]);
634                   evas_object_size_hint_max_set(it->icon, 99999, 99999);
635                   edje_object_part_swallow
636                     (VIEW(it), "elm.swallow.icon", it->icon);
637                }
638              if (it->end)
639                {
640                   evas_object_size_hint_min_set(it->end, minw[1], minh[1]);
641                   evas_object_size_hint_max_set(it->end, 99999, 99999);
642                   edje_object_part_swallow
643                     (VIEW(it), "elm.swallow.end", it->end);
644                }
645              if (!it->fixed)
646                {
647                   // this may call up user and it may modify the list item
648                   // but we're safe as we're flagged as walking.
649                   // just don't process further
650                   edje_object_message_signal_process(VIEW(it));
651                   if (it->deleted)
652                     continue;
653                   mw = mh = -1;
654                   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
655                   edje_object_size_min_restricted_calc
656                     (VIEW(it), &mw, &mh, mw, mh);
657                   elm_coords_finger_size_adjust(1, &mw, 1, &mh);
658                   evas_object_size_hint_min_set(VIEW(it), mw, mh);
659                   evas_object_show(VIEW(it));
660                }
661              if ((it->selected) || (it->highlighted))
662                {
663                   const char *select_raise;
664
665                   // this may call up user and it may modify the list item
666                   // but we're safe as we're flagged as walking.
667                   // just don't process further
668                   edje_object_signal_emit
669                     (VIEW(it), "elm,state,selected", "elm");
670                   if (it->deleted)
671                     continue;
672
673                   select_raise = edje_object_data_get(VIEW(it), "selectraise");
674                   if ((select_raise) && (!strcmp(select_raise, "on")))
675                     evas_object_raise(VIEW(it));
676                }
677              if (it->base.disabled)
678                edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
679
680              it->fixed = EINA_TRUE;
681              it->is_even = it->even;
682           }
683         i++;
684      }
685
686    _elm_list_mode_set_internal(sd);
687    _elm_list_unwalk(sd);
688
689    evas_object_unref(obj);
690 }
691
692 static void
693 _size_hints_changed_cb(void *data,
694                        Evas *e __UNUSED__,
695                        Evas_Object *obj __UNUSED__,
696                        void *event_info __UNUSED__)
697 {
698    ELM_LIST_DATA_GET(data, sd);
699    if (sd->delete_me) return;
700
701    _items_fix(data);
702    elm_layout_sizing_eval(data);
703 }
704
705 /* FIXME: take off later. maybe this show region coords belong in the
706  * interface (new api functions, set/get)? */
707 static void
708 _show_region_hook(void *data,
709                   Evas_Object *obj)
710 {
711    Evas_Coord x, y, w, h;
712
713    ELM_LIST_DATA_GET(data, sd);
714
715    elm_widget_show_region_get(obj, &x, &y, &w, &h);
716    sd->s_iface->content_region_set(obj, x, y, w, h);
717 }
718
719 static Eina_Bool
720 _elm_list_smart_disable(Evas_Object *obj)
721 {
722    ELM_LIST_DATA_GET(obj, sd);
723
724    if (!ELM_WIDGET_CLASS(_elm_list_parent_sc)->disable(obj))
725      return EINA_FALSE;
726
727    if (elm_widget_disabled_get(obj))
728      {
729         elm_widget_scroll_freeze_push(obj);
730         elm_widget_scroll_hold_push(obj);
731         /* FIXME: if we get to have a way to only un-highlight items
732          * in the future, keeping them selected... */
733         _all_items_unselect(sd);
734      }
735    else
736      {
737         elm_widget_scroll_freeze_pop(obj);
738         elm_widget_scroll_hold_pop(obj);
739      }
740
741    return EINA_TRUE;
742 }
743
744 static void
745 _mirrored_set(Evas_Object *obj,
746               Eina_Bool rtl)
747 {
748    Elm_List_Item *it;
749    Eina_List *n;
750
751    ELM_LIST_DATA_GET(obj, sd);
752
753    sd->s_iface->mirrored_set(obj, rtl);
754
755    EINA_LIST_FOREACH(sd->items, n, it)
756      edje_object_mirrored_set(VIEW(it), rtl);
757 }
758
759 static Eina_Bool
760 _elm_list_smart_theme(Evas_Object *obj)
761 {
762    Elm_List_Item *it;
763    Eina_List *n;
764
765    ELM_LIST_DATA_GET(obj, sd);
766
767    if (!ELM_WIDGET_CLASS(_elm_list_parent_sc)->theme(obj)) return EINA_FALSE;
768
769    _mirrored_set(obj, elm_widget_mirrored_get(obj));
770
771    EINA_LIST_FOREACH(sd->items, n, it)
772      {
773         edje_object_scale_set
774           (VIEW(it), elm_widget_scale_get(obj) * elm_config_scale_get());
775         it->fixed = 0;
776      }
777
778    _items_fix(obj);
779    elm_layout_sizing_eval(obj);
780
781    return EINA_TRUE;
782 }
783
784 static Eina_Bool
785 _elm_list_smart_on_focus(Evas_Object *obj)
786 {
787    ELM_LIST_DATA_GET(obj, sd);
788
789    if (!ELM_WIDGET_CLASS(_elm_list_parent_sc)->on_focus(obj))
790      return EINA_FALSE;
791
792    if (elm_widget_focus_get(obj) && sd->selected && !sd->last_selected_item)
793      sd->last_selected_item = eina_list_data_get(sd->selected);
794
795    return EINA_TRUE;
796 }
797
798 static Eina_Bool
799 _elm_list_smart_sub_object_del(Evas_Object *obj,
800                                Evas_Object *sobj)
801 {
802    const Eina_List *l;
803    Elm_List_Item *it;
804
805    ELM_LIST_DATA_GET(obj, sd);
806
807    if (!ELM_WIDGET_CLASS(_elm_list_parent_sc)->sub_object_del(obj, sobj))
808      return EINA_FALSE;
809
810    if ((sobj == sd->box) || (sobj == obj)) goto end;
811
812    EINA_LIST_FOREACH(sd->items, l, it)
813      {
814         if ((sobj == it->icon) || (sobj == it->end))
815           {
816              if (it->icon == sobj) it->icon = NULL;
817              if (it->end == sobj) it->end = NULL;
818              evas_object_event_callback_del_full
819                (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb,
820                obj);
821              if (!sd->walking)
822                {
823                   _items_fix(obj);
824                   elm_layout_sizing_eval(obj);
825                }
826              else
827                sd->fix_pending = EINA_TRUE;
828              break;
829           }
830      }
831
832 end:
833    return EINA_TRUE;
834 }
835
836 static void
837 _item_highlight(Elm_List_Item *it)
838 {
839    Evas_Object *obj;
840    const char *select_raise;
841
842    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
843    obj = WIDGET(it);
844    ELM_LIST_DATA_GET(obj, sd);
845
846    if ((it->highlighted) || (it->base.disabled) ||
847        (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return;
848
849    evas_object_ref(obj);
850    _elm_list_walk(sd);
851
852    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
853    evas_object_smart_callback_call(obj, SIG_HIGHLIGHTED, it);
854    select_raise = edje_object_data_get(VIEW(it), "selectraise");
855    if ((select_raise) && (!strcmp(select_raise, "on")))
856      evas_object_raise(VIEW(it));
857    it->highlighted = EINA_TRUE;
858
859    _elm_list_unwalk(sd);
860    evas_object_unref(obj);
861 }
862
863 static void
864 _item_select(Elm_List_Item *it)
865 {
866    Evas_Object *obj;
867
868    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
869    obj = WIDGET(it);
870    ELM_LIST_DATA_GET(obj, sd);
871
872    if (it->base.disabled || (sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
873      return;
874    if (it->selected)
875      {
876         if (sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) goto call;
877         return;
878      }
879    it->selected = EINA_TRUE;
880    sd->selected = eina_list_append(sd->selected, it);
881
882 call:
883    evas_object_ref(obj);
884    _elm_list_walk(sd);
885
886    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
887    evas_object_smart_callback_call(obj, SIG_SELECTED, it);
888    it->sd->last_selected_item = (Elm_Object_Item *)it;
889
890    _elm_list_unwalk(sd);
891    evas_object_unref(obj);
892 }
893
894 static void
895 _item_unselect(Elm_List_Item *it)
896 {
897    Evas_Object *obj = WIDGET(it);
898    ELM_LIST_DATA_GET(obj, sd);
899    const char *stacking, *select_raise;
900
901    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
902    if (!it->highlighted) return;
903
904    evas_object_ref(obj);
905    _elm_list_walk(sd);
906
907    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
908    evas_object_smart_callback_call(obj, SIG_UNHIGHLIGHTED, it);
909    stacking = edje_object_data_get(VIEW(it), "stacking");
910    select_raise = edje_object_data_get(VIEW(it), "selectraise");
911    if ((select_raise) && (!strcmp(select_raise, "on")))
912      {
913         if ((stacking) && (!strcmp(stacking, "below")))
914           evas_object_lower(VIEW(it));
915      }
916    it->highlighted = EINA_FALSE;
917    if (it->selected)
918      {
919         it->selected = EINA_FALSE;
920         sd->selected = eina_list_remove(sd->selected, it);
921         evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
922      }
923
924    _elm_list_unwalk(sd);
925    evas_object_unref(obj);
926 }
927
928 static Eina_Bool
929 _swipe_cancel(void *data)
930 {
931    Elm_List_Item *it = data;
932
933    ELM_LIST_ITEM_CHECK_OR_RETURN(it, ECORE_CALLBACK_CANCEL);
934    ELM_LIST_DATA_GET(WIDGET(it), sd);
935
936    sd->swipe = EINA_FALSE;
937    sd->movements = 0;
938
939    return ECORE_CALLBACK_RENEW;
940 }
941
942 static void
943 _edge_left_cb(Evas_Object *obj,
944               void *data __UNUSED__)
945 {
946    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
947 }
948
949 static void
950 _edge_right_cb(Evas_Object *obj,
951                void *data __UNUSED__)
952 {
953    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
954 }
955
956 static void
957 _edge_top_cb(Evas_Object *obj,
958              void *data __UNUSED__)
959 {
960    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
961 }
962
963 static void
964 _edge_bottom_cb(Evas_Object *obj,
965                 void *data __UNUSED__)
966 {
967    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
968 }
969
970 static Eina_Bool
971 _long_press_cb(void *data)
972 {
973    Elm_List_Item *it = data;
974    Evas_Object *obj;
975
976    ELM_LIST_ITEM_CHECK_OR_RETURN(it, ECORE_CALLBACK_CANCEL);
977    obj = WIDGET(it);
978    ELM_LIST_DATA_GET(obj, sd);
979
980    it->long_timer = NULL;
981    if (it->base.disabled) goto end;
982
983    sd->longpressed = EINA_TRUE;
984    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
985
986 end:
987    return ECORE_CALLBACK_CANCEL;
988 }
989
990 static void
991 _swipe_do(Elm_List_Item *it)
992 {
993    int i, sum = 0;
994
995    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
996    ELM_LIST_DATA_GET(WIDGET(it), sd);
997
998    sd->swipe = EINA_FALSE;
999    for (i = 0; i < sd->movements; i++)
1000      {
1001         sum += sd->history[i].x;
1002         if (abs(sd->history[0].y - sd->history[i].y) > 10) return;
1003      }
1004
1005    sum /= sd->movements;
1006    if (abs(sum - sd->history[0].x) <= 10) return;
1007
1008    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1009 }
1010
1011 static void
1012 _mouse_move_cb(void *data,
1013                Evas *evas __UNUSED__,
1014                Evas_Object *o __UNUSED__,
1015                void *event_info)
1016 {
1017    Evas_Object *obj;
1018    Elm_List_Item *it = data;
1019    Evas_Event_Mouse_Move *ev = event_info;
1020
1021    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1022    obj = WIDGET(it);
1023    ELM_LIST_DATA_GET(obj, sd);
1024
1025    evas_object_ref(obj);
1026    _elm_list_walk(sd);
1027
1028    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1029      {
1030         if (!sd->on_hold)
1031           {
1032              sd->on_hold = EINA_TRUE;
1033              if (it->long_timer)
1034                {
1035                   ecore_timer_del(it->long_timer);
1036                   it->long_timer = NULL;
1037                }
1038              if (!sd->was_selected)
1039                _item_unselect(it);
1040           }
1041         if (sd->movements == ELM_LIST_SWIPE_MOVES) sd->swipe = EINA_TRUE;
1042         else
1043           {
1044              sd->history[sd->movements].x = ev->cur.canvas.x;
1045              sd->history[sd->movements].y = ev->cur.canvas.y;
1046              if (abs((sd->history[sd->movements].x - sd->history[0].x)) > 40)
1047                sd->swipe = EINA_TRUE;
1048              else
1049                sd->movements++;
1050           }
1051      }
1052
1053    _elm_list_unwalk(sd);
1054    evas_object_unref(obj);
1055 }
1056
1057 static void
1058 _mouse_down_cb(void *data,
1059                Evas *evas __UNUSED__,
1060                Evas_Object *o __UNUSED__,
1061                void *event_info)
1062 {
1063    Evas_Event_Mouse_Down *ev = event_info;
1064    Elm_List_Item *it = data;
1065    Evas_Object *obj;
1066
1067    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1068    obj = WIDGET(it);
1069    ELM_LIST_DATA_GET(obj, sd);
1070
1071    if (ev->button != 1) return;
1072    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
1073    else sd->on_hold = EINA_FALSE;
1074
1075    if (sd->on_hold) return;
1076    sd->was_selected = it->selected;
1077
1078    evas_object_ref(obj);
1079    _elm_list_walk(sd);
1080
1081    _item_highlight(it);
1082    sd->longpressed = EINA_FALSE;
1083    if (it->long_timer) ecore_timer_del(it->long_timer);
1084    it->long_timer = ecore_timer_add
1085        (_elm_config->longpress_timeout, _long_press_cb, it);
1086    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
1087    it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1088
1089    /* Always call the callbacks last - the user may delete our context! */
1090    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1091      {
1092         evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1093         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1094      }
1095    sd->swipe = EINA_FALSE;
1096    sd->movements = 0;
1097
1098    _elm_list_unwalk(sd);
1099    evas_object_unref(obj);
1100 }
1101
1102 static void
1103 _mouse_up_cb(void *data,
1104              Evas *evas __UNUSED__,
1105              Evas_Object *o __UNUSED__,
1106              void *event_info)
1107 {
1108    Evas_Object *obj;
1109    Elm_List_Item *it = data;
1110    Evas_Event_Mouse_Up *ev = event_info;
1111
1112    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1113    obj = WIDGET(it);
1114    ELM_LIST_DATA_GET(obj, sd);
1115
1116    if (ev->button != 1) return;
1117    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
1118    else sd->on_hold = EINA_FALSE;
1119    sd->longpressed = EINA_FALSE;
1120    if (it->long_timer)
1121      {
1122         ecore_timer_del(it->long_timer);
1123         it->long_timer = NULL;
1124      }
1125    if (it->swipe_timer)
1126      {
1127         ecore_timer_del(it->swipe_timer);
1128         it->swipe_timer = NULL;
1129      }
1130    if (sd->on_hold)
1131      {
1132         if (sd->swipe) _swipe_do(data);
1133         sd->on_hold = EINA_FALSE;
1134         return;
1135      }
1136    if (sd->longpressed)
1137      {
1138         if (!sd->was_selected) _item_unselect(it);
1139         sd->was_selected = 0;
1140         return;
1141      }
1142
1143    if (it->base.disabled)
1144      return;
1145    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1146
1147    evas_object_ref(obj);
1148    _elm_list_walk(sd);
1149
1150    if (sd->multi)
1151      {
1152         if (!it->selected)
1153           {
1154              _item_highlight(it);
1155              _item_select(it);
1156           }
1157         else _item_unselect(it);
1158      }
1159    else
1160      {
1161         if (!it->selected)
1162           {
1163              while (sd->selected)
1164                _item_unselect(sd->selected->data);
1165              _item_highlight(it);
1166              _item_select(it);
1167           }
1168         else
1169           {
1170              const Eina_List *l, *l_next;
1171              Elm_List_Item *it2;
1172
1173              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, it2)
1174                if (it2 != it) _item_unselect(it2);
1175              _item_highlight(it);
1176              _item_select(it);
1177           }
1178      }
1179
1180    _elm_list_unwalk(sd);
1181    evas_object_unref(obj);
1182 }
1183
1184 static void
1185 _item_disable_hook(Elm_Object_Item *it)
1186 {
1187    Elm_List_Item *item = (Elm_List_Item *)it;
1188
1189    if (item->base.disabled)
1190      edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1191    else
1192      edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm");
1193 }
1194
1195 static void
1196 _item_content_set_hook(Elm_Object_Item *it,
1197                        const char *part,
1198                        Evas_Object *content)
1199 {
1200    Elm_List_Item *item = (Elm_List_Item *)it;
1201    Evas_Object **icon_p = NULL;
1202    Eina_Bool dummy = EINA_FALSE;
1203
1204    if ((!part) || (!strcmp(part, "start")))
1205      {
1206         icon_p = &(item->icon);
1207         dummy = item->dummy_icon;
1208         if (!content) item->dummy_icon = EINA_TRUE;
1209         else item->dummy_icon = EINA_FALSE;
1210      }
1211    else if (!strcmp(part, "end"))
1212      {
1213         icon_p = &(item->end);
1214         dummy = item->dummy_end;
1215         if (!content) item->dummy_end = EINA_TRUE;
1216         else item->dummy_end = EINA_FALSE;
1217      }
1218    else
1219      return;
1220
1221    if (content == *icon_p) return;
1222    if ((dummy) && (!content)) return;
1223    if (dummy) evas_object_del(*icon_p);
1224    if (!content)
1225      {
1226         content =
1227           evas_object_rectangle_add(evas_object_evas_get(WIDGET(item)));
1228         evas_object_color_set(content, 0, 0, 0, 0);
1229      }
1230    if (*icon_p)
1231      {
1232         evas_object_del(*icon_p);
1233         *icon_p = NULL;
1234      }
1235    *icon_p = content;
1236
1237    if (VIEW(item))
1238      edje_object_part_swallow(VIEW(item), "elm.swallow.icon", content);
1239 }
1240
1241 static Evas_Object *
1242 _item_content_get_hook(const Elm_Object_Item *it,
1243                        const char *part)
1244 {
1245    Elm_List_Item *item = (Elm_List_Item *)it;
1246
1247    if ((!part) || (!strcmp(part, "start")))
1248      {
1249         if (item->dummy_icon) return NULL;
1250         return item->icon;
1251      }
1252    else if (!strcmp(part, "end"))
1253      {
1254         if (item->dummy_end) return NULL;
1255         return item->end;
1256      }
1257
1258    return NULL;
1259 }
1260
1261 static Evas_Object *
1262 _item_content_unset_hook(const Elm_Object_Item *it,
1263                          const char *part)
1264 {
1265    Elm_List_Item *item = (Elm_List_Item *)it;
1266
1267    if ((!part) || (!strcmp(part, "start")))
1268      {
1269         Evas_Object *obj = item->icon;
1270         _item_content_set_hook((Elm_Object_Item *)it, part, NULL);
1271         return obj;
1272      }
1273    else if (!strcmp(part, "end"))
1274      {
1275         Evas_Object *obj = item->end;
1276         _item_content_set_hook((Elm_Object_Item *)it, part, NULL);
1277         return obj;
1278      }
1279
1280    return NULL;
1281 }
1282
1283 static void
1284 _item_text_set_hook(Elm_Object_Item *it,
1285                     const char *part,
1286                     const char *text)
1287 {
1288    Elm_List_Item *list_it = (Elm_List_Item *)it;
1289
1290    if (part && strcmp(part, "default")) return;
1291    if (!eina_stringshare_replace(&list_it->label, text)) return;
1292    if (VIEW(list_it))
1293      edje_object_part_text_escaped_set(VIEW(list_it), "elm.text", text);
1294 }
1295
1296 static const char *
1297 _item_text_get_hook(const Elm_Object_Item *it,
1298                     const char *part)
1299 {
1300    if (part && strcmp(part, "default")) return NULL;
1301    return ((Elm_List_Item *)it)->label;
1302 }
1303
1304 static Eina_Bool
1305 _item_del_pre_hook(Elm_Object_Item *it)
1306 {
1307    Evas_Object *obj = WIDGET(it);
1308    Elm_List_Item *item = (Elm_List_Item *)it;
1309
1310    ELM_LIST_DATA_GET(obj, sd);
1311
1312    if (item->selected) _item_unselect(item);
1313
1314    if (sd->walking > 0)
1315      {
1316         if (item->deleted) return EINA_FALSE;
1317         item->deleted = EINA_TRUE;
1318         sd->to_delete = eina_list_append(sd->to_delete, item);
1319         return EINA_FALSE;
1320      }
1321
1322    sd->items = eina_list_remove_list(sd->items, item->node);
1323
1324    evas_object_ref(obj);
1325    _elm_list_walk(sd);
1326
1327    _elm_list_item_free(item);
1328
1329    _elm_list_unwalk(sd);
1330    evas_object_unref(obj);
1331
1332    return EINA_TRUE;
1333 }
1334
1335 static char *
1336 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
1337 {
1338    Elm_List_Item *it = (Elm_List_Item *)data;
1339    const char *txt = NULL;
1340    if (!it) return NULL;
1341
1342    if (!txt) txt = it->label;
1343    if (txt) return strdup(txt);
1344
1345    return NULL;
1346 }
1347
1348 static char *
1349 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
1350 {
1351    Elm_List_Item *it = (Elm_List_Item *)data;
1352    if (!it) return NULL;
1353
1354    if (it->base.disabled)
1355      return strdup(E_("State: Disabled"));
1356
1357    return NULL;
1358 }
1359
1360 static void
1361 _access_on_highlight_cb(void *data)
1362 {
1363    Elm_Object_Item *it = (Elm_Object_Item *)data;
1364    if (!it) return;
1365
1366    elm_list_item_bring_in(it);
1367 }
1368
1369 static void
1370 _access_activate_cb(void *data __UNUSED__,
1371                     Evas_Object *part_obj __UNUSED__,
1372                     Elm_Object_Item *item)
1373 {
1374    Elm_List_Item *it;
1375    Evas_Object *obj;
1376
1377    it = (Elm_List_Item *)item;
1378    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
1379
1380    obj = WIDGET(it);
1381    ELM_LIST_DATA_GET(obj, sd);
1382
1383    evas_object_ref(obj);
1384    _elm_list_walk(sd);
1385
1386    if (sd->multi)
1387      {
1388         if (!it->selected)
1389           {
1390              _item_highlight(it);
1391              _item_select(it);
1392           }
1393         else _item_unselect(it);
1394      }
1395    else
1396      {
1397         if (!it->selected)
1398           {
1399              while (sd->selected)
1400                _item_unselect(sd->selected->data);
1401              _item_highlight(it);
1402              _item_select(it);
1403           }
1404         else
1405           {
1406              const Eina_List *l, *l_next;
1407              Elm_List_Item *it2;
1408
1409              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, it2)
1410                if (it2 != it) _item_unselect(it2);
1411              _item_highlight(it);
1412              _item_select(it);
1413           }
1414      }
1415
1416    _elm_list_unwalk(sd);
1417    evas_object_unref(obj);
1418 }
1419
1420 static void
1421 _access_widget_item_register(Elm_List_Item *it, Eina_Bool is_access)
1422 {
1423    Elm_Access_Info *ai;
1424
1425    if (!is_access) _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
1426    else
1427      {
1428         _elm_access_widget_item_register((Elm_Widget_Item *)it);
1429
1430         ai = _elm_access_object_get(it->base.access_obj);
1431
1432         _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
1433         _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
1434         _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, it);
1435         _elm_access_activate_callback_set(ai, _access_activate_cb, it);
1436      }
1437 }
1438
1439 static Elm_List_Item *
1440 _item_new(Evas_Object *obj,
1441           const char *label,
1442           Evas_Object *icon,
1443           Evas_Object *end,
1444           Evas_Smart_Cb func,
1445           const void *data)
1446 {
1447    Elm_List_Item *it;
1448
1449    ELM_LIST_DATA_GET(obj, sd);
1450
1451    it = elm_widget_item_new(obj, Elm_List_Item);
1452    if (!it) return NULL;
1453
1454    it->sd = sd;
1455    it->label = eina_stringshare_add(label);
1456    it->icon = icon;
1457    it->end = end;
1458    it->func = func;
1459    it->base.data = data;
1460
1461    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
1462
1463    /* access */
1464    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1465      _access_widget_item_register(it, EINA_TRUE);
1466
1467    edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
1468    evas_object_event_callback_add
1469      (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, it);
1470    evas_object_event_callback_add
1471      (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, it);
1472    evas_object_event_callback_add
1473      (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, it);
1474    evas_object_size_hint_weight_set
1475      (VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1476    evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
1477    edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
1478
1479    if (it->icon)
1480      {
1481         elm_widget_sub_object_add(obj, it->icon);
1482         evas_object_event_callback_add
1483           (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb,
1484           obj);
1485      }
1486    if (it->end)
1487      {
1488         elm_widget_sub_object_add(obj, it->end);
1489         evas_object_event_callback_add
1490           (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb,
1491           obj);
1492      }
1493
1494    elm_widget_item_disable_hook_set(it, _item_disable_hook);
1495    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1496    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1497    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1498    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1499    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1500    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1501
1502    return it;
1503 }
1504
1505 static void
1506 _resize_cb(void *data,
1507            Evas *e __UNUSED__,
1508            Evas_Object *obj __UNUSED__,
1509            void *event_info __UNUSED__)
1510 {
1511    elm_layout_sizing_eval(data);
1512 }
1513
1514 static Eina_Bool
1515 _elm_list_smart_focus_next(const Evas_Object *obj,
1516                            Elm_Focus_Direction dir,
1517                            Evas_Object **next)
1518 {
1519    Eina_List *items = NULL;
1520    Eina_List *elist = NULL;
1521    Elm_List_Item *it;
1522
1523    ELM_LIST_CHECK(obj) EINA_FALSE;
1524    ELM_LIST_DATA_GET(obj, sd);
1525
1526    if (_elm_config->access_mode != ELM_ACCESS_MODE_ON) return EINA_FALSE;
1527
1528    EINA_LIST_FOREACH(sd->items, elist, it)
1529      {
1530         items = eina_list_append(items, it->base.access_obj);
1531         if (it->icon) items = eina_list_append(items, it->icon);
1532         if (it->end) items = eina_list_append(items, it->end);
1533      }
1534
1535    return elm_widget_focus_list_next_get
1536             (obj, items, eina_list_data_get, dir, next);
1537 }
1538
1539 static void
1540 _elm_list_smart_add(Evas_Object *obj)
1541 {
1542    Evas_Coord minw, minh;
1543
1544    EVAS_SMART_DATA_ALLOC(obj, Elm_List_Smart_Data);
1545
1546    ELM_WIDGET_CLASS(_elm_list_parent_sc)->base.add(obj);
1547
1548    elm_widget_can_focus_set(obj, EINA_TRUE);
1549
1550    priv->mode = ELM_LIST_SCROLL;
1551
1552    elm_layout_theme_set(obj, "list", "base", elm_widget_style_get(obj));
1553
1554    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
1555    evas_object_data_set(priv->hit_rect, "_elm_leaveme", obj);
1556    evas_object_smart_member_add(priv->hit_rect, obj);
1557    elm_widget_sub_object_add(obj, priv->hit_rect);
1558
1559    /* common scroller hit rectangle setup */
1560    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
1561    evas_object_show(priv->hit_rect);
1562    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
1563
1564    priv->s_iface = evas_object_smart_interface_get
1565        (obj, ELM_SCROLLABLE_IFACE_NAME);
1566
1567    priv->s_iface->edge_left_cb_set(obj, _edge_left_cb);
1568    priv->s_iface->edge_right_cb_set(obj, _edge_right_cb);
1569    priv->s_iface->edge_top_cb_set(obj, _edge_top_cb);
1570    priv->s_iface->edge_bottom_cb_set(obj, _edge_bottom_cb);
1571
1572    priv->s_iface->content_min_limit_cb_set
1573      (obj, _elm_list_content_min_limit_cb);
1574
1575    priv->s_iface->objects_set
1576      (obj, ELM_WIDGET_DATA(priv)->resize_obj, priv->hit_rect);
1577
1578    /* the scrollable interface may set this */
1579    evas_object_event_callback_add
1580      (ELM_WIDGET_DATA(priv)->resize_obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1581      _size_hints_changed_cb, obj);
1582
1583    edje_object_size_min_calc
1584      (ELM_WIDGET_DATA(priv)->resize_obj, &minw, &minh);
1585    evas_object_size_hint_min_set(obj, minw, minh);
1586    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
1587
1588    priv->s_iface->bounce_allow_set
1589      (obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable);
1590
1591    priv->box = elm_box_add(obj);
1592    elm_box_homogeneous_set(priv->box, EINA_TRUE);
1593    evas_object_size_hint_weight_set(priv->box, EVAS_HINT_EXPAND, 0.0);
1594    evas_object_size_hint_align_set(priv->box, EVAS_HINT_FILL, 0.0);
1595
1596    /* FIXME: change this ugly code path later */
1597    elm_widget_on_show_region_hook_set(priv->box, _show_region_hook, obj);
1598    elm_widget_sub_object_add(obj, priv->box);
1599
1600    priv->s_iface->content_set(obj, priv->box);
1601    evas_object_event_callback_add
1602      (priv->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1603      _size_hints_changed_cb, obj);
1604 }
1605
1606 static void
1607 _elm_list_smart_del(Evas_Object *obj)
1608 {
1609    const Eina_List *l;
1610    Elm_List_Item *it;
1611
1612    ELM_LIST_DATA_GET(obj, sd);
1613
1614    if (sd->walking)
1615      ERR("ERROR: list deleted while walking.\n");
1616
1617    sd->delete_me = EINA_TRUE;
1618    EINA_LIST_FOREACH(sd->items, l, it)
1619      {
1620         if (it->icon)
1621           evas_object_event_callback_del
1622             (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1623             _size_hints_changed_cb);
1624         if (it->end)
1625           evas_object_event_callback_del
1626             (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1627             _size_hints_changed_cb);
1628      }
1629
1630    evas_object_event_callback_del
1631      (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1632      _size_hints_changed_cb);
1633    evas_object_event_callback_del
1634      (sd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _size_hints_changed_cb);
1635
1636    _elm_list_walk(sd);
1637
1638    EINA_LIST_FREE (sd->items, it)
1639      {
1640         /* issuing free because of "locking" item del pre hook */
1641         _elm_list_item_free(it);
1642         elm_widget_item_free(it);
1643      }
1644
1645    _elm_list_unwalk(sd);
1646
1647    if (sd->to_delete)
1648      ERR("ERROR: leaking nodes!\n");
1649
1650    eina_list_free(sd->selected);
1651
1652    ELM_WIDGET_CLASS(_elm_list_parent_sc)->base.del(obj);
1653 }
1654
1655 static void
1656 _elm_list_smart_move(Evas_Object *obj,
1657                      Evas_Coord x,
1658                      Evas_Coord y)
1659 {
1660    ELM_LIST_DATA_GET(obj, sd);
1661
1662    ELM_WIDGET_CLASS(_elm_list_parent_sc)->base.move(obj, x, y);
1663
1664    evas_object_move(sd->hit_rect, x, y);
1665 }
1666
1667 static void
1668 _elm_list_smart_resize(Evas_Object *obj,
1669                        Evas_Coord w,
1670                        Evas_Coord h)
1671 {
1672    ELM_LIST_DATA_GET(obj, sd);
1673
1674    ELM_WIDGET_CLASS(_elm_list_parent_sc)->base.resize(obj, w, h);
1675
1676    evas_object_resize(sd->hit_rect, w, h);
1677 }
1678
1679 static void
1680 _elm_list_smart_member_add(Evas_Object *obj,
1681                            Evas_Object *member)
1682 {
1683    ELM_LIST_DATA_GET(obj, sd);
1684
1685    ELM_WIDGET_CLASS(_elm_list_parent_sc)->base.member_add(obj, member);
1686
1687    if (sd->hit_rect)
1688      evas_object_raise(sd->hit_rect);
1689 }
1690
1691 static void
1692 _elm_list_smart_access(Evas_Object *obj, Eina_Bool is_access)
1693 {
1694    Eina_List *elist = NULL;
1695    Elm_List_Item *it;
1696
1697    ELM_LIST_DATA_GET(obj, sd);
1698
1699    if (is_access)
1700      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
1701         _elm_list_smart_focus_next;
1702    else
1703      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
1704
1705    EINA_LIST_FOREACH(sd->items, elist, it)
1706      _access_widget_item_register(it, is_access);
1707 }
1708
1709 static void
1710 _elm_list_smart_set_user(Elm_List_Smart_Class *sc)
1711 {
1712    ELM_WIDGET_CLASS(sc)->base.add = _elm_list_smart_add;
1713    ELM_WIDGET_CLASS(sc)->base.del = _elm_list_smart_del;
1714    ELM_WIDGET_CLASS(sc)->base.move = _elm_list_smart_move;
1715    ELM_WIDGET_CLASS(sc)->base.resize = _elm_list_smart_resize;
1716    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_list_smart_member_add;
1717
1718    ELM_WIDGET_CLASS(sc)->sub_object_del = _elm_list_smart_sub_object_del;
1719    ELM_WIDGET_CLASS(sc)->on_focus = _elm_list_smart_on_focus;
1720    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
1721    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1722    ELM_WIDGET_CLASS(sc)->theme = _elm_list_smart_theme;
1723    ELM_WIDGET_CLASS(sc)->disable = _elm_list_smart_disable;
1724    ELM_WIDGET_CLASS(sc)->event = _elm_list_smart_event;
1725    ELM_WIDGET_CLASS(sc)->translate = _elm_list_smart_translate;
1726    ELM_WIDGET_CLASS(sc)->access = _elm_list_smart_access;
1727
1728    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_list_smart_sizing_eval;
1729
1730    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1731      ELM_WIDGET_CLASS(sc)->focus_next = _elm_list_smart_focus_next;
1732 }
1733
1734 EAPI const Elm_List_Smart_Class *
1735 elm_list_smart_class_get(void)
1736 {
1737    static Elm_List_Smart_Class _sc =
1738      ELM_LIST_SMART_CLASS_INIT_NAME_VERSION(ELM_LIST_SMART_NAME);
1739    static const Elm_List_Smart_Class *class = NULL;
1740    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1741
1742    if (class)
1743      return class;
1744
1745    _elm_list_smart_set(&_sc);
1746    esc->callbacks = _smart_callbacks;
1747    class = &_sc;
1748
1749    return class;
1750 }
1751
1752 EAPI Evas_Object *
1753 elm_list_add(Evas_Object *parent)
1754 {
1755    Evas_Object *obj;
1756
1757    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1758
1759    obj = elm_widget_add(_elm_list_smart_class_new(), parent);
1760    if (!obj) return NULL;
1761
1762    if (!elm_widget_sub_object_add(parent, obj))
1763      ERR("could not add %p as sub object of %p", obj, parent);
1764
1765    return obj;
1766 }
1767
1768 EAPI void
1769 elm_list_go(Evas_Object *obj)
1770 {
1771    ELM_LIST_CHECK(obj);
1772
1773    _items_fix(obj);
1774 }
1775
1776 EAPI void
1777 elm_list_multi_select_set(Evas_Object *obj,
1778                           Eina_Bool multi)
1779 {
1780    ELM_LIST_CHECK(obj);
1781    ELM_LIST_DATA_GET(obj, sd);
1782
1783    sd->multi = multi;
1784 }
1785
1786 EAPI Eina_Bool
1787 elm_list_multi_select_get(const Evas_Object *obj)
1788 {
1789    ELM_LIST_CHECK(obj) EINA_FALSE;
1790    ELM_LIST_DATA_GET(obj, sd);
1791
1792    return sd->multi;
1793 }
1794
1795 EAPI void
1796 elm_list_mode_set(Evas_Object *obj,
1797                   Elm_List_Mode mode)
1798 {
1799    ELM_LIST_CHECK(obj);
1800    ELM_LIST_DATA_GET(obj, sd);
1801
1802    if (sd->mode == mode)
1803      return;
1804
1805    sd->mode = mode;
1806
1807    _elm_list_mode_set_internal(sd);
1808 }
1809
1810 EAPI Elm_List_Mode
1811 elm_list_mode_get(const Evas_Object *obj)
1812 {
1813    ELM_LIST_CHECK(obj) ELM_LIST_LAST;
1814    ELM_LIST_DATA_GET(obj, sd);
1815
1816    return sd->mode;
1817 }
1818
1819 EAPI void
1820 elm_list_horizontal_set(Evas_Object *obj,
1821                         Eina_Bool horizontal)
1822 {
1823    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1824
1825    ELM_LIST_CHECK(obj);
1826    ELM_LIST_DATA_GET(obj, sd);
1827
1828    horizontal = !!horizontal;
1829
1830    if (sd->h_mode == horizontal)
1831      return;
1832
1833    sd->h_mode = horizontal;
1834    elm_box_horizontal_set(sd->box, horizontal);
1835
1836    if (horizontal)
1837      {
1838         evas_object_size_hint_weight_set(sd->box, 0.0, EVAS_HINT_EXPAND);
1839         evas_object_size_hint_align_set(sd->box, 0.0, EVAS_HINT_FILL);
1840         sd->s_iface->bounce_allow_set(obj, bounce, EINA_FALSE);
1841      }
1842    else
1843      {
1844         evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND, 0.0);
1845         evas_object_size_hint_align_set(sd->box, EVAS_HINT_FILL, 0.0);
1846         sd->s_iface->bounce_allow_set(obj, EINA_FALSE, bounce);
1847      }
1848
1849    _elm_list_mode_set_internal(sd);
1850 }
1851
1852 EAPI Eina_Bool
1853 elm_list_horizontal_get(const Evas_Object *obj)
1854 {
1855    ELM_LIST_CHECK(obj) EINA_FALSE;
1856    ELM_LIST_DATA_GET(obj, sd);
1857
1858    return sd->h_mode;
1859 }
1860
1861 EAPI void
1862 elm_list_select_mode_set(Evas_Object *obj,
1863                          Elm_Object_Select_Mode mode)
1864 {
1865    ELM_LIST_CHECK(obj);
1866    ELM_LIST_DATA_GET(obj, sd);
1867
1868    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
1869      return;
1870
1871    if (sd->select_mode != mode)
1872      sd->select_mode = mode;
1873 }
1874
1875 EAPI Elm_Object_Select_Mode
1876 elm_list_select_mode_get(const Evas_Object *obj)
1877 {
1878    ELM_LIST_CHECK(obj) ELM_OBJECT_SELECT_MODE_MAX;
1879    ELM_LIST_DATA_GET(obj, sd);
1880
1881    return sd->select_mode;
1882 }
1883
1884 EAPI void
1885 elm_list_bounce_set(Evas_Object *obj,
1886                     Eina_Bool h_bounce,
1887                     Eina_Bool v_bounce)
1888 {
1889    ELM_LIST_CHECK(obj);
1890    ELM_LIST_DATA_GET(obj, sd);
1891
1892    sd->s_iface->bounce_allow_set(obj, h_bounce, v_bounce);
1893 }
1894
1895 EAPI void
1896 elm_list_bounce_get(const Evas_Object *obj,
1897                     Eina_Bool *h_bounce,
1898                     Eina_Bool *v_bounce)
1899 {
1900    ELM_LIST_CHECK(obj);
1901    ELM_LIST_DATA_GET(obj, sd);
1902
1903    sd->s_iface->bounce_allow_get(obj, h_bounce, v_bounce);
1904 }
1905
1906 EAPI void
1907 elm_list_scroller_policy_set(Evas_Object *obj,
1908                              Elm_Scroller_Policy policy_h,
1909                              Elm_Scroller_Policy policy_v)
1910 {
1911    ELM_LIST_CHECK(obj);
1912    ELM_LIST_DATA_GET(obj, sd);
1913
1914    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
1915        (policy_v >= ELM_SCROLLER_POLICY_LAST))
1916      return;
1917
1918    sd->s_iface->policy_set(obj, policy_h, policy_v);
1919 }
1920
1921 EAPI void
1922 elm_list_scroller_policy_get(const Evas_Object *obj,
1923                              Elm_Scroller_Policy *policy_h,
1924                              Elm_Scroller_Policy *policy_v)
1925 {
1926    ELM_LIST_CHECK(obj);
1927    ELM_LIST_DATA_GET(obj, sd);
1928
1929    sd->s_iface->policy_get(obj, policy_h, policy_v);
1930 }
1931
1932 EAPI void
1933 elm_list_clear(Evas_Object *obj)
1934 {
1935    Elm_List_Item *it;
1936
1937    ELM_LIST_CHECK(obj);
1938    ELM_LIST_DATA_GET(obj, sd);
1939
1940    if (!sd->items) return;
1941
1942    eina_list_free(sd->selected);
1943    sd->selected = NULL;
1944
1945    if (sd->walking > 0)
1946      {
1947         Eina_List *n;
1948
1949         EINA_LIST_FOREACH(sd->items, n, it)
1950           {
1951              if (it->deleted) continue;
1952              it->deleted = EINA_TRUE;
1953              sd->to_delete = eina_list_append(sd->to_delete, it);
1954           }
1955         return;
1956      }
1957
1958    evas_object_ref(obj);
1959
1960    _elm_list_walk(sd);
1961
1962    EINA_LIST_FREE (sd->items, it)
1963      {
1964         /* issuing free because of "locking" item del pre hook */
1965         _elm_list_item_free(it);
1966         elm_widget_item_free(it);
1967      }
1968
1969    _elm_list_unwalk(sd);
1970
1971    _items_fix(obj);
1972    elm_layout_sizing_eval(obj);
1973
1974    evas_object_unref(obj);
1975 }
1976
1977 EAPI const Eina_List *
1978 elm_list_items_get(const Evas_Object *obj)
1979 {
1980    ELM_LIST_CHECK(obj) NULL;
1981    ELM_LIST_DATA_GET(obj, sd);
1982
1983    return sd->items;
1984 }
1985
1986 EAPI Elm_Object_Item *
1987 elm_list_selected_item_get(const Evas_Object *obj)
1988 {
1989    ELM_LIST_CHECK(obj) NULL;
1990    ELM_LIST_DATA_GET(obj, sd);
1991
1992    if (sd->selected) return (Elm_Object_Item *)sd->selected->data;
1993
1994    return NULL;
1995 }
1996
1997 EAPI const Eina_List *
1998 elm_list_selected_items_get(const Evas_Object *obj)
1999 {
2000    ELM_LIST_CHECK(obj) NULL;
2001    ELM_LIST_DATA_GET(obj, sd);
2002
2003    return sd->selected;
2004 }
2005
2006 EAPI Elm_Object_Item *
2007 elm_list_item_append(Evas_Object *obj,
2008                      const char *label,
2009                      Evas_Object *icon,
2010                      Evas_Object *end,
2011                      Evas_Smart_Cb func,
2012                      const void *data)
2013 {
2014    Elm_List_Item *it;
2015
2016    ELM_LIST_CHECK(obj) NULL;
2017    ELM_LIST_DATA_GET(obj, sd);
2018
2019    it = _item_new(obj, label, icon, end, func, data);
2020
2021    sd->items = eina_list_append(sd->items, it);
2022    it->node = eina_list_last(sd->items);
2023    elm_box_pack_end(sd->box, VIEW(it));
2024
2025    return (Elm_Object_Item *)it;
2026 }
2027
2028 EAPI Elm_Object_Item *
2029 elm_list_item_prepend(Evas_Object *obj,
2030                       const char *label,
2031                       Evas_Object *icon,
2032                       Evas_Object *end,
2033                       Evas_Smart_Cb func,
2034                       const void *data)
2035 {
2036    Elm_List_Item *it;
2037
2038    ELM_LIST_CHECK(obj) NULL;
2039    ELM_LIST_DATA_GET(obj, sd);
2040
2041    it = _item_new(obj, label, icon, end, func, data);
2042
2043    sd->items = eina_list_prepend(sd->items, it);
2044    it->node = sd->items;
2045    elm_box_pack_start(sd->box, VIEW(it));
2046
2047    return (Elm_Object_Item *)it;
2048 }
2049
2050 EAPI Elm_Object_Item *
2051 elm_list_item_insert_before(Evas_Object *obj,
2052                             Elm_Object_Item *before,
2053                             const char *label,
2054                             Evas_Object *icon,
2055                             Evas_Object *end,
2056                             Evas_Smart_Cb func,
2057                             const void *data)
2058 {
2059    Elm_List_Item *it, *before_it;
2060
2061    ELM_LIST_CHECK(obj) NULL;
2062    ELM_LIST_ITEM_CHECK_OR_RETURN(before, NULL);
2063    ELM_LIST_DATA_GET(obj, sd);
2064
2065    before_it = (Elm_List_Item *)before;
2066    if (!before_it->node) return NULL;
2067
2068    it = _item_new(obj, label, icon, end, func, data);
2069    sd->items = eina_list_prepend_relative_list(sd->items, it, before_it->node);
2070    it->node = before_it->node->prev;
2071    elm_box_pack_before(sd->box, VIEW(it), VIEW(before_it));
2072
2073    return (Elm_Object_Item *)it;
2074 }
2075
2076 EAPI Elm_Object_Item *
2077 elm_list_item_insert_after(Evas_Object *obj,
2078                            Elm_Object_Item *after,
2079                            const char *label,
2080                            Evas_Object *icon,
2081                            Evas_Object *end,
2082                            Evas_Smart_Cb func,
2083                            const void *data)
2084 {
2085    Elm_List_Item *it, *after_it;
2086
2087    ELM_LIST_CHECK(obj) NULL;
2088    ELM_LIST_ITEM_CHECK_OR_RETURN(after, NULL);
2089    ELM_LIST_DATA_GET(obj, sd);
2090
2091    after_it = (Elm_List_Item *)after;
2092    if (!after_it->node) return NULL;
2093
2094    it = _item_new(obj, label, icon, end, func, data);
2095    sd->items = eina_list_append_relative_list(sd->items, it, after_it->node);
2096    it->node = after_it->node->next;
2097    elm_box_pack_after(sd->box, VIEW(it), VIEW(after_it));
2098
2099    return (Elm_Object_Item *)it;
2100 }
2101
2102 EAPI Elm_Object_Item *
2103 elm_list_item_sorted_insert(Evas_Object *obj,
2104                             const char *label,
2105                             Evas_Object *icon,
2106                             Evas_Object *end,
2107                             Evas_Smart_Cb func,
2108                             const void *data,
2109                             Eina_Compare_Cb cmp_func)
2110 {
2111    Eina_List *l;
2112    Elm_List_Item *it;
2113
2114    ELM_LIST_CHECK(obj) NULL;
2115    ELM_LIST_DATA_GET(obj, sd);
2116
2117    it = _item_new(obj, label, icon, end, func, data);
2118
2119    sd->items = eina_list_sorted_insert(sd->items, cmp_func, it);
2120    l = eina_list_data_find_list(sd->items, it);
2121    l = eina_list_next(l);
2122    if (!l)
2123      {
2124         it->node = eina_list_last(sd->items);
2125         elm_box_pack_end(sd->box, VIEW(it));
2126      }
2127    else
2128      {
2129         Elm_List_Item *before = eina_list_data_get(l);
2130
2131         it->node = before->node->prev;
2132         elm_box_pack_before(sd->box, VIEW(it), VIEW(before));
2133      }
2134
2135    return (Elm_Object_Item *)it;
2136 }
2137
2138 EAPI void
2139 elm_list_item_separator_set(Elm_Object_Item *it,
2140                             Eina_Bool setting)
2141 {
2142    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
2143
2144    ((Elm_List_Item *)it)->is_separator = !!setting;
2145 }
2146
2147 EAPI Eina_Bool
2148 elm_list_item_separator_get(const Elm_Object_Item *it)
2149 {
2150    ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2151
2152    return ((Elm_List_Item *)it)->is_separator;
2153 }
2154
2155 EAPI void
2156 elm_list_item_selected_set(Elm_Object_Item *it,
2157                            Eina_Bool selected)
2158 {
2159    Elm_List_Item *item = (Elm_List_Item *)it;
2160    Evas_Object *obj;
2161
2162    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
2163    obj = WIDGET(it);
2164    ELM_LIST_DATA_GET(obj, sd);
2165
2166    selected = !!selected;
2167    if (item->selected == selected) return;
2168
2169    evas_object_ref(obj);
2170    _elm_list_walk(sd);
2171
2172    if (selected)
2173      {
2174         if (!sd->multi)
2175           {
2176              while (sd->selected)
2177                _item_unselect(sd->selected->data);
2178           }
2179         _item_highlight(item);
2180         _item_select(item);
2181      }
2182    else
2183      _item_unselect(item);
2184
2185    _elm_list_unwalk(sd);
2186    evas_object_unref(obj);
2187 }
2188
2189 EAPI Eina_Bool
2190 elm_list_item_selected_get(const Elm_Object_Item *it)
2191 {
2192    ELM_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2193
2194    return ((Elm_List_Item *)it)->selected;
2195 }
2196
2197 EAPI void
2198 elm_list_item_show(Elm_Object_Item *it)
2199 {
2200    Evas_Coord bx, by, bw, bh;
2201    Evas_Coord x, y, w, h;
2202
2203    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
2204    ELM_LIST_DATA_GET(WIDGET(it), sd);
2205
2206    evas_smart_objects_calculate(evas_object_evas_get(sd->box));
2207    evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh);
2208    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
2209    x -= bx;
2210    y -= by;
2211
2212    sd->s_iface->content_region_show(WIDGET(it), x, y, w, h);
2213 }
2214
2215 EAPI void
2216 elm_list_item_bring_in(Elm_Object_Item *it)
2217 {
2218    Evas_Coord bx, by, bw, bh;
2219    Evas_Coord x, y, w, h;
2220
2221    ELM_LIST_ITEM_CHECK_OR_RETURN(it);
2222    ELM_LIST_DATA_GET(WIDGET(it), sd);
2223
2224    evas_smart_objects_calculate(evas_object_evas_get(sd->box));
2225    evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh);
2226    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
2227    x -= bx;
2228    y -= by;
2229
2230    sd->s_iface->region_bring_in(WIDGET(it), x, y, w, h);
2231 }
2232
2233 EAPI Evas_Object *
2234 elm_list_item_object_get(const Elm_Object_Item *it)
2235 {
2236    ELM_LIST_ITEM_CHECK_OR_RETURN(it, NULL);
2237
2238    return VIEW(it);
2239 }
2240
2241 EAPI Elm_Object_Item *
2242 elm_list_item_prev(const Elm_Object_Item *it)
2243 {
2244    Elm_List_Item *item = (Elm_List_Item *)it;
2245
2246    ELM_LIST_ITEM_CHECK_OR_RETURN(it, NULL);
2247
2248    if (item->node->prev) return item->node->prev->data;
2249    else return NULL;
2250 }
2251
2252 EAPI Elm_Object_Item *
2253 elm_list_item_next(const Elm_Object_Item *it)
2254 {
2255    Elm_List_Item *item = (Elm_List_Item *)it;
2256
2257    ELM_LIST_ITEM_CHECK_OR_RETURN(it, NULL);
2258
2259    if (item->node->next) return item->node->next->data;
2260    else return NULL;
2261 }
2262
2263 EAPI Elm_Object_Item *
2264 elm_list_first_item_get(const Evas_Object *obj)
2265 {
2266    ELM_LIST_CHECK(obj) NULL;
2267    ELM_LIST_DATA_GET(obj, sd);
2268
2269    if (!sd->items) return NULL;
2270
2271    return eina_list_data_get(sd->items);
2272 }
2273
2274 EAPI Elm_Object_Item *
2275 elm_list_last_item_get(const Evas_Object *obj)
2276 {
2277    ELM_LIST_CHECK(obj) NULL;
2278    ELM_LIST_DATA_GET(obj, sd);
2279
2280    if (!sd->items) return NULL;
2281
2282    return eina_list_data_get(eina_list_last(sd->items));
2283 }