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