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