ed2bef97515506da8648ed04f4223d5a9c22d395
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2 #include <fnmatch.h>
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_gen_common.h"
8
9 // internally allocated
10 #define CLASS_ALLOCATED 0x3a70f11f
11
12 #define MAX_ITEMS_PER_BLOCK 32
13 #define REORDER_EFFECT_TIME 0.5
14
15 #define ELM_GEN_SETUP(wd) \
16    (wd)->calc_cb = (Ecore_Cb)_calc_job; \
17    (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
18    (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
19
20 #define ELM_GEN_ITEM_SETUP(it) \
21    (it)->del_cb = (Ecore_Cb)_item_del; \
22    (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
23    (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
24    (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
25    (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
26
27 #define ELM_GENLIST_CHECK_ITC_VER(itc) \
28    do \
29      { \
30         if (!itc) \
31           { \
32              ERR("Genlist_Item_Class(itc) is NULL"); \
33              return; \
34           } \
35         if ((itc->version != ELM_GENLIST_ITEM_CLASS_VERSION) && \
36             (itc->version != CLASS_ALLOCATED)) \
37           { \
38              ERR("Genlist_Item_Class version mismatched! current = (%d), required = (%d) or (%d)", itc->version, ELM_GENLIST_ITEM_CLASS_VERSION, CLASS_ALLOCATED); \
39              return; \
40           } \
41      } \
42    while (0)
43
44 typedef struct _Item_Block  Item_Block;
45 typedef struct _Item_Cache  Item_Cache;
46
47 struct Elm_Gen_Item_Type
48 {
49    Elm_Gen_Item                 *it;
50    Item_Block                   *block;
51    Eina_List                    *items;
52    Evas_Coord                    w, h, minw, minh;
53    Elm_Gen_Item                 *group_item;
54    Elm_Genlist_Item_Type        type;
55    Eina_List                    *deco_it_texts, *deco_it_contents, *deco_it_states, *deco_it_content_objs;
56    Eina_List                    *deco_all_texts, *deco_all_contents, *deco_all_states, *deco_all_content_objs;
57    Eina_List                    *flip_contents, *flip_content_objs;
58    Ecore_Timer                  *swipe_timer;
59    Evas_Coord                    scrl_x, scrl_y, old_scrl_y;
60
61    Elm_Gen_Item                 *rel;
62    Evas_Object                  *deco_it_view;
63    int                           expanded_depth;
64    int                           order_num_in;
65
66    Eina_Bool                     before : 1;
67
68    Eina_Bool                     want_realize : 1;
69    Eina_Bool                     expanded : 1;
70    Eina_Bool                     mincalcd : 1;
71    Eina_Bool                     queued : 1;
72    Eina_Bool                     showme : 1;
73    Eina_Bool                     updateme : 1;
74    Eina_Bool                     nocache : 1; /* do not use cache for this item */
75    Eina_Bool                     nocache_once : 1; /* do not use cache for this item only once */
76    Eina_Bool                     stacking_even : 1;
77    Eina_Bool                     nostacking : 1;
78    Eina_Bool                     move_effect_enabled : 1;
79    Eina_Bool                     decorate_all_item_realized : 1;
80    Eina_Bool                     tree_effect_finished : 1; /* tree effect */
81    Eina_Bool                     tree_effect_hideme : 1; /* item hide for tree effect */
82 };
83
84 struct _Item_Block
85 {
86    EINA_INLIST;
87    int          count;
88    int          num;
89    int          reorder_offset;
90    Widget_Data *wd;
91    Eina_List   *items;
92    Evas_Coord   x, y, w, h, minw, minh;
93    int          position;
94    int          item_position_stamp;
95
96    Eina_Bool    position_update : 1;
97    Eina_Bool    want_unrealize : 1;
98    Eina_Bool    realized : 1;
99    Eina_Bool    changed : 1;
100    Eina_Bool    updateme : 1;
101    Eina_Bool    changeme : 1;
102    Eina_Bool    showme : 1;
103    Eina_Bool    must_recalc : 1;
104 };
105
106 struct _Item_Cache
107 {
108    EINA_INLIST;
109
110    Evas_Object *base_view, *spacer;
111
112    const char  *item_style; // it->itc->item_style
113    Eina_Bool    tree : 1; // it->group
114
115    Eina_Bool    selected : 1; // it->selected
116    Eina_Bool    disabled : 1; // it->disabled
117    Eina_Bool    expanded : 1; // it->item->expanded
118 };
119
120 static const char *widtype = NULL;
121 static void      _item_cache_zero(Widget_Data *wd);
122 static void      _del_hook(Evas_Object *obj);
123 static void      _mirrored_set(Evas_Object *obj,
124                                Eina_Bool    rtl);
125 static void      _theme_hook(Evas_Object *obj);
126 static void      _show_region_hook(void        *data,
127                                    Evas_Object *obj);
128 static void      _sizing_eval(Evas_Object *obj);
129 static void      _item_realize(Elm_Gen_Item *it,
130                                int           in,
131                                Eina_Bool     calc);
132 static void      _item_unrealize_cb(Elm_Gen_Item *it);
133 static void      _item_block_unrealize(Item_Block *itb);
134 static void      _calc_job(void *data);
135 static void      _on_focus_hook(void        *data,
136                                 Evas_Object *obj);
137 static void      _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
138 static void      _changed_job(void *data);
139 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
140 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
141 static Eina_Bool _item_single_select_up(Widget_Data *wd);
142 static Eina_Bool _item_single_select_down(Widget_Data *wd);
143 static Eina_Bool _event_hook(Evas_Object       *obj,
144                              Evas_Object       *src,
145                              Evas_Callback_Type type,
146                              void              *event_info);
147 static void      _signal_emit_hook(Evas_Object *obj,
148                                    const char  *emission,
149                                    const char  *source);
150 static Eina_Bool _deselect_all_items(Widget_Data *wd);
151 static void      _pan_calculate(Evas_Object *obj);
152 static void      _pan_max_get(Evas_Object *obj,
153                               Evas_Coord  *x,
154                               Evas_Coord  *y);
155 static void      _item_position(Elm_Gen_Item *it,
156                                 Evas_Object  *obj,
157                                 Evas_Coord    it_x,
158                                 Evas_Coord    it_y);
159 static void      _decorate_item_realize(Elm_Gen_Item *it);
160 static void      _decorate_item_unrealize(Elm_Gen_Item *it);
161 static void      _decorate_item_set(Elm_Gen_Item *it);
162 static void      _decorate_item_unset(Widget_Data *wd);
163 static void      _decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity);
164 static void      _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on);
165 static void      _decorate_all_item_unrealize(Elm_Gen_Item *it);
166 //FIXME: group raise
167 #if 0
168 static void      _group_items_recalc(void *data);
169 #endif
170 static void      _item_move_after(Elm_Gen_Item *it,
171                                   Elm_Gen_Item *after);
172 static void      _item_move_before(Elm_Gen_Item *it,
173                                    Elm_Gen_Item *before);
174 static void      _item_auto_scroll(Widget_Data *wd);
175 static void      _elm_genlist_clear(Evas_Object *obj,
176                                     Eina_Bool    standby);
177 static void      _pan_child_size_get(Evas_Object *obj,
178                                      Evas_Coord  *w,
179                                      Evas_Coord  *h);
180 static Evas_Object* _create_tray_alpha_bg(const Evas_Object *obj);
181 static void         _item_contract_emit(Elm_Gen_Item *it);
182 static int          _item_tree_effect_before(Elm_Gen_Item *it);
183 static void         _item_tree_effect(Widget_Data *wd, int y);
184 static void         _item_tree_effect_finish(Widget_Data *wd);
185 static Eina_Bool    _tree_effect_animator_cb(void *data);
186
187 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
188
189 static const char SIG_ACTIVATED[] = "activated";
190 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
191 static const char SIG_SELECTED[] = "selected";
192 static const char SIG_UNSELECTED[] = "unselected";
193 static const char SIG_EXPANDED[] = "expanded";
194 static const char SIG_CONTRACTED[] = "contracted";
195 static const char SIG_EXPAND_REQUEST[] = "expand,request";
196 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
197 static const char SIG_REALIZED[] = "realized";
198 static const char SIG_UNREALIZED[] = "unrealized";
199 static const char SIG_DRAG_START_UP[] = "drag,start,up";
200 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
201 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
202 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
203 static const char SIG_DRAG_STOP[] = "drag,stop";
204 static const char SIG_DRAG[] = "drag";
205 static const char SIG_LONGPRESSED[] = "longpressed";
206 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
207 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
208 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
209 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
210 static const char SIG_EDGE_TOP[] = "edge,top";
211 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
212 static const char SIG_EDGE_LEFT[] = "edge,left";
213 static const char SIG_EDGE_RIGHT[] = "edge,right";
214 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
215 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
216 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
217 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
218 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
219 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
220 static const char SIG_SWIPE[] = "swipe";
221 static const char SIG_MOVED[] = "moved";
222 static const char SIG_MOVED_AFTER[] = "moved,after";
223 static const char SIG_MOVED_BEFORE[] = "moved,before";
224 static const char SIG_INDEX_UPDATE[] = "index,update";
225 static const char SIG_TREE_EFFECT_FINISHED [] = "tree,effect,finished";
226
227 static const Evas_Smart_Cb_Description _signals[] = {
228    {SIG_CLICKED_DOUBLE, ""},
229    {SIG_ACTIVATED, ""},
230    {SIG_SELECTED, ""},
231    {SIG_UNSELECTED, ""},
232    {SIG_EXPANDED, ""},
233    {SIG_CONTRACTED, ""},
234    {SIG_EXPAND_REQUEST, ""},
235    {SIG_CONTRACT_REQUEST, ""},
236    {SIG_REALIZED, ""},
237    {SIG_UNREALIZED, ""},
238    {SIG_DRAG_START_UP, ""},
239    {SIG_DRAG_START_DOWN, ""},
240    {SIG_DRAG_START_LEFT, ""},
241    {SIG_DRAG_START_RIGHT, ""},
242    {SIG_DRAG_STOP, ""},
243    {SIG_DRAG, ""},
244    {SIG_LONGPRESSED, ""},
245    {SIG_SCROLL_ANIM_START, ""},
246    {SIG_SCROLL_ANIM_STOP, ""},
247    {SIG_SCROLL_DRAG_START, ""},
248    {SIG_SCROLL_DRAG_STOP, ""},
249    {SIG_EDGE_TOP, ""},
250    {SIG_EDGE_BOTTOM, ""},
251    {SIG_EDGE_LEFT, ""},
252    {SIG_EDGE_RIGHT, ""},
253    {SIG_MULTI_SWIPE_LEFT, ""},
254    {SIG_MULTI_SWIPE_RIGHT, ""},
255    {SIG_MULTI_SWIPE_UP, ""},
256    {SIG_MULTI_SWIPE_DOWN, ""},
257    {SIG_MULTI_PINCH_OUT, ""},
258    {SIG_MULTI_PINCH_IN, ""},
259    {SIG_SWIPE, ""},
260    {SIG_MOVED, ""},
261    {SIG_MOVED_AFTER, ""},
262    {SIG_MOVED_BEFORE, ""},
263    {SIG_TREE_EFFECT_FINISHED, ""},
264    {NULL, NULL}
265 };
266
267 /* TEMPORARY */
268 #undef ELM_CHECK_WIDTYPE
269 #define ELM_CHECK_WIDTYPE(obj, widtype) \
270    if ((!obj) || (!elm_genlist_type_check((obj), __func__))) return
271 #undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
272 #define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
273    ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
274    ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
275
276 static const char *_gengrid = NULL;
277 static const char *_genlist = NULL;
278
279 /* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
280 Eina_Bool
281 elm_genlist_type_check(const Evas_Object *obj,
282                        const char        *func)
283 {
284    const char *provided, *expected = "(unknown)";
285    static int abort_on_warn = -1;
286    provided = elm_widget_type_get(obj);
287    if (!_genlist) _genlist = eina_stringshare_add("genlist");
288    if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
289    if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
290      return EINA_TRUE;
291    if ((!provided) || (!provided[0]))
292      {
293         provided = evas_object_type_get(obj);
294         if ((!provided) || (!provided[0]))
295           provided = "(unknown)";
296      }
297    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
298    if (abort_on_warn == -1)
299      {
300         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
301         else abort_on_warn = 0;
302      }
303    if (abort_on_warn == 1) abort();
304    return EINA_FALSE;
305 }
306
307 static Eina_Bool
308 _event_hook(Evas_Object       *obj,
309             Evas_Object       *src __UNUSED__,
310             Evas_Callback_Type type,
311             void              *event_info)
312 {
313    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
314    Evas_Event_Key_Down *ev = event_info;
315    Widget_Data *wd = elm_widget_data_get(obj);
316    Evas_Coord pan_max_x = 0, pan_max_y = 0;
317    if (!wd) return EINA_FALSE;
318    if (!wd->items) return EINA_FALSE;
319    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
320    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
321
322    Elm_Object_Item *it = NULL;
323    Evas_Coord x = 0;
324    Evas_Coord y = 0;
325    Evas_Coord step_x = 0;
326    Evas_Coord step_y = 0;
327    Evas_Coord v_w = 0;
328    Evas_Coord v_h = 0;
329    Evas_Coord page_x = 0;
330    Evas_Coord page_y = 0;
331
332    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
333    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
334    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
335    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
336
337    if ((!strcmp(ev->keyname, "Left")) ||
338        ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
339      {
340         x -= step_x;
341      }
342    else if ((!strcmp(ev->keyname, "Right")) ||
343             ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
344      {
345         x += step_x;
346      }
347    else if ((!strcmp(ev->keyname, "Up")) ||
348             ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
349      {
350         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
351              (_item_multi_select_up(wd)))
352             || (_item_single_select_up(wd)))
353           {
354              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
355              return EINA_TRUE;
356           }
357         else
358           y -= step_y;
359      }
360    else if ((!strcmp(ev->keyname, "Down")) ||
361             ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
362      {
363         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
364              (_item_multi_select_down(wd)))
365             || (_item_single_select_down(wd)))
366           {
367              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
368              return EINA_TRUE;
369           }
370         else
371           y += step_y;
372      }
373    else if ((!strcmp(ev->keyname, "Home")) ||
374             ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
375      {
376         it = elm_genlist_first_item_get(obj);
377         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
378         elm_genlist_item_selected_set(it, EINA_TRUE);
379         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
380         return EINA_TRUE;
381      }
382    else if ((!strcmp(ev->keyname, "End")) ||
383             ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
384      {
385         it = elm_genlist_last_item_get(obj);
386         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
387         elm_genlist_item_selected_set(it, EINA_TRUE);
388         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
389         return EINA_TRUE;
390      }
391    else if ((!strcmp(ev->keyname, "Prior")) ||
392             ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
393      {
394         if (page_y < 0)
395           y -= -(page_y * v_h) / 100;
396         else
397           y -= page_y;
398      }
399    else if ((!strcmp(ev->keyname, "Next")) ||
400             ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
401      {
402         if (page_y < 0)
403           y += -(page_y * v_h) / 100;
404         else
405           y += page_y;
406      }
407    else if (!strcmp(ev->keyname, "Escape"))
408      {
409         if (!_deselect_all_items(wd)) return EINA_FALSE;
410         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
411         return EINA_TRUE;
412      }
413    else if (((!strcmp(ev->keyname, "Return")) ||
414              (!strcmp(ev->keyname, "KP_Enter")) ||
415              (!strcmp(ev->keyname, "space")))
416             && (!wd->multi) && (wd->selected))
417      {
418         it = elm_genlist_selected_item_get(obj);
419         elm_genlist_item_expanded_set(it,
420                                       !elm_genlist_item_expanded_get(it));
421         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
422      }
423    else return EINA_FALSE;
424
425    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
426    _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
427    if (x < 0) x = 0;
428    if (x > pan_max_x) x = pan_max_x;
429    if (y < 0) y = 0;
430    if (y > pan_max_y) y = pan_max_y;
431    elm_smart_scroller_child_pos_set(wd->scr, x, y);
432    return EINA_TRUE;
433 }
434
435 static Eina_Bool
436 _deselect_all_items(Widget_Data *wd)
437 {
438    if (!wd->selected) return EINA_FALSE;
439    while (wd->selected)
440      elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
441
442    return EINA_TRUE;
443 }
444
445 static Eina_Bool
446 _item_multi_select_up(Widget_Data *wd)
447 {
448    if (!wd->selected) return EINA_FALSE;
449    if (!wd->multi) return EINA_FALSE;
450
451    Elm_Object_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
452    if (!prev) return EINA_TRUE;
453
454    if (elm_genlist_item_selected_get(prev))
455      {
456         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
457         wd->last_selected_item = prev;
458         elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
459      }
460    else
461      {
462         elm_genlist_item_selected_set(prev, EINA_TRUE);
463         elm_genlist_item_show(prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
464      }
465    return EINA_TRUE;
466 }
467
468 static Eina_Bool
469 _item_multi_select_down(Widget_Data *wd)
470 {
471    if (!wd->selected) return EINA_FALSE;
472    if (!wd->multi) return EINA_FALSE;
473
474    Elm_Object_Item *next;
475    next = elm_genlist_item_next_get(wd->last_selected_item);
476    if (!next) return EINA_TRUE;
477
478    if (elm_genlist_item_selected_get(next))
479      {
480         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
481         wd->last_selected_item = next;
482         elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
483      }
484    else
485      {
486         elm_genlist_item_selected_set(next, EINA_TRUE);
487         elm_genlist_item_show(next, ELM_GENLIST_ITEM_SCROLLTO_IN);
488      }
489    return EINA_TRUE;
490 }
491
492 static Eina_Bool
493 _item_single_select_up(Widget_Data *wd)
494 {
495    Elm_Gen_Item *prev;
496    if (!wd->selected)
497      {
498         prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
499         while ((prev) && (prev->generation < wd->generation))
500           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
501      }
502    else prev = (Elm_Gen_Item *) elm_genlist_item_prev_get(wd->last_selected_item);
503
504    if (!prev) return EINA_FALSE;
505
506    _deselect_all_items(wd);
507
508    elm_genlist_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
509    elm_genlist_item_show((Elm_Object_Item *) prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
510    return EINA_TRUE;
511 }
512
513 static Eina_Bool
514 _item_single_select_down(Widget_Data *wd)
515 {
516    Elm_Gen_Item *next;
517    if (!wd->selected)
518      {
519         next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
520         while ((next) && (next->generation < wd->generation))
521           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
522      }
523    else next = (Elm_Gen_Item *) elm_genlist_item_next_get(wd->last_selected_item);
524
525    if (!next) return EINA_FALSE;
526
527    _deselect_all_items(wd);
528
529    elm_genlist_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
530    elm_genlist_item_show((Elm_Object_Item *) next, ELM_GENLIST_ITEM_SCROLLTO_IN);
531    return EINA_TRUE;
532 }
533
534 static void
535 _on_focus_hook(void        *data __UNUSED__,
536                Evas_Object *obj)
537 {
538    Widget_Data *wd = elm_widget_data_get(obj);
539    if (!wd) return;
540    if (elm_widget_focus_get(obj))
541      {
542         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
543         evas_object_focus_set(wd->obj, EINA_TRUE);
544         if ((wd->items) && (wd->selected) && (!wd->last_selected_item))
545           wd->last_selected_item = eina_list_data_get(wd->selected);
546      }
547    else
548      {
549         elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
550         evas_object_focus_set(wd->obj, EINA_FALSE);
551      }
552 }
553
554 static void
555 _del_hook(Evas_Object *obj)
556 {
557    Widget_Data *wd = elm_widget_data_get(obj);
558    if (!wd) return;
559    _item_cache_zero(wd);
560    if (wd->calc_job) ecore_job_del(wd->calc_job);
561    if (wd->update_job) ecore_job_del(wd->update_job);
562    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
563    if (wd->changed_job) ecore_job_del(wd->changed_job);
564    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
565    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
566    if (wd->decorate_it_type) eina_stringshare_del(wd->decorate_it_type);
567    if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
568    if (wd->tree_effect_animator) ecore_animator_del(wd->tree_effect_animator);
569    free(wd);
570 }
571
572 static void
573 _del_pre_hook(Evas_Object *obj)
574 {
575    Widget_Data *wd = elm_widget_data_get(obj);
576    if (!wd) return;
577    if (wd->decorate_all_mode) elm_genlist_decorate_mode_set(wd->obj, EINA_FALSE);
578    elm_genlist_clear(obj);
579    evas_object_del(wd->pan_smart);
580    wd->pan_smart = NULL;
581 }
582
583 static void
584 _mirrored_set(Evas_Object *obj,
585               Eina_Bool    rtl)
586 {
587    Widget_Data *wd = elm_widget_data_get(obj);
588    if (!wd) return;
589    _item_cache_zero(wd);
590    elm_smart_scroller_mirrored_set(wd->scr, rtl);
591 }
592
593 static void
594 _theme_hook(Evas_Object *obj)
595 {
596    Widget_Data *wd = elm_widget_data_get(obj);
597    Item_Block *itb;
598    if (!wd) return;
599    evas_event_freeze(evas_object_evas_get(wd->obj));
600    _item_cache_zero(wd);
601    _elm_widget_mirrored_reload(obj);
602    _mirrored_set(obj, elm_widget_mirrored_get(obj));
603    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
604                                        elm_widget_style_get(obj));
605    //edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
606    wd->item_width = wd->item_height = 0;
607    wd->group_item_width = wd->group_item_height = 0;
608    wd->minw = wd->minh = wd->realminw = 0;
609    EINA_INLIST_FOREACH(wd->blocks, itb)
610      {
611         Eina_List *l;
612         Elm_Gen_Item *it;
613
614         if (itb->realized) _item_block_unrealize(itb);
615         EINA_LIST_FOREACH(itb->items, l, it)
616           it->item->mincalcd = EINA_FALSE;
617
618         itb->changed = EINA_TRUE;
619      }
620    if (wd->calc_job) ecore_job_del(wd->calc_job);
621    wd->calc_job = ecore_job_add(_calc_job, wd);
622    _sizing_eval(obj);
623    evas_event_thaw(evas_object_evas_get(wd->obj));
624    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
625 }
626
627 static void
628 _show_region_hook(void        *data,
629                   Evas_Object *obj)
630 {
631    Widget_Data *wd = elm_widget_data_get(data);
632    Evas_Coord x, y, w, h;
633    if (!wd) return;
634    elm_widget_show_region_get(obj, &x, &y, &w, &h);
635    //x & y are screen coordinates, Add with pan coordinates
636    x += wd->pan_x;
637    y += wd->pan_y;
638    elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
639 }
640
641 static void
642 _translate_hook(Evas_Object *obj)
643 {
644    evas_object_smart_callback_call(obj, "language,changed", NULL);
645 }
646
647 static void
648 _sizing_eval(Evas_Object *obj)
649 {
650    Widget_Data *wd = elm_widget_data_get(obj);
651    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
652    Evas_Coord vmw = 0, vmh = 0;
653    if (!wd) return;
654
655    evas_object_size_hint_min_get(wd->scr, &minw, NULL);
656    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
657
658    edje_object_size_min_calc
659       (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
660
661    if (wd->mode == ELM_LIST_COMPRESS)
662      {
663         Evas_Coord vw, vh;
664
665         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
666         if ((vw != 0) && (vw != wd->prev_viewport_w))
667           {
668              Item_Block *itb;
669
670              wd->prev_viewport_w = vw;
671              EINA_INLIST_FOREACH(wd->blocks, itb)
672                {
673                   itb->must_recalc = EINA_TRUE;
674                }
675              if (wd->calc_job) ecore_job_del(wd->calc_job);
676              wd->calc_job = ecore_job_add(_calc_job, wd);
677           }
678         edje_object_size_min_calc
679           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
680         minw = vmw;
681         minh = vmh;
682      }
683    else if (wd->mode == ELM_LIST_LIMIT)
684      {
685         maxw = -1;
686         minw = vmw + wd->realminw;
687      }
688    else
689      {
690         minw = vmw;
691         minh = vmh;
692      }
693
694    evas_object_size_hint_min_set(obj, minw, minh);
695    evas_object_size_hint_max_set(obj, maxw, maxh);
696 }
697
698 static void
699 _signal_emit_hook(Evas_Object *obj,
700                   const char  *emission,
701                   const char  *source)
702 {
703    Widget_Data *wd = elm_widget_data_get(obj);
704    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
705                            emission, source);
706 }
707
708 static void
709 _item_highlight(Elm_Gen_Item *it)
710 {
711    const char *selectraise;
712    if ((it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
713        (!it->wd->highlight) ||
714        (it->generation < it->wd->generation) ||
715        (it->highlighted) || elm_widget_item_disabled_get(it) ||
716        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (it->item->deco_it_view) ||
717        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
718      return;
719    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
720    if (it->deco_all_view) edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
721    selectraise = edje_object_data_get(VIEW(it), "selectraise");
722    if ((selectraise) && (!strcmp(selectraise, "on")))
723      {
724         if (it->deco_all_view) evas_object_raise(it->deco_all_view);
725         else evas_object_raise(VIEW(it));
726 //FIXME: group raise
727 #if 0
728         if ((it->item->group_item) && (it->item->group_item->realized))
729           evas_object_raise(it->item->VIEW(group_item));
730 #endif
731      }
732    it->highlighted = EINA_TRUE;
733 }
734
735 static void
736 _item_unhighlight(Elm_Gen_Item *it)
737 {
738    if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
739    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
740    if (it->deco_all_view) edje_object_signal_emit(it->deco_all_view, "elm,state,unselected", "elm");
741    if (!it->item->nostacking)
742      {
743        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
744          {
745              if (it->deco_all_view) evas_object_lower(it->deco_all_view);
746              else evas_object_lower(VIEW(it));
747          }
748        else
749          {
750              if (it->deco_all_view) evas_object_raise(it->deco_all_view);
751              else evas_object_raise(VIEW(it));
752          }
753      }
754    it->highlighted = EINA_FALSE;
755 }
756
757 static void
758 _item_block_position_update(Eina_Inlist *list, int idx)
759 {
760    Item_Block *tmp;
761
762    EINA_INLIST_FOREACH(list, tmp)
763      {
764         tmp->position = idx++;
765         tmp->position_update = EINA_TRUE;
766      }
767 }
768
769 static void
770 _item_position_update(Eina_List *list, int idx)
771 {
772    Elm_Gen_Item *it;
773    Eina_List *l;
774
775    EINA_LIST_FOREACH(list, l, it)
776      {
777         it->position = idx++;
778         it->position_update = EINA_TRUE;
779      }
780 }
781
782 static void
783 _item_block_del(Elm_Gen_Item *it)
784 {
785    Eina_Inlist *il;
786    Item_Block *itb = it->item->block;
787    Eina_Bool block_changed;
788
789    itb->items = eina_list_remove(itb->items, it);
790    itb->count--;
791    itb->changed = EINA_TRUE;
792    if (!it->wd->reorder_deleted)
793      {
794         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
795         it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
796      }
797    if (itb->count < 1)
798      {
799         il = EINA_INLIST_GET(itb);
800         Item_Block *itbn = (Item_Block *)(il->next);
801         if (it->parent)
802           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
803         else
804           {
805              _item_block_position_update(il->next, itb->position);
806              it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
807           }
808         free(itb);
809         if (itbn) itbn->changed = EINA_TRUE;
810      }
811    else
812      {
813         if (itb->count < itb->wd->max_items_per_block/2)
814           {
815              il = EINA_INLIST_GET(itb);
816              Item_Block *itbp = (Item_Block *)(il->prev);
817              Item_Block *itbn = (Item_Block *)(il->next);
818              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
819                {
820                   Elm_Gen_Item *it2;
821
822                   EINA_LIST_FREE(itb->items, it2)
823                     {
824                        it2->item->block = itbp;
825                        itbp->items = eina_list_append(itbp->items, it2);
826                        itbp->count++;
827                        itbp->changed = EINA_TRUE;
828                     }
829                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
830                                               itb->position);
831                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
832                                                       EINA_INLIST_GET(itb));
833                   free(itb);
834                   block_changed = EINA_TRUE;
835                }
836              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
837                {
838                   while (itb->items)
839                     {
840                        Eina_List *last = eina_list_last(itb->items);
841                        Elm_Gen_Item *it2 = last->data;
842
843                        it2->item->block = itbn;
844                        itb->items = eina_list_remove_list(itb->items, last);
845                        itbn->items = eina_list_prepend(itbn->items, it2);
846                        itbn->count++;
847                        itbn->changed = EINA_TRUE;
848                     }
849                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
850                                               itb->position);
851                   it->wd->blocks =
852                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
853                   free(itb);
854                   block_changed = EINA_TRUE;
855                }
856           }
857      }
858    if (block_changed)
859      {
860         it->wd->pan_changed = EINA_TRUE;
861         evas_object_smart_changed(it->wd->pan_smart);
862         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
863         it->wd->calc_job = NULL;
864      }
865 }
866
867 static void
868 _item_subitems_clear(Elm_Gen_Item *it)
869 {
870    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
871    Eina_List *tl = NULL, *l;
872    Elm_Object_Item *it2;
873
874    EINA_LIST_FOREACH(it->item->items, l, it2)
875      tl = eina_list_append(tl, it2);
876    EINA_LIST_FREE(tl, it2)
877      elm_object_item_del(it2);
878 }
879
880 static void
881 _item_del(Elm_Gen_Item *it)
882 {
883    Evas_Object *obj = WIDGET(it);
884    Widget_Data *wd = it->wd;
885
886    evas_event_freeze(evas_object_evas_get(obj));
887    elm_genlist_item_subitems_clear((Elm_Object_Item *)it);
888    if (wd->show_item == it) wd->show_item = NULL;
889    if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
890    if (it->item->decorate_all_item_realized) _decorate_all_item_unrealize(it);
891    if (it->item->block) _item_block_del(it);
892    if (it->item->queued)
893      wd->queue = eina_list_remove(wd->queue, it);
894    if (wd->anchor_item == it)
895      {
896         wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
897         if (!wd->anchor_item)
898           wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
899      }
900    if (wd->expanded_item == it)
901      {
902         wd->expanded_item = NULL;
903         if (wd->tree_effect_animator)
904           {
905              ecore_animator_del(wd->tree_effect_animator);
906              wd->tree_effect_animator = NULL;
907           }
908         wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
909      }
910    if (wd->expanded_next_item == it) wd->expanded_next_item = NULL;
911    if (wd->move_items) wd->move_items = eina_list_remove(wd->move_items, it);
912    if (it->parent)
913      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
914    if (it->item->swipe_timer)
915      {
916         ecore_timer_del(it->item->swipe_timer);
917         it->item->swipe_timer = NULL;
918      }
919    _elm_genlist_item_del_serious(it);
920    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
921    evas_event_thaw(evas_object_evas_get(obj));
922    evas_event_thaw_eval(evas_object_evas_get(obj));
923 }
924
925 static void
926 _clear_cb(Widget_Data *wd)
927 {
928    wd->anchor_item = NULL;
929    if (wd->queue_idle_enterer)
930      {
931         ecore_idle_enterer_del(wd->queue_idle_enterer);
932         wd->queue_idle_enterer = NULL;
933      }
934    if (wd->must_recalc_idler)
935      {
936         ecore_idler_del(wd->must_recalc_idler);
937         wd->must_recalc_idler = NULL;
938      }
939    if (wd->queue) wd->queue = eina_list_free(wd->queue);
940    if (wd->reorder_move_animator)
941      {
942         ecore_animator_del(wd->reorder_move_animator);
943         wd->reorder_move_animator = NULL;
944      }
945    wd->show_item = NULL;
946    wd->reorder_old_pan_y = 0;
947 }
948
949 static void
950 _item_unselect(Elm_Gen_Item *it)
951 {
952    if ((it->generation < it->wd->generation) || (!it->selected)) return;
953    it->selected = EINA_FALSE;
954    it->wd->selected = eina_list_remove(it->wd->selected, it);
955    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
956 }
957
958 static void
959 _mouse_move(void        *data,
960             Evas        *evas __UNUSED__,
961             Evas_Object *obj,
962             void        *event_info)
963 {
964    Elm_Gen_Item *it = data;
965    Evas_Event_Mouse_Move *ev = event_info;
966    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
967    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
968
969    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
970      {
971         if (!it->wd->on_hold)
972           {
973              it->wd->on_hold = EINA_TRUE;
974              if ((!it->wd->wasselected) && (!it->flipped))
975                {
976                   _item_unhighlight(it);
977                   _item_unselect(it);
978                }
979           }
980      }
981    if (it->wd->multitouched)
982      {
983         it->wd->cur_x = ev->cur.canvas.x;
984         it->wd->cur_y = ev->cur.canvas.y;
985         return;
986      }
987    if ((it->dragging) && (it->down))
988      {
989         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
990         else
991           {
992              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
993              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
994              if (abs((it->wd->history[it->wd->movements].x -
995                       it->wd->history[0].x)) > 40)
996                it->wd->swipe = EINA_TRUE;
997              else
998                it->wd->movements++;
999           }
1000         if (it->long_timer)
1001           {
1002              ecore_timer_del(it->long_timer);
1003              it->long_timer = NULL;
1004           }
1005         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
1006         return;
1007      }
1008    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
1009      {
1010         if (it->long_timer)
1011           {
1012              ecore_timer_del(it->long_timer);
1013              it->long_timer = NULL;
1014           }
1015         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1016           {
1017              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
1018              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                   if ((itb->wd->homogeneous) &&
2482                       (itb->wd->mode == ELM_LIST_COMPRESS))
2483                     {
2484                        if (it->group)
2485                          {
2486                             it->item->w = it->item->minw = it->wd->group_item_width;
2487                             it->item->h = it->item->minh = it->wd->group_item_height;
2488                          }
2489                        else
2490                          {
2491                             it->item->w = it->item->minw = it->wd->item_width;
2492                             it->item->h = it->item->minh = it->wd->item_height;
2493                          }
2494                     }
2495                   else
2496                     {
2497                        _item_realize(it, in, EINA_TRUE);
2498                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2499                     }
2500                }
2501           }
2502         else
2503           {
2504              if (!it->item->mincalcd) changed = EINA_TRUE;
2505              _item_realize(it, in, EINA_FALSE);
2506           }
2507         minh += it->item->minh;
2508         if (minw < it->item->minw) minw = it->item->minw;
2509         in++;
2510         it->x = 0;
2511         it->y = y;
2512         y += it->item->h;
2513      }
2514    if (changed) itb->wd->pan_changed = changed;
2515    itb->minw = minw;
2516    itb->minh = minh;
2517    itb->changed = EINA_FALSE;
2518    itb->position_update = EINA_FALSE;
2519    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2520    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2521    return showme;
2522 }
2523
2524 static void
2525 _item_block_realize(Item_Block *itb)
2526 {
2527    if (itb->realized) return;
2528    itb->realized = EINA_TRUE;
2529    itb->want_unrealize = EINA_FALSE;
2530 }
2531
2532 static void
2533 _item_block_unrealize(Item_Block *itb)
2534 {
2535    const Eina_List *l;
2536    Elm_Gen_Item *it;
2537    Eina_Bool dragging = EINA_FALSE;
2538
2539    if (!itb->realized) return;
2540    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2541    EINA_LIST_FOREACH(itb->items, l, it)
2542      {
2543         if (itb->must_recalc || !it->group)
2544           {
2545              if (it->dragging)
2546                {
2547                   dragging = EINA_TRUE;
2548                   it->want_unrealize = EINA_TRUE;
2549                }
2550              else
2551                _elm_genlist_item_unrealize(it, EINA_FALSE);
2552           }
2553      }
2554    if (!dragging)
2555      {
2556         itb->realized = EINA_FALSE;
2557         itb->want_unrealize = EINA_TRUE;
2558      }
2559    else
2560      itb->want_unrealize = EINA_FALSE;
2561    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2562    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2563 }
2564
2565 static int
2566 _get_space_for_reorder_item(Elm_Gen_Item *it)
2567 {
2568    Evas_Coord rox, roy, row, roh, oy, oh;
2569    Eina_Bool top = EINA_FALSE;
2570    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2571    if (!reorder_it) return 0;
2572
2573    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2574    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2575
2576    if ((it->wd->reorder_start_y < it->item->block->y) &&
2577        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2578      {
2579         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2580         if (it->item->block->count == 1)
2581           it->wd->reorder_rel = it;
2582      }
2583    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2584             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2585      {
2586         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2587      }
2588    else
2589      it->item->block->reorder_offset = 0;
2590
2591    it->item->scrl_y += it->item->block->reorder_offset;
2592
2593    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2594                               rox, roy + (roh / 2), row, 1));
2595    if (top)
2596      {
2597         it->wd->reorder_rel = it;
2598         it->item->scrl_y += it->wd->reorder_it->item->h;
2599         return it->wd->reorder_it->item->h;
2600      }
2601    else
2602      return 0;
2603 }
2604
2605 static Eina_Bool
2606 _reorder_move_animator_cb(void *data)
2607 {
2608    Elm_Gen_Item *it = data;
2609    Eina_Bool down = EINA_FALSE;
2610    double t;
2611    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2612
2613    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2614
2615    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2616    else y = dy;
2617
2618    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2619    if (diff > it->item->h) y = diff / 2;
2620
2621    if (it->item->old_scrl_y < it->item->scrl_y)
2622      {
2623         it->item->old_scrl_y += y;
2624         down = EINA_TRUE;
2625      }
2626    else if (it->item->old_scrl_y > it->item->scrl_y)
2627      {
2628         it->item->old_scrl_y -= y;
2629         down = EINA_FALSE;
2630      }
2631
2632    if (it->deco_all_view)
2633      _item_position(it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
2634    else
2635      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2636 //FIXME : group raise
2637 #if 0
2638    _group_items_recalc(it->wd);
2639 #endif
2640
2641    if ((it->wd->reorder_pan_move) ||
2642        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2643        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2644      {
2645         it->item->old_scrl_y = it->item->scrl_y;
2646         it->item->move_effect_enabled = EINA_FALSE;
2647         it->wd->reorder_move_animator = NULL;
2648         return ECORE_CALLBACK_CANCEL;
2649      }
2650    return ECORE_CALLBACK_RENEW;
2651 }
2652
2653 static void
2654 _item_position(Elm_Gen_Item *it,
2655                Evas_Object  *view,
2656                Evas_Coord    it_x,
2657                Evas_Coord    it_y)
2658 {
2659    if (!it) return;
2660    if (!view) return;
2661
2662    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2663    evas_object_resize(view, it->item->w, it->item->h);
2664    evas_object_move(view, it_x, it_y);
2665    evas_object_show(view);
2666    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2667    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2668 }
2669
2670 static void
2671 _item_block_position(Item_Block *itb,
2672                      int         in)
2673 {
2674    const Eina_List *l;
2675    Elm_Gen_Item *it;
2676 //FIXME : group raise
2677 #if 0
2678    Elm_Gen_Item *git;
2679 #endif
2680    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2681    Eina_Bool vis = EINA_FALSE;
2682    Evas_Coord minh = 0;
2683
2684    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2685    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2686    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2687                             &cvw, &cvh);
2688    EINA_LIST_FOREACH(itb->items, l, it)
2689      {
2690         if (it->generation < it->wd->generation) continue;
2691         else if (it->wd->reorder_it == it) continue;
2692         it->x = 0;
2693         it->y = y;
2694         it->item->w = itb->w;
2695         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2696         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2697
2698         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2699                                    cvx, cvy, cvw, cvh));
2700 //FIXME : group raise
2701 #if 0
2702         if (!it->group)
2703 #endif
2704           {
2705              if ((itb->realized) && (!it->realized))
2706                {
2707                   if (vis) _item_realize(it, in, EINA_FALSE);
2708                }
2709              if (it->realized)
2710                {
2711                   if (vis || it->dragging)
2712                     {
2713                        if (it->wd->reorder_mode)
2714                          y += _get_space_for_reorder_item(it);
2715 //FIXME : group raise
2716 #if 0
2717                        git = it->item->group_item;
2718                        if (git)
2719                          {
2720                             if (git->item->scrl_y < oy)
2721                               git->item->scrl_y = oy;
2722                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2723                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2724                             git->item->want_realize = EINA_TRUE;
2725                          }
2726 #endif
2727                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2728                          {
2729                             if (!it->item->move_effect_enabled)
2730                               {
2731                                  it->item->move_effect_enabled = EINA_TRUE;
2732                                  it->wd->reorder_move_animator =
2733                                     ecore_animator_add(
2734                                        _reorder_move_animator_cb, it);
2735                               }
2736                          }
2737                        if (!it->item->move_effect_enabled)
2738                          {
2739                             if ((it->wd->decorate_all_mode) && (it->itc->decorate_all_item_style))
2740                               _decorate_all_item_position(it, it->item->scrl_x,
2741                                                        it->item->scrl_y);
2742                             else
2743                               {
2744                                  if (!it->wd->tree_effect_enabled ||
2745                                      (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE) ||
2746                                      ((it->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE) &&
2747                                      (it->item->old_scrl_y == it->item->scrl_y)))
2748                                    {
2749                                       if (it->item->deco_it_view)
2750                                         _item_position(it, it->item->deco_it_view,
2751                                                        it->item->scrl_x,
2752                                                        it->item->scrl_y);
2753                                       else
2754                                         _item_position(it, VIEW(it), it->item->scrl_x,
2755                                                        it->item->scrl_y);
2756                                    }
2757                               }
2758                             it->item->old_scrl_y = it->item->scrl_y;
2759                          }
2760                     }
2761                   else
2762                     {
2763                        if (!it->wd->tree_effect_animator)
2764                          {
2765                             it->want_unrealize = EINA_TRUE;
2766                             _elm_genlist_item_unrealize(it, EINA_FALSE);
2767                          }
2768                     }
2769                }
2770              in++;
2771           }
2772 //FIXME : group raise
2773 #if 0
2774         else
2775           {
2776              if (vis) it->item->want_realize = EINA_TRUE;
2777           }
2778 #endif
2779         y += it->item->h;
2780         minh += it->item->minh;
2781      }
2782    if (!itb->wd->reorder_it) itb->minh = minh;
2783    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2784    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2785 }
2786
2787 //FIXME: group raise
2788 #if 0
2789 static void
2790 _group_items_recalc(void *data)
2791 {
2792    Widget_Data *wd = data;
2793    Eina_List *l;
2794    Elm_Gen_Item *git;
2795
2796    evas_event_freeze(evas_object_evas_get(wd->obj));
2797    EINA_LIST_FOREACH(wd->group_items, l, git)
2798      {
2799         if (git->item->want_realize)
2800           {
2801              if (!git->realized)
2802                _item_realize(git, 0, EINA_FALSE);
2803              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2804              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2805              evas_object_show(VIEW(git));
2806              evas_object_raise(VIEW(git));
2807           }
2808         else if (!git->item->want_realize && git->realized)
2809           {
2810              if (!git->dragging)
2811                _elm_genlist_item_unrealize(git, EINA_FALSE);
2812           }
2813      }
2814    evas_event_thaw(evas_object_evas_get(wd->obj));
2815    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2816 }
2817 #endif
2818
2819 static void
2820 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2821 {
2822    Elm_Gen_Item *it = data;
2823    if (!it) return;
2824    if (it->want_unrealize) return;
2825    it->item->mincalcd = EINA_FALSE;
2826    it->item->block->changeme = EINA_TRUE;
2827    if (it->wd->changed_job) ecore_job_del(it->wd->changed_job);
2828    it->wd->changed_job = ecore_job_add(_changed_job, it->wd);
2829 }
2830
2831 static Eina_Bool
2832 _must_recalc_idler(void *data)
2833 {
2834    Widget_Data *wd = data;
2835    if (wd->calc_job) ecore_job_del(wd->calc_job);
2836    wd->calc_job = ecore_job_add(_calc_job, wd);
2837    wd->must_recalc_idler = NULL;
2838    return ECORE_CALLBACK_CANCEL;
2839 }
2840
2841 static void
2842 _scroll_item(Widget_Data *wd)
2843 {
2844    Elm_Gen_Item *it = NULL;
2845 //FIXME: group raise
2846 #if 0
2847    Evas_Coord gith = 0;
2848 #endif
2849    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
2850    if (!wd->show_item) return;
2851
2852    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
2853    it = wd->show_item;
2854    dx = it->x + it->item->block->x;
2855    dy = it->y + it->item->block->y;
2856    dw = it->item->block->w;
2857    dh = oh;
2858    switch (wd->scrollto_type)
2859      {
2860       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2861 //FIXME: group raise
2862 #if 0
2863          if (it->item->group_item) gith = it->item->group_item->item->h;
2864          dy -= gith;
2865 #endif
2866          break;
2867       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2868          dy += ((it->item->h / 2) - (oh / 2));
2869          break;
2870       case ELM_GENLIST_ITEM_SCROLLTO_IN:
2871       default:
2872          if ((wd->expanded_item) &&
2873              ((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
2874               - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
2875            {
2876               it = wd->expanded_item;
2877               dx = it->x + it->item->block->x;
2878               dy = it->y + it->item->block->y;
2879 //FIXME: group raise
2880 #if 0
2881               if (it->item->group_item) gith = it->item->group_item->item->h;
2882               dx = it->x + it->item->block->x;
2883               dy = it->y + it->item->block->y - gith;
2884 #endif
2885               dw = it->item->block->w;
2886            }
2887          else
2888            {
2889 //FIXME: group raise
2890 #if 0
2891               if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
2892                 gith = it->item->group_item->item->h;
2893               dy -= gith;
2894 #endif
2895               dh = it->item->h;
2896            }
2897          break;
2898      }
2899    if (wd->bring_in)
2900      elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
2901    else
2902      elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
2903
2904    it->item->showme = EINA_FALSE;
2905    wd->show_item = NULL;
2906    wd->auto_scroll_enabled = EINA_FALSE;
2907    wd->check_scroll = EINA_FALSE;
2908 }
2909
2910 static void
2911 _calc_job(void *data)
2912 {
2913    Widget_Data *wd = data;
2914    Item_Block *itb, *chb = NULL;
2915    Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw;
2916    Evas_Coord pan_w = 0, pan_h = 0;
2917    int in = 0;
2918    Eina_Bool minw_change = EINA_FALSE;
2919    Eina_Bool did_must_recalc = EINA_FALSE;
2920    if (!wd) return;
2921
2922    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2923    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2924
2925    if (wd->w != ow)
2926      wd->w = ow;
2927
2928    evas_event_freeze(evas_object_evas_get(wd->obj));
2929    EINA_INLIST_FOREACH(wd->blocks, itb)
2930      {
2931         Eina_Bool showme = EINA_FALSE;
2932
2933         itb->num = in;
2934         showme = itb->showme;
2935         itb->showme = EINA_FALSE;
2936         if (chb)
2937           {
2938              if (itb->realized) _item_block_unrealize(itb);
2939           }
2940         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2941           {
2942              if (itb->must_recalc)
2943                {
2944                   Eina_List *l;
2945                   Elm_Gen_Item *it;
2946                   EINA_LIST_FOREACH(itb->items, l, it)
2947                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2948                   itb->changed = EINA_TRUE;
2949                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2950                   if (itb->realized) _item_block_unrealize(itb);
2951                   itb->must_recalc = EINA_FALSE;
2952                }
2953              showme = _item_block_recalc(itb, in, EINA_FALSE);
2954              chb = itb;
2955           }
2956         itb->y = y;
2957         itb->x = 0;
2958         minh += itb->minh;
2959         if (minw == -1) minw = itb->minw;
2960         else if ((!itb->must_recalc) && (minw < itb->minw))
2961           {
2962              minw = itb->minw;
2963              minw_change = EINA_TRUE;
2964           }
2965         if (minw > vw)
2966           {
2967              minw = vw;
2968              minw_change = EINA_TRUE;
2969           }
2970         itb->w = minw;
2971         itb->h = itb->minh;
2972         y += itb->h;
2973         in += itb->count;
2974         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2975           wd->check_scroll = EINA_TRUE;
2976      }
2977    if (minw_change)
2978      {
2979         EINA_INLIST_FOREACH(wd->blocks, itb)
2980           {
2981              itb->minw = minw;
2982              itb->w = itb->minw;
2983           }
2984      }
2985    if ((chb) && (EINA_INLIST_GET(chb)->next))
2986      {
2987         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2988           {
2989              if (itb->realized) _item_block_unrealize(itb);
2990           }
2991      }
2992    wd->realminw = minw;
2993    if (minw < wd->w) minw = wd->w;
2994    if ((minw != wd->minw) || (minh != wd->minh))
2995      {
2996         wd->minw = minw;
2997         wd->minh = minh;
2998         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2999         _sizing_eval(wd->obj);
3000         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
3001           {
3002              Elm_Gen_Item *it;
3003              Evas_Coord it_y;
3004
3005              it = wd->anchor_item;
3006              it_y = wd->anchor_y;
3007              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
3008                                               it->item->block->y + it->y + it_y);
3009              wd->anchor_item = it;
3010              wd->anchor_y = it_y;
3011           }
3012      }
3013    if (did_must_recalc)
3014      {
3015         if (!wd->must_recalc_idler)
3016           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
3017      }
3018    if (wd->check_scroll)
3019      {
3020         _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
3021         if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
3022           wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3023        switch (wd->scrollto_type)
3024           {
3025            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
3026               dy = wd->h;
3027               break;
3028            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
3029               dy = wd->h / 2;
3030               break;
3031            case ELM_GENLIST_ITEM_SCROLLTO_IN:
3032            default:
3033               dy = 0;
3034               break;
3035           }
3036         if ((wd->show_item) && (wd->show_item->item->block))
3037           {
3038              if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
3039                  (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
3040                {
3041                   _scroll_item(wd);
3042                }
3043           }
3044      }
3045    wd->calc_job = NULL;
3046    evas_object_smart_changed(wd->pan_smart);
3047    evas_event_thaw(evas_object_evas_get(wd->obj));
3048    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3049 }
3050
3051 static void
3052 _update_job(void *data)
3053 {
3054    Widget_Data *wd = data;
3055    Eina_List *l2;
3056    Item_Block *itb;
3057    int num, num0;
3058    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
3059    if (!wd) return;
3060    wd->update_job = NULL;
3061    num = 0;
3062
3063    evas_event_freeze(evas_object_evas_get(wd->obj));
3064    EINA_INLIST_FOREACH(wd->blocks, itb)
3065      {
3066         Evas_Coord itminw, itminh;
3067         Elm_Gen_Item *it;
3068
3069         if (!itb->updateme)
3070           {
3071              num += itb->count;
3072              if (position)
3073                _item_block_position(itb, num);
3074              continue;
3075           }
3076         num0 = num;
3077         recalc = EINA_FALSE;
3078         EINA_LIST_FOREACH(itb->items, l2, it)
3079           {
3080              if (it->item->updateme)
3081                {
3082                   itminw = it->item->minw;
3083                   itminh = it->item->minh;
3084
3085                   if (it->realized)
3086                     {
3087                        _elm_genlist_item_unrealize(it, EINA_FALSE);
3088                        _item_realize(it, num, EINA_FALSE);
3089                        position = EINA_TRUE;
3090                     }
3091                   else
3092                     {
3093                        _item_realize(it, num, EINA_TRUE);
3094                        _elm_genlist_item_unrealize(it, EINA_TRUE);
3095                     }
3096                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
3097                     recalc = EINA_TRUE;
3098                   it->item->updateme = EINA_FALSE;
3099                }
3100              num++;
3101           }
3102         itb->updateme = EINA_FALSE;
3103         if (recalc)
3104           {
3105              position = EINA_TRUE;
3106              itb->changed = EINA_TRUE;
3107              _item_block_recalc(itb, num0, EINA_FALSE);
3108              _item_block_position(itb, num0);
3109           }
3110      }
3111    if (position)
3112      {
3113         if (wd->calc_job) ecore_job_del(wd->calc_job);
3114         wd->calc_job = ecore_job_add(_calc_job, wd);
3115      }
3116    evas_event_thaw(evas_object_evas_get(wd->obj));
3117    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3118 }
3119
3120 static void
3121 _changed_job(void *data)
3122 {
3123    Widget_Data *wd = data; Eina_List *l2;
3124    Item_Block *itb;
3125    int num, num0, position = 0;
3126    Eina_Bool width_changed = EINA_FALSE, height_changed = EINA_FALSE;
3127    if (!wd) return;
3128    wd->changed_job = NULL;
3129    num = 0;
3130    EINA_INLIST_FOREACH(wd->blocks, itb)
3131      {
3132         Evas_Coord itminw, itminh;
3133         Elm_Gen_Item *it;
3134
3135         if (!itb->changeme)
3136           {
3137              num += itb->count;
3138              if (position)
3139                _item_block_position(itb, num);
3140              continue;
3141           }
3142         num0 = num;
3143         width_changed = height_changed = EINA_FALSE;
3144         EINA_LIST_FOREACH(itb->items, l2, it)
3145           {
3146              if ((!it->item->mincalcd) && (it->realized))
3147                {
3148                   Evas_Coord mw = -1, mh = -1;
3149                   itminw = it->item->minw;
3150                   itminh = it->item->minh;
3151
3152                   if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->w;
3153                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3154                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
3155                   if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
3156                   edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
3157                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3158                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
3159                   if (mw > itb->w)
3160                     width_changed = EINA_TRUE;
3161                   else
3162                     mw = itb->w;
3163                   it->item->w = it->item->minw = mw;
3164                   it->item->h = it->item->minh = mh;
3165                   it->item->mincalcd = EINA_TRUE;
3166
3167                   //if ((it->item->minw != itminw) || (it->item->minh != itminh))
3168                   //if ((it->item->minh != itminh))
3169                   //  recalc = 1;
3170                   if ((it->item->minw != itminw))
3171                     width_changed = EINA_TRUE;
3172                   if ((it->item->minh != itminh))
3173                     height_changed = EINA_TRUE;
3174
3175                   if ((!it->wd->group_item_width) && (it->group))
3176                     {
3177                        it->wd->group_item_width = mw;
3178                        it->wd->group_item_height = mh;
3179                     }
3180                   else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
3181                     {
3182                        it->wd->item_width = mw;
3183                        it->wd->item_height = mh;
3184                     }
3185                }
3186              num++;
3187           }
3188         itb->changeme = EINA_FALSE;
3189         // TODO: why this is separated.
3190         if (height_changed)
3191           {
3192              position = 1;
3193              itb->changed = EINA_TRUE;
3194              _item_block_recalc(itb, num0, 0);
3195              _item_block_position(itb, num0);
3196           }
3197         else if (width_changed)
3198           {
3199              _item_block_position(itb, num0);
3200           }
3201      }
3202    if (position)
3203      {
3204         if (wd->calc_job) ecore_job_del(wd->calc_job);
3205         wd->calc_job = ecore_job_add(_calc_job, wd);
3206      }
3207 }
3208
3209 static void
3210 _pan_set(Evas_Object *obj,
3211          Evas_Coord   x,
3212          Evas_Coord   y)
3213 {
3214    Pan *sd = evas_object_smart_data_get(obj);
3215    Item_Block *itb;
3216
3217    if (!sd) return;
3218    //   Evas_Coord ow, oh;
3219    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3220    //   ow = sd->wd->minw - ow;
3221    //   if (ow < 0) ow = 0;
3222    //   oh = sd->wd->minh - oh;
3223    //   if (oh < 0) oh = 0;
3224    //   if (x < 0) x = 0;
3225    //   if (y < 0) y = 0;
3226    //   if (x > ow) x = ow;
3227    //   if (y > oh) y = oh;
3228    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
3229    sd->wd->pan_x = x;
3230    sd->wd->pan_y = y;
3231
3232    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3233      {
3234         if ((itb->y + itb->h) > y)
3235           {
3236              Elm_Gen_Item *it;
3237              Eina_List *l2;
3238
3239              EINA_LIST_FOREACH(itb->items, l2, it)
3240                {
3241                   if ((itb->y + it->y) >= y)
3242                     {
3243                        sd->wd->anchor_item = it;
3244                        sd->wd->anchor_y = -(itb->y + it->y - y);
3245                        goto done;
3246                     }
3247                }
3248           }
3249      }
3250 done:
3251    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
3252 }
3253
3254 static void
3255 _pan_get(Evas_Object *obj,
3256          Evas_Coord  *x,
3257          Evas_Coord  *y)
3258 {
3259    Pan *sd = evas_object_smart_data_get(obj);
3260
3261    if (!sd) return;
3262    if (x) *x = sd->wd->pan_x;
3263    if (y) *y = sd->wd->pan_y;
3264 }
3265
3266 static void
3267 _pan_max_get(Evas_Object *obj,
3268              Evas_Coord  *x,
3269              Evas_Coord  *y)
3270 {
3271    Pan *sd = evas_object_smart_data_get(obj);
3272    Evas_Coord ow, oh;
3273
3274    if (!sd) return;
3275    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3276    ow = sd->wd->minw - ow;
3277    if (ow < 0) ow = 0;
3278    oh = sd->wd->minh - oh;
3279    if (oh < 0) oh = 0;
3280    if (x) *x = ow;
3281    if (y) *y = oh;
3282 }
3283
3284 static void
3285 _pan_min_get(Evas_Object *obj __UNUSED__,
3286              Evas_Coord  *x,
3287              Evas_Coord  *y)
3288 {
3289    if (x) *x = 0;
3290    if (y) *y = 0;
3291 }
3292
3293 static void
3294 _pan_child_size_get(Evas_Object *obj,
3295                     Evas_Coord  *w,
3296                     Evas_Coord  *h)
3297 {
3298    Pan *sd = evas_object_smart_data_get(obj);
3299
3300    if (!sd) return;
3301    if (w) *w = sd->wd->minw;
3302    if (h) *h = sd->wd->minh;
3303 }
3304
3305 static void
3306 _pan_add(Evas_Object *obj)
3307 {
3308    Pan *sd;
3309    Evas_Object_Smart_Clipped_Data *cd;
3310
3311    _pan_sc.add(obj);
3312    cd = evas_object_smart_data_get(obj);
3313    sd = ELM_NEW(Pan);
3314    if (!sd) return;
3315    sd->__clipped_data = *cd;
3316    free(cd);
3317    evas_object_smart_data_set(obj, sd);
3318 }
3319
3320 static void
3321 _pan_del(Evas_Object *obj)
3322 {
3323    Pan *sd = evas_object_smart_data_get(obj);
3324
3325    if (!sd) return;
3326    if (sd->resize_job)
3327      {
3328         ecore_job_del(sd->resize_job);
3329         sd->resize_job = NULL;
3330      }
3331    _pan_sc.del(obj);
3332 }
3333
3334 static void
3335 _pan_resize_job(void *data)
3336 {
3337    Pan *sd = data;
3338    if (!sd) return;
3339    _sizing_eval(sd->wd->obj);
3340    sd->resize_job = NULL;
3341 }
3342
3343 static void
3344 _pan_resize(Evas_Object *obj,
3345             Evas_Coord   w,
3346             Evas_Coord   h)
3347 {
3348    Pan *sd = evas_object_smart_data_get(obj);
3349    Evas_Coord ow, oh;
3350
3351    if (!sd) return;
3352    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3353    if ((ow == w) && (oh == h)) return;
3354    if ((sd->wd->mode == ELM_LIST_COMPRESS) && (ow != w))
3355      {
3356         /* fix me later */
3357         if (sd->resize_job) ecore_job_del(sd->resize_job);
3358         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
3359      }
3360    sd->wd->pan_changed = EINA_TRUE;
3361    evas_object_smart_changed(obj);
3362    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3363    sd->wd->calc_job = NULL;
3364 }
3365
3366 static void
3367 _pan_calculate(Evas_Object *obj)
3368 {
3369    Pan *sd = evas_object_smart_data_get(obj);
3370    Item_Block *itb;
3371    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
3372    int in = 0;
3373 //FIXME: group raise
3374 #if 0
3375    Elm_Gen_Item *git;
3376    Eina_List *l;
3377 #endif
3378
3379    if (!sd) return;
3380    evas_event_freeze(evas_object_evas_get(obj));
3381
3382    if (sd->wd->pan_changed)
3383      {
3384         _calc_job(sd->wd);
3385         sd->wd->pan_changed = EINA_FALSE;
3386      }
3387
3388    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3389    sd->wd->prev_viewport_w = ow;
3390    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
3391 //FIXME: group raise
3392 #if 0
3393    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
3394      {
3395         git->item->want_realize = EINA_FALSE;
3396      }
3397 #endif
3398
3399    if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
3400      {
3401         if (!sd->wd->tree_effect_animator)
3402           {
3403              _item_tree_effect_before(sd->wd->expanded_item);
3404              evas_object_raise(sd->wd->alpha_bg);
3405              evas_object_show(sd->wd->alpha_bg);
3406              sd->wd->start_time = ecore_time_get();
3407              sd->wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, sd->wd);
3408           }
3409      }
3410
3411    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3412      {
3413         itb->w = sd->wd->minw;
3414         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3415                                 itb->y - sd->wd->pan_y + oy,
3416                                 itb->w, itb->h,
3417                                 cvx, cvy, cvw, cvh))
3418           {
3419              if ((!itb->realized) || (itb->changed))
3420                {
3421                   _item_block_realize(itb);
3422
3423                   if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3424                   sd->wd->calc_job = NULL;
3425                   _calc_job(sd->wd);
3426                }
3427              _item_block_position(itb, in);
3428           }
3429         else
3430           {
3431              if (itb->realized) _item_block_unrealize(itb);
3432           }
3433         in += itb->count;
3434      }
3435 //FIXME: group raise
3436 #if 0
3437    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
3438       _group_items_recalc(sd->wd);
3439 #endif
3440    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3441      {
3442         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
3443            sd->wd->reorder_pan_move = EINA_TRUE;
3444         else sd->wd->reorder_pan_move = EINA_FALSE;
3445         evas_object_raise(sd->wd->VIEW(reorder_it));
3446         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
3447         sd->wd->start_time = ecore_loop_time_get();
3448      }
3449
3450    if (!sd->wd->tree_effect_enabled || (sd->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE))
3451      _item_auto_scroll(sd->wd);
3452
3453    evas_event_thaw(evas_object_evas_get(obj));
3454    evas_event_thaw_eval(evas_object_evas_get(obj));
3455 }
3456
3457 static void
3458 _pan_move(Evas_Object *obj,
3459           Evas_Coord   x __UNUSED__,
3460           Evas_Coord   y __UNUSED__)
3461 {
3462    Pan *sd = evas_object_smart_data_get(obj);
3463
3464    if (!sd) return;
3465
3466    sd->wd->pan_changed = EINA_TRUE;
3467    evas_object_smart_changed(obj);
3468    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3469    sd->wd->calc_job = NULL;
3470 }
3471
3472 static void
3473 _hold_on(void        *data __UNUSED__,
3474          Evas_Object *obj,
3475          void        *event_info __UNUSED__)
3476 {
3477    Widget_Data *wd = elm_widget_data_get(obj);
3478    if (!wd) return;
3479    elm_smart_scroller_hold_set(wd->scr, 1);
3480 }
3481
3482 static void
3483 _hold_off(void        *data __UNUSED__,
3484           Evas_Object *obj,
3485           void        *event_info __UNUSED__)
3486 {
3487    Widget_Data *wd = elm_widget_data_get(obj);
3488    if (!wd) return;
3489    elm_smart_scroller_hold_set(wd->scr, 0);
3490 }
3491
3492 static void
3493 _freeze_on(void        *data __UNUSED__,
3494            Evas_Object *obj,
3495            void        *event_info __UNUSED__)
3496 {
3497    Widget_Data *wd = elm_widget_data_get(obj);
3498    if (!wd) return;
3499    elm_smart_scroller_freeze_set(wd->scr, 1);
3500 }
3501
3502 static void
3503 _freeze_off(void        *data __UNUSED__,
3504             Evas_Object *obj,
3505             void        *event_info __UNUSED__)
3506 {
3507    Widget_Data *wd = elm_widget_data_get(obj);
3508    if (!wd) return;
3509    elm_smart_scroller_freeze_set(wd->scr, 0);
3510 }
3511
3512 static void
3513 _scr_anim_start(void        *data,
3514                 Evas_Object *obj __UNUSED__,
3515                 void        *event_info __UNUSED__)
3516 {
3517    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3518 }
3519
3520 static void
3521 _scr_anim_stop(void        *data,
3522                Evas_Object *obj __UNUSED__,
3523                void        *event_info __UNUSED__)
3524 {
3525    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3526 }
3527
3528 static void
3529 _scr_drag_start(void        *data,
3530                 Evas_Object *obj __UNUSED__,
3531                 void        *event_info __UNUSED__)
3532 {
3533    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3534 }
3535
3536 static void
3537 _scr_drag_stop(void        *data,
3538                Evas_Object *obj __UNUSED__,
3539                void        *event_info __UNUSED__)
3540 {
3541    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3542 }
3543
3544 static void
3545 _edge_left(void        *data,
3546            Evas_Object *scr __UNUSED__,
3547            void        *event_info __UNUSED__)
3548 {
3549    Evas_Object *obj = data;
3550    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3551 }
3552
3553 static void
3554 _edge_right(void        *data,
3555             Evas_Object *scr __UNUSED__,
3556             void        *event_info __UNUSED__)
3557 {
3558    Evas_Object *obj = data;
3559    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3560 }
3561
3562 static void
3563 _edge_top(void        *data,
3564           Evas_Object *scr __UNUSED__,
3565           void        *event_info __UNUSED__)
3566 {
3567    Evas_Object *obj = data;
3568    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3569 }
3570
3571 static void
3572 _edge_bottom(void        *data,
3573              Evas_Object *scr __UNUSED__,
3574              void        *event_info __UNUSED__)
3575 {
3576    Evas_Object *obj = data;
3577    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3578 }
3579
3580 static void
3581 _decorate_item_realize(Elm_Gen_Item *it)
3582 {
3583    char buf[1024];
3584
3585    if ((it->item->deco_it_view) || (it->generation < it->wd->generation)) return;
3586
3587    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3588    it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3589    edje_object_scale_set(it->item->deco_it_view,
3590                          elm_widget_scale_get(WIDGET(it)) *
3591                          _elm_config->scale);
3592    evas_object_smart_member_add(it->item->deco_it_view, it->wd->pan_smart);
3593    elm_widget_sub_object_add(WIDGET(it), it->item->deco_it_view);
3594
3595    strncpy(buf, "item", sizeof(buf));
3596    if (it->wd->mode == ELM_LIST_COMPRESS)
3597      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3598
3599    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3600    strncat(buf, "/", sizeof(buf) - strlen(buf));
3601    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
3602
3603    _elm_theme_object_set(WIDGET(it), it->item->deco_it_view, "genlist", buf,
3604                          elm_widget_style_get(WIDGET(it)));
3605    edje_object_mirrored_set(it->item->deco_it_view,
3606                             elm_widget_mirrored_get(WIDGET(it)));
3607
3608    /* signal callback add */
3609    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN,
3610                                   _mouse_down, it);
3611    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP,
3612                                   _mouse_up, it);
3613    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE,
3614                                   _mouse_move, it);
3615
3616    /* text_get, content_get, state_get */
3617    /* FIXME: If you see that assert, please notify us and we
3618       will clean our mess */
3619    assert(eina_list_count(it->item->deco_it_content_objs) == 0);
3620
3621    _item_text_realize(it, it->item->deco_it_view, &it->item->deco_it_texts, NULL);
3622    if (!it->item->deco_it_contents)
3623      it->item->deco_it_contents =
3624         elm_widget_stringlist_get(edje_object_data_get(it->item->deco_it_view, "contents"));
3625    it->item->deco_it_content_objs =
3626      _item_mode_content_realize(it, it->item->deco_it_view,
3627                                 &it->item->deco_it_contents, NULL,
3628                                 &it->item->deco_it_content_objs);
3629    _item_state_realize(it, it->item->deco_it_view, &it->item->deco_it_states, NULL);
3630    edje_object_part_swallow(it->item->deco_it_view,
3631                             edje_object_data_get(it->item->deco_it_view, "mode_part"),
3632                             VIEW(it));
3633
3634    it->want_unrealize = EINA_FALSE;
3635    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3636    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3637 }
3638
3639 static void
3640 _decorate_item_unrealize(Elm_Gen_Item *it)
3641 {
3642    Widget_Data *wd = it->wd;
3643    Evas_Object *content;
3644    if (!it->item->deco_it_view) return;
3645
3646    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3647    elm_widget_stringlist_free(it->item->deco_it_texts);
3648    it->item->deco_it_texts = NULL;
3649    elm_widget_stringlist_free(it->item->deco_it_contents);
3650    it->item->deco_it_contents = NULL;
3651    elm_widget_stringlist_free(it->item->deco_it_states);
3652
3653    EINA_LIST_FREE(it->item->deco_it_content_objs, content)
3654      evas_object_del(content);
3655
3656    edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
3657    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3658    evas_object_del(it->item->deco_it_view);
3659    it->item->deco_it_view = NULL;
3660
3661    if (wd->mode_item == it)
3662      wd->mode_item = NULL;
3663    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3664    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3665 }
3666
3667 static void
3668 _decorate_item_set(Elm_Gen_Item *it)
3669 {
3670    if (!it) return;
3671    Widget_Data *wd = it->wd;
3672    if (!wd) return;
3673    char buf[1024];
3674
3675    wd->mode_item = it;
3676    it->item->nocache_once = EINA_TRUE;
3677
3678    if (wd->scr_hold_timer)
3679      {
3680         ecore_timer_del(wd->scr_hold_timer);
3681         wd->scr_hold_timer = NULL;
3682      }
3683    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3684    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3685
3686    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3687    _decorate_item_realize(it);
3688    if (it->item->group_item)
3689      evas_object_raise(it->item->VIEW(group_item));
3690    _item_position(it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
3691    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3692    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3693
3694    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->decorate_it_type);
3695    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3696 }
3697
3698 static void
3699 _decorate_item_unset(Widget_Data *wd)
3700 {
3701    if (!wd) return;
3702    if (!wd->mode_item) return;
3703    char buf[1024], buf2[1024];
3704    Elm_Gen_Item *it;
3705
3706    it = wd->mode_item;
3707    it->item->nocache_once = EINA_TRUE;
3708
3709    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->decorate_it_type);
3710    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->decorate_it_type);
3711
3712    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3713    edje_object_signal_callback_add(it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb, it);
3714
3715    wd->mode_item = NULL;
3716 }
3717
3718 static void
3719 _decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity)
3720 {
3721    if ((!it) || (!it->wd->decorate_all_mode)) return;
3722    evas_object_resize(it->deco_all_view, it->item->w, it->item->h);
3723    evas_object_move(it->deco_all_view, itx, ity);
3724 }
3725
3726 static void
3727 _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3728 {
3729    char buf[1024];
3730    const char *stacking_even;
3731    const char *stacking;
3732
3733    if ((!it) || (it->item->decorate_all_item_realized) ||
3734        (it->generation < it->wd->generation))
3735      return;
3736
3737    it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3738    edje_object_scale_set(it->deco_all_view, elm_widget_scale_get(WIDGET(it)) *
3739                          _elm_config->scale);
3740    evas_object_smart_member_add(it->deco_all_view, it->wd->pan_smart);
3741    elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
3742
3743    if (it->item->type & ELM_GENLIST_ITEM_TREE)
3744       strncpy(buf, "tree", sizeof(buf));
3745    else strncpy(buf, "item", sizeof(buf));
3746    if (it->wd->mode == ELM_LIST_COMPRESS)
3747       strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3748
3749    strncat(buf, "/", sizeof(buf) - strlen(buf));
3750    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
3751
3752    _elm_theme_object_set(WIDGET(it),  it->deco_all_view, "genlist", buf,
3753                          elm_widget_style_get(WIDGET(it)));
3754
3755    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3756    if (!stacking_even) stacking_even = "above";
3757    it->item->stacking_even = !!strcmp("above", stacking_even);
3758
3759    stacking = edje_object_data_get(VIEW(it), "stacking");
3760    if (!stacking) stacking = "yes";
3761    it->item->nostacking = !!strcmp("yes", stacking);
3762
3763    edje_object_mirrored_set(it->deco_all_view,
3764                             elm_widget_mirrored_get(WIDGET(it)));
3765
3766    _elm_genlist_item_odd_even_update(it);
3767    _elm_genlist_item_state_update(it, NULL);
3768
3769    if (effect_on) edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled,effect", "elm");
3770    else edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled", "elm");
3771
3772    _item_mouse_callbacks_del(it, VIEW(it));
3773    _item_mouse_callbacks_add(it, it->deco_all_view);
3774
3775    _item_text_realize(it, it->deco_all_view, &it->item->deco_all_texts, NULL);
3776    if (it->flipped) edje_object_signal_emit(it->deco_all_view, "elm,state,flip,enabled", "elm");
3777    if (!it->item->deco_all_contents)
3778      it->item->deco_all_contents =
3779         elm_widget_stringlist_get(edje_object_data_get(it->deco_all_view, "decorate_contents"));
3780    it->item->deco_all_content_objs =
3781      _item_mode_content_realize(it, it->deco_all_view,
3782                                 &it->item->deco_all_contents, NULL,
3783                                 &it->item->deco_all_content_objs);
3784    _item_state_realize(it, it->deco_all_view, &it->item->deco_all_states, NULL);
3785    edje_object_part_swallow(it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
3786
3787    _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
3788    evas_object_show(it->deco_all_view);
3789
3790    if (it->selected) edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
3791
3792    it->item->decorate_all_item_realized = EINA_TRUE;
3793    it->want_unrealize = EINA_FALSE;
3794 }
3795
3796 static void
3797 _decorate_all_item_unrealize(Elm_Gen_Item *it)
3798 {
3799    Evas_Object *icon;
3800    if ((!it) || (!it->item->decorate_all_item_realized)) return;
3801
3802    edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3803    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3804    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3805    _elm_genlist_item_odd_even_update(it);
3806    _elm_genlist_item_state_update(it, NULL);
3807
3808    evas_object_del(it->deco_all_view);
3809    it->deco_all_view = NULL;
3810    elm_widget_stringlist_free(it->item->deco_all_texts);
3811    it->item->deco_all_texts = NULL;
3812    elm_widget_stringlist_free(it->item->deco_all_contents);
3813    it->item->deco_all_contents = NULL;
3814    elm_widget_stringlist_free(it->item->deco_all_states);
3815    it->item->deco_all_states = NULL;
3816    EINA_LIST_FREE(it->item->deco_all_content_objs, icon)
3817      evas_object_del(icon);
3818    edje_object_message_signal_process(it->deco_all_view);
3819    _item_mouse_callbacks_del(it, it->deco_all_view);
3820    _item_mouse_callbacks_add(it, VIEW(it));
3821
3822    it->item->decorate_all_item_realized = EINA_FALSE;
3823 }
3824
3825 static void
3826 _item_auto_scroll(Widget_Data *wd)
3827 {
3828    if (!wd) return;
3829    Elm_Gen_Item  *tmp_item = NULL;
3830
3831    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3832      {
3833         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3834         if (!tmp_item) return;
3835         wd->show_item = tmp_item;
3836         wd->bring_in = EINA_TRUE;
3837         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3838         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3839           {
3840              wd->show_item->item->showme = EINA_TRUE;
3841              wd->auto_scroll_enabled = EINA_FALSE;
3842           }
3843         else
3844           _scroll_item(wd);
3845      }
3846 }
3847
3848 EAPI Evas_Object *
3849 elm_genlist_add(Evas_Object *parent)
3850 {
3851    Evas_Object *obj;
3852    Evas *e;
3853    Widget_Data *wd;
3854    Evas_Coord minw, minh;
3855    static Evas_Smart *smart = NULL;
3856
3857    if (!smart)
3858      {
3859         static Evas_Smart_Class sc;
3860
3861         evas_object_smart_clipped_smart_set(&_pan_sc);
3862         sc = _pan_sc;
3863         sc.name = "elm_genlist_pan";
3864         sc.version = EVAS_SMART_CLASS_VERSION;
3865         sc.add = _pan_add;
3866         sc.del = _pan_del;
3867         sc.resize = _pan_resize;
3868         sc.move = _pan_move;
3869         sc.calculate = _pan_calculate;
3870         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3871      }
3872
3873    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3874
3875    ELM_SET_WIDTYPE(widtype, "genlist");
3876    ELM_GEN_SETUP(wd);
3877    elm_widget_type_set(obj, "genlist");
3878    elm_widget_sub_object_add(parent, obj);
3879    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3880    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3881    elm_widget_data_set(obj, wd);
3882    elm_widget_del_hook_set(obj, _del_hook);
3883    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3884    elm_widget_theme_hook_set(obj, _theme_hook);
3885    elm_widget_can_focus_set(obj, EINA_TRUE);
3886    elm_widget_event_hook_set(obj, _event_hook);
3887    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3888    elm_widget_translate_hook_set(obj, _translate_hook);
3889
3890    wd->generation = 1;
3891    wd->scr = elm_smart_scroller_add(e);
3892    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_DOWN,
3893                                   _mouse_down_scroller, obj);
3894    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_UP,
3895                                   _mouse_up_scroller, obj);
3896    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_MOVE,
3897                                   _mouse_move_scroller, obj);
3898    elm_smart_scroller_widget_set(wd->scr, obj);
3899    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3900                                        elm_widget_style_get(obj));
3901    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3902                                        _elm_config->thumbscroll_bounce_enable);
3903    elm_widget_resize_object_set(obj, wd->scr);
3904
3905    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3906    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3907    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3908    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3909    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3910    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3911    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3912    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3913
3914    wd->obj = obj;
3915    wd->mode = ELM_LIST_SCROLL;
3916    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3917    wd->item_cache_max = wd->max_items_per_block * 2;
3918    wd->longpress_timeout = _elm_config->longpress_timeout;
3919    wd->highlight = EINA_TRUE;
3920    wd->tree_effect_enabled = _elm_config->effect_enable;
3921
3922    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3923    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3924    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3925    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3926
3927    wd->pan_smart = evas_object_smart_add(e, smart);
3928    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3929    wd->pan->wd = wd;
3930
3931    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3932                                      _pan_set, _pan_get, _pan_max_get,
3933                                      _pan_min_get, _pan_child_size_get);
3934
3935    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3936                              &minw, &minh);
3937    evas_object_size_hint_min_set(obj, minw, minh);
3938
3939    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3940
3941    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3942    _sizing_eval(obj);
3943    return obj;
3944 }
3945
3946 void
3947 _item_select(Elm_Gen_Item *it)
3948 {
3949    Eina_List *l;
3950    Evas_Object *obj = WIDGET(it);
3951    Evas_Object *item_obj;
3952
3953    if ((it->generation < it->wd->generation) || (it->decorate_it_set) ||
3954        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
3955        (it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
3956      return;
3957    if (!it->selected)
3958      {
3959         it->selected = EINA_TRUE;
3960         it->wd->selected = eina_list_append(it->wd->selected, it);
3961      }
3962    else if (it->wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) return;
3963
3964    evas_object_ref(obj);
3965    it->walking++;
3966    it->wd->walking++;
3967    if (it->wd->last_selected_item &&
3968        (it != (Elm_Gen_Item *) it->wd->last_selected_item))
3969      {
3970         Elm_Gen_Item *_lsit = (Elm_Gen_Item *)it->wd->last_selected_item;
3971
3972         EINA_LIST_FOREACH(_lsit->content_objs, l, item_obj)
3973           {
3974              elm_widget_focused_object_clear(item_obj);
3975              elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
3976           }
3977         if (elm_widget_type_get(obj) == _genlist)
3978           {
3979              EINA_LIST_FOREACH(_lsit->item->flip_content_objs, l, item_obj)
3980                {
3981                   elm_widget_focused_object_clear(item_obj);
3982                   elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
3983                }
3984              EINA_LIST_FOREACH(_lsit->item->deco_all_content_objs, l, item_obj)
3985                {
3986                   elm_widget_focused_object_clear(item_obj);
3987                   elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
3988                }
3989           }
3990         _lsit->can_focus = EINA_FALSE;
3991      }
3992    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3993    if (it->generation == it->wd->generation)
3994      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3995    it->walking--;
3996    it->wd->walking--;
3997    if ((it->wd->clear_me) && (!it->wd->walking))
3998      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3999    else
4000      {
4001         if ((!it->walking) && (it->generation < it->wd->generation))
4002           {
4003              if (!it->relcount)
4004                {
4005                   it->del_cb(it);
4006                   elm_widget_item_free(it);
4007                }
4008           }
4009         else
4010           it->wd->last_selected_item = (Elm_Object_Item *)it;
4011      }
4012    evas_object_unref(obj);
4013 }
4014
4015 static Evas_Object *
4016 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
4017 {
4018    return edje_object_part_swallow_get(VIEW(it), part);
4019 }
4020
4021 static void
4022 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
4023 {
4024    if (content && part)
4025      {
4026         it->content_objs = eina_list_append(it->content_objs, content);
4027         edje_object_part_swallow(VIEW(it), part, content);
4028      }
4029 }
4030
4031 static Evas_Object *
4032 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
4033 {
4034    Evas_Object *obj;
4035    obj = edje_object_part_swallow_get(VIEW(it), part);
4036    if (!obj) return NULL;
4037    it->content_objs = eina_list_remove(it->content_objs, obj);
4038    edje_object_part_unswallow(VIEW(it), obj);
4039    return obj;
4040 }
4041
4042 static const char *
4043 _item_text_get_hook(Elm_Gen_Item *it, const char *part)
4044 {
4045    if (!it->itc->func.text_get) return NULL;
4046    return edje_object_part_text_get(VIEW(it), part);
4047 }
4048
4049 static void
4050 _item_disable_hook(Elm_Object_Item *it)
4051 {
4052    Eina_List *l;
4053    Evas_Object *obj;
4054    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4055
4056    if (_it->generation < _it->wd->generation) return;
4057
4058    if (_it->selected)
4059      elm_genlist_item_selected_set(it, EINA_FALSE);
4060
4061    if (_it->realized)
4062      {
4063         if (elm_widget_item_disabled_get(it))
4064           {
4065              edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
4066              if (_it->deco_all_view)
4067                edje_object_signal_emit(_it->deco_all_view, "elm,state,disabled", "elm");
4068           }
4069         else
4070           {
4071              edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
4072              if (_it->deco_all_view)
4073                edje_object_signal_emit(_it->deco_all_view, "elm,state,enabled", "elm");
4074           }
4075         EINA_LIST_FOREACH(_it->content_objs, l, obj)
4076           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
4077      }
4078 }
4079
4080 static Eina_Bool
4081 _item_del_pre_hook(Elm_Object_Item *it)
4082 {
4083    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4084
4085    if ((_it->relcount > 0) || (_it->walking > 0))
4086      {
4087         elm_genlist_item_subitems_clear(it);
4088         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
4089         _elm_genlist_item_del_notserious(_it);
4090         if (_it->item->block)
4091           {
4092              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
4093              _it->item->block->changed = EINA_TRUE;
4094              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
4095              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
4096           }
4097         if (_it->parent)
4098           {
4099              _it->parent->item->items =
4100                 eina_list_remove(_it->parent->item->items, it);
4101              _it->parent = NULL;
4102           }
4103         return EINA_FALSE;
4104      }
4105    _item_del(_it);
4106    return EINA_TRUE;
4107 }
4108
4109 static void
4110 _item_signal_emit_hook(Elm_Object_Item *it,
4111                        const char *emission,
4112                        const char *source)
4113 {
4114    edje_object_signal_emit(VIEW(it), emission, source);
4115 }
4116
4117 Elm_Gen_Item *
4118 _elm_genlist_item_new(Widget_Data              *wd,
4119                       const Elm_Gen_Item_Class *itc,
4120                       const void               *data,
4121                       Elm_Gen_Item             *parent,
4122                       Evas_Smart_Cb             func,
4123                       const void               *func_data)
4124 {
4125    Elm_Gen_Item *it;
4126
4127    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
4128    if (!it) return NULL;
4129    it->wd = wd;
4130    it->generation = wd->generation;
4131    it->itc = itc;
4132    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
4133    it->base.data = data;
4134    it->parent = parent;
4135    it->func.func = func;
4136    it->func.data = func_data;
4137    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
4138    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
4139    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
4140    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
4141    elm_widget_item_disable_hook_set(it, _item_disable_hook);
4142    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
4143    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
4144
4145    /* TEMPORARY */
4146    it->sel_cb = (Ecore_Cb)_item_select;
4147
4148    return it;
4149 }
4150
4151 static Elm_Gen_Item *
4152 _item_new(Widget_Data                  *wd,
4153           const Elm_Genlist_Item_Class *itc,
4154           const void                   *data,
4155           Elm_Gen_Item                 *parent,
4156           Elm_Genlist_Item_Type         type,
4157           Evas_Smart_Cb                 func,
4158           const void                   *func_data)
4159 {
4160    Elm_Gen_Item *it, *it2;
4161    int depth = 0;
4162
4163    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
4164    if (!it) return NULL;
4165    it->item = ELM_NEW(Elm_Gen_Item_Type);
4166    it->item->type = type;
4167    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
4168    it->item->expanded_depth = 0;
4169    ELM_GEN_ITEM_SETUP(it);
4170    it->mouse_cursor = NULL;
4171    it->can_focus = EINA_TRUE;
4172    if (it->parent)
4173      {
4174         if (it->parent->group)
4175           it->item->group_item = parent;
4176         else if (it->parent->item->group_item)
4177           it->item->group_item = it->parent->item->group_item;
4178      }
4179    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
4180      {
4181         if (!it2->parent->group) depth += 1;
4182      }
4183    it->item->expanded_depth = depth;
4184    wd->item_count++;
4185    return it;
4186 }
4187
4188 static Item_Block *
4189 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
4190 {
4191    Item_Block *itb;
4192
4193    itb = calloc(1, sizeof(Item_Block));
4194    if (!itb) return NULL;
4195    itb->wd = wd;
4196    if (prepend)
4197      {
4198         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
4199         _item_block_position_update(wd->blocks, 0);
4200      }
4201    else
4202      {
4203         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4204         itb->position_update = EINA_TRUE;
4205         if (wd->blocks != EINA_INLIST_GET(itb))
4206           {
4207              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4208           }
4209         else
4210           {
4211              itb->position = 0;
4212           }
4213      }
4214    return itb;
4215 }
4216
4217 static Eina_Bool
4218 _item_block_add(Widget_Data  *wd,
4219                 Elm_Gen_Item *it)
4220 {
4221    Item_Block *itb = NULL;
4222
4223    if (!it->item->rel)
4224      {
4225 newblock:
4226         if (it->item->rel)
4227           {
4228              itb = calloc(1, sizeof(Item_Block));
4229              if (!itb) return EINA_FALSE;
4230              itb->wd = wd;
4231              if (!it->item->rel->item->block)
4232                {
4233                   wd->blocks =
4234                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4235                   itb->items = eina_list_append(itb->items, it);
4236                   itb->position_update = EINA_TRUE;
4237                   it->position = eina_list_count(itb->items);
4238                   it->position_update = EINA_TRUE;
4239
4240                   if (wd->blocks != EINA_INLIST_GET(itb))
4241                     {
4242                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4243                     }
4244                   else
4245                     {
4246                        itb->position = 0;
4247                     }
4248                }
4249              else
4250                {
4251                   Eina_List *tmp;
4252
4253                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
4254                   if (it->item->before)
4255                     {
4256                        wd->blocks = eina_inlist_prepend_relative
4257                            (wd->blocks, EINA_INLIST_GET(itb),
4258                            EINA_INLIST_GET(it->item->rel->item->block));
4259                        itb->items =
4260                          eina_list_prepend_relative_list(itb->items, it, tmp);
4261
4262                        /* Update index from where we prepended */
4263                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4264                        _item_block_position_update(EINA_INLIST_GET(itb),
4265                                                    it->item->rel->item->block->position);
4266                     }
4267                   else
4268                     {
4269                        wd->blocks = eina_inlist_append_relative
4270                            (wd->blocks, EINA_INLIST_GET(itb),
4271                            EINA_INLIST_GET(it->item->rel->item->block));
4272                        itb->items =
4273                          eina_list_append_relative_list(itb->items, it, tmp);
4274
4275                        /* Update block index from where we appended */
4276                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4277                        _item_block_position_update(EINA_INLIST_GET(itb),
4278                                                    it->item->rel->item->block->position + 1);
4279                     }
4280                }
4281           }
4282         else
4283           {
4284              if (it->item->before)
4285                {
4286                   if (wd->blocks)
4287                     {
4288                        itb = (Item_Block *)(wd->blocks);
4289                        if (itb->count >= wd->max_items_per_block)
4290                          {
4291                             itb = _item_block_new(wd, EINA_TRUE);
4292                             if (!itb) return EINA_FALSE;
4293                          }
4294                     }
4295                   else
4296                     {
4297                        itb = _item_block_new(wd, EINA_TRUE);
4298                        if (!itb) return EINA_FALSE;
4299                     }
4300                   itb->items = eina_list_prepend(itb->items, it);
4301
4302                   _item_position_update(itb->items, 0);
4303                }
4304              else
4305                {
4306                   if (wd->blocks)
4307                     {
4308                        itb = (Item_Block *)(wd->blocks->last);
4309                        if (itb->count >= wd->max_items_per_block)
4310                          {
4311                             itb = _item_block_new(wd, EINA_FALSE);
4312                             if (!itb) return EINA_FALSE;
4313                          }
4314                     }
4315                   else
4316                     {
4317                        itb = _item_block_new(wd, EINA_FALSE);
4318                        if (!itb) return EINA_FALSE;
4319                     }
4320                   itb->items = eina_list_append(itb->items, it);
4321                   it->position = eina_list_count(itb->items);
4322                }
4323           }
4324      }
4325    else
4326      {
4327         Eina_List *tmp;
4328
4329         if (it->item->rel->item->queued)
4330           {
4331              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
4332                 on sorted insertion order, so the queue is not always ordered like the item list.
4333                 This lead to issue where we depend on an item that is not yet created. As a quick
4334                 work around, we reschedule the calc of the item and stop reordering the list to
4335                 prevent any nasty issue to show up here.
4336               */
4337              wd->queue = eina_list_append(wd->queue, it);
4338              wd->requeued = EINA_TRUE;
4339              it->item->queued = EINA_TRUE;
4340              return EINA_FALSE;
4341           }
4342         itb = it->item->rel->item->block;
4343         if (!itb) goto newblock;
4344         tmp = eina_list_data_find_list(itb->items, it->item->rel);
4345         if (it->item->before)
4346           {
4347              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
4348              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4349           }
4350         else
4351           {
4352              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
4353              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4354           }
4355      }
4356    itb->count++;
4357    itb->changed = EINA_TRUE;
4358    it->item->block = itb;
4359    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
4360    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
4361    if (it->item->rel)
4362      {
4363         it->item->rel->relcount--;
4364         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
4365           {
4366              _item_del(it->item->rel);
4367              elm_widget_item_free(it->item->rel);
4368           }
4369         it->item->rel = NULL;
4370      }
4371    if (itb->count > itb->wd->max_items_per_block)
4372      {
4373         Item_Block *itb2;
4374         Elm_Gen_Item *it2;
4375         int newc;
4376         Eina_Bool done = EINA_FALSE;
4377
4378         newc = itb->count / 2;
4379
4380         if (EINA_INLIST_GET(itb)->prev)
4381           {
4382              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
4383
4384              if (itbp->count + newc < wd->max_items_per_block / 2)
4385                {
4386                   /* moving items to previous block */
4387                   while ((itb->count > newc) && (itb->items))
4388                     {
4389                        it2 = eina_list_data_get(itb->items);
4390                        itb->items = eina_list_remove_list(itb->items, itb->items);
4391                        itb->count--;
4392
4393                        itbp->items = eina_list_append(itbp->items, it2);
4394                        it2->item->block = itbp;
4395                        itbp->count++;
4396                     }
4397
4398                   done = EINA_TRUE;
4399                }
4400           }
4401
4402         if (!done && EINA_INLIST_GET(itb)->next)
4403           {
4404              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4405
4406              if (itbn->count + newc < wd->max_items_per_block / 2)
4407                {
4408                   /* moving items to next block */
4409                   while ((itb->count > newc) && (itb->items))
4410                     {
4411                        Eina_List *l;
4412
4413                        l = eina_list_last(itb->items);
4414                        it2 = eina_list_data_get(l);
4415                        itb->items = eina_list_remove_list(itb->items, l);
4416                        itb->count--;
4417
4418                        itbn->items = eina_list_prepend(itbn->items, it2);
4419                        it2->item->block = itbn;
4420                        itbn->count++;
4421                     }
4422
4423                   done = EINA_TRUE;
4424                }
4425           }
4426
4427         if (!done)
4428           {
4429              /* moving items to new block */
4430              itb2 = calloc(1, sizeof(Item_Block));
4431              if (!itb2) return EINA_FALSE;
4432              itb2->wd = wd;
4433              wd->blocks =
4434                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
4435                                            EINA_INLIST_GET(itb));
4436              itb2->changed = EINA_TRUE;
4437              while ((itb->count > newc) && (itb->items))
4438                {
4439                   Eina_List *l;
4440
4441                   l = eina_list_last(itb->items);
4442                   it2 = l->data;
4443                   itb->items = eina_list_remove_list(itb->items, l);
4444                   itb->count--;
4445
4446                   itb2->items = eina_list_prepend(itb2->items, it2);
4447                   it2->item->block = itb2;
4448                   itb2->count++;
4449                }
4450           }
4451      }
4452
4453    return EINA_TRUE;
4454 }
4455
4456 static int
4457 _item_process(Widget_Data *wd, Elm_Gen_Item *it)
4458 {
4459    if (!_item_block_add(wd, it)) return 1;
4460    if (!wd->blocks)
4461      _item_block_realize(it->item->block);
4462    return 0;
4463 }
4464
4465 static void
4466 _item_process_post(Widget_Data *wd, Elm_Gen_Item *it, Eina_Bool qadd)
4467 {
4468    Eina_Bool showme = EINA_FALSE;
4469
4470    if (it->item->block->changed)
4471      {
4472         showme = _item_block_recalc(it->item->block, it->item->block->num, qadd);
4473         it->item->block->changed = 0;
4474         if (wd->pan_changed)
4475           {
4476              if (wd->calc_job) ecore_job_del(wd->calc_job);
4477              wd->calc_job = NULL;
4478              _calc_job(wd);
4479              wd->pan_changed = EINA_FALSE;
4480           }
4481      }
4482    if (showme) it->item->block->showme = EINA_TRUE;
4483 }
4484
4485 static int
4486 _queue_process(Widget_Data *wd)
4487 {
4488    int n;
4489    double t0, t;
4490
4491    t0 = ecore_loop_time_get();
4492    //evas_event_freeze(evas_object_evas_get(wd->obj));
4493    for (n = 0; (wd->queue) && (n < 128); n++)
4494      {
4495         Elm_Gen_Item *it;
4496
4497         it = eina_list_data_get(wd->queue);
4498         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4499         it->item->queued = EINA_FALSE;
4500         if (_item_process(wd, it)) continue;
4501         t = ecore_time_get();
4502         _item_process_post(wd, it, EINA_TRUE);
4503         /* same as eina_inlist_count > 1 */
4504         if (wd->blocks && wd->blocks->next)
4505           {
4506              if ((t - t0) > (ecore_animator_frametime_get())) break;
4507           }
4508      }
4509    //evas_event_thaw(evas_object_evas_get(wd->obj));
4510    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4511    return n;
4512 }
4513
4514 static Eina_Bool
4515 _idle_process(void *data, Eina_Bool *wakeup)
4516 {
4517    Widget_Data *wd = data;
4518
4519    //xxx
4520    //static double q_start = 0.0;
4521    //if (q_start == 0.0) q_start = ecore_time_get();
4522    //xxx
4523    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4524    if (!wd->queue)
4525      {
4526         //xxx
4527         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4528         //xxx
4529         return ECORE_CALLBACK_CANCEL;
4530      }
4531    return ECORE_CALLBACK_RENEW;
4532 }
4533
4534 static Eina_Bool
4535 _item_idle_enterer(void *data)
4536 {
4537    Widget_Data *wd = data;
4538    Eina_Bool wakeup = EINA_FALSE;
4539    Eina_Bool ok = _idle_process(data, &wakeup);
4540
4541    if (wakeup)
4542      {
4543         // wake up mainloop
4544         if (wd->calc_job) ecore_job_del(wd->calc_job);
4545         wd->calc_job = ecore_job_add(_calc_job, wd);
4546      }
4547    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4548    return ok;
4549 }
4550
4551 static void
4552 _item_queue(Widget_Data    *wd,
4553             Elm_Gen_Item   *it,
4554             Eina_Compare_Cb cb)
4555 {
4556    if (it->item->queued) return;
4557    if ((wd->blocks) && (wd->homogeneous) && (wd->mode == ELM_LIST_COMPRESS))
4558      {
4559         if (!_item_process(wd, it))
4560           _item_process_post(wd, it, EINA_FALSE);
4561         return;
4562      }
4563    it->item->queued = EINA_TRUE;
4564    if (cb && !wd->requeued)
4565      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4566    else
4567      wd->queue = eina_list_append(wd->queue, it);
4568 // FIXME: why does a freeze then thaw here cause some genlist
4569 // elm_genlist_item_append() to be much much slower?
4570 //   evas_event_freeze(evas_object_evas_get(wd->obj));
4571    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4572      {
4573         if (wd->queue_idle_enterer)
4574           {
4575              ecore_idle_enterer_del(wd->queue_idle_enterer);
4576              wd->queue_idle_enterer = NULL;
4577           }
4578         _queue_process(wd);
4579      }
4580 //   evas_event_thaw(evas_object_evas_get(wd->obj));
4581 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4582    if (!wd->queue_idle_enterer)
4583      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4584 }
4585
4586 static int
4587 _elm_genlist_item_compare(const void *data, const void *data1)
4588 {
4589    const Elm_Gen_Item *it, *item1;
4590    it = ELM_GEN_ITEM_FROM_INLIST(data);
4591    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4592    return it->wd->item_compare_cb(it, item1);
4593 }
4594
4595 static int
4596 _elm_genlist_item_list_compare(const void *data, const void *data1)
4597 {
4598    const Elm_Gen_Item *it = data;
4599    const Elm_Gen_Item *item1 = data1;
4600    return it->wd->item_compare_cb(it, item1);
4601 }
4602
4603 /*If application want to know the relative item, use elm_genlist_item_prev_get(it)*/
4604 static void
4605 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4606 {
4607    if (!it) return;
4608    if (!after) return;
4609
4610    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4611    _item_block_del(it);
4612
4613    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4614    it->item->rel = after;
4615    it->item->rel->relcount++;
4616    it->item->before = EINA_FALSE;
4617    if (after->item->group_item) it->item->group_item = after->item->group_item;
4618    _item_queue(it->wd, it, NULL);
4619
4620    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_AFTER, it);
4621 }
4622
4623 /*If application want to know the relative item, use elm_genlist_item_next_get(it)*/
4624 static void
4625 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4626 {
4627    if (!it) return;
4628    if (!before) return;
4629
4630    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4631    _item_block_del(it);
4632    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4633    it->item->rel = before;
4634    it->item->rel->relcount++;
4635    it->item->before = EINA_TRUE;
4636    if (before->item->group_item) it->item->group_item = before->item->group_item;
4637    _item_queue(it->wd, it, NULL);
4638
4639    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_BEFORE, it);
4640 }
4641
4642 EAPI unsigned int
4643 elm_genlist_items_count(const Evas_Object *obj)
4644 {
4645    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4646    Widget_Data *wd = elm_widget_data_get(obj);
4647    if (!wd) return 0;
4648    return wd->item_count;
4649 }
4650
4651 EAPI Elm_Object_Item *
4652 elm_genlist_item_append(Evas_Object                  *obj,
4653                         const Elm_Genlist_Item_Class *itc,
4654                         const void                   *data,
4655                         Elm_Object_Item              *parent,
4656                         Elm_Genlist_Item_Type         type,
4657                         Evas_Smart_Cb                 func,
4658                         const void                   *func_data)
4659 {
4660    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4661    Widget_Data *wd = elm_widget_data_get(obj);
4662    if (!wd) return NULL;
4663    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4664                                 func, func_data);
4665    if (!it) return NULL;
4666    if (!it->parent)
4667      {
4668         if (it->group)
4669           wd->group_items = eina_list_append(wd->group_items, it);
4670         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4671         it->item->rel = NULL;
4672      }
4673    else
4674      {
4675         Elm_Gen_Item *it2 = NULL;
4676         Eina_List *ll = eina_list_last(it->parent->item->items);
4677         if (ll) it2 = ll->data;
4678         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4679         if (!it2) it2 = it->parent;
4680         wd->items =
4681           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4682                                       EINA_INLIST_GET(it2));
4683         it->item->rel = it2;
4684         it->item->rel->relcount++;
4685      }
4686    it->item->before = EINA_FALSE;
4687    _item_queue(wd, it, NULL);
4688    return (Elm_Object_Item *)it;
4689 }
4690
4691 EAPI Elm_Object_Item *
4692 elm_genlist_item_prepend(Evas_Object                  *obj,
4693                          const Elm_Genlist_Item_Class *itc,
4694                          const void                   *data,
4695                          Elm_Object_Item              *parent,
4696                          Elm_Genlist_Item_Type         type,
4697                          Evas_Smart_Cb                 func,
4698                          const void                   *func_data)
4699 {
4700    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4701    Widget_Data *wd = elm_widget_data_get(obj);
4702    if (!wd) return NULL;
4703    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4704                                 func, func_data);
4705    if (!it) return NULL;
4706    if (!it->parent)
4707      {
4708         if (it->group)
4709           wd->group_items = eina_list_prepend(wd->group_items, it);
4710         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4711         it->item->rel = NULL;
4712      }
4713    else
4714      {
4715         Elm_Gen_Item *it2 = NULL;
4716         Eina_List *ll = it->parent->item->items;
4717         if (ll) it2 = ll->data;
4718         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4719         if (!it2) it2 = it->parent;
4720         wd->items =
4721           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4722                                        EINA_INLIST_GET(it2));
4723         it->item->rel = it2;
4724         it->item->rel->relcount++;
4725      }
4726    it->item->before = EINA_TRUE;
4727    _item_queue(wd, it, NULL);
4728    return (Elm_Object_Item *)it;
4729 }
4730
4731 EAPI Elm_Object_Item *
4732 elm_genlist_item_insert_after(Evas_Object                  *obj,
4733                               const Elm_Genlist_Item_Class *itc,
4734                               const void                   *data,
4735                               Elm_Object_Item              *parent,
4736                               Elm_Object_Item              *after,
4737                               Elm_Genlist_Item_Type         type,
4738                               Evas_Smart_Cb                 func,
4739                               const void                   *func_data)
4740 {
4741    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4742    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4743    Widget_Data *wd = elm_widget_data_get(obj);
4744    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4745    if (!wd) return NULL;
4746    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4747    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4748
4749    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4750                                 func, func_data);
4751    if (!it) return NULL;
4752    if (!it->parent)
4753      {
4754         if ((it->group) && (_after->group))
4755           wd->group_items = eina_list_append_relative(wd->group_items, it,
4756                                                       _after);
4757      }
4758    else
4759      {
4760         it->parent->item->items =
4761            eina_list_append_relative(it->parent->item->items, it, _after);
4762      }
4763    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4764                                            EINA_INLIST_GET(_after));
4765    it->item->rel = _after;
4766    it->item->rel->relcount++;
4767    it->item->before = EINA_FALSE;
4768    _item_queue(wd, it, NULL);
4769    return (Elm_Object_Item *)it;
4770 }
4771
4772 EAPI Elm_Object_Item *
4773 elm_genlist_item_insert_before(Evas_Object                  *obj,
4774                                const Elm_Genlist_Item_Class *itc,
4775                                const void                   *data,
4776                                Elm_Object_Item              *parent,
4777                                Elm_Object_Item              *before,
4778                                Elm_Genlist_Item_Type         type,
4779                                Evas_Smart_Cb                 func,
4780                                const void                   *func_data)
4781 {
4782    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4783    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4784    Widget_Data *wd = elm_widget_data_get(obj);
4785    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4786    if (!wd) return NULL;
4787    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4788    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4789
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    if (!it->parent)
4794      {
4795         if (it->group && _before->group)
4796           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4797                                                        _before);
4798      }
4799    else
4800      {
4801         it->parent->item->items =
4802            eina_list_prepend_relative(it->parent->item->items, it, _before);
4803      }
4804    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4805                                             EINA_INLIST_GET(_before));
4806    it->item->rel = _before;
4807    it->item->rel->relcount++;
4808    it->item->before = EINA_TRUE;
4809    _item_queue(wd, it, NULL);
4810    return (Elm_Object_Item *)it;
4811 }
4812
4813 EAPI Elm_Object_Item *
4814 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4815                                const Elm_Genlist_Item_Class *itc,
4816                                const void                   *data,
4817                                Elm_Object_Item              *parent,
4818                                Elm_Genlist_Item_Type         type,
4819                                Eina_Compare_Cb               comp,
4820                                Evas_Smart_Cb                 func,
4821                                const void                   *func_data)
4822 {
4823    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4824    Widget_Data *wd = elm_widget_data_get(obj);
4825    if (!wd) return NULL;
4826    Elm_Gen_Item *rel = NULL;
4827    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4828                                 func, func_data);
4829    if (!it) return NULL;
4830
4831    wd->item_compare_cb = comp;
4832
4833    if (it->parent)
4834      {
4835         Eina_List *l;
4836         int cmp_result;
4837
4838         l = eina_list_search_sorted_near_list(it->parent->item->items,
4839                                               _elm_genlist_item_list_compare,
4840                                               it,
4841                                               &cmp_result);
4842         if (l)
4843           rel = eina_list_data_get(l);
4844         else
4845           rel = it->parent;
4846
4847         if (cmp_result >= 0)
4848           {
4849              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4850              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4851              it->item->before = EINA_FALSE;
4852           }
4853         else if (cmp_result < 0)
4854           {
4855              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4856              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4857              it->item->before = EINA_TRUE;
4858           }
4859      }
4860    else
4861      {
4862         if (!wd->state)
4863           {
4864              wd->state = eina_inlist_sorted_state_new();
4865              eina_inlist_sorted_state_init(wd->state, wd->items);
4866              wd->requeued = EINA_FALSE;
4867           }
4868
4869         if (it->group)
4870           wd->group_items = eina_list_append(wd->group_items, it);
4871
4872         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4873                                                     _elm_genlist_item_compare, wd->state);
4874
4875         if (EINA_INLIST_GET(it)->next)
4876           {
4877              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4878              it->item->before = EINA_TRUE;
4879           }
4880         else if (EINA_INLIST_GET(it)->prev)
4881           {
4882              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4883              it->item->before = EINA_FALSE;
4884           }
4885      }
4886
4887    if (rel)
4888      {
4889         it->item->rel = rel;
4890         it->item->rel->relcount++;
4891      }
4892
4893    _item_queue(wd, it, _elm_genlist_item_list_compare);
4894
4895    return (Elm_Object_Item *)it;
4896 }
4897
4898 static void
4899 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4900 {
4901    Eina_Inlist *next, *l;
4902    Widget_Data *wd = elm_widget_data_get(obj);
4903    if (!wd) return;
4904
4905    if (!standby) wd->generation++;
4906
4907    if (wd->state)
4908      {
4909         eina_inlist_sorted_state_free(wd->state);
4910         wd->state = NULL;
4911      }
4912
4913    if (wd->walking > 0)
4914      {
4915         wd->clear_me = EINA_TRUE;
4916         return;
4917      }
4918    evas_event_freeze(evas_object_evas_get(wd->obj));
4919    for (l = wd->items, next = l ? l->next : NULL;
4920         l;
4921         l = next, next = next ? next->next : NULL)
4922      {
4923         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4924
4925         if (it->generation < wd->generation)
4926           {
4927              Elm_Gen_Item *itn = NULL;
4928
4929              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4930              if (itn) itn->walking++; /* prevent early death of subitem */
4931              it->del_cb(it);
4932              elm_widget_item_free(it);
4933              if (itn) itn->walking--;
4934           }
4935      }
4936    wd->clear_me = EINA_FALSE;
4937    wd->pan_changed = EINA_TRUE;
4938    if (wd->calc_job)
4939      {
4940         ecore_job_del(wd->calc_job);
4941         wd->calc_job = NULL;
4942      }
4943    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4944    if (wd->clear_cb) wd->clear_cb(wd);
4945    wd->pan_x = 0;
4946    wd->pan_y = 0;
4947    wd->minw = 0;
4948    wd->minh = 0;
4949
4950    if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4951    wd->alpha_bg = NULL;
4952
4953    if (wd->pan_smart)
4954      {
4955         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4956         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4957      }
4958    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4959    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4960    evas_event_thaw(evas_object_evas_get(wd->obj));
4961    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4962 }
4963
4964 EAPI void
4965 elm_genlist_clear(Evas_Object *obj)
4966 {
4967    ELM_CHECK_WIDTYPE(obj, widtype);
4968    _elm_genlist_clear(obj, EINA_FALSE);
4969 }
4970
4971 EAPI void
4972 elm_genlist_multi_select_set(Evas_Object *obj,
4973                              Eina_Bool    multi)
4974 {
4975    ELM_CHECK_WIDTYPE(obj, widtype);
4976    Widget_Data *wd = elm_widget_data_get(obj);
4977    if (!wd) return;
4978    wd->multi = !!multi;
4979 }
4980
4981 EAPI Eina_Bool
4982 elm_genlist_multi_select_get(const Evas_Object *obj)
4983 {
4984    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4985    Widget_Data *wd = elm_widget_data_get(obj);
4986    if (!wd) return EINA_FALSE;
4987    return wd->multi;
4988 }
4989
4990 EAPI Elm_Object_Item *
4991 elm_genlist_selected_item_get(const Evas_Object *obj)
4992 {
4993    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4994    Widget_Data *wd = elm_widget_data_get(obj);
4995    if (!wd) return NULL;
4996    if (wd->selected) return wd->selected->data;
4997    return NULL;
4998 }
4999
5000 EAPI const Eina_List *
5001 elm_genlist_selected_items_get(const Evas_Object *obj)
5002 {
5003    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5004    Widget_Data *wd = elm_widget_data_get(obj);
5005    if (!wd) return NULL;
5006    return wd->selected;
5007 }
5008
5009 EAPI Eina_List *
5010 elm_genlist_realized_items_get(const Evas_Object *obj)
5011 {
5012    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5013    Widget_Data *wd = elm_widget_data_get(obj);
5014    Eina_List *list = NULL;
5015    Item_Block *itb;
5016    Eina_Bool done = EINA_FALSE;
5017    if (!wd) return NULL;
5018    EINA_INLIST_FOREACH(wd->blocks, itb)
5019      {
5020         if (itb->realized)
5021           {
5022              Eina_List *l;
5023              Elm_Gen_Item *it;
5024
5025              done = EINA_TRUE;
5026              EINA_LIST_FOREACH(itb->items, l, it)
5027                {
5028                   if (it->realized) list = eina_list_append(list, it);
5029                }
5030           }
5031         else
5032           {
5033              if (done) break;
5034           }
5035      }
5036    return list;
5037 }
5038
5039 EAPI Elm_Object_Item *
5040 elm_genlist_at_xy_item_get(const Evas_Object *obj,
5041                            Evas_Coord         x,
5042                            Evas_Coord         y,
5043                            int               *posret)
5044 {
5045    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5046    Widget_Data *wd = elm_widget_data_get(obj);
5047    Evas_Coord ox, oy, ow, oh;
5048    Item_Block *itb;
5049    Evas_Coord lasty;
5050    if (!wd) return NULL;
5051    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5052    lasty = oy;
5053    EINA_INLIST_FOREACH(wd->blocks, itb)
5054      {
5055         Eina_List *l;
5056         Elm_Gen_Item *it;
5057
5058         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
5059                                  oy + itb->y - itb->wd->pan_y,
5060                                  itb->w, itb->h, x, y, 1, 1))
5061           continue;
5062         EINA_LIST_FOREACH(itb->items, l, it)
5063           {
5064              Evas_Coord itx, ity;
5065
5066              itx = ox + itb->x + it->x - itb->wd->pan_x;
5067              ity = oy + itb->y + it->y - itb->wd->pan_y;
5068              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
5069                {
5070                   if (posret)
5071                     {
5072                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
5073                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
5074                          *posret = 1;
5075                        else *posret = 0;
5076                     }
5077                   return (Elm_Object_Item *)it;
5078                }
5079              lasty = ity + it->item->h;
5080           }
5081      }
5082    if (posret)
5083      {
5084         if (y > lasty) *posret = 1;
5085         else *posret = -1;
5086      }
5087    return NULL;
5088 }
5089
5090 EAPI Elm_Object_Item *
5091 elm_genlist_first_item_get(const Evas_Object *obj)
5092 {
5093    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5094    Widget_Data *wd = elm_widget_data_get(obj);
5095    if (!wd) return NULL;
5096    if (!wd->items) return NULL;
5097    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
5098    while ((it) && (it->generation < wd->generation))
5099      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5100    return (Elm_Object_Item *)it;
5101 }
5102
5103 EAPI Elm_Object_Item *
5104 elm_genlist_last_item_get(const Evas_Object *obj)
5105 {
5106    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5107    Widget_Data *wd = elm_widget_data_get(obj);
5108    if (!wd) return NULL;
5109    if (!wd->items) return NULL;
5110    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
5111    while ((it) && (it->generation < wd->generation))
5112      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5113    return (Elm_Object_Item *)it;
5114 }
5115
5116 EAPI Elm_Object_Item *
5117 elm_genlist_item_next_get(const Elm_Object_Item *it)
5118 {
5119    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5120    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5121    while (_it)
5122      {
5123         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
5124         if ((_it) && (_it->generation == _it->wd->generation)) break;
5125      }
5126    return (Elm_Object_Item *) _it;
5127 }
5128
5129 EAPI Elm_Object_Item *
5130 elm_genlist_item_prev_get(const Elm_Object_Item *it)
5131 {
5132    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5133    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5134    while (_it)
5135      {
5136         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
5137         if ((_it) && (_it->generation == _it->wd->generation)) break;
5138      }
5139    return (Elm_Object_Item *) _it;
5140 }
5141
5142 EAPI Elm_Object_Item *
5143 elm_genlist_item_parent_get(const Elm_Object_Item *it)
5144 {
5145    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5146    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
5147 }
5148
5149 EAPI void
5150 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
5151 {
5152    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5153    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
5154    if (!wd) return;
5155    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5156
5157    if (!wd->tree_effect_enabled || !wd->move_effect_mode)
5158      _item_subitems_clear(_it);
5159    else
5160      {
5161         if (!wd->tree_effect_animator)
5162           {
5163              wd->expanded_item = _it;
5164              _item_tree_effect_before(_it);
5165              evas_object_raise(wd->alpha_bg);
5166              evas_object_show(wd->alpha_bg);
5167              wd->start_time = ecore_time_get();
5168              wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, wd);
5169           }
5170         else
5171            _item_subitems_clear(_it);
5172      }
5173 }
5174
5175 EAPI void
5176 elm_genlist_item_selected_set(Elm_Object_Item *it,
5177                               Eina_Bool selected)
5178 {
5179    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5180    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5181    Widget_Data *wd = _it->wd;
5182    if (!wd) return;
5183    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
5184      return;
5185    selected = !!selected;
5186    if (_it->selected == selected) return;
5187
5188    if (selected)
5189      {
5190         if (!wd->multi)
5191           {
5192              while (wd->selected)
5193                {
5194                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
5195                   _it->unsel_cb(wd->selected->data);
5196                }
5197           }
5198         _it->highlight_cb(_it);
5199         _item_select(_it);
5200         return;
5201      }
5202    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
5203    _it->unsel_cb(_it);
5204 }
5205
5206 EAPI Eina_Bool
5207 elm_genlist_item_selected_get(const Elm_Object_Item *it)
5208 {
5209    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5210    return ((Elm_Gen_Item *)it)->selected;
5211 }
5212
5213 Elm_Gen_Item *
5214 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
5215 {
5216    Elm_Gen_Item *it2;
5217    if (it->item->expanded)
5218      {
5219         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5220      }
5221    else
5222      {
5223         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5224         while (it2)
5225           {
5226              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
5227              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5228           }
5229      }
5230    return it2;
5231 }
5232
5233 static void
5234 _elm_genlist_move_items_set(Elm_Gen_Item *it)
5235 {
5236    Eina_List *l, *ll;
5237    Elm_Gen_Item *it2 = NULL;
5238    Evas_Coord ox, oy, ow, oh, dh = 0;
5239
5240    it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
5241
5242    if (it->item->expanded)
5243      {
5244         it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
5245         EINA_LIST_FOREACH_SAFE(it->wd->move_items, l, ll, it2)
5246           {
5247              if (it2 == it->wd->expanded_next_item) break;
5248              it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
5249           }
5250      }
5251    else
5252      {
5253         evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
5254         it2 = it->wd->expanded_next_item;
5255         while (it2 && (dh < oy + oh))
5256           {
5257              dh += it2->item->h;
5258              it->wd->move_items = eina_list_append(it->wd->move_items, it2);
5259              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5260           }
5261      }
5262 }
5263
5264 EAPI void
5265 elm_genlist_item_expanded_set(Elm_Object_Item *it,
5266                               Eina_Bool        expanded)
5267 {
5268    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5269    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5270    expanded = !!expanded;
5271    if (_it->item->expanded == expanded) return;
5272    _it->item->expanded = expanded;
5273    _it->wd->expanded_item = _it;
5274    _elm_genlist_move_items_set(_it);
5275
5276    if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
5277       _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
5278
5279    if (_it->item->expanded)
5280      {
5281         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
5282         if (_it->realized)
5283           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
5284         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
5285         _it->wd->auto_scroll_enabled = EINA_TRUE;
5286      }
5287    else
5288      {
5289         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
5290         if (_it->realized)
5291           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
5292         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
5293         _it->wd->auto_scroll_enabled = EINA_FALSE;
5294      }
5295 }
5296
5297 EAPI Eina_Bool
5298 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
5299 {
5300    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5301    return ((Elm_Gen_Item *)it)->item->expanded;
5302 }
5303
5304 EAPI int
5305 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
5306 {
5307    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
5308    return ((Elm_Gen_Item *)it)->item->expanded_depth;
5309 }
5310
5311 EINA_DEPRECATED EAPI void
5312 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
5313                                   Eina_Bool         display_only)
5314 {
5315    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5316    display_only = !!display_only;
5317
5318    if (display_only)
5319      elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
5320    else
5321      {
5322         Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5323         if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5324           elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DEFAULT);
5325      }
5326 }
5327
5328 EINA_DEPRECATED EAPI Eina_Bool
5329 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
5330 {
5331    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5332    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5333    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5334    Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5335    if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5336      return EINA_TRUE;
5337    return EINA_FALSE;
5338 }
5339
5340 static Eina_Bool
5341 _elm_genlist_item_compute_coordinates(Elm_Object_Item               *it,
5342                                       Elm_Genlist_Item_Scrollto_Type type,
5343                                       Eina_Bool                      bring_in,
5344                                       Evas_Coord                    *x,
5345                                       Evas_Coord                    *y,
5346                                       Evas_Coord                    *w,
5347                                       Evas_Coord                    *h)
5348 {
5349    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5350    Evas_Coord gith = 0;
5351    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5352    if ((_it->wd->homogeneous) &&
5353        (_it->wd->mode == ELM_LIST_COMPRESS))
5354      goto hm_shortcut;  /* homogenous genlist shortcut */
5355    if ((_it->item->queued) || (!_it->item->mincalcd))
5356      {
5357         _it->wd->show_item = _it;
5358         _it->wd->bring_in = bring_in;
5359         _it->wd->scrollto_type = type;
5360         _it->item->showme = EINA_TRUE;
5361         return EINA_FALSE;
5362      }
5363 hm_shortcut:
5364    if (_it->wd->show_item)
5365      {
5366         _it->wd->show_item->item->showme = EINA_FALSE;
5367         _it->wd->show_item = NULL;
5368      }
5369
5370    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
5371    switch (type)
5372      {
5373       case ELM_GENLIST_ITEM_SCROLLTO_IN:
5374          if ((_it->item->group_item) &&
5375              (_it->wd->pan_y > (_it->y + _it->item->block->y)))
5376            gith = _it->item->group_item->item->h;
5377          *h = _it->item->h;
5378          *y = _it->y + _it->item->block->y - gith;
5379          break;
5380       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
5381          if (_it->item->group_item) gith = _it->item->group_item->item->h;
5382          *y = _it->y + _it->item->block->y - gith;
5383          break;
5384       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
5385          *y = _it->y + _it->item->block->y - (*h / 2) + (_it->item->h / 2);
5386          break;
5387       default:
5388          return EINA_FALSE;
5389      }
5390
5391    *x = _it->x + _it->item->block->x;
5392    *w = _it->item->block->w;
5393    return EINA_TRUE;
5394 }
5395
5396 EAPI void
5397 elm_genlist_item_promote(Elm_Object_Item *it)
5398 {
5399    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5400    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5401    if (_it->generation < _it->wd->generation) return;
5402    _item_move_before(_it,
5403                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
5404 }
5405
5406 EAPI void
5407 elm_genlist_item_demote(Elm_Object_Item *it)
5408 {
5409    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5410    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5411    if (_it->generation < _it->wd->generation) return;
5412    _item_move_after(_it,
5413                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
5414 }
5415
5416 EAPI void
5417 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5418 {
5419    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5420    Evas_Coord x, y, w, h;
5421    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5422
5423    if (_elm_genlist_item_compute_coordinates(it, type, EINA_FALSE, &x, &y, &w, &h))
5424      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
5425 }
5426
5427 EAPI void
5428 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5429 {
5430
5431    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5432    Evas_Coord x, y, w, h;
5433    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5434
5435    elm_smart_scroller_child_viewport_size_get(_it->wd->scr, &x, &y);
5436
5437    if (_elm_genlist_item_compute_coordinates(it, type, EINA_TRUE, &x, &y, &w, &h))
5438      elm_smart_scroller_region_bring_in(_it->wd->scr, x, y, w, h);
5439 }
5440
5441 EAPI void
5442 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
5443 {
5444    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5445
5446    Evas_Object *content;
5447    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
5448      {
5449         elm_widget_sub_object_del(WIDGET(it), content);
5450         evas_object_smart_member_del(content);
5451         evas_object_hide(content);
5452         if (l) *l = eina_list_append(*l, content);
5453      }
5454 }
5455
5456 EAPI void
5457 elm_genlist_item_update(Elm_Object_Item *it)
5458 {
5459    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5460    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5461
5462    if (!_it->item->block) return;
5463    if (_it->generation < _it->wd->generation) return;
5464    _it->item->mincalcd = EINA_FALSE;
5465    _it->item->updateme = EINA_TRUE;
5466    _it->item->block->updateme = EINA_TRUE;
5467    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5468    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5469 }
5470
5471 EAPI void
5472 elm_genlist_item_fields_update(Elm_Object_Item            *it,
5473                                const char                 *parts,
5474                                Elm_Genlist_Item_Field_Type itf)
5475 {
5476    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5477    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5478
5479    if (!_it->item->block) return;
5480    if (_it->generation < _it->wd->generation) return;
5481
5482    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
5483      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
5484    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
5485      {
5486         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
5487                                                    &_it->contents, parts);
5488         _it->content_objs = _item_content_realize(_it, VIEW(_it),
5489                                                  &_it->contents, parts);
5490
5491         if (_it->flipped)
5492           {
5493              _it->item->flip_content_objs =
5494                _item_mode_content_unrealize(_it, VIEW(_it),
5495                                             &_it->item->flip_contents, parts,
5496                                             &_it->item->flip_content_objs);
5497              _it->item->flip_content_objs =
5498                _item_mode_content_realize(_it, VIEW(_it),
5499                                           &_it->item->flip_contents, parts,
5500                                           &_it->item->flip_content_objs);
5501           }
5502         if (_it->item->deco_it_view)
5503           {
5504              _it->item->deco_it_content_objs =
5505                _item_mode_content_unrealize(_it, _it->item->deco_it_view,
5506                                             &_it->item->deco_it_contents, parts,
5507                                             &_it->item->deco_it_content_objs);
5508              _it->item->deco_it_content_objs =
5509                _item_mode_content_realize(_it, _it->item->deco_it_view,
5510                                           &_it->item->deco_it_contents, parts,
5511                                           &_it->item->deco_it_content_objs);
5512           }
5513         if (_it->wd->decorate_all_mode)
5514           {
5515              _it->item->deco_all_content_objs =
5516                _item_mode_content_unrealize(_it, _it->deco_all_view,
5517                                             &_it->item->deco_all_contents, parts,
5518                                             &_it->item->deco_all_content_objs);
5519              _it->item->deco_all_content_objs =
5520                _item_mode_content_realize(_it, _it->deco_all_view,
5521                                           &_it->item->deco_all_contents, parts,
5522                                           &_it->item->deco_all_content_objs);
5523           }
5524      }
5525    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
5526      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
5527 }
5528
5529 EAPI void
5530 elm_genlist_item_item_class_update(Elm_Object_Item              *it,
5531                                    const Elm_Genlist_Item_Class *itc)
5532 {
5533    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5534    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5535
5536    if (!_it->item->block) return;
5537    EINA_SAFETY_ON_NULL_RETURN(itc);
5538    if (_it->generation < _it->wd->generation) return;
5539    _it->itc = itc;
5540    _it->item->nocache_once = EINA_TRUE;
5541
5542    elm_widget_stringlist_free(_it->texts);
5543    _it->texts = NULL;
5544    elm_widget_stringlist_free(_it->contents);
5545    _it->contents = NULL;
5546    elm_widget_stringlist_free(_it->states);
5547    _it->states = NULL;
5548
5549    if (_it->flipped)
5550      {
5551         elm_widget_stringlist_free(_it->item->flip_contents);
5552         _it->item->flip_contents = NULL;
5553      }
5554    if (_it->item->deco_it_view)
5555      {
5556         elm_widget_stringlist_free(_it->item->deco_it_texts);
5557         _it->item->deco_it_texts = NULL;
5558         elm_widget_stringlist_free(_it->item->deco_it_contents);
5559         _it->item->deco_it_contents = NULL;
5560      }
5561    if (_it->wd->decorate_all_mode)
5562      {
5563         elm_widget_stringlist_free(_it->item->deco_all_texts);
5564         _it->item->deco_all_texts = NULL;
5565         elm_widget_stringlist_free(_it->item->deco_all_contents);
5566         _it->item->deco_all_contents = NULL;
5567      }
5568
5569    elm_genlist_item_update(it);
5570 }
5571
5572 EAPI const Elm_Genlist_Item_Class *
5573 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
5574 {
5575    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5576    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5577    if (_it->generation < _it->wd->generation) return NULL;
5578    return _it->itc;
5579 }
5580
5581 static Evas_Object *
5582 _elm_genlist_item_label_create(void        *data,
5583                                Evas_Object *obj __UNUSED__,
5584                                Evas_Object *tooltip,
5585                                void        *it __UNUSED__)
5586 {
5587    Evas_Object *label = elm_label_add(tooltip);
5588    if (!label)
5589      return NULL;
5590    elm_object_style_set(label, "tooltip");
5591    elm_object_text_set(label, data);
5592    return label;
5593 }
5594
5595 static void
5596 _elm_genlist_item_label_del_cb(void        *data,
5597                                Evas_Object *obj __UNUSED__,
5598                                void        *event_info __UNUSED__)
5599 {
5600    eina_stringshare_del(data);
5601 }
5602
5603 EAPI void
5604 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5605                                   const char      *text)
5606 {
5607    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5608    text = eina_stringshare_add(text);
5609    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5610                                            text,
5611                                            _elm_genlist_item_label_del_cb);
5612 }
5613
5614 EAPI void
5615 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item            *it,
5616                                         Elm_Tooltip_Item_Content_Cb func,
5617                                         const void                 *data,
5618                                         Evas_Smart_Cb               del_cb)
5619 {
5620    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5621    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5622
5623    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5624      return;
5625
5626    if (_it->tooltip.del_cb)
5627      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5628
5629    _it->tooltip.content_cb = func;
5630    _it->tooltip.data = data;
5631    _it->tooltip.del_cb = del_cb;
5632
5633    if (VIEW(_it))
5634      {
5635         elm_widget_item_tooltip_content_cb_set(_it,
5636                                                _it->tooltip.content_cb,
5637                                                _it->tooltip.data, NULL);
5638         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5639         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5640      }
5641
5642    return;
5643
5644 error:
5645    if (del_cb) del_cb((void *)data, NULL, NULL);
5646 }
5647
5648 EAPI void
5649 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5650 {
5651    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5652    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5653
5654    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5655      elm_widget_item_tooltip_unset(_it);
5656
5657    if (_it->tooltip.del_cb)
5658      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5659    _it->tooltip.del_cb = NULL;
5660    _it->tooltip.content_cb = NULL;
5661    _it->tooltip.data = NULL;
5662    _it->tooltip.free_size = EINA_FALSE;
5663    if (_it->tooltip.style)
5664      elm_genlist_item_tooltip_style_set(it, NULL);
5665 }
5666
5667 EAPI void
5668 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5669                                    const char       *style)
5670 {
5671    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5672    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5673
5674    eina_stringshare_replace(&_it->tooltip.style, style);
5675    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5676 }
5677
5678 EAPI const char *
5679 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5680 {
5681    return elm_object_item_tooltip_style_get(it);
5682 }
5683
5684 EAPI Eina_Bool
5685 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5686                                          Eina_Bool        disable)
5687 {
5688    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5689    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5690
5691    _it->tooltip.free_size = disable;
5692    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5693    return EINA_TRUE;
5694 }
5695
5696 EAPI Eina_Bool
5697 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5698 {
5699    return elm_object_tooltip_window_mode_get(VIEW(it));
5700 }
5701
5702 EAPI void
5703 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5704                             const char       *cursor)
5705 {
5706    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5707    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5708    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5709    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5710 }
5711
5712 EAPI const char *
5713 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5714 {
5715    return elm_widget_item_cursor_get(it);
5716 }
5717
5718 EAPI void
5719 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5720 {
5721    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5722    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5723
5724    if (!_it->mouse_cursor) return;
5725
5726    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5727
5728    eina_stringshare_del(_it->mouse_cursor);
5729    _it->mouse_cursor = NULL;
5730 }
5731
5732 EAPI void
5733 elm_genlist_item_cursor_style_set(Elm_Object_Item *it,
5734                                   const char      *style)
5735 {
5736    elm_widget_item_cursor_style_set(it, style);
5737 }
5738
5739 EAPI const char *
5740 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5741 {
5742    return elm_widget_item_cursor_style_get(it);
5743 }
5744
5745 EAPI void
5746 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5747                                         Eina_Bool        engine_only)
5748 {
5749    elm_widget_item_cursor_engine_only_set(it, engine_only);
5750 }
5751
5752 EAPI Eina_Bool
5753 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5754 {
5755    return elm_widget_item_cursor_engine_only_get(it);
5756 }
5757
5758 EAPI int
5759 elm_genlist_item_index_get(const Elm_Object_Item *it)
5760 {
5761    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5762    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5763
5764    if (_it->item->block)
5765      return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5766    return -1;
5767 }
5768
5769 EAPI void
5770 elm_genlist_mode_set(Evas_Object  *obj,
5771                      Elm_List_Mode mode)
5772 {
5773    ELM_CHECK_WIDTYPE(obj, widtype);
5774    Widget_Data *wd = elm_widget_data_get(obj);
5775    if (!wd) return;
5776    if (wd->mode == mode) return;
5777    wd->mode = mode;
5778    _sizing_eval(obj);
5779 }
5780
5781
5782 EAPI Elm_List_Mode
5783 elm_genlist_mode_get(const Evas_Object *obj)
5784 {
5785    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5786    Widget_Data *wd = elm_widget_data_get(obj);
5787    if (!wd) return ELM_LIST_LAST;
5788    return wd->mode;
5789 }
5790
5791 EAPI void
5792 elm_genlist_bounce_set(Evas_Object *obj,
5793                        Eina_Bool    h_bounce,
5794                        Eina_Bool    v_bounce)
5795 {
5796    ELM_CHECK_WIDTYPE(obj, widtype);
5797    Widget_Data *wd = elm_widget_data_get(obj);
5798    if (!wd) return;
5799    wd->h_bounce = !!h_bounce;
5800    wd->v_bounce = !!v_bounce;
5801    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5802 }
5803
5804 EAPI void
5805 elm_genlist_bounce_get(const Evas_Object *obj,
5806                        Eina_Bool         *h_bounce,
5807                        Eina_Bool         *v_bounce)
5808 {
5809    ELM_CHECK_WIDTYPE(obj, widtype);
5810    Widget_Data *wd = elm_widget_data_get(obj);
5811    if (!wd) return;
5812    if (h_bounce) *h_bounce = wd->h_bounce;
5813    if (v_bounce) *v_bounce = wd->v_bounce;
5814 }
5815
5816 EAPI void
5817 elm_genlist_homogeneous_set(Evas_Object *obj,
5818                             Eina_Bool    homogeneous)
5819 {
5820    ELM_CHECK_WIDTYPE(obj, widtype);
5821    Widget_Data *wd = elm_widget_data_get(obj);
5822    if (!wd) return;
5823    wd->homogeneous = !!homogeneous;
5824 }
5825
5826 EAPI Eina_Bool
5827 elm_genlist_homogeneous_get(const Evas_Object *obj)
5828 {
5829    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5830    Widget_Data *wd = elm_widget_data_get(obj);
5831    if (!wd) return EINA_FALSE;
5832    return wd->homogeneous;
5833 }
5834
5835 EAPI void
5836 elm_genlist_block_count_set(Evas_Object *obj,
5837                             int          count)
5838 {
5839    ELM_CHECK_WIDTYPE(obj, widtype);
5840    Widget_Data *wd = elm_widget_data_get(obj);
5841    if (!wd) return;
5842    wd->max_items_per_block = count;
5843    wd->item_cache_max = wd->max_items_per_block * 2;
5844    _item_cache_clean(wd);
5845 }
5846
5847 EAPI int
5848 elm_genlist_block_count_get(const Evas_Object *obj)
5849 {
5850    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5851    Widget_Data *wd = elm_widget_data_get(obj);
5852    if (!wd) return 0;
5853    return wd->max_items_per_block;
5854 }
5855
5856 EAPI void
5857 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5858                                   double       timeout)
5859 {
5860    ELM_CHECK_WIDTYPE(obj, widtype);
5861    Widget_Data *wd = elm_widget_data_get(obj);
5862    if (!wd) return;
5863    wd->longpress_timeout = timeout;
5864 }
5865
5866 EAPI double
5867 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5868 {
5869    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5870    Widget_Data *wd = elm_widget_data_get(obj);
5871    if (!wd) return 0;
5872    return wd->longpress_timeout;
5873 }
5874
5875 EAPI void
5876 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5877                                 Elm_Scroller_Policy policy_h,
5878                                 Elm_Scroller_Policy policy_v)
5879 {
5880    ELM_CHECK_WIDTYPE(obj, widtype);
5881    Widget_Data *wd = elm_widget_data_get(obj);
5882    if ((!wd) || (!wd->scr)) return;
5883    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5884        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5885      return;
5886    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5887 }
5888
5889 EAPI void
5890 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5891                                 Elm_Scroller_Policy *policy_h,
5892                                 Elm_Scroller_Policy *policy_v)
5893 {
5894    ELM_CHECK_WIDTYPE(obj, widtype);
5895    Widget_Data *wd = elm_widget_data_get(obj);
5896    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5897    if ((!wd) || (!wd->scr)) return;
5898    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5899    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5900    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5901 }
5902
5903 EAPI void
5904 elm_genlist_realized_items_update(Evas_Object *obj)
5905 {
5906    ELM_CHECK_WIDTYPE(obj, widtype);
5907
5908    Eina_List *list, *l;
5909    Elm_Object_Item *it;
5910
5911    list = elm_genlist_realized_items_get(obj);
5912    EINA_LIST_FOREACH(list, l, it)
5913      elm_genlist_item_update(it);
5914 }
5915
5916 EAPI void
5917 elm_genlist_item_decorate_mode_set(Elm_Object_Item *it,
5918                                    const char      *decorate_it_type,
5919                                    Eina_Bool        decorate_it_set)
5920 {
5921    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5922    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5923
5924    Widget_Data *wd = _it->wd;
5925    Eina_List *l;
5926    Elm_Object_Item *it2;
5927
5928    if (!wd) return;
5929    if (!decorate_it_type) return;
5930    if ((_it->generation < _it->wd->generation) ||
5931        elm_widget_item_disabled_get(_it)) return;
5932    if (wd->decorate_all_mode) return;
5933
5934    if ((wd->mode_item == _it) &&
5935        (!strcmp(decorate_it_type, wd->decorate_it_type)) &&
5936        (decorate_it_set))
5937       return;
5938    if (!_it->itc->decorate_item_style) return;
5939    _it->decorate_it_set = decorate_it_set;
5940
5941    if (wd->multi)
5942      {
5943         EINA_LIST_FOREACH(wd->selected, l, it2)
5944           if (((Elm_Gen_Item *)it2)->realized)
5945             elm_genlist_item_selected_set(it2, EINA_FALSE);
5946      }
5947    else
5948      {
5949         it2 = elm_genlist_selected_item_get(wd->obj);
5950         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5951           elm_genlist_item_selected_set(it2, EINA_FALSE);
5952      }
5953
5954    if (((wd->decorate_it_type) && (strcmp(decorate_it_type, wd->decorate_it_type))) ||
5955        (decorate_it_set) || ((_it == wd->mode_item) && (!decorate_it_set)))
5956      _decorate_item_unset(wd);
5957
5958    eina_stringshare_replace(&wd->decorate_it_type, decorate_it_type);
5959    if (decorate_it_set) _decorate_item_set(_it);
5960 }
5961
5962 EAPI const char *
5963 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5964 {
5965    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5966    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5967    return _it->wd->decorate_it_type;
5968 }
5969
5970 EAPI const Elm_Object_Item *
5971 elm_genlist_decorated_item_get(const Evas_Object *obj)
5972 {
5973    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5974    Widget_Data *wd = elm_widget_data_get(obj);
5975    if (!wd) return NULL;
5976    return (Elm_Object_Item *) wd->mode_item;
5977 }
5978
5979 EAPI Eina_Bool
5980 elm_genlist_decorate_mode_get(const Evas_Object *obj)
5981 {
5982    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5983    Widget_Data *wd = elm_widget_data_get(obj);
5984    if (!wd) return EINA_FALSE;
5985
5986    return wd->decorate_all_mode;
5987 }
5988
5989 EAPI void
5990 elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
5991 {
5992    ELM_CHECK_WIDTYPE(obj, widtype);
5993    Eina_List *list, *l;
5994    Elm_Gen_Item *it;
5995
5996    Widget_Data *wd = elm_widget_data_get(obj);
5997    if (!wd) return;
5998    decorated = !!decorated;
5999    if (wd->decorate_all_mode == decorated) return;
6000    wd->decorate_all_mode = decorated;
6001
6002    list = elm_genlist_realized_items_get(obj);
6003    if (!wd->decorate_all_mode)
6004      {
6005         EINA_LIST_FOREACH(list, l, it)
6006           {
6007              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6008                _decorate_all_item_unrealize(it);
6009           }
6010         _item_cache_zero(wd);
6011      }
6012    else
6013      {
6014         EINA_LIST_FOREACH(list, l, it)
6015           {
6016              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6017                {
6018                   if (it->itc->decorate_all_item_style)
6019                      _decorate_all_item_realize(it, EINA_TRUE);
6020                }
6021           }
6022      }
6023    if (wd->calc_job) ecore_job_del(wd->calc_job);
6024    wd->calc_job = ecore_job_add(_calc_job, wd);
6025 }
6026
6027 EAPI void
6028 elm_genlist_reorder_mode_set(Evas_Object *obj,
6029                              Eina_Bool    reorder_mode)
6030 {
6031    ELM_CHECK_WIDTYPE(obj, widtype);
6032    Widget_Data *wd = elm_widget_data_get(obj);
6033    if (!wd) return;
6034    wd->reorder_mode = !!reorder_mode;
6035 }
6036
6037 EAPI Eina_Bool
6038 elm_genlist_reorder_mode_get(const Evas_Object *obj)
6039 {
6040    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6041    Widget_Data *wd = elm_widget_data_get(obj);
6042    if (!wd) return EINA_FALSE;
6043    return wd->reorder_mode;
6044 }
6045
6046 EAPI Elm_Genlist_Item_Type
6047 elm_genlist_item_type_get(const Elm_Object_Item *it)
6048 {
6049    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
6050    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6051    return _it->item->type;
6052 }
6053
6054 EAPI Elm_Genlist_Item_Class *
6055 elm_genlist_item_class_new(void)
6056 {
6057    Elm_Genlist_Item_Class *itc;
6058
6059    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
6060    if (!itc)
6061      return NULL;
6062    itc->version = CLASS_ALLOCATED;
6063    itc->refcount = 1;
6064    itc->delete_me = EINA_FALSE;
6065
6066    return itc;
6067 }
6068
6069 EAPI void
6070 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
6071 {
6072    if (itc && (itc->version == CLASS_ALLOCATED))
6073      {
6074         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
6075         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
6076         else
6077           {
6078              itc->version = 0;
6079              free(itc);
6080           }
6081      }
6082 }
6083
6084 EAPI void
6085 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
6086 {
6087    if (itc && (itc->version == CLASS_ALLOCATED))
6088      {
6089         itc->refcount++;
6090         if (itc->refcount == 0) itc->refcount--;
6091      }
6092 }
6093
6094 EAPI void
6095 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
6096 {
6097    if (itc && (itc->version == CLASS_ALLOCATED))
6098      {
6099         if (itc->refcount > 0) itc->refcount--;
6100         if (itc->delete_me && (!itc->refcount))
6101           elm_genlist_item_class_free(itc);
6102      }
6103 }
6104
6105 void _flip_job(void *data)
6106 {
6107    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
6108    _item_unhighlight(it);
6109    _item_unselect(it);
6110    _elm_genlist_item_unrealize(it, EINA_FALSE);
6111    it->flipped = EINA_TRUE;
6112    it->item->nocache = EINA_TRUE;
6113    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
6114    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
6115 }
6116
6117 EAPI void
6118 elm_genlist_item_flip_set(Elm_Object_Item *it,
6119                           Eina_Bool flip)
6120 {
6121    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6122    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6123
6124    flip = !!flip;
6125    if (_it->flipped == flip) return;
6126
6127    if (flip)
6128      {
6129         ecore_job_add(_flip_job, _it);
6130      }
6131    else
6132      {
6133         _it->flipped = flip;
6134         _item_cache_zero(_it->wd);
6135         elm_genlist_item_update(it);
6136         _it->item->nocache = EINA_FALSE;
6137      }
6138 }
6139
6140 EAPI Eina_Bool
6141 elm_genlist_item_flip_get(const Elm_Object_Item *it)
6142 {
6143    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
6144    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6145    return _it->flipped;
6146 }
6147
6148 EAPI void
6149 elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
6150 {
6151    ELM_CHECK_WIDTYPE(obj, widtype);
6152    Widget_Data *wd = elm_widget_data_get(obj);
6153    if (!wd) return;
6154    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6155      return;
6156    if (wd->select_mode != mode)
6157      wd->select_mode = mode;
6158 }
6159
6160 EAPI Elm_Object_Select_Mode
6161 elm_genlist_select_mode_get(const Evas_Object *obj)
6162 {
6163    ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
6164    Widget_Data *wd = elm_widget_data_get(obj);
6165    if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
6166    return wd->select_mode;
6167 }
6168
6169 EAPI void
6170 elm_genlist_highlight_mode_set(Evas_Object *obj,
6171                                Eina_Bool    highlight)
6172 {
6173    ELM_CHECK_WIDTYPE(obj, widtype);
6174    Widget_Data *wd = elm_widget_data_get(obj);
6175    if (!wd) return;
6176    wd->highlight = !!highlight;
6177 }
6178
6179 EAPI Eina_Bool
6180 elm_genlist_highlight_mode_get(const Evas_Object *obj)
6181 {
6182    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6183    Widget_Data *wd = elm_widget_data_get(obj);
6184    if (!wd) return EINA_FALSE;
6185    return wd->highlight;
6186 }
6187
6188 EAPI void
6189 elm_genlist_item_select_mode_set(Elm_Object_Item       *it,
6190                                  Elm_Object_Select_Mode mode)
6191 {
6192    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6193    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6194    if (!_it) return;
6195    if (_it->generation < _it->wd->generation) return;
6196    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6197      return;
6198    if (_it->select_mode != mode)
6199      _it->select_mode = mode;
6200
6201    if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
6202      {
6203         _it->item->mincalcd = EINA_FALSE;
6204         _it->item->updateme = EINA_TRUE;
6205         if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
6206         if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
6207         _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
6208      }
6209 }
6210
6211 EAPI Elm_Object_Select_Mode
6212 elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
6213 {
6214    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
6215    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6216    if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
6217    return _it->select_mode;
6218 }
6219
6220 /* for gengrid as of now */
6221 void
6222 _elm_genlist_page_relative_set(Evas_Object *obj,
6223                                double       h_pagerel,
6224                                double       v_pagerel)
6225 {
6226    Evas_Coord pagesize_h;
6227    Evas_Coord pagesize_v;
6228
6229    ELM_CHECK_WIDTYPE(obj, widtype);
6230    Widget_Data *wd = elm_widget_data_get(obj);
6231    if (!wd) return;
6232
6233    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
6234    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
6235                                  pagesize_v);
6236 }
6237
6238 /* for gengrid as of now */
6239 void
6240 _elm_genlist_page_relative_get(const Evas_Object *obj,
6241                                double            *h_pagerel,
6242                                double            *v_pagerel)
6243 {
6244    ELM_CHECK_WIDTYPE(obj, widtype);
6245    Widget_Data *wd = elm_widget_data_get(obj);
6246    if (!wd) return;
6247
6248    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
6249 }
6250
6251 /* for gengrid as of now */
6252 void
6253 _elm_genlist_page_size_set(Evas_Object *obj,
6254                            Evas_Coord   h_pagesize,
6255                            Evas_Coord   v_pagesize)
6256 {
6257    double pagerel_h;
6258    double pagerel_v;
6259
6260    ELM_CHECK_WIDTYPE(obj, widtype);
6261    Widget_Data *wd = elm_widget_data_get(obj);
6262    if (!wd) return;
6263    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
6264    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
6265                                  v_pagesize);
6266 }
6267
6268 /* for gengrid as of now */
6269 void
6270 _elm_genlist_current_page_get(const Evas_Object *obj,
6271                               int               *h_pagenumber,
6272                               int               *v_pagenumber)
6273 {
6274    ELM_CHECK_WIDTYPE(obj, widtype);
6275    Widget_Data *wd = elm_widget_data_get(obj);
6276    if (!wd) return;
6277    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
6278 }
6279
6280 /* for gengrid as of now */
6281 void
6282 _elm_genlist_last_page_get(const Evas_Object *obj,
6283                            int               *h_pagenumber,
6284                            int               *v_pagenumber)
6285 {
6286    ELM_CHECK_WIDTYPE(obj, widtype);
6287    Widget_Data *wd = elm_widget_data_get(obj);
6288    if (!wd) return;
6289    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
6290 }
6291
6292 /* for gengrid as of now */
6293 void
6294 _elm_genlist_page_show(const Evas_Object *obj,
6295                        int                h_pagenumber,
6296                        int                v_pagenumber)
6297 {
6298    ELM_CHECK_WIDTYPE(obj, widtype);
6299    Widget_Data *wd = elm_widget_data_get(obj);
6300    if (!wd) return;
6301    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
6302 }
6303
6304 /* for gengrid as of now */
6305 void
6306 _elm_genlist_page_bring_in(const Evas_Object *obj,
6307                            int                h_pagenumber,
6308                            int                v_pagenumber)
6309 {
6310    ELM_CHECK_WIDTYPE(obj, widtype);
6311    Widget_Data *wd = elm_widget_data_get(obj);
6312    if (!wd) return;
6313    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
6314 }
6315
6316 void
6317 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
6318                             Eina_Bool     calc)
6319 {
6320    Evas_Object *content;
6321
6322    if (!it->realized) return;
6323    if (it->wd->reorder_it == it) return;
6324    if (it->defer_unrealize && !it->item->updateme) return;
6325
6326    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
6327    if (!calc)
6328      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
6329    if (it->long_timer)
6330      {
6331         ecore_timer_del(it->long_timer);
6332         it->long_timer = NULL;
6333      }
6334
6335    elm_widget_stringlist_free(it->texts);
6336    it->texts = NULL;
6337    elm_widget_stringlist_free(it->contents);
6338    it->contents = NULL;
6339    elm_widget_stringlist_free(it->states);
6340    it->states = NULL;
6341    EINA_LIST_FREE(it->content_objs, content)
6342      evas_object_del(content);
6343
6344    it->unrealize_cb(it);
6345
6346    it->realized = EINA_FALSE;
6347    it->want_unrealize = EINA_FALSE;
6348    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
6349    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
6350 }
6351
6352 void
6353 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
6354 {
6355    elm_widget_item_pre_notify_del(it);
6356    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
6357
6358    if ((it->relcount > 0) || (it->walking > 0)) return;
6359
6360    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
6361
6362    if (it->itc->func.del)
6363      it->itc->func.del((void *)it->base.data, WIDGET(it));
6364 }
6365
6366 void
6367 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
6368 {
6369    _elm_genlist_item_del_notserious(it);
6370    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
6371    if (it->tooltip.del_cb)
6372      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6373    it->wd->walking -= it->walking;
6374    if (it->long_timer)
6375      {
6376         ecore_timer_del(it->long_timer);
6377         it->long_timer = NULL;
6378      }
6379    if (it->group)
6380      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
6381
6382    if (it->wd->state)
6383      {
6384         eina_inlist_sorted_state_free(it->wd->state);
6385         it->wd->state = NULL;
6386      }
6387    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
6388    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
6389    free(it->item);
6390
6391    it->item = NULL;
6392    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
6393      it->wd->last_selected_item = NULL;
6394    it->wd->item_count--;
6395 }
6396
6397 EAPI void
6398 elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
6399 {
6400    ELM_CHECK_WIDTYPE(obj, widtype);
6401    Widget_Data *wd = elm_widget_data_get(obj);
6402    if (!wd) return;
6403    wd->tree_effect_enabled = !!enabled;
6404 }
6405
6406 EAPI Eina_Bool
6407 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
6408 {
6409    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6410    Widget_Data *wd = elm_widget_data_get(obj);
6411    if (!wd) return EINA_FALSE;
6412    return wd->tree_effect_enabled;
6413 }
6414
6415 static Evas_Object*
6416 _create_tray_alpha_bg(const Evas_Object *obj)
6417 {
6418    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
6419    Widget_Data *wd = elm_widget_data_get(obj);
6420    if (!wd) return NULL;
6421
6422    Evas_Object *bg = NULL;
6423    Evas_Coord ox, oy, ow, oh;
6424
6425    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6426    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
6427    evas_object_color_set(bg,0,0,0,0);
6428    evas_object_resize(bg , ow, oh);
6429    evas_object_move(bg , ox, oy);
6430    return bg ;
6431 }
6432
6433 static void
6434 _item_contract_emit(Elm_Gen_Item *it)
6435 {
6436    Elm_Gen_Item *it2;
6437    Eina_List *l;
6438
6439    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
6440    it->item->tree_effect_finished = EINA_FALSE;
6441
6442    EINA_LIST_FOREACH(it->item->items, l, it2)
6443      if (it2) _item_contract_emit(it2);
6444 }
6445
6446 static int
6447 _item_tree_effect_before(Elm_Gen_Item *it)
6448 {
6449    Elm_Gen_Item *it2;
6450    Eina_List *l;
6451
6452    EINA_LIST_FOREACH(it->item->items, l, it2)
6453      {
6454         if (it2->parent && (it == it2->parent))
6455           {
6456              if (!it2->realized)
6457                it2->item->tree_effect_hideme = EINA_TRUE;
6458              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6459                edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
6460              else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6461                _item_contract_emit(it2);
6462           }
6463      }
6464    return ECORE_CALLBACK_CANCEL;
6465 }
6466
6467 static void
6468 _item_tree_effect(Widget_Data *wd, int y)
6469 {
6470    Elm_Gen_Item *it = NULL, *expanded_next_it;
6471
6472    expanded_next_it = wd->expanded_next_item;
6473
6474    if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6475      {
6476         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6477         while (it)
6478           {
6479              if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
6480              if (it->item->scrl_y && (it->item->scrl_y <= expanded_next_it->item->old_scrl_y + y) &&
6481                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6482                {
6483                   if (!it->item->tree_effect_finished)
6484                     {
6485                        edje_object_signal_emit(VIEW(it), "flip_item", "");
6486                        _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6487                        it->item->tree_effect_finished = EINA_TRUE;
6488                     }
6489                }
6490              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6491           }
6492      }
6493    else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6494      {
6495         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6496         while (it)
6497           {
6498              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
6499                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6500                {
6501                   if (!it->item->tree_effect_finished)
6502                     {
6503                        edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
6504                        it->item->tree_effect_finished = EINA_TRUE;
6505                     }
6506                }
6507              else
6508                break;
6509              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6510           }
6511      }
6512 }
6513
6514 static void
6515 _item_tree_effect_finish(Widget_Data *wd)
6516 {
6517    Elm_Gen_Item *it = NULL;
6518    const Eina_List *l;
6519
6520    if (wd->tree_effect_animator)
6521      {
6522         if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6523           _item_subitems_clear(wd->expanded_item);
6524         EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
6525           {
6526              it->item->tree_effect_finished = EINA_TRUE;
6527              it->item->old_scrl_y = it->item->scrl_y;
6528              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6529                edje_object_signal_emit(VIEW(it), "elm,state,show", "");
6530           }
6531      }
6532    _item_auto_scroll(wd);
6533    evas_object_lower(wd->alpha_bg);
6534    evas_object_hide(wd->alpha_bg);
6535    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6536    if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
6537
6538    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
6539    evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
6540    evas_object_smart_changed(wd->pan_smart);
6541
6542    wd->tree_effect_animator = NULL;
6543 }
6544
6545 static Eina_Bool
6546 _tree_effect_animator_cb(void *data)
6547 {
6548    Widget_Data *wd = data;
6549    if (!wd) return ECORE_CALLBACK_CANCEL;
6550    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
6551    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
6552    const Eina_List *l;
6553    double effect_duration = 0.3, t;
6554    int y = 0, dy = 0, dh = 0;
6555    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
6556    int in = 0;
6557
6558    t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
6559    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6560    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
6561    if (t > effect_duration) end = EINA_TRUE;
6562
6563    // Below while statement is needed, when the genlist is resized.
6564    it2 = wd->expanded_item;
6565    while (it2 && vis)
6566      {
6567         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
6568         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
6569                                    cvx, cvy, cvw, cvh));
6570         it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
6571      }
6572
6573    if (wd->expanded_next_item)
6574      {
6575         expanded_next_it = wd->expanded_next_item;
6576
6577         /* move items */
6578         EINA_LIST_FOREACH(wd->move_items, l, it)
6579           {
6580              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6581                {
6582                   expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6583                   if (expanded_next_it->item->scrl_y <= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6584                     expanded_next_it->item->scrl_y = cvy + cvh;
6585
6586                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6587                          cvy + cvh : expanded_next_it->item->scrl_y) -
6588                          expanded_next_it->item->old_scrl_y;
6589                }
6590              else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6591                {
6592                   if (expanded_next_it->item->scrl_y >= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6593                      expanded_next_it->item->old_scrl_y = cvy + cvh;
6594
6595                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6596                     {
6597                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6598                        cvy + cvh;
6599                        expanded_next_it->item->old_scrl_y = cvy + cvh;
6600                     }
6601                   else
6602                     {
6603                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6604                              expanded_next_it->item->old_scrl_y;
6605                     }
6606                }
6607
6608              if (t <= effect_duration)
6609                {
6610                   y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6611                }
6612              else
6613                {
6614                   end = EINA_TRUE;
6615                   y = dy;
6616                }
6617
6618              if (!it->realized && !it->item->queued)
6619                _item_realize(it, in, 0);
6620              in++;
6621
6622              if (it != expanded_next_it)
6623                {
6624                   it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6625                   dh += it->item->h;
6626                }
6627
6628              if ((it->item->old_scrl_y + y) < (cvy + cvh))
6629                _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6630           }
6631         /* tree effect */
6632         _item_tree_effect(wd, y);
6633      }
6634    else
6635      {
6636         int expanded_item_num = 0;
6637         int num = 0;
6638
6639         if (wd->expanded_item)
6640           it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6641
6642         it2 = it;
6643         while (it2)
6644           {
6645              expanded_item_num++;
6646              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6647           }
6648
6649         while (it)
6650           {
6651              num++;
6652              if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6653              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6654                {
6655                   if (!it->item->tree_effect_finished)
6656                     {
6657                        if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6658                          {
6659                             edje_object_signal_emit(VIEW(it), "flip_item", "");
6660                             _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6661                             it->item->tree_effect_finished = EINA_TRUE;
6662                          }
6663                     }
6664                }
6665              it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6666           }
6667      }
6668
6669    if (end)
6670      {
6671         _item_tree_effect_finish(wd);
6672         return ECORE_CALLBACK_CANCEL;
6673      }
6674    return ECORE_CALLBACK_RENEW;
6675 }