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