elm genlist: Added mode_item_style to Elm_Genlist_Item_Class and
[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->itc->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    wd->item_count++;
3376    return it;
3377 }
3378
3379 static Item_Block *
3380 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
3381 {
3382    Item_Block *itb;
3383
3384    itb = calloc(1, sizeof(Item_Block));
3385    if (!itb) return NULL;
3386    itb->wd = wd;
3387    if (prepend)
3388      {
3389         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3390         _item_block_position_update(wd->blocks, 0);
3391      }
3392    else
3393      {
3394         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3395         itb->position_update = EINA_TRUE;
3396         if (wd->blocks != EINA_INLIST_GET(itb))
3397           {
3398              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3399           }
3400         else
3401           {
3402              itb->position = 0;
3403           }
3404      }
3405    return itb;
3406 }
3407
3408 static Eina_Bool
3409 _item_block_add(Widget_Data *wd,
3410                 Elm_Gen_Item *it)
3411 {
3412    Item_Block *itb = NULL;
3413
3414    if (!it->item->rel)
3415      {
3416 newblock:
3417         if (it->item->rel)
3418           {
3419              itb = calloc(1, sizeof(Item_Block));
3420              if (!itb) return EINA_FALSE;
3421              itb->wd = wd;
3422              if (!it->item->rel->item->block)
3423                {
3424                   wd->blocks =
3425                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3426                   itb->items = eina_list_append(itb->items, it);
3427                   itb->position_update = EINA_TRUE;
3428                   it->position = eina_list_count(itb->items);
3429                   it->position_update = EINA_TRUE;
3430
3431                   if (wd->blocks != EINA_INLIST_GET(itb))
3432                     {
3433                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3434                     }
3435                   else
3436                     {
3437                        itb->position = 0;
3438                     }
3439                }
3440              else
3441                {
3442                   Eina_List *tmp;
3443
3444                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3445                   if (it->item->before)
3446                     {
3447                        wd->blocks = eina_inlist_prepend_relative
3448                            (wd->blocks, EINA_INLIST_GET(itb),
3449                            EINA_INLIST_GET(it->item->rel->item->block));
3450                        itb->items =
3451                          eina_list_prepend_relative_list(itb->items, it, tmp);
3452
3453                        /* Update index from where we prepended */
3454                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3455                        _item_block_position_update(EINA_INLIST_GET(itb),
3456                                                    it->item->rel->item->block->position);
3457                     }
3458                   else
3459                     {
3460                        wd->blocks = eina_inlist_append_relative
3461                            (wd->blocks, EINA_INLIST_GET(itb),
3462                            EINA_INLIST_GET(it->item->rel->item->block));
3463                        itb->items =
3464                          eina_list_append_relative_list(itb->items, it, tmp);
3465
3466                        /* Update block index from where we appended */
3467                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3468                        _item_block_position_update(EINA_INLIST_GET(itb),
3469                                                    it->item->rel->item->block->position + 1);
3470                     }
3471                }
3472           }
3473         else
3474           {
3475              if (it->item->before)
3476                {
3477                   if (wd->blocks)
3478                     {
3479                        itb = (Item_Block *)(wd->blocks);
3480                        if (itb->count >= wd->max_items_per_block)
3481                          {
3482                             itb = _item_block_new(wd, EINA_TRUE);
3483                             if (!itb) return EINA_FALSE;
3484                          }
3485                     }
3486                   else
3487                     {
3488                        itb = _item_block_new(wd, EINA_TRUE);
3489                        if (!itb) return EINA_FALSE;
3490                     }
3491                   itb->items = eina_list_prepend(itb->items, it);
3492
3493                   _item_position_update(itb->items, 0);
3494                }
3495              else
3496                {
3497                   if (wd->blocks)
3498                     {
3499                        itb = (Item_Block *)(wd->blocks->last);
3500                        if (itb->count >= wd->max_items_per_block)
3501                          {
3502                             itb = _item_block_new(wd, EINA_FALSE);
3503                             if (!itb) return EINA_FALSE;
3504                          }
3505                     }
3506                   else
3507                     {
3508                        itb = _item_block_new(wd, EINA_FALSE);
3509                        if (!itb) return EINA_FALSE;
3510                     }
3511                   itb->items = eina_list_append(itb->items, it);
3512                   it->position = eina_list_count(itb->items);
3513                }
3514           }
3515      }
3516    else
3517      {
3518         Eina_List *tmp;
3519
3520         if (it->item->rel->item->queued)
3521           {
3522              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3523                 on sorted insertion order, so the queue is not always ordered like the item list.
3524                 This lead to issue where we depend on an item that is not yet created. As a quick
3525                 work around, we reschedule the calc of the item and stop reordering the list to
3526                 prevent any nasty issue to show up here.
3527               */
3528              wd->queue = eina_list_append(wd->queue, it);
3529              wd->requeued = EINA_TRUE;
3530              it->item->queued = EINA_TRUE;
3531              return EINA_FALSE;
3532           }
3533         itb = it->item->rel->item->block;
3534         if (!itb) goto newblock;
3535         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3536         if (it->item->before)
3537           {
3538              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3539              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3540           }
3541         else
3542           {
3543              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3544              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3545           }
3546      }
3547    itb->count++;
3548    itb->changed = EINA_TRUE;
3549    it->item->block = itb;
3550    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3551    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3552    if (it->item->rel)
3553      {
3554         it->item->rel->relcount--;
3555         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3556           {
3557              _item_del(it->item->rel);
3558              elm_widget_item_free(it->item->rel);
3559           }
3560         it->item->rel = NULL;
3561      }
3562    if (itb->count > itb->wd->max_items_per_block)
3563      {
3564         Item_Block *itb2;
3565         Elm_Gen_Item *it2;
3566         int newc;
3567         Eina_Bool done = EINA_FALSE;
3568
3569         newc = itb->count / 2;
3570
3571         if (EINA_INLIST_GET(itb)->prev)
3572           {
3573              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3574
3575              if (itbp->count + newc < wd->max_items_per_block / 2)
3576                {
3577                   /* moving items to previous block */
3578                   while ((itb->count > newc) && (itb->items))
3579                     {
3580                        it2 = eina_list_data_get(itb->items);
3581                        itb->items = eina_list_remove_list(itb->items, itb->items);
3582                        itb->count--;
3583
3584                        itbp->items = eina_list_append(itbp->items, it2);
3585                        it2->item->block = itbp;
3586                        itbp->count++;
3587                     }
3588
3589                   done = EINA_TRUE;
3590                }
3591           }
3592
3593         if (!done && EINA_INLIST_GET(itb)->next)
3594           {
3595              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3596
3597              if (itbn->count + newc < wd->max_items_per_block / 2)
3598                {
3599                   /* moving items to next block */
3600                   while ((itb->count > newc) && (itb->items))
3601                     {
3602                        Eina_List *l;
3603
3604                        l = eina_list_last(itb->items);
3605                        it2 = eina_list_data_get(l);
3606                        itb->items = eina_list_remove_list(itb->items, l);
3607                        itb->count--;
3608
3609                        itbn->items = eina_list_prepend(itbn->items, it2);
3610                        it2->item->block = itbn;
3611                        itbn->count++;
3612                     }
3613
3614                   done = EINA_TRUE;
3615                }
3616           }
3617
3618         if (!done)
3619           {
3620              /* moving items to new block */
3621              itb2 = calloc(1, sizeof(Item_Block));
3622              if (!itb2) return EINA_FALSE;
3623              itb2->wd = wd;
3624              wd->blocks =
3625                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3626                                            EINA_INLIST_GET(itb));
3627              itb2->changed = EINA_TRUE;
3628              while ((itb->count > newc) && (itb->items))
3629                {
3630                   Eina_List *l;
3631
3632                   l = eina_list_last(itb->items);
3633                   it2 = l->data;
3634                   itb->items = eina_list_remove_list(itb->items, l);
3635                   itb->count--;
3636
3637                   itb2->items = eina_list_prepend(itb2->items, it2);
3638                   it2->item->block = itb2;
3639                   itb2->count++;
3640                }
3641           }
3642      }
3643
3644    return EINA_TRUE;
3645 }
3646
3647 static int
3648 _queue_process(Widget_Data *wd)
3649 {
3650    int n;
3651    Eina_Bool showme = EINA_FALSE;
3652    double t0, t;
3653
3654    t0 = ecore_loop_time_get();
3655    //evas_event_freeze(evas_object_evas_get(wd->obj));
3656    for (n = 0; (wd->queue) && (n < 128); n++)
3657      {
3658         Elm_Gen_Item *it;
3659
3660         it = eina_list_data_get(wd->queue);
3661         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3662         it->item->queued = EINA_FALSE;
3663         if (!_item_block_add(wd, it)) continue;
3664         if (!wd->blocks)
3665           _item_block_realize(it->item->block);
3666         t = ecore_time_get();
3667         if (it->item->block->changed)
3668           {
3669              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
3670              it->item->block->changed = 0;
3671              if (wd->pan_changed)
3672                {
3673                   if (wd->calc_job) ecore_job_del(wd->calc_job);
3674                   wd->calc_job = NULL;
3675                   _calc_job(wd);
3676                   wd->pan_changed = EINA_FALSE;
3677                }
3678           }
3679         if (showme) it->item->block->showme = EINA_TRUE;
3680         /* same as eina_inlist_count > 1 */
3681         if (wd->blocks && wd->blocks->next)
3682           {
3683              if ((t - t0) > (ecore_animator_frametime_get())) break;
3684           }
3685      }
3686    //evas_event_thaw(evas_object_evas_get(wd->obj));
3687    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3688    return n;
3689 }
3690
3691 static Eina_Bool
3692 _idle_process(void *data, Eina_Bool *wakeup)
3693 {
3694    Widget_Data *wd = data;
3695
3696    //xxx
3697    //static double q_start = 0.0;
3698    //if (q_start == 0.0) q_start = ecore_time_get();
3699    //xxx
3700    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3701    if (!wd->queue)
3702      {
3703         //xxx
3704         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3705         //xxx
3706         return ECORE_CALLBACK_CANCEL;
3707      }
3708    return ECORE_CALLBACK_RENEW;
3709 }
3710
3711 static Eina_Bool
3712 _item_idle_enterer(void *data)
3713 {
3714    Widget_Data *wd = data;
3715    Eina_Bool wakeup = EINA_FALSE;
3716    Eina_Bool ok = _idle_process(data, &wakeup);
3717
3718    if (wakeup)
3719      {
3720         // wake up mainloop
3721         if (wd->calc_job) ecore_job_del(wd->calc_job);
3722         wd->calc_job = ecore_job_add(_calc_job, wd);
3723      }
3724    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3725    return ok;
3726 }
3727
3728 static void
3729 _item_queue(Widget_Data *wd,
3730             Elm_Gen_Item *it,
3731             Eina_Compare_Cb cb)
3732 {
3733    if (it->item->queued) return;
3734    it->item->queued = EINA_TRUE;
3735    if (cb && !wd->requeued)
3736      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
3737    else
3738      wd->queue = eina_list_append(wd->queue, it);
3739 // FIXME: why does a freeze then thaw here cause some genlist
3740 // elm_genlist_item_append() to be much much slower?
3741 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3742    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3743      {
3744         if (wd->queue_idle_enterer)
3745           {
3746              ecore_idle_enterer_del(wd->queue_idle_enterer);
3747              wd->queue_idle_enterer = NULL;
3748           }
3749         _queue_process(wd);
3750      }
3751 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3752 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3753    if (!wd->queue_idle_enterer)
3754      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3755 }
3756
3757 static int
3758 _elm_genlist_item_compare_data(const void *data, const void *data1)
3759 {
3760    const Elm_Gen_Item *it = data;
3761    const Elm_Gen_Item *item1 = data1;
3762
3763    return it->wd->item_compare_data_cb(it->base.data, item1->base.data);
3764 }
3765
3766 static int
3767 _elm_genlist_item_compare(const void *data, const void *data1)
3768 {
3769    const Elm_Gen_Item *it, *item1;
3770    it = ELM_GEN_ITEM_FROM_INLIST(data);
3771    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
3772    return it->wd->item_compare_cb(it, item1);
3773 }
3774
3775 static int
3776 _elm_genlist_item_list_compare(const void *data, const void *data1)
3777 {
3778    const Elm_Gen_Item *it = data;
3779    const Elm_Gen_Item *item1 = data1;
3780    return it->wd->item_compare_cb(it, item1);
3781 }
3782
3783 static void
3784 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
3785 {
3786    if (!it) return;
3787    if (!after) return;
3788
3789    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3790    _item_block_del(it);
3791
3792    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3793    it->item->rel = after;
3794    it->item->rel->relcount++;
3795    it->item->before = EINA_FALSE;
3796    if (after->item->group_item) it->item->group_item = after->item->group_item;
3797    _item_queue(it->wd, it, NULL);
3798
3799    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3800 }
3801
3802 static void
3803 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
3804 {
3805    if (!it) return;
3806    if (!before) return;
3807
3808    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3809    _item_block_del(it);
3810    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3811    it->item->rel = before;
3812    it->item->rel->relcount++;
3813    it->item->before = EINA_TRUE;
3814    if (before->item->group_item) it->item->group_item = before->item->group_item;
3815    _item_queue(it->wd, it, NULL);
3816
3817    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3818 }
3819
3820 EAPI unsigned int
3821 elm_genlist_items_count(const Evas_Object *obj)
3822 {
3823    ELM_CHECK_WIDTYPE(obj, widtype) 0;
3824    Widget_Data *wd = elm_widget_data_get(obj);
3825    if (!wd) return 0;
3826    return wd->item_count;
3827 }
3828
3829 EAPI Elm_Object_Item *
3830 elm_genlist_item_append(Evas_Object                  *obj,
3831                         const Elm_Genlist_Item_Class *itc,
3832                         const void                   *data,
3833                         Elm_Object_Item              *parent,
3834                         Elm_Genlist_Item_Flags        flags,
3835                         Evas_Smart_Cb                 func,
3836                         const void                   *func_data)
3837 {
3838    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3839    Widget_Data *wd = elm_widget_data_get(obj);
3840    if (!wd) return NULL;
3841    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3842                                 func, func_data);
3843    if (!it) return NULL;
3844    if (!it->parent)
3845      {
3846         if (it->group)
3847           wd->group_items = eina_list_append(wd->group_items, it);
3848         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3849         it->item->rel = NULL;
3850      }
3851    else
3852      {
3853         Elm_Gen_Item *it2 = NULL;
3854         Eina_List *ll = eina_list_last(it->parent->item->items);
3855         if (ll) it2 = ll->data;
3856         it->parent->item->items = eina_list_append(it->parent->item->items, it);
3857         if (!it2) it2 = it->parent;
3858         wd->items =
3859           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3860                                       EINA_INLIST_GET(it2));
3861         it->item->rel = it2;
3862         it->item->rel->relcount++;
3863      }
3864    it->item->before = EINA_FALSE;
3865    _item_queue(wd, it, NULL);
3866    return (Elm_Object_Item *) it;
3867 }
3868
3869 EAPI Elm_Object_Item *
3870 elm_genlist_item_prepend(Evas_Object                  *obj,
3871                          const Elm_Genlist_Item_Class *itc,
3872                          const void                   *data,
3873                          Elm_Object_Item              *parent,
3874                          Elm_Genlist_Item_Flags        flags,
3875                          Evas_Smart_Cb                 func,
3876                          const void                   *func_data)
3877 {
3878    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3879    Widget_Data *wd = elm_widget_data_get(obj);
3880    if (!wd) return NULL;
3881    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3882                                 func, func_data);
3883    if (!it) return NULL;
3884    if (!it->parent)
3885      {
3886         if (it->group)
3887           wd->group_items = eina_list_prepend(wd->group_items, it);
3888         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3889         it->item->rel = NULL;
3890      }
3891    else
3892      {
3893         Elm_Gen_Item *it2 = NULL;
3894         Eina_List *ll = it->parent->item->items;
3895         if (ll) it2 = ll->data;
3896         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
3897         if (!it2) it2 = it->parent;
3898         wd->items =
3899           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3900                                        EINA_INLIST_GET(it2));
3901         it->item->rel = it2;
3902         it->item->rel->relcount++;
3903      }
3904    it->item->before = EINA_TRUE;
3905    _item_queue(wd, it, NULL);
3906    return (Elm_Object_Item *) it;
3907 }
3908
3909 EAPI Elm_Object_Item *
3910 elm_genlist_item_insert_after(Evas_Object                  *obj,
3911                               const Elm_Genlist_Item_Class *itc,
3912                               const void                   *data,
3913                               Elm_Object_Item              *parent,
3914                               Elm_Object_Item              *after,
3915                               Elm_Genlist_Item_Flags        flags,
3916                               Evas_Smart_Cb                 func,
3917                               const void                   *func_data)
3918 {
3919    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3920    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
3921    Widget_Data *wd = elm_widget_data_get(obj);
3922    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
3923    if (!wd) return NULL;
3924    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
3925    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3926
3927    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3928                                 func, func_data);
3929    if (!it) return NULL;
3930    if (!it->parent)
3931      {
3932         if ((it->group) && (_after->group))
3933           wd->group_items = eina_list_append_relative(wd->group_items, it,
3934                                                       _after);
3935      }
3936    else
3937      {
3938         it->parent->item->items =
3939            eina_list_append_relative(it->parent->item->items, it, _after);
3940      }
3941    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3942                                            EINA_INLIST_GET(_after));
3943    it->item->rel = _after;
3944    it->item->rel->relcount++;
3945    it->item->before = EINA_FALSE;
3946    _item_queue(wd, it, NULL);
3947    return (Elm_Object_Item *) it;
3948 }
3949
3950 EAPI Elm_Object_Item *
3951 elm_genlist_item_insert_before(Evas_Object                  *obj,
3952                                const Elm_Genlist_Item_Class *itc,
3953                                const void                   *data,
3954                                Elm_Object_Item              *parent,
3955                                Elm_Object_Item              *before,
3956                                Elm_Genlist_Item_Flags        flags,
3957                                Evas_Smart_Cb                 func,
3958                                const void                   *func_data)
3959 {
3960    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3961    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
3962    Widget_Data *wd = elm_widget_data_get(obj);
3963    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
3964    if (!wd) return NULL;
3965    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
3966    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3967
3968    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3969                                 func, func_data);
3970    if (!it) return NULL;
3971    if (!it->parent)
3972      {
3973         if (it->group && _before->group)
3974           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
3975                                                        _before);
3976      }
3977    else
3978      {
3979         it->parent->item->items =
3980            eina_list_prepend_relative(it->parent->item->items, it, _before);
3981      }
3982    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3983                                             EINA_INLIST_GET(_before));
3984    it->item->rel = _before;
3985    it->item->rel->relcount++;
3986    it->item->before = EINA_TRUE;
3987    _item_queue(wd, it, NULL);
3988    return (Elm_Object_Item *) it;
3989 }
3990
3991 EAPI Elm_Object_Item *
3992 elm_genlist_item_direct_sorted_insert(Evas_Object                  *obj,
3993                                       const Elm_Genlist_Item_Class *itc,
3994                                       const void                   *data,
3995                                       Elm_Object_Item              *parent,
3996                                       Elm_Genlist_Item_Flags        flags,
3997                                       Eina_Compare_Cb               comp,
3998                                       Evas_Smart_Cb                 func,
3999                                       const void                   *func_data)
4000 {
4001    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4002    Widget_Data *wd = elm_widget_data_get(obj);
4003    if (!wd) return NULL;
4004    Elm_Gen_Item *rel = NULL;
4005    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
4006                                 func, func_data);
4007    if (!it) return NULL;
4008
4009    wd->item_compare_cb = comp;
4010
4011    if (it->parent)
4012      {
4013         Eina_List *l;
4014         int cmp_result;
4015
4016         l = eina_list_search_sorted_near_list(it->parent->item->items,
4017                                               _elm_genlist_item_list_compare, it,
4018                                               &cmp_result);
4019         if (l)
4020           rel = eina_list_data_get(l);
4021         else
4022           rel = it->parent;
4023
4024         if (cmp_result >= 0)
4025           {
4026              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4027              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4028              it->item->before = EINA_FALSE;
4029           }
4030         else if (cmp_result < 0)
4031           {
4032              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4033              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4034              it->item->before = EINA_TRUE;
4035           }
4036      }
4037    else
4038      {
4039         if (!wd->state)
4040           {
4041              wd->state = eina_inlist_sorted_state_new();
4042              eina_inlist_sorted_state_init(wd->state, wd->items);
4043              wd->requeued = EINA_FALSE;
4044           }
4045
4046         if (it->group)
4047           wd->group_items = eina_list_append(wd->group_items, it);
4048
4049         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4050                                                     _elm_genlist_item_compare, wd->state);
4051
4052         if (EINA_INLIST_GET(it)->next)
4053           {
4054              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4055              it->item->before = EINA_TRUE;
4056           }
4057         else if (EINA_INLIST_GET(it)->prev)
4058           {
4059              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4060              it->item->before = EINA_FALSE;
4061           }
4062      }
4063
4064    if (rel)
4065      {
4066         it->item->rel = rel;
4067         it->item->rel->relcount++;
4068      }
4069
4070    _item_queue(wd, it, _elm_genlist_item_list_compare);
4071
4072    return (Elm_Object_Item *) it;
4073 }
4074
4075 EAPI Elm_Object_Item *
4076 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4077                                const Elm_Genlist_Item_Class *itc,
4078                                const void                   *data,
4079                                Elm_Object_Item              *parent,
4080                                Elm_Genlist_Item_Flags        flags,
4081                                Eina_Compare_Cb               comp,
4082                                Evas_Smart_Cb                 func,
4083                                const void                   *func_data)
4084 {
4085    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4086    Widget_Data *wd = elm_widget_data_get(obj);
4087    wd->item_compare_data_cb = comp;
4088    return elm_genlist_item_direct_sorted_insert(obj, itc, data, parent, flags,
4089                                                 _elm_genlist_item_compare_data,
4090                                                 func, func_data);
4091 }
4092
4093 static void
4094 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4095 {
4096    Eina_Inlist *next, *l;
4097
4098    ELM_CHECK_WIDTYPE(obj, widtype);
4099    Widget_Data *wd = elm_widget_data_get(obj);
4100    if (!wd) return;
4101
4102    if (!standby) wd->generation++;
4103
4104    if (wd->state)
4105      {
4106         eina_inlist_sorted_state_free(wd->state);
4107         wd->state = NULL;
4108      }
4109
4110    if (wd->walking > 0)
4111      {
4112         wd->clear_me = 1;
4113         return;
4114      }
4115    evas_event_freeze(evas_object_evas_get(wd->obj));
4116    for (l = wd->items, next = l ? l->next : NULL;
4117         l;
4118         l = next, next = next ? next->next : NULL)
4119      {
4120         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4121
4122         if (it->generation < wd->generation)
4123           {
4124              Elm_Gen_Item *itn = NULL;
4125
4126              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4127              if (itn) itn->walking++; /* prevent early death of subitem */
4128              it->del_cb(it);
4129              elm_widget_item_free(it);
4130              if (itn) itn->walking--;
4131           }
4132      }
4133    wd->clear_me = 0;
4134    wd->pan_changed = EINA_TRUE;
4135    if (wd->calc_job)
4136      {
4137         ecore_job_del(wd->calc_job);
4138         wd->calc_job = NULL;
4139      }
4140    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4141    if (wd->clear_cb) wd->clear_cb(wd);
4142    wd->pan_x = 0;
4143    wd->pan_y = 0;
4144    wd->minw = 0;
4145    wd->minh = 0;
4146    if (wd->pan_smart)
4147      {
4148         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4149         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4150      }
4151    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4152    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4153    evas_event_thaw(evas_object_evas_get(wd->obj));
4154    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4155 }
4156
4157 EAPI void
4158 elm_genlist_clear(Evas_Object *obj)
4159 {
4160    _elm_genlist_clear(obj, EINA_FALSE);
4161 }
4162
4163 EAPI void
4164 elm_genlist_multi_select_set(Evas_Object *obj,
4165                              Eina_Bool    multi)
4166 {
4167    ELM_CHECK_WIDTYPE(obj, widtype);
4168    Widget_Data *wd = elm_widget_data_get(obj);
4169    if (!wd) return;
4170    wd->multi = multi;
4171 }
4172
4173 EAPI Eina_Bool
4174 elm_genlist_multi_select_get(const Evas_Object *obj)
4175 {
4176    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4177    Widget_Data *wd = elm_widget_data_get(obj);
4178    if (!wd) return EINA_FALSE;
4179    return wd->multi;
4180 }
4181
4182 EAPI Elm_Object_Item *
4183 elm_genlist_selected_item_get(const Evas_Object *obj)
4184 {
4185    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4186    Widget_Data *wd = elm_widget_data_get(obj);
4187    if (!wd) return NULL;
4188    if (wd->selected) return wd->selected->data;
4189    return NULL;
4190 }
4191
4192 EAPI const Eina_List *
4193 elm_genlist_selected_items_get(const Evas_Object *obj)
4194 {
4195    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4196    Widget_Data *wd = elm_widget_data_get(obj);
4197    if (!wd) return NULL;
4198    return wd->selected;
4199 }
4200
4201 EAPI Eina_List *
4202 elm_genlist_realized_items_get(const Evas_Object *obj)
4203 {
4204    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4205    Widget_Data *wd = elm_widget_data_get(obj);
4206    Eina_List *list = NULL;
4207    Item_Block *itb;
4208    Eina_Bool done = EINA_FALSE;
4209    if (!wd) return NULL;
4210    EINA_INLIST_FOREACH(wd->blocks, itb)
4211      {
4212         if (itb->realized)
4213           {
4214              Eina_List *l;
4215              Elm_Gen_Item *it;
4216
4217              done = 1;
4218              EINA_LIST_FOREACH(itb->items, l, it)
4219                {
4220                   if (it->realized) list = eina_list_append(list, it);
4221                }
4222           }
4223         else
4224           {
4225              if (done) break;
4226           }
4227      }
4228    return list;
4229 }
4230
4231 EAPI Elm_Object_Item *
4232 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4233                            Evas_Coord         x,
4234                            Evas_Coord         y,
4235                            int               *posret)
4236 {
4237    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4238    Widget_Data *wd = elm_widget_data_get(obj);
4239    Evas_Coord ox, oy, ow, oh;
4240    Item_Block *itb;
4241    Evas_Coord lasty;
4242    if (!wd) return NULL;
4243    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4244    lasty = oy;
4245    EINA_INLIST_FOREACH(wd->blocks, itb)
4246      {
4247         Eina_List *l;
4248         Elm_Gen_Item *it;
4249
4250         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4251                                  oy + itb->y - itb->wd->pan_y,
4252                                  itb->w, itb->h, x, y, 1, 1))
4253           continue;
4254         EINA_LIST_FOREACH(itb->items, l, it)
4255           {
4256              Evas_Coord itx, ity;
4257
4258              itx = ox + itb->x + it->x - itb->wd->pan_x;
4259              ity = oy + itb->y + it->y - itb->wd->pan_y;
4260              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4261                {
4262                   if (posret)
4263                     {
4264                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
4265                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
4266                          *posret = 1;
4267                        else *posret = 0;
4268                     }
4269                   return (Elm_Object_Item *) it;
4270                }
4271              lasty = ity + it->item->h;
4272           }
4273      }
4274    if (posret)
4275      {
4276         if (y > lasty) *posret = 1;
4277         else *posret = -1;
4278      }
4279    return NULL;
4280 }
4281
4282 EAPI Elm_Object_Item *
4283 elm_genlist_first_item_get(const Evas_Object *obj)
4284 {
4285    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4286    Widget_Data *wd = elm_widget_data_get(obj);
4287    if (!wd) return NULL;
4288    if (!wd->items) return NULL;
4289    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4290    while ((it) && (it->generation < wd->generation))
4291      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4292    return (Elm_Object_Item *) it;
4293 }
4294
4295 EAPI Elm_Object_Item *
4296 elm_genlist_last_item_get(const Evas_Object *obj)
4297 {
4298    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4299    Widget_Data *wd = elm_widget_data_get(obj);
4300    if (!wd) return NULL;
4301    if (!wd->items) return NULL;
4302    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4303    while ((it) && (it->generation < wd->generation))
4304      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4305    return (Elm_Object_Item *) it;
4306 }
4307
4308 EAPI Elm_Object_Item *
4309 elm_genlist_item_next_get(const Elm_Object_Item *it)
4310 {
4311    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4312    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4313    while (_it)
4314      {
4315         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
4316         if ((_it) && (_it->generation == _it->wd->generation)) break;
4317      }
4318    return (Elm_Object_Item *) _it;
4319 }
4320
4321 EAPI Elm_Object_Item *
4322 elm_genlist_item_prev_get(const Elm_Object_Item *it)
4323 {
4324    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4325    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4326    while (_it)
4327      {
4328         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
4329         if ((_it) && (_it->generation == _it->wd->generation)) break;
4330      }
4331    return (Elm_Object_Item *) _it;
4332 }
4333
4334 EAPI Evas_Object *
4335 elm_genlist_item_genlist_get(const Elm_Object_Item *it)
4336 {
4337    return elm_object_item_widget_get(it);
4338 }
4339
4340 EAPI Elm_Object_Item *
4341 elm_genlist_item_parent_get(const Elm_Object_Item *it)
4342 {
4343    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4344    return (Elm_Object_Item *) ((Elm_Gen_Item *) it)->parent;
4345 }
4346
4347 EAPI void
4348 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4349 {
4350    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4351    Eina_List *tl = NULL, *l;
4352    Elm_Gen_Item *_it;
4353    Elm_Object_Item *it2;
4354    _it = (Elm_Gen_Item *) it;
4355
4356    EINA_LIST_FOREACH(_it->item->items, l, it2)
4357      tl = eina_list_append(tl, it2);
4358    EINA_LIST_FREE(tl, it2)
4359      elm_object_item_del(it2);
4360 }
4361
4362 EAPI void
4363 elm_genlist_item_selected_set(Elm_Object_Item *it,
4364                               Eina_Bool selected)
4365 {
4366    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4367    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4368    Widget_Data *wd = _it->wd;
4369    if (!wd) return;
4370    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4371      return;
4372    selected = !!selected;
4373    if (_it->selected == selected) return;
4374
4375    if (selected)
4376      {
4377         if (!wd->multi)
4378           {
4379              while (wd->selected)
4380                {
4381                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4382                   _it->unsel_cb(wd->selected->data);
4383                }
4384           }
4385         _it->highlight_cb(_it);
4386         _item_select(_it);
4387         return;
4388      }
4389    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4390    _it->unsel_cb(_it);
4391 }
4392
4393 EAPI Eina_Bool
4394 elm_genlist_item_selected_get(const Elm_Object_Item *it)
4395 {
4396    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4397    return ((Elm_Gen_Item *) it)->selected;
4398 }
4399
4400 EAPI void
4401 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
4402                               Eina_Bool         expanded)
4403 {
4404    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4405    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4406    if (_it->item->expanded == expanded) return;
4407    _it->item->expanded = expanded;
4408    _it->wd->expanded_item = _it;
4409    if (_it->item->expanded)
4410      {
4411         if (_it->realized)
4412           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4413         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4414         _it->wd->auto_scroll_enabled = EINA_TRUE;
4415      }
4416    else
4417      {
4418         if (_it->realized)
4419           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4420         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4421         _it->wd->auto_scroll_enabled = EINA_FALSE;
4422      }
4423 }
4424
4425 EAPI Eina_Bool
4426 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4427 {
4428    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4429    return ((Elm_Gen_Item *) it)->item->expanded;
4430 }
4431
4432 EAPI int
4433 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4434 {
4435    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4436    return ((Elm_Gen_Item *) it)->item->expanded_depth;
4437 }
4438
4439 EAPI void
4440 elm_genlist_item_disabled_set(Elm_Object_Item  *it,
4441                               Eina_Bool         disabled)
4442 {
4443    elm_object_item_disabled_set(it, disabled);
4444 }
4445
4446 EAPI Eina_Bool
4447 elm_genlist_item_disabled_get(const Elm_Object_Item *it)
4448 {
4449    return elm_object_item_disabled_get(it);
4450 }
4451
4452 EAPI void
4453 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
4454                                   Eina_Bool         display_only)
4455 {
4456    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4457    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4458    display_only = !!display_only;
4459    if (_it->display_only == display_only) return;
4460    if (_it->generation < _it->wd->generation) return;
4461    _it->display_only = display_only;
4462    _it->item->mincalcd = EINA_FALSE;
4463    _it->item->updateme = EINA_TRUE;
4464    if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
4465    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4466    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4467 }
4468
4469 EAPI Eina_Bool
4470 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
4471 {
4472    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4473    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4474    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4475    return _it->display_only;
4476 }
4477
4478 EAPI void
4479 elm_genlist_item_show(Elm_Object_Item *it)
4480 {
4481    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4482    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4483    Evas_Coord gith = 0;
4484    if (_it->generation < _it->wd->generation) return;
4485    if ((_it->item->queued) || (!_it->item->mincalcd))
4486      {
4487         _it->wd->show_item = _it;
4488         _it->wd->bring_in = EINA_FALSE;
4489         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
4490         _it->item->showme = EINA_TRUE;
4491         return;
4492      }
4493    if (_it->wd->show_item)
4494      {
4495         _it->wd->show_item->item->showme = EINA_FALSE;
4496         _it->wd->show_item = NULL;
4497      }
4498    if ((_it->item->group_item) &&
4499        (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4500      gith = _it->item->group_item->item->h;
4501    elm_smart_scroller_child_region_show(_it->wd->scr,
4502                                         _it->x + _it->item->block->x,
4503                                         _it->y + _it->item->block->y - gith,
4504                                         _it->item->block->w, _it->item->h);
4505 }
4506
4507 EAPI void
4508 elm_genlist_item_promote(Elm_Object_Item *it)
4509 {
4510    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4511    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4512    if (_it->generation < _it->wd->generation) return;
4513    _item_move_before(_it,
4514                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4515 }
4516
4517 EAPI void
4518 elm_genlist_item_demote(Elm_Object_Item *it)
4519 {
4520    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4521    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4522    if (_it->generation < _it->wd->generation) return;
4523    _item_move_after(_it,
4524                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4525 }
4526
4527 EAPI void
4528 elm_genlist_item_bring_in(Elm_Object_Item *it)
4529 {
4530    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4531    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4532    Evas_Coord gith = 0;
4533    if (_it->generation < _it->wd->generation) return;
4534    if ((_it->item->queued) || (!_it->item->mincalcd))
4535      {
4536         _it->wd->show_item = _it;
4537         _it->wd->bring_in = EINA_TRUE;
4538         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
4539         _it->item->showme = EINA_TRUE;
4540         return;
4541      }
4542    if (_it->wd->show_item)
4543      {
4544         _it->wd->show_item->item->showme = EINA_FALSE;
4545         _it->wd->show_item = NULL;
4546      }
4547    if ((_it->item->group_item) &&
4548        (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4549      gith = _it->item->group_item->item->h;
4550    elm_smart_scroller_region_bring_in(_it->wd->scr,
4551                                       _it->x + _it->item->block->x,
4552                                       _it->y + _it->item->block->y - gith,
4553                                       _it->item->block->w, _it->item->h);
4554 }
4555
4556 EAPI void
4557 elm_genlist_item_top_show(Elm_Object_Item *it)
4558 {
4559    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4560    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4561    Evas_Coord ow, oh;
4562    Evas_Coord gith = 0;
4563
4564    if (_it->generation < _it->wd->generation) return;
4565    if ((_it->item->queued) || (!_it->item->mincalcd))
4566      {
4567         _it->wd->show_item = _it;
4568         _it->wd->bring_in = EINA_FALSE;
4569         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
4570         _it->item->showme = EINA_TRUE;
4571         return;
4572      }
4573    if (_it->wd->show_item)
4574      {
4575         _it->wd->show_item->item->showme = EINA_FALSE;
4576         _it->wd->show_item = NULL;
4577      }
4578    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4579    if (_it->item->group_item) gith = _it->item->group_item->item->h;
4580    elm_smart_scroller_child_region_show(_it->wd->scr,
4581                                         _it->x + _it->item->block->x,
4582                                         _it->y + _it->item->block->y - gith,
4583                                         _it->item->block->w, oh);
4584 }
4585
4586 EAPI void
4587 elm_genlist_item_top_bring_in(Elm_Object_Item *it)
4588 {
4589    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4590    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4591    Evas_Coord ow, oh;
4592    Evas_Coord gith = 0;
4593
4594    if (_it->generation < _it->wd->generation) return;
4595    if ((_it->item->queued) || (!_it->item->mincalcd))
4596      {
4597         _it->wd->show_item = _it;
4598         _it->wd->bring_in = EINA_TRUE;
4599         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
4600         _it->item->showme = EINA_TRUE;
4601         return;
4602      }
4603    if (_it->wd->show_item)
4604      {
4605         _it->wd->show_item->item->showme = EINA_FALSE;
4606         _it->wd->show_item = NULL;
4607      }
4608    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4609    if (_it->item->group_item) gith = _it->item->group_item->item->h;
4610    elm_smart_scroller_region_bring_in(_it->wd->scr,
4611                                       _it->x + _it->item->block->x,
4612                                       _it->y + _it->item->block->y - gith,
4613                                       _it->item->block->w, oh);
4614 }
4615
4616 EAPI void
4617 elm_genlist_item_middle_show(Elm_Object_Item *it)
4618 {
4619    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4620    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4621    Evas_Coord ow, oh;
4622
4623    if (_it->generation < _it->wd->generation) return;
4624    if ((_it->item->queued) || (!_it->item->mincalcd))
4625      {
4626         _it->wd->show_item = _it;
4627         _it->wd->bring_in = EINA_FALSE;
4628         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
4629         _it->item->showme = EINA_TRUE;
4630         return;
4631      }
4632    if (_it->wd->show_item)
4633      {
4634         _it->wd->show_item->item->showme = EINA_FALSE;
4635         _it->wd->show_item = NULL;
4636      }
4637    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4638    elm_smart_scroller_child_region_show(_it->wd->scr,
4639                                         _it->x + _it->item->block->x,
4640                                         _it->y + _it->item->block->y - oh / 2 +
4641                                         _it->item->h / 2, _it->item->block->w,
4642                                         oh);
4643 }
4644
4645 EAPI void
4646 elm_genlist_item_middle_bring_in(Elm_Object_Item *it)
4647 {
4648    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4649    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4650    Evas_Coord ow, oh;
4651
4652    if (_it->generation < _it->wd->generation) return;
4653    if ((_it->item->queued) || (!_it->item->mincalcd))
4654      {
4655         _it->wd->show_item = _it;
4656         _it->wd->bring_in = EINA_TRUE;
4657         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
4658         _it->item->showme = EINA_TRUE;
4659         return;
4660      }
4661    if (_it->wd->show_item)
4662      {
4663         _it->wd->show_item->item->showme = EINA_FALSE;
4664         _it->wd->show_item = NULL;
4665      }
4666    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4667    elm_smart_scroller_region_bring_in(_it->wd->scr,
4668                                       _it->x + _it->item->block->x,
4669                                       _it->y + _it->item->block->y - oh / 2 +
4670                                       _it->item->h / 2, _it->item->block->w,
4671                                       oh);
4672 }
4673
4674 EAPI void
4675 elm_genlist_item_del(Elm_Object_Item *it)
4676 {
4677    elm_object_item_del(it);
4678 }
4679
4680 EAPI void
4681 elm_genlist_item_data_set(Elm_Object_Item  *it,
4682                           const void       *data)
4683 {
4684    elm_object_item_data_set(it, (void *) data);
4685 }
4686
4687 EAPI void *
4688 elm_genlist_item_data_get(const Elm_Object_Item *it)
4689 {
4690    return elm_object_item_data_get(it);
4691 }
4692
4693 EAPI void
4694 elm_genlist_item_icons_orphan(Elm_Object_Item *it)
4695 {
4696    elm_genlist_item_contents_orphan(it);
4697 }
4698
4699 EAPI void
4700 elm_genlist_item_contents_orphan(Elm_Object_Item *it)
4701 {
4702    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4703
4704    Evas_Object *content;
4705    EINA_LIST_FREE(((Elm_Gen_Item *) it)->content_objs, content)
4706      {
4707         elm_widget_sub_object_del(WIDGET(it), content);
4708         evas_object_smart_member_del(content);
4709         evas_object_hide(content);
4710      }
4711 }
4712
4713 EAPI const Evas_Object *
4714 elm_genlist_item_object_get(const Elm_Object_Item *it)
4715 {
4716    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4717    return VIEW(it);
4718 }
4719
4720 EAPI void
4721 elm_genlist_item_update(Elm_Object_Item *it)
4722 {
4723    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4724    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4725
4726    if (!_it->item->block) return;
4727    if (_it->generation < _it->wd->generation) return;
4728    _it->item->mincalcd = EINA_FALSE;
4729    _it->item->updateme = EINA_TRUE;
4730    _it->item->block->updateme = EINA_TRUE;
4731    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4732    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4733 }
4734
4735 EAPI void
4736 elm_genlist_item_fields_update(Elm_Object_Item *it,
4737                                const char *parts,
4738                                Elm_Genlist_Item_Field_Flags itf)
4739 {
4740    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4741    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4742
4743    if (!_it->item->block) return;
4744    if (_it->generation < _it->wd->generation) return;
4745
4746    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4747      _item_text_realize(_it, _it->base.view, &_it->texts, parts);
4748    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4749      {
4750         _it->content_objs = _item_content_unrealize(_it, _it->base.view,
4751                                                    &_it->contents, parts);
4752         _it->content_objs = _item_content_realize(_it, _it->base.view,
4753                                                  &_it->contents, parts);
4754      }
4755    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4756      _item_state_realize(_it, _it->base.view, &_it->states, parts);
4757 }
4758
4759 EAPI void
4760 elm_genlist_item_item_class_update(Elm_Object_Item *it,
4761                                    const Elm_Genlist_Item_Class *itc)
4762 {
4763    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4764    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4765
4766    if (!_it->item->block) return;
4767    EINA_SAFETY_ON_NULL_RETURN(itc);
4768    if (_it->generation < _it->wd->generation) return;
4769    _it->itc = itc;
4770    _it->item->nocache = EINA_TRUE;
4771    elm_genlist_item_update(it);
4772 }
4773
4774 EAPI const Elm_Genlist_Item_Class *
4775 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
4776 {
4777    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4778    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4779    if (_it->generation < _it->wd->generation) return NULL;
4780    return _it->itc;
4781 }
4782
4783 static Evas_Object *
4784 _elm_genlist_item_label_create(void        *data,
4785                                Evas_Object *obj __UNUSED__,
4786                                Evas_Object *tooltip,
4787                                void        *it __UNUSED__)
4788 {
4789    Evas_Object *label = elm_label_add(tooltip);
4790    if (!label)
4791      return NULL;
4792    elm_object_style_set(label, "tooltip");
4793    elm_object_text_set(label, data);
4794    return label;
4795 }
4796
4797 static void
4798 _elm_genlist_item_label_del_cb(void        *data,
4799                                Evas_Object *obj __UNUSED__,
4800                                void        *event_info __UNUSED__)
4801 {
4802    eina_stringshare_del(data);
4803 }
4804
4805 EAPI void
4806 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
4807                                   const char      *text)
4808 {
4809    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4810    text = eina_stringshare_add(text);
4811    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4812                                            text,
4813                                            _elm_genlist_item_label_del_cb);
4814 }
4815
4816 EAPI void
4817 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
4818                                         Elm_Tooltip_Item_Content_Cb func,
4819                                         const void                 *data,
4820                                         Evas_Smart_Cb               del_cb)
4821 {
4822    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
4823    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4824
4825    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
4826      return;
4827
4828    if (_it->tooltip.del_cb)
4829      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
4830
4831    _it->tooltip.content_cb = func;
4832    _it->tooltip.data = data;
4833    _it->tooltip.del_cb = del_cb;
4834
4835    if (VIEW(_it))
4836      {
4837         elm_widget_item_tooltip_content_cb_set(_it,
4838                                                _it->tooltip.content_cb,
4839                                                _it->tooltip.data, NULL);
4840         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
4841         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
4842      }
4843
4844    return;
4845
4846 error:
4847    if (del_cb) del_cb((void *)data, NULL, NULL);
4848 }
4849
4850 EAPI void
4851 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
4852 {
4853    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4854    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4855
4856    if ((VIEW(_it)) && (_it->tooltip.content_cb))
4857      elm_widget_item_tooltip_unset(_it);
4858
4859    if (_it->tooltip.del_cb)
4860      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
4861    _it->tooltip.del_cb = NULL;
4862    _it->tooltip.content_cb = NULL;
4863    _it->tooltip.data = NULL;
4864    _it->tooltip.free_size = EINA_FALSE;
4865    if (_it->tooltip.style)
4866      elm_genlist_item_tooltip_style_set(it, NULL);
4867 }
4868
4869 EAPI void
4870 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
4871                                    const char       *style)
4872 {
4873    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4874    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4875
4876    eina_stringshare_replace(&_it->tooltip.style, style);
4877    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
4878 }
4879
4880 EAPI const char *
4881 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
4882 {
4883    return elm_object_item_tooltip_style_get(it);
4884 }
4885
4886 EAPI Eina_Bool
4887 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
4888                                          Eina_Bool disable)
4889 {
4890    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4891    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4892
4893    _it->tooltip.free_size = disable;
4894    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
4895    return EINA_TRUE;
4896 }
4897
4898 EAPI Eina_Bool
4899 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
4900 {
4901    return elm_object_tooltip_window_mode_get(VIEW(it));
4902 }
4903
4904 EAPI void
4905 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
4906                             const char       *cursor)
4907 {
4908    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4909    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4910    eina_stringshare_replace(&_it->mouse_cursor, cursor);
4911    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
4912 }
4913
4914 EAPI const char *
4915 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
4916 {
4917    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4918    return elm_widget_item_cursor_get(it);
4919 }
4920
4921 EAPI void
4922 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
4923 {
4924    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4925    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4926
4927    if (!_it->mouse_cursor) return;
4928
4929    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
4930
4931    eina_stringshare_del(_it->mouse_cursor);
4932    _it->mouse_cursor = NULL;
4933 }
4934
4935 EAPI void
4936 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
4937                                   const char       *style)
4938 {
4939    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4940    elm_widget_item_cursor_style_set(it, style);
4941 }
4942
4943 EAPI const char *
4944 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
4945 {
4946    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4947    return elm_widget_item_cursor_style_get(it);
4948 }
4949
4950 EAPI void
4951 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
4952                                         Eina_Bool        engine_only)
4953 {
4954    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4955    elm_widget_item_cursor_engine_only_set(it, engine_only);
4956 }
4957
4958 EAPI Eina_Bool
4959 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
4960 {
4961    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4962    return elm_widget_item_cursor_engine_only_get(it);
4963 }
4964
4965 EAPI int
4966 elm_genlist_item_index_get(Elm_Object_Item *it)
4967 {
4968    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
4969    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4970
4971    if (_it->item->block)
4972      return _it->position + _it->item->block->position;
4973    return -1;
4974 }
4975
4976 EAPI void
4977 elm_genlist_mode_set(Evas_Object  *obj,
4978                      Elm_List_Mode mode)
4979 {
4980    ELM_CHECK_WIDTYPE(obj, widtype);
4981    Widget_Data *wd = elm_widget_data_get(obj);
4982    if (!wd) return;
4983    if (wd->mode == mode) return;
4984    wd->mode = mode;
4985    _sizing_eval(obj);
4986 }
4987
4988 EAPI void
4989 elm_genlist_horizontal_set(Evas_Object  *obj,
4990                            Elm_List_Mode mode)
4991 {
4992    elm_genlist_mode_set(obj, mode);
4993 }
4994
4995 EAPI void
4996 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4997                                 Elm_List_Mode mode)
4998 {
4999    elm_genlist_mode_set(obj, mode);
5000 }
5001
5002 EAPI Elm_List_Mode
5003 elm_genlist_mode_get(const Evas_Object *obj)
5004 {
5005    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5006    Widget_Data *wd = elm_widget_data_get(obj);
5007    if (!wd) return ELM_LIST_LAST;
5008    return wd->mode;
5009 }
5010
5011 EAPI Elm_List_Mode
5012 elm_genlist_horizontal_get(const Evas_Object *obj)
5013 {
5014    return elm_genlist_mode_get(obj);
5015 }
5016
5017 EAPI Elm_List_Mode
5018 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
5019 {
5020    return elm_genlist_mode_get(obj);
5021 }
5022
5023 EAPI void
5024 elm_genlist_always_select_mode_set(Evas_Object *obj,
5025                                    Eina_Bool    always_select)
5026 {
5027    ELM_CHECK_WIDTYPE(obj, widtype);
5028    Widget_Data *wd = elm_widget_data_get(obj);
5029    if (!wd) return;
5030    wd->always_select = always_select;
5031 }
5032
5033 EAPI Eina_Bool
5034 elm_genlist_always_select_mode_get(const Evas_Object *obj)
5035 {
5036    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5037    Widget_Data *wd = elm_widget_data_get(obj);
5038    if (!wd) return EINA_FALSE;
5039    return wd->always_select;
5040 }
5041
5042 EAPI void
5043 elm_genlist_no_select_mode_set(Evas_Object *obj,
5044                                Eina_Bool    no_select)
5045 {
5046    ELM_CHECK_WIDTYPE(obj, widtype);
5047    Widget_Data *wd = elm_widget_data_get(obj);
5048    if (!wd) return;
5049    wd->no_select = no_select;
5050 }
5051
5052 EAPI Eina_Bool
5053 elm_genlist_no_select_mode_get(const Evas_Object *obj)
5054 {
5055    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5056    Widget_Data *wd = elm_widget_data_get(obj);
5057    if (!wd) return EINA_FALSE;
5058    return wd->no_select;
5059 }
5060
5061 EAPI void
5062 elm_genlist_compress_mode_set(Evas_Object *obj,
5063                               Eina_Bool    compress)
5064 {
5065    ELM_CHECK_WIDTYPE(obj, widtype);
5066    Widget_Data *wd = elm_widget_data_get(obj);
5067    if (!wd) return;
5068    wd->compress = compress;
5069    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
5070 }
5071
5072 EAPI Eina_Bool
5073 elm_genlist_compress_mode_get(const Evas_Object *obj)
5074 {
5075    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5076    Widget_Data *wd = elm_widget_data_get(obj);
5077    if (!wd) return EINA_FALSE;
5078    return wd->compress;
5079 }
5080
5081 EAPI void
5082 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5083                                       Eina_Bool    height_for_width)
5084 {
5085    ELM_CHECK_WIDTYPE(obj, widtype);
5086    Widget_Data *wd = elm_widget_data_get(obj);
5087    if (!wd) return;
5088    wd->height_for_width = !!height_for_width;
5089    if (wd->height_for_width)
5090      {
5091         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5092         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5093      }
5094 }
5095
5096 EAPI Eina_Bool
5097 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5098 {
5099    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5100    Widget_Data *wd = elm_widget_data_get(obj);
5101    if (!wd) return EINA_FALSE;
5102    return wd->height_for_width;
5103 }
5104
5105 EAPI void
5106 elm_genlist_bounce_set(Evas_Object *obj,
5107                        Eina_Bool    h_bounce,
5108                        Eina_Bool    v_bounce)
5109 {
5110    ELM_CHECK_WIDTYPE(obj, widtype);
5111    Widget_Data *wd = elm_widget_data_get(obj);
5112    if (!wd) return;
5113    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
5114    wd->h_bounce = h_bounce;
5115    wd->v_bounce = v_bounce;
5116 }
5117
5118 EAPI void
5119 elm_genlist_bounce_get(const Evas_Object *obj,
5120                        Eina_Bool         *h_bounce,
5121                        Eina_Bool         *v_bounce)
5122 {
5123    ELM_CHECK_WIDTYPE(obj, widtype);
5124    Widget_Data *wd = elm_widget_data_get(obj);
5125    if (!wd) return;
5126    if (h_bounce) *h_bounce = wd->h_bounce;
5127    if (v_bounce) *v_bounce = wd->v_bounce;
5128 }
5129
5130 EAPI void
5131 elm_genlist_homogeneous_set(Evas_Object *obj,
5132                             Eina_Bool    homogeneous)
5133 {
5134    ELM_CHECK_WIDTYPE(obj, widtype);
5135    Widget_Data *wd = elm_widget_data_get(obj);
5136    if (!wd) return;
5137    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5138    wd->homogeneous = homogeneous;
5139 }
5140
5141 EAPI Eina_Bool
5142 elm_genlist_homogeneous_get(const Evas_Object *obj)
5143 {
5144    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5145    Widget_Data *wd = elm_widget_data_get(obj);
5146    if (!wd) return EINA_FALSE;
5147    return wd->homogeneous;
5148 }
5149
5150 EAPI void
5151 elm_genlist_block_count_set(Evas_Object *obj,
5152                             int          n)
5153 {
5154    ELM_CHECK_WIDTYPE(obj, widtype);
5155    Widget_Data *wd = elm_widget_data_get(obj);
5156    if (!wd) return;
5157    wd->max_items_per_block = n;
5158    wd->item_cache_max = wd->max_items_per_block * 2;
5159    _item_cache_clean(wd);
5160 }
5161
5162 EAPI int
5163 elm_genlist_block_count_get(const Evas_Object *obj)
5164 {
5165    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5166    Widget_Data *wd = elm_widget_data_get(obj);
5167    if (!wd) return 0;
5168    return wd->max_items_per_block;
5169 }
5170
5171 EAPI void
5172 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5173                                   double       timeout)
5174 {
5175    ELM_CHECK_WIDTYPE(obj, widtype);
5176    Widget_Data *wd = elm_widget_data_get(obj);
5177    if (!wd) return;
5178    wd->longpress_timeout = timeout;
5179 }
5180
5181 EAPI double
5182 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5183 {
5184    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5185    Widget_Data *wd = elm_widget_data_get(obj);
5186    if (!wd) return 0;
5187    return wd->longpress_timeout;
5188 }
5189
5190 EAPI void
5191 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5192                                 Elm_Scroller_Policy policy_h,
5193                                 Elm_Scroller_Policy policy_v)
5194 {
5195    ELM_CHECK_WIDTYPE(obj, widtype);
5196    Widget_Data *wd = elm_widget_data_get(obj);
5197    if ((!wd) || (!wd->scr)) return;
5198    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5199        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5200      return;
5201    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5202 }
5203
5204 EAPI void
5205 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5206                                 Elm_Scroller_Policy *policy_h,
5207                                 Elm_Scroller_Policy *policy_v)
5208 {
5209    ELM_CHECK_WIDTYPE(obj, widtype);
5210    Widget_Data *wd = elm_widget_data_get(obj);
5211    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5212    if ((!wd) || (!wd->scr)) return;
5213    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5214    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5215    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5216 }
5217
5218 EAPI void
5219 elm_genlist_realized_items_update(Evas_Object *obj)
5220 {
5221    ELM_CHECK_WIDTYPE(obj, widtype);
5222
5223    Eina_List *list, *l;
5224    Elm_Object_Item *it;
5225
5226    list = elm_genlist_realized_items_get(obj);
5227    EINA_LIST_FOREACH(list, l, it)
5228      elm_genlist_item_update(it);
5229 }
5230
5231 EAPI void
5232 elm_genlist_item_mode_set(Elm_Object_Item  *it,
5233                           const char       *mode_type,
5234                           Eina_Bool         mode_set)
5235 {
5236    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5237    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5238
5239    Widget_Data *wd = _it->wd;
5240    Eina_List *l;
5241    Elm_Object_Item *it2;
5242
5243    if (!wd) return;
5244    if (!mode_type) return;
5245    if ((_it->generation < _it->wd->generation) ||
5246        elm_widget_item_disabled_get(_it)) return;
5247
5248    if ((wd->mode_item == _it) &&
5249        (!strcmp(mode_type, wd->mode_type)) &&
5250        (mode_set))
5251       return;
5252    if (!_it->itc->mode_item_style) return;
5253    _it->mode_set = mode_set;
5254
5255    if (wd->multi)
5256      {
5257         EINA_LIST_FOREACH(wd->selected, l, it2)
5258           if (((Elm_Gen_Item *) it2)->realized)
5259             elm_genlist_item_selected_set(it2, EINA_FALSE);
5260      }
5261    else
5262      {
5263         it2 = elm_genlist_selected_item_get(wd->obj);
5264         if ((it2) && (((Elm_Gen_Item *) it2)->realized))
5265           elm_genlist_item_selected_set(it2, EINA_FALSE);
5266      }
5267
5268    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5269        (mode_set) ||
5270        ((_it == wd->mode_item) && (!mode_set)))
5271      _item_mode_unset(wd);
5272
5273    eina_stringshare_replace(&wd->mode_type, mode_type);
5274    if (mode_set) _item_mode_set(_it);
5275 }
5276
5277 EAPI const char *
5278 elm_genlist_mode_item_style_get(const Evas_Object *obj)
5279 {
5280    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5281    Widget_Data *wd = elm_widget_data_get(obj);
5282    if (!wd) return NULL;
5283    return wd->mode_item->itc->mode_item_style;
5284 }
5285
5286 EAPI void
5287 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
5288 {
5289    ELM_CHECK_WIDTYPE(obj, widtype);
5290    Widget_Data *wd = elm_widget_data_get(obj);
5291    if (!wd) return;
5292    if ((style == wd->mode_item->itc->mode_item_style) ||
5293        (style && wd->mode_item->itc->mode_item_style &&
5294        (!strcmp(style, wd->mode_item->itc->mode_item_style))))
5295      return;
5296    eina_stringshare_replace((const char**)&wd->mode_item->itc->mode_item_style, style);
5297    elm_genlist_realized_items_update(obj);
5298 }
5299
5300 EAPI const char *
5301 elm_genlist_mode_type_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 wd->mode_type;
5307 }
5308
5309 EAPI const Elm_Object_Item *
5310 elm_genlist_mode_item_get(const Evas_Object *obj)
5311 {
5312    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5313    Widget_Data *wd = elm_widget_data_get(obj);
5314    if (!wd) return NULL;
5315    return (Elm_Object_Item *) wd->mode_item;
5316 }
5317
5318 EAPI void
5319 elm_genlist_reorder_mode_set(Evas_Object *obj,
5320                              Eina_Bool    reorder_mode)
5321 {
5322    ELM_CHECK_WIDTYPE(obj, widtype);
5323    Widget_Data *wd = elm_widget_data_get(obj);
5324    if (!wd) return;
5325    wd->reorder_mode = reorder_mode;
5326 }
5327
5328 EAPI Eina_Bool
5329 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5330 {
5331    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5332    Widget_Data *wd = elm_widget_data_get(obj);
5333    if (!wd) return EINA_FALSE;
5334    return wd->reorder_mode;
5335 }
5336
5337 EAPI Elm_Genlist_Item_Flags
5338 elm_genlist_item_flags_get(const Elm_Object_Item *it)
5339 {
5340    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5341    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5342    return _it->item->flags;
5343 }
5344
5345 EAPI Elm_Genlist_Item_Class *
5346 elm_genlist_item_class_new(void)
5347 {
5348    Elm_Genlist_Item_Class *itc;
5349
5350    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5351    if (!itc)
5352      return NULL;
5353    itc->version = ELM_GENLIST_ITEM_CLASS_VERSION;
5354    itc->refcount = 1;
5355    itc->delete_me = EINA_FALSE;
5356
5357    return itc;
5358 }
5359
5360 EAPI void
5361 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5362 {
5363    if (itc && (itc->version == ELM_GENLIST_ITEM_CLASS_VERSION))
5364      {
5365         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5366         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5367         else
5368           {
5369              itc->version = 0;
5370              free(itc);
5371           }
5372      }
5373 }
5374
5375 EAPI void
5376 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5377 {
5378    if (itc && (itc->version == ELM_GENLIST_ITEM_CLASS_VERSION))
5379      {
5380         itc->refcount++;
5381         if (itc->refcount == 0) itc->refcount--;
5382      }
5383 }
5384
5385 EAPI void
5386 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5387 {
5388    if (itc && (itc->version == ELM_GENLIST_ITEM_CLASS_VERSION))
5389      {
5390         if (itc->refcount > 0) itc->refcount--;
5391         if (itc->delete_me && (!itc->refcount))
5392           elm_genlist_item_class_free(itc);
5393      }
5394 }
5395
5396 /* for gengrid as of now */
5397 void
5398 _elm_genlist_page_relative_set(Evas_Object *obj,
5399                                double       h_pagerel,
5400                                double       v_pagerel)
5401 {
5402    Evas_Coord pagesize_h;
5403    Evas_Coord pagesize_v;
5404
5405    ELM_CHECK_WIDTYPE(obj, widtype);
5406    Widget_Data *wd = elm_widget_data_get(obj);
5407    if (!wd) return;
5408
5409    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5410    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5411                                  pagesize_v);
5412 }
5413
5414 /* for gengrid as of now */
5415 void
5416 _elm_genlist_page_relative_get(const Evas_Object *obj,
5417                                double            *h_pagerel,
5418                                double            *v_pagerel)
5419 {
5420    ELM_CHECK_WIDTYPE(obj, widtype);
5421    Widget_Data *wd = elm_widget_data_get(obj);
5422    if (!wd) return;
5423
5424    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5425 }
5426
5427 /* for gengrid as of now */
5428 void
5429 _elm_genlist_page_size_set(Evas_Object *obj,
5430                            Evas_Coord   h_pagesize,
5431                            Evas_Coord   v_pagesize)
5432 {
5433    double pagerel_h;
5434    double pagerel_v;
5435
5436    ELM_CHECK_WIDTYPE(obj, widtype);
5437    Widget_Data *wd = elm_widget_data_get(obj);
5438    if (!wd) return;
5439    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5440    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5441                                  v_pagesize);
5442 }
5443
5444 /* for gengrid as of now */
5445 void
5446 _elm_genlist_current_page_get(const Evas_Object *obj,
5447                               int               *h_pagenumber,
5448                               int               *v_pagenumber)
5449 {
5450    ELM_CHECK_WIDTYPE(obj, widtype);
5451    Widget_Data *wd = elm_widget_data_get(obj);
5452    if (!wd) return;
5453    if (wd->scr)
5454      elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5455 }
5456
5457 /* for gengrid as of now */
5458 void
5459 _elm_genlist_last_page_get(const Evas_Object *obj,
5460                            int               *h_pagenumber,
5461                            int               *v_pagenumber)
5462 {
5463    ELM_CHECK_WIDTYPE(obj, widtype);
5464    Widget_Data *wd = elm_widget_data_get(obj);
5465    if (!wd) return;
5466    if (wd->scr)
5467      elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5468 }
5469
5470 /* for gengrid as of now */
5471 void
5472 _elm_genlist_page_show(const Evas_Object *obj,
5473                        int                h_pagenumber,
5474                        int                v_pagenumber)
5475 {
5476    ELM_CHECK_WIDTYPE(obj, widtype);
5477    Widget_Data *wd = elm_widget_data_get(obj);
5478    if (!wd) return;
5479    if (wd->scr)
5480      elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5481 }
5482
5483 /* for gengrid as of now */
5484 void
5485 _elm_genlist_page_bring_in(const Evas_Object *obj,
5486                            int                h_pagenumber,
5487                            int                v_pagenumber)
5488 {
5489    ELM_CHECK_WIDTYPE(obj, widtype);
5490    Widget_Data *wd = elm_widget_data_get(obj);
5491    if (!wd) return;
5492    if (wd->scr)
5493      elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5494 }
5495
5496 void
5497 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5498                             Eina_Bool     calc)
5499 {
5500    Evas_Object *content;
5501
5502    if (!it->realized) return;
5503    if (it->wd->reorder_it == it) return;
5504    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5505    if (!calc)
5506      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5507    if (it->long_timer)
5508      {
5509         ecore_timer_del(it->long_timer);
5510         it->long_timer = NULL;
5511      }
5512
5513    elm_widget_stringlist_free(it->texts);
5514    it->texts = NULL;
5515    elm_widget_stringlist_free(it->contents);
5516    it->contents = NULL;
5517    elm_widget_stringlist_free(it->states);
5518    it->states = NULL;
5519
5520    EINA_LIST_FREE(it->content_objs, content)
5521      evas_object_del(content);
5522
5523    it->unrealize_cb(it);
5524
5525    it->realized = EINA_FALSE;
5526    it->want_unrealize = EINA_FALSE;
5527    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5528    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5529 }
5530
5531 void
5532 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5533 {
5534    elm_widget_item_pre_notify_del(it);
5535    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5536    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5537
5538    if (it->itc->func.del)
5539      it->itc->func.del((void *)it->base.data, WIDGET(it));
5540 }
5541
5542 void
5543 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5544 {
5545    _elm_genlist_item_del_notserious(it);
5546    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5547    if (it->tooltip.del_cb)
5548      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5549    it->wd->walking -= it->walking;
5550    if (it->long_timer) ecore_timer_del(it->long_timer);
5551    if (it->group)
5552      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5553
5554    if (it->wd->state)
5555      {
5556         eina_inlist_sorted_state_free(it->wd->state);
5557         it->wd->state = NULL;
5558      }
5559    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5560    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5561    free(it->item);
5562
5563    it->item = NULL;
5564    if (it->wd->last_selected_item == (Elm_Object_Item *) it)
5565      it->wd->last_selected_item = NULL;
5566    it->wd->item_count--;
5567 }