fix genlist item signals on prepend
[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_order_update(const Eina_Inlist *l, int start)
2201 {
2202    Elm_Gen_Item *it, *it2;
2203
2204    for (it = ELM_GEN_ITEM_FROM_INLIST(l); l; l = l->next, it = ELM_GEN_ITEM_FROM_INLIST(l))
2205      {
2206         it->item->order_num_in = start++;
2207         _elm_genlist_item_odd_even_update(it);
2208         it2 = ELM_GEN_ITEM_FROM_INLIST(l->next);
2209         if (it2 && (it->item->order_num_in != it2->item->order_num_in)) return;
2210      }
2211 }
2212
2213 static void
2214 _item_realize(Elm_Gen_Item *it,
2215               int           in,
2216               Eina_Bool     calc)
2217 {
2218    const char *treesize;
2219    char buf[1024];
2220    int tsize = 20;
2221    Item_Cache *itc = NULL;
2222
2223    if (it->generation < it->wd->generation) return;
2224    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
2225    if (it->realized)
2226      {
2227         if (it->item->order_num_in != in)
2228           {
2229              _item_order_update(EINA_INLIST_GET(it), in);
2230              _elm_genlist_item_state_update(it, NULL);
2231              _elm_genlist_item_index_update(it);
2232           }
2233         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2234         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2235         return;
2236      }
2237    it->item->order_num_in = in;
2238
2239    if ((it->item->nocache_once) && (!it->flipped))
2240      it->item->nocache_once = EINA_FALSE;
2241    else if (!it->item->nocache)
2242      itc = _item_cache_find(it);
2243    if (itc && (!it->wd->tree_effect_enabled))
2244      {
2245         VIEW(it) = itc->base_view;
2246         itc->base_view = NULL;
2247         it->spacer = itc->spacer;
2248         itc->spacer = NULL;
2249      }
2250    else
2251      {
2252         const char *stacking_even;
2253         const char *stacking;
2254
2255         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
2256         edje_object_scale_set(VIEW(it),
2257                               elm_widget_scale_get(WIDGET(it)) *
2258                               _elm_config->scale);
2259         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
2260         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
2261
2262         if (it->item->type & ELM_GENLIST_ITEM_TREE)
2263           snprintf(buf, sizeof(buf), "tree%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2264         else
2265           snprintf(buf, sizeof(buf), "item%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2266
2267         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
2268                               elm_widget_style_get(WIDGET(it)));
2269
2270         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
2271         if (!stacking_even) stacking_even = "above";
2272         it->item->stacking_even = !!strcmp("above", stacking_even);
2273
2274         stacking = edje_object_data_get(VIEW(it), "stacking");
2275         if (!stacking) stacking = "yes";
2276         it->item->nostacking = !!strcmp("yes", stacking);
2277
2278         edje_object_mirrored_set(VIEW(it),
2279                                  elm_widget_mirrored_get(WIDGET(it)));
2280      }
2281
2282    _item_order_update(EINA_INLIST_GET(it), in);
2283
2284    treesize = edje_object_data_get(VIEW(it), "treesize");
2285    if (treesize) tsize = atoi(treesize);
2286    if (!it->spacer && treesize)
2287      {
2288         it->spacer =
2289           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
2290         evas_object_color_set(it->spacer, 0, 0, 0, 0);
2291         elm_widget_sub_object_add(WIDGET(it), it->spacer);
2292      }
2293    if (it->spacer)
2294      {
2295         evas_object_size_hint_min_set(it->spacer,
2296                                       (it->item->expanded_depth * tsize) * _elm_config->scale, 1);
2297         edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
2298      }
2299    if (!calc)
2300      {
2301         edje_object_signal_callback_add(VIEW(it),
2302                                         "elm,action,expand,toggle",
2303                                         "elm", _signal_expand_toggle, it);
2304         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
2305                                         "elm", _signal_expand, it);
2306         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
2307                                         "elm", _signal_contract, it);
2308         _item_mouse_callbacks_add(it, VIEW(it));
2309
2310         if ((it->wd->decorate_all_mode) && (!it->deco_all_view) &&
2311             (it->item->type != ELM_GENLIST_ITEM_GROUP) && (it->itc->decorate_all_item_style))
2312           _decorate_all_item_realize(it, EINA_FALSE);
2313
2314         _elm_genlist_item_state_update(it, itc);
2315         _elm_genlist_item_index_update(it);
2316      }
2317
2318    if ((calc) && (it->wd->homogeneous) &&
2319        ((it->wd->item_width) ||
2320         ((it->wd->item_width) && (it->wd->group_item_width))))
2321      {
2322         /* homogenous genlist shortcut */
2323         if (!it->item->mincalcd)
2324           {
2325              if (it->group)
2326                {
2327                   it->item->w = it->item->minw = it->wd->group_item_width;
2328                   it->item->h = it->item->minh = it->wd->group_item_height;
2329                }
2330              else
2331                {
2332                   it->item->w = it->item->minw = it->wd->item_width;
2333                   it->item->h = it->item->minh = it->wd->item_height;
2334                }
2335              it->item->mincalcd = EINA_TRUE;
2336           }
2337      }
2338    else
2339      {
2340         /* FIXME: If you see that assert, please notify us and we
2341            will clean our mess */
2342         assert(eina_list_count(it->content_objs) == 0);
2343
2344         _item_text_realize(it, VIEW(it), &it->texts, NULL);
2345         it->content_objs = _item_content_realize(it, VIEW(it), &it->contents, NULL);
2346         _item_state_realize(it, VIEW(it), &it->states, NULL);
2347         if (it->flipped)
2348           {
2349              edje_object_signal_emit(VIEW(it), "elm,state,flip,enabled", "elm");
2350              if (!(it->item->flip_contents))
2351                it->item->flip_contents =
2352                   elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "flips"));
2353              it->item->flip_content_objs =
2354                _item_mode_content_realize(it, VIEW(it),
2355                                           &it->item->flip_contents, NULL,
2356                                           &it->item->flip_content_objs);
2357           }
2358
2359         if (!it->item->mincalcd || ((it->wd->mode == ELM_LIST_COMPRESS) && (it->item->w != it->item->minw)))
2360           {
2361              Evas_Coord mw = -1, mh = -1;
2362
2363              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2364                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2365              if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
2366              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
2367                                                   mh);
2368              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2369                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2370              it->item->w = it->item->minw = mw;
2371              it->item->h = it->item->minh = mh;
2372              it->item->mincalcd = EINA_TRUE;
2373
2374              if ((!it->wd->group_item_width) && (it->group))
2375                {
2376                   it->wd->group_item_width = mw;
2377                   it->wd->group_item_height = mh;
2378                }
2379              else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
2380                {
2381                   it->wd->item_width = mw;
2382                   it->wd->item_height = mh;
2383                }
2384           }
2385         if (!calc) evas_object_show(VIEW(it));
2386      }
2387
2388    if (it->tooltip.content_cb)
2389      {
2390         elm_widget_item_tooltip_content_cb_set(it,
2391                                                it->tooltip.content_cb,
2392                                                it->tooltip.data, NULL);
2393         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
2394         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
2395      }
2396
2397    if (it->mouse_cursor)
2398      elm_widget_item_cursor_set(it, it->mouse_cursor);
2399
2400    it->realized = EINA_TRUE;
2401    it->want_unrealize = EINA_FALSE;
2402
2403    if (itc) _item_cache_free(itc);
2404    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2405    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2406    if (!calc)
2407      {
2408         if (it->item->tree_effect_hideme)
2409           {
2410              if (it->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE)
2411                edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
2412              it->item->tree_effect_hideme = EINA_FALSE;
2413           }
2414         evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
2415      }
2416
2417    if ((!calc) && (it->wd->decorate_all_mode) && (it->item->type != ELM_GENLIST_ITEM_GROUP))
2418      {
2419         if (it->itc->decorate_all_item_style)
2420           {
2421              if (!it->deco_all_view) _decorate_all_item_realize(it, EINA_FALSE);
2422              edje_object_message_signal_process(it->deco_all_view);
2423           }
2424      }
2425    edje_object_message_signal_process(VIEW(it));
2426 }
2427
2428 static void
2429 _item_unrealize_cb(Elm_Gen_Item *it)
2430 {
2431    Evas_Object *content;
2432    elm_widget_stringlist_free(it->item->flip_contents);
2433    it->item->flip_contents = NULL;
2434    EINA_LIST_FREE(it->item->flip_content_objs, content)
2435      evas_object_del(content);
2436
2437    if (it->item->nocache_once || it->item->nocache)
2438      {
2439         evas_object_del(VIEW(it));
2440         VIEW(it) = NULL;
2441         if (it->spacer)
2442           {
2443              evas_object_del(it->spacer);
2444              it->spacer = NULL;
2445           }
2446      }
2447    else
2448      {
2449         edje_object_mirrored_set(VIEW(it),
2450                                  elm_widget_mirrored_get(WIDGET(it)));
2451         edje_object_scale_set(VIEW(it),
2452                               elm_widget_scale_get(WIDGET(it))
2453                               * _elm_config->scale);
2454         _item_cache_add(it);
2455      }
2456
2457    _decorate_item_unrealize(it);
2458    it->states = NULL;
2459    it->realized = EINA_FALSE;
2460    it->want_unrealize = EINA_FALSE;
2461    if (it->wd->decorate_all_mode) _decorate_all_item_unrealize(it);
2462 }
2463
2464 static Eina_Bool
2465 _item_block_recalc(Item_Block *itb,
2466                    int         in,
2467                    Eina_Bool   qadd)
2468 {
2469    const Eina_List *l;
2470    Elm_Gen_Item *it;
2471    Evas_Coord minw = 0, minh = 0;
2472    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
2473    Evas_Coord y = 0;
2474
2475    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2476    itb->num = in;
2477    EINA_LIST_FOREACH(itb->items, l, it)
2478      {
2479         if (it->generation < it->wd->generation) continue;
2480         showme |= it->item->showme;
2481         if (!itb->realized)
2482           {
2483              if (qadd)
2484                {
2485                   if (!it->item->mincalcd) changed = EINA_TRUE;
2486                   if (changed)
2487                     {
2488                        _item_realize(it, in, EINA_TRUE);
2489                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2490                     }
2491                }
2492              else
2493                {
2494                   if ((itb->wd->homogeneous) &&
2495                       (itb->wd->mode == ELM_LIST_COMPRESS))
2496                     {
2497                        if (it->group)
2498                          {
2499                             it->item->w = it->item->minw = it->wd->group_item_width;
2500                             it->item->h = it->item->minh = it->wd->group_item_height;
2501                          }
2502                        else
2503                          {
2504                             it->item->w = it->item->minw = it->wd->item_width;
2505                             it->item->h = it->item->minh = it->wd->item_height;
2506                          }
2507                     }
2508                   else
2509                     {
2510                        _item_realize(it, in, EINA_TRUE);
2511                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2512                     }
2513                }
2514           }
2515         else
2516           {
2517              if (!it->item->mincalcd) changed = EINA_TRUE;
2518              _item_realize(it, in, EINA_FALSE);
2519           }
2520         minh += it->item->minh;
2521         if (minw < it->item->minw) minw = it->item->minw;
2522         in++;
2523         it->x = 0;
2524         it->y = y;
2525         y += it->item->h;
2526      }
2527    if (changed) itb->wd->pan_changed = changed;
2528    itb->minw = minw;
2529    itb->minh = minh;
2530    itb->changed = EINA_FALSE;
2531    itb->position_update = EINA_FALSE;
2532    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2533    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2534    return showme;
2535 }
2536
2537 static void
2538 _item_block_realize(Item_Block *itb)
2539 {
2540    if (itb->realized) return;
2541    itb->realized = EINA_TRUE;
2542    itb->want_unrealize = EINA_FALSE;
2543 }
2544
2545 static void
2546 _item_block_unrealize(Item_Block *itb)
2547 {
2548    const Eina_List *l;
2549    Elm_Gen_Item *it;
2550    Eina_Bool dragging = EINA_FALSE;
2551
2552    if (!itb->realized) return;
2553    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2554    EINA_LIST_FOREACH(itb->items, l, it)
2555      {
2556         if (itb->must_recalc || !it->group)
2557           {
2558              if (it->dragging)
2559                {
2560                   dragging = EINA_TRUE;
2561                   it->want_unrealize = EINA_TRUE;
2562                }
2563              else
2564                _elm_genlist_item_unrealize(it, EINA_FALSE);
2565           }
2566      }
2567    if (!dragging)
2568      {
2569         itb->realized = EINA_FALSE;
2570         itb->want_unrealize = EINA_TRUE;
2571      }
2572    else
2573      itb->want_unrealize = EINA_FALSE;
2574    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2575    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2576 }
2577
2578 static int
2579 _get_space_for_reorder_item(Elm_Gen_Item *it)
2580 {
2581    Evas_Coord rox, roy, row, roh, oy, oh;
2582    Eina_Bool top = EINA_FALSE;
2583    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2584    if (!reorder_it) return 0;
2585
2586    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2587    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2588
2589    if ((it->wd->reorder_start_y < it->item->block->y) &&
2590        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2591      {
2592         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2593         if (it->item->block->count == 1)
2594           it->wd->reorder_rel = it;
2595      }
2596    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2597             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2598      {
2599         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2600      }
2601    else
2602      it->item->block->reorder_offset = 0;
2603
2604    it->item->scrl_y += it->item->block->reorder_offset;
2605
2606    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2607                               rox, roy + (roh / 2), row, 1));
2608    if (top)
2609      {
2610         it->wd->reorder_rel = it;
2611         it->item->scrl_y += it->wd->reorder_it->item->h;
2612         return it->wd->reorder_it->item->h;
2613      }
2614    else
2615      return 0;
2616 }
2617
2618 static Eina_Bool
2619 _reorder_move_animator_cb(void *data)
2620 {
2621    Elm_Gen_Item *it = data;
2622    Eina_Bool down = EINA_FALSE;
2623    double t;
2624    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2625
2626    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2627
2628    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2629    else y = dy;
2630
2631    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2632    if (diff > it->item->h) y = diff / 2;
2633
2634    if (it->item->old_scrl_y < it->item->scrl_y)
2635      {
2636         it->item->old_scrl_y += y;
2637         down = EINA_TRUE;
2638      }
2639    else if (it->item->old_scrl_y > it->item->scrl_y)
2640      {
2641         it->item->old_scrl_y -= y;
2642         down = EINA_FALSE;
2643      }
2644
2645    if (it->deco_all_view)
2646      _item_position(it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
2647    else
2648      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2649 //FIXME : group raise
2650 #if 0
2651    _group_items_recalc(it->wd);
2652 #endif
2653
2654    if ((it->wd->reorder_pan_move) ||
2655        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2656        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2657      {
2658         it->item->old_scrl_y = it->item->scrl_y;
2659         it->item->move_effect_enabled = EINA_FALSE;
2660         it->wd->reorder_move_animator = NULL;
2661         return ECORE_CALLBACK_CANCEL;
2662      }
2663    return ECORE_CALLBACK_RENEW;
2664 }
2665
2666 static void
2667 _item_position(Elm_Gen_Item *it,
2668                Evas_Object  *view,
2669                Evas_Coord    it_x,
2670                Evas_Coord    it_y)
2671 {
2672    if (!it) return;
2673    if (!view) return;
2674
2675    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2676    evas_object_resize(view, it->item->w, it->item->h);
2677    evas_object_move(view, it_x, it_y);
2678    evas_object_show(view);
2679    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2680    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2681 }
2682
2683 static void
2684 _item_block_position(Item_Block *itb,
2685                      int         in)
2686 {
2687    const Eina_List *l;
2688    Elm_Gen_Item *it;
2689 //FIXME : group raise
2690 #if 0
2691    Elm_Gen_Item *git;
2692 #endif
2693    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2694    Eina_Bool vis = EINA_FALSE;
2695    Evas_Coord minh = 0;
2696
2697    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2698    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2699    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2700                             &cvw, &cvh);
2701    EINA_LIST_FOREACH(itb->items, l, it)
2702      {
2703         if (it->generation < it->wd->generation) continue;
2704         else if (it->wd->reorder_it == it) continue;
2705         it->x = 0;
2706         it->y = y;
2707         it->item->w = itb->w;
2708         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2709         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2710
2711         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2712                                    cvx, cvy, cvw, cvh));
2713 //FIXME : group raise
2714 #if 0
2715         if (!it->group)
2716 #endif
2717           {
2718              if ((itb->realized) && (!it->realized))
2719                {
2720                   if (vis) _item_realize(it, in, EINA_FALSE);
2721                }
2722              if (it->realized)
2723                {
2724                   if (vis || it->dragging)
2725                     {
2726                        if (it->wd->reorder_mode)
2727                          y += _get_space_for_reorder_item(it);
2728 //FIXME : group raise
2729 #if 0
2730                        git = it->item->group_item;
2731                        if (git)
2732                          {
2733                             if (git->item->scrl_y < oy)
2734                               git->item->scrl_y = oy;
2735                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2736                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2737                             git->item->want_realize = EINA_TRUE;
2738                          }
2739 #endif
2740                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2741                          {
2742                             if (!it->item->move_effect_enabled)
2743                               {
2744                                  it->item->move_effect_enabled = EINA_TRUE;
2745                                  it->wd->reorder_move_animator =
2746                                     ecore_animator_add(
2747                                        _reorder_move_animator_cb, it);
2748                               }
2749                          }
2750                        if (!it->item->move_effect_enabled)
2751                          {
2752                             if ((it->wd->decorate_all_mode) && (it->itc->decorate_all_item_style))
2753                               _decorate_all_item_position(it, it->item->scrl_x,
2754                                                        it->item->scrl_y);
2755                             else
2756                               {
2757                                  if (!it->wd->tree_effect_enabled ||
2758                                      (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE) ||
2759                                      ((it->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE) &&
2760                                      (it->item->old_scrl_y == it->item->scrl_y)))
2761                                    {
2762                                       if (it->item->deco_it_view)
2763                                         _item_position(it, it->item->deco_it_view,
2764                                                        it->item->scrl_x,
2765                                                        it->item->scrl_y);
2766                                       else
2767                                         _item_position(it, VIEW(it), it->item->scrl_x,
2768                                                        it->item->scrl_y);
2769                                    }
2770                               }
2771                             it->item->old_scrl_y = it->item->scrl_y;
2772                          }
2773                     }
2774                   else
2775                     {
2776                        if (!it->wd->tree_effect_animator)
2777                          {
2778                             it->want_unrealize = EINA_TRUE;
2779                             _elm_genlist_item_unrealize(it, EINA_FALSE);
2780                          }
2781                     }
2782                }
2783              in++;
2784           }
2785 //FIXME : group raise
2786 #if 0
2787         else
2788           {
2789              if (vis) it->item->want_realize = EINA_TRUE;
2790           }
2791 #endif
2792         y += it->item->h;
2793         minh += it->item->minh;
2794      }
2795    if (!itb->wd->reorder_it) itb->minh = minh;
2796    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2797    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2798 }
2799
2800 //FIXME: group raise
2801 #if 0
2802 static void
2803 _group_items_recalc(void *data)
2804 {
2805    Widget_Data *wd = data;
2806    Eina_List *l;
2807    Elm_Gen_Item *git;
2808
2809    evas_event_freeze(evas_object_evas_get(wd->obj));
2810    EINA_LIST_FOREACH(wd->group_items, l, git)
2811      {
2812         if (git->item->want_realize)
2813           {
2814              if (!git->realized)
2815                _item_realize(git, 0, EINA_FALSE);
2816              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2817              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2818              evas_object_show(VIEW(git));
2819              evas_object_raise(VIEW(git));
2820           }
2821         else if (!git->item->want_realize && git->realized)
2822           {
2823              if (!git->dragging)
2824                _elm_genlist_item_unrealize(git, EINA_FALSE);
2825           }
2826      }
2827    evas_event_thaw(evas_object_evas_get(wd->obj));
2828    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2829 }
2830 #endif
2831
2832 static void
2833 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2834 {
2835    Elm_Gen_Item *it = data;
2836    if (!it) return;
2837    if (it->want_unrealize) return;
2838    it->item->mincalcd = EINA_FALSE;
2839    it->item->block->changeme = EINA_TRUE;
2840    if (it->wd->changed_job) ecore_job_del(it->wd->changed_job);
2841    it->wd->changed_job = ecore_job_add(_changed_job, it->wd);
2842 }
2843
2844 static Eina_Bool
2845 _must_recalc_idler(void *data)
2846 {
2847    Widget_Data *wd = data;
2848    if (wd->calc_job) ecore_job_del(wd->calc_job);
2849    wd->calc_job = ecore_job_add(_calc_job, wd);
2850    wd->must_recalc_idler = NULL;
2851    return ECORE_CALLBACK_CANCEL;
2852 }
2853
2854 static void
2855 _scroll_item(Widget_Data *wd)
2856 {
2857    Elm_Gen_Item *it = NULL;
2858 //FIXME: group raise
2859 #if 0
2860    Evas_Coord gith = 0;
2861 #endif
2862    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
2863    if (!wd->show_item) return;
2864
2865    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
2866    it = wd->show_item;
2867    dx = it->x + it->item->block->x;
2868    dy = it->y + it->item->block->y;
2869    dw = it->item->block->w;
2870    dh = oh;
2871    switch (wd->scrollto_type)
2872      {
2873       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2874 //FIXME: group raise
2875 #if 0
2876          if (it->item->group_item) gith = it->item->group_item->item->h;
2877          dy -= gith;
2878 #endif
2879          break;
2880       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2881          dy += ((it->item->h / 2) - (oh / 2));
2882          break;
2883       case ELM_GENLIST_ITEM_SCROLLTO_IN:
2884       default:
2885          if ((wd->expanded_item) &&
2886              ((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
2887               - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
2888            {
2889               it = wd->expanded_item;
2890               dx = it->x + it->item->block->x;
2891               dy = it->y + it->item->block->y;
2892 //FIXME: group raise
2893 #if 0
2894               if (it->item->group_item) gith = it->item->group_item->item->h;
2895               dx = it->x + it->item->block->x;
2896               dy = it->y + it->item->block->y - gith;
2897 #endif
2898               dw = it->item->block->w;
2899            }
2900          else
2901            {
2902 //FIXME: group raise
2903 #if 0
2904               if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
2905                 gith = it->item->group_item->item->h;
2906               dy -= gith;
2907 #endif
2908               dh = it->item->h;
2909            }
2910          break;
2911      }
2912    if (wd->bring_in)
2913      elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
2914    else
2915      elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
2916
2917    it->item->showme = EINA_FALSE;
2918    wd->show_item = NULL;
2919    wd->auto_scroll_enabled = EINA_FALSE;
2920    wd->check_scroll = EINA_FALSE;
2921 }
2922
2923 static void
2924 _calc_job(void *data)
2925 {
2926    Widget_Data *wd = data;
2927    Item_Block *itb, *chb = NULL;
2928    Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw;
2929    Evas_Coord pan_w = 0, pan_h = 0;
2930    int in = 0;
2931    Eina_Bool minw_change = EINA_FALSE;
2932    Eina_Bool did_must_recalc = EINA_FALSE;
2933    if (!wd) return;
2934
2935    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2936    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2937
2938    if (wd->w != ow)
2939      wd->w = ow;
2940
2941    evas_event_freeze(evas_object_evas_get(wd->obj));
2942    EINA_INLIST_FOREACH(wd->blocks, itb)
2943      {
2944         Eina_Bool showme = EINA_FALSE;
2945
2946         itb->num = in;
2947         showme = itb->showme;
2948         itb->showme = EINA_FALSE;
2949         if (chb)
2950           {
2951              if (itb->realized) _item_block_unrealize(itb);
2952           }
2953         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2954           {
2955              if (itb->must_recalc)
2956                {
2957                   Eina_List *l;
2958                   Elm_Gen_Item *it;
2959                   EINA_LIST_FOREACH(itb->items, l, it)
2960                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2961                   itb->changed = EINA_TRUE;
2962                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2963                   if (itb->realized) _item_block_unrealize(itb);
2964                   itb->must_recalc = EINA_FALSE;
2965                }
2966              showme = _item_block_recalc(itb, in, EINA_FALSE);
2967              chb = itb;
2968           }
2969         itb->y = y;
2970         itb->x = 0;
2971         minh += itb->minh;
2972         if (minw == -1) minw = itb->minw;
2973         else if ((!itb->must_recalc) && (minw < itb->minw))
2974           {
2975              minw = itb->minw;
2976              minw_change = EINA_TRUE;
2977           }
2978         if (minw > vw)
2979           {
2980              minw = vw;
2981              minw_change = EINA_TRUE;
2982           }
2983         itb->w = minw;
2984         itb->h = itb->minh;
2985         y += itb->h;
2986         in += itb->count;
2987         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2988           wd->check_scroll = EINA_TRUE;
2989      }
2990    if (minw_change)
2991      {
2992         EINA_INLIST_FOREACH(wd->blocks, itb)
2993           {
2994              itb->minw = minw;
2995              itb->w = itb->minw;
2996           }
2997      }
2998    if ((chb) && (EINA_INLIST_GET(chb)->next))
2999      {
3000         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
3001           {
3002              if (itb->realized) _item_block_unrealize(itb);
3003           }
3004      }
3005    wd->realminw = minw;
3006    if (minw < wd->w) minw = wd->w;
3007    if ((minw != wd->minw) || (minh != wd->minh))
3008      {
3009         wd->minw = minw;
3010         wd->minh = minh;
3011         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
3012         _sizing_eval(wd->obj);
3013         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
3014           {
3015              Elm_Gen_Item *it;
3016              Evas_Coord it_y;
3017
3018              it = wd->anchor_item;
3019              it_y = wd->anchor_y;
3020              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
3021                                               it->item->block->y + it->y + it_y);
3022              wd->anchor_item = it;
3023              wd->anchor_y = it_y;
3024           }
3025      }
3026    if (did_must_recalc)
3027      {
3028         if (!wd->must_recalc_idler)
3029           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
3030      }
3031    if (wd->check_scroll)
3032      {
3033         _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
3034         if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
3035           wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3036        switch (wd->scrollto_type)
3037           {
3038            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
3039               dy = wd->h;
3040               break;
3041            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
3042               dy = wd->h / 2;
3043               break;
3044            case ELM_GENLIST_ITEM_SCROLLTO_IN:
3045            default:
3046               dy = 0;
3047               break;
3048           }
3049         if ((wd->show_item) && (wd->show_item->item->block))
3050           {
3051              if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
3052                  (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
3053                {
3054                   _scroll_item(wd);
3055                }
3056           }
3057      }
3058    wd->calc_job = NULL;
3059    evas_object_smart_changed(wd->pan_smart);
3060    evas_event_thaw(evas_object_evas_get(wd->obj));
3061    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3062 }
3063
3064 static void
3065 _update_job(void *data)
3066 {
3067    Widget_Data *wd = data;
3068    Eina_List *l2;
3069    Item_Block *itb;
3070    int num, num0;
3071    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
3072    if (!wd) return;
3073    wd->update_job = NULL;
3074    num = 0;
3075
3076    evas_event_freeze(evas_object_evas_get(wd->obj));
3077    EINA_INLIST_FOREACH(wd->blocks, itb)
3078      {
3079         Evas_Coord itminw, itminh;
3080         Elm_Gen_Item *it;
3081
3082         if (!itb->updateme)
3083           {
3084              num += itb->count;
3085              if (position)
3086                _item_block_position(itb, num);
3087              continue;
3088           }
3089         num0 = num;
3090         recalc = EINA_FALSE;
3091         EINA_LIST_FOREACH(itb->items, l2, it)
3092           {
3093              if (it->item->updateme)
3094                {
3095                   itminw = it->item->minw;
3096                   itminh = it->item->minh;
3097
3098                   if (it->realized)
3099                     {
3100                        _elm_genlist_item_unrealize(it, EINA_FALSE);
3101                        _item_realize(it, num, EINA_FALSE);
3102                        position = EINA_TRUE;
3103                     }
3104                   else
3105                     {
3106                        _item_realize(it, num, EINA_TRUE);
3107                        _elm_genlist_item_unrealize(it, EINA_TRUE);
3108                     }
3109                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
3110                     recalc = EINA_TRUE;
3111                   it->item->updateme = EINA_FALSE;
3112                }
3113              num++;
3114           }
3115         itb->updateme = EINA_FALSE;
3116         if (recalc)
3117           {
3118              position = EINA_TRUE;
3119              itb->changed = EINA_TRUE;
3120              _item_block_recalc(itb, num0, EINA_FALSE);
3121              _item_block_position(itb, num0);
3122           }
3123      }
3124    if (position)
3125      {
3126         if (wd->calc_job) ecore_job_del(wd->calc_job);
3127         wd->calc_job = ecore_job_add(_calc_job, wd);
3128      }
3129    evas_event_thaw(evas_object_evas_get(wd->obj));
3130    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3131 }
3132
3133 static void
3134 _changed_job(void *data)
3135 {
3136    Widget_Data *wd = data; Eina_List *l2;
3137    Item_Block *itb;
3138    int num, num0, position = 0;
3139    Eina_Bool width_changed = EINA_FALSE, height_changed = EINA_FALSE;
3140    if (!wd) return;
3141    wd->changed_job = NULL;
3142    num = 0;
3143    EINA_INLIST_FOREACH(wd->blocks, itb)
3144      {
3145         Evas_Coord itminw, itminh;
3146         Elm_Gen_Item *it;
3147
3148         if (!itb->changeme)
3149           {
3150              num += itb->count;
3151              if (position)
3152                _item_block_position(itb, num);
3153              continue;
3154           }
3155         num0 = num;
3156         width_changed = height_changed = EINA_FALSE;
3157         EINA_LIST_FOREACH(itb->items, l2, it)
3158           {
3159              if ((!it->item->mincalcd) && (it->realized))
3160                {
3161                   Evas_Coord mw = -1, mh = -1;
3162                   itminw = it->item->minw;
3163                   itminh = it->item->minh;
3164
3165                   if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->w;
3166                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3167                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
3168                   if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
3169                   edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
3170                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3171                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
3172                   if (mw > itb->w)
3173                     width_changed = EINA_TRUE;
3174                   else
3175                     mw = itb->w;
3176                   it->item->w = it->item->minw = mw;
3177                   it->item->h = it->item->minh = mh;
3178                   it->item->mincalcd = EINA_TRUE;
3179
3180                   //if ((it->item->minw != itminw) || (it->item->minh != itminh))
3181                   //if ((it->item->minh != itminh))
3182                   //  recalc = 1;
3183                   if ((it->item->minw != itminw))
3184                     width_changed = EINA_TRUE;
3185                   if ((it->item->minh != itminh))
3186                     height_changed = EINA_TRUE;
3187
3188                   if ((!it->wd->group_item_width) && (it->group))
3189                     {
3190                        it->wd->group_item_width = mw;
3191                        it->wd->group_item_height = mh;
3192                     }
3193                   else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
3194                     {
3195                        it->wd->item_width = mw;
3196                        it->wd->item_height = mh;
3197                     }
3198                }
3199              num++;
3200           }
3201         itb->changeme = EINA_FALSE;
3202         // TODO: why this is separated.
3203         if (height_changed)
3204           {
3205              position = 1;
3206              itb->changed = EINA_TRUE;
3207              _item_block_recalc(itb, num0, 0);
3208              _item_block_position(itb, num0);
3209           }
3210         else if (width_changed)
3211           {
3212              _item_block_position(itb, num0);
3213           }
3214      }
3215    if (position)
3216      {
3217         if (wd->calc_job) ecore_job_del(wd->calc_job);
3218         wd->calc_job = ecore_job_add(_calc_job, wd);
3219      }
3220 }
3221
3222 static void
3223 _pan_set(Evas_Object *obj,
3224          Evas_Coord   x,
3225          Evas_Coord   y)
3226 {
3227    Pan *sd = evas_object_smart_data_get(obj);
3228    Item_Block *itb;
3229
3230    if (!sd) return;
3231    //   Evas_Coord ow, oh;
3232    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3233    //   ow = sd->wd->minw - ow;
3234    //   if (ow < 0) ow = 0;
3235    //   oh = sd->wd->minh - oh;
3236    //   if (oh < 0) oh = 0;
3237    //   if (x < 0) x = 0;
3238    //   if (y < 0) y = 0;
3239    //   if (x > ow) x = ow;
3240    //   if (y > oh) y = oh;
3241    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
3242    sd->wd->pan_x = x;
3243    sd->wd->pan_y = y;
3244
3245    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3246      {
3247         if ((itb->y + itb->h) > y)
3248           {
3249              Elm_Gen_Item *it;
3250              Eina_List *l2;
3251
3252              EINA_LIST_FOREACH(itb->items, l2, it)
3253                {
3254                   if ((itb->y + it->y) >= y)
3255                     {
3256                        sd->wd->anchor_item = it;
3257                        sd->wd->anchor_y = -(itb->y + it->y - y);
3258                        goto done;
3259                     }
3260                }
3261           }
3262      }
3263 done:
3264    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
3265 }
3266
3267 static void
3268 _pan_get(Evas_Object *obj,
3269          Evas_Coord  *x,
3270          Evas_Coord  *y)
3271 {
3272    Pan *sd = evas_object_smart_data_get(obj);
3273
3274    if (!sd) return;
3275    if (x) *x = sd->wd->pan_x;
3276    if (y) *y = sd->wd->pan_y;
3277 }
3278
3279 static void
3280 _pan_max_get(Evas_Object *obj,
3281              Evas_Coord  *x,
3282              Evas_Coord  *y)
3283 {
3284    Pan *sd = evas_object_smart_data_get(obj);
3285    Evas_Coord ow, oh;
3286
3287    if (!sd) return;
3288    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3289    ow = sd->wd->minw - ow;
3290    if (ow < 0) ow = 0;
3291    oh = sd->wd->minh - oh;
3292    if (oh < 0) oh = 0;
3293    if (x) *x = ow;
3294    if (y) *y = oh;
3295 }
3296
3297 static void
3298 _pan_min_get(Evas_Object *obj __UNUSED__,
3299              Evas_Coord  *x,
3300              Evas_Coord  *y)
3301 {
3302    if (x) *x = 0;
3303    if (y) *y = 0;
3304 }
3305
3306 static void
3307 _pan_child_size_get(Evas_Object *obj,
3308                     Evas_Coord  *w,
3309                     Evas_Coord  *h)
3310 {
3311    Pan *sd = evas_object_smart_data_get(obj);
3312
3313    if (!sd) return;
3314    if (w) *w = sd->wd->minw;
3315    if (h) *h = sd->wd->minh;
3316 }
3317
3318 static void
3319 _pan_add(Evas_Object *obj)
3320 {
3321    Pan *sd;
3322    Evas_Object_Smart_Clipped_Data *cd;
3323
3324    _pan_sc.add(obj);
3325    cd = evas_object_smart_data_get(obj);
3326    sd = ELM_NEW(Pan);
3327    if (!sd) return;
3328    sd->__clipped_data = *cd;
3329    free(cd);
3330    evas_object_smart_data_set(obj, sd);
3331 }
3332
3333 static void
3334 _pan_del(Evas_Object *obj)
3335 {
3336    Pan *sd = evas_object_smart_data_get(obj);
3337
3338    if (!sd) return;
3339    if (sd->resize_job)
3340      {
3341         ecore_job_del(sd->resize_job);
3342         sd->resize_job = NULL;
3343      }
3344    _pan_sc.del(obj);
3345 }
3346
3347 static void
3348 _pan_resize_job(void *data)
3349 {
3350    Pan *sd = data;
3351    if (!sd) return;
3352    _sizing_eval(sd->wd->obj);
3353    sd->resize_job = NULL;
3354 }
3355
3356 static void
3357 _pan_resize(Evas_Object *obj,
3358             Evas_Coord   w,
3359             Evas_Coord   h)
3360 {
3361    Pan *sd = evas_object_smart_data_get(obj);
3362    Evas_Coord ow, oh;
3363
3364    if (!sd) return;
3365    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3366    if ((ow == w) && (oh == h)) return;
3367    if ((sd->wd->mode == ELM_LIST_COMPRESS) && (ow != w))
3368      {
3369         /* fix me later */
3370         if (sd->resize_job) ecore_job_del(sd->resize_job);
3371         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
3372      }
3373    sd->wd->pan_changed = EINA_TRUE;
3374    evas_object_smart_changed(obj);
3375    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3376    sd->wd->calc_job = NULL;
3377 }
3378
3379 static void
3380 _pan_calculate(Evas_Object *obj)
3381 {
3382    Pan *sd = evas_object_smart_data_get(obj);
3383    Item_Block *itb;
3384    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
3385    int in = 0;
3386 //FIXME: group raise
3387 #if 0
3388    Elm_Gen_Item *git;
3389    Eina_List *l;
3390 #endif
3391
3392    if (!sd) return;
3393    evas_event_freeze(evas_object_evas_get(obj));
3394
3395    if (sd->wd->pan_changed)
3396      {
3397         _calc_job(sd->wd);
3398         sd->wd->pan_changed = EINA_FALSE;
3399      }
3400
3401    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3402    sd->wd->prev_viewport_w = ow;
3403    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
3404 //FIXME: group raise
3405 #if 0
3406    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
3407      {
3408         git->item->want_realize = EINA_FALSE;
3409      }
3410 #endif
3411
3412    if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
3413      {
3414         if (!sd->wd->tree_effect_animator)
3415           {
3416              _item_tree_effect_before(sd->wd->expanded_item);
3417              evas_object_raise(sd->wd->alpha_bg);
3418              evas_object_show(sd->wd->alpha_bg);
3419              sd->wd->start_time = ecore_time_get();
3420              sd->wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, sd->wd);
3421           }
3422      }
3423
3424    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3425      {
3426         itb->w = sd->wd->minw;
3427         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3428                                 itb->y - sd->wd->pan_y + oy,
3429                                 itb->w, itb->h,
3430                                 cvx, cvy, cvw, cvh))
3431           {
3432              if ((!itb->realized) || (itb->changed))
3433                {
3434                   _item_block_realize(itb);
3435
3436                   if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3437                   sd->wd->calc_job = NULL;
3438                   _calc_job(sd->wd);
3439                }
3440              _item_block_position(itb, in);
3441           }
3442         else
3443           {
3444              if (itb->realized) _item_block_unrealize(itb);
3445           }
3446         in += itb->count;
3447      }
3448 //FIXME: group raise
3449 #if 0
3450    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
3451       _group_items_recalc(sd->wd);
3452 #endif
3453    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3454      {
3455         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
3456            sd->wd->reorder_pan_move = EINA_TRUE;
3457         else sd->wd->reorder_pan_move = EINA_FALSE;
3458         evas_object_raise(sd->wd->VIEW(reorder_it));
3459         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
3460         sd->wd->start_time = ecore_loop_time_get();
3461      }
3462
3463    if (!sd->wd->tree_effect_enabled || (sd->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE))
3464      _item_auto_scroll(sd->wd);
3465
3466    evas_event_thaw(evas_object_evas_get(obj));
3467    evas_event_thaw_eval(evas_object_evas_get(obj));
3468 }
3469
3470 static void
3471 _pan_move(Evas_Object *obj,
3472           Evas_Coord   x __UNUSED__,
3473           Evas_Coord   y __UNUSED__)
3474 {
3475    Pan *sd = evas_object_smart_data_get(obj);
3476
3477    if (!sd) return;
3478
3479    sd->wd->pan_changed = EINA_TRUE;
3480    evas_object_smart_changed(obj);
3481    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3482    sd->wd->calc_job = NULL;
3483 }
3484
3485 static void
3486 _hold_on(void        *data __UNUSED__,
3487          Evas_Object *obj,
3488          void        *event_info __UNUSED__)
3489 {
3490    Widget_Data *wd = elm_widget_data_get(obj);
3491    if (!wd) return;
3492    elm_smart_scroller_hold_set(wd->scr, 1);
3493 }
3494
3495 static void
3496 _hold_off(void        *data __UNUSED__,
3497           Evas_Object *obj,
3498           void        *event_info __UNUSED__)
3499 {
3500    Widget_Data *wd = elm_widget_data_get(obj);
3501    if (!wd) return;
3502    elm_smart_scroller_hold_set(wd->scr, 0);
3503 }
3504
3505 static void
3506 _freeze_on(void        *data __UNUSED__,
3507            Evas_Object *obj,
3508            void        *event_info __UNUSED__)
3509 {
3510    Widget_Data *wd = elm_widget_data_get(obj);
3511    if (!wd) return;
3512    elm_smart_scroller_freeze_set(wd->scr, 1);
3513 }
3514
3515 static void
3516 _freeze_off(void        *data __UNUSED__,
3517             Evas_Object *obj,
3518             void        *event_info __UNUSED__)
3519 {
3520    Widget_Data *wd = elm_widget_data_get(obj);
3521    if (!wd) return;
3522    elm_smart_scroller_freeze_set(wd->scr, 0);
3523 }
3524
3525 static void
3526 _scr_anim_start(void        *data,
3527                 Evas_Object *obj __UNUSED__,
3528                 void        *event_info __UNUSED__)
3529 {
3530    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3531 }
3532
3533 static void
3534 _scr_anim_stop(void        *data,
3535                Evas_Object *obj __UNUSED__,
3536                void        *event_info __UNUSED__)
3537 {
3538    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3539 }
3540
3541 static void
3542 _scr_drag_start(void        *data,
3543                 Evas_Object *obj __UNUSED__,
3544                 void        *event_info __UNUSED__)
3545 {
3546    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3547 }
3548
3549 static void
3550 _scr_drag_stop(void        *data,
3551                Evas_Object *obj __UNUSED__,
3552                void        *event_info __UNUSED__)
3553 {
3554    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3555 }
3556
3557 static void
3558 _edge_left(void        *data,
3559            Evas_Object *scr __UNUSED__,
3560            void        *event_info __UNUSED__)
3561 {
3562    Evas_Object *obj = data;
3563    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3564 }
3565
3566 static void
3567 _edge_right(void        *data,
3568             Evas_Object *scr __UNUSED__,
3569             void        *event_info __UNUSED__)
3570 {
3571    Evas_Object *obj = data;
3572    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3573 }
3574
3575 static void
3576 _edge_top(void        *data,
3577           Evas_Object *scr __UNUSED__,
3578           void        *event_info __UNUSED__)
3579 {
3580    Evas_Object *obj = data;
3581    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3582 }
3583
3584 static void
3585 _edge_bottom(void        *data,
3586              Evas_Object *scr __UNUSED__,
3587              void        *event_info __UNUSED__)
3588 {
3589    Evas_Object *obj = data;
3590    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3591 }
3592
3593 static void
3594 _decorate_item_realize(Elm_Gen_Item *it)
3595 {
3596    char buf[1024];
3597
3598    if ((it->item->deco_it_view) || (it->generation < it->wd->generation)) return;
3599
3600    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3601    it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3602    edje_object_scale_set(it->item->deco_it_view,
3603                          elm_widget_scale_get(WIDGET(it)) *
3604                          _elm_config->scale);
3605    evas_object_smart_member_add(it->item->deco_it_view, it->wd->pan_smart);
3606    elm_widget_sub_object_add(WIDGET(it), it->item->deco_it_view);
3607
3608    strncpy(buf, "item", sizeof(buf));
3609    if (it->wd->mode == ELM_LIST_COMPRESS)
3610      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3611
3612    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3613    strncat(buf, "/", sizeof(buf) - strlen(buf));
3614    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
3615
3616    _elm_theme_object_set(WIDGET(it), it->item->deco_it_view, "genlist", buf,
3617                          elm_widget_style_get(WIDGET(it)));
3618    edje_object_mirrored_set(it->item->deco_it_view,
3619                             elm_widget_mirrored_get(WIDGET(it)));
3620
3621    /* signal callback add */
3622    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN,
3623                                   _mouse_down, it);
3624    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP,
3625                                   _mouse_up, it);
3626    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE,
3627                                   _mouse_move, it);
3628
3629    /* text_get, content_get, state_get */
3630    /* FIXME: If you see that assert, please notify us and we
3631       will clean our mess */
3632    assert(eina_list_count(it->item->deco_it_content_objs) == 0);
3633
3634    _item_text_realize(it, it->item->deco_it_view, &it->item->deco_it_texts, NULL);
3635    if (!it->item->deco_it_contents)
3636      it->item->deco_it_contents =
3637         elm_widget_stringlist_get(edje_object_data_get(it->item->deco_it_view, "contents"));
3638    it->item->deco_it_content_objs =
3639      _item_mode_content_realize(it, it->item->deco_it_view,
3640                                 &it->item->deco_it_contents, NULL,
3641                                 &it->item->deco_it_content_objs);
3642    _item_state_realize(it, it->item->deco_it_view, &it->item->deco_it_states, NULL);
3643    edje_object_part_swallow(it->item->deco_it_view,
3644                             edje_object_data_get(it->item->deco_it_view, "mode_part"),
3645                             VIEW(it));
3646
3647    it->want_unrealize = EINA_FALSE;
3648    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3649    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3650 }
3651
3652 static void
3653 _decorate_item_unrealize(Elm_Gen_Item *it)
3654 {
3655    Widget_Data *wd = it->wd;
3656    Evas_Object *content;
3657    if (!it->item->deco_it_view) return;
3658
3659    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3660    elm_widget_stringlist_free(it->item->deco_it_texts);
3661    it->item->deco_it_texts = NULL;
3662    elm_widget_stringlist_free(it->item->deco_it_contents);
3663    it->item->deco_it_contents = NULL;
3664    elm_widget_stringlist_free(it->item->deco_it_states);
3665
3666    EINA_LIST_FREE(it->item->deco_it_content_objs, content)
3667      evas_object_del(content);
3668
3669    edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
3670    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3671    evas_object_del(it->item->deco_it_view);
3672    it->item->deco_it_view = NULL;
3673
3674    if (wd->mode_item == it)
3675      wd->mode_item = NULL;
3676    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3677    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3678 }
3679
3680 static void
3681 _decorate_item_set(Elm_Gen_Item *it)
3682 {
3683    if (!it) return;
3684    Widget_Data *wd = it->wd;
3685    if (!wd) return;
3686    char buf[1024];
3687
3688    wd->mode_item = it;
3689    it->item->nocache_once = EINA_TRUE;
3690
3691    if (wd->scr_hold_timer)
3692      {
3693         ecore_timer_del(wd->scr_hold_timer);
3694         wd->scr_hold_timer = NULL;
3695      }
3696    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3697    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3698
3699    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3700    _decorate_item_realize(it);
3701    if (it->item->group_item)
3702      evas_object_raise(it->item->VIEW(group_item));
3703    _item_position(it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
3704    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3705    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3706
3707    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->decorate_it_type);
3708    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3709 }
3710
3711 static void
3712 _decorate_item_unset(Widget_Data *wd)
3713 {
3714    if (!wd) return;
3715    if (!wd->mode_item) return;
3716    char buf[1024], buf2[1024];
3717    Elm_Gen_Item *it;
3718
3719    it = wd->mode_item;
3720    it->item->nocache_once = EINA_TRUE;
3721
3722    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->decorate_it_type);
3723    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->decorate_it_type);
3724
3725    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3726    edje_object_signal_callback_add(it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb, it);
3727
3728    wd->mode_item = NULL;
3729 }
3730
3731 static void
3732 _decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity)
3733 {
3734    if ((!it) || (!it->wd->decorate_all_mode)) return;
3735    evas_object_resize(it->deco_all_view, it->item->w, it->item->h);
3736    evas_object_move(it->deco_all_view, itx, ity);
3737 }
3738
3739 static void
3740 _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3741 {
3742    char buf[1024];
3743    const char *stacking_even;
3744    const char *stacking;
3745
3746    if ((!it) || (it->item->decorate_all_item_realized) ||
3747        (it->generation < it->wd->generation))
3748      return;
3749
3750    it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3751    edje_object_scale_set(it->deco_all_view, elm_widget_scale_get(WIDGET(it)) *
3752                          _elm_config->scale);
3753    evas_object_smart_member_add(it->deco_all_view, it->wd->pan_smart);
3754    elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
3755
3756    if (it->item->type & ELM_GENLIST_ITEM_TREE)
3757       strncpy(buf, "tree", sizeof(buf));
3758    else strncpy(buf, "item", sizeof(buf));
3759    if (it->wd->mode == ELM_LIST_COMPRESS)
3760       strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3761
3762    strncat(buf, "/", sizeof(buf) - strlen(buf));
3763    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
3764
3765    _elm_theme_object_set(WIDGET(it),  it->deco_all_view, "genlist", buf,
3766                          elm_widget_style_get(WIDGET(it)));
3767
3768    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3769    if (!stacking_even) stacking_even = "above";
3770    it->item->stacking_even = !!strcmp("above", stacking_even);
3771
3772    stacking = edje_object_data_get(VIEW(it), "stacking");
3773    if (!stacking) stacking = "yes";
3774    it->item->nostacking = !!strcmp("yes", stacking);
3775
3776    edje_object_mirrored_set(it->deco_all_view,
3777                             elm_widget_mirrored_get(WIDGET(it)));
3778
3779    _elm_genlist_item_odd_even_update(it);
3780    _elm_genlist_item_state_update(it, NULL);
3781
3782    if (effect_on) edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled,effect", "elm");
3783    else edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled", "elm");
3784
3785    _item_mouse_callbacks_del(it, VIEW(it));
3786    _item_mouse_callbacks_add(it, it->deco_all_view);
3787
3788    _item_text_realize(it, it->deco_all_view, &it->item->deco_all_texts, NULL);
3789    if (it->flipped) edje_object_signal_emit(it->deco_all_view, "elm,state,flip,enabled", "elm");
3790    if (!it->item->deco_all_contents)
3791      it->item->deco_all_contents =
3792         elm_widget_stringlist_get(edje_object_data_get(it->deco_all_view, "decorate_contents"));
3793    it->item->deco_all_content_objs =
3794      _item_mode_content_realize(it, it->deco_all_view,
3795                                 &it->item->deco_all_contents, NULL,
3796                                 &it->item->deco_all_content_objs);
3797    _item_state_realize(it, it->deco_all_view, &it->item->deco_all_states, NULL);
3798    edje_object_part_swallow(it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
3799
3800    _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
3801    evas_object_show(it->deco_all_view);
3802
3803    if (it->selected) edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
3804
3805    it->item->decorate_all_item_realized = EINA_TRUE;
3806    it->want_unrealize = EINA_FALSE;
3807 }
3808
3809 static void
3810 _decorate_all_item_unrealize(Elm_Gen_Item *it)
3811 {
3812    Evas_Object *icon;
3813    if ((!it) || (!it->item->decorate_all_item_realized)) return;
3814
3815    edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3816    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3817    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3818    _elm_genlist_item_odd_even_update(it);
3819    _elm_genlist_item_state_update(it, NULL);
3820
3821    evas_object_del(it->deco_all_view);
3822    it->deco_all_view = NULL;
3823    elm_widget_stringlist_free(it->item->deco_all_texts);
3824    it->item->deco_all_texts = NULL;
3825    elm_widget_stringlist_free(it->item->deco_all_contents);
3826    it->item->deco_all_contents = NULL;
3827    elm_widget_stringlist_free(it->item->deco_all_states);
3828    it->item->deco_all_states = NULL;
3829    EINA_LIST_FREE(it->item->deco_all_content_objs, icon)
3830      evas_object_del(icon);
3831    edje_object_message_signal_process(it->deco_all_view);
3832    _item_mouse_callbacks_del(it, it->deco_all_view);
3833    _item_mouse_callbacks_add(it, VIEW(it));
3834
3835    it->item->decorate_all_item_realized = EINA_FALSE;
3836 }
3837
3838 static void
3839 _item_auto_scroll(Widget_Data *wd)
3840 {
3841    if (!wd) return;
3842    Elm_Gen_Item  *tmp_item = NULL;
3843
3844    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3845      {
3846         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3847         if (!tmp_item) return;
3848         wd->show_item = tmp_item;
3849         wd->bring_in = EINA_TRUE;
3850         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3851         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3852           {
3853              wd->show_item->item->showme = EINA_TRUE;
3854              wd->auto_scroll_enabled = EINA_FALSE;
3855           }
3856         else
3857           _scroll_item(wd);
3858      }
3859 }
3860
3861 EAPI Evas_Object *
3862 elm_genlist_add(Evas_Object *parent)
3863 {
3864    Evas_Object *obj;
3865    Evas *e;
3866    Widget_Data *wd;
3867    Evas_Coord minw, minh;
3868    static Evas_Smart *smart = NULL;
3869
3870    if (!smart)
3871      {
3872         static Evas_Smart_Class sc;
3873
3874         evas_object_smart_clipped_smart_set(&_pan_sc);
3875         sc = _pan_sc;
3876         sc.name = "elm_genlist_pan";
3877         sc.version = EVAS_SMART_CLASS_VERSION;
3878         sc.add = _pan_add;
3879         sc.del = _pan_del;
3880         sc.resize = _pan_resize;
3881         sc.move = _pan_move;
3882         sc.calculate = _pan_calculate;
3883         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3884      }
3885
3886    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3887
3888    ELM_SET_WIDTYPE(widtype, "genlist");
3889    ELM_GEN_SETUP(wd);
3890    elm_widget_type_set(obj, "genlist");
3891    elm_widget_sub_object_add(parent, obj);
3892    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3893    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3894    elm_widget_data_set(obj, wd);
3895    elm_widget_del_hook_set(obj, _del_hook);
3896    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3897    elm_widget_theme_hook_set(obj, _theme_hook);
3898    elm_widget_can_focus_set(obj, EINA_TRUE);
3899    elm_widget_event_hook_set(obj, _event_hook);
3900    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3901    elm_widget_translate_hook_set(obj, _translate_hook);
3902
3903    wd->generation = 1;
3904    wd->scr = elm_smart_scroller_add(e);
3905    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_DOWN,
3906                                   _mouse_down_scroller, obj);
3907    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_UP,
3908                                   _mouse_up_scroller, obj);
3909    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_MOVE,
3910                                   _mouse_move_scroller, obj);
3911    elm_smart_scroller_widget_set(wd->scr, obj);
3912    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3913                                        elm_widget_style_get(obj));
3914    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3915                                        _elm_config->thumbscroll_bounce_enable);
3916    elm_widget_resize_object_set(obj, wd->scr);
3917
3918    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3919    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3920    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3921    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3922    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3923    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3924    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3925    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3926
3927    wd->obj = obj;
3928    wd->mode = ELM_LIST_SCROLL;
3929    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3930    wd->item_cache_max = wd->max_items_per_block * 2;
3931    wd->longpress_timeout = _elm_config->longpress_timeout;
3932    wd->highlight = EINA_TRUE;
3933    wd->tree_effect_enabled = _elm_config->effect_enable;
3934
3935    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3936    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3937    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3938    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3939
3940    wd->pan_smart = evas_object_smart_add(e, smart);
3941    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3942    wd->pan->wd = wd;
3943
3944    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3945                                      _pan_set, _pan_get, _pan_max_get,
3946                                      _pan_min_get, _pan_child_size_get);
3947
3948    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3949                              &minw, &minh);
3950    evas_object_size_hint_min_set(obj, minw, minh);
3951
3952    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3953
3954    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3955    _sizing_eval(obj);
3956    return obj;
3957 }
3958
3959 void
3960 _item_select(Elm_Gen_Item *it)
3961 {
3962    Eina_List *l;
3963    Evas_Object *obj = WIDGET(it);
3964    Evas_Object *item_obj;
3965
3966    if ((it->generation < it->wd->generation) || (it->decorate_it_set) ||
3967        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
3968        (it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
3969      return;
3970    if (!it->selected)
3971      {
3972         it->selected = EINA_TRUE;
3973         it->wd->selected = eina_list_append(it->wd->selected, it);
3974      }
3975    else if (it->wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) return;
3976
3977    evas_object_ref(obj);
3978    it->walking++;
3979    it->wd->walking++;
3980    if (it->wd->last_selected_item &&
3981        (it != (Elm_Gen_Item *) it->wd->last_selected_item))
3982      {
3983         Elm_Gen_Item *_lsit = (Elm_Gen_Item *)it->wd->last_selected_item;
3984
3985         EINA_LIST_FOREACH(_lsit->content_objs, l, item_obj)
3986           {
3987              elm_widget_focused_object_clear(item_obj);
3988              elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
3989           }
3990         if (elm_widget_type_get(obj) == _genlist)
3991           {
3992              EINA_LIST_FOREACH(_lsit->item->flip_content_objs, l, item_obj)
3993                {
3994                   elm_widget_focused_object_clear(item_obj);
3995                   elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
3996                }
3997              EINA_LIST_FOREACH(_lsit->item->deco_all_content_objs, l, item_obj)
3998                {
3999                   elm_widget_focused_object_clear(item_obj);
4000                   elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
4001                }
4002           }
4003         _lsit->can_focus = EINA_FALSE;
4004      }
4005    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
4006    if (it->generation == it->wd->generation)
4007      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
4008    it->walking--;
4009    it->wd->walking--;
4010    if ((it->wd->clear_me) && (!it->wd->walking))
4011      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
4012    else
4013      {
4014         if ((!it->walking) && (it->generation < it->wd->generation))
4015           {
4016              if (!it->relcount)
4017                {
4018                   it->del_cb(it);
4019                   elm_widget_item_free(it);
4020                }
4021           }
4022         else
4023           it->wd->last_selected_item = (Elm_Object_Item *)it;
4024      }
4025    evas_object_unref(obj);
4026 }
4027
4028 static Evas_Object *
4029 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
4030 {
4031    return edje_object_part_swallow_get(VIEW(it), part);
4032 }
4033
4034 static void
4035 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
4036 {
4037    if (content && part)
4038      {
4039         it->content_objs = eina_list_append(it->content_objs, content);
4040         edje_object_part_swallow(VIEW(it), part, content);
4041      }
4042 }
4043
4044 static Evas_Object *
4045 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
4046 {
4047    Evas_Object *obj;
4048    obj = edje_object_part_swallow_get(VIEW(it), part);
4049    if (!obj) return NULL;
4050    it->content_objs = eina_list_remove(it->content_objs, obj);
4051    edje_object_part_unswallow(VIEW(it), obj);
4052    return obj;
4053 }
4054
4055 static const char *
4056 _item_text_get_hook(Elm_Gen_Item *it, const char *part)
4057 {
4058    if (!it->itc->func.text_get) return NULL;
4059    return edje_object_part_text_get(VIEW(it), part);
4060 }
4061
4062 static void
4063 _item_disable_hook(Elm_Object_Item *it)
4064 {
4065    Eina_List *l;
4066    Evas_Object *obj;
4067    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4068
4069    if (_it->generation < _it->wd->generation) return;
4070
4071    if (_it->selected)
4072      elm_genlist_item_selected_set(it, EINA_FALSE);
4073
4074    if (_it->realized)
4075      {
4076         if (elm_widget_item_disabled_get(it))
4077           {
4078              edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
4079              if (_it->deco_all_view)
4080                edje_object_signal_emit(_it->deco_all_view, "elm,state,disabled", "elm");
4081           }
4082         else
4083           {
4084              edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
4085              if (_it->deco_all_view)
4086                edje_object_signal_emit(_it->deco_all_view, "elm,state,enabled", "elm");
4087           }
4088         EINA_LIST_FOREACH(_it->content_objs, l, obj)
4089           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
4090      }
4091 }
4092
4093 static Eina_Bool
4094 _item_del_pre_hook(Elm_Object_Item *it)
4095 {
4096    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4097
4098    if ((_it->relcount > 0) || (_it->walking > 0))
4099      {
4100         elm_genlist_item_subitems_clear(it);
4101         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
4102         _elm_genlist_item_del_notserious(_it);
4103         if (_it->item->block)
4104           {
4105              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
4106              _it->item->block->changed = EINA_TRUE;
4107              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
4108              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
4109           }
4110         if (_it->parent)
4111           {
4112              _it->parent->item->items =
4113                 eina_list_remove(_it->parent->item->items, it);
4114              _it->parent = NULL;
4115           }
4116         return EINA_FALSE;
4117      }
4118    _item_del(_it);
4119    return EINA_TRUE;
4120 }
4121
4122 static void
4123 _item_signal_emit_hook(Elm_Object_Item *it,
4124                        const char *emission,
4125                        const char *source)
4126 {
4127    edje_object_signal_emit(VIEW(it), emission, source);
4128 }
4129
4130 Elm_Gen_Item *
4131 _elm_genlist_item_new(Widget_Data              *wd,
4132                       const Elm_Gen_Item_Class *itc,
4133                       const void               *data,
4134                       Elm_Gen_Item             *parent,
4135                       Evas_Smart_Cb             func,
4136                       const void               *func_data)
4137 {
4138    Elm_Gen_Item *it;
4139
4140    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
4141    if (!it) return NULL;
4142    it->wd = wd;
4143    it->generation = wd->generation;
4144    it->itc = itc;
4145    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
4146    it->base.data = data;
4147    it->parent = parent;
4148    it->func.func = func;
4149    it->func.data = func_data;
4150    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
4151    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
4152    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
4153    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
4154    elm_widget_item_disable_hook_set(it, _item_disable_hook);
4155    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
4156    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
4157
4158    /* TEMPORARY */
4159    it->sel_cb = (Ecore_Cb)_item_select;
4160
4161    return it;
4162 }
4163
4164 static Elm_Gen_Item *
4165 _item_new(Widget_Data                  *wd,
4166           const Elm_Genlist_Item_Class *itc,
4167           const void                   *data,
4168           Elm_Gen_Item                 *parent,
4169           Elm_Genlist_Item_Type         type,
4170           Evas_Smart_Cb                 func,
4171           const void                   *func_data)
4172 {
4173    Elm_Gen_Item *it, *it2;
4174    int depth = 0;
4175
4176    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
4177    if (!it) return NULL;
4178    it->item = ELM_NEW(Elm_Gen_Item_Type);
4179    it->item->type = type;
4180    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
4181    it->item->expanded_depth = 0;
4182    ELM_GEN_ITEM_SETUP(it);
4183    it->mouse_cursor = NULL;
4184    it->can_focus = EINA_TRUE;
4185    if (it->parent)
4186      {
4187         if (it->parent->group)
4188           it->item->group_item = parent;
4189         else if (it->parent->item->group_item)
4190           it->item->group_item = it->parent->item->group_item;
4191      }
4192    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
4193      {
4194         if (!it2->parent->group) depth += 1;
4195      }
4196    it->item->expanded_depth = depth;
4197    wd->item_count++;
4198    return it;
4199 }
4200
4201 static Item_Block *
4202 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
4203 {
4204    Item_Block *itb;
4205
4206    itb = calloc(1, sizeof(Item_Block));
4207    if (!itb) return NULL;
4208    itb->wd = wd;
4209    if (prepend)
4210      {
4211         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
4212         _item_block_position_update(wd->blocks, 0);
4213      }
4214    else
4215      {
4216         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4217         itb->position_update = EINA_TRUE;
4218         if (wd->blocks != EINA_INLIST_GET(itb))
4219           {
4220              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4221           }
4222         else
4223           {
4224              itb->position = 0;
4225           }
4226      }
4227    return itb;
4228 }
4229
4230 static Eina_Bool
4231 _item_block_add(Widget_Data  *wd,
4232                 Elm_Gen_Item *it)
4233 {
4234    Item_Block *itb = NULL;
4235
4236    if (!it->item->rel)
4237      {
4238 newblock:
4239         if (it->item->rel)
4240           {
4241              itb = calloc(1, sizeof(Item_Block));
4242              if (!itb) return EINA_FALSE;
4243              itb->wd = wd;
4244              if (!it->item->rel->item->block)
4245                {
4246                   wd->blocks =
4247                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4248                   itb->items = eina_list_append(itb->items, it);
4249                   itb->position_update = EINA_TRUE;
4250                   it->position = eina_list_count(itb->items);
4251                   it->position_update = EINA_TRUE;
4252
4253                   if (wd->blocks != EINA_INLIST_GET(itb))
4254                     {
4255                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4256                     }
4257                   else
4258                     {
4259                        itb->position = 0;
4260                     }
4261                }
4262              else
4263                {
4264                   Eina_List *tmp;
4265
4266                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
4267                   if (it->item->before)
4268                     {
4269                        wd->blocks = eina_inlist_prepend_relative
4270                            (wd->blocks, EINA_INLIST_GET(itb),
4271                            EINA_INLIST_GET(it->item->rel->item->block));
4272                        itb->items =
4273                          eina_list_prepend_relative_list(itb->items, it, tmp);
4274
4275                        /* Update index from where we prepended */
4276                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4277                        _item_block_position_update(EINA_INLIST_GET(itb),
4278                                                    it->item->rel->item->block->position);
4279                     }
4280                   else
4281                     {
4282                        wd->blocks = eina_inlist_append_relative
4283                            (wd->blocks, EINA_INLIST_GET(itb),
4284                            EINA_INLIST_GET(it->item->rel->item->block));
4285                        itb->items =
4286                          eina_list_append_relative_list(itb->items, it, tmp);
4287
4288                        /* Update block index from where we appended */
4289                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4290                        _item_block_position_update(EINA_INLIST_GET(itb),
4291                                                    it->item->rel->item->block->position + 1);
4292                     }
4293                }
4294           }
4295         else
4296           {
4297              if (it->item->before)
4298                {
4299                   if (wd->blocks)
4300                     {
4301                        itb = (Item_Block *)(wd->blocks);
4302                        if (itb->count >= wd->max_items_per_block)
4303                          {
4304                             itb = _item_block_new(wd, EINA_TRUE);
4305                             if (!itb) return EINA_FALSE;
4306                          }
4307                     }
4308                   else
4309                     {
4310                        itb = _item_block_new(wd, EINA_TRUE);
4311                        if (!itb) return EINA_FALSE;
4312                     }
4313                   itb->items = eina_list_prepend(itb->items, it);
4314
4315                   _item_position_update(itb->items, 0);
4316                }
4317              else
4318                {
4319                   if (wd->blocks)
4320                     {
4321                        itb = (Item_Block *)(wd->blocks->last);
4322                        if (itb->count >= wd->max_items_per_block)
4323                          {
4324                             itb = _item_block_new(wd, EINA_FALSE);
4325                             if (!itb) return EINA_FALSE;
4326                          }
4327                     }
4328                   else
4329                     {
4330                        itb = _item_block_new(wd, EINA_FALSE);
4331                        if (!itb) return EINA_FALSE;
4332                     }
4333                   itb->items = eina_list_append(itb->items, it);
4334                   it->position = eina_list_count(itb->items);
4335                }
4336           }
4337      }
4338    else
4339      {
4340         Eina_List *tmp;
4341
4342         if (it->item->rel->item->queued)
4343           {
4344              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
4345                 on sorted insertion order, so the queue is not always ordered like the item list.
4346                 This lead to issue where we depend on an item that is not yet created. As a quick
4347                 work around, we reschedule the calc of the item and stop reordering the list to
4348                 prevent any nasty issue to show up here.
4349               */
4350              wd->queue = eina_list_append(wd->queue, it);
4351              wd->requeued = EINA_TRUE;
4352              it->item->queued = EINA_TRUE;
4353              return EINA_FALSE;
4354           }
4355         itb = it->item->rel->item->block;
4356         if (!itb) goto newblock;
4357         tmp = eina_list_data_find_list(itb->items, it->item->rel);
4358         if (it->item->before)
4359           {
4360              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
4361              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4362           }
4363         else
4364           {
4365              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
4366              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4367           }
4368      }
4369    itb->count++;
4370    itb->changed = EINA_TRUE;
4371    it->item->block = itb;
4372    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
4373    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
4374    if (it->item->rel)
4375      {
4376         it->item->rel->relcount--;
4377         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
4378           {
4379              _item_del(it->item->rel);
4380              elm_widget_item_free(it->item->rel);
4381           }
4382         it->item->rel = NULL;
4383      }
4384    if (itb->count > itb->wd->max_items_per_block)
4385      {
4386         Item_Block *itb2;
4387         Elm_Gen_Item *it2;
4388         int newc;
4389         Eina_Bool done = EINA_FALSE;
4390
4391         newc = itb->count / 2;
4392
4393         if (EINA_INLIST_GET(itb)->prev)
4394           {
4395              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
4396
4397              if (itbp->count + newc < wd->max_items_per_block / 2)
4398                {
4399                   /* moving items to previous block */
4400                   while ((itb->count > newc) && (itb->items))
4401                     {
4402                        it2 = eina_list_data_get(itb->items);
4403                        itb->items = eina_list_remove_list(itb->items, itb->items);
4404                        itb->count--;
4405
4406                        itbp->items = eina_list_append(itbp->items, it2);
4407                        it2->item->block = itbp;
4408                        itbp->count++;
4409                     }
4410
4411                   done = EINA_TRUE;
4412                }
4413           }
4414
4415         if (!done && EINA_INLIST_GET(itb)->next)
4416           {
4417              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4418
4419              if (itbn->count + newc < wd->max_items_per_block / 2)
4420                {
4421                   /* moving items to next block */
4422                   while ((itb->count > newc) && (itb->items))
4423                     {
4424                        Eina_List *l;
4425
4426                        l = eina_list_last(itb->items);
4427                        it2 = eina_list_data_get(l);
4428                        itb->items = eina_list_remove_list(itb->items, l);
4429                        itb->count--;
4430
4431                        itbn->items = eina_list_prepend(itbn->items, it2);
4432                        it2->item->block = itbn;
4433                        itbn->count++;
4434                     }
4435
4436                   done = EINA_TRUE;
4437                }
4438           }
4439
4440         if (!done)
4441           {
4442              /* moving items to new block */
4443              itb2 = calloc(1, sizeof(Item_Block));
4444              if (!itb2) return EINA_FALSE;
4445              itb2->wd = wd;
4446              wd->blocks =
4447                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
4448                                            EINA_INLIST_GET(itb));
4449              itb2->changed = EINA_TRUE;
4450              while ((itb->count > newc) && (itb->items))
4451                {
4452                   Eina_List *l;
4453
4454                   l = eina_list_last(itb->items);
4455                   it2 = l->data;
4456                   itb->items = eina_list_remove_list(itb->items, l);
4457                   itb->count--;
4458
4459                   itb2->items = eina_list_prepend(itb2->items, it2);
4460                   it2->item->block = itb2;
4461                   itb2->count++;
4462                }
4463           }
4464      }
4465
4466    return EINA_TRUE;
4467 }
4468
4469 static int
4470 _item_process(Widget_Data *wd, Elm_Gen_Item *it)
4471 {
4472    if (!_item_block_add(wd, it)) return 1;
4473    if (!wd->blocks)
4474      _item_block_realize(it->item->block);
4475    return 0;
4476 }
4477
4478 static void
4479 _item_process_post(Widget_Data *wd, Elm_Gen_Item *it, Eina_Bool qadd)
4480 {
4481    Eina_Bool showme = EINA_FALSE;
4482
4483    if (it->item->block->changed)
4484      {
4485         showme = _item_block_recalc(it->item->block, it->item->block->num, qadd);
4486         it->item->block->changed = 0;
4487         if (wd->pan_changed)
4488           {
4489              if (wd->calc_job) ecore_job_del(wd->calc_job);
4490              wd->calc_job = NULL;
4491              _calc_job(wd);
4492              wd->pan_changed = EINA_FALSE;
4493           }
4494      }
4495    if (showme) it->item->block->showme = EINA_TRUE;
4496    /* when prepending, move the scroller along with the first selected item to
4497     * create the illusion that we're watching the selected item
4498     * this prevents the selected item being scrolled off the viewport
4499     */
4500    if (wd->selected && it->item->before)
4501      {
4502         int y, h;
4503         it = wd->selected->data;
4504         elm_smart_scroller_child_pos_get(wd->scr, NULL, &y);
4505         evas_object_geometry_get(wd->pan_smart, NULL, NULL, NULL, &h);
4506         elm_smart_scroller_child_region_show(wd->scr, it->x + it->item->block->x, y + it->item->h, it->item->block->w, h);
4507      }
4508 }
4509
4510 static int
4511 _queue_process(Widget_Data *wd)
4512 {
4513    int n;
4514    double t0, t;
4515
4516    t0 = ecore_loop_time_get();
4517    //evas_event_freeze(evas_object_evas_get(wd->obj));
4518    for (n = 0; (wd->queue) && (n < 128); n++)
4519      {
4520         Elm_Gen_Item *it;
4521
4522         it = eina_list_data_get(wd->queue);
4523         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4524         it->item->queued = EINA_FALSE;
4525         if (_item_process(wd, it)) continue;
4526         t = ecore_time_get();
4527         _item_process_post(wd, it, EINA_TRUE);
4528         /* same as eina_inlist_count > 1 */
4529         if (wd->blocks && wd->blocks->next)
4530           {
4531              if ((t - t0) > (ecore_animator_frametime_get())) break;
4532           }
4533      }
4534    //evas_event_thaw(evas_object_evas_get(wd->obj));
4535    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4536    return n;
4537 }
4538
4539 static Eina_Bool
4540 _idle_process(void *data, Eina_Bool *wakeup)
4541 {
4542    Widget_Data *wd = data;
4543
4544    //xxx
4545    //static double q_start = 0.0;
4546    //if (q_start == 0.0) q_start = ecore_time_get();
4547    //xxx
4548    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4549    if (!wd->queue)
4550      {
4551         //xxx
4552         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4553         //xxx
4554         return ECORE_CALLBACK_CANCEL;
4555      }
4556    return ECORE_CALLBACK_RENEW;
4557 }
4558
4559 static Eina_Bool
4560 _item_idle_enterer(void *data)
4561 {
4562    Widget_Data *wd = data;
4563    Eina_Bool wakeup = EINA_FALSE;
4564    Eina_Bool ok = _idle_process(data, &wakeup);
4565
4566    if (wakeup)
4567      {
4568         // wake up mainloop
4569         if (wd->calc_job) ecore_job_del(wd->calc_job);
4570         wd->calc_job = ecore_job_add(_calc_job, wd);
4571      }
4572    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4573    return ok;
4574 }
4575
4576 static void
4577 _item_queue(Widget_Data    *wd,
4578             Elm_Gen_Item   *it,
4579             Eina_Compare_Cb cb)
4580 {
4581    if (it->item->queued) return;
4582    if ((wd->blocks) && (wd->homogeneous) && (wd->mode == ELM_LIST_COMPRESS))
4583      {
4584         if (!_item_process(wd, it))
4585           _item_process_post(wd, it, EINA_FALSE);
4586         return;
4587      }
4588    it->item->queued = EINA_TRUE;
4589    if (cb && !wd->requeued)
4590      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4591    else
4592      wd->queue = eina_list_append(wd->queue, it);
4593 // FIXME: why does a freeze then thaw here cause some genlist
4594 // elm_genlist_item_append() to be much much slower?
4595 //   evas_event_freeze(evas_object_evas_get(wd->obj));
4596    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4597      {
4598         if (wd->queue_idle_enterer)
4599           {
4600              ecore_idle_enterer_del(wd->queue_idle_enterer);
4601              wd->queue_idle_enterer = NULL;
4602           }
4603         _queue_process(wd);
4604      }
4605 //   evas_event_thaw(evas_object_evas_get(wd->obj));
4606 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4607    if (!wd->queue_idle_enterer)
4608      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4609 }
4610
4611 static int
4612 _elm_genlist_item_compare(const void *data, const void *data1)
4613 {
4614    const Elm_Gen_Item *it, *item1;
4615    it = ELM_GEN_ITEM_FROM_INLIST(data);
4616    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4617    return it->wd->item_compare_cb(it, item1);
4618 }
4619
4620 static int
4621 _elm_genlist_item_list_compare(const void *data, const void *data1)
4622 {
4623    const Elm_Gen_Item *it = data;
4624    const Elm_Gen_Item *item1 = data1;
4625    return it->wd->item_compare_cb(it, item1);
4626 }
4627
4628 /*If application want to know the relative item, use elm_genlist_item_prev_get(it)*/
4629 static void
4630 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4631 {
4632    if (!it) return;
4633    if (!after) return;
4634
4635    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4636    _item_block_del(it);
4637
4638    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4639    it->item->rel = after;
4640    it->item->rel->relcount++;
4641    it->item->before = EINA_FALSE;
4642    if (after->item->group_item) it->item->group_item = after->item->group_item;
4643    _item_queue(it->wd, it, NULL);
4644
4645    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_AFTER, it);
4646 }
4647
4648 /*If application want to know the relative item, use elm_genlist_item_next_get(it)*/
4649 static void
4650 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4651 {
4652    if (!it) return;
4653    if (!before) return;
4654
4655    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4656    _item_block_del(it);
4657    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4658    it->item->rel = before;
4659    it->item->rel->relcount++;
4660    it->item->before = EINA_TRUE;
4661    if (before->item->group_item) it->item->group_item = before->item->group_item;
4662    _item_queue(it->wd, it, NULL);
4663
4664    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_BEFORE, it);
4665 }
4666
4667 EAPI unsigned int
4668 elm_genlist_items_count(const Evas_Object *obj)
4669 {
4670    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4671    Widget_Data *wd = elm_widget_data_get(obj);
4672    if (!wd) return 0;
4673    return wd->item_count;
4674 }
4675
4676 EAPI Elm_Object_Item *
4677 elm_genlist_item_append(Evas_Object                  *obj,
4678                         const Elm_Genlist_Item_Class *itc,
4679                         const void                   *data,
4680                         Elm_Object_Item              *parent,
4681                         Elm_Genlist_Item_Type         type,
4682                         Evas_Smart_Cb                 func,
4683                         const void                   *func_data)
4684 {
4685    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4686    Widget_Data *wd = elm_widget_data_get(obj);
4687    if (!wd) return NULL;
4688    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4689                                 func, func_data);
4690    if (!it) return NULL;
4691    if (!it->parent)
4692      {
4693         if (it->group)
4694           wd->group_items = eina_list_append(wd->group_items, it);
4695         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4696         it->item->rel = NULL;
4697      }
4698    else
4699      {
4700         Elm_Gen_Item *it2 = NULL;
4701         Eina_List *ll = eina_list_last(it->parent->item->items);
4702         if (ll) it2 = ll->data;
4703         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4704         if (!it2) it2 = it->parent;
4705         wd->items =
4706           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4707                                       EINA_INLIST_GET(it2));
4708         it->item->rel = it2;
4709         it->item->rel->relcount++;
4710      }
4711    it->item->before = EINA_FALSE;
4712    _item_queue(wd, it, NULL);
4713    return (Elm_Object_Item *)it;
4714 }
4715
4716 EAPI Elm_Object_Item *
4717 elm_genlist_item_prepend(Evas_Object                  *obj,
4718                          const Elm_Genlist_Item_Class *itc,
4719                          const void                   *data,
4720                          Elm_Object_Item              *parent,
4721                          Elm_Genlist_Item_Type         type,
4722                          Evas_Smart_Cb                 func,
4723                          const void                   *func_data)
4724 {
4725    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4726    Widget_Data *wd = elm_widget_data_get(obj);
4727    if (!wd) return NULL;
4728    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4729                                 func, func_data);
4730    if (!it) return NULL;
4731    if (!it->parent)
4732      {
4733         if (it->group)
4734           wd->group_items = eina_list_prepend(wd->group_items, it);
4735         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4736         it->item->rel = NULL;
4737      }
4738    else
4739      {
4740         Elm_Gen_Item *it2 = NULL;
4741         Eina_List *ll = it->parent->item->items;
4742         if (ll) it2 = ll->data;
4743         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4744         if (!it2) it2 = it->parent;
4745         wd->items =
4746           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4747                                        EINA_INLIST_GET(it2));
4748         it->item->rel = it2;
4749         it->item->rel->relcount++;
4750      }
4751    it->item->before = EINA_TRUE;
4752    _item_queue(wd, it, NULL);
4753    return (Elm_Object_Item *)it;
4754 }
4755
4756 EAPI Elm_Object_Item *
4757 elm_genlist_item_insert_after(Evas_Object                  *obj,
4758                               const Elm_Genlist_Item_Class *itc,
4759                               const void                   *data,
4760                               Elm_Object_Item              *parent,
4761                               Elm_Object_Item              *after,
4762                               Elm_Genlist_Item_Type         type,
4763                               Evas_Smart_Cb                 func,
4764                               const void                   *func_data)
4765 {
4766    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4767    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4768    Widget_Data *wd = elm_widget_data_get(obj);
4769    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4770    if (!wd) return NULL;
4771    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4772    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4773
4774    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4775                                 func, func_data);
4776    if (!it) return NULL;
4777    if (!it->parent)
4778      {
4779         if ((it->group) && (_after->group))
4780           wd->group_items = eina_list_append_relative(wd->group_items, it,
4781                                                       _after);
4782      }
4783    else
4784      {
4785         it->parent->item->items =
4786            eina_list_append_relative(it->parent->item->items, it, _after);
4787      }
4788    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4789                                            EINA_INLIST_GET(_after));
4790    it->item->rel = _after;
4791    it->item->rel->relcount++;
4792    it->item->before = EINA_FALSE;
4793    _item_queue(wd, it, NULL);
4794    return (Elm_Object_Item *)it;
4795 }
4796
4797 EAPI Elm_Object_Item *
4798 elm_genlist_item_insert_before(Evas_Object                  *obj,
4799                                const Elm_Genlist_Item_Class *itc,
4800                                const void                   *data,
4801                                Elm_Object_Item              *parent,
4802                                Elm_Object_Item              *before,
4803                                Elm_Genlist_Item_Type         type,
4804                                Evas_Smart_Cb                 func,
4805                                const void                   *func_data)
4806 {
4807    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4808    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4809    Widget_Data *wd = elm_widget_data_get(obj);
4810    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4811    if (!wd) return NULL;
4812    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4813    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4814
4815    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4816                                 func, func_data);
4817    if (!it) return NULL;
4818    if (!it->parent)
4819      {
4820         if (it->group && _before->group)
4821           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4822                                                        _before);
4823      }
4824    else
4825      {
4826         it->parent->item->items =
4827            eina_list_prepend_relative(it->parent->item->items, it, _before);
4828      }
4829    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4830                                             EINA_INLIST_GET(_before));
4831    it->item->rel = _before;
4832    it->item->rel->relcount++;
4833    it->item->before = EINA_TRUE;
4834    _item_queue(wd, it, NULL);
4835    return (Elm_Object_Item *)it;
4836 }
4837
4838 EAPI Elm_Object_Item *
4839 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4840                                const Elm_Genlist_Item_Class *itc,
4841                                const void                   *data,
4842                                Elm_Object_Item              *parent,
4843                                Elm_Genlist_Item_Type         type,
4844                                Eina_Compare_Cb               comp,
4845                                Evas_Smart_Cb                 func,
4846                                const void                   *func_data)
4847 {
4848    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4849    Widget_Data *wd = elm_widget_data_get(obj);
4850    if (!wd) return NULL;
4851    Elm_Gen_Item *rel = NULL;
4852    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4853                                 func, func_data);
4854    if (!it) return NULL;
4855
4856    wd->item_compare_cb = comp;
4857
4858    if (it->parent)
4859      {
4860         Eina_List *l;
4861         int cmp_result;
4862
4863         l = eina_list_search_sorted_near_list(it->parent->item->items,
4864                                               _elm_genlist_item_list_compare,
4865                                               it,
4866                                               &cmp_result);
4867         if (l)
4868           rel = eina_list_data_get(l);
4869         else
4870           rel = it->parent;
4871
4872         if (cmp_result >= 0)
4873           {
4874              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4875              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4876              it->item->before = EINA_FALSE;
4877           }
4878         else if (cmp_result < 0)
4879           {
4880              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4881              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4882              it->item->before = EINA_TRUE;
4883           }
4884      }
4885    else
4886      {
4887         if (!wd->state)
4888           {
4889              wd->state = eina_inlist_sorted_state_new();
4890              eina_inlist_sorted_state_init(wd->state, wd->items);
4891              wd->requeued = EINA_FALSE;
4892           }
4893
4894         if (it->group)
4895           wd->group_items = eina_list_append(wd->group_items, it);
4896
4897         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4898                                                     _elm_genlist_item_compare, wd->state);
4899
4900         if (EINA_INLIST_GET(it)->next)
4901           {
4902              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4903              it->item->before = EINA_TRUE;
4904           }
4905         else if (EINA_INLIST_GET(it)->prev)
4906           {
4907              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4908              it->item->before = EINA_FALSE;
4909           }
4910      }
4911
4912    if (rel)
4913      {
4914         it->item->rel = rel;
4915         it->item->rel->relcount++;
4916      }
4917
4918    _item_queue(wd, it, _elm_genlist_item_list_compare);
4919
4920    return (Elm_Object_Item *)it;
4921 }
4922
4923 static void
4924 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4925 {
4926    Eina_Inlist *next, *l;
4927    Widget_Data *wd = elm_widget_data_get(obj);
4928    if (!wd) return;
4929
4930    if (!standby) wd->generation++;
4931
4932    if (wd->state)
4933      {
4934         eina_inlist_sorted_state_free(wd->state);
4935         wd->state = NULL;
4936      }
4937
4938    if (wd->walking > 0)
4939      {
4940         wd->clear_me = EINA_TRUE;
4941         return;
4942      }
4943    evas_event_freeze(evas_object_evas_get(wd->obj));
4944    for (l = wd->items, next = l ? l->next : NULL;
4945         l;
4946         l = next, next = next ? next->next : NULL)
4947      {
4948         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4949
4950         if (it->generation < wd->generation)
4951           {
4952              Elm_Gen_Item *itn = NULL;
4953
4954              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4955              if (itn) itn->walking++; /* prevent early death of subitem */
4956              it->del_cb(it);
4957              elm_widget_item_free(it);
4958              if (itn) itn->walking--;
4959           }
4960      }
4961    wd->clear_me = EINA_FALSE;
4962    wd->pan_changed = EINA_TRUE;
4963    if (wd->calc_job)
4964      {
4965         ecore_job_del(wd->calc_job);
4966         wd->calc_job = NULL;
4967      }
4968    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4969    if (wd->clear_cb) wd->clear_cb(wd);
4970    wd->pan_x = 0;
4971    wd->pan_y = 0;
4972    wd->minw = 0;
4973    wd->minh = 0;
4974
4975    if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4976    wd->alpha_bg = NULL;
4977
4978    if (wd->pan_smart)
4979      {
4980         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4981         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4982      }
4983    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4984    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4985    evas_event_thaw(evas_object_evas_get(wd->obj));
4986    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4987 }
4988
4989 EAPI void
4990 elm_genlist_clear(Evas_Object *obj)
4991 {
4992    ELM_CHECK_WIDTYPE(obj, widtype);
4993    _elm_genlist_clear(obj, EINA_FALSE);
4994 }
4995
4996 EAPI void
4997 elm_genlist_multi_select_set(Evas_Object *obj,
4998                              Eina_Bool    multi)
4999 {
5000    ELM_CHECK_WIDTYPE(obj, widtype);
5001    Widget_Data *wd = elm_widget_data_get(obj);
5002    if (!wd) return;
5003    wd->multi = !!multi;
5004 }
5005
5006 EAPI Eina_Bool
5007 elm_genlist_multi_select_get(const Evas_Object *obj)
5008 {
5009    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5010    Widget_Data *wd = elm_widget_data_get(obj);
5011    if (!wd) return EINA_FALSE;
5012    return wd->multi;
5013 }
5014
5015 EAPI Elm_Object_Item *
5016 elm_genlist_selected_item_get(const Evas_Object *obj)
5017 {
5018    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5019    Widget_Data *wd = elm_widget_data_get(obj);
5020    if (!wd) return NULL;
5021    if (wd->selected) return wd->selected->data;
5022    return NULL;
5023 }
5024
5025 EAPI const Eina_List *
5026 elm_genlist_selected_items_get(const Evas_Object *obj)
5027 {
5028    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5029    Widget_Data *wd = elm_widget_data_get(obj);
5030    if (!wd) return NULL;
5031    return wd->selected;
5032 }
5033
5034 EAPI Eina_List *
5035 elm_genlist_realized_items_get(const Evas_Object *obj)
5036 {
5037    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5038    Widget_Data *wd = elm_widget_data_get(obj);
5039    Eina_List *list = NULL;
5040    Item_Block *itb;
5041    Eina_Bool done = EINA_FALSE;
5042    if (!wd) return NULL;
5043    EINA_INLIST_FOREACH(wd->blocks, itb)
5044      {
5045         if (itb->realized)
5046           {
5047              Eina_List *l;
5048              Elm_Gen_Item *it;
5049
5050              done = EINA_TRUE;
5051              EINA_LIST_FOREACH(itb->items, l, it)
5052                {
5053                   if (it->realized) list = eina_list_append(list, it);
5054                }
5055           }
5056         else
5057           {
5058              if (done) break;
5059           }
5060      }
5061    return list;
5062 }
5063
5064 EAPI Elm_Object_Item *
5065 elm_genlist_at_xy_item_get(const Evas_Object *obj,
5066                            Evas_Coord         x,
5067                            Evas_Coord         y,
5068                            int               *posret)
5069 {
5070    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5071    Widget_Data *wd = elm_widget_data_get(obj);
5072    Evas_Coord ox, oy, ow, oh;
5073    Item_Block *itb;
5074    Evas_Coord lasty;
5075    if (!wd) return NULL;
5076    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5077    lasty = oy;
5078    EINA_INLIST_FOREACH(wd->blocks, itb)
5079      {
5080         Eina_List *l;
5081         Elm_Gen_Item *it;
5082
5083         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
5084                                  oy + itb->y - itb->wd->pan_y,
5085                                  itb->w, itb->h, x, y, 1, 1))
5086           continue;
5087         EINA_LIST_FOREACH(itb->items, l, it)
5088           {
5089              Evas_Coord itx, ity;
5090
5091              itx = ox + itb->x + it->x - itb->wd->pan_x;
5092              ity = oy + itb->y + it->y - itb->wd->pan_y;
5093              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
5094                {
5095                   if (posret)
5096                     {
5097                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
5098                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
5099                          *posret = 1;
5100                        else *posret = 0;
5101                     }
5102                   return (Elm_Object_Item *)it;
5103                }
5104              lasty = ity + it->item->h;
5105           }
5106      }
5107    if (posret)
5108      {
5109         if (y > lasty) *posret = 1;
5110         else *posret = -1;
5111      }
5112    return NULL;
5113 }
5114
5115 EAPI Elm_Object_Item *
5116 elm_genlist_first_item_get(const Evas_Object *obj)
5117 {
5118    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5119    Widget_Data *wd = elm_widget_data_get(obj);
5120    if (!wd) return NULL;
5121    if (!wd->items) return NULL;
5122    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
5123    while ((it) && (it->generation < wd->generation))
5124      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5125    return (Elm_Object_Item *)it;
5126 }
5127
5128 EAPI Elm_Object_Item *
5129 elm_genlist_last_item_get(const Evas_Object *obj)
5130 {
5131    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5132    Widget_Data *wd = elm_widget_data_get(obj);
5133    if (!wd) return NULL;
5134    if (!wd->items) return NULL;
5135    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
5136    while ((it) && (it->generation < wd->generation))
5137      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5138    return (Elm_Object_Item *)it;
5139 }
5140
5141 EAPI Elm_Object_Item *
5142 elm_genlist_item_next_get(const Elm_Object_Item *it)
5143 {
5144    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5145    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5146    while (_it)
5147      {
5148         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
5149         if ((_it) && (_it->generation == _it->wd->generation)) break;
5150      }
5151    return (Elm_Object_Item *) _it;
5152 }
5153
5154 EAPI Elm_Object_Item *
5155 elm_genlist_item_prev_get(const Elm_Object_Item *it)
5156 {
5157    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5158    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5159    while (_it)
5160      {
5161         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
5162         if ((_it) && (_it->generation == _it->wd->generation)) break;
5163      }
5164    return (Elm_Object_Item *) _it;
5165 }
5166
5167 EAPI Elm_Object_Item *
5168 elm_genlist_item_parent_get(const Elm_Object_Item *it)
5169 {
5170    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5171    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
5172 }
5173
5174 EAPI void
5175 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
5176 {
5177    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5178    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
5179    if (!wd) return;
5180    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5181
5182    if (!wd->tree_effect_enabled || !wd->move_effect_mode)
5183      _item_subitems_clear(_it);
5184    else
5185      {
5186         if (!wd->tree_effect_animator)
5187           {
5188              wd->expanded_item = _it;
5189              _item_tree_effect_before(_it);
5190              evas_object_raise(wd->alpha_bg);
5191              evas_object_show(wd->alpha_bg);
5192              wd->start_time = ecore_time_get();
5193              wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, wd);
5194           }
5195         else
5196            _item_subitems_clear(_it);
5197      }
5198 }
5199
5200 EAPI void
5201 elm_genlist_item_selected_set(Elm_Object_Item *it,
5202                               Eina_Bool selected)
5203 {
5204    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5205    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5206    Widget_Data *wd = _it->wd;
5207    if (!wd) return;
5208    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
5209      return;
5210    selected = !!selected;
5211    if (_it->selected == selected) return;
5212
5213    if (selected)
5214      {
5215         if (!wd->multi)
5216           {
5217              while (wd->selected)
5218                {
5219                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
5220                   _it->unsel_cb(wd->selected->data);
5221                }
5222           }
5223         _it->highlight_cb(_it);
5224         _item_select(_it);
5225         return;
5226      }
5227    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
5228    _it->unsel_cb(_it);
5229 }
5230
5231 EAPI Eina_Bool
5232 elm_genlist_item_selected_get(const Elm_Object_Item *it)
5233 {
5234    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5235    return ((Elm_Gen_Item *)it)->selected;
5236 }
5237
5238 Elm_Gen_Item *
5239 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
5240 {
5241    Elm_Gen_Item *it2;
5242    if (it->item->expanded)
5243      {
5244         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5245      }
5246    else
5247      {
5248         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5249         while (it2)
5250           {
5251              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
5252              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5253           }
5254      }
5255    return it2;
5256 }
5257
5258 static void
5259 _elm_genlist_move_items_set(Elm_Gen_Item *it)
5260 {
5261    Eina_List *l, *ll;
5262    Elm_Gen_Item *it2 = NULL;
5263    Evas_Coord ox, oy, ow, oh, dh = 0;
5264
5265    it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
5266
5267    if (it->item->expanded)
5268      {
5269         it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
5270         EINA_LIST_FOREACH_SAFE(it->wd->move_items, l, ll, it2)
5271           {
5272              if (it2 == it->wd->expanded_next_item) break;
5273              it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
5274           }
5275      }
5276    else
5277      {
5278         evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
5279         it2 = it->wd->expanded_next_item;
5280         while (it2 && (dh < oy + oh))
5281           {
5282              dh += it2->item->h;
5283              it->wd->move_items = eina_list_append(it->wd->move_items, it2);
5284              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5285           }
5286      }
5287 }
5288
5289 EAPI void
5290 elm_genlist_item_expanded_set(Elm_Object_Item *it,
5291                               Eina_Bool        expanded)
5292 {
5293    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5294    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5295    expanded = !!expanded;
5296    if (_it->item->expanded == expanded) return;
5297    if (_it->item->type != ELM_GENLIST_ITEM_TREE) return;
5298    _it->item->expanded = expanded;
5299    _it->wd->expanded_item = _it;
5300    _elm_genlist_move_items_set(_it);
5301
5302    if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
5303       _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
5304
5305    if (_it->item->expanded)
5306      {
5307         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
5308         if (_it->realized)
5309           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
5310         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
5311         _it->wd->auto_scroll_enabled = EINA_TRUE;
5312      }
5313    else
5314      {
5315         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
5316         if (_it->realized)
5317           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
5318         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
5319         _it->wd->auto_scroll_enabled = EINA_FALSE;
5320      }
5321 }
5322
5323 EAPI Eina_Bool
5324 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
5325 {
5326    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5327    return ((Elm_Gen_Item *)it)->item->expanded;
5328 }
5329
5330 EAPI int
5331 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
5332 {
5333    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
5334    return ((Elm_Gen_Item *)it)->item->expanded_depth;
5335 }
5336
5337 EINA_DEPRECATED EAPI void
5338 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
5339                                   Eina_Bool         display_only)
5340 {
5341    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5342    display_only = !!display_only;
5343
5344    if (display_only)
5345      elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
5346    else
5347      {
5348         Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5349         if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5350           elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DEFAULT);
5351      }
5352 }
5353
5354 EINA_DEPRECATED EAPI Eina_Bool
5355 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
5356 {
5357    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5358    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5359    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5360    Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5361    if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5362      return EINA_TRUE;
5363    return EINA_FALSE;
5364 }
5365
5366 static Eina_Bool
5367 _elm_genlist_item_compute_coordinates(Elm_Object_Item               *it,
5368                                       Elm_Genlist_Item_Scrollto_Type type,
5369                                       Eina_Bool                      bring_in,
5370                                       Evas_Coord                    *x,
5371                                       Evas_Coord                    *y,
5372                                       Evas_Coord                    *w,
5373                                       Evas_Coord                    *h)
5374 {
5375    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5376    Evas_Coord gith = 0;
5377    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5378    if ((_it->wd->homogeneous) &&
5379        (_it->wd->mode == ELM_LIST_COMPRESS))
5380      goto hm_shortcut;  /* homogenous genlist shortcut */
5381    if ((_it->item->queued) || (!_it->item->mincalcd))
5382      {
5383         _it->wd->show_item = _it;
5384         _it->wd->bring_in = bring_in;
5385         _it->wd->scrollto_type = type;
5386         _it->item->showme = EINA_TRUE;
5387         return EINA_FALSE;
5388      }
5389 hm_shortcut:
5390    if (_it->wd->show_item)
5391      {
5392         _it->wd->show_item->item->showme = EINA_FALSE;
5393         _it->wd->show_item = NULL;
5394      }
5395
5396    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
5397    switch (type)
5398      {
5399       case ELM_GENLIST_ITEM_SCROLLTO_IN:
5400          if ((_it->item->group_item) &&
5401              (_it->wd->pan_y > (_it->y + _it->item->block->y)))
5402            gith = _it->item->group_item->item->h;
5403          *h = _it->item->h;
5404          *y = _it->y + _it->item->block->y - gith;
5405          break;
5406       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
5407          if (_it->item->group_item) gith = _it->item->group_item->item->h;
5408          *y = _it->y + _it->item->block->y - gith;
5409          break;
5410       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
5411          *y = _it->y + _it->item->block->y - (*h / 2) + (_it->item->h / 2);
5412          break;
5413       default:
5414          return EINA_FALSE;
5415      }
5416
5417    *x = _it->x + _it->item->block->x;
5418    *w = _it->item->block->w;
5419    return EINA_TRUE;
5420 }
5421
5422 EAPI void
5423 elm_genlist_item_promote(Elm_Object_Item *it)
5424 {
5425    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5426    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5427    if (_it->generation < _it->wd->generation) return;
5428    _item_move_before(_it,
5429                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
5430 }
5431
5432 EAPI void
5433 elm_genlist_item_demote(Elm_Object_Item *it)
5434 {
5435    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5436    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5437    if (_it->generation < _it->wd->generation) return;
5438    _item_move_after(_it,
5439                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
5440 }
5441
5442 EAPI void
5443 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5444 {
5445    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5446    Evas_Coord x, y, w, h;
5447    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5448
5449    if (_elm_genlist_item_compute_coordinates(it, type, EINA_FALSE, &x, &y, &w, &h))
5450      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
5451 }
5452
5453 EAPI void
5454 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5455 {
5456
5457    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5458    Evas_Coord x, y, w, h;
5459    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5460
5461    elm_smart_scroller_child_viewport_size_get(_it->wd->scr, &x, &y);
5462
5463    if (_elm_genlist_item_compute_coordinates(it, type, EINA_TRUE, &x, &y, &w, &h))
5464      elm_smart_scroller_region_bring_in(_it->wd->scr, x, y, w, h);
5465 }
5466
5467 EAPI void
5468 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
5469 {
5470    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5471
5472    Evas_Object *content;
5473    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
5474      {
5475         elm_widget_sub_object_del(WIDGET(it), content);
5476         evas_object_smart_member_del(content);
5477         evas_object_hide(content);
5478         if (l) *l = eina_list_append(*l, content);
5479      }
5480 }
5481
5482 EAPI void
5483 elm_genlist_item_update(Elm_Object_Item *it)
5484 {
5485    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5486    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5487
5488    if (!_it->item->block) return;
5489    if (_it->generation < _it->wd->generation) return;
5490    _it->item->mincalcd = EINA_FALSE;
5491    _it->item->updateme = EINA_TRUE;
5492    _it->item->block->updateme = EINA_TRUE;
5493    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5494    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5495 }
5496
5497 EAPI void
5498 elm_genlist_item_fields_update(Elm_Object_Item            *it,
5499                                const char                 *parts,
5500                                Elm_Genlist_Item_Field_Type itf)
5501 {
5502    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5503    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5504
5505    if (!_it->item->block) return;
5506    if (_it->generation < _it->wd->generation) return;
5507
5508    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
5509      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
5510    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
5511      {
5512         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
5513                                                    &_it->contents, parts);
5514         _it->content_objs = _item_content_realize(_it, VIEW(_it),
5515                                                  &_it->contents, parts);
5516
5517         if (_it->flipped)
5518           {
5519              _it->item->flip_content_objs =
5520                _item_mode_content_unrealize(_it, VIEW(_it),
5521                                             &_it->item->flip_contents, parts,
5522                                             &_it->item->flip_content_objs);
5523              _it->item->flip_content_objs =
5524                _item_mode_content_realize(_it, VIEW(_it),
5525                                           &_it->item->flip_contents, parts,
5526                                           &_it->item->flip_content_objs);
5527           }
5528         if (_it->item->deco_it_view)
5529           {
5530              _it->item->deco_it_content_objs =
5531                _item_mode_content_unrealize(_it, _it->item->deco_it_view,
5532                                             &_it->item->deco_it_contents, parts,
5533                                             &_it->item->deco_it_content_objs);
5534              _it->item->deco_it_content_objs =
5535                _item_mode_content_realize(_it, _it->item->deco_it_view,
5536                                           &_it->item->deco_it_contents, parts,
5537                                           &_it->item->deco_it_content_objs);
5538           }
5539         if (_it->wd->decorate_all_mode)
5540           {
5541              _it->item->deco_all_content_objs =
5542                _item_mode_content_unrealize(_it, _it->deco_all_view,
5543                                             &_it->item->deco_all_contents, parts,
5544                                             &_it->item->deco_all_content_objs);
5545              _it->item->deco_all_content_objs =
5546                _item_mode_content_realize(_it, _it->deco_all_view,
5547                                           &_it->item->deco_all_contents, parts,
5548                                           &_it->item->deco_all_content_objs);
5549           }
5550      }
5551    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
5552      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
5553 }
5554
5555 EAPI void
5556 elm_genlist_item_item_class_update(Elm_Object_Item              *it,
5557                                    const Elm_Genlist_Item_Class *itc)
5558 {
5559    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5560    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5561
5562    if (!_it->item->block) return;
5563    EINA_SAFETY_ON_NULL_RETURN(itc);
5564    if (_it->generation < _it->wd->generation) return;
5565    _it->itc = itc;
5566    _it->item->nocache_once = EINA_TRUE;
5567
5568    elm_widget_stringlist_free(_it->texts);
5569    _it->texts = NULL;
5570    elm_widget_stringlist_free(_it->contents);
5571    _it->contents = NULL;
5572    elm_widget_stringlist_free(_it->states);
5573    _it->states = NULL;
5574
5575    if (_it->flipped)
5576      {
5577         elm_widget_stringlist_free(_it->item->flip_contents);
5578         _it->item->flip_contents = NULL;
5579      }
5580    if (_it->item->deco_it_view)
5581      {
5582         elm_widget_stringlist_free(_it->item->deco_it_texts);
5583         _it->item->deco_it_texts = NULL;
5584         elm_widget_stringlist_free(_it->item->deco_it_contents);
5585         _it->item->deco_it_contents = NULL;
5586      }
5587    if (_it->wd->decorate_all_mode)
5588      {
5589         elm_widget_stringlist_free(_it->item->deco_all_texts);
5590         _it->item->deco_all_texts = NULL;
5591         elm_widget_stringlist_free(_it->item->deco_all_contents);
5592         _it->item->deco_all_contents = NULL;
5593      }
5594
5595    elm_genlist_item_update(it);
5596 }
5597
5598 EAPI const Elm_Genlist_Item_Class *
5599 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
5600 {
5601    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5602    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5603    if (_it->generation < _it->wd->generation) return NULL;
5604    return _it->itc;
5605 }
5606
5607 static Evas_Object *
5608 _elm_genlist_item_label_create(void        *data,
5609                                Evas_Object *obj __UNUSED__,
5610                                Evas_Object *tooltip,
5611                                void        *it __UNUSED__)
5612 {
5613    Evas_Object *label = elm_label_add(tooltip);
5614    if (!label)
5615      return NULL;
5616    elm_object_style_set(label, "tooltip");
5617    elm_object_text_set(label, data);
5618    return label;
5619 }
5620
5621 static void
5622 _elm_genlist_item_label_del_cb(void        *data,
5623                                Evas_Object *obj __UNUSED__,
5624                                void        *event_info __UNUSED__)
5625 {
5626    eina_stringshare_del(data);
5627 }
5628
5629 EAPI void
5630 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5631                                   const char      *text)
5632 {
5633    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5634    text = eina_stringshare_add(text);
5635    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5636                                            text,
5637                                            _elm_genlist_item_label_del_cb);
5638 }
5639
5640 EAPI void
5641 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item            *it,
5642                                         Elm_Tooltip_Item_Content_Cb func,
5643                                         const void                 *data,
5644                                         Evas_Smart_Cb               del_cb)
5645 {
5646    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5647    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5648
5649    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5650      return;
5651
5652    if (_it->tooltip.del_cb)
5653      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5654
5655    _it->tooltip.content_cb = func;
5656    _it->tooltip.data = data;
5657    _it->tooltip.del_cb = del_cb;
5658
5659    if (VIEW(_it))
5660      {
5661         elm_widget_item_tooltip_content_cb_set(_it,
5662                                                _it->tooltip.content_cb,
5663                                                _it->tooltip.data, NULL);
5664         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5665         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5666      }
5667
5668    return;
5669
5670 error:
5671    if (del_cb) del_cb((void *)data, NULL, NULL);
5672 }
5673
5674 EAPI void
5675 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5676 {
5677    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5678    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5679
5680    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5681      elm_widget_item_tooltip_unset(_it);
5682
5683    if (_it->tooltip.del_cb)
5684      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5685    _it->tooltip.del_cb = NULL;
5686    _it->tooltip.content_cb = NULL;
5687    _it->tooltip.data = NULL;
5688    _it->tooltip.free_size = EINA_FALSE;
5689    if (_it->tooltip.style)
5690      elm_genlist_item_tooltip_style_set(it, NULL);
5691 }
5692
5693 EAPI void
5694 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5695                                    const char       *style)
5696 {
5697    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5698    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5699
5700    eina_stringshare_replace(&_it->tooltip.style, style);
5701    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5702 }
5703
5704 EAPI const char *
5705 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5706 {
5707    return elm_object_item_tooltip_style_get(it);
5708 }
5709
5710 EAPI Eina_Bool
5711 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5712                                          Eina_Bool        disable)
5713 {
5714    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5715    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5716
5717    _it->tooltip.free_size = disable;
5718    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5719    return EINA_TRUE;
5720 }
5721
5722 EAPI Eina_Bool
5723 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5724 {
5725    return elm_object_tooltip_window_mode_get(VIEW(it));
5726 }
5727
5728 EAPI void
5729 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5730                             const char       *cursor)
5731 {
5732    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5733    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5734    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5735    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5736 }
5737
5738 EAPI const char *
5739 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5740 {
5741    return elm_widget_item_cursor_get(it);
5742 }
5743
5744 EAPI void
5745 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5746 {
5747    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5748    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5749
5750    if (!_it->mouse_cursor) return;
5751
5752    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5753
5754    eina_stringshare_del(_it->mouse_cursor);
5755    _it->mouse_cursor = NULL;
5756 }
5757
5758 EAPI void
5759 elm_genlist_item_cursor_style_set(Elm_Object_Item *it,
5760                                   const char      *style)
5761 {
5762    elm_widget_item_cursor_style_set(it, style);
5763 }
5764
5765 EAPI const char *
5766 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5767 {
5768    return elm_widget_item_cursor_style_get(it);
5769 }
5770
5771 EAPI void
5772 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5773                                         Eina_Bool        engine_only)
5774 {
5775    elm_widget_item_cursor_engine_only_set(it, engine_only);
5776 }
5777
5778 EAPI Eina_Bool
5779 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5780 {
5781    return elm_widget_item_cursor_engine_only_get(it);
5782 }
5783
5784 EAPI int
5785 elm_genlist_item_index_get(const Elm_Object_Item *it)
5786 {
5787    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5788    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5789
5790    if (_it->item->block)
5791      return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5792    return -1;
5793 }
5794
5795 EAPI void
5796 elm_genlist_mode_set(Evas_Object  *obj,
5797                      Elm_List_Mode mode)
5798 {
5799    ELM_CHECK_WIDTYPE(obj, widtype);
5800    Widget_Data *wd = elm_widget_data_get(obj);
5801    if (!wd) return;
5802    if (wd->mode == mode) return;
5803    wd->mode = mode;
5804    _sizing_eval(obj);
5805 }
5806
5807
5808 EAPI Elm_List_Mode
5809 elm_genlist_mode_get(const Evas_Object *obj)
5810 {
5811    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5812    Widget_Data *wd = elm_widget_data_get(obj);
5813    if (!wd) return ELM_LIST_LAST;
5814    return wd->mode;
5815 }
5816
5817 EAPI void
5818 elm_genlist_bounce_set(Evas_Object *obj,
5819                        Eina_Bool    h_bounce,
5820                        Eina_Bool    v_bounce)
5821 {
5822    ELM_CHECK_WIDTYPE(obj, widtype);
5823    Widget_Data *wd = elm_widget_data_get(obj);
5824    if (!wd) return;
5825    wd->h_bounce = !!h_bounce;
5826    wd->v_bounce = !!v_bounce;
5827    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5828 }
5829
5830 EAPI void
5831 elm_genlist_bounce_get(const Evas_Object *obj,
5832                        Eina_Bool         *h_bounce,
5833                        Eina_Bool         *v_bounce)
5834 {
5835    ELM_CHECK_WIDTYPE(obj, widtype);
5836    Widget_Data *wd = elm_widget_data_get(obj);
5837    if (!wd) return;
5838    if (h_bounce) *h_bounce = wd->h_bounce;
5839    if (v_bounce) *v_bounce = wd->v_bounce;
5840 }
5841
5842 EAPI void
5843 elm_genlist_homogeneous_set(Evas_Object *obj,
5844                             Eina_Bool    homogeneous)
5845 {
5846    ELM_CHECK_WIDTYPE(obj, widtype);
5847    Widget_Data *wd = elm_widget_data_get(obj);
5848    if (!wd) return;
5849    wd->homogeneous = !!homogeneous;
5850 }
5851
5852 EAPI Eina_Bool
5853 elm_genlist_homogeneous_get(const Evas_Object *obj)
5854 {
5855    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5856    Widget_Data *wd = elm_widget_data_get(obj);
5857    if (!wd) return EINA_FALSE;
5858    return wd->homogeneous;
5859 }
5860
5861 EAPI void
5862 elm_genlist_block_count_set(Evas_Object *obj,
5863                             int          count)
5864 {
5865    ELM_CHECK_WIDTYPE(obj, widtype);
5866    Widget_Data *wd = elm_widget_data_get(obj);
5867    if (!wd) return;
5868    wd->max_items_per_block = count;
5869    wd->item_cache_max = wd->max_items_per_block * 2;
5870    _item_cache_clean(wd);
5871 }
5872
5873 EAPI int
5874 elm_genlist_block_count_get(const Evas_Object *obj)
5875 {
5876    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5877    Widget_Data *wd = elm_widget_data_get(obj);
5878    if (!wd) return 0;
5879    return wd->max_items_per_block;
5880 }
5881
5882 EAPI void
5883 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5884                                   double       timeout)
5885 {
5886    ELM_CHECK_WIDTYPE(obj, widtype);
5887    Widget_Data *wd = elm_widget_data_get(obj);
5888    if (!wd) return;
5889    wd->longpress_timeout = timeout;
5890 }
5891
5892 EAPI double
5893 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5894 {
5895    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5896    Widget_Data *wd = elm_widget_data_get(obj);
5897    if (!wd) return 0;
5898    return wd->longpress_timeout;
5899 }
5900
5901 EAPI void
5902 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5903                                 Elm_Scroller_Policy policy_h,
5904                                 Elm_Scroller_Policy policy_v)
5905 {
5906    ELM_CHECK_WIDTYPE(obj, widtype);
5907    Widget_Data *wd = elm_widget_data_get(obj);
5908    if ((!wd) || (!wd->scr)) return;
5909    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5910        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5911      return;
5912    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5913 }
5914
5915 EAPI void
5916 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5917                                 Elm_Scroller_Policy *policy_h,
5918                                 Elm_Scroller_Policy *policy_v)
5919 {
5920    ELM_CHECK_WIDTYPE(obj, widtype);
5921    Widget_Data *wd = elm_widget_data_get(obj);
5922    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5923    if ((!wd) || (!wd->scr)) return;
5924    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5925    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5926    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5927 }
5928
5929 EAPI void
5930 elm_genlist_realized_items_update(Evas_Object *obj)
5931 {
5932    ELM_CHECK_WIDTYPE(obj, widtype);
5933
5934    Eina_List *list, *l;
5935    Elm_Object_Item *it;
5936
5937    list = elm_genlist_realized_items_get(obj);
5938    EINA_LIST_FOREACH(list, l, it)
5939      elm_genlist_item_update(it);
5940 }
5941
5942 EAPI void
5943 elm_genlist_item_decorate_mode_set(Elm_Object_Item *it,
5944                                    const char      *decorate_it_type,
5945                                    Eina_Bool        decorate_it_set)
5946 {
5947    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5948    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5949
5950    Widget_Data *wd = _it->wd;
5951    Eina_List *l;
5952    Elm_Object_Item *it2;
5953
5954    if (!wd) return;
5955    if (!decorate_it_type) return;
5956    if ((_it->generation < _it->wd->generation) ||
5957        elm_widget_item_disabled_get(_it)) return;
5958    if (wd->decorate_all_mode) return;
5959
5960    if ((wd->mode_item == _it) &&
5961        (!strcmp(decorate_it_type, wd->decorate_it_type)) &&
5962        (decorate_it_set))
5963       return;
5964    if (!_it->itc->decorate_item_style) return;
5965    _it->decorate_it_set = decorate_it_set;
5966
5967    if (wd->multi)
5968      {
5969         EINA_LIST_FOREACH(wd->selected, l, it2)
5970           if (((Elm_Gen_Item *)it2)->realized)
5971             elm_genlist_item_selected_set(it2, EINA_FALSE);
5972      }
5973    else
5974      {
5975         it2 = elm_genlist_selected_item_get(wd->obj);
5976         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5977           elm_genlist_item_selected_set(it2, EINA_FALSE);
5978      }
5979
5980    if (((wd->decorate_it_type) && (strcmp(decorate_it_type, wd->decorate_it_type))) ||
5981        (decorate_it_set) || ((_it == wd->mode_item) && (!decorate_it_set)))
5982      _decorate_item_unset(wd);
5983
5984    eina_stringshare_replace(&wd->decorate_it_type, decorate_it_type);
5985    if (decorate_it_set) _decorate_item_set(_it);
5986 }
5987
5988 EAPI const char *
5989 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5990 {
5991    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5992    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5993    return _it->wd->decorate_it_type;
5994 }
5995
5996 EAPI const Elm_Object_Item *
5997 elm_genlist_decorated_item_get(const Evas_Object *obj)
5998 {
5999    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
6000    Widget_Data *wd = elm_widget_data_get(obj);
6001    if (!wd) return NULL;
6002    return (Elm_Object_Item *) wd->mode_item;
6003 }
6004
6005 EAPI Eina_Bool
6006 elm_genlist_decorate_mode_get(const Evas_Object *obj)
6007 {
6008    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6009    Widget_Data *wd = elm_widget_data_get(obj);
6010    if (!wd) return EINA_FALSE;
6011
6012    return wd->decorate_all_mode;
6013 }
6014
6015 EAPI void
6016 elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
6017 {
6018    ELM_CHECK_WIDTYPE(obj, widtype);
6019    Eina_List *list, *l;
6020    Elm_Gen_Item *it;
6021
6022    Widget_Data *wd = elm_widget_data_get(obj);
6023    if (!wd) return;
6024    decorated = !!decorated;
6025    if (wd->decorate_all_mode == decorated) return;
6026    wd->decorate_all_mode = decorated;
6027
6028    if (wd->tree_effect_animator)
6029      {
6030         ecore_animator_del(wd->tree_effect_animator);
6031         wd->tree_effect_animator = NULL;
6032      }
6033    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6034
6035    list = elm_genlist_realized_items_get(obj);
6036    if (!wd->decorate_all_mode)
6037      {
6038         EINA_LIST_FOREACH(list, l, it)
6039           {
6040              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6041                _decorate_all_item_unrealize(it);
6042           }
6043         _item_cache_zero(wd);
6044      }
6045    else
6046      {
6047         EINA_LIST_FOREACH(list, l, it)
6048           {
6049              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6050                {
6051                   if (it->itc->decorate_all_item_style)
6052                      _decorate_all_item_realize(it, EINA_TRUE);
6053                }
6054           }
6055      }
6056    if (wd->calc_job) ecore_job_del(wd->calc_job);
6057    wd->calc_job = ecore_job_add(_calc_job, wd);
6058 }
6059
6060 EAPI void
6061 elm_genlist_reorder_mode_set(Evas_Object *obj,
6062                              Eina_Bool    reorder_mode)
6063 {
6064    ELM_CHECK_WIDTYPE(obj, widtype);
6065    Widget_Data *wd = elm_widget_data_get(obj);
6066    if (!wd) return;
6067    wd->reorder_mode = !!reorder_mode;
6068 }
6069
6070 EAPI Eina_Bool
6071 elm_genlist_reorder_mode_get(const Evas_Object *obj)
6072 {
6073    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6074    Widget_Data *wd = elm_widget_data_get(obj);
6075    if (!wd) return EINA_FALSE;
6076    return wd->reorder_mode;
6077 }
6078
6079 EAPI Elm_Genlist_Item_Type
6080 elm_genlist_item_type_get(const Elm_Object_Item *it)
6081 {
6082    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
6083    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6084    return _it->item->type;
6085 }
6086
6087 EAPI Elm_Genlist_Item_Class *
6088 elm_genlist_item_class_new(void)
6089 {
6090    Elm_Genlist_Item_Class *itc;
6091
6092    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
6093    if (!itc)
6094      return NULL;
6095    itc->version = CLASS_ALLOCATED;
6096    itc->refcount = 1;
6097    itc->delete_me = EINA_FALSE;
6098
6099    return itc;
6100 }
6101
6102 EAPI void
6103 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
6104 {
6105    if (itc && (itc->version == CLASS_ALLOCATED))
6106      {
6107         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
6108         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
6109         else
6110           {
6111              itc->version = 0;
6112              free(itc);
6113           }
6114      }
6115 }
6116
6117 EAPI void
6118 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
6119 {
6120    if (itc && (itc->version == CLASS_ALLOCATED))
6121      {
6122         itc->refcount++;
6123         if (itc->refcount == 0) itc->refcount--;
6124      }
6125 }
6126
6127 EAPI void
6128 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
6129 {
6130    if (itc && (itc->version == CLASS_ALLOCATED))
6131      {
6132         if (itc->refcount > 0) itc->refcount--;
6133         if (itc->delete_me && (!itc->refcount))
6134           elm_genlist_item_class_free(itc);
6135      }
6136 }
6137
6138 void _flip_job(void *data)
6139 {
6140    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
6141    _item_unhighlight(it);
6142    _item_unselect(it);
6143    _elm_genlist_item_unrealize(it, EINA_FALSE);
6144    it->flipped = EINA_TRUE;
6145    it->item->nocache = EINA_TRUE;
6146    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
6147    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
6148 }
6149
6150 EAPI void
6151 elm_genlist_item_flip_set(Elm_Object_Item *it,
6152                           Eina_Bool flip)
6153 {
6154    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6155    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6156
6157    flip = !!flip;
6158    if (_it->flipped == flip) return;
6159
6160    if (flip)
6161      {
6162         ecore_job_add(_flip_job, _it);
6163      }
6164    else
6165      {
6166         _it->flipped = flip;
6167         _item_cache_zero(_it->wd);
6168         elm_genlist_item_update(it);
6169         _it->item->nocache = EINA_FALSE;
6170      }
6171 }
6172
6173 EAPI Eina_Bool
6174 elm_genlist_item_flip_get(const Elm_Object_Item *it)
6175 {
6176    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
6177    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6178    return _it->flipped;
6179 }
6180
6181 EAPI void
6182 elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
6183 {
6184    ELM_CHECK_WIDTYPE(obj, widtype);
6185    Widget_Data *wd = elm_widget_data_get(obj);
6186    if (!wd) return;
6187    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6188      return;
6189    if (wd->select_mode != mode)
6190      wd->select_mode = mode;
6191 }
6192
6193 EAPI Elm_Object_Select_Mode
6194 elm_genlist_select_mode_get(const Evas_Object *obj)
6195 {
6196    ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
6197    Widget_Data *wd = elm_widget_data_get(obj);
6198    if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
6199    return wd->select_mode;
6200 }
6201
6202 EAPI void
6203 elm_genlist_highlight_mode_set(Evas_Object *obj,
6204                                Eina_Bool    highlight)
6205 {
6206    ELM_CHECK_WIDTYPE(obj, widtype);
6207    Widget_Data *wd = elm_widget_data_get(obj);
6208    if (!wd) return;
6209    wd->highlight = !!highlight;
6210 }
6211
6212 EAPI Eina_Bool
6213 elm_genlist_highlight_mode_get(const Evas_Object *obj)
6214 {
6215    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6216    Widget_Data *wd = elm_widget_data_get(obj);
6217    if (!wd) return EINA_FALSE;
6218    return wd->highlight;
6219 }
6220
6221 EAPI void
6222 elm_genlist_item_select_mode_set(Elm_Object_Item       *it,
6223                                  Elm_Object_Select_Mode mode)
6224 {
6225    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6226    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6227    if (!_it) return;
6228    if (_it->generation < _it->wd->generation) return;
6229    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6230      return;
6231    if (_it->select_mode != mode)
6232      _it->select_mode = mode;
6233
6234    if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
6235      {
6236         _it->item->mincalcd = EINA_FALSE;
6237         _it->item->updateme = EINA_TRUE;
6238         if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
6239         if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
6240         _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
6241      }
6242 }
6243
6244 EAPI Elm_Object_Select_Mode
6245 elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
6246 {
6247    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
6248    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6249    if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
6250    return _it->select_mode;
6251 }
6252
6253 /* for gengrid as of now */
6254 void
6255 _elm_genlist_page_relative_set(Evas_Object *obj,
6256                                double       h_pagerel,
6257                                double       v_pagerel)
6258 {
6259    Evas_Coord pagesize_h;
6260    Evas_Coord pagesize_v;
6261
6262    ELM_CHECK_WIDTYPE(obj, widtype);
6263    Widget_Data *wd = elm_widget_data_get(obj);
6264    if (!wd) return;
6265
6266    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
6267    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
6268                                  pagesize_v);
6269 }
6270
6271 /* for gengrid as of now */
6272 void
6273 _elm_genlist_page_relative_get(const Evas_Object *obj,
6274                                double            *h_pagerel,
6275                                double            *v_pagerel)
6276 {
6277    ELM_CHECK_WIDTYPE(obj, widtype);
6278    Widget_Data *wd = elm_widget_data_get(obj);
6279    if (!wd) return;
6280
6281    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
6282 }
6283
6284 /* for gengrid as of now */
6285 void
6286 _elm_genlist_page_size_set(Evas_Object *obj,
6287                            Evas_Coord   h_pagesize,
6288                            Evas_Coord   v_pagesize)
6289 {
6290    double pagerel_h;
6291    double pagerel_v;
6292
6293    ELM_CHECK_WIDTYPE(obj, widtype);
6294    Widget_Data *wd = elm_widget_data_get(obj);
6295    if (!wd) return;
6296    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
6297    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
6298                                  v_pagesize);
6299 }
6300
6301 /* for gengrid as of now */
6302 void
6303 _elm_genlist_current_page_get(const Evas_Object *obj,
6304                               int               *h_pagenumber,
6305                               int               *v_pagenumber)
6306 {
6307    ELM_CHECK_WIDTYPE(obj, widtype);
6308    Widget_Data *wd = elm_widget_data_get(obj);
6309    if (!wd) return;
6310    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
6311 }
6312
6313 /* for gengrid as of now */
6314 void
6315 _elm_genlist_last_page_get(const Evas_Object *obj,
6316                            int               *h_pagenumber,
6317                            int               *v_pagenumber)
6318 {
6319    ELM_CHECK_WIDTYPE(obj, widtype);
6320    Widget_Data *wd = elm_widget_data_get(obj);
6321    if (!wd) return;
6322    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
6323 }
6324
6325 /* for gengrid as of now */
6326 void
6327 _elm_genlist_page_show(const Evas_Object *obj,
6328                        int                h_pagenumber,
6329                        int                v_pagenumber)
6330 {
6331    ELM_CHECK_WIDTYPE(obj, widtype);
6332    Widget_Data *wd = elm_widget_data_get(obj);
6333    if (!wd) return;
6334    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
6335 }
6336
6337 /* for gengrid as of now */
6338 void
6339 _elm_genlist_page_bring_in(const Evas_Object *obj,
6340                            int                h_pagenumber,
6341                            int                v_pagenumber)
6342 {
6343    ELM_CHECK_WIDTYPE(obj, widtype);
6344    Widget_Data *wd = elm_widget_data_get(obj);
6345    if (!wd) return;
6346    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
6347 }
6348
6349 void
6350 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
6351                             Eina_Bool     calc)
6352 {
6353    Evas_Object *content;
6354
6355    if (!it->realized) return;
6356    if (it->wd->reorder_it == it) return;
6357    if (it->defer_unrealize && !it->item->updateme) return;
6358
6359    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
6360    if (!calc)
6361      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
6362    if (it->long_timer)
6363      {
6364         ecore_timer_del(it->long_timer);
6365         it->long_timer = NULL;
6366      }
6367
6368    elm_widget_stringlist_free(it->texts);
6369    it->texts = NULL;
6370    elm_widget_stringlist_free(it->contents);
6371    it->contents = NULL;
6372    elm_widget_stringlist_free(it->states);
6373    it->states = NULL;
6374    EINA_LIST_FREE(it->content_objs, content)
6375      evas_object_del(content);
6376
6377    it->unrealize_cb(it);
6378
6379    it->realized = EINA_FALSE;
6380    it->want_unrealize = EINA_FALSE;
6381    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
6382    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
6383 }
6384
6385 void
6386 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
6387 {
6388    elm_widget_item_pre_notify_del(it);
6389    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
6390
6391    if ((it->relcount > 0) || (it->walking > 0)) return;
6392
6393    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
6394
6395    if (it->itc->func.del)
6396      it->itc->func.del((void *)it->base.data, WIDGET(it));
6397 }
6398
6399 void
6400 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
6401 {
6402    _elm_genlist_item_del_notserious(it);
6403    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
6404    if (it->tooltip.del_cb)
6405      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6406    it->wd->walking -= it->walking;
6407    if (it->long_timer)
6408      {
6409         ecore_timer_del(it->long_timer);
6410         it->long_timer = NULL;
6411      }
6412    if (it->group)
6413      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
6414
6415    if (it->wd->state)
6416      {
6417         eina_inlist_sorted_state_free(it->wd->state);
6418         it->wd->state = NULL;
6419      }
6420    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
6421    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
6422    free(it->item);
6423
6424    it->item = NULL;
6425    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
6426      it->wd->last_selected_item = NULL;
6427    it->wd->item_count--;
6428 }
6429
6430 EAPI void
6431 elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
6432 {
6433    ELM_CHECK_WIDTYPE(obj, widtype);
6434    Widget_Data *wd = elm_widget_data_get(obj);
6435    if (!wd) return;
6436    wd->tree_effect_enabled = !!enabled;
6437 }
6438
6439 EAPI Eina_Bool
6440 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
6441 {
6442    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6443    Widget_Data *wd = elm_widget_data_get(obj);
6444    if (!wd) return EINA_FALSE;
6445    return wd->tree_effect_enabled;
6446 }
6447
6448 static Evas_Object*
6449 _create_tray_alpha_bg(const Evas_Object *obj)
6450 {
6451    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
6452    Widget_Data *wd = elm_widget_data_get(obj);
6453    if (!wd) return NULL;
6454
6455    Evas_Object *bg = NULL;
6456    Evas_Coord ox, oy, ow, oh;
6457
6458    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6459    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
6460    evas_object_color_set(bg,0,0,0,0);
6461    evas_object_resize(bg , ow, oh);
6462    evas_object_move(bg , ox, oy);
6463    return bg ;
6464 }
6465
6466 static void
6467 _item_contract_emit(Elm_Gen_Item *it)
6468 {
6469    Elm_Gen_Item *it2;
6470    Eina_List *l;
6471
6472    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
6473    it->item->tree_effect_finished = EINA_FALSE;
6474
6475    EINA_LIST_FOREACH(it->item->items, l, it2)
6476      if (it2) _item_contract_emit(it2);
6477 }
6478
6479 static int
6480 _item_tree_effect_before(Elm_Gen_Item *it)
6481 {
6482    Elm_Gen_Item *it2;
6483    Eina_List *l;
6484
6485    EINA_LIST_FOREACH(it->item->items, l, it2)
6486      {
6487         if (it2->parent && (it == it2->parent))
6488           {
6489              if (!it2->realized)
6490                it2->item->tree_effect_hideme = EINA_TRUE;
6491              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6492                edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
6493              else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6494                _item_contract_emit(it2);
6495           }
6496      }
6497    return ECORE_CALLBACK_CANCEL;
6498 }
6499
6500 static void
6501 _item_tree_effect(Widget_Data *wd, int y)
6502 {
6503    Elm_Gen_Item *it = NULL, *expanded_next_it;
6504
6505    expanded_next_it = wd->expanded_next_item;
6506
6507    if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6508      {
6509         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6510         while (it)
6511           {
6512              if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
6513              if (it->item->scrl_y && (it->item->scrl_y <= expanded_next_it->item->old_scrl_y + y) &&
6514                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6515                {
6516                   if (!it->item->tree_effect_finished)
6517                     {
6518                        edje_object_signal_emit(VIEW(it), "flip_item", "");
6519                        _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6520                        it->item->tree_effect_finished = EINA_TRUE;
6521                     }
6522                }
6523              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6524           }
6525      }
6526    else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6527      {
6528         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6529         while (it)
6530           {
6531              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
6532                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6533                {
6534                   if (!it->item->tree_effect_finished)
6535                     {
6536                        edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
6537                        it->item->tree_effect_finished = EINA_TRUE;
6538                     }
6539                }
6540              else
6541                break;
6542              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6543           }
6544      }
6545 }
6546
6547 static void
6548 _item_tree_effect_finish(Widget_Data *wd)
6549 {
6550    Elm_Gen_Item *it = NULL;
6551    const Eina_List *l;
6552
6553    if (wd->tree_effect_animator)
6554      {
6555         if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6556           _item_subitems_clear(wd->expanded_item);
6557         EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
6558           {
6559              it->item->tree_effect_finished = EINA_TRUE;
6560              it->item->old_scrl_y = it->item->scrl_y;
6561              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6562                edje_object_signal_emit(VIEW(it), "elm,state,show", "");
6563           }
6564      }
6565    _item_auto_scroll(wd);
6566    evas_object_lower(wd->alpha_bg);
6567    evas_object_hide(wd->alpha_bg);
6568    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6569    if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
6570
6571    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
6572    evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
6573    evas_object_smart_changed(wd->pan_smart);
6574
6575    wd->tree_effect_animator = NULL;
6576 }
6577
6578 static Eina_Bool
6579 _tree_effect_animator_cb(void *data)
6580 {
6581    Widget_Data *wd = data;
6582    if (!wd) return ECORE_CALLBACK_CANCEL;
6583    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
6584    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
6585    const Eina_List *l;
6586    double effect_duration = 0.3, t;
6587    int y = 0, dy = 0, dh = 0;
6588    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
6589    int in = 0;
6590
6591    t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
6592    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6593    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
6594    if (t > effect_duration) end = EINA_TRUE;
6595
6596    // Below while statement is needed, when the genlist is resized.
6597    it2 = wd->expanded_item;
6598    while (it2 && vis)
6599      {
6600         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
6601         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
6602                                    cvx, cvy, cvw, cvh));
6603         it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
6604      }
6605
6606    if (wd->expanded_next_item)
6607      {
6608         expanded_next_it = wd->expanded_next_item;
6609
6610         /* move items */
6611         EINA_LIST_FOREACH(wd->move_items, l, it)
6612           {
6613              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6614                {
6615                   expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6616                   if (expanded_next_it->item->scrl_y <= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6617                     expanded_next_it->item->scrl_y = cvy + cvh;
6618
6619                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6620                          cvy + cvh : expanded_next_it->item->scrl_y) -
6621                          expanded_next_it->item->old_scrl_y;
6622                }
6623              else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6624                {
6625                   if (expanded_next_it->item->scrl_y >= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6626                      expanded_next_it->item->old_scrl_y = cvy + cvh;
6627
6628                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6629                     {
6630                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6631                        cvy + cvh;
6632                        expanded_next_it->item->old_scrl_y = cvy + cvh;
6633                     }
6634                   else
6635                     {
6636                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6637                              expanded_next_it->item->old_scrl_y;
6638                     }
6639                }
6640
6641              if (t <= effect_duration)
6642                {
6643                   y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6644                }
6645              else
6646                {
6647                   end = EINA_TRUE;
6648                   y = dy;
6649                }
6650
6651              if (!it->realized && !it->item->queued)
6652                _item_realize(it, in, 0);
6653              in++;
6654
6655              if (it != expanded_next_it)
6656                {
6657                   it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6658                   dh += it->item->h;
6659                }
6660
6661              if ((it->item->old_scrl_y + y) < (cvy + cvh))
6662                _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6663           }
6664         /* tree effect */
6665         _item_tree_effect(wd, y);
6666      }
6667    else
6668      {
6669         int expanded_item_num = 0;
6670         int num = 0;
6671
6672         if (wd->expanded_item)
6673           it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6674
6675         it2 = it;
6676         while (it2)
6677           {
6678              expanded_item_num++;
6679              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6680           }
6681
6682         while (it)
6683           {
6684              num++;
6685              if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6686              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6687                {
6688                   if (!it->item->tree_effect_finished)
6689                     {
6690                        if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6691                          {
6692                             edje_object_signal_emit(VIEW(it), "flip_item", "");
6693                             _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6694                             it->item->tree_effect_finished = EINA_TRUE;
6695                          }
6696                     }
6697                }
6698              it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6699           }
6700      }
6701
6702    if (end)
6703      {
6704         _item_tree_effect_finish(wd);
6705         return ECORE_CALLBACK_CANCEL;
6706      }
6707    return ECORE_CALLBACK_RENEW;
6708 }