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