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