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