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