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