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