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