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