missed some things with my tooltip api break
[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_window_mode_set(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 Item_Block *
3196 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
3197 {
3198    Item_Block *itb;
3199
3200    itb = calloc(1, sizeof(Item_Block));
3201    if (!itb) return NULL;
3202    itb->wd = wd;
3203    if (prepend)
3204      wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3205    else
3206      wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3207    return itb;
3208 }
3209
3210 static Eina_Bool
3211 _item_block_add(Widget_Data *wd,
3212                 Elm_Gen_Item *it)
3213 {
3214    Item_Block *itb = NULL;
3215
3216    if (!it->item->rel)
3217      {
3218 newblock:
3219         if (it->item->rel)
3220           {
3221              itb = calloc(1, sizeof(Item_Block));
3222              if (!itb) return EINA_FALSE;
3223              itb->wd = wd;
3224              if (!it->item->rel->item->block)
3225                {
3226                   wd->blocks =
3227                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3228                   itb->items = eina_list_append(itb->items, it);
3229                }
3230              else
3231                {
3232                   if (it->item->before)
3233                     {
3234                        wd->blocks = eina_inlist_prepend_relative
3235                            (wd->blocks, EINA_INLIST_GET(itb),
3236                            EINA_INLIST_GET(it->item->rel->item->block));
3237                        itb->items =
3238                          eina_list_prepend_relative(itb->items, it, it->item->rel);
3239                     }
3240                   else
3241                     {
3242                        wd->blocks = eina_inlist_append_relative
3243                            (wd->blocks, EINA_INLIST_GET(itb),
3244                            EINA_INLIST_GET(it->item->rel->item->block));
3245                        itb->items =
3246                          eina_list_append_relative(itb->items, it, it->item->rel);
3247                     }
3248                }
3249           }
3250         else
3251           {
3252              if (it->item->before)
3253                {
3254                   if (wd->blocks)
3255                     {
3256                        itb = (Item_Block *)(wd->blocks);
3257                        if (itb->count >= wd->max_items_per_block)
3258                          {
3259                             itb = _item_block_new(wd, EINA_TRUE);
3260                             if (!itb) return EINA_FALSE;
3261                          }
3262                     }
3263                   else
3264                     {
3265                        itb = _item_block_new(wd, EINA_TRUE);
3266                        if (!itb) return EINA_FALSE;
3267                     }
3268                   itb->items = eina_list_prepend(itb->items, it);
3269                }
3270              else
3271                {
3272                   if (wd->blocks)
3273                     {
3274                        itb = (Item_Block *)(wd->blocks->last);
3275                        if (itb->count >= wd->max_items_per_block)
3276                          {
3277                             itb = _item_block_new(wd, EINA_FALSE);
3278                             if (!itb) return EINA_FALSE;
3279                          }
3280                     }
3281                   else
3282                     {
3283                        itb = _item_block_new(wd, EINA_FALSE);
3284                        if (!itb) return EINA_FALSE;
3285                     }
3286                   itb->items = eina_list_append(itb->items, it);
3287                }
3288           }
3289      }
3290    else
3291      {
3292         if (it->item->rel->item->queued)
3293           {
3294              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3295                 on sorted insertion order, so the queue is not always ordered like the item list.
3296                 This lead to issue where we depend on a item that is not yet created. As a quick
3297                 work around, we reschedule the calc of the item and stop reordering the list to
3298                 prevent any nasty issue to show up here.
3299               */
3300              wd->queue = eina_list_append(wd->queue, it);
3301              wd->requeue = EINA_TRUE;
3302              it->item->queued = EINA_TRUE;
3303              return EINA_FALSE;
3304           }
3305         itb = it->item->rel->item->block;
3306         if (!itb) goto newblock;
3307         if (it->item->before)
3308           itb->items = eina_list_prepend_relative(itb->items, it, it->item->rel);
3309         else
3310           itb->items = eina_list_append_relative(itb->items, it, it->item->rel);
3311      }
3312    itb->count++;
3313    itb->changed = EINA_TRUE;
3314    it->item->block = itb;
3315    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3316    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3317    if (it->item->rel)
3318      {
3319         it->item->rel->relcount--;
3320         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3321           _item_del(it->item->rel);
3322         it->item->rel = NULL;
3323      }
3324    if (itb->count > itb->wd->max_items_per_block)
3325      {
3326         Item_Block *itb2;
3327         Elm_Gen_Item *it2;
3328         int newc;
3329         Eina_Bool done = EINA_FALSE;
3330
3331         newc = itb->count / 2;
3332
3333         if (EINA_INLIST_GET(itb)->prev)
3334           {
3335              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3336
3337              if (itbp->count + newc < wd->max_items_per_block / 2)
3338                {
3339                   /* moving items to previous block */
3340                   while ((itb->count > newc) && (itb->items))
3341                     {
3342                        it2 = eina_list_data_get(itb->items);
3343                        itb->items = eina_list_remove_list(itb->items, itb->items);
3344                        itb->count--;
3345
3346                        itbp->items = eina_list_append(itbp->items, it2);
3347                        it2->item->block = itbp;
3348                        itbp->count++;
3349                     }
3350
3351                   done = EINA_TRUE;
3352                }
3353           }
3354
3355         if (!done && EINA_INLIST_GET(itb)->next)
3356           {
3357              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3358
3359              if (itbn->count + newc < wd->max_items_per_block / 2)
3360                {
3361                   /* moving items to next block */
3362                   while ((itb->count > newc) && (itb->items))
3363                     {
3364                        Eina_List *l;
3365
3366                        l = eina_list_last(itb->items);
3367                        it2 = eina_list_data_get(l);
3368                        itb->items = eina_list_remove_list(itb->items, l);
3369                        itb->count--;
3370
3371                        itbn->items = eina_list_prepend(itbn->items, it2);
3372                        it2->item->block = itbn;
3373                        itbn->count++;
3374                     }
3375
3376                   done = EINA_TRUE;
3377                }
3378           }
3379
3380         if (!done)
3381           {
3382              /* moving items to new block */
3383              itb2 = calloc(1, sizeof(Item_Block));
3384              if (!itb2) return EINA_FALSE;
3385              itb2->wd = wd;
3386              wd->blocks =
3387                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3388                                            EINA_INLIST_GET(itb));
3389              itb2->changed = EINA_TRUE;
3390              while ((itb->count > newc) && (itb->items))
3391                {
3392                   Eina_List *l;
3393
3394                   l = eina_list_last(itb->items);
3395                   it2 = l->data;
3396                   itb->items = eina_list_remove_list(itb->items, l);
3397                   itb->count--;
3398
3399                   itb2->items = eina_list_prepend(itb2->items, it2);
3400                   it2->item->block = itb2;
3401                   itb2->count++;
3402                }
3403           }
3404      }
3405
3406    return EINA_TRUE;
3407 }
3408
3409 static int
3410 _queue_process(Widget_Data *wd)
3411 {
3412    int n;
3413    Eina_Bool showme = EINA_FALSE;
3414    double t0, t;
3415
3416    t0 = ecore_loop_time_get();
3417    //evas_event_freeze(evas_object_evas_get(wd->obj));
3418    for (n = 0; (wd->queue) && (n < 128); n++)
3419      {
3420         Elm_Gen_Item *it;
3421
3422         it = eina_list_data_get(wd->queue);
3423         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3424         it->item->queued = EINA_FALSE;
3425         if (!_item_block_add(wd, it)) continue;
3426         if (!wd->blocks)
3427           _item_block_realize(it->item->block);
3428         t = ecore_time_get();
3429         if (it->item->block->changed)
3430           {
3431              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
3432              it->item->block->changed = 0;
3433           }
3434         if (showme) it->item->block->showme = EINA_TRUE;
3435         if (eina_inlist_count(wd->blocks) > 1)
3436           {
3437              if ((t - t0) > (ecore_animator_frametime_get())) break;
3438           }
3439      }
3440    //evas_event_thaw(evas_object_evas_get(wd->obj));
3441    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3442    return n;
3443 }
3444
3445 static Eina_Bool
3446 _idle_process(void *data, Eina_Bool *wakeup)
3447 {
3448    Widget_Data *wd = data;
3449
3450    //xxx
3451    //static double q_start = 0.0;
3452    //if (q_start == 0.0) q_start = ecore_time_get();
3453    //xxx
3454    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3455    if (!wd->queue)
3456      {
3457         //xxx
3458         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3459         //xxx
3460         return ECORE_CALLBACK_CANCEL;
3461      }
3462    return ECORE_CALLBACK_RENEW;
3463 }
3464
3465 static Eina_Bool
3466 _item_idle_enterer(void *data)
3467 {
3468    Widget_Data *wd = data;
3469    Eina_Bool wakeup = EINA_FALSE;
3470    Eina_Bool ok = _idle_process(data, &wakeup);
3471
3472    if (wakeup)
3473      {
3474         // wake up mainloop
3475         if (wd->calc_job) ecore_job_del(wd->calc_job);
3476         wd->calc_job = ecore_job_add(_calc_job, wd);
3477      }
3478    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3479    return ok;
3480 }
3481
3482 static void
3483 _item_queue(Widget_Data *wd,
3484             Elm_Gen_Item *it,
3485             Eina_Compare_Cb cb)
3486 {
3487    if (it->item->queued) return;
3488    it->item->queued = EINA_TRUE;
3489    if (cb && !wd->requeue)
3490      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
3491    else
3492      wd->queue = eina_list_append(wd->queue, it);
3493 // FIXME: why does a freeze then thaw here cause some genlist
3494 // elm_genlist_item_append() to be much much slower?
3495 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3496    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3497      {
3498         if (wd->queue_idle_enterer)
3499           {
3500              ecore_idle_enterer_del(wd->queue_idle_enterer);
3501              wd->queue_idle_enterer = NULL;
3502           }
3503         _queue_process(wd);
3504      }
3505 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3506 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3507    if (!wd->queue_idle_enterer)
3508      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3509 }
3510
3511 static int
3512 _elm_genlist_item_compare_data(const void *data, const void *data1)
3513 {
3514    const Elm_Gen_Item *it = data;
3515    const Elm_Gen_Item *item1 = data1;
3516
3517    return _elm_genlist_item_compare_data_cb(it->base.data, item1->base.data);
3518 }
3519
3520 static int
3521 _elm_genlist_item_compare(const void *data, const void *data1)
3522 {
3523    const Elm_Gen_Item *it, *item1;
3524    it = ELM_GEN_ITEM_FROM_INLIST(data);
3525    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
3526    return _elm_genlist_item_compare_cb(it, item1);
3527 }
3528
3529 static int
3530 _elm_genlist_item_list_compare(const void *data, const void *data1)
3531 {
3532    const Elm_Gen_Item *it = data;
3533    const Elm_Gen_Item *item1 = data1;
3534    return _elm_genlist_item_compare_cb(it, item1);
3535 }
3536
3537 static void
3538 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
3539 {
3540    if (!it) return;
3541    if (!after) return;
3542
3543    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3544    _item_block_del(it);
3545
3546    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3547    it->item->rel = after;
3548    it->item->rel->relcount++;
3549    it->item->before = EINA_FALSE;
3550    if (after->item->group_item) it->item->group_item = after->item->group_item;
3551    _item_queue(it->wd, it, NULL);
3552
3553    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3554 }
3555
3556 static void
3557 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
3558 {
3559    if (!it) return;
3560    if (!before) return;
3561
3562    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3563    _item_block_del(it);
3564    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3565    it->item->rel = before;
3566    it->item->rel->relcount++;
3567    it->item->before = EINA_TRUE;
3568    if (before->item->group_item) it->item->group_item = before->item->group_item;
3569    _item_queue(it->wd, it, NULL);
3570
3571    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3572 }
3573
3574 EAPI Elm_Gen_Item *
3575 elm_genlist_item_append(Evas_Object                  *obj,
3576                         const Elm_Genlist_Item_Class *itc,
3577                         const void                   *data,
3578                         Elm_Gen_Item             *parent,
3579                         Elm_Genlist_Item_Flags        flags,
3580                         Evas_Smart_Cb                 func,
3581                         const void                   *func_data)
3582 {
3583    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3584    Widget_Data *wd = elm_widget_data_get(obj);
3585    if (!wd) return NULL;
3586    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3587                                     func_data);
3588    if (!it) return NULL;
3589    if (!it->parent)
3590      {
3591         if (it->group)
3592           wd->group_items = eina_list_append(wd->group_items, it);
3593         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3594         it->item->rel = NULL;
3595      }
3596    else
3597      {
3598         Elm_Gen_Item *it2 = NULL;
3599         Eina_List *ll = eina_list_last(it->parent->item->items);
3600         if (ll) it2 = ll->data;
3601         it->parent->item->items = eina_list_append(it->parent->item->items, it);
3602         if (!it2) it2 = it->parent;
3603         wd->items =
3604           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3605                                       EINA_INLIST_GET(it2));
3606         it->item->rel = it2;
3607         it->item->rel->relcount++;
3608      }
3609    it->item->before = EINA_FALSE;
3610    _item_queue(wd, it, NULL);
3611    return it;
3612 }
3613
3614 EAPI Elm_Gen_Item *
3615 elm_genlist_item_prepend(Evas_Object                  *obj,
3616                          const Elm_Genlist_Item_Class *itc,
3617                          const void                   *data,
3618                          Elm_Gen_Item             *parent,
3619                          Elm_Genlist_Item_Flags        flags,
3620                          Evas_Smart_Cb                 func,
3621                          const void                   *func_data)
3622 {
3623    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3624    Widget_Data *wd = elm_widget_data_get(obj);
3625    if (!wd) return NULL;
3626    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3627                                     func_data);
3628    if (!it) return NULL;
3629    if (!it->parent)
3630      {
3631         if (it->group)
3632           wd->group_items = eina_list_prepend(wd->group_items, it);
3633         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3634         it->item->rel = NULL;
3635      }
3636    else
3637      {
3638         Elm_Gen_Item *it2 = NULL;
3639         Eina_List *ll = it->parent->item->items;
3640         if (ll) it2 = ll->data;
3641         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
3642         if (!it2) it2 = it->parent;
3643         wd->items =
3644           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3645                                        EINA_INLIST_GET(it2));
3646         it->item->rel = it2;
3647         it->item->rel->relcount++;
3648      }
3649    it->item->before = EINA_TRUE;
3650    _item_queue(wd, it, NULL);
3651    return it;
3652 }
3653
3654 EAPI Elm_Gen_Item *
3655 elm_genlist_item_insert_after(Evas_Object                  *obj,
3656                               const Elm_Genlist_Item_Class *itc,
3657                               const void                   *data,
3658                               Elm_Gen_Item             *parent,
3659                               Elm_Gen_Item             *after,
3660                               Elm_Genlist_Item_Flags        flags,
3661                               Evas_Smart_Cb                 func,
3662                               const void                   *func_data)
3663 {
3664    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3665    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
3666    Widget_Data *wd = elm_widget_data_get(obj);
3667    if (!wd) return NULL;
3668    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
3669    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3670
3671    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3672                                     func_data);
3673    if (!it) return NULL;
3674    if (!it->parent)
3675      {
3676         if ((it->group) &&
3677             (after->group))
3678           wd->group_items = eina_list_append_relative(wd->group_items, it,
3679                                                       after);
3680      }
3681    else
3682      {
3683         it->parent->item->items = eina_list_append_relative(it->parent->item->items, it,
3684                                                       after);
3685      }
3686    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3687                                            EINA_INLIST_GET(after));
3688    it->item->rel = after;
3689    it->item->rel->relcount++;
3690    it->item->before = EINA_FALSE;
3691    _item_queue(wd, it, NULL);
3692    return it;
3693 }
3694
3695 EAPI Elm_Gen_Item *
3696 elm_genlist_item_insert_before(Evas_Object                  *obj,
3697                                const Elm_Genlist_Item_Class *itc,
3698                                const void                   *data,
3699                                Elm_Gen_Item             *parent,
3700                                Elm_Gen_Item             *before,
3701                                Elm_Genlist_Item_Flags        flags,
3702                                Evas_Smart_Cb                 func,
3703                                const void                   *func_data)
3704 {
3705    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3706    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
3707    Widget_Data *wd = elm_widget_data_get(obj);
3708    if (!wd) return NULL;
3709    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
3710    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3711
3712    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3713                                     func_data);
3714    if (!it) return NULL;
3715    if (!it->parent)
3716      {
3717         if (it->group && before->group)
3718           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
3719                                                        before);
3720      }
3721    else
3722      {
3723         it->parent->item->items = eina_list_prepend_relative(it->parent->item->items, it,
3724                                                        before);
3725      }
3726    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3727                                             EINA_INLIST_GET(before));
3728    it->item->rel = before;
3729    it->item->rel->relcount++;
3730    it->item->before = EINA_TRUE;
3731    _item_queue(wd, it, NULL);
3732    return it;
3733 }
3734
3735 EAPI Elm_Gen_Item *
3736 elm_genlist_item_direct_sorted_insert(Evas_Object                  *obj,
3737                                       const Elm_Genlist_Item_Class *itc,
3738                                       const void                   *data,
3739                                       Elm_Gen_Item             *parent,
3740                                       Elm_Genlist_Item_Flags        flags,
3741                                       Eina_Compare_Cb               comp,
3742                                       Evas_Smart_Cb                 func,
3743                                       const void                   *func_data)
3744 {
3745    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3746    Widget_Data *wd = elm_widget_data_get(obj);
3747    if (!wd) return NULL;
3748    Elm_Gen_Item *rel = NULL;
3749    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3750                                     func_data);
3751    if (!it) return NULL;
3752
3753    _elm_genlist_item_compare_cb = comp;
3754
3755    if (it->parent)
3756      {
3757         Eina_List *l;
3758         int cmp_result;
3759
3760         l = eina_list_search_sorted_near_list(it->parent->item->items,
3761                                               _elm_genlist_item_list_compare, it,
3762                                               &cmp_result);
3763         if (l)
3764           rel = eina_list_data_get(l);
3765         else
3766           rel = it->parent;
3767
3768         if (cmp_result >= 0)
3769           {
3770              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
3771              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3772              it->item->before = EINA_FALSE;
3773           }
3774         else if (cmp_result < 0)
3775           {
3776              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
3777              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3778              it->item->before = EINA_TRUE;
3779           }
3780      }
3781    else
3782      {
3783         if (!wd->state)
3784           {
3785              wd->state = eina_inlist_sorted_state_new();
3786              eina_inlist_sorted_state_init(wd->state, wd->items);
3787              wd->requeue = EINA_FALSE;
3788           }
3789
3790         if (it->group)
3791           wd->group_items = eina_list_append(wd->group_items, it);
3792
3793         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
3794                                                     _elm_genlist_item_compare, wd->state);
3795
3796         if (EINA_INLIST_GET(it)->next)
3797           {
3798              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3799              it->item->before = EINA_TRUE;
3800           }
3801         else if (EINA_INLIST_GET(it)->prev)
3802           {
3803              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3804              it->item->before = EINA_FALSE;
3805           }
3806      }
3807
3808    if (rel)
3809      {
3810         it->item->rel = rel;
3811         it->item->rel->relcount++;
3812      }
3813
3814    _item_queue(wd, it, _elm_genlist_item_list_compare);
3815
3816    return it;
3817 }
3818
3819 EAPI Elm_Gen_Item *
3820 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
3821                                const Elm_Genlist_Item_Class *itc,
3822                                const void                   *data,
3823                                Elm_Gen_Item             *parent,
3824                                Elm_Genlist_Item_Flags        flags,
3825                                Eina_Compare_Cb               comp,
3826                                Evas_Smart_Cb                 func,
3827                                const void                   *func_data)
3828 {
3829    _elm_genlist_item_compare_data_cb = comp;
3830
3831    return elm_genlist_item_direct_sorted_insert(obj, itc, data, parent, flags,
3832                                                 _elm_genlist_item_compare_data, func, func_data);
3833 }
3834
3835 static void
3836 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
3837 {
3838    Eina_Inlist *next, *l;
3839
3840    ELM_CHECK_WIDTYPE(obj, widtype);
3841    Widget_Data *wd = elm_widget_data_get(obj);
3842    if (!wd) return;
3843
3844    if (!standby) wd->generation++;
3845
3846    if (wd->state)
3847      {
3848         eina_inlist_sorted_state_free(wd->state);
3849         wd->state = NULL;
3850      }
3851
3852    if (wd->walking > 0)
3853      {
3854         wd->clear_me = 1;
3855         return;
3856      }
3857    evas_event_freeze(evas_object_evas_get(wd->obj));
3858    for (l = wd->items, next = l ? l->next : NULL;
3859         l;
3860         l = next, next = next ? next->next : NULL)
3861      {
3862         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
3863
3864         if (it->generation < wd->generation)
3865           {
3866              Elm_Gen_Item *itn = NULL;
3867
3868              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
3869              if (itn) itn->walking++; /* prevent early death of subitem */
3870              it->del_cb(it);
3871              if (itn) itn->walking--;
3872           }
3873      }
3874    wd->clear_me = 0;
3875    if (wd->calc_job)
3876      {
3877         ecore_job_del(wd->calc_job);
3878         wd->calc_job = NULL;
3879      }
3880    if (wd->selected) wd->selected = eina_list_free(wd->selected);
3881    if (wd->clear_cb) wd->clear_cb(wd);
3882    wd->pan_x = 0;
3883    wd->pan_y = 0;
3884    wd->minw = 0;
3885    wd->minh = 0;
3886    wd->count = 0;
3887    if (wd->pan_smart)
3888      {
3889         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
3890         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
3891      }
3892    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
3893    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
3894    evas_event_thaw(evas_object_evas_get(wd->obj));
3895    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3896 }
3897
3898 EAPI void
3899 elm_genlist_clear(Evas_Object *obj)
3900 {
3901    _elm_genlist_clear(obj, EINA_FALSE);
3902 }
3903
3904 EAPI void
3905 elm_genlist_multi_select_set(Evas_Object *obj,
3906                              Eina_Bool    multi)
3907 {
3908    ELM_CHECK_WIDTYPE(obj, widtype);
3909    Widget_Data *wd = elm_widget_data_get(obj);
3910    if (!wd) return;
3911    wd->multi = multi;
3912 }
3913
3914 EAPI Eina_Bool
3915 elm_genlist_multi_select_get(const Evas_Object *obj)
3916 {
3917    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3918    Widget_Data *wd = elm_widget_data_get(obj);
3919    if (!wd) return EINA_FALSE;
3920    return wd->multi;
3921 }
3922
3923 EAPI Elm_Gen_Item *
3924 elm_genlist_selected_item_get(const Evas_Object *obj)
3925 {
3926    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3927    Widget_Data *wd = elm_widget_data_get(obj);
3928    if (!wd) return NULL;
3929    if (wd->selected) return wd->selected->data;
3930    return NULL;
3931 }
3932
3933 EAPI const Eina_List *
3934 elm_genlist_selected_items_get(const Evas_Object *obj)
3935 {
3936    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3937    Widget_Data *wd = elm_widget_data_get(obj);
3938    if (!wd) return NULL;
3939    return wd->selected;
3940 }
3941
3942 EAPI Eina_List *
3943 elm_genlist_realized_items_get(const Evas_Object *obj)
3944 {
3945    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3946    Widget_Data *wd = elm_widget_data_get(obj);
3947    Eina_List *list = NULL;
3948    Item_Block *itb;
3949    Eina_Bool done = EINA_FALSE;
3950    if (!wd) return NULL;
3951    EINA_INLIST_FOREACH(wd->blocks, itb)
3952      {
3953         if (itb->realized)
3954           {
3955              Eina_List *l;
3956              Elm_Gen_Item *it;
3957
3958              done = 1;
3959              EINA_LIST_FOREACH(itb->items, l, it)
3960                {
3961                   if (it->realized) list = eina_list_append(list, it);
3962                }
3963           }
3964         else
3965           {
3966              if (done) break;
3967           }
3968      }
3969    return list;
3970 }
3971
3972 EAPI Elm_Gen_Item *
3973 elm_genlist_at_xy_item_get(const Evas_Object *obj,
3974                            Evas_Coord         x,
3975                            Evas_Coord         y,
3976                            int               *posret)
3977 {
3978    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3979    Widget_Data *wd = elm_widget_data_get(obj);
3980    Evas_Coord ox, oy, ow, oh;
3981    Item_Block *itb;
3982    Evas_Coord lasty;
3983    if (!wd) return NULL;
3984    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
3985    lasty = oy;
3986    EINA_INLIST_FOREACH(wd->blocks, itb)
3987      {
3988         Eina_List *l;
3989         Elm_Gen_Item *it;
3990
3991         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
3992                                  oy + itb->y - itb->wd->pan_y,
3993                                  itb->w, itb->h, x, y, 1, 1))
3994           continue;
3995         EINA_LIST_FOREACH(itb->items, l, it)
3996           {
3997              Evas_Coord itx, ity;
3998
3999              itx = ox + itb->x + it->x - itb->wd->pan_x;
4000              ity = oy + itb->y + it->y - itb->wd->pan_y;
4001              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4002                {
4003                   if (posret)
4004                     {
4005                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
4006                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
4007                          *posret = 1;
4008                        else *posret = 0;
4009                     }
4010                   return it;
4011                }
4012              lasty = ity + it->item->h;
4013           }
4014      }
4015    if (posret)
4016      {
4017         if (y > lasty) *posret = 1;
4018         else *posret = -1;
4019      }
4020    return NULL;
4021 }
4022
4023 EAPI Elm_Gen_Item *
4024 elm_genlist_first_item_get(const Evas_Object *obj)
4025 {
4026    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4027    Widget_Data *wd = elm_widget_data_get(obj);
4028    if (!wd) return NULL;
4029    if (!wd->items) return NULL;
4030    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4031    while ((it) && (it->generation < wd->generation))
4032      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4033    return it;
4034 }
4035
4036 EAPI Elm_Gen_Item *
4037 elm_genlist_last_item_get(const Evas_Object *obj)
4038 {
4039    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4040    Widget_Data *wd = elm_widget_data_get(obj);
4041    if (!wd) return NULL;
4042    if (!wd->items) return NULL;
4043    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4044    while ((it) && (it->generation < wd->generation))
4045      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4046    return it;
4047 }
4048
4049 EAPI Elm_Gen_Item *
4050 elm_genlist_item_next_get(const Elm_Gen_Item *it)
4051 {
4052    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4053    while (it)
4054      {
4055         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4056         if ((it) && (it->generation == it->wd->generation)) break;
4057      }
4058    return (Elm_Gen_Item *)it;
4059 }
4060
4061 EAPI Elm_Gen_Item *
4062 elm_genlist_item_prev_get(const Elm_Gen_Item *it)
4063 {
4064    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4065    while (it)
4066      {
4067         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4068         if ((it) && (it->generation == it->wd->generation)) break;
4069      }
4070    return (Elm_Gen_Item *)it;
4071 }
4072
4073 EAPI Evas_Object *
4074 elm_genlist_item_genlist_get(const Elm_Gen_Item *it)
4075 {
4076    return _elm_genlist_item_widget_get(it);
4077 }
4078
4079 EAPI Elm_Gen_Item *
4080 elm_genlist_item_parent_get(const Elm_Gen_Item *it)
4081 {
4082    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4083    return it->parent;
4084 }
4085
4086 EAPI void
4087 elm_genlist_item_subitems_clear(Elm_Gen_Item *it)
4088 {
4089    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4090    Eina_List *tl = NULL, *l;
4091    Elm_Gen_Item *it2;
4092
4093    EINA_LIST_FOREACH(it->item->items, l, it2)
4094      tl = eina_list_append(tl, it2);
4095    EINA_LIST_FREE(tl, it2)
4096      elm_genlist_item_del(it2);
4097 }
4098
4099 EAPI void
4100 elm_genlist_item_selected_set(Elm_Gen_Item *it,
4101                               Eina_Bool         selected)
4102 {
4103    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4104    Widget_Data *wd = it->wd;
4105    if (!wd) return;
4106    if ((it->generation < wd->generation) || (it->disabled)) return;
4107    selected = !!selected;
4108    if (it->selected == selected) return;
4109
4110    if (selected)
4111      {
4112         if (!wd->multi)
4113           {
4114              while (wd->selected)
4115                {
4116                   if (it->unhighlight_cb) it->unhighlight_cb(wd->selected->data);
4117                   it->unsel_cb(wd->selected->data);
4118                }
4119           }
4120         it->highlight_cb(it);
4121         _item_select(it);
4122         return;
4123      }
4124    if (it->unhighlight_cb) it->unhighlight_cb(it);
4125    it->unsel_cb(it);
4126 }
4127
4128 EAPI Eina_Bool
4129 elm_genlist_item_selected_get(const Elm_Gen_Item *it)
4130 {
4131    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4132    return it->selected;
4133 }
4134
4135 EAPI void
4136 elm_genlist_item_expanded_set(Elm_Gen_Item *it,
4137                               Eina_Bool         expanded)
4138 {
4139    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4140    if (it->item->expanded == expanded) return;
4141    it->item->expanded = expanded;
4142    it->wd->expanded_item = it;
4143    if (it->item->expanded)
4144      {
4145         if (it->realized)
4146           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
4147         evas_object_smart_callback_call(WIDGET(it), SIG_EXPANDED, it);
4148         it->wd->auto_scroll_enabled = EINA_TRUE;
4149      }
4150    else
4151      {
4152         if (it->realized)
4153           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
4154         evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACTED, it);
4155         it->wd->auto_scroll_enabled = EINA_FALSE;
4156      }
4157 }
4158
4159 EAPI Eina_Bool
4160 elm_genlist_item_expanded_get(const Elm_Gen_Item *it)
4161 {
4162    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4163    return it->item->expanded;
4164 }
4165
4166 EAPI int
4167 elm_genlist_item_expanded_depth_get(const Elm_Gen_Item *it)
4168 {
4169    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
4170    return it->item->expanded_depth;
4171 }
4172
4173 EAPI void
4174 elm_genlist_item_disabled_set(Elm_Gen_Item *it,
4175                               Eina_Bool         disabled)
4176 {
4177    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4178    Eina_List *l;
4179    Evas_Object *obj;
4180    if (it->disabled == disabled) return;
4181    if (it->generation < it->wd->generation) return;
4182    it->disabled = !!disabled;
4183    if (it->selected)
4184      elm_genlist_item_selected_set(it, EINA_FALSE);
4185    if (it->realized)
4186      {
4187         if (it->disabled)
4188           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
4189         else
4190           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
4191         EINA_LIST_FOREACH(it->content_objs, l, obj)
4192           elm_widget_disabled_set(obj, disabled);
4193      }
4194 }
4195
4196 EAPI Eina_Bool
4197 elm_genlist_item_disabled_get(const Elm_Gen_Item *it)
4198 {
4199    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4200    if (it->generation < it->wd->generation) return EINA_FALSE;
4201    return it->disabled;
4202 }
4203
4204 EAPI void
4205 elm_genlist_item_display_only_set(Elm_Gen_Item *it,
4206                                   Eina_Bool         display_only)
4207 {
4208    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4209    if (it->display_only == display_only) return;
4210    if (it->generation < it->wd->generation) return;
4211    it->display_only = display_only;
4212    it->item->mincalcd = EINA_FALSE;
4213    it->item->updateme = EINA_TRUE;
4214    if (it->item->block) it->item->block->updateme = EINA_TRUE;
4215    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4216    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4217 }
4218
4219 EAPI Eina_Bool
4220 elm_genlist_item_display_only_get(const Elm_Gen_Item *it)
4221 {
4222    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4223    if (it->generation < it->wd->generation) return EINA_FALSE;
4224    return it->display_only;
4225 }
4226
4227 EAPI void
4228 elm_genlist_item_show(Elm_Gen_Item *it)
4229 {
4230    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4231    Evas_Coord gith = 0;
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    if ((it->item->group_item) && (it->wd->pan_y > (it->y + it->item->block->y)))
4246      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, it->item->h);
4251 }
4252
4253 EAPI void
4254 elm_genlist_item_promote(Elm_Gen_Item *it)
4255 {
4256    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4257    if (it->generation < it->wd->generation) return;
4258    _item_move_before(it, elm_genlist_first_item_get(WIDGET(it)));
4259 }
4260
4261 EAPI void
4262 elm_genlist_item_demote(Elm_Gen_Item *it)
4263 {
4264    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4265    if (it->generation < it->wd->generation) return;
4266    _item_move_after(it, elm_genlist_last_item_get(WIDGET(it)));
4267 }
4268
4269 EAPI void
4270 elm_genlist_item_bring_in(Elm_Gen_Item *it)
4271 {
4272    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4273    Evas_Coord gith = 0;
4274    if (it->generation < it->wd->generation) return;
4275    if ((it->item->queued) || (!it->item->mincalcd))
4276      {
4277         it->wd->show_item = it;
4278         it->wd->bring_in = EINA_TRUE;
4279         it->item->showme = EINA_TRUE;
4280         return;
4281      }
4282    if (it->wd->show_item)
4283      {
4284         it->wd->show_item->item->showme = EINA_FALSE;
4285         it->wd->show_item = NULL;
4286      }
4287    if ((it->item->group_item) && (it->wd->pan_y > (it->y + it->item->block->y)))
4288      gith = it->item->group_item->item->h;
4289    elm_smart_scroller_region_bring_in(it->wd->scr,
4290                                       it->x + it->item->block->x,
4291                                       it->y + it->item->block->y - gith,
4292                                       it->item->block->w, it->item->h);
4293 }
4294
4295 EAPI void
4296 elm_genlist_item_top_show(Elm_Gen_Item *it)
4297 {
4298    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4299    Evas_Coord ow, oh;
4300    Evas_Coord gith = 0;
4301
4302    if (it->generation < it->wd->generation) return;
4303    if ((it->item->queued) || (!it->item->mincalcd))
4304      {
4305         it->wd->show_item = it;
4306         it->wd->bring_in = EINA_TRUE;
4307         it->item->showme = EINA_TRUE;
4308         return;
4309      }
4310    if (it->wd->show_item)
4311      {
4312         it->wd->show_item->item->showme = EINA_FALSE;
4313         it->wd->show_item = NULL;
4314      }
4315    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4316    if (it->item->group_item) gith = it->item->group_item->item->h;
4317    elm_smart_scroller_child_region_show(it->wd->scr,
4318                                         it->x + it->item->block->x,
4319                                         it->y + it->item->block->y - gith,
4320                                         it->item->block->w, oh);
4321 }
4322
4323 EAPI void
4324 elm_genlist_item_top_bring_in(Elm_Gen_Item *it)
4325 {
4326    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4327    Evas_Coord ow, oh;
4328    Evas_Coord gith = 0;
4329
4330    if (it->generation < it->wd->generation) return;
4331    if ((it->item->queued) || (!it->item->mincalcd))
4332      {
4333         it->wd->show_item = it;
4334         it->wd->bring_in = EINA_TRUE;
4335         it->item->showme = EINA_TRUE;
4336         return;
4337      }
4338    if (it->wd->show_item)
4339      {
4340         it->wd->show_item->item->showme = EINA_FALSE;
4341         it->wd->show_item = NULL;
4342      }
4343    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4344    if (it->item->group_item) gith = it->item->group_item->item->h;
4345    elm_smart_scroller_region_bring_in(it->wd->scr,
4346                                       it->x + it->item->block->x,
4347                                       it->y + it->item->block->y - gith,
4348                                       it->item->block->w, oh);
4349 }
4350
4351 EAPI void
4352 elm_genlist_item_middle_show(Elm_Gen_Item *it)
4353 {
4354    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4355    Evas_Coord ow, oh;
4356
4357    if (it->generation < it->wd->generation) return;
4358    if ((it->item->queued) || (!it->item->mincalcd))
4359      {
4360         it->wd->show_item = it;
4361         it->wd->bring_in = EINA_TRUE;
4362         it->item->showme = EINA_TRUE;
4363         return;
4364      }
4365    if (it->wd->show_item)
4366      {
4367         it->wd->show_item->item->showme = EINA_FALSE;
4368         it->wd->show_item = NULL;
4369      }
4370    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4371    elm_smart_scroller_child_region_show(it->wd->scr,
4372                                         it->x + it->item->block->x,
4373                                         it->y + it->item->block->y - oh / 2 +
4374                                         it->item->h / 2, it->item->block->w, oh);
4375 }
4376
4377 EAPI void
4378 elm_genlist_item_middle_bring_in(Elm_Gen_Item *it)
4379 {
4380    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4381    Evas_Coord ow, oh;
4382
4383    if (it->generation < it->wd->generation) return;
4384    if ((it->item->queued) || (!it->item->mincalcd))
4385      {
4386         it->wd->show_item = it;
4387         it->wd->bring_in = EINA_TRUE;
4388         it->item->showme = EINA_TRUE;
4389         return;
4390      }
4391    if (it->wd->show_item)
4392      {
4393         it->wd->show_item->item->showme = EINA_FALSE;
4394         it->wd->show_item = NULL;
4395      }
4396    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4397    elm_smart_scroller_region_bring_in(it->wd->scr,
4398                                       it->x + it->item->block->x,
4399                                       it->y + it->item->block->y - oh / 2 + it->item->h / 2,
4400                                       it->item->block->w, oh);
4401 }
4402
4403 EAPI void
4404 elm_genlist_item_del(Elm_Gen_Item *it)
4405 {
4406    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4407    if ((it->relcount > 0) || (it->walking > 0))
4408      {
4409         elm_genlist_item_subitems_clear(it);
4410         if (it->wd->show_item == it) it->wd->show_item = NULL;
4411         _elm_genlist_item_del_notserious(it);
4412         if (it->item->block)
4413           {
4414              if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
4415              it->item->block->changed = EINA_TRUE;
4416              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
4417              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
4418           }
4419         if (it->parent)
4420           {
4421              it->parent->item->items = eina_list_remove(it->parent->item->items, it);
4422              it->parent = NULL;
4423           }
4424         return;
4425      }
4426    _item_del(it);
4427 }
4428
4429 EAPI void
4430 elm_genlist_item_data_set(Elm_Gen_Item *it,
4431                           const void       *data)
4432 {
4433    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4434    elm_widget_item_data_set(it, data);
4435 }
4436
4437 EAPI void *
4438 elm_genlist_item_data_get(const Elm_Gen_Item *it)
4439 {
4440    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4441    return elm_widget_item_data_get(it);
4442 }
4443
4444 EAPI void
4445 elm_genlist_item_icons_orphan(Elm_Gen_Item *it)
4446 {
4447    elm_genlist_item_contents_orphan(it);
4448 }
4449
4450 EAPI void
4451 elm_genlist_item_contents_orphan(Elm_Gen_Item *it)
4452 {
4453    Evas_Object *content;
4454    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4455    EINA_LIST_FREE(it->content_objs, content)
4456      {
4457         elm_widget_sub_object_del(WIDGET(it), content);
4458         evas_object_smart_member_del(content);
4459         evas_object_hide(content);
4460      }
4461 }
4462
4463 EAPI const Evas_Object *
4464 elm_genlist_item_object_get(const Elm_Gen_Item *it)
4465 {
4466    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4467    return VIEW(it);
4468 }
4469
4470 EAPI void
4471 elm_genlist_item_update(Elm_Gen_Item *it)
4472 {
4473    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4474    if (!it->item->block) return;
4475    if (it->generation < it->wd->generation) return;
4476    it->item->mincalcd = EINA_FALSE;
4477    it->item->updateme = EINA_TRUE;
4478    it->item->block->updateme = EINA_TRUE;
4479    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4480    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4481 }
4482
4483 EAPI void
4484 elm_genlist_item_fields_update(Elm_Genlist_Item *it,
4485                                const char *parts,
4486                                Elm_Genlist_Item_Field_Flags itf)
4487 {
4488    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4489    if (!it->item->block) return;
4490    if (it->generation < it->wd->generation) return;
4491
4492    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4493      _item_label_realize(it, it->base.view, &it->labels, parts);
4494    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4495      {
4496         it->content_objs = _item_content_unrealize(it, it->base.view,
4497                                                    &it->contents, parts);
4498         it->content_objs = _item_content_realize(it, it->base.view,
4499                                                  &it->contents, parts);
4500      }
4501    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4502      _item_state_realize(it, it->base.view, &it->states, parts);
4503 }
4504
4505 EAPI void
4506 elm_genlist_item_item_class_update(Elm_Gen_Item             *it,
4507                                    const Elm_Genlist_Item_Class *itc)
4508 {
4509    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4510    if (!it->item->block) return;
4511    EINA_SAFETY_ON_NULL_RETURN(itc);
4512    if (it->generation < it->wd->generation) return;
4513    it->itc = itc;
4514    it->item->nocache = EINA_TRUE;
4515    elm_genlist_item_update(it);
4516 }
4517
4518 EAPI const Elm_Genlist_Item_Class *
4519 elm_genlist_item_item_class_get(const Elm_Gen_Item *it)
4520 {
4521    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4522    if (it->generation < it->wd->generation) return NULL;
4523    return it->itc;
4524 }
4525
4526 static Evas_Object *
4527 _elm_genlist_item_label_create(void        *data,
4528                                Evas_Object *obj __UNUSED__,
4529                                Evas_Object *tooltip,
4530                                void        *it __UNUSED__)
4531 {
4532    Evas_Object *label = elm_label_add(tooltip);
4533    if (!label)
4534      return NULL;
4535    elm_object_style_set(label, "tooltip");
4536    elm_object_text_set(label, data);
4537    return label;
4538 }
4539
4540 static void
4541 _elm_genlist_item_label_del_cb(void        *data,
4542                                Evas_Object *obj __UNUSED__,
4543                                void        *event_info __UNUSED__)
4544 {
4545    eina_stringshare_del(data);
4546 }
4547
4548 EAPI void
4549 elm_genlist_item_tooltip_text_set(Elm_Gen_Item *it,
4550                                   const char       *text)
4551 {
4552    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4553    text = eina_stringshare_add(text);
4554    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4555                                            text,
4556                                            _elm_genlist_item_label_del_cb);
4557 }
4558
4559 EAPI void
4560 elm_genlist_item_tooltip_content_cb_set(Elm_Gen_Item           *it,
4561                                         Elm_Tooltip_Item_Content_Cb func,
4562                                         const void                 *data,
4563                                         Evas_Smart_Cb               del_cb)
4564 {
4565    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, error);
4566
4567    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
4568      return;
4569
4570    if (it->tooltip.del_cb)
4571      it->tooltip.del_cb((void *)it->tooltip.data,
4572                           WIDGET(it), it);
4573
4574    it->tooltip.content_cb = func;
4575    it->tooltip.data = data;
4576    it->tooltip.del_cb = del_cb;
4577
4578    if (VIEW(it))
4579      {
4580         elm_widget_item_tooltip_content_cb_set(it,
4581                                                it->tooltip.content_cb,
4582                                                it->tooltip.data, NULL);
4583         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
4584         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
4585      }
4586
4587    return;
4588
4589 error:
4590    if (del_cb) del_cb((void *)data, NULL, NULL);
4591 }
4592
4593 EAPI void
4594 elm_genlist_item_tooltip_unset(Elm_Gen_Item *it)
4595 {
4596    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4597    if ((VIEW(it)) && (it->tooltip.content_cb))
4598      elm_widget_item_tooltip_unset(it);
4599
4600    if (it->tooltip.del_cb)
4601      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
4602    it->tooltip.del_cb = NULL;
4603    it->tooltip.content_cb = NULL;
4604    it->tooltip.data = NULL;
4605    it->tooltip.free_size = EINA_FALSE;
4606    if (it->tooltip.style)
4607      elm_genlist_item_tooltip_style_set(it, NULL);
4608 }
4609
4610 EAPI void
4611 elm_genlist_item_tooltip_style_set(Elm_Gen_Item *it,
4612                                    const char       *style)
4613 {
4614    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4615    eina_stringshare_replace(&it->tooltip.style, style);
4616    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
4617 }
4618
4619 EAPI const char *
4620 elm_genlist_item_tooltip_style_get(const Elm_Gen_Item *it)
4621 {
4622    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4623    return it->tooltip.style;
4624 }
4625
4626 EAPI Eina_Bool
4627 elm_genlist_item_tooltip_window_mode_set(Elm_Gen_Item *it, Eina_Bool disable)
4628 {
4629    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4630    it->tooltip.free_size = disable;
4631    if (VIEW(it)) return elm_widget_item_tooltip_window_mode_set(it, disable);
4632    return EINA_TRUE;
4633 }
4634
4635 EAPI Eina_Bool
4636 elm_genlist_item_tooltip_window_mode_get(const Elm_Gen_Item *it)
4637 {
4638    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4639    return it->tooltip.free_size;
4640 }
4641
4642 EAPI void
4643 elm_genlist_item_cursor_set(Elm_Gen_Item *it,
4644                             const char       *cursor)
4645 {
4646    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4647    eina_stringshare_replace(&it->mouse_cursor, cursor);
4648    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
4649 }
4650
4651 EAPI const char *
4652 elm_genlist_item_cursor_get(const Elm_Gen_Item *it)
4653 {
4654    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4655    return elm_widget_item_cursor_get(it);
4656 }
4657
4658 EAPI void
4659 elm_genlist_item_cursor_unset(Elm_Gen_Item *it)
4660 {
4661    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4662    if (!it->mouse_cursor)
4663      return;
4664
4665    if (VIEW(it))
4666      elm_widget_item_cursor_unset(it);
4667
4668    eina_stringshare_del(it->mouse_cursor);
4669    it->mouse_cursor = NULL;
4670 }
4671
4672 EAPI void
4673 elm_genlist_item_cursor_style_set(Elm_Gen_Item *it,
4674                                   const char       *style)
4675 {
4676    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4677    elm_widget_item_cursor_style_set(it, style);
4678 }
4679
4680 EAPI const char *
4681 elm_genlist_item_cursor_style_get(const Elm_Gen_Item *it)
4682 {
4683    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4684    return elm_widget_item_cursor_style_get(it);
4685 }
4686
4687 EAPI void
4688 elm_genlist_item_cursor_engine_only_set(Elm_Gen_Item *it,
4689                                         Eina_Bool         engine_only)
4690 {
4691    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4692    elm_widget_item_cursor_engine_only_set(it, engine_only);
4693 }
4694
4695 EAPI Eina_Bool
4696 elm_genlist_item_cursor_engine_only_get(const Elm_Gen_Item *it)
4697 {
4698    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4699    return elm_widget_item_cursor_engine_only_get(it);
4700 }
4701
4702 EAPI void
4703 elm_genlist_horizontal_set(Evas_Object  *obj,
4704                                 Elm_List_Mode mode)
4705 {
4706    ELM_CHECK_WIDTYPE(obj, widtype);
4707    Widget_Data *wd = elm_widget_data_get(obj);
4708    if (!wd) return;
4709    if (wd->mode == mode) return;
4710    wd->mode = mode;
4711    _sizing_eval(obj);
4712 }
4713
4714 EAPI void
4715 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4716                                 Elm_List_Mode mode)
4717 {
4718    elm_genlist_horizontal_set(obj, mode);
4719 }
4720
4721 EAPI Elm_List_Mode
4722 elm_genlist_horizontal_get(const Evas_Object *obj)
4723 {
4724    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4725    Widget_Data *wd = elm_widget_data_get(obj);
4726    if (!wd) return ELM_LIST_LAST;
4727    return wd->mode;
4728 }
4729
4730 EAPI Elm_List_Mode
4731 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
4732 {
4733    return elm_genlist_horizontal_get(obj);
4734 }
4735
4736 EAPI void
4737 elm_genlist_always_select_mode_set(Evas_Object *obj,
4738                                    Eina_Bool    always_select)
4739 {
4740    ELM_CHECK_WIDTYPE(obj, widtype);
4741    Widget_Data *wd = elm_widget_data_get(obj);
4742    if (!wd) return;
4743    wd->always_select = always_select;
4744 }
4745
4746 EAPI Eina_Bool
4747 elm_genlist_always_select_mode_get(const Evas_Object *obj)
4748 {
4749    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4750    Widget_Data *wd = elm_widget_data_get(obj);
4751    if (!wd) return EINA_FALSE;
4752    return wd->always_select;
4753 }
4754
4755 EAPI void
4756 elm_genlist_no_select_mode_set(Evas_Object *obj,
4757                                Eina_Bool    no_select)
4758 {
4759    ELM_CHECK_WIDTYPE(obj, widtype);
4760    Widget_Data *wd = elm_widget_data_get(obj);
4761    if (!wd) return;
4762    wd->no_select = no_select;
4763 }
4764
4765 EAPI Eina_Bool
4766 elm_genlist_no_select_mode_get(const Evas_Object *obj)
4767 {
4768    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4769    Widget_Data *wd = elm_widget_data_get(obj);
4770    if (!wd) return EINA_FALSE;
4771    return wd->no_select;
4772 }
4773
4774 EAPI void
4775 elm_genlist_compress_mode_set(Evas_Object *obj,
4776                               Eina_Bool    compress)
4777 {
4778    ELM_CHECK_WIDTYPE(obj, widtype);
4779    Widget_Data *wd = elm_widget_data_get(obj);
4780    if (!wd) return;
4781    wd->compress = compress;
4782    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
4783 }
4784
4785 EAPI Eina_Bool
4786 elm_genlist_compress_mode_get(const Evas_Object *obj)
4787 {
4788    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4789    Widget_Data *wd = elm_widget_data_get(obj);
4790    if (!wd) return EINA_FALSE;
4791    return wd->compress;
4792 }
4793
4794 EAPI void
4795 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
4796                                       Eina_Bool    height_for_width)
4797 {
4798    ELM_CHECK_WIDTYPE(obj, widtype);
4799    Widget_Data *wd = elm_widget_data_get(obj);
4800    if (!wd) return;
4801    wd->height_for_width = !!height_for_width;
4802    if (wd->height_for_width)
4803      {
4804         elm_genlist_homogeneous_set(obj, EINA_FALSE);
4805         elm_genlist_compress_mode_set(obj, EINA_TRUE);
4806      }
4807 }
4808
4809 EAPI Eina_Bool
4810 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
4811 {
4812    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4813    Widget_Data *wd = elm_widget_data_get(obj);
4814    if (!wd) return EINA_FALSE;
4815    return wd->height_for_width;
4816 }
4817
4818 EAPI void
4819 elm_genlist_bounce_set(Evas_Object *obj,
4820                        Eina_Bool    h_bounce,
4821                        Eina_Bool    v_bounce)
4822 {
4823    ELM_CHECK_WIDTYPE(obj, widtype);
4824    Widget_Data *wd = elm_widget_data_get(obj);
4825    if (!wd) return;
4826    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
4827    wd->h_bounce = h_bounce;
4828    wd->v_bounce = v_bounce;
4829 }
4830
4831 EAPI void
4832 elm_genlist_bounce_get(const Evas_Object *obj,
4833                        Eina_Bool         *h_bounce,
4834                        Eina_Bool         *v_bounce)
4835 {
4836    ELM_CHECK_WIDTYPE(obj, widtype);
4837    Widget_Data *wd = elm_widget_data_get(obj);
4838    if (!wd) return;
4839    if (h_bounce) *h_bounce = wd->h_bounce;
4840    if (v_bounce) *v_bounce = wd->v_bounce;
4841 }
4842
4843 EAPI void
4844 elm_genlist_homogeneous_set(Evas_Object *obj,
4845                             Eina_Bool    homogeneous)
4846 {
4847    ELM_CHECK_WIDTYPE(obj, widtype);
4848    Widget_Data *wd = elm_widget_data_get(obj);
4849    if (!wd) return;
4850    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
4851    wd->homogeneous = homogeneous;
4852 }
4853
4854 EAPI Eina_Bool
4855 elm_genlist_homogeneous_get(const Evas_Object *obj)
4856 {
4857    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4858    Widget_Data *wd = elm_widget_data_get(obj);
4859    if (!wd) return EINA_FALSE;
4860    return wd->homogeneous;
4861 }
4862
4863 EAPI void
4864 elm_genlist_block_count_set(Evas_Object *obj,
4865                             int          n)
4866 {
4867    ELM_CHECK_WIDTYPE(obj, widtype);
4868    Widget_Data *wd = elm_widget_data_get(obj);
4869    if (!wd) return;
4870    wd->max_items_per_block = n;
4871    wd->item_cache_max = wd->max_items_per_block * 2;
4872    _item_cache_clean(wd);
4873 }
4874
4875 EAPI int
4876 elm_genlist_block_count_get(const Evas_Object *obj)
4877 {
4878    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4879    Widget_Data *wd = elm_widget_data_get(obj);
4880    if (!wd) return 0;
4881    return wd->max_items_per_block;
4882 }
4883
4884 EAPI void
4885 elm_genlist_longpress_timeout_set(Evas_Object *obj,
4886                                   double       timeout)
4887 {
4888    ELM_CHECK_WIDTYPE(obj, widtype);
4889    Widget_Data *wd = elm_widget_data_get(obj);
4890    if (!wd) return;
4891    wd->longpress_timeout = timeout;
4892 }
4893
4894 EAPI double
4895 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
4896 {
4897    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4898    Widget_Data *wd = elm_widget_data_get(obj);
4899    if (!wd) return 0;
4900    return wd->longpress_timeout;
4901 }
4902
4903 EAPI void
4904 elm_genlist_scroller_policy_set(Evas_Object        *obj,
4905                                 Elm_Scroller_Policy policy_h,
4906                                 Elm_Scroller_Policy policy_v)
4907 {
4908    ELM_CHECK_WIDTYPE(obj, widtype);
4909    Widget_Data *wd = elm_widget_data_get(obj);
4910    if ((!wd) || (!wd->scr)) return;
4911    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
4912        (policy_v >= ELM_SCROLLER_POLICY_LAST))
4913      return;
4914    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
4915 }
4916
4917 EAPI void
4918 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
4919                                 Elm_Scroller_Policy *policy_h,
4920                                 Elm_Scroller_Policy *policy_v)
4921 {
4922    ELM_CHECK_WIDTYPE(obj, widtype);
4923    Widget_Data *wd = elm_widget_data_get(obj);
4924    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
4925    if ((!wd) || (!wd->scr)) return;
4926    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
4927    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
4928    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
4929 }
4930
4931 EAPI void
4932 elm_genlist_realized_items_update(Evas_Object *obj)
4933 {
4934    ELM_CHECK_WIDTYPE(obj, widtype);
4935
4936    Eina_List *list, *l;
4937    Elm_Gen_Item *it;
4938
4939    list = elm_genlist_realized_items_get(obj);
4940    EINA_LIST_FOREACH(list, l, it)
4941      elm_genlist_item_update(it);
4942 }
4943
4944 EAPI void
4945 elm_genlist_item_mode_set(Elm_Gen_Item *it,
4946                           const char       *mode_type,
4947                           Eina_Bool         mode_set)
4948 {
4949    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4950    Widget_Data *wd = it->wd;
4951    Eina_List *l;
4952    Elm_Gen_Item *it2;
4953
4954    if (!wd) return;
4955    if (!mode_type) return;
4956    if ((it->generation < it->wd->generation) || (it->disabled)) return;
4957
4958    if ((wd->mode_item == it) &&
4959        (!strcmp(mode_type, wd->mode_type)) &&
4960        (mode_set))
4961       return;
4962    if (!wd->mode_item_style) return;
4963    it->mode_set = mode_set;
4964
4965    if (wd->multi)
4966      {
4967         EINA_LIST_FOREACH(wd->selected, l, it2)
4968           if (it2->realized)
4969             elm_genlist_item_selected_set(it2, EINA_FALSE);
4970      }
4971    else
4972      {
4973         it2 = elm_genlist_selected_item_get(wd->obj);
4974         if ((it2) && (it2->realized))
4975           elm_genlist_item_selected_set(it2, EINA_FALSE);
4976      }
4977
4978    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
4979        (mode_set) ||
4980        ((it == wd->mode_item) && (!mode_set)))
4981      _item_mode_unset(wd);
4982
4983    eina_stringshare_replace(&wd->mode_type, mode_type);
4984    if (mode_set) _item_mode_set(it);
4985 }
4986
4987
4988 EAPI const char *
4989 elm_genlist_mode_item_style_get(const Evas_Object *obj)
4990 {
4991    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4992    Widget_Data *wd = elm_widget_data_get(obj);
4993    if (!wd) return NULL;
4994    return wd->mode_item_style;
4995 }
4996
4997 EAPI void
4998 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
4999 {
5000    ELM_CHECK_WIDTYPE(obj, widtype);
5001    Widget_Data *wd = elm_widget_data_get(obj);
5002    if (!wd) return;
5003    if ((style == wd->mode_item_style) || (style && wd->mode_item_style &&
5004        (!strcmp(style, wd->mode_item_style))))
5005      return;
5006    eina_stringshare_replace(&wd->mode_item_style, style);
5007    elm_genlist_realized_items_update(obj);
5008 }
5009
5010 EAPI const char *
5011 elm_genlist_mode_get(const Evas_Object *obj)
5012 {
5013    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5014    Widget_Data *wd = elm_widget_data_get(obj);
5015    if (!wd) return NULL;
5016    return wd->mode_type;
5017 }
5018
5019 EAPI const Elm_Gen_Item *
5020 elm_genlist_mode_item_get(const Evas_Object *obj)
5021 {
5022    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5023    Widget_Data *wd = elm_widget_data_get(obj);
5024    if (!wd) return NULL;
5025    return wd->mode_item;
5026 }
5027
5028 EAPI void
5029 elm_genlist_reorder_mode_set(Evas_Object *obj,
5030                              Eina_Bool    reorder_mode)
5031 {
5032    ELM_CHECK_WIDTYPE(obj, widtype);
5033    Widget_Data *wd = elm_widget_data_get(obj);
5034    if (!wd) return;
5035    wd->reorder_mode = reorder_mode;
5036 }
5037
5038 EAPI Eina_Bool
5039 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5040 {
5041    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5042    Widget_Data *wd = elm_widget_data_get(obj);
5043    if (!wd) return EINA_FALSE;
5044    return wd->reorder_mode;
5045 }
5046
5047 /* for gengrid as of now */
5048 void
5049 _elm_genlist_page_relative_set(Evas_Object *obj,
5050                                double       h_pagerel,
5051                                double       v_pagerel)
5052 {
5053    Evas_Coord pagesize_h;
5054    Evas_Coord pagesize_v;
5055
5056    ELM_CHECK_WIDTYPE(obj, widtype);
5057    Widget_Data *wd = elm_widget_data_get(obj);
5058    if (!wd) return;
5059
5060    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5061    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5062                                  pagesize_v);
5063 }
5064
5065 /* for gengrid as of now */
5066 void
5067 _elm_genlist_page_relative_get(const Evas_Object *obj,
5068                                double            *h_pagerel,
5069                                double            *v_pagerel)
5070 {
5071    ELM_CHECK_WIDTYPE(obj, widtype);
5072    Widget_Data *wd = elm_widget_data_get(obj);
5073    if (!wd) return;
5074
5075    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5076 }
5077
5078 /* for gengrid as of now */
5079 void
5080 _elm_genlist_page_size_set(Evas_Object *obj,
5081                            Evas_Coord   h_pagesize,
5082                            Evas_Coord   v_pagesize)
5083 {
5084    double pagerel_h;
5085    double pagerel_v;
5086
5087    ELM_CHECK_WIDTYPE(obj, widtype);
5088    Widget_Data *wd = elm_widget_data_get(obj);
5089    if (!wd) return;
5090    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5091    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5092                                  v_pagesize);
5093 }
5094
5095 /* for gengrid as of now */
5096 void
5097 _elm_genlist_current_page_get(const Evas_Object *obj,
5098                               int               *h_pagenumber,
5099                               int               *v_pagenumber)
5100 {
5101    ELM_CHECK_WIDTYPE(obj, widtype);
5102    Widget_Data *wd = elm_widget_data_get(obj);
5103    if (!wd) return;
5104    if (wd->scr)
5105      elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5106 }
5107
5108 /* for gengrid as of now */
5109 void
5110 _elm_genlist_last_page_get(const Evas_Object *obj,
5111                            int               *h_pagenumber,
5112                            int               *v_pagenumber)
5113 {
5114    ELM_CHECK_WIDTYPE(obj, widtype);
5115    Widget_Data *wd = elm_widget_data_get(obj);
5116    if (!wd) return;
5117    if (wd->scr)
5118      elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5119 }
5120
5121 /* for gengrid as of now */
5122 void
5123 _elm_genlist_page_show(const Evas_Object *obj,
5124                        int                h_pagenumber,
5125                        int                v_pagenumber)
5126 {
5127    ELM_CHECK_WIDTYPE(obj, widtype);
5128    Widget_Data *wd = elm_widget_data_get(obj);
5129    if (!wd) return;
5130    if (wd->scr)
5131      elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5132 }
5133
5134 /* for gengrid as of now */
5135 void
5136 _elm_genlist_page_bring_in(const Evas_Object *obj,
5137                            int                h_pagenumber,
5138                            int                v_pagenumber)
5139 {
5140    ELM_CHECK_WIDTYPE(obj, widtype);
5141    Widget_Data *wd = elm_widget_data_get(obj);
5142    if (!wd) return;
5143    if (wd->scr)
5144      elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5145 }
5146
5147 Evas_Object *
5148 _elm_genlist_item_widget_get(const Elm_Gen_Item *it)
5149 {
5150    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
5151    return WIDGET(it);
5152 }
5153
5154 void
5155 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5156                             Eina_Bool     calc)
5157 {
5158    Evas_Object *content;
5159
5160    if (!it->realized) return;
5161    if (it->wd->reorder_it == it) return;
5162    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5163    if (!calc)
5164      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5165    if (it->long_timer)
5166      {
5167         ecore_timer_del(it->long_timer);
5168         it->long_timer = NULL;
5169      }
5170
5171    elm_widget_stringlist_free(it->labels);
5172    it->labels = NULL;
5173    elm_widget_stringlist_free(it->contents);
5174    it->contents = NULL;
5175    elm_widget_stringlist_free(it->states);
5176    it->states = NULL;
5177
5178    EINA_LIST_FREE(it->content_objs, content)
5179      evas_object_del(content);
5180
5181    it->unrealize_cb(it);
5182
5183    it->realized = EINA_FALSE;
5184    it->want_unrealize = EINA_FALSE;
5185    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5186    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5187 }
5188
5189 void
5190 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5191 {
5192    elm_widget_item_pre_notify_del(it);
5193    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5194    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5195
5196    if (it->itc->func.del)
5197      it->itc->func.del((void *)it->base.data, WIDGET(it));
5198 }
5199
5200 void
5201 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5202 {
5203    _elm_genlist_item_del_notserious(it);
5204    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5205    if (it->tooltip.del_cb)
5206      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5207    it->wd->walking -= it->walking;
5208    if (it->long_timer) ecore_timer_del(it->long_timer);
5209    if (it->group)
5210      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5211
5212    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5213    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5214    free(it->item);
5215    it->item = NULL;
5216    elm_widget_item_del(it);
5217 }