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