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