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