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