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