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