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