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