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