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