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