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