elementary: improve rendering stability by ordering queue like the displayed list.
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2 #include <fnmatch.h>
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_genlist.h"
8
9 #define MAX_ITEMS_PER_BLOCK 32
10 #define REORDER_EFFECT_TIME 0.5
11
12 #define ELM_GEN_SETUP(wd) \
13    (wd)->calc_cb = (Ecore_Cb)_calc_job; \
14    (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
15    (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
16
17 #define ELM_GEN_ITEM_SETUP(it) \
18    (it)->del_cb = (Ecore_Cb)_item_del; \
19    (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
20    (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
21    (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
22    (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
23
24 typedef struct _Item_Block  Item_Block;
25 typedef struct _Item_Cache  Item_Cache;
26
27 struct Elm_Gen_Item_Type
28 {
29    Elm_Gen_Item                 *it;
30    Item_Block                   *block;
31    Eina_List                    *items;
32    Evas_Coord                    w, h, minw, minh;
33    Elm_Gen_Item                 *group_item;
34    Elm_Genlist_Item_Flags        flags;
35    Eina_List                    *mode_labels, *mode_contents, *mode_states, *mode_content_objs;
36    Ecore_Timer                  *swipe_timer;
37    Evas_Coord                    scrl_x, scrl_y, old_scrl_y;
38
39    Elm_Gen_Item                 *rel;
40    Evas_Object                  *mode_view;
41    int                           expanded_depth;
42    int                           order_num_in;
43
44    Eina_Bool                     before : 1;
45
46    Eina_Bool                     want_realize : 1;
47    Eina_Bool                     expanded : 1;
48    Eina_Bool                     mincalcd : 1;
49    Eina_Bool                     queued : 1;
50    Eina_Bool                     showme : 1;
51    Eina_Bool                     updateme : 1;
52    Eina_Bool                     nocache : 1;
53    Eina_Bool                     stacking_even : 1;
54    Eina_Bool                     nostacking : 1;
55    Eina_Bool                     move_effect_enabled : 1;
56 };
57
58 struct _Item_Block
59 {
60    EINA_INLIST;
61    int          count;
62    int          num;
63    int          reorder_offset;
64    Widget_Data *wd;
65    Eina_List   *items;
66    Evas_Coord   x, y, w, h, minw, minh;
67    Eina_Bool    want_unrealize : 1;
68    Eina_Bool    realized : 1;
69    Eina_Bool    changed : 1;
70    Eina_Bool    updateme : 1;
71    Eina_Bool    showme : 1;
72    Eina_Bool    must_recalc : 1;
73 };
74
75 struct _Item_Cache
76 {
77    EINA_INLIST;
78
79    Evas_Object *base_view, *spacer;
80
81    const char  *item_style; // it->itc->item_style
82    Eina_Bool    tree : 1; // it->group
83    Eina_Bool    compress : 1; // it->wd->compress
84
85    Eina_Bool    selected : 1; // it->selected
86    Eina_Bool    disabled : 1; // it->disabled
87    Eina_Bool    expanded : 1; // it->item->expanded
88 };
89
90 static const char *widtype = NULL;
91 static void      _item_cache_zero(Widget_Data *wd);
92 static void      _del_hook(Evas_Object *obj);
93 static void      _mirrored_set(Evas_Object *obj,
94                                Eina_Bool    rtl);
95 static void      _theme_hook(Evas_Object *obj);
96 static void      _show_region_hook(void        *data,
97                                    Evas_Object *obj);
98 static void      _sizing_eval(Evas_Object *obj);
99 static void      _item_realize(Elm_Gen_Item *it,
100                                int               in,
101                                Eina_Bool         calc);
102 static void      _item_unrealize_cb(Elm_Gen_Item *it);
103 static void      _item_block_unrealize(Item_Block *itb);
104 static void      _calc_job(void *data);
105 static void      _on_focus_hook(void        *data,
106                                 Evas_Object *obj);
107 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
108 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
109 static Eina_Bool _item_single_select_up(Widget_Data *wd);
110 static Eina_Bool _item_single_select_down(Widget_Data *wd);
111 static Eina_Bool _event_hook(Evas_Object       *obj,
112                              Evas_Object       *src,
113                              Evas_Callback_Type type,
114                              void              *event_info);
115 static void      _signal_emit_hook(Evas_Object *obj,
116                                    const char *emission,
117                                    const char *source);
118 static Eina_Bool _deselect_all_items(Widget_Data *wd);
119 static void      _pan_calculate(Evas_Object *obj);
120 static void      _pan_max_get(Evas_Object *obj,
121                               Evas_Coord  *x,
122                               Evas_Coord  *y);
123 static void      _item_position(Elm_Gen_Item *it,
124                                 Evas_Object      *obj,
125                                 Evas_Coord        it_x,
126                                 Evas_Coord        it_y);
127 static void      _mode_item_realize(Elm_Gen_Item *it);
128 static void      _mode_item_unrealize(Elm_Gen_Item *it);
129 static void      _item_mode_set(Elm_Gen_Item *it);
130 static void      _item_mode_unset(Widget_Data *wd);
131 static void      _group_items_recalc(void *data);
132 static void      _item_move_after(Elm_Gen_Item *it,
133                                   Elm_Gen_Item *after);
134 static void      _item_move_before(Elm_Gen_Item *it,
135                                    Elm_Gen_Item *before);
136 static void      _item_auto_scroll(Widget_Data *wd);
137 static void      _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby);
138
139 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
140
141 static const char SIG_ACTIVATED[] = "activated";
142 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
143 static const char SIG_SELECTED[] = "selected";
144 static const char SIG_UNSELECTED[] = "unselected";
145 static const char SIG_EXPANDED[] = "expanded";
146 static const char SIG_CONTRACTED[] = "contracted";
147 static const char SIG_EXPAND_REQUEST[] = "expand,request";
148 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
149 static const char SIG_REALIZED[] = "realized";
150 static const char SIG_UNREALIZED[] = "unrealized";
151 static const char SIG_DRAG_START_UP[] = "drag,start,up";
152 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
153 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
154 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
155 static const char SIG_DRAG_STOP[] = "drag,stop";
156 static const char SIG_DRAG[] = "drag";
157 static const char SIG_LONGPRESSED[] = "longpressed";
158 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
159 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
160 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
161 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
162 static const char SIG_EDGE_TOP[] = "edge,top";
163 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
164 static const char SIG_EDGE_LEFT[] = "edge,left";
165 static const char SIG_EDGE_RIGHT[] = "edge,right";
166 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
167 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
168 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
169 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
170 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
171 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
172 static const char SIG_SWIPE[] = "swipe";
173 static const char SIG_MOVED[] = "moved";
174
175 static const Evas_Smart_Cb_Description _signals[] = {
176    {SIG_CLICKED_DOUBLE, ""},
177    {SIG_ACTIVATED, ""},
178    {SIG_SELECTED, ""},
179    {SIG_UNSELECTED, ""},
180    {SIG_EXPANDED, ""},
181    {SIG_CONTRACTED, ""},
182    {SIG_EXPAND_REQUEST, ""},
183    {SIG_CONTRACT_REQUEST, ""},
184    {SIG_REALIZED, ""},
185    {SIG_UNREALIZED, ""},
186    {SIG_DRAG_START_UP, ""},
187    {SIG_DRAG_START_DOWN, ""},
188    {SIG_DRAG_START_LEFT, ""},
189    {SIG_DRAG_START_RIGHT, ""},
190    {SIG_DRAG_STOP, ""},
191    {SIG_DRAG, ""},
192    {SIG_LONGPRESSED, ""},
193    {SIG_SCROLL_ANIM_START, ""},
194    {SIG_SCROLL_ANIM_STOP, ""},
195    {SIG_SCROLL_DRAG_START, ""},
196    {SIG_SCROLL_DRAG_STOP, ""},
197    {SIG_EDGE_TOP, ""},
198    {SIG_EDGE_BOTTOM, ""},
199    {SIG_EDGE_LEFT, ""},
200    {SIG_EDGE_RIGHT, ""},
201    {SIG_MULTI_SWIPE_LEFT, ""},
202    {SIG_MULTI_SWIPE_RIGHT, ""},
203    {SIG_MULTI_SWIPE_UP, ""},
204    {SIG_MULTI_SWIPE_DOWN, ""},
205    {SIG_MULTI_PINCH_OUT, ""},
206    {SIG_MULTI_PINCH_IN, ""},
207    {SIG_SWIPE, ""},
208    {SIG_MOVED, ""},
209    {NULL, NULL}
210 };
211
212 static Eina_Compare_Cb _elm_genlist_item_compare_cb;
213 static Eina_Compare_Cb _elm_genlist_item_compare_data_cb;
214
215 /* TEMPORARY */
216 #undef ELM_CHECK_WIDTYPE
217 #define ELM_CHECK_WIDTYPE(obj, widtype) \
218    if ((!obj) || (!elm_genlist_type_check((obj), __func__))) return
219 #undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
220 #define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
221    ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
222    ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
223
224 static const char *_gengrid = NULL;
225 static const char *_genlist = NULL;
226
227 /* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
228 Eina_Bool
229 elm_genlist_type_check(const Evas_Object *obj,
230                        const char        *func)
231 {
232    const char *provided, *expected = "(unknown)";
233    static int abort_on_warn = -1;
234    provided = elm_widget_type_get(obj);
235    if (!_genlist) _genlist = eina_stringshare_add("genlist");
236    if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
237    if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
238      return EINA_TRUE;
239    if ((!provided) || (!provided[0]))
240      {
241         provided = evas_object_type_get(obj);
242         if ((!provided) || (!provided[0]))
243           provided = "(unknown)";
244      }
245    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
246    if (abort_on_warn == -1)
247      {
248         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
249         else abort_on_warn = 0;
250      }
251    if (abort_on_warn == 1) abort();
252    return EINA_FALSE;
253 }
254
255 static Eina_Bool
256 _event_hook(Evas_Object       *obj,
257             Evas_Object       *src __UNUSED__,
258             Evas_Callback_Type type,
259             void              *event_info)
260 {
261    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
262    Evas_Event_Key_Down *ev = event_info;
263    Widget_Data *wd = elm_widget_data_get(obj);
264    Evas_Coord pan_max_x = 0, pan_max_y = 0;
265    if (!wd) return EINA_FALSE;
266    if (!wd->items) return EINA_FALSE;
267    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
268    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
269
270    Elm_Gen_Item *it = NULL;
271    Evas_Coord x = 0;
272    Evas_Coord y = 0;
273    Evas_Coord step_x = 0;
274    Evas_Coord step_y = 0;
275    Evas_Coord v_w = 0;
276    Evas_Coord v_h = 0;
277    Evas_Coord page_x = 0;
278    Evas_Coord page_y = 0;
279
280    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
281    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
282    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
283    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
284
285    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
286      {
287         x -= step_x;
288      }
289    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
290      {
291         x += step_x;
292      }
293    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
294      {
295         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
296              (_item_multi_select_up(wd)))
297             || (_item_single_select_up(wd)))
298           {
299              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
300              return EINA_TRUE;
301           }
302         else
303           y -= step_y;
304      }
305    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
306      {
307         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
308              (_item_multi_select_down(wd)))
309             || (_item_single_select_down(wd)))
310           {
311              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
312              return EINA_TRUE;
313           }
314         else
315           y += step_y;
316      }
317    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
318      {
319         it = elm_genlist_first_item_get(obj);
320         elm_genlist_item_bring_in(it);
321         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
322         return EINA_TRUE;
323      }
324    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
325      {
326         it = elm_genlist_last_item_get(obj);
327         elm_genlist_item_bring_in(it);
328         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
329         return EINA_TRUE;
330      }
331    else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
332      {
333         if (page_y < 0)
334           y -= -(page_y * v_h) / 100;
335         else
336           y -= page_y;
337      }
338    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
339      {
340         if (page_y < 0)
341           y += -(page_y * v_h) / 100;
342         else
343           y += page_y;
344      }
345    else if (!strcmp(ev->keyname, "Escape"))
346      {
347         if (!_deselect_all_items(wd)) return EINA_FALSE;
348         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
349         return EINA_TRUE;
350      }
351    else if (((!strcmp(ev->keyname, "Return")) ||
352             (!strcmp(ev->keyname, "KP_Enter")) ||
353             (!strcmp(ev->keyname, "space")))
354            && (!wd->multi) && (wd->selected))
355      {
356         it = elm_genlist_selected_item_get(obj);
357         elm_genlist_item_expanded_set(it,
358                                       !elm_genlist_item_expanded_get(it));
359         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
360      }
361    else return EINA_FALSE;
362
363    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
364    _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
365    if (x < 0) x = 0;
366    if (x > pan_max_x) x = pan_max_x;
367    if (y < 0) y = 0;
368    if (y > pan_max_y) y = pan_max_y;
369    elm_smart_scroller_child_pos_set(wd->scr, x, y);
370    return EINA_TRUE;
371 }
372
373 static Eina_Bool
374 _deselect_all_items(Widget_Data *wd)
375 {
376    if (!wd->selected) return EINA_FALSE;
377    while (wd->selected)
378      elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
379
380    return EINA_TRUE;
381 }
382
383 static Eina_Bool
384 _item_multi_select_up(Widget_Data *wd)
385 {
386    if (!wd->selected) return EINA_FALSE;
387    if (!wd->multi) return EINA_FALSE;
388
389    Elm_Gen_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
390    if (!prev) return EINA_TRUE;
391
392    if (elm_genlist_item_selected_get(prev))
393      {
394         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
395         wd->last_selected_item = prev;
396         elm_genlist_item_show(wd->last_selected_item);
397      }
398    else
399      {
400         elm_genlist_item_selected_set(prev, EINA_TRUE);
401         elm_genlist_item_show(prev);
402      }
403    return EINA_TRUE;
404 }
405
406 static Eina_Bool
407 _item_multi_select_down(Widget_Data *wd)
408 {
409    if (!wd->selected) return EINA_FALSE;
410    if (!wd->multi) return EINA_FALSE;
411
412    Elm_Gen_Item *next = elm_genlist_item_next_get(wd->last_selected_item);
413    if (!next) return EINA_TRUE;
414
415    if (elm_genlist_item_selected_get(next))
416      {
417         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
418         wd->last_selected_item = next;
419         elm_genlist_item_show(wd->last_selected_item);
420      }
421    else
422      {
423         elm_genlist_item_selected_set(next, EINA_TRUE);
424         elm_genlist_item_show(next);
425      }
426    return EINA_TRUE;
427 }
428
429 static Eina_Bool
430 _item_single_select_up(Widget_Data *wd)
431 {
432    Elm_Gen_Item *prev;
433    if (!wd->selected)
434      {
435         prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
436         while ((prev) && (prev->generation < wd->generation))
437           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
438      }
439    else prev = elm_genlist_item_prev_get(wd->last_selected_item);
440
441    if (!prev) return EINA_FALSE;
442
443    _deselect_all_items(wd);
444
445    elm_genlist_item_selected_set(prev, EINA_TRUE);
446    elm_genlist_item_show(prev);
447    return EINA_TRUE;
448 }
449
450 static Eina_Bool
451 _item_single_select_down(Widget_Data *wd)
452 {
453    Elm_Gen_Item *next;
454    if (!wd->selected)
455      {
456         next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
457         while ((next) && (next->generation < wd->generation))
458           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
459      }
460    else next = elm_genlist_item_next_get(wd->last_selected_item);
461
462    if (!next) return EINA_FALSE;
463
464    _deselect_all_items(wd);
465
466    elm_genlist_item_selected_set(next, EINA_TRUE);
467    elm_genlist_item_show(next);
468    return EINA_TRUE;
469 }
470
471 static void
472 _on_focus_hook(void        *data __UNUSED__,
473                Evas_Object *obj)
474 {
475    Widget_Data *wd = elm_widget_data_get(obj);
476    if (!wd) return;
477    if (elm_widget_focus_get(obj))
478      {
479         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
480         evas_object_focus_set(wd->obj, EINA_TRUE);
481         if ((wd->selected) && (!wd->last_selected_item))
482           wd->last_selected_item = eina_list_data_get(wd->selected);
483      }
484    else
485      {
486         elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
487         evas_object_focus_set(wd->obj, EINA_FALSE);
488      }
489 }
490
491 static void
492 _del_hook(Evas_Object *obj)
493 {
494    Widget_Data *wd = elm_widget_data_get(obj);
495    if (!wd) return;
496    _item_cache_zero(wd);
497    if (wd->calc_job) ecore_job_del(wd->calc_job);
498    if (wd->update_job) ecore_job_del(wd->update_job);
499    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
500    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
501    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
502    if (wd->mode_type) eina_stringshare_del(wd->mode_type);
503    if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
504    free(wd);
505 }
506
507 static void
508 _del_pre_hook(Evas_Object *obj)
509 {
510    Widget_Data *wd = elm_widget_data_get(obj);
511    if (!wd) return;
512    elm_genlist_clear(obj);
513    evas_object_del(wd->pan_smart);
514    wd->pan_smart = NULL;
515 }
516
517 static void
518 _mirrored_set(Evas_Object *obj,
519               Eina_Bool    rtl)
520 {
521    Widget_Data *wd = elm_widget_data_get(obj);
522    if (!wd) return;
523    _item_cache_zero(wd);
524    elm_smart_scroller_mirrored_set(wd->scr, rtl);
525 }
526
527 static void
528 _theme_hook(Evas_Object *obj)
529 {
530    Widget_Data *wd = elm_widget_data_get(obj);
531    Item_Block *itb;
532    if (!wd) return;
533    evas_event_freeze(evas_object_evas_get(wd->obj));
534    _item_cache_zero(wd);
535    _elm_widget_mirrored_reload(obj);
536    _mirrored_set(obj, elm_widget_mirrored_get(obj));
537    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
538                                        elm_widget_style_get(obj));
539    edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
540    wd->item_width = wd->item_height = 0;
541    wd->group_item_width = wd->group_item_height = 0;
542    wd->minw = wd->minh = wd->realminw = 0;
543    EINA_INLIST_FOREACH(wd->blocks, itb)
544      {
545         Eina_List *l;
546         Elm_Gen_Item *it;
547
548         if (itb->realized) _item_block_unrealize(itb);
549         EINA_LIST_FOREACH(itb->items, l, it)
550           it->item->mincalcd = EINA_FALSE;
551
552         itb->changed = EINA_TRUE;
553      }
554    if (wd->calc_job) ecore_job_del(wd->calc_job);
555    wd->calc_job = ecore_job_add(_calc_job, wd);
556    _sizing_eval(obj);
557    evas_event_thaw(evas_object_evas_get(wd->obj));
558    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
559 }
560
561 static void
562 _show_region_hook(void        *data,
563                   Evas_Object *obj)
564 {
565    Widget_Data *wd = elm_widget_data_get(data);
566    Evas_Coord x, y, w, h;
567    if (!wd) return;
568    elm_widget_show_region_get(obj, &x, &y, &w, &h);
569    //x & y are screen coordinates, Add with pan coordinates
570    x += wd->pan_x;
571    y += wd->pan_y;
572    elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
573 }
574
575 static void
576 _translate_hook(Evas_Object *obj)
577 {
578    evas_object_smart_callback_call(obj, "language,changed", NULL);
579 }
580
581 static void
582 _sizing_eval(Evas_Object *obj)
583 {
584    Widget_Data *wd = elm_widget_data_get(obj);
585    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
586    if (!wd) return;
587    evas_object_size_hint_min_get(wd->scr, &minw, &minh);
588    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
589    minh = -1;
590    if (wd->height_for_width)
591      {
592         Evas_Coord vw, vh;
593
594         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
595         if ((vw != 0) && (vw != wd->prev_viewport_w))
596           {
597              Item_Block *itb;
598
599              wd->prev_viewport_w = vw;
600              EINA_INLIST_FOREACH(wd->blocks, itb)
601                {
602                   itb->must_recalc = EINA_TRUE;
603                }
604              if (wd->calc_job) ecore_job_del(wd->calc_job);
605              wd->calc_job = ecore_job_add(_calc_job, wd);
606           }
607      }
608    if (wd->mode == ELM_LIST_LIMIT)
609      {
610         Evas_Coord vmw, vmh;
611
612         minw = wd->realminw;
613         maxw = -1;
614         edje_object_size_min_calc
615           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
616         minw = vmw + minw;
617      }
618    else
619      {
620         Evas_Coord vmw, vmh;
621
622         edje_object_size_min_calc
623           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
624         minw = vmw;
625         minh = vmh;
626      }
627    evas_object_size_hint_min_set(obj, minw, minh);
628    evas_object_size_hint_max_set(obj, maxw, maxh);
629 }
630
631 static void
632 _signal_emit_hook(Evas_Object *obj,
633                   const char  *emission,
634                   const char  *source)
635 {
636    Widget_Data *wd = elm_widget_data_get(obj);
637    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
638                            emission, source);
639 }
640
641 static void
642 _item_highlight(Elm_Gen_Item *it)
643 {
644    const char *selectraise;
645    if ((it->wd->no_select) || (it->generation < it->wd->generation) || (it->highlighted) ||
646        (it->disabled) || (it->display_only) || (it->item->mode_view))
647      return;
648    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
649    selectraise = edje_object_data_get(VIEW(it), "selectraise");
650    if ((selectraise) && (!strcmp(selectraise, "on")))
651      {
652         evas_object_raise(VIEW(it));
653         if ((it->item->group_item) && (it->item->group_item->realized))
654           evas_object_raise(it->item->VIEW(group_item));
655      }
656    it->highlighted = EINA_TRUE;
657 }
658
659 static void
660 _item_unhighlight(Elm_Gen_Item *it)
661 {
662    if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
663    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
664    if (!it->item->nostacking)
665      {
666        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even) evas_object_lower(VIEW(it));
667        else evas_object_raise(VIEW(it));
668      }
669    it->highlighted = EINA_FALSE;
670 }
671
672 static void
673 _item_block_del(Elm_Gen_Item *it)
674 {
675    Eina_Inlist *il;
676    Item_Block *itb = it->item->block;
677
678    itb->items = eina_list_remove(itb->items, it);
679    itb->count--;
680    itb->changed = EINA_TRUE;
681    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
682    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
683    if (itb->count < 1)
684      {
685         il = EINA_INLIST_GET(itb);
686         Item_Block *itbn = (Item_Block *)(il->next);
687         if (it->parent)
688           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
689         else
690           it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
691         free(itb);
692         if (itbn) itbn->changed = EINA_TRUE;
693      }
694    else
695      {
696         if (itb->count < itb->wd->max_items_per_block/2)
697           {
698              il = EINA_INLIST_GET(itb);
699              Item_Block *itbp = (Item_Block *)(il->prev);
700              Item_Block *itbn = (Item_Block *)(il->next);
701              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
702                {
703                   Elm_Gen_Item *it2;
704
705                   EINA_LIST_FREE(itb->items, it2)
706                     {
707                        it2->item->block = itbp;
708                        itbp->items = eina_list_append(itbp->items, it2);
709                        itbp->count++;
710                        itbp->changed = EINA_TRUE;
711                     }
712                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
713                                                       EINA_INLIST_GET(itb));
714                   free(itb);
715                }
716              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
717                {
718                   while (itb->items)
719                     {
720                        Eina_List *last = eina_list_last(itb->items);
721                        Elm_Gen_Item *it2 = last->data;
722
723                        it2->item->block = itbn;
724                        itb->items = eina_list_remove_list(itb->items, last);
725                        itbn->items = eina_list_prepend(itbn->items, it2);
726                        itbn->count++;
727                        itbn->changed = EINA_TRUE;
728                     }
729                   it->wd->blocks =
730                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
731                   free(itb);
732                }
733           }
734      }
735 }
736
737 static void
738 _item_del(Elm_Gen_Item *it)
739 {
740    Evas_Object *obj = WIDGET(it);
741
742    evas_event_freeze(evas_object_evas_get(obj));
743    elm_genlist_item_subitems_clear(it);
744    if (it->wd->show_item == it) it->wd->show_item = NULL;
745    if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
746    if (it->item->block) _item_block_del(it);
747    if (it->item->queued)
748      it->wd->queue = eina_list_remove(it->wd->queue, it);
749    if (it->wd->anchor_item == it)
750      {
751         it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
752         if (!it->wd->anchor_item)
753           it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
754      }
755    if (it->parent)
756      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
757    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
758    _elm_genlist_item_del_serious(it);
759    evas_event_thaw(evas_object_evas_get(obj));
760    evas_event_thaw_eval(evas_object_evas_get(obj));
761 }
762
763 static void
764 _clear_cb(Widget_Data *wd)
765 {
766    wd->anchor_item = NULL;
767    while (wd->blocks)
768      {
769         Item_Block *itb = (Item_Block *)(wd->blocks);
770
771         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
772         if (itb->items) eina_list_free(itb->items);
773         free(itb);
774      }
775    if (wd->queue_idle_enterer)
776      {
777         ecore_idle_enterer_del(wd->queue_idle_enterer);
778         wd->queue_idle_enterer = NULL;
779      }
780    if (wd->must_recalc_idler)
781      {
782         ecore_idler_del(wd->must_recalc_idler);
783         wd->must_recalc_idler = NULL;
784      }
785    if (wd->queue) wd->queue = eina_list_free(wd->queue);
786    if (wd->reorder_move_animator)
787      {
788         ecore_animator_del(wd->reorder_move_animator);
789         wd->reorder_move_animator = NULL;
790      }
791    wd->show_item = NULL;
792    wd->reorder_old_pan_y = 0;
793 }
794
795 static void
796 _item_unselect(Elm_Gen_Item *it)
797 {
798    if ((it->generation < it->wd->generation) || (!it->selected)) return;
799    it->selected = EINA_FALSE;
800    it->wd->selected = eina_list_remove(it->wd->selected, it);
801    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
802 }
803
804 static void
805 _mouse_move(void        *data,
806             Evas        *evas __UNUSED__,
807             Evas_Object *obj,
808             void        *event_info)
809 {
810    Elm_Gen_Item *it = data;
811    Evas_Event_Mouse_Move *ev = event_info;
812    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
813    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
814
815    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
816      {
817         if (!it->wd->on_hold)
818           {
819              it->wd->on_hold = EINA_TRUE;
820              if (!it->wd->wasselected)
821                {
822                   _item_unhighlight(it);
823                   _item_unselect(it);
824                }
825           }
826      }
827    if (it->wd->multitouched)
828      {
829         it->wd->cur_x = ev->cur.canvas.x;
830         it->wd->cur_y = ev->cur.canvas.y;
831         return;
832      }
833    if ((it->dragging) && (it->down))
834      {
835         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
836         else
837           {
838              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
839              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
840              if (abs((it->wd->history[it->wd->movements].x -
841                       it->wd->history[0].x)) > 40)
842                it->wd->swipe = EINA_TRUE;
843              else
844                it->wd->movements++;
845           }
846         if (it->long_timer)
847           {
848              ecore_timer_del(it->long_timer);
849              it->long_timer = NULL;
850           }
851         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
852         return;
853      }
854    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
855      {
856         if (it->long_timer)
857           {
858              ecore_timer_del(it->long_timer);
859              it->long_timer = NULL;
860           }
861         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
862           {
863              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
864              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
865
866              if (!it->wd->reorder_start_y)
867                it->wd->reorder_start_y = it->item->block->y + it->y;
868
869              if (it_scrl_y < oy)
870                y_pos = oy;
871              else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
872                y_pos = oy + oh - it->wd->reorder_it->item->h;
873              else
874                y_pos = it_scrl_y;
875
876              _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
877
878              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
879              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
880           }
881         return;
882      }
883    if (!it->display_only)
884      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
885    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
886    x = ev->cur.canvas.x - x;
887    y = ev->cur.canvas.y - y;
888    dx = x - it->dx;
889    adx = dx;
890    if (adx < 0) adx = -dx;
891    dy = y - it->dy;
892    ady = dy;
893    if (ady < 0) ady = -dy;
894    minw /= 2;
895    minh /= 2;
896    if ((adx > minw) || (ady > minh))
897      {
898         it->dragging = EINA_TRUE;
899         if (it->long_timer)
900           {
901              ecore_timer_del(it->long_timer);
902              it->long_timer = NULL;
903           }
904         if (!it->wd->wasselected)
905           {
906              _item_unhighlight(it);
907              _item_unselect(it);
908           }
909         if (dy < 0)
910           {
911              if (ady > adx)
912                evas_object_smart_callback_call(WIDGET(it),
913                                                SIG_DRAG_START_UP, it);
914              else
915                {
916                   if (dx < 0)
917                     evas_object_smart_callback_call(WIDGET(it),
918                                                     SIG_DRAG_START_LEFT, it);
919                   else
920                     evas_object_smart_callback_call(WIDGET(it),
921                                                     SIG_DRAG_START_RIGHT, it);
922                }
923           }
924         else
925           {
926              if (ady > adx)
927                evas_object_smart_callback_call(WIDGET(it),
928                                                SIG_DRAG_START_DOWN, it);
929              else
930                {
931                   if (dx < 0)
932                     evas_object_smart_callback_call(WIDGET(it),
933                                                     SIG_DRAG_START_LEFT, it);
934                   else
935                     evas_object_smart_callback_call(WIDGET(it),
936                                                     SIG_DRAG_START_RIGHT, it);
937                }
938           }
939      }
940 }
941
942 static Eina_Bool
943 _long_press(void *data)
944 {
945    Elm_Gen_Item *it = data, *it_tmp;
946    Eina_List *list, *l;
947
948    it->long_timer = NULL;
949    if ((it->disabled) || (it->dragging) || (it->display_only))
950      return ECORE_CALLBACK_CANCEL;
951    it->wd->longpressed = EINA_TRUE;
952    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
953    if ((it->wd->reorder_mode) && (!it->group))
954      {
955         it->wd->reorder_it = it;
956         it->wd->reorder_start_y = 0;
957
958         evas_object_raise(VIEW(it));
959         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
960         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
961
962         list = elm_genlist_realized_items_get(it->wd->obj);
963         EINA_LIST_FOREACH(list, l, it_tmp)
964           {
965              if (it != it_tmp) _item_unselect(it_tmp);
966           }
967         if (elm_genlist_item_expanded_get(it))
968           {
969              elm_genlist_item_expanded_set(it, EINA_FALSE);
970              return ECORE_CALLBACK_RENEW;
971           }
972         edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
973      }
974    return ECORE_CALLBACK_CANCEL;
975 }
976
977 static void
978 _swipe(Elm_Gen_Item *it)
979 {
980    int i, sum = 0;
981
982    if (!it) return;
983    if ((it->display_only) || (it->disabled)) return;
984    it->wd->swipe = EINA_FALSE;
985    for (i = 0; i < it->wd->movements; i++)
986      {
987         sum += it->wd->history[i].x;
988         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
989      }
990
991    sum /= it->wd->movements;
992    if (abs(sum - it->wd->history[0].x) <= 10) return;
993    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
994 }
995
996 static Eina_Bool
997 _swipe_cancel(void *data)
998 {
999    Elm_Gen_Item *it = data;
1000
1001    if (!it) return ECORE_CALLBACK_CANCEL;
1002    it->wd->swipe = EINA_FALSE;
1003    it->wd->movements = 0;
1004    return ECORE_CALLBACK_RENEW;
1005 }
1006
1007 static Eina_Bool
1008 _multi_cancel(void *data)
1009 {
1010    Widget_Data *wd = data;
1011
1012    if (!wd) return ECORE_CALLBACK_CANCEL;
1013    wd->multi_timeout = EINA_TRUE;
1014    return ECORE_CALLBACK_RENEW;
1015 }
1016
1017 static void
1018 _multi_touch_gesture_eval(void *data)
1019 {
1020    Elm_Gen_Item *it = data;
1021
1022    it->wd->multitouched = EINA_FALSE;
1023    if (it->wd->multi_timer)
1024      {
1025         ecore_timer_del(it->wd->multi_timer);
1026         it->wd->multi_timer = NULL;
1027      }
1028    if (it->wd->multi_timeout)
1029      {
1030         it->wd->multi_timeout = EINA_FALSE;
1031         return;
1032      }
1033
1034    Evas_Coord minw = 0, minh = 0;
1035    Evas_Coord off_x, off_y, off_mx, off_my;
1036
1037    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1038    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1039    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1040    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1041    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1042
1043    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1044      {
1045         if ((off_x + off_mx) > (off_y + off_my))
1046           {
1047              if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1048                evas_object_smart_callback_call(WIDGET(it),
1049                                                SIG_MULTI_SWIPE_RIGHT, it);
1050              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1051                evas_object_smart_callback_call(WIDGET(it),
1052                                                SIG_MULTI_SWIPE_LEFT, it);
1053              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1054                evas_object_smart_callback_call(WIDGET(it),
1055                                                SIG_MULTI_PINCH_OUT, it);
1056              else
1057                evas_object_smart_callback_call(WIDGET(it),
1058                                                SIG_MULTI_PINCH_IN, it);
1059           }
1060         else
1061           {
1062              if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1063                evas_object_smart_callback_call(WIDGET(it),
1064                                                SIG_MULTI_SWIPE_DOWN, it);
1065              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1066                evas_object_smart_callback_call(WIDGET(it),
1067                                                SIG_MULTI_SWIPE_UP, it);
1068              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1069                evas_object_smart_callback_call(WIDGET(it),
1070                                                SIG_MULTI_PINCH_OUT, it);
1071              else
1072                evas_object_smart_callback_call(WIDGET(it),
1073                                                SIG_MULTI_PINCH_IN, it);
1074           }
1075      }
1076    it->wd->multi_timeout = EINA_FALSE;
1077 }
1078
1079 static void
1080 _multi_down(void        *data,
1081             Evas        *evas __UNUSED__,
1082             Evas_Object *obj __UNUSED__,
1083             void        *event_info)
1084 {
1085    Elm_Gen_Item *it = data;
1086    Evas_Event_Multi_Down *ev = event_info;
1087
1088    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1089    it->wd->multi_device = ev->device;
1090    it->wd->multi_down = EINA_TRUE;
1091    it->wd->multitouched = EINA_TRUE;
1092    it->wd->prev_mx = ev->canvas.x;
1093    it->wd->prev_my = ev->canvas.y;
1094    if (!it->wd->wasselected)
1095      {
1096         _item_unhighlight(it);
1097         _item_unselect(it);
1098      }
1099    it->wd->wasselected = EINA_FALSE;
1100    it->wd->longpressed = EINA_FALSE;
1101    if (it->long_timer)
1102      {
1103         ecore_timer_del(it->long_timer);
1104         it->long_timer = NULL;
1105      }
1106    if (it->dragging)
1107      {
1108         it->dragging = EINA_FALSE;
1109         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1110      }
1111    if (it->item->swipe_timer)
1112      {
1113         ecore_timer_del(it->item->swipe_timer);
1114         it->item->swipe_timer = NULL;
1115      }
1116    if (it->wd->on_hold)
1117      {
1118         it->wd->swipe = EINA_FALSE;
1119         it->wd->movements = 0;
1120         it->wd->on_hold = EINA_FALSE;
1121      }
1122 }
1123
1124 static void
1125 _multi_up(void        *data,
1126           Evas        *evas __UNUSED__,
1127           Evas_Object *obj __UNUSED__,
1128           void        *event_info)
1129 {
1130    Elm_Gen_Item *it = data;
1131    Evas_Event_Multi_Up *ev = event_info;
1132
1133    if (it->wd->multi_device != ev->device) return;
1134    it->wd->multi_device = 0;
1135    it->wd->multi_down = EINA_FALSE;
1136    if (it->wd->mouse_down) return;
1137    _multi_touch_gesture_eval(data);
1138 }
1139
1140 static void
1141 _multi_move(void        *data,
1142             Evas        *evas __UNUSED__,
1143             Evas_Object *obj __UNUSED__,
1144             void        *event_info)
1145 {
1146    Elm_Gen_Item *it = data;
1147    Evas_Event_Multi_Move *ev = event_info;
1148
1149    if (it->wd->multi_device != ev->device) return;
1150    it->wd->cur_mx = ev->cur.canvas.x;
1151    it->wd->cur_my = ev->cur.canvas.y;
1152 }
1153
1154 static void
1155 _mouse_down(void        *data,
1156             Evas        *evas __UNUSED__,
1157             Evas_Object *obj,
1158             void        *event_info)
1159 {
1160    Elm_Gen_Item *it = data;
1161    Evas_Event_Mouse_Down *ev = event_info;
1162    Evas_Coord x, y;
1163
1164    if (ev->button != 1) return;
1165    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1166      {
1167         it->wd->on_hold = EINA_TRUE;
1168      }
1169
1170    it->down = EINA_TRUE;
1171    it->dragging = EINA_FALSE;
1172    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1173    it->dx = ev->canvas.x - x;
1174    it->dy = ev->canvas.y - y;
1175    it->wd->mouse_down = EINA_TRUE;
1176    if (!it->wd->multitouched)
1177      {
1178         it->wd->prev_x = ev->canvas.x;
1179         it->wd->prev_y = ev->canvas.y;
1180         it->wd->multi_timeout = EINA_FALSE;
1181         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1182         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1183      }
1184    it->wd->longpressed = EINA_FALSE;
1185    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1186    else it->wd->on_hold = EINA_FALSE;
1187    if (it->wd->on_hold) return;
1188    it->wd->wasselected = it->selected;
1189    _item_highlight(it);
1190    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1191      if ((!it->disabled) && (!it->display_only))
1192        {
1193           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1194           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1195        }
1196    if (it->long_timer) ecore_timer_del(it->long_timer);
1197    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1198    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1199    if (it->realized)
1200      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1201                                       it);
1202    else
1203      it->long_timer = NULL;
1204    it->wd->swipe = EINA_FALSE;
1205    it->wd->movements = 0;
1206 }
1207
1208 static void
1209 _mouse_up(void        *data,
1210           Evas        *evas __UNUSED__,
1211           Evas_Object *obj __UNUSED__,
1212           void        *event_info)
1213 {
1214    Elm_Gen_Item *it = data;
1215    Evas_Event_Mouse_Up *ev = event_info;
1216    Eina_Bool dragged = EINA_FALSE;
1217
1218    if (ev->button != 1) return;
1219    it->down = EINA_FALSE;
1220    it->wd->mouse_down = EINA_FALSE;
1221    if (it->wd->multitouched)
1222      {
1223         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1224         if (it->wd->multi_down) return;
1225         _multi_touch_gesture_eval(data);
1226         return;
1227      }
1228    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1229    else it->wd->on_hold = EINA_FALSE;
1230    if (it->long_timer)
1231      {
1232         ecore_timer_del(it->long_timer);
1233         it->long_timer = NULL;
1234      }
1235    if (it->dragging)
1236      {
1237         it->dragging = EINA_FALSE;
1238         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1239         dragged = 1;
1240      }
1241    if (it->item->swipe_timer)
1242      {
1243         ecore_timer_del(it->item->swipe_timer);
1244         it->item->swipe_timer = NULL;
1245      }
1246    if (it->wd->multi_timer)
1247      {
1248         ecore_timer_del(it->wd->multi_timer);
1249         it->wd->multi_timer = NULL;
1250         it->wd->multi_timeout = EINA_FALSE;
1251      }
1252    if (it->wd->on_hold)
1253      {
1254         if (it->wd->swipe) _swipe(data);
1255         it->wd->longpressed = EINA_FALSE;
1256         it->wd->on_hold = EINA_FALSE;
1257         return;
1258      }
1259    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1260      {
1261         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1262
1263         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1264           {
1265              if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1266                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1267              else
1268                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1269           }
1270         else
1271           {
1272              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1273              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1274           }
1275         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1276         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1277         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1278         elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1279      }
1280    if (it->wd->longpressed)
1281      {
1282         it->wd->longpressed = EINA_FALSE;
1283         if (!it->wd->wasselected)
1284           {
1285              _item_unhighlight(it);
1286              _item_unselect(it);
1287           }
1288         it->wd->wasselected = EINA_FALSE;
1289         return;
1290      }
1291    if (dragged)
1292      {
1293         if (it->want_unrealize)
1294           {
1295              _elm_genlist_item_unrealize(it, EINA_FALSE);
1296              if (it->item->block->want_unrealize)
1297                _item_block_unrealize(it->item->block);
1298           }
1299      }
1300    if ((it->disabled) || (dragged) || (it->display_only)) return;
1301    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1302    if (it->wd->multi)
1303      {
1304         if (!it->selected)
1305           {
1306              _item_highlight(it);
1307              it->sel_cb(it);
1308           }
1309         else
1310           {
1311              _item_unhighlight(it);
1312              _item_unselect(it);
1313           }
1314      }
1315    else
1316      {
1317         if (!it->selected)
1318           {
1319              Widget_Data *wd = it->wd;
1320              if (wd)
1321                {
1322                   while (wd->selected)
1323                     {
1324                        _item_unhighlight(wd->selected->data);
1325                        _item_unselect(wd->selected->data);
1326                     }
1327                }
1328           }
1329         else
1330           {
1331              const Eina_List *l, *l_next;
1332              Elm_Gen_Item *it2;
1333
1334              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1335                 if (it2 != it)
1336                   {
1337                      _item_unhighlight(it2);
1338                      _item_unselect(it2);
1339                   }
1340              //_item_highlight(it);
1341              //_item_select(it);
1342           }
1343         _item_highlight(it);
1344         it->sel_cb(it);
1345      }
1346 }
1347
1348 static void
1349 _signal_expand_toggle(void        *data,
1350                       Evas_Object *obj __UNUSED__,
1351                       const char  *emission __UNUSED__,
1352                       const char  *source __UNUSED__)
1353 {
1354    Elm_Gen_Item *it = data;
1355
1356    if (it->item->expanded)
1357      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1358    else
1359      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1360 }
1361
1362 static void
1363 _signal_expand(void        *data,
1364                Evas_Object *obj __UNUSED__,
1365                const char  *emission __UNUSED__,
1366                const char  *source __UNUSED__)
1367 {
1368    Elm_Gen_Item *it = data;
1369
1370    if (!it->item->expanded)
1371      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1372 }
1373
1374 static void
1375 _signal_contract(void        *data,
1376                  Evas_Object *obj __UNUSED__,
1377                  const char  *emission __UNUSED__,
1378                  const char  *source __UNUSED__)
1379 {
1380    Elm_Gen_Item *it = data;
1381
1382    if (it->item->expanded)
1383      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1384 }
1385
1386 static Eina_Bool
1387 _scr_hold_timer_cb(void *data)
1388 {
1389    if (!data) return ECORE_CALLBACK_CANCEL;
1390    Widget_Data *wd = data;
1391    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1392    wd->scr_hold_timer = NULL;
1393    return ECORE_CALLBACK_CANCEL;
1394 }
1395
1396 static void
1397 _mode_finished_signal_cb(void        *data,
1398                          Evas_Object *obj,
1399                          const char  *emission __UNUSED__,
1400                          const char  *source __UNUSED__)
1401 {
1402    if (!data) return;
1403    if (!obj) return;
1404    Elm_Gen_Item *it = data;
1405    if ((it->generation < it->wd->generation) || (!it->realized) || (!it->item->mode_view)) return;
1406    char buf[1024];
1407    Evas *te = evas_object_evas_get(obj);
1408
1409    evas_event_freeze(te);
1410    it->item->nocache = EINA_FALSE;
1411    _mode_item_unrealize(it);
1412    if (it->item->group_item)
1413      evas_object_raise(it->item->VIEW(group_item));
1414    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type);
1415    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1416    evas_event_thaw(te);
1417    evas_event_thaw_eval(te);
1418 }
1419
1420 static void
1421 _item_cache_clean(Widget_Data *wd)
1422 {
1423    evas_event_freeze(evas_object_evas_get(wd->obj));
1424    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1425      {
1426         Item_Cache *itc;
1427
1428         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1429         wd->item_cache = eina_inlist_remove(wd->item_cache,
1430                                             wd->item_cache->last);
1431         wd->item_cache_count--;
1432         if (itc->spacer) evas_object_del(itc->spacer);
1433         if (itc->base_view) evas_object_del(itc->base_view);
1434         if (itc->item_style) eina_stringshare_del(itc->item_style);
1435         free(itc);
1436      }
1437    evas_event_thaw(evas_object_evas_get(wd->obj));
1438    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1439 }
1440
1441 static void
1442 _item_cache_zero(Widget_Data *wd)
1443 {
1444    int pmax = wd->item_cache_max;
1445    wd->item_cache_max = 0;
1446    _item_cache_clean(wd);
1447    wd->item_cache_max = pmax;
1448 }
1449
1450 static void
1451 _item_cache_add(Elm_Gen_Item *it)
1452 {
1453    Item_Cache *itc;
1454
1455    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1456    if (it->wd->item_cache_max <= 0)
1457      {
1458         evas_object_del(VIEW(it));
1459         VIEW(it) = NULL;
1460         evas_object_del(it->spacer);
1461         it->spacer = NULL;
1462         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1463         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1464         return;
1465      }
1466
1467    it->wd->item_cache_count++;
1468    itc = calloc(1, sizeof(Item_Cache));
1469    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1470                                             EINA_INLIST_GET(itc));
1471    itc->spacer = it->spacer;
1472    it->spacer = NULL;
1473    itc->base_view = VIEW(it);
1474    VIEW(it) = NULL;
1475    evas_object_hide(itc->base_view);
1476    evas_object_move(itc->base_view, -9999, -9999);
1477    itc->item_style = eina_stringshare_add(it->itc->item_style);
1478    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) itc->tree = 1;
1479    itc->compress = (it->wd->compress);
1480    itc->selected = it->selected;
1481    itc->disabled = it->disabled;
1482    itc->expanded = it->item->expanded;
1483    if (it->long_timer)
1484      {
1485         ecore_timer_del(it->long_timer);
1486         it->long_timer = NULL;
1487      }
1488    if (it->item->swipe_timer)
1489      {
1490         ecore_timer_del(it->item->swipe_timer);
1491         it->item->swipe_timer = NULL;
1492      }
1493    // FIXME: other callbacks?
1494    edje_object_signal_callback_del_full(itc->base_view,
1495                                         "elm,action,expand,toggle",
1496                                         "elm", _signal_expand_toggle, it);
1497    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1498                                         "elm",
1499                                         _signal_expand, it);
1500    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1501                                         "elm", _signal_contract, it);
1502    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
1503                                        _mouse_down, it);
1504    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
1505                                        _mouse_up, it);
1506    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
1507                                        _mouse_move, it);
1508    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
1509                                        _multi_down, it);
1510    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
1511                                        _multi_up, it);
1512    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
1513                                        _multi_move, it);
1514    _item_cache_clean(it->wd);
1515    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1516    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1517 }
1518
1519 static Item_Cache *
1520 _item_cache_find(Elm_Gen_Item *it)
1521 {
1522    Item_Cache *itc;
1523    Eina_Bool tree = 0;
1524
1525    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) tree = 1;
1526    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1527      {
1528         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1529           continue;
1530         if ((itc->tree == tree) &&
1531             (itc->compress == it->wd->compress) &&
1532             (!strcmp(it->itc->item_style, itc->item_style)))
1533           {
1534              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1535                                                      EINA_INLIST_GET(itc));
1536              it->wd->item_cache_count--;
1537              return itc;
1538           }
1539      }
1540    return NULL;
1541 }
1542
1543 static void
1544 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1545 {
1546    if (!it->item->nostacking)
1547      {
1548         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1549           evas_object_lower(VIEW(it));
1550         else
1551           evas_object_raise(VIEW(it));
1552      }
1553
1554    if (it->item->order_num_in & 0x1)
1555      edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1556    else
1557      edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1558 }
1559
1560 static void
1561 _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1562 {
1563    if (itc)
1564      {
1565         if (it->selected != itc->selected)
1566           {
1567              if (it->selected)
1568                edje_object_signal_emit(VIEW(it),
1569                                        "elm,state,selected", "elm");
1570           }
1571         if (it->disabled != itc->disabled)
1572           {
1573              if (it->disabled)
1574                edje_object_signal_emit(VIEW(it),
1575                                        "elm,state,disabled", "elm");
1576           }
1577         if (it->item->expanded != itc->expanded)
1578           {
1579              if (it->item->expanded)
1580                edje_object_signal_emit(VIEW(it),
1581                                        "elm,state,expanded", "elm");
1582           }
1583      }
1584    else
1585      {
1586         if (it->selected)
1587           edje_object_signal_emit(VIEW(it),
1588                                   "elm,state,selected", "elm");
1589         if (it->disabled)
1590           edje_object_signal_emit(VIEW(it),
1591                                   "elm,state,disabled", "elm");
1592         if (it->item->expanded)
1593           edje_object_signal_emit(VIEW(it),
1594                                   "elm,state,expanded", "elm");
1595      }
1596 }
1597
1598 static void
1599 _item_cache_free(Item_Cache *itc)
1600 {
1601    if (itc->spacer) evas_object_del(itc->spacer);
1602    if (itc->base_view) evas_object_del(itc->base_view);
1603    if (itc->item_style) eina_stringshare_del(itc->item_style);
1604    free(itc);
1605 }
1606
1607 static void
1608 _item_del_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1609 {
1610    Elm_Gen_Item *it = event_info;
1611    if (!it) return;
1612    if (it->wd->last_selected_item == it)
1613      it->wd->last_selected_item = NULL;
1614 }
1615
1616 static void
1617 _item_label_realize(Elm_Gen_Item *it,
1618                     Evas_Object *target,
1619                     Eina_List **source,
1620                     const char *parts)
1621 {
1622    if (it->itc->func.text_get)
1623      {
1624         const Eina_List *l;
1625         const char *key;
1626
1627         *source = elm_widget_stringlist_get(edje_object_data_get(target, "labels"));
1628         EINA_LIST_FOREACH(*source, l, key)
1629           {
1630              if (parts && fnmatch(parts, key, FNM_PERIOD))
1631                continue;
1632
1633              char *s = it->itc->func.text_get
1634                 ((void *)it->base.data, WIDGET(it), key);
1635
1636              if (s)
1637                {
1638                   edje_object_part_text_set(target, key, s);
1639                   free(s);
1640                }
1641              else
1642                {
1643                   edje_object_part_text_set(target, key, "");
1644                }
1645           }
1646      }
1647 }
1648
1649 static Eina_List *
1650 _item_content_unrealize(Elm_Gen_Item *it,
1651                    Evas_Object *target,
1652                    Eina_List **source,
1653                    const char *parts)
1654 {
1655    Eina_List *res = it->content_objs;
1656
1657    if (it->itc->func.content_get)
1658      {
1659         const Eina_List *l;
1660         const char *key;
1661         Evas_Object *ic = NULL;
1662
1663         EINA_LIST_FOREACH(*source, l, key)
1664           {
1665              if (parts && fnmatch(parts, key, FNM_PERIOD))
1666                continue;
1667
1668              ic = edje_object_part_swallow_get(target, key);
1669              if (ic)
1670                {
1671                   res = eina_list_remove(res, ic);
1672                   edje_object_part_unswallow(target, ic);
1673                   evas_object_del(ic);
1674                }
1675           }
1676      }
1677
1678    return res;
1679 }
1680
1681 static Eina_List *
1682 _item_content_realize(Elm_Gen_Item *it,
1683                    Evas_Object *target,
1684                    Eina_List **source,
1685                    const char *parts)
1686 {
1687    Eina_List *res = NULL;
1688
1689    if (it->itc->func.content_get)
1690      {
1691         const Eina_List *l;
1692         const char *key;
1693         Evas_Object *ic = NULL;
1694
1695         *source = elm_widget_stringlist_get(edje_object_data_get(target, "contents"));
1696
1697         if (parts && (eina_list_count(*source) != eina_list_count(it->content_objs)))
1698           res = it->content_objs;
1699
1700         EINA_LIST_FOREACH(*source, l, key)
1701           {
1702              if (parts && fnmatch(parts, key, FNM_PERIOD))
1703                continue;
1704
1705              if (it->itc->func.content_get)
1706                ic = it->itc->func.content_get
1707                   ((void *)it->base.data, WIDGET(it), key);
1708              if (ic)
1709                {
1710                   res = eina_list_append(res, ic);
1711                   edje_object_part_swallow(target, key, ic);
1712                   evas_object_show(ic);
1713                   elm_widget_sub_object_add(WIDGET(it), ic);
1714                   if (it->disabled)
1715                     elm_widget_disabled_set(ic, EINA_TRUE);
1716                }
1717           }
1718      }
1719
1720    return res;
1721 }
1722
1723 static void
1724 _item_state_realize(Elm_Gen_Item *it,
1725                     Evas_Object *target,
1726                     Eina_List **source,
1727                     const char *parts)
1728 {
1729    if (it->itc->func.state_get)
1730      {
1731         const Eina_List *l;
1732         const char *key;
1733         char buf[4096];
1734
1735         *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
1736         EINA_LIST_FOREACH(*source, l, key)
1737           {
1738              if (parts && fnmatch(parts, key, FNM_PERIOD))
1739                continue;
1740
1741              Eina_Bool on = it->itc->func.state_get
1742                 ((void *)it->base.data, WIDGET(it), key);
1743
1744              if (on)
1745                {
1746                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1747                   edje_object_signal_emit(target, buf, "elm");
1748                }
1749              else
1750                {
1751                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
1752                   edje_object_signal_emit(target, buf, "elm");
1753                }
1754           }
1755      }
1756 }
1757
1758 static void
1759 _item_realize(Elm_Gen_Item *it,
1760               int               in,
1761               Eina_Bool         calc)
1762 {
1763    Elm_Gen_Item *it2;
1764    const char *treesize;
1765    char buf[1024];
1766    int depth, tsize = 20;
1767    Item_Cache *itc = NULL;
1768
1769    if (it->generation < it->wd->generation) return;
1770    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
1771    if (it->realized)
1772      {
1773         if (it->item->order_num_in != in)
1774           {
1775              it->item->order_num_in = in;
1776              _elm_genlist_item_odd_even_update(it);
1777              _elm_genlist_item_state_update(it, NULL);
1778           }
1779         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1780         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1781         return;
1782      }
1783    it->item->order_num_in = in;
1784
1785    if (it->item->nocache)
1786      it->item->nocache = EINA_FALSE;
1787    else
1788      itc = _item_cache_find(it);
1789    if (itc)
1790      {
1791         VIEW(it) = itc->base_view;
1792         itc->base_view = NULL;
1793         it->spacer = itc->spacer;
1794         itc->spacer = NULL;
1795      }
1796    else
1797      {
1798         const char *stacking_even;
1799         const char *stacking;
1800
1801         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
1802         edje_object_scale_set(VIEW(it),
1803                               elm_widget_scale_get(WIDGET(it)) *
1804                               _elm_config->scale);
1805         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
1806         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
1807
1808         if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS)
1809           strncpy(buf, "tree", sizeof(buf));
1810         else strncpy(buf, "item", sizeof(buf));
1811         if (it->wd->compress)
1812           strncat(buf, "_compress", sizeof(buf) - strlen(buf));
1813
1814         strncat(buf, "/", sizeof(buf) - strlen(buf));
1815         strncat(buf, it->itc->item_style, sizeof(buf) - strlen(buf));
1816
1817         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
1818                               elm_widget_style_get(WIDGET(it)));
1819
1820         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1821         if (!stacking_even) stacking_even = "above";
1822         it->item->stacking_even = !!strcmp("above", stacking_even);
1823
1824         stacking = edje_object_data_get(VIEW(it), "stacking");
1825         if (!stacking) stacking = "yes";
1826         it->item->nostacking = !!strcmp("yes", stacking);
1827
1828         edje_object_mirrored_set(VIEW(it),
1829                                  elm_widget_mirrored_get(WIDGET(it)));
1830         it->spacer =
1831           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1832         evas_object_color_set(it->spacer, 0, 0, 0, 0);
1833         elm_widget_sub_object_add(WIDGET(it), it->spacer);
1834      }
1835
1836    _elm_genlist_item_odd_even_update(it);
1837
1838    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
1839      {
1840         if (!it2->parent->group) depth += 1;
1841      }
1842    it->item->expanded_depth = depth;
1843    treesize = edje_object_data_get(VIEW(it), "treesize");
1844    if (treesize) tsize = atoi(treesize);
1845    evas_object_size_hint_min_set(it->spacer,
1846                                  (depth * tsize) * _elm_config->scale, 1);
1847    edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1848    if (!calc)
1849      {
1850         edje_object_signal_callback_add(VIEW(it),
1851                                         "elm,action,expand,toggle",
1852                                         "elm", _signal_expand_toggle, it);
1853         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
1854                                         "elm", _signal_expand, it);
1855         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
1856                                         "elm", _signal_contract, it);
1857         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1858                                        _mouse_down, it);
1859         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1860                                        _mouse_up, it);
1861         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1862                                        _mouse_move, it);
1863         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
1864                                        _multi_down, it);
1865         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_UP,
1866                                        _multi_up, it);
1867         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
1868                                        _multi_move, it);
1869
1870         _elm_genlist_item_state_update(it, itc);
1871      }
1872
1873    if ((calc) && (it->wd->homogeneous) &&
1874        ((it->wd->item_width) ||
1875         ((it->wd->item_width) && (it->wd->group_item_width))))
1876      {
1877         /* homogenous genlist shortcut */
1878         if (!it->item->mincalcd)
1879           {
1880              if (it->group)
1881                {
1882                   it->item->w = it->item->minw = it->wd->group_item_width;
1883                   it->item->h = it->item->minh = it->wd->group_item_height;
1884                }
1885              else
1886                {
1887                   it->item->w = it->item->minw = it->wd->item_width;
1888                   it->item->h = it->item->minh = it->wd->item_height;
1889                }
1890              it->item->mincalcd = EINA_TRUE;
1891           }
1892      }
1893    else
1894      {
1895         /* FIXME: If you see that assert, please notify us and we
1896            will clean our mess */
1897         assert(eina_list_count(it->content_objs) == 0);
1898
1899         _item_label_realize(it, VIEW(it), &it->labels, NULL);
1900         it->content_objs = _item_content_realize(it, VIEW(it), &it->contents, NULL);
1901         _item_state_realize(it, VIEW(it), &it->states, NULL);
1902
1903         if (!it->item->mincalcd)
1904           {
1905              Evas_Coord mw = -1, mh = -1;
1906
1907              if (!it->display_only)
1908                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1909              if (it->wd->height_for_width) mw = it->wd->prev_viewport_w;
1910              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
1911                                                   mh);
1912              if (!it->display_only)
1913                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1914              it->item->w = it->item->minw = mw;
1915              it->item->h = it->item->minh = mh;
1916              it->item->mincalcd = EINA_TRUE;
1917
1918              if ((!it->wd->group_item_width) && (it->group))
1919                {
1920                   it->wd->group_item_width = mw;
1921                   it->wd->group_item_height = mh;
1922                }
1923              else if ((!it->wd->item_width) && (it->item->flags == ELM_GENLIST_ITEM_NONE))
1924                {
1925                   it->wd->item_width = mw;
1926                   it->wd->item_height = mh;
1927                }
1928           }
1929         if (!calc) evas_object_show(VIEW(it));
1930      }
1931
1932    if (it->tooltip.content_cb)
1933      {
1934         elm_widget_item_tooltip_content_cb_set(it,
1935                                                it->tooltip.content_cb,
1936                                                it->tooltip.data, NULL);
1937         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
1938         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
1939      }
1940
1941    if (it->mouse_cursor)
1942      elm_widget_item_cursor_set(it, it->mouse_cursor);
1943
1944    it->realized = EINA_TRUE;
1945    it->want_unrealize = EINA_FALSE;
1946
1947    if (itc) _item_cache_free(itc);
1948    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1949    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1950    if (!calc)
1951      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1952    edje_object_message_signal_process(VIEW(it));
1953 }
1954
1955 static void
1956 _item_unrealize_cb(Elm_Gen_Item *it)
1957 {
1958    if (it->item->nocache)
1959      {
1960         evas_object_del(VIEW(it));
1961         VIEW(it) = NULL;
1962         evas_object_del(it->spacer);
1963         it->spacer = NULL;
1964      }
1965    else
1966      {
1967         edje_object_mirrored_set(VIEW(it),
1968                                  elm_widget_mirrored_get(WIDGET(it)));
1969         edje_object_scale_set(VIEW(it),
1970                               elm_widget_scale_get(WIDGET(it))
1971                               * _elm_config->scale);
1972         _item_cache_add(it);
1973      }
1974
1975    _mode_item_unrealize(it);
1976    it->states = NULL;
1977    it->realized = EINA_FALSE;
1978    it->want_unrealize = EINA_FALSE;
1979 }
1980
1981 static Eina_Bool
1982 _item_block_recalc(Item_Block *itb,
1983                    int         in,
1984                    Eina_Bool   qadd)
1985 {
1986    const Eina_List *l;
1987    Elm_Gen_Item *it;
1988    Evas_Coord minw = 0, minh = 0;
1989    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
1990    Evas_Coord y = 0;
1991
1992    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
1993    itb->num = in;
1994    EINA_LIST_FOREACH(itb->items, l, it)
1995      {
1996         if (it->generation < it->wd->generation) continue;
1997         showme |= it->item->showme;
1998         if (!itb->realized)
1999           {
2000              if (qadd)
2001                {
2002                   if (!it->item->mincalcd) changed = EINA_TRUE;
2003                   if (changed)
2004                     {
2005                        _item_realize(it, in, EINA_TRUE);
2006                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2007                     }
2008                }
2009              else
2010                {
2011                   _item_realize(it, in, EINA_TRUE);
2012                   _elm_genlist_item_unrealize(it, EINA_TRUE);
2013                }
2014           }
2015         else
2016           _item_realize(it, in, EINA_FALSE);
2017         minh += it->item->minh;
2018         if (minw < it->item->minw) minw = it->item->minw;
2019         in++;
2020         it->x = 0;
2021         it->y = y;
2022         y += it->item->h;
2023      }
2024    itb->minw = minw;
2025    itb->minh = minh;
2026    itb->changed = EINA_FALSE;
2027    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2028    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2029    return showme;
2030 }
2031
2032 static void
2033 _item_block_realize(Item_Block *itb)
2034 {
2035    if (itb->realized) return;
2036    itb->realized = EINA_TRUE;
2037    itb->want_unrealize = EINA_FALSE;
2038 }
2039
2040 static void
2041 _item_block_unrealize(Item_Block *itb)
2042 {
2043    const Eina_List *l;
2044    Elm_Gen_Item *it;
2045    Eina_Bool dragging = EINA_FALSE;
2046
2047    if (!itb->realized) return;
2048    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2049    EINA_LIST_FOREACH(itb->items, l, it)
2050      {
2051         if (!it->group)
2052           {
2053              if (it->dragging)
2054                {
2055                   dragging = EINA_TRUE;
2056                   it->want_unrealize = EINA_TRUE;
2057                }
2058              else
2059                _elm_genlist_item_unrealize(it, EINA_FALSE);
2060           }
2061      }
2062    if (!dragging)
2063      {
2064         itb->realized = EINA_FALSE;
2065         itb->want_unrealize = EINA_TRUE;
2066      }
2067    else
2068      itb->want_unrealize = EINA_FALSE;
2069    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2070    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2071 }
2072
2073 static int
2074 _get_space_for_reorder_item(Elm_Gen_Item *it)
2075 {
2076    Evas_Coord rox, roy, row, roh, oy, oh;
2077    Eina_Bool top = EINA_FALSE;
2078    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2079    if (!reorder_it) return 0;
2080
2081    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2082    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2083
2084    if ((it->wd->reorder_start_y < it->item->block->y) &&
2085        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2086      {
2087         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2088         if (it->item->block->count == 1)
2089           it->wd->reorder_rel = it;
2090      }
2091    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2092             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2093      {
2094         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2095      }
2096    else
2097      it->item->block->reorder_offset = 0;
2098
2099    it->item->scrl_y += it->item->block->reorder_offset;
2100
2101    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2102                               rox, roy + (roh / 2), row, 1));
2103    if (top)
2104      {
2105         it->wd->reorder_rel = it;
2106         it->item->scrl_y += it->wd->reorder_it->item->h;
2107         return it->wd->reorder_it->item->h;
2108      }
2109    else
2110      return 0;
2111 }
2112
2113 static Eina_Bool
2114 _reorder_move_animator_cb(void *data)
2115 {
2116    Elm_Gen_Item *it = data;
2117    Eina_Bool down = EINA_FALSE;
2118    double t;
2119    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2120
2121    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2122
2123    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2124    else y = dy;
2125
2126    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2127    if (diff > it->item->h) y = diff / 2;
2128
2129    if (it->item->old_scrl_y < it->item->scrl_y)
2130      {
2131         it->item->old_scrl_y += y;
2132         down = EINA_TRUE;
2133      }
2134    else if (it->item->old_scrl_y > it->item->scrl_y)
2135      {
2136         it->item->old_scrl_y -= y;
2137         down = EINA_FALSE;
2138      }
2139    _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2140    _group_items_recalc(it->wd);
2141
2142    if ((it->wd->reorder_pan_move) ||
2143        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2144        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2145      {
2146         it->item->old_scrl_y = it->item->scrl_y;
2147         it->item->move_effect_enabled = EINA_FALSE;
2148         it->wd->reorder_move_animator = NULL;
2149         return ECORE_CALLBACK_CANCEL;
2150      }
2151    return ECORE_CALLBACK_RENEW;
2152 }
2153
2154 static void
2155 _item_position(Elm_Gen_Item *it,
2156                Evas_Object      *view,
2157                Evas_Coord        it_x,
2158                Evas_Coord        it_y)
2159 {
2160    if (!it) return;
2161    if (!view) return;
2162
2163    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2164    evas_object_resize(view, it->item->w, it->item->h);
2165    evas_object_move(view, it_x, it_y);
2166    evas_object_show(view);
2167    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2168    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2169 }
2170
2171 static void
2172 _item_block_position(Item_Block *itb,
2173                      int         in)
2174 {
2175    const Eina_List *l;
2176    Elm_Gen_Item *it;
2177    Elm_Gen_Item *git;
2178    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2179    Eina_Bool vis = EINA_FALSE;
2180
2181    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2182    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2183    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2184                             &cvw, &cvh);
2185    EINA_LIST_FOREACH(itb->items, l, it)
2186      {
2187         if (it->generation < it->wd->generation) continue;
2188         else if (it->wd->reorder_it == it) continue;
2189         it->x = 0;
2190         it->y = y;
2191         it->item->w = itb->w;
2192         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2193         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2194
2195         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2196                                    cvx, cvy, cvw, cvh));
2197         if (!it->group)
2198           {
2199              if ((itb->realized) && (!it->realized))
2200                {
2201                   if (vis) _item_realize(it, in, EINA_FALSE);
2202                }
2203              if (it->realized)
2204                {
2205                   if (vis)
2206                     {
2207                        if (it->wd->reorder_mode)
2208                          y += _get_space_for_reorder_item(it);
2209                        git = it->item->group_item;
2210                        if (git)
2211                          {
2212                             if (git->item->scrl_y < oy)
2213                               git->item->scrl_y = oy;
2214                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2215                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2216                             git->item->want_realize = EINA_TRUE;
2217                          }
2218                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2219                          {
2220                             if (!it->item->move_effect_enabled)
2221                               {
2222                                  it->item->move_effect_enabled = EINA_TRUE;
2223                                  it->wd->reorder_move_animator =
2224                                     ecore_animator_add(
2225                                        _reorder_move_animator_cb, it);
2226                               }
2227                          }
2228                        if (!it->item->move_effect_enabled)
2229                          {
2230                             if (it->item->mode_view)
2231                                _item_position(it, it->item->mode_view, it->item->scrl_x,
2232                                               it->item->scrl_y);
2233                             else
2234                                _item_position(it, VIEW(it), it->item->scrl_x,
2235                                               it->item->scrl_y);
2236                             it->item->old_scrl_y = it->item->scrl_y;
2237                          }
2238                     }
2239                   else
2240                     {
2241                        if (!it->dragging) _elm_genlist_item_unrealize(it, EINA_FALSE);
2242                     }
2243                }
2244              in++;
2245           }
2246         else
2247           {
2248              if (vis) it->item->want_realize = EINA_TRUE;
2249           }
2250         y += it->item->h;
2251      }
2252    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2253    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2254 }
2255
2256 static void
2257 _group_items_recalc(void *data)
2258 {
2259    Widget_Data *wd = data;
2260    Eina_List *l;
2261    Elm_Gen_Item *git;
2262
2263    evas_event_freeze(evas_object_evas_get(wd->obj));
2264    EINA_LIST_FOREACH(wd->group_items, l, git)
2265      {
2266         if (git->item->want_realize)
2267           {
2268              if (!git->realized)
2269                _item_realize(git, 0, EINA_FALSE);
2270              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2271              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2272              evas_object_show(VIEW(git));
2273              evas_object_raise(VIEW(git));
2274           }
2275         else if (!git->item->want_realize && git->realized)
2276           {
2277              if (!git->dragging)
2278                _elm_genlist_item_unrealize(git, EINA_FALSE);
2279           }
2280      }
2281    evas_event_thaw(evas_object_evas_get(wd->obj));
2282    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2283 }
2284
2285 static Eina_Bool
2286 _must_recalc_idler(void *data)
2287 {
2288    Widget_Data *wd = data;
2289    if (wd->calc_job) ecore_job_del(wd->calc_job);
2290    wd->calc_job = ecore_job_add(_calc_job, wd);
2291    wd->must_recalc_idler = NULL;
2292    return ECORE_CALLBACK_CANCEL;
2293 }
2294
2295 static void
2296 _calc_job(void *data)
2297 {
2298    Widget_Data *wd = data;
2299    Item_Block *itb, *chb = NULL;
2300    Evas_Coord minw = -1, minh = 0, y = 0, ow;
2301    int in = 0;
2302    Eina_Bool minw_change = EINA_FALSE;
2303    Eina_Bool did_must_recalc = EINA_FALSE;
2304    if (!wd) return;
2305
2306    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2307    if (wd->w != ow)
2308      wd->w = ow;
2309
2310    evas_event_freeze(evas_object_evas_get(wd->obj));
2311    EINA_INLIST_FOREACH(wd->blocks, itb)
2312      {
2313         Eina_Bool showme = EINA_FALSE;
2314
2315         itb->num = in;
2316         showme = itb->showme;
2317         itb->showme = EINA_FALSE;
2318         if (chb)
2319           {
2320              if (itb->realized) _item_block_unrealize(itb);
2321           }
2322         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2323           {
2324              if (itb->must_recalc)
2325                {
2326                   Eina_List *l;
2327                   Elm_Gen_Item *it;
2328                   EINA_LIST_FOREACH(itb->items, l, it)
2329                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2330                   itb->changed = EINA_TRUE;
2331                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2332                   itb->must_recalc = EINA_FALSE;
2333                }
2334              if (itb->realized) _item_block_unrealize(itb);
2335              showme = _item_block_recalc(itb, in, EINA_FALSE);
2336              chb = itb;
2337           }
2338         itb->y = y;
2339         itb->x = 0;
2340         minh += itb->minh;
2341         if (minw == -1) minw = itb->minw;
2342         else if ((!itb->must_recalc) && (minw < itb->minw))
2343           {
2344              minw = itb->minw;
2345              minw_change = EINA_TRUE;
2346           }
2347         itb->w = minw;
2348         itb->h = itb->minh;
2349         y += itb->h;
2350         in += itb->count;
2351         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2352           {
2353              wd->show_item->item->showme = EINA_FALSE;
2354              if (wd->bring_in)
2355                elm_smart_scroller_region_bring_in(wd->scr,
2356                                                   wd->show_item->x +
2357                                                   wd->show_item->item->block->x,
2358                                                   wd->show_item->y +
2359                                                   wd->show_item->item->block->y,
2360                                                   wd->show_item->item->block->w,
2361                                                   wd->show_item->item->h);
2362              else
2363                elm_smart_scroller_child_region_show(wd->scr,
2364                                                     wd->show_item->x +
2365                                                     wd->show_item->item->block->x,
2366                                                     wd->show_item->y +
2367                                                     wd->show_item->item->block->y,
2368                                                     wd->show_item->item->block->w,
2369                                                     wd->show_item->item->h);
2370              wd->show_item = NULL;
2371           }
2372      }
2373    if (minw_change)
2374      {
2375         EINA_INLIST_FOREACH(wd->blocks, itb)
2376           {
2377              itb->minw = minw;
2378              itb->w = itb->minw;
2379           }
2380      }
2381    if ((chb) && (EINA_INLIST_GET(chb)->next))
2382      {
2383         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2384           {
2385              if (itb->realized) _item_block_unrealize(itb);
2386           }
2387      }
2388    wd->realminw = minw;
2389    if (minw < wd->w) minw = wd->w;
2390    if ((minw != wd->minw) || (minh != wd->minh))
2391      {
2392         wd->minw = minw;
2393         wd->minh = minh;
2394         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2395         _sizing_eval(wd->obj);
2396         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2397           {
2398              Elm_Gen_Item *it;
2399              Evas_Coord it_y;
2400
2401              it = wd->anchor_item;
2402              it_y = wd->anchor_y;
2403              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2404                                               it->item->block->y + it->y + it_y);
2405              wd->anchor_item = it;
2406              wd->anchor_y = it_y;
2407           }
2408      }
2409    if (did_must_recalc)
2410      {
2411         if (!wd->must_recalc_idler)
2412           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2413      }
2414    wd->calc_job = NULL;
2415    evas_object_smart_changed(wd->pan_smart);
2416    evas_event_thaw(evas_object_evas_get(wd->obj));
2417    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2418 }
2419
2420 static void
2421 _update_job(void *data)
2422 {
2423    Widget_Data *wd = data;
2424    Eina_List *l2;
2425    Item_Block *itb;
2426    int num, num0;
2427    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2428    if (!wd) return;
2429    wd->update_job = NULL;
2430    num = 0;
2431
2432    evas_event_freeze(evas_object_evas_get(wd->obj));
2433    EINA_INLIST_FOREACH(wd->blocks, itb)
2434      {
2435         Evas_Coord itminw, itminh;
2436         Elm_Gen_Item *it;
2437
2438         if (!itb->updateme)
2439           {
2440              num += itb->count;
2441              if (position)
2442                _item_block_position(itb, num);
2443              continue;
2444           }
2445         num0 = num;
2446         recalc = EINA_FALSE;
2447         EINA_LIST_FOREACH(itb->items, l2, it)
2448           {
2449              if (it->item->updateme)
2450                {
2451                   itminw = it->item->minw;
2452                   itminh = it->item->minh;
2453
2454                   it->item->updateme = EINA_FALSE;
2455                   if (it->realized)
2456                     {
2457                        _elm_genlist_item_unrealize(it, EINA_FALSE);
2458                        _item_realize(it, num, EINA_FALSE);
2459                        position = EINA_TRUE;
2460                     }
2461                   else
2462                     {
2463                        _item_realize(it, num, EINA_TRUE);
2464                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2465                     }
2466                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
2467                     recalc = EINA_TRUE;
2468                }
2469              num++;
2470           }
2471         itb->updateme = EINA_FALSE;
2472         if (recalc)
2473           {
2474              position = EINA_TRUE;
2475              itb->changed = EINA_TRUE;
2476              _item_block_recalc(itb, num0, EINA_FALSE);
2477              _item_block_position(itb, num0);
2478           }
2479      }
2480    if (position)
2481      {
2482         if (wd->calc_job) ecore_job_del(wd->calc_job);
2483         wd->calc_job = ecore_job_add(_calc_job, wd);
2484      }
2485    evas_event_thaw(evas_object_evas_get(wd->obj));
2486    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2487 }
2488
2489 static void
2490 _pan_set(Evas_Object *obj,
2491          Evas_Coord   x,
2492          Evas_Coord   y)
2493 {
2494    Pan *sd = evas_object_smart_data_get(obj);
2495    Item_Block *itb;
2496
2497    if (!sd) return;
2498    //   Evas_Coord ow, oh;
2499    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2500    //   ow = sd->wd->minw - ow;
2501    //   if (ow < 0) ow = 0;
2502    //   oh = sd->wd->minh - oh;
2503    //   if (oh < 0) oh = 0;
2504    //   if (x < 0) x = 0;
2505    //   if (y < 0) y = 0;
2506    //   if (x > ow) x = ow;
2507    //   if (y > oh) y = oh;
2508    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2509    sd->wd->pan_x = x;
2510    sd->wd->pan_y = y;
2511
2512    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2513      {
2514         if ((itb->y + itb->h) > y)
2515           {
2516              Elm_Gen_Item *it;
2517              Eina_List *l2;
2518
2519              EINA_LIST_FOREACH(itb->items, l2, it)
2520                {
2521                   if ((itb->y + it->y) >= y)
2522                     {
2523                        sd->wd->anchor_item = it;
2524                        sd->wd->anchor_y = -(itb->y + it->y - y);
2525                        goto done;
2526                     }
2527                }
2528           }
2529      }
2530 done:
2531    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2532 }
2533
2534 static void
2535 _pan_get(Evas_Object *obj,
2536          Evas_Coord  *x,
2537          Evas_Coord  *y)
2538 {
2539    Pan *sd = evas_object_smart_data_get(obj);
2540
2541    if (!sd) return;
2542    if (x) *x = sd->wd->pan_x;
2543    if (y) *y = sd->wd->pan_y;
2544 }
2545
2546 static void
2547 _pan_max_get(Evas_Object *obj,
2548              Evas_Coord  *x,
2549              Evas_Coord  *y)
2550 {
2551    Pan *sd = evas_object_smart_data_get(obj);
2552    Evas_Coord ow, oh;
2553
2554    if (!sd) return;
2555    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2556    ow = sd->wd->minw - ow;
2557    if (ow < 0) ow = 0;
2558    oh = sd->wd->minh - oh;
2559    if (oh < 0) oh = 0;
2560    if (x) *x = ow;
2561    if (y) *y = oh;
2562 }
2563
2564 static void
2565 _pan_min_get(Evas_Object *obj __UNUSED__,
2566              Evas_Coord  *x,
2567              Evas_Coord  *y)
2568 {
2569    if (x) *x = 0;
2570    if (y) *y = 0;
2571 }
2572
2573 static void
2574 _pan_child_size_get(Evas_Object *obj,
2575                     Evas_Coord  *w,
2576                     Evas_Coord  *h)
2577 {
2578    Pan *sd = evas_object_smart_data_get(obj);
2579
2580    if (!sd) return;
2581    if (w) *w = sd->wd->minw;
2582    if (h) *h = sd->wd->minh;
2583 }
2584
2585 static void
2586 _pan_add(Evas_Object *obj)
2587 {
2588    Pan *sd;
2589    Evas_Object_Smart_Clipped_Data *cd;
2590
2591    _pan_sc.add(obj);
2592    cd = evas_object_smart_data_get(obj);
2593    sd = ELM_NEW(Pan);
2594    if (!sd) return;
2595    sd->__clipped_data = *cd;
2596    free(cd);
2597    evas_object_smart_data_set(obj, sd);
2598 }
2599
2600 static void
2601 _pan_del(Evas_Object *obj)
2602 {
2603    Pan *sd = evas_object_smart_data_get(obj);
2604
2605    if (!sd) return;
2606    if (sd->resize_job)
2607      {
2608         ecore_job_del(sd->resize_job);
2609         sd->resize_job = NULL;
2610      }
2611    _pan_sc.del(obj);
2612 }
2613
2614 static void
2615 _pan_resize_job(void *data)
2616 {
2617    Pan *sd = data;
2618    if (!sd) return;
2619    _sizing_eval(sd->wd->obj);
2620    sd->resize_job = NULL;
2621 }
2622
2623 static void
2624 _pan_resize(Evas_Object *obj,
2625             Evas_Coord   w,
2626             Evas_Coord   h)
2627 {
2628    Pan *sd = evas_object_smart_data_get(obj);
2629    Evas_Coord ow, oh;
2630
2631    if (!sd) return;
2632    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2633    if ((ow == w) && (oh == h)) return;
2634    if ((sd->wd->height_for_width) && (ow != w))
2635      {
2636         /* fix me later */
2637         if (sd->resize_job) ecore_job_del(sd->resize_job);
2638         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
2639      }
2640    sd->wd->pan_resized = EINA_TRUE;
2641    evas_object_smart_changed(obj);
2642    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2643    sd->wd->calc_job = NULL;
2644 /* OLD
2645    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2646    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2647  */
2648 }
2649
2650 static void
2651 _pan_calculate(Evas_Object *obj)
2652 {
2653    Pan *sd = evas_object_smart_data_get(obj);
2654    Item_Block *itb;
2655    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2656    int in = 0;
2657    Elm_Gen_Item *git;
2658    Eina_List *l;
2659
2660    if (!sd) return;
2661    evas_event_freeze(evas_object_evas_get(obj));
2662
2663    if (sd->wd->pan_resized)
2664      {
2665         _calc_job(sd->wd);
2666         sd->wd->pan_resized = EINA_FALSE;
2667      }
2668
2669    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2670    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2671    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
2672      {
2673         git->item->want_realize = EINA_FALSE;
2674      }
2675    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2676      {
2677         itb->w = sd->wd->minw;
2678         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
2679                                 itb->y - sd->wd->pan_y + oy,
2680                                 itb->w, itb->h,
2681                                 cvx, cvy, cvw, cvh))
2682           {
2683              if ((!itb->realized) || (itb->changed))
2684                _item_block_realize(itb);
2685              _item_block_position(itb, in);
2686           }
2687         else
2688           {
2689              if (itb->realized) _item_block_unrealize(itb);
2690           }
2691         in += itb->count;
2692      }
2693    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
2694       _group_items_recalc(sd->wd);
2695    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
2696      {
2697         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
2698            sd->wd->reorder_pan_move = EINA_TRUE;
2699         else sd->wd->reorder_pan_move = EINA_FALSE;
2700         evas_object_raise(sd->wd->VIEW(reorder_it));
2701         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
2702         sd->wd->start_time = ecore_loop_time_get();
2703      }
2704    _item_auto_scroll(sd->wd);
2705    evas_event_thaw(evas_object_evas_get(obj));
2706    evas_event_thaw_eval(evas_object_evas_get(obj));
2707 }
2708
2709 static void
2710 _pan_move(Evas_Object *obj,
2711           Evas_Coord   x __UNUSED__,
2712           Evas_Coord   y __UNUSED__)
2713 {
2714    Pan *sd = evas_object_smart_data_get(obj);
2715
2716    if (!sd) return;
2717    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2718    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2719 }
2720
2721 static void
2722 _hold_on(void        *data __UNUSED__,
2723          Evas_Object *obj,
2724          void        *event_info __UNUSED__)
2725 {
2726    Widget_Data *wd = elm_widget_data_get(obj);
2727    if (!wd) return;
2728    elm_smart_scroller_hold_set(wd->scr, 1);
2729 }
2730
2731 static void
2732 _hold_off(void        *data __UNUSED__,
2733           Evas_Object *obj,
2734           void        *event_info __UNUSED__)
2735 {
2736    Widget_Data *wd = elm_widget_data_get(obj);
2737    if (!wd) return;
2738    elm_smart_scroller_hold_set(wd->scr, 0);
2739 }
2740
2741 static void
2742 _freeze_on(void        *data __UNUSED__,
2743            Evas_Object *obj,
2744            void        *event_info __UNUSED__)
2745 {
2746    Widget_Data *wd = elm_widget_data_get(obj);
2747    if (!wd) return;
2748    elm_smart_scroller_freeze_set(wd->scr, 1);
2749 }
2750
2751 static void
2752 _freeze_off(void        *data __UNUSED__,
2753             Evas_Object *obj,
2754             void        *event_info __UNUSED__)
2755 {
2756    Widget_Data *wd = elm_widget_data_get(obj);
2757    if (!wd) return;
2758    elm_smart_scroller_freeze_set(wd->scr, 0);
2759 }
2760
2761 static void
2762 _scr_anim_start(void        *data,
2763                 Evas_Object *obj __UNUSED__,
2764                 void        *event_info __UNUSED__)
2765 {
2766    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
2767 }
2768
2769 static void
2770 _scr_anim_stop(void        *data,
2771                Evas_Object *obj __UNUSED__,
2772                void        *event_info __UNUSED__)
2773 {
2774    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
2775 }
2776
2777 static void
2778 _scr_drag_start(void            *data,
2779                 Evas_Object     *obj __UNUSED__,
2780                 void            *event_info __UNUSED__)
2781 {
2782    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
2783 }
2784
2785 static void
2786 _scr_drag_stop(void            *data,
2787                Evas_Object     *obj __UNUSED__,
2788                void            *event_info __UNUSED__)
2789 {
2790    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
2791 }
2792
2793 static void
2794 _edge_left(void        *data,
2795            Evas_Object *scr __UNUSED__,
2796            void        *event_info __UNUSED__)
2797 {
2798    Evas_Object *obj = data;
2799    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
2800 }
2801
2802 static void
2803 _edge_right(void        *data,
2804             Evas_Object *scr __UNUSED__,
2805             void        *event_info __UNUSED__)
2806 {
2807    Evas_Object *obj = data;
2808    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
2809 }
2810
2811 static void
2812 _edge_top(void        *data,
2813           Evas_Object *scr __UNUSED__,
2814           void        *event_info __UNUSED__)
2815 {
2816    Evas_Object *obj = data;
2817    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
2818 }
2819
2820 static void
2821 _edge_bottom(void        *data,
2822              Evas_Object *scr __UNUSED__,
2823              void        *event_info __UNUSED__)
2824 {
2825    Evas_Object *obj = data;
2826    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
2827 }
2828
2829 static void
2830 _mode_item_realize(Elm_Gen_Item *it)
2831 {
2832    char buf[1024];
2833
2834    if ((it->item->mode_view) || (it->generation < it->wd->generation)) return;
2835
2836    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2837    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
2838    edje_object_scale_set(it->item->mode_view,
2839                          elm_widget_scale_get(WIDGET(it)) *
2840                          _elm_config->scale);
2841    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
2842    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
2843
2844    strncpy(buf, "item", sizeof(buf));
2845    if (it->wd->compress)
2846      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
2847
2848    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
2849    strncat(buf, "/", sizeof(buf) - strlen(buf));
2850    strncat(buf, it->wd->mode_item_style, sizeof(buf) - strlen(buf));
2851
2852    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
2853                          elm_widget_style_get(WIDGET(it)));
2854    edje_object_mirrored_set(it->item->mode_view,
2855                             elm_widget_mirrored_get(WIDGET(it)));
2856
2857    /* signal callback add */
2858    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
2859                                   _mouse_down, it);
2860    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
2861                                   _mouse_up, it);
2862    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
2863                                   _mouse_move, it);
2864
2865    /* text_get, content_get, state_get */
2866    /* FIXME: If you see that assert, please notify us and we
2867       will clean our mess */
2868    assert(eina_list_count(it->item->mode_content_objs) == 0);
2869
2870    _item_label_realize(it, it->item->mode_view, &it->item->mode_labels, NULL);
2871    it->item->mode_content_objs =
2872      _item_content_realize(it, it->item->mode_view,
2873                            &it->item->mode_contents, NULL);
2874    _item_state_realize(it, it->item->mode_view, &it->item->mode_states, NULL);
2875
2876    edje_object_part_swallow(it->item->mode_view,
2877                             edje_object_data_get(it->item->mode_view, "mode_part"),
2878                             VIEW(it));
2879
2880    it->want_unrealize = EINA_FALSE;
2881    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2882    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2883 }
2884
2885 static void
2886 _mode_item_unrealize(Elm_Gen_Item *it)
2887 {
2888    Widget_Data *wd = it->wd;
2889    Evas_Object *content;
2890    if (!it->item->mode_view) return;
2891
2892    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2893    elm_widget_stringlist_free(it->item->mode_labels);
2894    it->item->mode_labels = NULL;
2895    elm_widget_stringlist_free(it->item->mode_contents);
2896    it->item->mode_contents = NULL;
2897    elm_widget_stringlist_free(it->item->mode_states);
2898
2899    EINA_LIST_FREE(it->item->mode_content_objs, content)
2900      evas_object_del(content);
2901
2902    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
2903    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
2904    evas_object_del(it->item->mode_view);
2905    it->item->mode_view = NULL;
2906
2907    if (wd->mode_item == it)
2908      wd->mode_item = NULL;
2909    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2910    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2911 }
2912
2913 static void
2914 _item_mode_set(Elm_Gen_Item *it)
2915 {
2916    if (!it) return;
2917    Widget_Data *wd = it->wd;
2918    if (!wd) return;
2919    char buf[1024];
2920
2921    wd->mode_item = it;
2922    it->item->nocache = EINA_TRUE;
2923
2924    if (wd->scr_hold_timer)
2925      {
2926         ecore_timer_del(wd->scr_hold_timer);
2927         wd->scr_hold_timer = NULL;
2928      }
2929    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
2930    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
2931
2932    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2933    _mode_item_realize(it);
2934    if (it->item->group_item)
2935      evas_object_raise(it->item->VIEW(group_item));
2936    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
2937    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2938    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2939
2940    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
2941    edje_object_signal_emit(it->item->mode_view, buf, "elm");
2942 }
2943
2944 static void
2945 _item_mode_unset(Widget_Data *wd)
2946 {
2947    if (!wd) return;
2948    if (!wd->mode_item) return;
2949    char buf[1024], buf2[1024];
2950    Elm_Gen_Item *it;
2951
2952    it = wd->mode_item;
2953    it->item->nocache = EINA_TRUE;
2954
2955    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type);
2956    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type);
2957
2958    edje_object_signal_emit(it->item->mode_view, buf, "elm");
2959    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
2960
2961    wd->mode_item = NULL;
2962 }
2963
2964 static void
2965 _item_auto_scroll(Widget_Data *wd)
2966 {
2967    if (!wd) return;
2968    Elm_Gen_Item  *it;
2969    Eina_List *l;
2970    Evas_Coord ox, oy, ow, oh;
2971
2972    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
2973      {
2974         evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
2975         if (wd->expanded_item->item->scrl_y > (oh + oy) / 2)
2976           {
2977              EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
2978                 elm_genlist_item_bring_in(it);
2979           }
2980         wd->auto_scroll_enabled = EINA_FALSE;
2981      }
2982 }
2983
2984 EAPI Evas_Object *
2985 elm_genlist_add(Evas_Object *parent)
2986 {
2987    Evas_Object *obj;
2988    Evas *e;
2989    Widget_Data *wd;
2990    Evas_Coord minw, minh;
2991    static Evas_Smart *smart = NULL;
2992
2993    if (!smart)
2994      {
2995         static Evas_Smart_Class sc;
2996
2997         evas_object_smart_clipped_smart_set(&_pan_sc);
2998         sc = _pan_sc;
2999         sc.name = "elm_genlist_pan";
3000         sc.version = EVAS_SMART_CLASS_VERSION;
3001         sc.add = _pan_add;
3002         sc.del = _pan_del;
3003         sc.resize = _pan_resize;
3004         sc.move = _pan_move;
3005         sc.calculate = _pan_calculate;
3006         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3007      }
3008
3009    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3010
3011    ELM_SET_WIDTYPE(widtype, "genlist");
3012    ELM_GEN_SETUP(wd);
3013    elm_widget_type_set(obj, "genlist");
3014    elm_widget_sub_object_add(parent, obj);
3015    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3016    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3017    elm_widget_data_set(obj, wd);
3018    elm_widget_del_hook_set(obj, _del_hook);
3019    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3020    elm_widget_theme_hook_set(obj, _theme_hook);
3021    elm_widget_can_focus_set(obj, EINA_TRUE);
3022    elm_widget_event_hook_set(obj, _event_hook);
3023    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3024    elm_widget_translate_hook_set(obj, _translate_hook);
3025
3026    wd->generation = 1;
3027    wd->scr = elm_smart_scroller_add(e);
3028    elm_smart_scroller_widget_set(wd->scr, obj);
3029    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3030                                        elm_widget_style_get(obj));
3031    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3032                                        _elm_config->thumbscroll_bounce_enable);
3033    elm_widget_resize_object_set(obj, wd->scr);
3034
3035    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3036    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3037    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3038    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3039    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3040    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3041    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3042    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3043
3044    wd->obj = obj;
3045    wd->mode = ELM_LIST_SCROLL;
3046    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3047    wd->item_cache_max = wd->max_items_per_block * 2;
3048    wd->longpress_timeout = _elm_config->longpress_timeout;
3049
3050    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3051    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3052    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3053    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3054
3055    wd->pan_smart = evas_object_smart_add(e, smart);
3056    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3057    wd->pan->wd = wd;
3058
3059    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3060                                      _pan_set, _pan_get, _pan_max_get,
3061                                      _pan_min_get, _pan_child_size_get);
3062
3063    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3064                              &minw, &minh);
3065    evas_object_size_hint_min_set(obj, minw, minh);
3066
3067    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3068
3069    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3070    _sizing_eval(obj);
3071    return obj;
3072 }
3073
3074 void
3075 _item_select(Elm_Gen_Item *it)
3076 {
3077    if ((it->wd->no_select) || (it->generation < it->wd->generation) || (it->mode_set)) return;
3078    if (!it->selected)
3079      {
3080         it->selected = EINA_TRUE;
3081         it->wd->selected = eina_list_append(it->wd->selected, it);
3082      }
3083    else if (!it->wd->always_select) return;
3084
3085    evas_object_ref(WIDGET(it));
3086    it->walking++;
3087    it->wd->walking++;
3088    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3089    if (it->generation == it->wd->generation)
3090      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3091    it->walking--;
3092    it->wd->walking--;
3093    evas_object_unref(WIDGET(it));
3094    if ((it->wd->clear_me) && (!it->wd->walking))
3095      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3096    else
3097      {
3098         if ((!it->walking) && (it->generation < it->wd->generation))
3099           {
3100              if (!it->relcount) it->del_cb(it);
3101           }
3102         else
3103           it->wd->last_selected_item = it;
3104      }
3105 }
3106
3107 static Evas_Object *
3108 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
3109 {
3110    return edje_object_part_swallow_get(VIEW(it), part);
3111 }
3112
3113 static void
3114 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
3115 {
3116    edje_object_part_swallow(VIEW(it), part, content);
3117 }
3118
3119 static Evas_Object *
3120 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
3121 {
3122    Evas_Object *obj;
3123
3124    obj = edje_object_part_swallow_get(VIEW(it), part);
3125    if (!obj) return NULL;
3126    edje_object_part_unswallow(VIEW(it), obj);
3127    return obj;
3128 }
3129
3130 static const char *
3131 _item_label_hook(Elm_Gen_Item *it, const char *part)
3132 {
3133    if (!it->itc->func.text_get) return NULL;
3134    return edje_object_part_text_get(VIEW(it), part);
3135 }
3136
3137 Elm_Gen_Item *
3138 _elm_genlist_item_new(Widget_Data              *wd,
3139                       const Elm_Gen_Item_Class *itc,
3140                       const void               *data,
3141                       Elm_Gen_Item             *parent,
3142                       Evas_Smart_Cb             func,
3143                       const void               *func_data)
3144 {
3145    Elm_Gen_Item *it;
3146
3147    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
3148    if (!it) return NULL;
3149    it->wd = wd;
3150    it->generation = wd->generation;
3151    it->itc = itc;
3152    it->base.data = data;
3153    it->parent = parent;
3154    it->func.func = func;
3155    it->func.data = func_data;
3156    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
3157    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
3158    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
3159    /* TEMPORARY */
3160    it->sel_cb = (Ecore_Cb)_item_select;
3161
3162    elm_widget_item_text_get_hook_set(it, _item_label_hook);
3163    return it;
3164 }
3165
3166 static Elm_Gen_Item *
3167 _item_new(Widget_Data                  *wd,
3168           const Elm_Genlist_Item_Class *itc,
3169           const void                   *data,
3170           Elm_Gen_Item                 *parent,
3171           Elm_Genlist_Item_Flags        flags,
3172           Evas_Smart_Cb                 func,
3173           const void                   *func_data)
3174 {
3175    Elm_Gen_Item *it;
3176
3177    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
3178    if (!it) return NULL;
3179    it->item = ELM_NEW(Elm_Gen_Item_Type);
3180    it->item->flags = flags;
3181    if (flags & ELM_GENLIST_ITEM_GROUP) it->group++;
3182    it->item->expanded_depth = 0;
3183    elm_widget_item_del_cb_set(it, _item_del_hook);
3184    ELM_GEN_ITEM_SETUP(it);
3185    if (it->parent)
3186      {
3187         if (it->parent->group)
3188           it->item->group_item = parent;
3189         else if (it->parent->item->group_item)
3190           it->item->group_item = it->parent->item->group_item;
3191      }
3192    return it;
3193 }
3194
3195 static void
3196 _item_block_add(Widget_Data      *wd,
3197                 Elm_Gen_Item *it)
3198 {
3199    Item_Block *itb = NULL;
3200
3201    if (!it->item->rel)
3202      {
3203 newblock:
3204         if (it->item->rel)
3205           {
3206              itb = calloc(1, sizeof(Item_Block));
3207              if (!itb) return;
3208              itb->wd = wd;
3209              if (!it->item->rel->item->block)
3210                {
3211                   wd->blocks =
3212                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3213                   itb->items = eina_list_append(itb->items, it);
3214                }
3215              else
3216                {
3217                   if (it->item->before)
3218                     {
3219                        wd->blocks = eina_inlist_prepend_relative
3220                            (wd->blocks, EINA_INLIST_GET(itb),
3221                            EINA_INLIST_GET(it->item->rel->item->block));
3222                        itb->items =
3223                          eina_list_prepend_relative(itb->items, it, it->item->rel);
3224                     }
3225                   else
3226                     {
3227                        wd->blocks = eina_inlist_append_relative
3228                            (wd->blocks, EINA_INLIST_GET(itb),
3229                            EINA_INLIST_GET(it->item->rel->item->block));
3230                        itb->items =
3231                          eina_list_append_relative(itb->items, it, it->item->rel);
3232                     }
3233                }
3234           }
3235         else
3236           {
3237              if (it->item->before)
3238                {
3239                   if (wd->blocks)
3240                     {
3241                        itb = (Item_Block *)(wd->blocks);
3242                        if (itb->count >= wd->max_items_per_block)
3243                          {
3244                             itb = calloc(1, sizeof(Item_Block));
3245                             if (!itb) return;
3246                             itb->wd = wd;
3247                             wd->blocks =
3248                               eina_inlist_prepend(wd->blocks,
3249                                                   EINA_INLIST_GET(itb));
3250                          }
3251                     }
3252                   else
3253                     {
3254                        itb = calloc(1, sizeof(Item_Block));
3255                        if (!itb) return;
3256                        itb->wd = wd;
3257                        wd->blocks =
3258                          eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3259                     }
3260                   itb->items = eina_list_prepend(itb->items, it);
3261                }
3262              else
3263                {
3264                   if (wd->blocks)
3265                     {
3266                        itb = (Item_Block *)(wd->blocks->last);
3267                        if (itb->count >= wd->max_items_per_block)
3268                          {
3269                             itb = calloc(1, sizeof(Item_Block));
3270                             if (!itb) return;
3271                             itb->wd = wd;
3272                             wd->blocks =
3273                               eina_inlist_append(wd->blocks,
3274                                                  EINA_INLIST_GET(itb));
3275                          }
3276                     }
3277                   else
3278                     {
3279                        itb = calloc(1, sizeof(Item_Block));
3280                        if (!itb) return;
3281                        itb->wd = wd;
3282                        wd->blocks =
3283                          eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3284                     }
3285                   itb->items = eina_list_append(itb->items, it);
3286                }
3287           }
3288      }
3289    else
3290      {
3291         itb = it->item->rel->item->block;
3292         if (!itb) goto newblock;
3293         if (it->item->before)
3294           itb->items = eina_list_prepend_relative(itb->items, it, it->item->rel);
3295         else
3296           itb->items = eina_list_append_relative(itb->items, it, it->item->rel);
3297      }
3298    itb->count++;
3299    itb->changed = EINA_TRUE;
3300    it->item->block = itb;
3301    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3302    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3303    if (it->item->rel)
3304      {
3305         it->item->rel->relcount--;
3306         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3307           _item_del(it->item->rel);
3308         it->item->rel = NULL;
3309      }
3310    if (itb->count > itb->wd->max_items_per_block)
3311      {
3312         int newc;
3313         Item_Block *itb2;
3314         Elm_Gen_Item *it2;
3315
3316         newc = itb->count / 2;
3317         itb2 = calloc(1, sizeof(Item_Block));
3318         if (!itb2) return;
3319         itb2->wd = wd;
3320         wd->blocks =
3321           eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3322                                       EINA_INLIST_GET(itb));
3323         itb2->changed = EINA_TRUE;
3324         while ((itb->count > newc) && (itb->items))
3325           {
3326              Eina_List *l;
3327
3328              l = eina_list_last(itb->items);
3329              it2 = l->data;
3330              itb->items = eina_list_remove_list(itb->items, l);
3331              itb->count--;
3332
3333              itb2->items = eina_list_prepend(itb2->items, it2);
3334              it2->item->block = itb2;
3335              itb2->count++;
3336           }
3337      }
3338 }
3339
3340 static int
3341 _queue_process(Widget_Data *wd)
3342 {
3343    int n;
3344    Eina_Bool showme = EINA_FALSE;
3345    double t0, t;
3346
3347    t0 = ecore_time_get();
3348    //evas_event_freeze(evas_object_evas_get(wd->obj));
3349    for (n = 0; (wd->queue) && (n < 128); n++)
3350      {
3351         Elm_Gen_Item *it;
3352
3353         it = wd->queue->data;
3354         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3355         it->item->queued = EINA_FALSE;
3356         _item_block_add(wd, it);
3357         if (!wd->blocks)
3358           _item_block_realize(it->item->block);
3359         t = ecore_time_get();
3360         if (it->item->block->changed)
3361           {
3362              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
3363              it->item->block->changed = 0;
3364           }
3365         if (showme) it->item->block->showme = EINA_TRUE;
3366         if (eina_inlist_count(wd->blocks) > 1)
3367           {
3368              if ((t - t0) > (ecore_animator_frametime_get())) break;
3369           }
3370      }
3371    //evas_event_thaw(evas_object_evas_get(wd->obj));
3372    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3373    return n;
3374 }
3375
3376 static Eina_Bool
3377 _idle_process(void *data, Eina_Bool *wakeup)
3378 {
3379    Widget_Data *wd = data;
3380
3381    //xxx
3382    //static double q_start = 0.0;
3383    //if (q_start == 0.0) q_start = ecore_time_get();
3384    //xxx
3385    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3386    if (!wd->queue)
3387      {
3388         //xxx
3389         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3390         //xxx
3391         return ECORE_CALLBACK_CANCEL;
3392      }
3393    return ECORE_CALLBACK_RENEW;
3394 }
3395
3396 static Eina_Bool
3397 _item_idle_enterer(void *data)
3398 {
3399    Widget_Data *wd = data;
3400    Eina_Bool wakeup = EINA_FALSE;
3401    Eina_Bool ok = _idle_process(data, &wakeup);
3402
3403    if (wakeup)
3404      {
3405         // wake up mainloop
3406         if (wd->calc_job) ecore_job_del(wd->calc_job);
3407         wd->calc_job = ecore_job_add(_calc_job, wd);
3408      }
3409    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3410    return ok;
3411 }
3412
3413 static void
3414 _item_queue(Widget_Data *wd,
3415             Elm_Gen_Item *it,
3416             Eina_Compare_Cb cb)
3417 {
3418    if (it->item->queued) return;
3419    it->item->queued = EINA_TRUE;
3420    if (cb)
3421      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
3422    else
3423      wd->queue = eina_list_append(wd->queue, it);
3424 // FIXME: why does a freeze then thaw here cause some genlist
3425 // elm_genlist_item_append() to be much much slower?
3426 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3427    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3428      {
3429         if (wd->queue_idle_enterer)
3430           {
3431              ecore_idle_enterer_del(wd->queue_idle_enterer);
3432              wd->queue_idle_enterer = NULL;
3433           }
3434         _queue_process(wd);
3435      }
3436 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3437 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3438    if (!wd->queue_idle_enterer)
3439      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3440 }
3441
3442 static int
3443 _elm_genlist_item_compare_data(const void *data, const void *data1)
3444 {
3445    const Elm_Gen_Item *it = data;
3446    const Elm_Gen_Item *item1 = data1;
3447
3448    return _elm_genlist_item_compare_data_cb(it->base.data, item1->base.data);
3449 }
3450
3451 static int
3452 _elm_genlist_item_compare(const void *data, const void *data1)
3453 {
3454    const Elm_Gen_Item *it, *item1;
3455    it = ELM_GEN_ITEM_FROM_INLIST(data);
3456    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
3457    return _elm_genlist_item_compare_cb(it, item1);
3458 }
3459
3460 static int
3461 _elm_genlist_item_list_compare(const void *data, const void *data1)
3462 {
3463    const Elm_Gen_Item *it = data;
3464    const Elm_Gen_Item *item1 = data1;
3465    return _elm_genlist_item_compare_cb(it, item1);
3466 }
3467
3468 static void
3469 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
3470 {
3471    if (!it) return;
3472    if (!after) return;
3473
3474    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3475    _item_block_del(it);
3476
3477    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3478    it->item->rel = after;
3479    it->item->rel->relcount++;
3480    it->item->before = EINA_FALSE;
3481    if (after->item->group_item) it->item->group_item = after->item->group_item;
3482    _item_queue(it->wd, it, NULL);
3483
3484    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3485 }
3486
3487 static void
3488 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
3489 {
3490    if (!it) return;
3491    if (!before) return;
3492
3493    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3494    _item_block_del(it);
3495    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3496    it->item->rel = before;
3497    it->item->rel->relcount++;
3498    it->item->before = EINA_TRUE;
3499    if (before->item->group_item) it->item->group_item = before->item->group_item;
3500    _item_queue(it->wd, it, NULL);
3501
3502    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3503 }
3504
3505 EAPI Elm_Gen_Item *
3506 elm_genlist_item_append(Evas_Object                  *obj,
3507                         const Elm_Genlist_Item_Class *itc,
3508                         const void                   *data,
3509                         Elm_Gen_Item             *parent,
3510                         Elm_Genlist_Item_Flags        flags,
3511                         Evas_Smart_Cb                 func,
3512                         const void                   *func_data)
3513 {
3514    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3515    Widget_Data *wd = elm_widget_data_get(obj);
3516    if (!wd) return NULL;
3517    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3518                                     func_data);
3519    if (!it) return NULL;
3520    if (!it->parent)
3521      {
3522         if (it->group)
3523           wd->group_items = eina_list_append(wd->group_items, it);
3524         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3525         it->item->rel = NULL;
3526      }
3527    else
3528      {
3529         Elm_Gen_Item *it2 = NULL;
3530         Eina_List *ll = eina_list_last(it->parent->item->items);
3531         if (ll) it2 = ll->data;
3532         it->parent->item->items = eina_list_append(it->parent->item->items, it);
3533         if (!it2) it2 = it->parent;
3534         wd->items =
3535           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3536                                       EINA_INLIST_GET(it2));
3537         it->item->rel = it2;
3538         it->item->rel->relcount++;
3539      }
3540    it->item->before = EINA_FALSE;
3541    _item_queue(wd, it, NULL);
3542    return it;
3543 }
3544
3545 EAPI Elm_Gen_Item *
3546 elm_genlist_item_prepend(Evas_Object                  *obj,
3547                          const Elm_Genlist_Item_Class *itc,
3548                          const void                   *data,
3549                          Elm_Gen_Item             *parent,
3550                          Elm_Genlist_Item_Flags        flags,
3551                          Evas_Smart_Cb                 func,
3552                          const void                   *func_data)
3553 {
3554    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3555    Widget_Data *wd = elm_widget_data_get(obj);
3556    if (!wd) return NULL;
3557    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3558                                     func_data);
3559    if (!it) return NULL;
3560    if (!it->parent)
3561      {
3562         if (it->group)
3563           wd->group_items = eina_list_prepend(wd->group_items, it);
3564         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3565         it->item->rel = NULL;
3566      }
3567    else
3568      {
3569         Elm_Gen_Item *it2 = NULL;
3570         Eina_List *ll = it->parent->item->items;
3571         if (ll) it2 = ll->data;
3572         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
3573         if (!it2) it2 = it->parent;
3574         wd->items =
3575           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3576                                        EINA_INLIST_GET(it2));
3577         it->item->rel = it2;
3578         it->item->rel->relcount++;
3579      }
3580    it->item->before = EINA_TRUE;
3581    _item_queue(wd, it, NULL);
3582    return it;
3583 }
3584
3585 EAPI Elm_Gen_Item *
3586 elm_genlist_item_insert_after(Evas_Object                  *obj,
3587                               const Elm_Genlist_Item_Class *itc,
3588                               const void                   *data,
3589                               Elm_Gen_Item             *parent,
3590                               Elm_Gen_Item             *after,
3591                               Elm_Genlist_Item_Flags        flags,
3592                               Evas_Smart_Cb                 func,
3593                               const void                   *func_data)
3594 {
3595    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3596    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
3597    Widget_Data *wd = elm_widget_data_get(obj);
3598    if (!wd) return NULL;
3599    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
3600    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3601
3602    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3603                                     func_data);
3604    if (!it) return NULL;
3605    if (!it->parent)
3606      {
3607         if ((it->group) &&
3608             (after->group))
3609           wd->group_items = eina_list_append_relative(wd->group_items, it,
3610                                                       after);
3611      }
3612    else
3613      {
3614         it->parent->item->items = eina_list_append_relative(it->parent->item->items, it,
3615                                                       after);
3616      }
3617    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3618                                            EINA_INLIST_GET(after));
3619    it->item->rel = after;
3620    it->item->rel->relcount++;
3621    it->item->before = EINA_FALSE;
3622    _item_queue(wd, it, NULL);
3623    return it;
3624 }
3625
3626 EAPI Elm_Gen_Item *
3627 elm_genlist_item_insert_before(Evas_Object                  *obj,
3628                                const Elm_Genlist_Item_Class *itc,
3629                                const void                   *data,
3630                                Elm_Gen_Item             *parent,
3631                                Elm_Gen_Item             *before,
3632                                Elm_Genlist_Item_Flags        flags,
3633                                Evas_Smart_Cb                 func,
3634                                const void                   *func_data)
3635 {
3636    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3637    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
3638    Widget_Data *wd = elm_widget_data_get(obj);
3639    if (!wd) return NULL;
3640    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
3641    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3642
3643    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3644                                     func_data);
3645    if (!it) return NULL;
3646    if (!it->parent)
3647      {
3648         if (it->group && before->group)
3649           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
3650                                                        before);
3651      }
3652    else
3653      {
3654         it->parent->item->items = eina_list_prepend_relative(it->parent->item->items, it,
3655                                                        before);
3656      }
3657    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3658                                             EINA_INLIST_GET(before));
3659    it->item->rel = before;
3660    it->item->rel->relcount++;
3661    it->item->before = EINA_TRUE;
3662    _item_queue(wd, it, NULL);
3663    return it;
3664 }
3665
3666 EAPI Elm_Gen_Item *
3667 elm_genlist_item_direct_sorted_insert(Evas_Object                  *obj,
3668                                       const Elm_Genlist_Item_Class *itc,
3669                                       const void                   *data,
3670                                       Elm_Gen_Item             *parent,
3671                                       Elm_Genlist_Item_Flags        flags,
3672                                       Eina_Compare_Cb               comp,
3673                                       Evas_Smart_Cb                 func,
3674                                       const void                   *func_data)
3675 {
3676    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3677    Widget_Data *wd = elm_widget_data_get(obj);
3678    if (!wd) return NULL;
3679    Elm_Gen_Item *rel = NULL;
3680    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3681                                     func_data);
3682    if (!it) return NULL;
3683
3684    _elm_genlist_item_compare_cb = comp;
3685
3686    if (it->parent)
3687      {
3688         Eina_List *l;
3689         int cmp_result;
3690
3691         l = eina_list_search_sorted_near_list(it->parent->item->items,
3692                                               _elm_genlist_item_list_compare, it,
3693                                               &cmp_result);
3694         if (l)
3695           rel = eina_list_data_get(l);
3696         else
3697           rel = it->parent;
3698
3699         if (cmp_result >= 0)
3700           {
3701              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
3702              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3703              it->item->before = EINA_FALSE;
3704           }
3705         else if (cmp_result < 0)
3706           {
3707              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
3708              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3709              it->item->before = EINA_TRUE;
3710           }
3711      }
3712    else
3713      {
3714         if (!wd->state)
3715           {
3716              wd->state = eina_inlist_sorted_state_new();
3717              eina_inlist_sorted_state_init(wd->state, wd->items);
3718           }
3719
3720         if (it->group)
3721           wd->group_items = eina_list_append(wd->group_items, it);
3722
3723         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
3724                                                     _elm_genlist_item_compare, wd->state);
3725
3726         if (EINA_INLIST_GET(it)->next)
3727           {
3728              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3729              it->item->before = EINA_TRUE;
3730           }
3731         else if (EINA_INLIST_GET(it)->prev)
3732           {
3733              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3734              it->item->before = EINA_FALSE;
3735           }
3736      }
3737
3738    if (rel)
3739      {
3740         it->item->rel = rel;
3741         it->item->rel->relcount++;
3742      }
3743
3744    _item_queue(wd, it, comp);
3745
3746    return it;
3747 }
3748
3749 EAPI Elm_Gen_Item *
3750 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
3751                                const Elm_Genlist_Item_Class *itc,
3752                                const void                   *data,
3753                                Elm_Gen_Item             *parent,
3754                                Elm_Genlist_Item_Flags        flags,
3755                                Eina_Compare_Cb               comp,
3756                                Evas_Smart_Cb                 func,
3757                                const void                   *func_data)
3758 {
3759    _elm_genlist_item_compare_data_cb = comp;
3760
3761    return elm_genlist_item_direct_sorted_insert(obj, itc, data, parent, flags,
3762                                                 _elm_genlist_item_compare_data, func, func_data);
3763 }
3764
3765 static void
3766 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
3767 {
3768    Eina_Inlist *next, *l;
3769
3770    ELM_CHECK_WIDTYPE(obj, widtype);
3771    Widget_Data *wd = elm_widget_data_get(obj);
3772    if (!wd) return;
3773
3774    if (!standby) wd->generation++;
3775
3776    if (wd->state)
3777      {
3778         eina_inlist_sorted_state_free(wd->state);
3779         wd->state = NULL;
3780      }
3781
3782    if (wd->walking > 0)
3783      {
3784         wd->clear_me = 1;
3785         return;
3786      }
3787    evas_event_freeze(evas_object_evas_get(wd->obj));
3788    for (l = wd->items, next = l ? l->next : NULL;
3789         l;
3790         l = next, next = next ? next->next : NULL)
3791      {
3792         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
3793
3794         if (it->generation < wd->generation)
3795           {
3796              Elm_Gen_Item *itn = NULL;
3797
3798              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
3799              if (itn) itn->walking++; /* prevent early death of subitem */
3800              it->del_cb(it);
3801              if (itn) itn->walking--;
3802           }
3803      }
3804    wd->clear_me = 0;
3805    if (wd->calc_job)
3806      {
3807         ecore_job_del(wd->calc_job);
3808         wd->calc_job = NULL;
3809      }
3810    if (wd->selected) wd->selected = eina_list_free(wd->selected);
3811    if (wd->clear_cb) wd->clear_cb(wd);
3812    wd->pan_x = 0;
3813    wd->pan_y = 0;
3814    wd->minw = 0;
3815    wd->minh = 0;
3816    wd->count = 0;
3817    if (wd->pan_smart)
3818      {
3819         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
3820         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
3821      }
3822    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
3823    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
3824    evas_event_thaw(evas_object_evas_get(wd->obj));
3825    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3826 }
3827
3828 EAPI void
3829 elm_genlist_clear(Evas_Object *obj)
3830 {
3831    _elm_genlist_clear(obj, EINA_FALSE);
3832 }
3833
3834 EAPI void
3835 elm_genlist_multi_select_set(Evas_Object *obj,
3836                              Eina_Bool    multi)
3837 {
3838    ELM_CHECK_WIDTYPE(obj, widtype);
3839    Widget_Data *wd = elm_widget_data_get(obj);
3840    if (!wd) return;
3841    wd->multi = multi;
3842 }
3843
3844 EAPI Eina_Bool
3845 elm_genlist_multi_select_get(const Evas_Object *obj)
3846 {
3847    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3848    Widget_Data *wd = elm_widget_data_get(obj);
3849    if (!wd) return EINA_FALSE;
3850    return wd->multi;
3851 }
3852
3853 EAPI Elm_Gen_Item *
3854 elm_genlist_selected_item_get(const Evas_Object *obj)
3855 {
3856    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3857    Widget_Data *wd = elm_widget_data_get(obj);
3858    if (!wd) return NULL;
3859    if (wd->selected) return wd->selected->data;
3860    return NULL;
3861 }
3862
3863 EAPI const Eina_List *
3864 elm_genlist_selected_items_get(const Evas_Object *obj)
3865 {
3866    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3867    Widget_Data *wd = elm_widget_data_get(obj);
3868    if (!wd) return NULL;
3869    return wd->selected;
3870 }
3871
3872 EAPI Eina_List *
3873 elm_genlist_realized_items_get(const Evas_Object *obj)
3874 {
3875    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3876    Widget_Data *wd = elm_widget_data_get(obj);
3877    Eina_List *list = NULL;
3878    Item_Block *itb;
3879    Eina_Bool done = EINA_FALSE;
3880    if (!wd) return NULL;
3881    EINA_INLIST_FOREACH(wd->blocks, itb)
3882      {
3883         if (itb->realized)
3884           {
3885              Eina_List *l;
3886              Elm_Gen_Item *it;
3887
3888              done = 1;
3889              EINA_LIST_FOREACH(itb->items, l, it)
3890                {
3891                   if (it->realized) list = eina_list_append(list, it);
3892                }
3893           }
3894         else
3895           {
3896              if (done) break;
3897           }
3898      }
3899    return list;
3900 }
3901
3902 EAPI Elm_Gen_Item *
3903 elm_genlist_at_xy_item_get(const Evas_Object *obj,
3904                            Evas_Coord         x,
3905                            Evas_Coord         y,
3906                            int               *posret)
3907 {
3908    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3909    Widget_Data *wd = elm_widget_data_get(obj);
3910    Evas_Coord ox, oy, ow, oh;
3911    Item_Block *itb;
3912    Evas_Coord lasty;
3913    if (!wd) return NULL;
3914    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
3915    lasty = oy;
3916    EINA_INLIST_FOREACH(wd->blocks, itb)
3917      {
3918         Eina_List *l;
3919         Elm_Gen_Item *it;
3920
3921         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
3922                                  oy + itb->y - itb->wd->pan_y,
3923                                  itb->w, itb->h, x, y, 1, 1))
3924           continue;
3925         EINA_LIST_FOREACH(itb->items, l, it)
3926           {
3927              Evas_Coord itx, ity;
3928
3929              itx = ox + itb->x + it->x - itb->wd->pan_x;
3930              ity = oy + itb->y + it->y - itb->wd->pan_y;
3931              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
3932                {
3933                   if (posret)
3934                     {
3935                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
3936                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
3937                          *posret = 1;
3938                        else *posret = 0;
3939                     }
3940                   return it;
3941                }
3942              lasty = ity + it->item->h;
3943           }
3944      }
3945    if (posret)
3946      {
3947         if (y > lasty) *posret = 1;
3948         else *posret = -1;
3949      }
3950    return NULL;
3951 }
3952
3953 EAPI Elm_Gen_Item *
3954 elm_genlist_first_item_get(const Evas_Object *obj)
3955 {
3956    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3957    Widget_Data *wd = elm_widget_data_get(obj);
3958    if (!wd) return NULL;
3959    if (!wd->items) return NULL;
3960    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
3961    while ((it) && (it->generation < wd->generation))
3962      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3963    return it;
3964 }
3965
3966 EAPI Elm_Gen_Item *
3967 elm_genlist_last_item_get(const Evas_Object *obj)
3968 {
3969    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3970    Widget_Data *wd = elm_widget_data_get(obj);
3971    if (!wd) return NULL;
3972    if (!wd->items) return NULL;
3973    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
3974    while ((it) && (it->generation < wd->generation))
3975      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3976    return it;
3977 }
3978
3979 EAPI Elm_Gen_Item *
3980 elm_genlist_item_next_get(const Elm_Gen_Item *it)
3981 {
3982    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
3983    while (it)
3984      {
3985         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3986         if ((it) && (it->generation == it->wd->generation)) break;
3987      }
3988    return (Elm_Gen_Item *)it;
3989 }
3990
3991 EAPI Elm_Gen_Item *
3992 elm_genlist_item_prev_get(const Elm_Gen_Item *it)
3993 {
3994    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
3995    while (it)
3996      {
3997         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3998         if ((it) && (it->generation == it->wd->generation)) break;
3999      }
4000    return (Elm_Gen_Item *)it;
4001 }
4002
4003 EAPI Evas_Object *
4004 elm_genlist_item_genlist_get(const Elm_Gen_Item *it)
4005 {
4006    return _elm_genlist_item_widget_get(it);
4007 }
4008
4009 EAPI Elm_Gen_Item *
4010 elm_genlist_item_parent_get(const Elm_Gen_Item *it)
4011 {
4012    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4013    return it->parent;
4014 }
4015
4016 EAPI void
4017 elm_genlist_item_subitems_clear(Elm_Gen_Item *it)
4018 {
4019    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4020    Eina_List *tl = NULL, *l;
4021    Elm_Gen_Item *it2;
4022
4023    EINA_LIST_FOREACH(it->item->items, l, it2)
4024      tl = eina_list_append(tl, it2);
4025    EINA_LIST_FREE(tl, it2)
4026      elm_genlist_item_del(it2);
4027 }
4028
4029 EAPI void
4030 elm_genlist_item_selected_set(Elm_Gen_Item *it,
4031                               Eina_Bool         selected)
4032 {
4033    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4034    Widget_Data *wd = it->wd;
4035    if (!wd) return;
4036    if ((it->generation < wd->generation) || (it->disabled)) return;
4037    selected = !!selected;
4038    if (it->selected == selected) return;
4039
4040    if (selected)
4041      {
4042         if (!wd->multi)
4043           {
4044              while (wd->selected)
4045                {
4046                   if (it->unhighlight_cb) it->unhighlight_cb(wd->selected->data);
4047                   it->unsel_cb(wd->selected->data);
4048                }
4049           }
4050         it->highlight_cb(it);
4051         _item_select(it);
4052         return;
4053      }
4054    if (it->unhighlight_cb) it->unhighlight_cb(it);
4055    it->unsel_cb(it);
4056 }
4057
4058 EAPI Eina_Bool
4059 elm_genlist_item_selected_get(const Elm_Gen_Item *it)
4060 {
4061    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4062    return it->selected;
4063 }
4064
4065 EAPI void
4066 elm_genlist_item_expanded_set(Elm_Gen_Item *it,
4067                               Eina_Bool         expanded)
4068 {
4069    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4070    if (it->item->expanded == expanded) return;
4071    it->item->expanded = expanded;
4072    it->wd->expanded_item = it;
4073    if (it->item->expanded)
4074      {
4075         if (it->realized)
4076           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
4077         evas_object_smart_callback_call(WIDGET(it), SIG_EXPANDED, it);
4078         it->wd->auto_scroll_enabled = EINA_TRUE;
4079      }
4080    else
4081      {
4082         if (it->realized)
4083           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
4084         evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACTED, it);
4085         it->wd->auto_scroll_enabled = EINA_FALSE;
4086      }
4087 }
4088
4089 EAPI Eina_Bool
4090 elm_genlist_item_expanded_get(const Elm_Gen_Item *it)
4091 {
4092    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4093    return it->item->expanded;
4094 }
4095
4096 EAPI int
4097 elm_genlist_item_expanded_depth_get(const Elm_Gen_Item *it)
4098 {
4099    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
4100    return it->item->expanded_depth;
4101 }
4102
4103 EAPI void
4104 elm_genlist_item_disabled_set(Elm_Gen_Item *it,
4105                               Eina_Bool         disabled)
4106 {
4107    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4108    Eina_List *l;
4109    Evas_Object *obj;
4110    if (it->disabled == disabled) return;
4111    if (it->generation < it->wd->generation) return;
4112    it->disabled = !!disabled;
4113    if (it->selected)
4114      elm_genlist_item_selected_set(it, EINA_FALSE);
4115    if (it->realized)
4116      {
4117         if (it->disabled)
4118           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
4119         else
4120           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
4121         EINA_LIST_FOREACH(it->content_objs, l, obj)
4122           elm_widget_disabled_set(obj, disabled);
4123      }
4124 }
4125
4126 EAPI Eina_Bool
4127 elm_genlist_item_disabled_get(const Elm_Gen_Item *it)
4128 {
4129    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4130    if (it->generation < it->wd->generation) return EINA_FALSE;
4131    return it->disabled;
4132 }
4133
4134 EAPI void
4135 elm_genlist_item_display_only_set(Elm_Gen_Item *it,
4136                                   Eina_Bool         display_only)
4137 {
4138    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4139    if (it->display_only == display_only) return;
4140    if (it->generation < it->wd->generation) return;
4141    it->display_only = display_only;
4142    it->item->mincalcd = EINA_FALSE;
4143    it->item->updateme = EINA_TRUE;
4144    if (it->item->block) it->item->block->updateme = EINA_TRUE;
4145    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4146    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4147 }
4148
4149 EAPI Eina_Bool
4150 elm_genlist_item_display_only_get(const Elm_Gen_Item *it)
4151 {
4152    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4153    if (it->generation < it->wd->generation) return EINA_FALSE;
4154    return it->display_only;
4155 }
4156
4157 EAPI void
4158 elm_genlist_item_show(Elm_Gen_Item *it)
4159 {
4160    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4161    Evas_Coord gith = 0;
4162    if (it->generation < it->wd->generation) return;
4163    if ((it->item->queued) || (!it->item->mincalcd))
4164      {
4165         it->wd->show_item = it;
4166         it->wd->bring_in = EINA_TRUE;
4167         it->item->showme = EINA_TRUE;
4168         return;
4169      }
4170    if (it->wd->show_item)
4171      {
4172         it->wd->show_item->item->showme = EINA_FALSE;
4173         it->wd->show_item = NULL;
4174      }
4175    if ((it->item->group_item) && (it->wd->pan_y > (it->y + it->item->block->y)))
4176      gith = it->item->group_item->item->h;
4177    elm_smart_scroller_child_region_show(it->wd->scr,
4178                                         it->x + it->item->block->x,
4179                                         it->y + it->item->block->y - gith,
4180                                         it->item->block->w, it->item->h);
4181 }
4182
4183 EAPI void
4184 elm_genlist_item_promote(Elm_Gen_Item *it)
4185 {
4186    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4187    if (it->generation < it->wd->generation) return;
4188    _item_move_before(it, elm_genlist_first_item_get(WIDGET(it)));
4189 }
4190
4191 EAPI void
4192 elm_genlist_item_demote(Elm_Gen_Item *it)
4193 {
4194    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4195    if (it->generation < it->wd->generation) return;
4196    _item_move_after(it, elm_genlist_last_item_get(WIDGET(it)));
4197 }
4198
4199 EAPI void
4200 elm_genlist_item_bring_in(Elm_Gen_Item *it)
4201 {
4202    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4203    Evas_Coord gith = 0;
4204    if (it->generation < it->wd->generation) return;
4205    if ((it->item->queued) || (!it->item->mincalcd))
4206      {
4207         it->wd->show_item = it;
4208         it->wd->bring_in = EINA_TRUE;
4209         it->item->showme = EINA_TRUE;
4210         return;
4211      }
4212    if (it->wd->show_item)
4213      {
4214         it->wd->show_item->item->showme = EINA_FALSE;
4215         it->wd->show_item = NULL;
4216      }
4217    if ((it->item->group_item) && (it->wd->pan_y > (it->y + it->item->block->y)))
4218      gith = it->item->group_item->item->h;
4219    elm_smart_scroller_region_bring_in(it->wd->scr,
4220                                       it->x + it->item->block->x,
4221                                       it->y + it->item->block->y - gith,
4222                                       it->item->block->w, it->item->h);
4223 }
4224
4225 EAPI void
4226 elm_genlist_item_top_show(Elm_Gen_Item *it)
4227 {
4228    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4229    Evas_Coord ow, oh;
4230    Evas_Coord gith = 0;
4231
4232    if (it->generation < it->wd->generation) return;
4233    if ((it->item->queued) || (!it->item->mincalcd))
4234      {
4235         it->wd->show_item = it;
4236         it->wd->bring_in = EINA_TRUE;
4237         it->item->showme = EINA_TRUE;
4238         return;
4239      }
4240    if (it->wd->show_item)
4241      {
4242         it->wd->show_item->item->showme = EINA_FALSE;
4243         it->wd->show_item = NULL;
4244      }
4245    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4246    if (it->item->group_item) gith = it->item->group_item->item->h;
4247    elm_smart_scroller_child_region_show(it->wd->scr,
4248                                         it->x + it->item->block->x,
4249                                         it->y + it->item->block->y - gith,
4250                                         it->item->block->w, oh);
4251 }
4252
4253 EAPI void
4254 elm_genlist_item_top_bring_in(Elm_Gen_Item *it)
4255 {
4256    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4257    Evas_Coord ow, oh;
4258    Evas_Coord gith = 0;
4259
4260    if (it->generation < it->wd->generation) return;
4261    if ((it->item->queued) || (!it->item->mincalcd))
4262      {
4263         it->wd->show_item = it;
4264         it->wd->bring_in = EINA_TRUE;
4265         it->item->showme = EINA_TRUE;
4266         return;
4267      }
4268    if (it->wd->show_item)
4269      {
4270         it->wd->show_item->item->showme = EINA_FALSE;
4271         it->wd->show_item = NULL;
4272      }
4273    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4274    if (it->item->group_item) gith = it->item->group_item->item->h;
4275    elm_smart_scroller_region_bring_in(it->wd->scr,
4276                                       it->x + it->item->block->x,
4277                                       it->y + it->item->block->y - gith,
4278                                       it->item->block->w, oh);
4279 }
4280
4281 EAPI void
4282 elm_genlist_item_middle_show(Elm_Gen_Item *it)
4283 {
4284    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4285    Evas_Coord ow, oh;
4286
4287    if (it->generation < it->wd->generation) return;
4288    if ((it->item->queued) || (!it->item->mincalcd))
4289      {
4290         it->wd->show_item = it;
4291         it->wd->bring_in = EINA_TRUE;
4292         it->item->showme = EINA_TRUE;
4293         return;
4294      }
4295    if (it->wd->show_item)
4296      {
4297         it->wd->show_item->item->showme = EINA_FALSE;
4298         it->wd->show_item = NULL;
4299      }
4300    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4301    elm_smart_scroller_child_region_show(it->wd->scr,
4302                                         it->x + it->item->block->x,
4303                                         it->y + it->item->block->y - oh / 2 +
4304                                         it->item->h / 2, it->item->block->w, oh);
4305 }
4306
4307 EAPI void
4308 elm_genlist_item_middle_bring_in(Elm_Gen_Item *it)
4309 {
4310    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4311    Evas_Coord ow, oh;
4312
4313    if (it->generation < it->wd->generation) return;
4314    if ((it->item->queued) || (!it->item->mincalcd))
4315      {
4316         it->wd->show_item = it;
4317         it->wd->bring_in = EINA_TRUE;
4318         it->item->showme = EINA_TRUE;
4319         return;
4320      }
4321    if (it->wd->show_item)
4322      {
4323         it->wd->show_item->item->showme = EINA_FALSE;
4324         it->wd->show_item = NULL;
4325      }
4326    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4327    elm_smart_scroller_region_bring_in(it->wd->scr,
4328                                       it->x + it->item->block->x,
4329                                       it->y + it->item->block->y - oh / 2 + it->item->h / 2,
4330                                       it->item->block->w, oh);
4331 }
4332
4333 EAPI void
4334 elm_genlist_item_del(Elm_Gen_Item *it)
4335 {
4336    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4337    if ((it->relcount > 0) || (it->walking > 0))
4338      {
4339         elm_genlist_item_subitems_clear(it);
4340         if (it->wd->show_item == it) it->wd->show_item = NULL;
4341         _elm_genlist_item_del_notserious(it);
4342         if (it->item->block)
4343           {
4344              if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
4345              it->item->block->changed = EINA_TRUE;
4346              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
4347              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
4348           }
4349         if (it->parent)
4350           {
4351              it->parent->item->items = eina_list_remove(it->parent->item->items, it);
4352              it->parent = NULL;
4353           }
4354         return;
4355      }
4356    _item_del(it);
4357 }
4358
4359 EAPI void
4360 elm_genlist_item_data_set(Elm_Gen_Item *it,
4361                           const void       *data)
4362 {
4363    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4364    elm_widget_item_data_set(it, data);
4365 }
4366
4367 EAPI void *
4368 elm_genlist_item_data_get(const Elm_Gen_Item *it)
4369 {
4370    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4371    return elm_widget_item_data_get(it);
4372 }
4373
4374 EAPI void
4375 elm_genlist_item_icons_orphan(Elm_Gen_Item *it)
4376 {
4377    elm_genlist_item_contents_orphan(it);
4378 }
4379
4380 EAPI void
4381 elm_genlist_item_contents_orphan(Elm_Gen_Item *it)
4382 {
4383    Evas_Object *content;
4384    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4385    EINA_LIST_FREE(it->content_objs, content)
4386      {
4387         elm_widget_sub_object_del(WIDGET(it), content);
4388         evas_object_smart_member_del(content);
4389         evas_object_hide(content);
4390      }
4391 }
4392
4393 EAPI const Evas_Object *
4394 elm_genlist_item_object_get(const Elm_Gen_Item *it)
4395 {
4396    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4397    return VIEW(it);
4398 }
4399
4400 EAPI void
4401 elm_genlist_item_update(Elm_Gen_Item *it)
4402 {
4403    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4404    if (!it->item->block) return;
4405    if (it->generation < it->wd->generation) return;
4406    it->item->mincalcd = EINA_FALSE;
4407    it->item->updateme = EINA_TRUE;
4408    it->item->block->updateme = EINA_TRUE;
4409    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4410    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4411 }
4412
4413 EAPI void
4414 elm_genlist_item_fields_update(Elm_Genlist_Item *it,
4415                                const char *parts,
4416                                Elm_Genlist_Item_Field_Flags itf)
4417 {
4418    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4419    if (!it->item->block) return;
4420    if (it->generation < it->wd->generation) return;
4421
4422    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4423      _item_label_realize(it, it->base.view, &it->labels, parts);
4424    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4425      {
4426         it->content_objs = _item_content_unrealize(it, it->base.view,
4427                                                    &it->contents, parts);
4428         it->content_objs = _item_content_realize(it, it->base.view,
4429                                                  &it->contents, parts);
4430      }
4431    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4432      _item_state_realize(it, it->base.view, &it->states, parts);
4433 }
4434
4435 EAPI void
4436 elm_genlist_item_item_class_update(Elm_Gen_Item             *it,
4437                                    const Elm_Genlist_Item_Class *itc)
4438 {
4439    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4440    if (!it->item->block) return;
4441    EINA_SAFETY_ON_NULL_RETURN(itc);
4442    if (it->generation < it->wd->generation) return;
4443    it->itc = itc;
4444    it->item->nocache = EINA_TRUE;
4445    elm_genlist_item_update(it);
4446 }
4447
4448 EAPI const Elm_Genlist_Item_Class *
4449 elm_genlist_item_item_class_get(const Elm_Gen_Item *it)
4450 {
4451    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4452    if (it->generation < it->wd->generation) return NULL;
4453    return it->itc;
4454 }
4455
4456 static Evas_Object *
4457 _elm_genlist_item_label_create(void        *data,
4458                                Evas_Object *obj __UNUSED__,
4459                                Evas_Object *tooltip,
4460                                void        *it __UNUSED__)
4461 {
4462    Evas_Object *label = elm_label_add(tooltip);
4463    if (!label)
4464      return NULL;
4465    elm_object_style_set(label, "tooltip");
4466    elm_object_text_set(label, data);
4467    return label;
4468 }
4469
4470 static void
4471 _elm_genlist_item_label_del_cb(void        *data,
4472                                Evas_Object *obj __UNUSED__,
4473                                void        *event_info __UNUSED__)
4474 {
4475    eina_stringshare_del(data);
4476 }
4477
4478 EAPI void
4479 elm_genlist_item_tooltip_text_set(Elm_Gen_Item *it,
4480                                   const char       *text)
4481 {
4482    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4483    text = eina_stringshare_add(text);
4484    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4485                                            text,
4486                                            _elm_genlist_item_label_del_cb);
4487 }
4488
4489 EAPI void
4490 elm_genlist_item_tooltip_content_cb_set(Elm_Gen_Item           *it,
4491                                         Elm_Tooltip_Item_Content_Cb func,
4492                                         const void                 *data,
4493                                         Evas_Smart_Cb               del_cb)
4494 {
4495    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, error);
4496
4497    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
4498      return;
4499
4500    if (it->tooltip.del_cb)
4501      it->tooltip.del_cb((void *)it->tooltip.data,
4502                           WIDGET(it), it);
4503
4504    it->tooltip.content_cb = func;
4505    it->tooltip.data = data;
4506    it->tooltip.del_cb = del_cb;
4507
4508    if (VIEW(it))
4509      {
4510         elm_widget_item_tooltip_content_cb_set(it,
4511                                                it->tooltip.content_cb,
4512                                                it->tooltip.data, NULL);
4513         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
4514         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
4515      }
4516
4517    return;
4518
4519 error:
4520    if (del_cb) del_cb((void *)data, NULL, NULL);
4521 }
4522
4523 EAPI void
4524 elm_genlist_item_tooltip_unset(Elm_Gen_Item *it)
4525 {
4526    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4527    if ((VIEW(it)) && (it->tooltip.content_cb))
4528      elm_widget_item_tooltip_unset(it);
4529
4530    if (it->tooltip.del_cb)
4531      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
4532    it->tooltip.del_cb = NULL;
4533    it->tooltip.content_cb = NULL;
4534    it->tooltip.data = NULL;
4535    it->tooltip.free_size = EINA_FALSE;
4536    if (it->tooltip.style)
4537      elm_genlist_item_tooltip_style_set(it, NULL);
4538 }
4539
4540 EAPI void
4541 elm_genlist_item_tooltip_style_set(Elm_Gen_Item *it,
4542                                    const char       *style)
4543 {
4544    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4545    eina_stringshare_replace(&it->tooltip.style, style);
4546    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
4547 }
4548
4549 EAPI const char *
4550 elm_genlist_item_tooltip_style_get(const Elm_Gen_Item *it)
4551 {
4552    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4553    return it->tooltip.style;
4554 }
4555
4556 EAPI Eina_Bool
4557 elm_genlist_item_tooltip_size_restrict_disable(Elm_Gen_Item *it, Eina_Bool disable)
4558 {
4559    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4560    it->tooltip.free_size = disable;
4561    if (VIEW(it)) return elm_widget_item_tooltip_size_restrict_disable(it, disable);
4562    return EINA_TRUE;
4563 }
4564
4565 EAPI Eina_Bool
4566 elm_genlist_item_tooltip_size_restrict_disabled_get(const Elm_Gen_Item *it)
4567 {
4568    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4569    return it->tooltip.free_size;
4570 }
4571
4572 EAPI void
4573 elm_genlist_item_cursor_set(Elm_Gen_Item *it,
4574                             const char       *cursor)
4575 {
4576    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4577    eina_stringshare_replace(&it->mouse_cursor, cursor);
4578    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
4579 }
4580
4581 EAPI const char *
4582 elm_genlist_item_cursor_get(const Elm_Gen_Item *it)
4583 {
4584    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4585    return elm_widget_item_cursor_get(it);
4586 }
4587
4588 EAPI void
4589 elm_genlist_item_cursor_unset(Elm_Gen_Item *it)
4590 {
4591    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4592    if (!it->mouse_cursor)
4593      return;
4594
4595    if (VIEW(it))
4596      elm_widget_item_cursor_unset(it);
4597
4598    eina_stringshare_del(it->mouse_cursor);
4599    it->mouse_cursor = NULL;
4600 }
4601
4602 EAPI void
4603 elm_genlist_item_cursor_style_set(Elm_Gen_Item *it,
4604                                   const char       *style)
4605 {
4606    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4607    elm_widget_item_cursor_style_set(it, style);
4608 }
4609
4610 EAPI const char *
4611 elm_genlist_item_cursor_style_get(const Elm_Gen_Item *it)
4612 {
4613    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4614    return elm_widget_item_cursor_style_get(it);
4615 }
4616
4617 EAPI void
4618 elm_genlist_item_cursor_engine_only_set(Elm_Gen_Item *it,
4619                                         Eina_Bool         engine_only)
4620 {
4621    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4622    elm_widget_item_cursor_engine_only_set(it, engine_only);
4623 }
4624
4625 EAPI Eina_Bool
4626 elm_genlist_item_cursor_engine_only_get(const Elm_Gen_Item *it)
4627 {
4628    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4629    return elm_widget_item_cursor_engine_only_get(it);
4630 }
4631
4632 EAPI void
4633 elm_genlist_horizontal_set(Evas_Object  *obj,
4634                                 Elm_List_Mode mode)
4635 {
4636    ELM_CHECK_WIDTYPE(obj, widtype);
4637    Widget_Data *wd = elm_widget_data_get(obj);
4638    if (!wd) return;
4639    if (wd->mode == mode) return;
4640    wd->mode = mode;
4641    _sizing_eval(obj);
4642 }
4643
4644 EAPI void
4645 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4646                                 Elm_List_Mode mode)
4647 {
4648    elm_genlist_horizontal_set(obj, mode);
4649 }
4650
4651 EAPI Elm_List_Mode
4652 elm_genlist_horizontal_get(const Evas_Object *obj)
4653 {
4654    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4655    Widget_Data *wd = elm_widget_data_get(obj);
4656    if (!wd) return ELM_LIST_LAST;
4657    return wd->mode;
4658 }
4659
4660 EAPI Elm_List_Mode
4661 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
4662 {
4663    return elm_genlist_horizontal_get(obj);
4664 }
4665
4666 EAPI void
4667 elm_genlist_always_select_mode_set(Evas_Object *obj,
4668                                    Eina_Bool    always_select)
4669 {
4670    ELM_CHECK_WIDTYPE(obj, widtype);
4671    Widget_Data *wd = elm_widget_data_get(obj);
4672    if (!wd) return;
4673    wd->always_select = always_select;
4674 }
4675
4676 EAPI Eina_Bool
4677 elm_genlist_always_select_mode_get(const Evas_Object *obj)
4678 {
4679    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4680    Widget_Data *wd = elm_widget_data_get(obj);
4681    if (!wd) return EINA_FALSE;
4682    return wd->always_select;
4683 }
4684
4685 EAPI void
4686 elm_genlist_no_select_mode_set(Evas_Object *obj,
4687                                Eina_Bool    no_select)
4688 {
4689    ELM_CHECK_WIDTYPE(obj, widtype);
4690    Widget_Data *wd = elm_widget_data_get(obj);
4691    if (!wd) return;
4692    wd->no_select = no_select;
4693 }
4694
4695 EAPI Eina_Bool
4696 elm_genlist_no_select_mode_get(const Evas_Object *obj)
4697 {
4698    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4699    Widget_Data *wd = elm_widget_data_get(obj);
4700    if (!wd) return EINA_FALSE;
4701    return wd->no_select;
4702 }
4703
4704 EAPI void
4705 elm_genlist_compress_mode_set(Evas_Object *obj,
4706                               Eina_Bool    compress)
4707 {
4708    ELM_CHECK_WIDTYPE(obj, widtype);
4709    Widget_Data *wd = elm_widget_data_get(obj);
4710    if (!wd) return;
4711    wd->compress = compress;
4712    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
4713 }
4714
4715 EAPI Eina_Bool
4716 elm_genlist_compress_mode_get(const Evas_Object *obj)
4717 {
4718    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4719    Widget_Data *wd = elm_widget_data_get(obj);
4720    if (!wd) return EINA_FALSE;
4721    return wd->compress;
4722 }
4723
4724 EAPI void
4725 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
4726                                       Eina_Bool    height_for_width)
4727 {
4728    ELM_CHECK_WIDTYPE(obj, widtype);
4729    Widget_Data *wd = elm_widget_data_get(obj);
4730    if (!wd) return;
4731    wd->height_for_width = !!height_for_width;
4732    if (wd->height_for_width)
4733      {
4734         elm_genlist_homogeneous_set(obj, EINA_FALSE);
4735         elm_genlist_compress_mode_set(obj, EINA_TRUE);
4736      }
4737 }
4738
4739 EAPI Eina_Bool
4740 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
4741 {
4742    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4743    Widget_Data *wd = elm_widget_data_get(obj);
4744    if (!wd) return EINA_FALSE;
4745    return wd->height_for_width;
4746 }
4747
4748 EAPI void
4749 elm_genlist_bounce_set(Evas_Object *obj,
4750                        Eina_Bool    h_bounce,
4751                        Eina_Bool    v_bounce)
4752 {
4753    ELM_CHECK_WIDTYPE(obj, widtype);
4754    Widget_Data *wd = elm_widget_data_get(obj);
4755    if (!wd) return;
4756    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
4757    wd->h_bounce = h_bounce;
4758    wd->v_bounce = v_bounce;
4759 }
4760
4761 EAPI void
4762 elm_genlist_bounce_get(const Evas_Object *obj,
4763                        Eina_Bool         *h_bounce,
4764                        Eina_Bool         *v_bounce)
4765 {
4766    ELM_CHECK_WIDTYPE(obj, widtype);
4767    Widget_Data *wd = elm_widget_data_get(obj);
4768    if (!wd) return;
4769    if (h_bounce) *h_bounce = wd->h_bounce;
4770    if (v_bounce) *v_bounce = wd->v_bounce;
4771 }
4772
4773 EAPI void
4774 elm_genlist_homogeneous_set(Evas_Object *obj,
4775                             Eina_Bool    homogeneous)
4776 {
4777    ELM_CHECK_WIDTYPE(obj, widtype);
4778    Widget_Data *wd = elm_widget_data_get(obj);
4779    if (!wd) return;
4780    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
4781    wd->homogeneous = homogeneous;
4782 }
4783
4784 EAPI Eina_Bool
4785 elm_genlist_homogeneous_get(const Evas_Object *obj)
4786 {
4787    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4788    Widget_Data *wd = elm_widget_data_get(obj);
4789    if (!wd) return EINA_FALSE;
4790    return wd->homogeneous;
4791 }
4792
4793 EAPI void
4794 elm_genlist_block_count_set(Evas_Object *obj,
4795                             int          n)
4796 {
4797    ELM_CHECK_WIDTYPE(obj, widtype);
4798    Widget_Data *wd = elm_widget_data_get(obj);
4799    if (!wd) return;
4800    wd->max_items_per_block = n;
4801    wd->item_cache_max = wd->max_items_per_block * 2;
4802    _item_cache_clean(wd);
4803 }
4804
4805 EAPI int
4806 elm_genlist_block_count_get(const Evas_Object *obj)
4807 {
4808    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4809    Widget_Data *wd = elm_widget_data_get(obj);
4810    if (!wd) return 0;
4811    return wd->max_items_per_block;
4812 }
4813
4814 EAPI void
4815 elm_genlist_longpress_timeout_set(Evas_Object *obj,
4816                                   double       timeout)
4817 {
4818    ELM_CHECK_WIDTYPE(obj, widtype);
4819    Widget_Data *wd = elm_widget_data_get(obj);
4820    if (!wd) return;
4821    wd->longpress_timeout = timeout;
4822 }
4823
4824 EAPI double
4825 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
4826 {
4827    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4828    Widget_Data *wd = elm_widget_data_get(obj);
4829    if (!wd) return 0;
4830    return wd->longpress_timeout;
4831 }
4832
4833 EAPI void
4834 elm_genlist_scroller_policy_set(Evas_Object        *obj,
4835                                 Elm_Scroller_Policy policy_h,
4836                                 Elm_Scroller_Policy policy_v)
4837 {
4838    ELM_CHECK_WIDTYPE(obj, widtype);
4839    Widget_Data *wd = elm_widget_data_get(obj);
4840    if ((!wd) || (!wd->scr)) return;
4841    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
4842        (policy_v >= ELM_SCROLLER_POLICY_LAST))
4843      return;
4844    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
4845 }
4846
4847 EAPI void
4848 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
4849                                 Elm_Scroller_Policy *policy_h,
4850                                 Elm_Scroller_Policy *policy_v)
4851 {
4852    ELM_CHECK_WIDTYPE(obj, widtype);
4853    Widget_Data *wd = elm_widget_data_get(obj);
4854    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
4855    if ((!wd) || (!wd->scr)) return;
4856    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
4857    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
4858    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
4859 }
4860
4861 EAPI void
4862 elm_genlist_realized_items_update(Evas_Object *obj)
4863 {
4864    ELM_CHECK_WIDTYPE(obj, widtype);
4865
4866    Eina_List *list, *l;
4867    Elm_Gen_Item *it;
4868
4869    list = elm_genlist_realized_items_get(obj);
4870    EINA_LIST_FOREACH(list, l, it)
4871      elm_genlist_item_update(it);
4872 }
4873
4874 EAPI void
4875 elm_genlist_item_mode_set(Elm_Gen_Item *it,
4876                           const char       *mode_type,
4877                           Eina_Bool         mode_set)
4878 {
4879    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4880    Widget_Data *wd = it->wd;
4881    Eina_List *l;
4882    Elm_Gen_Item *it2;
4883
4884    if (!wd) return;
4885    if (!mode_type) return;
4886    if ((it->generation < it->wd->generation) || (it->disabled)) return;
4887
4888    if ((wd->mode_item == it) &&
4889        (!strcmp(mode_type, wd->mode_type)) &&
4890        (mode_set))
4891       return;
4892    if (!wd->mode_item_style) return;
4893    it->mode_set = mode_set;
4894
4895    if (wd->multi)
4896      {
4897         EINA_LIST_FOREACH(wd->selected, l, it2)
4898           if (it2->realized)
4899             elm_genlist_item_selected_set(it2, EINA_FALSE);
4900      }
4901    else
4902      {
4903         it2 = elm_genlist_selected_item_get(wd->obj);
4904         if ((it2) && (it2->realized))
4905           elm_genlist_item_selected_set(it2, EINA_FALSE);
4906      }
4907
4908    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
4909        (mode_set) ||
4910        ((it == wd->mode_item) && (!mode_set)))
4911      _item_mode_unset(wd);
4912
4913    eina_stringshare_replace(&wd->mode_type, mode_type);
4914    if (mode_set) _item_mode_set(it);
4915 }
4916
4917
4918 EAPI const char *
4919 elm_genlist_mode_item_style_get(const Evas_Object *obj)
4920 {
4921    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4922    Widget_Data *wd = elm_widget_data_get(obj);
4923    if (!wd) return NULL;
4924    return wd->mode_item_style;
4925 }
4926
4927 EAPI void
4928 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
4929 {
4930    ELM_CHECK_WIDTYPE(obj, widtype);
4931    Widget_Data *wd = elm_widget_data_get(obj);
4932    if (!wd) return;
4933    if ((style == wd->mode_item_style) || (style && wd->mode_item_style &&
4934        (!strcmp(style, wd->mode_item_style))))
4935      return;
4936    eina_stringshare_replace(&wd->mode_item_style, style);
4937    elm_genlist_realized_items_update(obj);
4938 }
4939
4940 EAPI const char *
4941 elm_genlist_mode_get(const Evas_Object *obj)
4942 {
4943    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4944    Widget_Data *wd = elm_widget_data_get(obj);
4945    if (!wd) return NULL;
4946    return wd->mode_type;
4947 }
4948
4949 EAPI const Elm_Gen_Item *
4950 elm_genlist_mode_item_get(const Evas_Object *obj)
4951 {
4952    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4953    Widget_Data *wd = elm_widget_data_get(obj);
4954    if (!wd) return NULL;
4955    return wd->mode_item;
4956 }
4957
4958 EAPI void
4959 elm_genlist_reorder_mode_set(Evas_Object *obj,
4960                              Eina_Bool    reorder_mode)
4961 {
4962    ELM_CHECK_WIDTYPE(obj, widtype);
4963    Widget_Data *wd = elm_widget_data_get(obj);
4964    if (!wd) return;
4965    wd->reorder_mode = reorder_mode;
4966 }
4967
4968 EAPI Eina_Bool
4969 elm_genlist_reorder_mode_get(const Evas_Object *obj)
4970 {
4971    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4972    Widget_Data *wd = elm_widget_data_get(obj);
4973    if (!wd) return EINA_FALSE;
4974    return wd->reorder_mode;
4975 }
4976
4977 /* for gengrid as of now */
4978 void
4979 _elm_genlist_page_relative_set(Evas_Object *obj,
4980                                double       h_pagerel,
4981                                double       v_pagerel)
4982 {
4983    Evas_Coord pagesize_h;
4984    Evas_Coord pagesize_v;
4985
4986    ELM_CHECK_WIDTYPE(obj, widtype);
4987    Widget_Data *wd = elm_widget_data_get(obj);
4988    if (!wd) return;
4989
4990    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
4991    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
4992                                  pagesize_v);
4993 }
4994
4995 /* for gengrid as of now */
4996 void
4997 _elm_genlist_page_relative_get(const Evas_Object *obj,
4998                                double            *h_pagerel,
4999                                double            *v_pagerel)
5000 {
5001    ELM_CHECK_WIDTYPE(obj, widtype);
5002    Widget_Data *wd = elm_widget_data_get(obj);
5003    if (!wd) return;
5004
5005    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5006 }
5007
5008 /* for gengrid as of now */
5009 void
5010 _elm_genlist_page_size_set(Evas_Object *obj,
5011                            Evas_Coord   h_pagesize,
5012                            Evas_Coord   v_pagesize)
5013 {
5014    double pagerel_h;
5015    double pagerel_v;
5016
5017    ELM_CHECK_WIDTYPE(obj, widtype);
5018    Widget_Data *wd = elm_widget_data_get(obj);
5019    if (!wd) return;
5020    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5021    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5022                                  v_pagesize);
5023 }
5024
5025 /* for gengrid as of now */
5026 void
5027 _elm_genlist_current_page_get(const Evas_Object *obj,
5028                               int               *h_pagenumber,
5029                               int               *v_pagenumber)
5030 {
5031    ELM_CHECK_WIDTYPE(obj, widtype);
5032    Widget_Data *wd = elm_widget_data_get(obj);
5033    if (!wd) return;
5034    if (wd->scr)
5035      elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5036 }
5037
5038 /* for gengrid as of now */
5039 void
5040 _elm_genlist_last_page_get(const Evas_Object *obj,
5041                            int               *h_pagenumber,
5042                            int               *v_pagenumber)
5043 {
5044    ELM_CHECK_WIDTYPE(obj, widtype);
5045    Widget_Data *wd = elm_widget_data_get(obj);
5046    if (!wd) return;
5047    if (wd->scr)
5048      elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5049 }
5050
5051 /* for gengrid as of now */
5052 void
5053 _elm_genlist_page_show(const Evas_Object *obj,
5054                        int                h_pagenumber,
5055                        int                v_pagenumber)
5056 {
5057    ELM_CHECK_WIDTYPE(obj, widtype);
5058    Widget_Data *wd = elm_widget_data_get(obj);
5059    if (!wd) return;
5060    if (wd->scr)
5061      elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5062 }
5063
5064 /* for gengrid as of now */
5065 void
5066 _elm_genlist_page_bring_in(const Evas_Object *obj,
5067                            int                h_pagenumber,
5068                            int                v_pagenumber)
5069 {
5070    ELM_CHECK_WIDTYPE(obj, widtype);
5071    Widget_Data *wd = elm_widget_data_get(obj);
5072    if (!wd) return;
5073    if (wd->scr)
5074      elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5075 }
5076
5077 Evas_Object *
5078 _elm_genlist_item_widget_get(const Elm_Gen_Item *it)
5079 {
5080    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
5081    return WIDGET(it);
5082 }
5083
5084 void
5085 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5086                             Eina_Bool     calc)
5087 {
5088    Evas_Object *content;
5089
5090    if (!it->realized) return;
5091    if (it->wd->reorder_it == it) return;
5092    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5093    if (!calc)
5094      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5095    if (it->long_timer)
5096      {
5097         ecore_timer_del(it->long_timer);
5098         it->long_timer = NULL;
5099      }
5100
5101    elm_widget_stringlist_free(it->labels);
5102    it->labels = NULL;
5103    elm_widget_stringlist_free(it->contents);
5104    it->contents = NULL;
5105    elm_widget_stringlist_free(it->states);
5106    it->states = NULL;
5107
5108    EINA_LIST_FREE(it->content_objs, content)
5109      evas_object_del(content);
5110
5111    it->unrealize_cb(it);
5112
5113    it->realized = EINA_FALSE;
5114    it->want_unrealize = EINA_FALSE;
5115    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5116    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5117 }
5118
5119 void
5120 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5121 {
5122    elm_widget_item_pre_notify_del(it);
5123    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5124    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5125
5126    if (it->itc->func.del)
5127      it->itc->func.del((void *)it->base.data, WIDGET(it));
5128 }
5129
5130 void
5131 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5132 {
5133    _elm_genlist_item_del_notserious(it);
5134    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5135    if (it->tooltip.del_cb)
5136      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5137    it->wd->walking -= it->walking;
5138    if (it->long_timer) ecore_timer_del(it->long_timer);
5139    if (it->group)
5140      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5141
5142    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5143    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5144    free(it->item);
5145    it->item = NULL;
5146    elm_widget_item_del(it);
5147 }