From: Hyoyoung Chang <hyoyoung@gmail.com>
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2 #include <fnmatch.h>
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_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(wd->last_selected_item);
396    if (!prev) return EINA_TRUE;
397
398    if (elm_genlist_item_selected_get(prev))
399      {
400         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
401         wd->last_selected_item = prev;
402         elm_genlist_item_show(wd->last_selected_item);
403      }
404    else
405      {
406         elm_genlist_item_selected_set(prev, EINA_TRUE);
407         elm_genlist_item_show(prev);
408      }
409    return EINA_TRUE;
410 }
411
412 static Eina_Bool
413 _item_multi_select_down(Widget_Data *wd)
414 {
415    if (!wd->selected) return EINA_FALSE;
416    if (!wd->multi) return EINA_FALSE;
417
418    Elm_Object_Item *next;
419    next = elm_genlist_item_next_get(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(wd->last_selected_item, EINA_FALSE);
425         wd->last_selected_item = next;
426         elm_genlist_item_show(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(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(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, vw;
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    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2402
2403    if (wd->w != ow)
2404      wd->w = ow;
2405
2406    evas_event_freeze(evas_object_evas_get(wd->obj));
2407    EINA_INLIST_FOREACH(wd->blocks, itb)
2408      {
2409         Eina_Bool showme = EINA_FALSE;
2410
2411         itb->num = in;
2412         showme = itb->showme;
2413         itb->showme = EINA_FALSE;
2414         if (chb)
2415           {
2416              if (itb->realized) _item_block_unrealize(itb);
2417           }
2418         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2419           {
2420              if (itb->must_recalc)
2421                {
2422                   Eina_List *l;
2423                   Elm_Gen_Item *it;
2424                   EINA_LIST_FOREACH(itb->items, l, it)
2425                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2426                   itb->changed = EINA_TRUE;
2427                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2428                   if (itb->realized) _item_block_unrealize(itb);
2429                   itb->must_recalc = EINA_FALSE;
2430                }
2431              showme = _item_block_recalc(itb, in, EINA_FALSE);
2432              chb = itb;
2433           }
2434         itb->y = y;
2435         itb->x = 0;
2436         minh += itb->minh;
2437         if (minw == -1) minw = itb->minw;
2438         else if ((!itb->must_recalc) && (minw < itb->minw))
2439           {
2440              minw = itb->minw;
2441              minw_change = EINA_TRUE;
2442           }
2443         if (minw > vw)
2444           {
2445              minw = vw;
2446              minw_change = EINA_TRUE;
2447           }
2448         itb->w = minw;
2449         itb->h = itb->minh;
2450         y += itb->h;
2451         in += itb->count;
2452         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2453           wd->check_scroll = EINA_TRUE;
2454      }
2455    if (minw_change)
2456      {
2457         EINA_INLIST_FOREACH(wd->blocks, itb)
2458           {
2459              itb->minw = minw;
2460              itb->w = itb->minw;
2461           }
2462      }
2463    if ((chb) && (EINA_INLIST_GET(chb)->next))
2464      {
2465         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2466           {
2467              if (itb->realized) _item_block_unrealize(itb);
2468           }
2469      }
2470    wd->realminw = minw;
2471    if (minw < wd->w) minw = wd->w;
2472    if ((minw != wd->minw) || (minh != wd->minh))
2473      {
2474         wd->minw = minw;
2475         wd->minh = minh;
2476         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2477         _sizing_eval(wd->obj);
2478         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2479           {
2480              Elm_Gen_Item *it;
2481              Evas_Coord it_y;
2482
2483              it = wd->anchor_item;
2484              it_y = wd->anchor_y;
2485              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2486                                               it->item->block->y + it->y + it_y);
2487              wd->anchor_item = it;
2488              wd->anchor_y = it_y;
2489           }
2490      }
2491    if (did_must_recalc)
2492      {
2493         if (!wd->must_recalc_idler)
2494           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2495      }
2496    if (wd->check_scroll)
2497      {
2498         _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
2499         if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
2500           wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
2501        switch (wd->scrollto_type)
2502           {
2503            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2504               dy = wd->h;
2505               break;
2506            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2507               dy = wd->h / 2;
2508               break;
2509            case ELM_GENLIST_ITEM_SCROLLTO_IN:
2510            default:
2511               dy = 0;
2512               break;
2513           }
2514         if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
2515             (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
2516           {
2517              _scroll_item(wd);
2518           }
2519      }
2520    wd->calc_job = NULL;
2521    evas_object_smart_changed(wd->pan_smart);
2522    evas_event_thaw(evas_object_evas_get(wd->obj));
2523    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2524 }
2525
2526 static void
2527 _update_job(void *data)
2528 {
2529    Widget_Data *wd = data;
2530    Eina_List *l2;
2531    Item_Block *itb;
2532    int num, num0;
2533    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2534    if (!wd) return;
2535    wd->update_job = NULL;
2536    num = 0;
2537
2538    evas_event_freeze(evas_object_evas_get(wd->obj));
2539    EINA_INLIST_FOREACH(wd->blocks, itb)
2540      {
2541         Evas_Coord itminw, itminh;
2542         Elm_Gen_Item *it;
2543
2544         if (!itb->updateme)
2545           {
2546              num += itb->count;
2547              if (position)
2548                _item_block_position(itb, num);
2549              continue;
2550           }
2551         num0 = num;
2552         recalc = EINA_FALSE;
2553         EINA_LIST_FOREACH(itb->items, l2, it)
2554           {
2555              if (it->item->updateme)
2556                {
2557                   itminw = it->item->minw;
2558                   itminh = it->item->minh;
2559
2560                   it->item->updateme = EINA_FALSE;
2561                   if (it->realized)
2562                     {
2563                        _elm_genlist_item_unrealize(it, EINA_FALSE);
2564                        _item_realize(it, num, EINA_FALSE);
2565                        position = EINA_TRUE;
2566                     }
2567                   else
2568                     {
2569                        _item_realize(it, num, EINA_TRUE);
2570                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2571                     }
2572                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
2573                     recalc = EINA_TRUE;
2574                }
2575              num++;
2576           }
2577         itb->updateme = EINA_FALSE;
2578         if (recalc)
2579           {
2580              position = EINA_TRUE;
2581              itb->changed = EINA_TRUE;
2582              _item_block_recalc(itb, num0, EINA_FALSE);
2583              _item_block_position(itb, num0);
2584           }
2585      }
2586    if (position)
2587      {
2588         if (wd->calc_job) ecore_job_del(wd->calc_job);
2589         wd->calc_job = ecore_job_add(_calc_job, wd);
2590      }
2591    evas_event_thaw(evas_object_evas_get(wd->obj));
2592    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2593 }
2594
2595 static void
2596 _pan_set(Evas_Object *obj,
2597          Evas_Coord   x,
2598          Evas_Coord   y)
2599 {
2600    Pan *sd = evas_object_smart_data_get(obj);
2601    Item_Block *itb;
2602
2603    if (!sd) return;
2604    //   Evas_Coord ow, oh;
2605    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2606    //   ow = sd->wd->minw - ow;
2607    //   if (ow < 0) ow = 0;
2608    //   oh = sd->wd->minh - oh;
2609    //   if (oh < 0) oh = 0;
2610    //   if (x < 0) x = 0;
2611    //   if (y < 0) y = 0;
2612    //   if (x > ow) x = ow;
2613    //   if (y > oh) y = oh;
2614    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2615    sd->wd->pan_x = x;
2616    sd->wd->pan_y = y;
2617
2618    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2619      {
2620         if ((itb->y + itb->h) > y)
2621           {
2622              Elm_Gen_Item *it;
2623              Eina_List *l2;
2624
2625              EINA_LIST_FOREACH(itb->items, l2, it)
2626                {
2627                   if ((itb->y + it->y) >= y)
2628                     {
2629                        sd->wd->anchor_item = it;
2630                        sd->wd->anchor_y = -(itb->y + it->y - y);
2631                        goto done;
2632                     }
2633                }
2634           }
2635      }
2636 done:
2637    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2638 }
2639
2640 static void
2641 _pan_get(Evas_Object *obj,
2642          Evas_Coord  *x,
2643          Evas_Coord  *y)
2644 {
2645    Pan *sd = evas_object_smart_data_get(obj);
2646
2647    if (!sd) return;
2648    if (x) *x = sd->wd->pan_x;
2649    if (y) *y = sd->wd->pan_y;
2650 }
2651
2652 static void
2653 _pan_max_get(Evas_Object *obj,
2654              Evas_Coord  *x,
2655              Evas_Coord  *y)
2656 {
2657    Pan *sd = evas_object_smart_data_get(obj);
2658    Evas_Coord ow, oh;
2659
2660    if (!sd) return;
2661    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2662    ow = sd->wd->minw - ow;
2663    if (ow < 0) ow = 0;
2664    oh = sd->wd->minh - oh;
2665    if (oh < 0) oh = 0;
2666    if (x) *x = ow;
2667    if (y) *y = oh;
2668 }
2669
2670 static void
2671 _pan_min_get(Evas_Object *obj __UNUSED__,
2672              Evas_Coord  *x,
2673              Evas_Coord  *y)
2674 {
2675    if (x) *x = 0;
2676    if (y) *y = 0;
2677 }
2678
2679 static void
2680 _pan_child_size_get(Evas_Object *obj,
2681                     Evas_Coord  *w,
2682                     Evas_Coord  *h)
2683 {
2684    Pan *sd = evas_object_smart_data_get(obj);
2685
2686    if (!sd) return;
2687    if (w) *w = sd->wd->minw;
2688    if (h) *h = sd->wd->minh;
2689 }
2690
2691 static void
2692 _pan_add(Evas_Object *obj)
2693 {
2694    Pan *sd;
2695    Evas_Object_Smart_Clipped_Data *cd;
2696
2697    _pan_sc.add(obj);
2698    cd = evas_object_smart_data_get(obj);
2699    sd = ELM_NEW(Pan);
2700    if (!sd) return;
2701    sd->__clipped_data = *cd;
2702    free(cd);
2703    evas_object_smart_data_set(obj, sd);
2704 }
2705
2706 static void
2707 _pan_del(Evas_Object *obj)
2708 {
2709    Pan *sd = evas_object_smart_data_get(obj);
2710
2711    if (!sd) return;
2712    if (sd->resize_job)
2713      {
2714         ecore_job_del(sd->resize_job);
2715         sd->resize_job = NULL;
2716      }
2717    _pan_sc.del(obj);
2718 }
2719
2720 static void
2721 _pan_resize_job(void *data)
2722 {
2723    Pan *sd = data;
2724    if (!sd) return;
2725    _sizing_eval(sd->wd->obj);
2726    sd->resize_job = NULL;
2727 }
2728
2729 static void
2730 _pan_resize(Evas_Object *obj,
2731             Evas_Coord   w,
2732             Evas_Coord   h)
2733 {
2734    Pan *sd = evas_object_smart_data_get(obj);
2735    Evas_Coord ow, oh;
2736
2737    if (!sd) return;
2738    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2739    if ((ow == w) && (oh == h)) return;
2740    if ((sd->wd->height_for_width) && (ow != w))
2741      {
2742         /* fix me later */
2743         if (sd->resize_job) ecore_job_del(sd->resize_job);
2744         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
2745      }
2746    sd->wd->pan_changed = EINA_TRUE;
2747    evas_object_smart_changed(obj);
2748    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2749    sd->wd->calc_job = NULL;
2750 /* OLD
2751    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2752    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2753  */
2754 }
2755
2756 static void
2757 _pan_calculate(Evas_Object *obj)
2758 {
2759    Pan *sd = evas_object_smart_data_get(obj);
2760    Item_Block *itb;
2761    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2762    int in = 0;
2763    Elm_Gen_Item *git;
2764    Eina_List *l;
2765
2766    if (!sd) return;
2767    evas_event_freeze(evas_object_evas_get(obj));
2768
2769    if (sd->wd->pan_changed)
2770      {
2771         _calc_job(sd->wd);
2772         sd->wd->pan_changed = EINA_FALSE;
2773      }
2774
2775    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2776    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2777    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
2778      {
2779         git->item->want_realize = EINA_FALSE;
2780      }
2781    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2782      {
2783         itb->w = sd->wd->minw;
2784         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
2785                                 itb->y - sd->wd->pan_y + oy,
2786                                 itb->w, itb->h,
2787                                 cvx, cvy, cvw, cvh))
2788           {
2789              if ((!itb->realized) || (itb->changed))
2790                _item_block_realize(itb);
2791              _item_block_position(itb, in);
2792           }
2793         else
2794           {
2795              if (itb->realized) _item_block_unrealize(itb);
2796           }
2797         in += itb->count;
2798      }
2799    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
2800       _group_items_recalc(sd->wd);
2801    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
2802      {
2803         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
2804            sd->wd->reorder_pan_move = EINA_TRUE;
2805         else sd->wd->reorder_pan_move = EINA_FALSE;
2806         evas_object_raise(sd->wd->VIEW(reorder_it));
2807         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
2808         sd->wd->start_time = ecore_loop_time_get();
2809      }
2810    _item_auto_scroll(sd->wd);
2811    evas_event_thaw(evas_object_evas_get(obj));
2812    evas_event_thaw_eval(evas_object_evas_get(obj));
2813 }
2814
2815 static void
2816 _pan_move(Evas_Object *obj,
2817           Evas_Coord   x __UNUSED__,
2818           Evas_Coord   y __UNUSED__)
2819 {
2820    Pan *sd = evas_object_smart_data_get(obj);
2821
2822    if (!sd) return;
2823
2824    sd->wd->pan_changed = EINA_TRUE;
2825    evas_object_smart_changed(obj);
2826    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2827    sd->wd->calc_job = NULL;
2828 }
2829
2830 static void
2831 _hold_on(void        *data __UNUSED__,
2832          Evas_Object *obj,
2833          void        *event_info __UNUSED__)
2834 {
2835    Widget_Data *wd = elm_widget_data_get(obj);
2836    if (!wd) return;
2837    elm_smart_scroller_hold_set(wd->scr, 1);
2838 }
2839
2840 static void
2841 _hold_off(void        *data __UNUSED__,
2842           Evas_Object *obj,
2843           void        *event_info __UNUSED__)
2844 {
2845    Widget_Data *wd = elm_widget_data_get(obj);
2846    if (!wd) return;
2847    elm_smart_scroller_hold_set(wd->scr, 0);
2848 }
2849
2850 static void
2851 _freeze_on(void        *data __UNUSED__,
2852            Evas_Object *obj,
2853            void        *event_info __UNUSED__)
2854 {
2855    Widget_Data *wd = elm_widget_data_get(obj);
2856    if (!wd) return;
2857    elm_smart_scroller_freeze_set(wd->scr, 1);
2858 }
2859
2860 static void
2861 _freeze_off(void        *data __UNUSED__,
2862             Evas_Object *obj,
2863             void        *event_info __UNUSED__)
2864 {
2865    Widget_Data *wd = elm_widget_data_get(obj);
2866    if (!wd) return;
2867    elm_smart_scroller_freeze_set(wd->scr, 0);
2868 }
2869
2870 static void
2871 _scr_anim_start(void        *data,
2872                 Evas_Object *obj __UNUSED__,
2873                 void        *event_info __UNUSED__)
2874 {
2875    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
2876 }
2877
2878 static void
2879 _scr_anim_stop(void        *data,
2880                Evas_Object *obj __UNUSED__,
2881                void        *event_info __UNUSED__)
2882 {
2883    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
2884 }
2885
2886 static void
2887 _scr_drag_start(void            *data,
2888                 Evas_Object     *obj __UNUSED__,
2889                 void            *event_info __UNUSED__)
2890 {
2891    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
2892 }
2893
2894 static void
2895 _scr_drag_stop(void            *data,
2896                Evas_Object     *obj __UNUSED__,
2897                void            *event_info __UNUSED__)
2898 {
2899    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
2900 }
2901
2902 static void
2903 _edge_left(void        *data,
2904            Evas_Object *scr __UNUSED__,
2905            void        *event_info __UNUSED__)
2906 {
2907    Evas_Object *obj = data;
2908    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
2909 }
2910
2911 static void
2912 _edge_right(void        *data,
2913             Evas_Object *scr __UNUSED__,
2914             void        *event_info __UNUSED__)
2915 {
2916    Evas_Object *obj = data;
2917    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
2918 }
2919
2920 static void
2921 _edge_top(void        *data,
2922           Evas_Object *scr __UNUSED__,
2923           void        *event_info __UNUSED__)
2924 {
2925    Evas_Object *obj = data;
2926    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
2927 }
2928
2929 static void
2930 _edge_bottom(void        *data,
2931              Evas_Object *scr __UNUSED__,
2932              void        *event_info __UNUSED__)
2933 {
2934    Evas_Object *obj = data;
2935    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
2936 }
2937
2938 static void
2939 _mode_item_realize(Elm_Gen_Item *it)
2940 {
2941    char buf[1024];
2942
2943    if ((it->item->mode_view) || (it->generation < it->wd->generation)) return;
2944
2945    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2946    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
2947    edje_object_scale_set(it->item->mode_view,
2948                          elm_widget_scale_get(WIDGET(it)) *
2949                          _elm_config->scale);
2950    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
2951    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
2952
2953    strncpy(buf, "item", sizeof(buf));
2954    if (it->wd->compress)
2955      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
2956
2957    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
2958    strncat(buf, "/", sizeof(buf) - strlen(buf));
2959    strncat(buf, it->wd->mode_item_style, sizeof(buf) - strlen(buf));
2960
2961    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
2962                          elm_widget_style_get(WIDGET(it)));
2963    edje_object_mirrored_set(it->item->mode_view,
2964                             elm_widget_mirrored_get(WIDGET(it)));
2965
2966    /* signal callback add */
2967    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
2968                                   _mouse_down, it);
2969    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
2970                                   _mouse_up, it);
2971    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
2972                                   _mouse_move, it);
2973
2974    /* text_get, content_get, state_get */
2975    /* FIXME: If you see that assert, please notify us and we
2976       will clean our mess */
2977    assert(eina_list_count(it->item->mode_content_objs) == 0);
2978
2979    _item_text_realize(it, it->item->mode_view, &it->item->mode_texts, NULL);
2980    it->item->mode_content_objs =
2981      _item_content_realize(it, it->item->mode_view,
2982                            &it->item->mode_contents, NULL);
2983    _item_state_realize(it, it->item->mode_view, &it->item->mode_states, NULL);
2984
2985    edje_object_part_swallow(it->item->mode_view,
2986                             edje_object_data_get(it->item->mode_view, "mode_part"),
2987                             VIEW(it));
2988
2989    it->want_unrealize = EINA_FALSE;
2990    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2991    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2992 }
2993
2994 static void
2995 _mode_item_unrealize(Elm_Gen_Item *it)
2996 {
2997    Widget_Data *wd = it->wd;
2998    Evas_Object *content;
2999    if (!it->item->mode_view) return;
3000
3001    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3002    elm_widget_stringlist_free(it->item->mode_texts);
3003    it->item->mode_texts = NULL;
3004    elm_widget_stringlist_free(it->item->mode_contents);
3005    it->item->mode_contents = NULL;
3006    elm_widget_stringlist_free(it->item->mode_states);
3007
3008    EINA_LIST_FREE(it->item->mode_content_objs, content)
3009      evas_object_del(content);
3010
3011    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
3012    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3013    evas_object_del(it->item->mode_view);
3014    it->item->mode_view = NULL;
3015
3016    if (wd->mode_item == it)
3017      wd->mode_item = NULL;
3018    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3019    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3020 }
3021
3022 static void
3023 _item_mode_set(Elm_Gen_Item *it)
3024 {
3025    if (!it) return;
3026    Widget_Data *wd = it->wd;
3027    if (!wd) return;
3028    char buf[1024];
3029
3030    wd->mode_item = it;
3031    it->item->nocache = EINA_TRUE;
3032
3033    if (wd->scr_hold_timer)
3034      {
3035         ecore_timer_del(wd->scr_hold_timer);
3036         wd->scr_hold_timer = NULL;
3037      }
3038    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3039    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3040
3041    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3042    _mode_item_realize(it);
3043    if (it->item->group_item)
3044      evas_object_raise(it->item->VIEW(group_item));
3045    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
3046    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3047    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3048
3049    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
3050    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3051 }
3052
3053 static void
3054 _item_mode_unset(Widget_Data *wd)
3055 {
3056    if (!wd) return;
3057    if (!wd->mode_item) return;
3058    char buf[1024], buf2[1024];
3059    Elm_Gen_Item *it;
3060
3061    it = wd->mode_item;
3062    it->item->nocache = EINA_TRUE;
3063
3064    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type);
3065    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type);
3066
3067    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3068    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
3069
3070    wd->mode_item = NULL;
3071 }
3072
3073 static void
3074 _item_auto_scroll(Widget_Data *wd)
3075 {
3076    if (!wd) return;
3077    Elm_Gen_Item  *tmp_item = NULL;
3078
3079    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3080      {
3081         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3082         if (!tmp_item) return;
3083         wd->show_item = tmp_item;
3084         wd->bring_in = EINA_TRUE;
3085         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3086         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3087           {
3088              wd->show_item->item->showme = EINA_TRUE;
3089              wd->auto_scroll_enabled = EINA_FALSE;
3090           }
3091         else
3092           _scroll_item(wd);
3093      }
3094 }
3095
3096 EAPI Evas_Object *
3097 elm_genlist_add(Evas_Object *parent)
3098 {
3099    Evas_Object *obj;
3100    Evas *e;
3101    Widget_Data *wd;
3102    Evas_Coord minw, minh;
3103    static Evas_Smart *smart = NULL;
3104
3105    if (!smart)
3106      {
3107         static Evas_Smart_Class sc;
3108
3109         evas_object_smart_clipped_smart_set(&_pan_sc);
3110         sc = _pan_sc;
3111         sc.name = "elm_genlist_pan";
3112         sc.version = EVAS_SMART_CLASS_VERSION;
3113         sc.add = _pan_add;
3114         sc.del = _pan_del;
3115         sc.resize = _pan_resize;
3116         sc.move = _pan_move;
3117         sc.calculate = _pan_calculate;
3118         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3119      }
3120
3121    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3122
3123    ELM_SET_WIDTYPE(widtype, "genlist");
3124    ELM_GEN_SETUP(wd);
3125    elm_widget_type_set(obj, "genlist");
3126    elm_widget_sub_object_add(parent, obj);
3127    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3128    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3129    elm_widget_data_set(obj, wd);
3130    elm_widget_del_hook_set(obj, _del_hook);
3131    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3132    elm_widget_theme_hook_set(obj, _theme_hook);
3133    elm_widget_can_focus_set(obj, EINA_TRUE);
3134    elm_widget_event_hook_set(obj, _event_hook);
3135    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3136    elm_widget_translate_hook_set(obj, _translate_hook);
3137
3138    wd->generation = 1;
3139    wd->scr = elm_smart_scroller_add(e);
3140    elm_smart_scroller_widget_set(wd->scr, obj);
3141    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3142                                        elm_widget_style_get(obj));
3143    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3144                                        _elm_config->thumbscroll_bounce_enable);
3145    elm_widget_resize_object_set(obj, wd->scr);
3146
3147    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3148    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3149    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3150    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3151    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3152    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3153    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3154    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3155
3156    wd->obj = obj;
3157    wd->mode = ELM_LIST_SCROLL;
3158    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3159    wd->item_cache_max = wd->max_items_per_block * 2;
3160    wd->longpress_timeout = _elm_config->longpress_timeout;
3161
3162    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3163    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3164    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3165    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3166
3167    wd->pan_smart = evas_object_smart_add(e, smart);
3168    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3169    wd->pan->wd = wd;
3170
3171    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3172                                      _pan_set, _pan_get, _pan_max_get,
3173                                      _pan_min_get, _pan_child_size_get);
3174
3175    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3176                              &minw, &minh);
3177    evas_object_size_hint_min_set(obj, minw, minh);
3178
3179    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3180
3181    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3182    _sizing_eval(obj);
3183    return obj;
3184 }
3185
3186 void
3187 _item_select(Elm_Gen_Item *it)
3188 {
3189    if ((it->wd->no_select) || (it->generation < it->wd->generation) || (it->mode_set)) return;
3190    if (!it->selected)
3191      {
3192         it->selected = EINA_TRUE;
3193         it->wd->selected = eina_list_append(it->wd->selected, it);
3194      }
3195    else if (!it->wd->always_select) return;
3196
3197    evas_object_ref(WIDGET(it));
3198    it->walking++;
3199    it->wd->walking++;
3200    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3201    if (it->generation == it->wd->generation)
3202      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3203    it->walking--;
3204    it->wd->walking--;
3205    evas_object_unref(WIDGET(it));
3206    if ((it->wd->clear_me) && (!it->wd->walking))
3207      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3208    else
3209      {
3210         if ((!it->walking) && (it->generation < it->wd->generation))
3211           {
3212              if (!it->relcount)
3213                {
3214                   it->del_cb(it);
3215                   elm_widget_item_free(it);
3216                }
3217           }
3218         else
3219           it->wd->last_selected_item = (Elm_Object_Item *) it;
3220      }
3221 }
3222
3223 static Evas_Object *
3224 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
3225 {
3226    return edje_object_part_swallow_get(VIEW(it), part);
3227 }
3228
3229 static void
3230 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
3231 {
3232    if (content && part)
3233      {
3234         it->content_objs = eina_list_append(it->content_objs, content);
3235         edje_object_part_swallow(VIEW(it), part, content);
3236      }
3237 }
3238
3239 static Evas_Object *
3240 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
3241 {
3242    Evas_Object *obj;
3243    obj = edje_object_part_swallow_get(VIEW(it), part);
3244    if (!obj) return NULL;
3245    it->content_objs = eina_list_remove(it->content_objs, obj);
3246    edje_object_part_unswallow(VIEW(it), obj);
3247    return obj;
3248 }
3249
3250 static const char *
3251 _item_text_hook(Elm_Gen_Item *it, const char *part)
3252 {
3253    if (!it->itc->func.text_get) return NULL;
3254    return edje_object_part_text_get(VIEW(it), part);
3255 }
3256
3257 static void
3258 _item_disable_hook(Elm_Object_Item *it)
3259 {
3260    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
3261    Eina_List *l;
3262    Evas_Object *obj;
3263    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
3264
3265    if (_it->generation < _it->wd->generation) return;
3266
3267    if (_it->selected)
3268      elm_genlist_item_selected_set(it, EINA_FALSE);
3269
3270    if (_it->realized)
3271      {
3272         if (elm_widget_item_disabled_get(it))
3273           edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
3274         else
3275           edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
3276         EINA_LIST_FOREACH(_it->content_objs, l, obj)
3277           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
3278      }
3279 }
3280
3281 static Eina_Bool
3282 _item_del_pre_hook(Elm_Object_Item *it)
3283 {
3284    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3285    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
3286
3287    if ((_it->relcount > 0) || (_it->walking > 0))
3288      {
3289         elm_genlist_item_subitems_clear(it);
3290         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
3291         _elm_genlist_item_del_notserious(_it);
3292         if (_it->item->block)
3293           {
3294              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
3295              _it->item->block->changed = EINA_TRUE;
3296              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
3297              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
3298           }
3299         if (_it->parent)
3300           {
3301              _it->parent->item->items =
3302                 eina_list_remove(_it->parent->item->items, it);
3303              _it->parent = NULL;
3304           }
3305         return EINA_FALSE;
3306      }
3307    _item_del(_it);
3308    return EINA_TRUE;
3309 }
3310
3311 Elm_Gen_Item *
3312 _elm_genlist_item_new(Widget_Data              *wd,
3313                       const Elm_Gen_Item_Class *itc,
3314                       const void               *data,
3315                       Elm_Gen_Item             *parent,
3316                       Evas_Smart_Cb             func,
3317                       const void               *func_data)
3318 {
3319    Elm_Gen_Item *it;
3320
3321    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
3322    if (!it) return NULL;
3323    it->wd = wd;
3324    it->generation = wd->generation;
3325    it->itc = itc;
3326    it->base.data = data;
3327    it->parent = parent;
3328    it->func.func = func;
3329    it->func.data = func_data;
3330    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
3331    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
3332    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
3333    elm_widget_item_disable_hook_set(it, _item_disable_hook);
3334    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
3335    /* TEMPORARY */
3336    it->sel_cb = (Ecore_Cb)_item_select;
3337
3338    elm_widget_item_text_get_hook_set(it, _item_text_hook);
3339    return it;
3340 }
3341
3342 static Elm_Gen_Item *
3343 _item_new(Widget_Data                  *wd,
3344           const Elm_Genlist_Item_Class *itc,
3345           const void                   *data,
3346           Elm_Gen_Item                 *parent,
3347           Elm_Genlist_Item_Flags        flags,
3348           Evas_Smart_Cb                 func,
3349           const void                   *func_data)
3350 {
3351    Elm_Gen_Item *it, *it2;
3352    int depth = 0;
3353
3354    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
3355    if (!it) return NULL;
3356    it->item = ELM_NEW(Elm_Gen_Item_Type);
3357    it->item->flags = flags;
3358    if (flags & ELM_GENLIST_ITEM_GROUP) it->group++;
3359    it->item->expanded_depth = 0;
3360    ELM_GEN_ITEM_SETUP(it);
3361    if (it->parent)
3362      {
3363         if (it->parent->group)
3364           it->item->group_item = parent;
3365         else if (it->parent->item->group_item)
3366           it->item->group_item = it->parent->item->group_item;
3367      }
3368    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
3369      {
3370         if (!it2->parent->group) depth += 1;
3371      }
3372    it->item->expanded_depth = depth;
3373    return it;
3374 }
3375
3376 static Item_Block *
3377 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
3378 {
3379    Item_Block *itb;
3380
3381    itb = calloc(1, sizeof(Item_Block));
3382    if (!itb) return NULL;
3383    itb->wd = wd;
3384    if (prepend)
3385      {
3386         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3387         _item_block_position_update(wd->blocks, 0);
3388      }
3389    else
3390      {
3391         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3392         itb->position_update = EINA_TRUE;
3393         if (wd->blocks != EINA_INLIST_GET(itb))
3394           {
3395              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3396           }
3397         else
3398           {
3399              itb->position = 0;
3400           }
3401      }
3402    return itb;
3403 }
3404
3405 static Eina_Bool
3406 _item_block_add(Widget_Data *wd,
3407                 Elm_Gen_Item *it)
3408 {
3409    Item_Block *itb = NULL;
3410
3411    if (!it->item->rel)
3412      {
3413 newblock:
3414         if (it->item->rel)
3415           {
3416              itb = calloc(1, sizeof(Item_Block));
3417              if (!itb) return EINA_FALSE;
3418              itb->wd = wd;
3419              if (!it->item->rel->item->block)
3420                {
3421                   wd->blocks =
3422                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3423                   itb->items = eina_list_append(itb->items, it);
3424                   itb->position_update = EINA_TRUE;
3425                   it->position = eina_list_count(itb->items);
3426                   it->position_update = EINA_TRUE;
3427
3428                   if (wd->blocks != EINA_INLIST_GET(itb))
3429                     {
3430                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3431                     }
3432                   else
3433                     {
3434                        itb->position = 0;
3435                     }
3436                }
3437              else
3438                {
3439                   Eina_List *tmp;
3440
3441                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3442                   if (it->item->before)
3443                     {
3444                        wd->blocks = eina_inlist_prepend_relative
3445                            (wd->blocks, EINA_INLIST_GET(itb),
3446                            EINA_INLIST_GET(it->item->rel->item->block));
3447                        itb->items =
3448                          eina_list_prepend_relative_list(itb->items, it, tmp);
3449
3450                        /* Update index from where we prepended */
3451                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3452                        _item_block_position_update(EINA_INLIST_GET(itb),
3453                                                    it->item->rel->item->block->position);
3454                     }
3455                   else
3456                     {
3457                        wd->blocks = eina_inlist_append_relative
3458                            (wd->blocks, EINA_INLIST_GET(itb),
3459                            EINA_INLIST_GET(it->item->rel->item->block));
3460                        itb->items =
3461                          eina_list_append_relative_list(itb->items, it, tmp);
3462
3463                        /* Update block index from where we appended */
3464                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3465                        _item_block_position_update(EINA_INLIST_GET(itb),
3466                                                    it->item->rel->item->block->position + 1);
3467                     }
3468                }
3469           }
3470         else
3471           {
3472              if (it->item->before)
3473                {
3474                   if (wd->blocks)
3475                     {
3476                        itb = (Item_Block *)(wd->blocks);
3477                        if (itb->count >= wd->max_items_per_block)
3478                          {
3479                             itb = _item_block_new(wd, EINA_TRUE);
3480                             if (!itb) return EINA_FALSE;
3481                          }
3482                     }
3483                   else
3484                     {
3485                        itb = _item_block_new(wd, EINA_TRUE);
3486                        if (!itb) return EINA_FALSE;
3487                     }
3488                   itb->items = eina_list_prepend(itb->items, it);
3489
3490                   _item_position_update(itb->items, 0);
3491                }
3492              else
3493                {
3494                   if (wd->blocks)
3495                     {
3496                        itb = (Item_Block *)(wd->blocks->last);
3497                        if (itb->count >= wd->max_items_per_block)
3498                          {
3499                             itb = _item_block_new(wd, EINA_FALSE);
3500                             if (!itb) return EINA_FALSE;
3501                          }
3502                     }
3503                   else
3504                     {
3505                        itb = _item_block_new(wd, EINA_FALSE);
3506                        if (!itb) return EINA_FALSE;
3507                     }
3508                   itb->items = eina_list_append(itb->items, it);
3509                   it->position = eina_list_count(itb->items);
3510                }
3511           }
3512      }
3513    else
3514      {
3515         Eina_List *tmp;
3516
3517         if (it->item->rel->item->queued)
3518           {
3519              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3520                 on sorted insertion order, so the queue is not always ordered like the item list.
3521                 This lead to issue where we depend on an item that is not yet created. As a quick
3522                 work around, we reschedule the calc of the item and stop reordering the list to
3523                 prevent any nasty issue to show up here.
3524               */
3525              wd->queue = eina_list_append(wd->queue, it);
3526              wd->requeued = EINA_TRUE;
3527              it->item->queued = EINA_TRUE;
3528              return EINA_FALSE;
3529           }
3530         itb = it->item->rel->item->block;
3531         if (!itb) goto newblock;
3532         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3533         if (it->item->before)
3534           {
3535              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3536              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3537           }
3538         else
3539           {
3540              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3541              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3542           }
3543      }
3544    itb->count++;
3545    itb->changed = EINA_TRUE;
3546    it->item->block = itb;
3547    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3548    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3549    if (it->item->rel)
3550      {
3551         it->item->rel->relcount--;
3552         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3553           {
3554              _item_del(it->item->rel);
3555              elm_widget_item_free(it->item->rel);
3556           }
3557         it->item->rel = NULL;
3558      }
3559    if (itb->count > itb->wd->max_items_per_block)
3560      {
3561         Item_Block *itb2;
3562         Elm_Gen_Item *it2;
3563         int newc;
3564         Eina_Bool done = EINA_FALSE;
3565
3566         newc = itb->count / 2;
3567
3568         if (EINA_INLIST_GET(itb)->prev)
3569           {
3570              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3571
3572              if (itbp->count + newc < wd->max_items_per_block / 2)
3573                {
3574                   /* moving items to previous block */
3575                   while ((itb->count > newc) && (itb->items))
3576                     {
3577                        it2 = eina_list_data_get(itb->items);
3578                        itb->items = eina_list_remove_list(itb->items, itb->items);
3579                        itb->count--;
3580
3581                        itbp->items = eina_list_append(itbp->items, it2);
3582                        it2->item->block = itbp;
3583                        itbp->count++;
3584                     }
3585
3586                   done = EINA_TRUE;
3587                }
3588           }
3589
3590         if (!done && EINA_INLIST_GET(itb)->next)
3591           {
3592              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3593
3594              if (itbn->count + newc < wd->max_items_per_block / 2)
3595                {
3596                   /* moving items to next block */
3597                   while ((itb->count > newc) && (itb->items))
3598                     {
3599                        Eina_List *l;
3600
3601                        l = eina_list_last(itb->items);
3602                        it2 = eina_list_data_get(l);
3603                        itb->items = eina_list_remove_list(itb->items, l);
3604                        itb->count--;
3605
3606                        itbn->items = eina_list_prepend(itbn->items, it2);
3607                        it2->item->block = itbn;
3608                        itbn->count++;
3609                     }
3610
3611                   done = EINA_TRUE;
3612                }
3613           }
3614
3615         if (!done)
3616           {
3617              /* moving items to new block */
3618              itb2 = calloc(1, sizeof(Item_Block));
3619              if (!itb2) return EINA_FALSE;
3620              itb2->wd = wd;
3621              wd->blocks =
3622                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3623                                            EINA_INLIST_GET(itb));
3624              itb2->changed = EINA_TRUE;
3625              while ((itb->count > newc) && (itb->items))
3626                {
3627                   Eina_List *l;
3628
3629                   l = eina_list_last(itb->items);
3630                   it2 = l->data;
3631                   itb->items = eina_list_remove_list(itb->items, l);
3632                   itb->count--;
3633
3634                   itb2->items = eina_list_prepend(itb2->items, it2);
3635                   it2->item->block = itb2;
3636                   itb2->count++;
3637                }
3638           }
3639      }
3640
3641    return EINA_TRUE;
3642 }
3643
3644 static int
3645 _queue_process(Widget_Data *wd)
3646 {
3647    int n;
3648    Eina_Bool showme = EINA_FALSE;
3649    double t0, t;
3650
3651    t0 = ecore_loop_time_get();
3652    //evas_event_freeze(evas_object_evas_get(wd->obj));
3653    for (n = 0; (wd->queue) && (n < 128); n++)
3654      {
3655         Elm_Gen_Item *it;
3656
3657         it = eina_list_data_get(wd->queue);
3658         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3659         it->item->queued = EINA_FALSE;
3660         if (!_item_block_add(wd, it)) continue;
3661         if (!wd->blocks)
3662           _item_block_realize(it->item->block);
3663         t = ecore_time_get();
3664         if (it->item->block->changed)
3665           {
3666              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
3667              it->item->block->changed = 0;
3668              if (wd->pan_changed)
3669                {
3670                   if (wd->calc_job) ecore_job_del(wd->calc_job);
3671                   wd->calc_job = NULL;
3672                   _calc_job(wd);
3673                   wd->pan_changed = EINA_FALSE;
3674                }
3675           }
3676         if (showme) it->item->block->showme = EINA_TRUE;
3677         /* same as eina_inlist_count > 1 */
3678         if (wd->blocks && wd->blocks->next)
3679           {
3680              if ((t - t0) > (ecore_animator_frametime_get())) break;
3681           }
3682      }
3683    //evas_event_thaw(evas_object_evas_get(wd->obj));
3684    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3685    return n;
3686 }
3687
3688 static Eina_Bool
3689 _idle_process(void *data, Eina_Bool *wakeup)
3690 {
3691    Widget_Data *wd = data;
3692
3693    //xxx
3694    //static double q_start = 0.0;
3695    //if (q_start == 0.0) q_start = ecore_time_get();
3696    //xxx
3697    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3698    if (!wd->queue)
3699      {
3700         //xxx
3701         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3702         //xxx
3703         return ECORE_CALLBACK_CANCEL;
3704      }
3705    return ECORE_CALLBACK_RENEW;
3706 }
3707
3708 static Eina_Bool
3709 _item_idle_enterer(void *data)
3710 {
3711    Widget_Data *wd = data;
3712    Eina_Bool wakeup = EINA_FALSE;
3713    Eina_Bool ok = _idle_process(data, &wakeup);
3714
3715    if (wakeup)
3716      {
3717         // wake up mainloop
3718         if (wd->calc_job) ecore_job_del(wd->calc_job);
3719         wd->calc_job = ecore_job_add(_calc_job, wd);
3720      }
3721    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3722    return ok;
3723 }
3724
3725 static void
3726 _item_queue(Widget_Data *wd,
3727             Elm_Gen_Item *it,
3728             Eina_Compare_Cb cb)
3729 {
3730    if (it->item->queued) return;
3731    it->item->queued = EINA_TRUE;
3732    if (cb && !wd->requeued)
3733      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
3734    else
3735      wd->queue = eina_list_append(wd->queue, it);
3736 // FIXME: why does a freeze then thaw here cause some genlist
3737 // elm_genlist_item_append() to be much much slower?
3738 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3739    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3740      {
3741         if (wd->queue_idle_enterer)
3742           {
3743              ecore_idle_enterer_del(wd->queue_idle_enterer);
3744              wd->queue_idle_enterer = NULL;
3745           }
3746         _queue_process(wd);
3747      }
3748 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3749 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3750    if (!wd->queue_idle_enterer)
3751      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3752 }
3753
3754 static int
3755 _elm_genlist_item_compare_data(const void *data, const void *data1)
3756 {
3757    const Elm_Gen_Item *it = data;
3758    const Elm_Gen_Item *item1 = data1;
3759
3760    return it->wd->item_compare_data_cb(it->base.data, item1->base.data);
3761 }
3762
3763 static int
3764 _elm_genlist_item_compare(const void *data, const void *data1)
3765 {
3766    const Elm_Gen_Item *it, *item1;
3767    it = ELM_GEN_ITEM_FROM_INLIST(data);
3768    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
3769    return it->wd->item_compare_cb(it, item1);
3770 }
3771
3772 static int
3773 _elm_genlist_item_list_compare(const void *data, const void *data1)
3774 {
3775    const Elm_Gen_Item *it = data;
3776    const Elm_Gen_Item *item1 = data1;
3777    return it->wd->item_compare_cb(it, item1);
3778 }
3779
3780 static void
3781 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
3782 {
3783    if (!it) return;
3784    if (!after) return;
3785
3786    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3787    _item_block_del(it);
3788
3789    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3790    it->item->rel = after;
3791    it->item->rel->relcount++;
3792    it->item->before = EINA_FALSE;
3793    if (after->item->group_item) it->item->group_item = after->item->group_item;
3794    _item_queue(it->wd, it, NULL);
3795
3796    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3797 }
3798
3799 static void
3800 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
3801 {
3802    if (!it) return;
3803    if (!before) return;
3804
3805    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3806    _item_block_del(it);
3807    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3808    it->item->rel = before;
3809    it->item->rel->relcount++;
3810    it->item->before = EINA_TRUE;
3811    if (before->item->group_item) it->item->group_item = before->item->group_item;
3812    _item_queue(it->wd, it, NULL);
3813
3814    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3815 }
3816
3817 EAPI Elm_Object_Item *
3818 elm_genlist_item_append(Evas_Object                  *obj,
3819                         const Elm_Genlist_Item_Class *itc,
3820                         const void                   *data,
3821                         Elm_Object_Item              *parent,
3822                         Elm_Genlist_Item_Flags        flags,
3823                         Evas_Smart_Cb                 func,
3824                         const void                   *func_data)
3825 {
3826    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3827    Widget_Data *wd = elm_widget_data_get(obj);
3828    if (!wd) return NULL;
3829    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3830                                 func, func_data);
3831    if (!it) return NULL;
3832    if (!it->parent)
3833      {
3834         if (it->group)
3835           wd->group_items = eina_list_append(wd->group_items, it);
3836         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3837         it->item->rel = NULL;
3838      }
3839    else
3840      {
3841         Elm_Gen_Item *it2 = NULL;
3842         Eina_List *ll = eina_list_last(it->parent->item->items);
3843         if (ll) it2 = ll->data;
3844         it->parent->item->items = eina_list_append(it->parent->item->items, it);
3845         if (!it2) it2 = it->parent;
3846         wd->items =
3847           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3848                                       EINA_INLIST_GET(it2));
3849         it->item->rel = it2;
3850         it->item->rel->relcount++;
3851      }
3852    it->item->before = EINA_FALSE;
3853    _item_queue(wd, it, NULL);
3854    return (Elm_Object_Item *) it;
3855 }
3856
3857 EAPI Elm_Object_Item *
3858 elm_genlist_item_prepend(Evas_Object                  *obj,
3859                          const Elm_Genlist_Item_Class *itc,
3860                          const void                   *data,
3861                          Elm_Object_Item              *parent,
3862                          Elm_Genlist_Item_Flags        flags,
3863                          Evas_Smart_Cb                 func,
3864                          const void                   *func_data)
3865 {
3866    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3867    Widget_Data *wd = elm_widget_data_get(obj);
3868    if (!wd) return NULL;
3869    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3870                                 func, func_data);
3871    if (!it) return NULL;
3872    if (!it->parent)
3873      {
3874         if (it->group)
3875           wd->group_items = eina_list_prepend(wd->group_items, it);
3876         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3877         it->item->rel = NULL;
3878      }
3879    else
3880      {
3881         Elm_Gen_Item *it2 = NULL;
3882         Eina_List *ll = it->parent->item->items;
3883         if (ll) it2 = ll->data;
3884         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
3885         if (!it2) it2 = it->parent;
3886         wd->items =
3887           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3888                                        EINA_INLIST_GET(it2));
3889         it->item->rel = it2;
3890         it->item->rel->relcount++;
3891      }
3892    it->item->before = EINA_TRUE;
3893    _item_queue(wd, it, NULL);
3894    return (Elm_Object_Item *) it;
3895 }
3896
3897 EAPI Elm_Object_Item *
3898 elm_genlist_item_insert_after(Evas_Object                  *obj,
3899                               const Elm_Genlist_Item_Class *itc,
3900                               const void                   *data,
3901                               Elm_Object_Item              *parent,
3902                               Elm_Object_Item              *after,
3903                               Elm_Genlist_Item_Flags        flags,
3904                               Evas_Smart_Cb                 func,
3905                               const void                   *func_data)
3906 {
3907    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3908    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
3909    Widget_Data *wd = elm_widget_data_get(obj);
3910    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
3911    if (!wd) return NULL;
3912    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
3913    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3914
3915    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3916                                 func, func_data);
3917    if (!it) return NULL;
3918    if (!it->parent)
3919      {
3920         if ((it->group) && (_after->group))
3921           wd->group_items = eina_list_append_relative(wd->group_items, it,
3922                                                       _after);
3923      }
3924    else
3925      {
3926         it->parent->item->items =
3927            eina_list_append_relative(it->parent->item->items, it, _after);
3928      }
3929    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3930                                            EINA_INLIST_GET(_after));
3931    it->item->rel = _after;
3932    it->item->rel->relcount++;
3933    it->item->before = EINA_FALSE;
3934    _item_queue(wd, it, NULL);
3935    return (Elm_Object_Item *) it;
3936 }
3937
3938 EAPI Elm_Object_Item *
3939 elm_genlist_item_insert_before(Evas_Object                  *obj,
3940                                const Elm_Genlist_Item_Class *itc,
3941                                const void                   *data,
3942                                Elm_Object_Item              *parent,
3943                                Elm_Object_Item              *before,
3944                                Elm_Genlist_Item_Flags        flags,
3945                                Evas_Smart_Cb                 func,
3946                                const void                   *func_data)
3947 {
3948    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3949    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
3950    Widget_Data *wd = elm_widget_data_get(obj);
3951    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
3952    if (!wd) return NULL;
3953    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
3954    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3955
3956    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3957                                 func, func_data);
3958    if (!it) return NULL;
3959    if (!it->parent)
3960      {
3961         if (it->group && _before->group)
3962           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
3963                                                        _before);
3964      }
3965    else
3966      {
3967         it->parent->item->items =
3968            eina_list_prepend_relative(it->parent->item->items, it, _before);
3969      }
3970    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3971                                             EINA_INLIST_GET(_before));
3972    it->item->rel = _before;
3973    it->item->rel->relcount++;
3974    it->item->before = EINA_TRUE;
3975    _item_queue(wd, it, NULL);
3976    return (Elm_Object_Item *) it;
3977 }
3978
3979 EAPI Elm_Object_Item *
3980 elm_genlist_item_direct_sorted_insert(Evas_Object                  *obj,
3981                                       const Elm_Genlist_Item_Class *itc,
3982                                       const void                   *data,
3983                                       Elm_Object_Item              *parent,
3984                                       Elm_Genlist_Item_Flags        flags,
3985                                       Eina_Compare_Cb               comp,
3986                                       Evas_Smart_Cb                 func,
3987                                       const void                   *func_data)
3988 {
3989    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3990    Widget_Data *wd = elm_widget_data_get(obj);
3991    if (!wd) return NULL;
3992    Elm_Gen_Item *rel = NULL;
3993    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
3994                                 func, func_data);
3995    if (!it) return NULL;
3996
3997    wd->item_compare_cb = comp;
3998
3999    if (it->parent)
4000      {
4001         Eina_List *l;
4002         int cmp_result;
4003
4004         l = eina_list_search_sorted_near_list(it->parent->item->items,
4005                                               _elm_genlist_item_list_compare, it,
4006                                               &cmp_result);
4007         if (l)
4008           rel = eina_list_data_get(l);
4009         else
4010           rel = it->parent;
4011
4012         if (cmp_result >= 0)
4013           {
4014              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4015              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4016              it->item->before = EINA_FALSE;
4017           }
4018         else if (cmp_result < 0)
4019           {
4020              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4021              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4022              it->item->before = EINA_TRUE;
4023           }
4024      }
4025    else
4026      {
4027         if (!wd->state)
4028           {
4029              wd->state = eina_inlist_sorted_state_new();
4030              eina_inlist_sorted_state_init(wd->state, wd->items);
4031              wd->requeued = EINA_FALSE;
4032           }
4033
4034         if (it->group)
4035           wd->group_items = eina_list_append(wd->group_items, it);
4036
4037         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4038                                                     _elm_genlist_item_compare, wd->state);
4039
4040         if (EINA_INLIST_GET(it)->next)
4041           {
4042              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4043              it->item->before = EINA_TRUE;
4044           }
4045         else if (EINA_INLIST_GET(it)->prev)
4046           {
4047              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4048              it->item->before = EINA_FALSE;
4049           }
4050      }
4051
4052    if (rel)
4053      {
4054         it->item->rel = rel;
4055         it->item->rel->relcount++;
4056      }
4057
4058    _item_queue(wd, it, _elm_genlist_item_list_compare);
4059
4060    return (Elm_Object_Item *) it;
4061 }
4062
4063 EAPI Elm_Object_Item *
4064 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4065                                const Elm_Genlist_Item_Class *itc,
4066                                const void                   *data,
4067                                Elm_Object_Item              *parent,
4068                                Elm_Genlist_Item_Flags        flags,
4069                                Eina_Compare_Cb               comp,
4070                                Evas_Smart_Cb                 func,
4071                                const void                   *func_data)
4072 {
4073    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4074    Widget_Data *wd = elm_widget_data_get(obj);
4075    wd->item_compare_data_cb = comp;
4076    return elm_genlist_item_direct_sorted_insert(obj, itc, data, parent, flags,
4077                                                 _elm_genlist_item_compare_data,
4078                                                 func, func_data);
4079 }
4080
4081 static void
4082 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4083 {
4084    Eina_Inlist *next, *l;
4085
4086    ELM_CHECK_WIDTYPE(obj, widtype);
4087    Widget_Data *wd = elm_widget_data_get(obj);
4088    if (!wd) return;
4089
4090    if (!standby) wd->generation++;
4091
4092    if (wd->state)
4093      {
4094         eina_inlist_sorted_state_free(wd->state);
4095         wd->state = NULL;
4096      }
4097
4098    if (wd->walking > 0)
4099      {
4100         wd->clear_me = 1;
4101         return;
4102      }
4103    evas_event_freeze(evas_object_evas_get(wd->obj));
4104    for (l = wd->items, next = l ? l->next : NULL;
4105         l;
4106         l = next, next = next ? next->next : NULL)
4107      {
4108         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4109
4110         if (it->generation < wd->generation)
4111           {
4112              Elm_Gen_Item *itn = NULL;
4113
4114              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4115              if (itn) itn->walking++; /* prevent early death of subitem */
4116              it->del_cb(it);
4117              elm_widget_item_free(it);
4118              if (itn) itn->walking--;
4119           }
4120      }
4121    wd->clear_me = 0;
4122    wd->pan_changed = EINA_TRUE;
4123    if (wd->calc_job)
4124      {
4125         ecore_job_del(wd->calc_job);
4126         wd->calc_job = NULL;
4127      }
4128    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4129    if (wd->clear_cb) wd->clear_cb(wd);
4130    wd->pan_x = 0;
4131    wd->pan_y = 0;
4132    wd->minw = 0;
4133    wd->minh = 0;
4134    wd->count = 0;
4135    if (wd->pan_smart)
4136      {
4137         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4138         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4139      }
4140    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4141    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4142    evas_event_thaw(evas_object_evas_get(wd->obj));
4143    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4144 }
4145
4146 EAPI void
4147 elm_genlist_clear(Evas_Object *obj)
4148 {
4149    _elm_genlist_clear(obj, EINA_FALSE);
4150 }
4151
4152 EAPI void
4153 elm_genlist_multi_select_set(Evas_Object *obj,
4154                              Eina_Bool    multi)
4155 {
4156    ELM_CHECK_WIDTYPE(obj, widtype);
4157    Widget_Data *wd = elm_widget_data_get(obj);
4158    if (!wd) return;
4159    wd->multi = multi;
4160 }
4161
4162 EAPI Eina_Bool
4163 elm_genlist_multi_select_get(const Evas_Object *obj)
4164 {
4165    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4166    Widget_Data *wd = elm_widget_data_get(obj);
4167    if (!wd) return EINA_FALSE;
4168    return wd->multi;
4169 }
4170
4171 EAPI Elm_Object_Item *
4172 elm_genlist_selected_item_get(const Evas_Object *obj)
4173 {
4174    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4175    Widget_Data *wd = elm_widget_data_get(obj);
4176    if (!wd) return NULL;
4177    if (wd->selected) return wd->selected->data;
4178    return NULL;
4179 }
4180
4181 EAPI const Eina_List *
4182 elm_genlist_selected_items_get(const Evas_Object *obj)
4183 {
4184    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4185    Widget_Data *wd = elm_widget_data_get(obj);
4186    if (!wd) return NULL;
4187    return wd->selected;
4188 }
4189
4190 EAPI Eina_List *
4191 elm_genlist_realized_items_get(const Evas_Object *obj)
4192 {
4193    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4194    Widget_Data *wd = elm_widget_data_get(obj);
4195    Eina_List *list = NULL;
4196    Item_Block *itb;
4197    Eina_Bool done = EINA_FALSE;
4198    if (!wd) return NULL;
4199    EINA_INLIST_FOREACH(wd->blocks, itb)
4200      {
4201         if (itb->realized)
4202           {
4203              Eina_List *l;
4204              Elm_Gen_Item *it;
4205
4206              done = 1;
4207              EINA_LIST_FOREACH(itb->items, l, it)
4208                {
4209                   if (it->realized) list = eina_list_append(list, it);
4210                }
4211           }
4212         else
4213           {
4214              if (done) break;
4215           }
4216      }
4217    return list;
4218 }
4219
4220 EAPI Elm_Object_Item *
4221 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4222                            Evas_Coord         x,
4223                            Evas_Coord         y,
4224                            int               *posret)
4225 {
4226    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4227    Widget_Data *wd = elm_widget_data_get(obj);
4228    Evas_Coord ox, oy, ow, oh;
4229    Item_Block *itb;
4230    Evas_Coord lasty;
4231    if (!wd) return NULL;
4232    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4233    lasty = oy;
4234    EINA_INLIST_FOREACH(wd->blocks, itb)
4235      {
4236         Eina_List *l;
4237         Elm_Gen_Item *it;
4238
4239         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4240                                  oy + itb->y - itb->wd->pan_y,
4241                                  itb->w, itb->h, x, y, 1, 1))
4242           continue;
4243         EINA_LIST_FOREACH(itb->items, l, it)
4244           {
4245              Evas_Coord itx, ity;
4246
4247              itx = ox + itb->x + it->x - itb->wd->pan_x;
4248              ity = oy + itb->y + it->y - itb->wd->pan_y;
4249              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4250                {
4251                   if (posret)
4252                     {
4253                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
4254                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
4255                          *posret = 1;
4256                        else *posret = 0;
4257                     }
4258                   return (Elm_Object_Item *) it;
4259                }
4260              lasty = ity + it->item->h;
4261           }
4262      }
4263    if (posret)
4264      {
4265         if (y > lasty) *posret = 1;
4266         else *posret = -1;
4267      }
4268    return NULL;
4269 }
4270
4271 EAPI Elm_Object_Item *
4272 elm_genlist_first_item_get(const Evas_Object *obj)
4273 {
4274    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4275    Widget_Data *wd = elm_widget_data_get(obj);
4276    if (!wd) return NULL;
4277    if (!wd->items) return NULL;
4278    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4279    while ((it) && (it->generation < wd->generation))
4280      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4281    return (Elm_Object_Item *) it;
4282 }
4283
4284 EAPI Elm_Object_Item *
4285 elm_genlist_last_item_get(const Evas_Object *obj)
4286 {
4287    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4288    Widget_Data *wd = elm_widget_data_get(obj);
4289    if (!wd) return NULL;
4290    if (!wd->items) return NULL;
4291    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4292    while ((it) && (it->generation < wd->generation))
4293      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4294    return (Elm_Object_Item *) it;
4295 }
4296
4297 EAPI Elm_Object_Item *
4298 elm_genlist_item_next_get(const Elm_Object_Item *it)
4299 {
4300    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4301    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4302    while (_it)
4303      {
4304         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
4305         if ((_it) && (_it->generation == _it->wd->generation)) break;
4306      }
4307    return (Elm_Object_Item *) _it;
4308 }
4309
4310 EAPI Elm_Object_Item *
4311 elm_genlist_item_prev_get(const Elm_Object_Item *it)
4312 {
4313    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4314    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4315    while (_it)
4316      {
4317         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
4318         if ((_it) && (_it->generation == _it->wd->generation)) break;
4319      }
4320    return (Elm_Object_Item *) _it;
4321 }
4322
4323 EAPI Evas_Object *
4324 elm_genlist_item_genlist_get(const Elm_Object_Item *it)
4325 {
4326    return elm_object_item_widget_get(it);
4327 }
4328
4329 EAPI Elm_Object_Item *
4330 elm_genlist_item_parent_get(const Elm_Object_Item *it)
4331 {
4332    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4333    return (Elm_Object_Item *) ((Elm_Gen_Item *) it)->parent;
4334 }
4335
4336 EAPI void
4337 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4338 {
4339    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4340    Eina_List *tl = NULL, *l;
4341    Elm_Gen_Item *_it;
4342    Elm_Object_Item *it2;
4343    _it = (Elm_Gen_Item *) it;
4344
4345    EINA_LIST_FOREACH(_it->item->items, l, it2)
4346      tl = eina_list_append(tl, it2);
4347    EINA_LIST_FREE(tl, it2)
4348      elm_object_item_del(it2);
4349 }
4350
4351 EAPI void
4352 elm_genlist_item_selected_set(Elm_Object_Item *it,
4353                               Eina_Bool selected)
4354 {
4355    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4356    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4357    Widget_Data *wd = _it->wd;
4358    if (!wd) return;
4359    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4360      return;
4361    selected = !!selected;
4362    if (_it->selected == selected) return;
4363
4364    if (selected)
4365      {
4366         if (!wd->multi)
4367           {
4368              while (wd->selected)
4369                {
4370                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4371                   _it->unsel_cb(wd->selected->data);
4372                }
4373           }
4374         _it->highlight_cb(_it);
4375         _item_select(_it);
4376         return;
4377      }
4378    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4379    _it->unsel_cb(_it);
4380 }
4381
4382 EAPI Eina_Bool
4383 elm_genlist_item_selected_get(const Elm_Object_Item *it)
4384 {
4385    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4386    return ((Elm_Gen_Item *) it)->selected;
4387 }
4388
4389 EAPI void
4390 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
4391                               Eina_Bool         expanded)
4392 {
4393    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4394    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4395    if (_it->item->expanded == expanded) return;
4396    _it->item->expanded = expanded;
4397    _it->wd->expanded_item = _it;
4398    if (_it->item->expanded)
4399      {
4400         if (_it->realized)
4401           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4402         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4403         _it->wd->auto_scroll_enabled = EINA_TRUE;
4404      }
4405    else
4406      {
4407         if (_it->realized)
4408           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4409         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4410         _it->wd->auto_scroll_enabled = EINA_FALSE;
4411      }
4412 }
4413
4414 EAPI Eina_Bool
4415 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4416 {
4417    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4418    return ((Elm_Gen_Item *) it)->item->expanded;
4419 }
4420
4421 EAPI int
4422 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4423 {
4424    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4425    return ((Elm_Gen_Item *) it)->item->expanded_depth;
4426 }
4427
4428 EAPI void
4429 elm_genlist_item_disabled_set(Elm_Object_Item  *it,
4430                               Eina_Bool         disabled)
4431 {
4432    elm_object_item_disabled_set(it, disabled);
4433 }
4434
4435 EAPI Eina_Bool
4436 elm_genlist_item_disabled_get(const Elm_Object_Item *it)
4437 {
4438    return elm_object_item_disabled_get(it);
4439 }
4440
4441 EAPI void
4442 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
4443                                   Eina_Bool         display_only)
4444 {
4445    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4446    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4447    display_only = !!display_only;
4448    if (_it->display_only == display_only) return;
4449    if (_it->generation < _it->wd->generation) return;
4450    _it->display_only = display_only;
4451    _it->item->mincalcd = EINA_FALSE;
4452    _it->item->updateme = EINA_TRUE;
4453    if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
4454    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4455    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4456 }
4457
4458 EAPI Eina_Bool
4459 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
4460 {
4461    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4462    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4463    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4464    return _it->display_only;
4465 }
4466
4467 EAPI void
4468 elm_genlist_item_show(Elm_Object_Item *it)
4469 {
4470    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4471    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4472    Evas_Coord gith = 0;
4473    if (_it->generation < _it->wd->generation) return;
4474    if ((_it->item->queued) || (!_it->item->mincalcd))
4475      {
4476         _it->wd->show_item = _it;
4477         _it->wd->bring_in = EINA_FALSE;
4478         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
4479         _it->item->showme = EINA_TRUE;
4480         return;
4481      }
4482    if (_it->wd->show_item)
4483      {
4484         _it->wd->show_item->item->showme = EINA_FALSE;
4485         _it->wd->show_item = NULL;
4486      }
4487    if ((_it->item->group_item) &&
4488        (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4489      gith = _it->item->group_item->item->h;
4490    elm_smart_scroller_child_region_show(_it->wd->scr,
4491                                         _it->x + _it->item->block->x,
4492                                         _it->y + _it->item->block->y - gith,
4493                                         _it->item->block->w, _it->item->h);
4494 }
4495
4496 EAPI void
4497 elm_genlist_item_promote(Elm_Object_Item *it)
4498 {
4499    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4500    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4501    if (_it->generation < _it->wd->generation) return;
4502    _item_move_before(_it,
4503                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4504 }
4505
4506 EAPI void
4507 elm_genlist_item_demote(Elm_Object_Item *it)
4508 {
4509    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4510    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4511    if (_it->generation < _it->wd->generation) return;
4512    _item_move_after(_it,
4513                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4514 }
4515
4516 EAPI void
4517 elm_genlist_item_bring_in(Elm_Object_Item *it)
4518 {
4519    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4520    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4521    Evas_Coord gith = 0;
4522    if (_it->generation < _it->wd->generation) return;
4523    if ((_it->item->queued) || (!_it->item->mincalcd))
4524      {
4525         _it->wd->show_item = _it;
4526         _it->wd->bring_in = EINA_TRUE;
4527         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
4528         _it->item->showme = EINA_TRUE;
4529         return;
4530      }
4531    if (_it->wd->show_item)
4532      {
4533         _it->wd->show_item->item->showme = EINA_FALSE;
4534         _it->wd->show_item = NULL;
4535      }
4536    if ((_it->item->group_item) &&
4537        (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4538      gith = _it->item->group_item->item->h;
4539    elm_smart_scroller_region_bring_in(_it->wd->scr,
4540                                       _it->x + _it->item->block->x,
4541                                       _it->y + _it->item->block->y - gith,
4542                                       _it->item->block->w, _it->item->h);
4543 }
4544
4545 EAPI void
4546 elm_genlist_item_top_show(Elm_Object_Item *it)
4547 {
4548    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4549    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4550    Evas_Coord ow, oh;
4551    Evas_Coord gith = 0;
4552
4553    if (_it->generation < _it->wd->generation) return;
4554    if ((_it->item->queued) || (!_it->item->mincalcd))
4555      {
4556         _it->wd->show_item = _it;
4557         _it->wd->bring_in = EINA_FALSE;
4558         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
4559         _it->item->showme = EINA_TRUE;
4560         return;
4561      }
4562    if (_it->wd->show_item)
4563      {
4564         _it->wd->show_item->item->showme = EINA_FALSE;
4565         _it->wd->show_item = NULL;
4566      }
4567    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4568    if (_it->item->group_item) gith = _it->item->group_item->item->h;
4569    elm_smart_scroller_child_region_show(_it->wd->scr,
4570                                         _it->x + _it->item->block->x,
4571                                         _it->y + _it->item->block->y - gith,
4572                                         _it->item->block->w, oh);
4573 }
4574
4575 EAPI void
4576 elm_genlist_item_top_bring_in(Elm_Object_Item *it)
4577 {
4578    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4579    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4580    Evas_Coord ow, oh;
4581    Evas_Coord gith = 0;
4582
4583    if (_it->generation < _it->wd->generation) return;
4584    if ((_it->item->queued) || (!_it->item->mincalcd))
4585      {
4586         _it->wd->show_item = _it;
4587         _it->wd->bring_in = EINA_TRUE;
4588         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
4589         _it->item->showme = EINA_TRUE;
4590         return;
4591      }
4592    if (_it->wd->show_item)
4593      {
4594         _it->wd->show_item->item->showme = EINA_FALSE;
4595         _it->wd->show_item = NULL;
4596      }
4597    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4598    if (_it->item->group_item) gith = _it->item->group_item->item->h;
4599    elm_smart_scroller_region_bring_in(_it->wd->scr,
4600                                       _it->x + _it->item->block->x,
4601                                       _it->y + _it->item->block->y - gith,
4602                                       _it->item->block->w, oh);
4603 }
4604
4605 EAPI void
4606 elm_genlist_item_middle_show(Elm_Object_Item *it)
4607 {
4608    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4609    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4610    Evas_Coord ow, oh;
4611
4612    if (_it->generation < _it->wd->generation) return;
4613    if ((_it->item->queued) || (!_it->item->mincalcd))
4614      {
4615         _it->wd->show_item = _it;
4616         _it->wd->bring_in = EINA_FALSE;
4617         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
4618         _it->item->showme = EINA_TRUE;
4619         return;
4620      }
4621    if (_it->wd->show_item)
4622      {
4623         _it->wd->show_item->item->showme = EINA_FALSE;
4624         _it->wd->show_item = NULL;
4625      }
4626    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4627    elm_smart_scroller_child_region_show(_it->wd->scr,
4628                                         _it->x + _it->item->block->x,
4629                                         _it->y + _it->item->block->y - oh / 2 +
4630                                         _it->item->h / 2, _it->item->block->w,
4631                                         oh);
4632 }
4633
4634 EAPI void
4635 elm_genlist_item_middle_bring_in(Elm_Object_Item *it)
4636 {
4637    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4638    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4639    Evas_Coord ow, oh;
4640
4641    if (_it->generation < _it->wd->generation) return;
4642    if ((_it->item->queued) || (!_it->item->mincalcd))
4643      {
4644         _it->wd->show_item = _it;
4645         _it->wd->bring_in = EINA_TRUE;
4646         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
4647         _it->item->showme = EINA_TRUE;
4648         return;
4649      }
4650    if (_it->wd->show_item)
4651      {
4652         _it->wd->show_item->item->showme = EINA_FALSE;
4653         _it->wd->show_item = NULL;
4654      }
4655    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4656    elm_smart_scroller_region_bring_in(_it->wd->scr,
4657                                       _it->x + _it->item->block->x,
4658                                       _it->y + _it->item->block->y - oh / 2 +
4659                                       _it->item->h / 2, _it->item->block->w,
4660                                       oh);
4661 }
4662
4663 EAPI void
4664 elm_genlist_item_del(Elm_Object_Item *it)
4665 {
4666    elm_object_item_del(it);
4667 }
4668
4669 EAPI void
4670 elm_genlist_item_data_set(Elm_Object_Item  *it,
4671                           const void       *data)
4672 {
4673    elm_object_item_data_set(it, (void *) data);
4674 }
4675
4676 EAPI void *
4677 elm_genlist_item_data_get(const Elm_Object_Item *it)
4678 {
4679    return elm_object_item_data_get(it);
4680 }
4681
4682 EAPI void
4683 elm_genlist_item_icons_orphan(Elm_Object_Item *it)
4684 {
4685    elm_genlist_item_contents_orphan(it);
4686 }
4687
4688 EAPI void
4689 elm_genlist_item_contents_orphan(Elm_Object_Item *it)
4690 {
4691    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4692
4693    Evas_Object *content;
4694    EINA_LIST_FREE(((Elm_Gen_Item *) it)->content_objs, content)
4695      {
4696         elm_widget_sub_object_del(WIDGET(it), content);
4697         evas_object_smart_member_del(content);
4698         evas_object_hide(content);
4699      }
4700 }
4701
4702 EAPI const Evas_Object *
4703 elm_genlist_item_object_get(const Elm_Object_Item *it)
4704 {
4705    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4706    return VIEW(it);
4707 }
4708
4709 EAPI void
4710 elm_genlist_item_update(Elm_Object_Item *it)
4711 {
4712    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4713    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4714
4715    if (!_it->item->block) return;
4716    if (_it->generation < _it->wd->generation) return;
4717    _it->item->mincalcd = EINA_FALSE;
4718    _it->item->updateme = EINA_TRUE;
4719    _it->item->block->updateme = EINA_TRUE;
4720    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4721    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4722 }
4723
4724 EAPI void
4725 elm_genlist_item_fields_update(Elm_Object_Item *it,
4726                                const char *parts,
4727                                Elm_Genlist_Item_Field_Flags itf)
4728 {
4729    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4730    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4731
4732    if (!_it->item->block) return;
4733    if (_it->generation < _it->wd->generation) return;
4734
4735    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4736      _item_text_realize(_it, _it->base.view, &_it->texts, parts);
4737    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4738      {
4739         _it->content_objs = _item_content_unrealize(_it, _it->base.view,
4740                                                    &_it->contents, parts);
4741         _it->content_objs = _item_content_realize(_it, _it->base.view,
4742                                                  &_it->contents, parts);
4743      }
4744    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4745      _item_state_realize(_it, _it->base.view, &_it->states, parts);
4746 }
4747
4748 EAPI void
4749 elm_genlist_item_item_class_update(Elm_Object_Item *it,
4750                                    const Elm_Genlist_Item_Class *itc)
4751 {
4752    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4753    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4754
4755    if (!_it->item->block) return;
4756    EINA_SAFETY_ON_NULL_RETURN(itc);
4757    if (_it->generation < _it->wd->generation) return;
4758    _it->itc = itc;
4759    _it->item->nocache = EINA_TRUE;
4760    elm_genlist_item_update(it);
4761 }
4762
4763 EAPI const Elm_Genlist_Item_Class *
4764 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
4765 {
4766    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4767    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4768    if (_it->generation < _it->wd->generation) return NULL;
4769    return _it->itc;
4770 }
4771
4772 static Evas_Object *
4773 _elm_genlist_item_label_create(void        *data,
4774                                Evas_Object *obj __UNUSED__,
4775                                Evas_Object *tooltip,
4776                                void        *it __UNUSED__)
4777 {
4778    Evas_Object *label = elm_label_add(tooltip);
4779    if (!label)
4780      return NULL;
4781    elm_object_style_set(label, "tooltip");
4782    elm_object_text_set(label, data);
4783    return label;
4784 }
4785
4786 static void
4787 _elm_genlist_item_label_del_cb(void        *data,
4788                                Evas_Object *obj __UNUSED__,
4789                                void        *event_info __UNUSED__)
4790 {
4791    eina_stringshare_del(data);
4792 }
4793
4794 EAPI void
4795 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
4796                                   const char      *text)
4797 {
4798    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4799    text = eina_stringshare_add(text);
4800    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4801                                            text,
4802                                            _elm_genlist_item_label_del_cb);
4803 }
4804
4805 EAPI void
4806 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
4807                                         Elm_Tooltip_Item_Content_Cb func,
4808                                         const void                 *data,
4809                                         Evas_Smart_Cb               del_cb)
4810 {
4811    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
4812    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4813
4814    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
4815      return;
4816
4817    if (_it->tooltip.del_cb)
4818      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
4819
4820    _it->tooltip.content_cb = func;
4821    _it->tooltip.data = data;
4822    _it->tooltip.del_cb = del_cb;
4823
4824    if (VIEW(_it))
4825      {
4826         elm_widget_item_tooltip_content_cb_set(_it,
4827                                                _it->tooltip.content_cb,
4828                                                _it->tooltip.data, NULL);
4829         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
4830         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
4831      }
4832
4833    return;
4834
4835 error:
4836    if (del_cb) del_cb((void *)data, NULL, NULL);
4837 }
4838
4839 EAPI void
4840 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
4841 {
4842    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4843    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4844
4845    if ((VIEW(_it)) && (_it->tooltip.content_cb))
4846      elm_widget_item_tooltip_unset(_it);
4847
4848    if (_it->tooltip.del_cb)
4849      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
4850    _it->tooltip.del_cb = NULL;
4851    _it->tooltip.content_cb = NULL;
4852    _it->tooltip.data = NULL;
4853    _it->tooltip.free_size = EINA_FALSE;
4854    if (_it->tooltip.style)
4855      elm_genlist_item_tooltip_style_set(it, NULL);
4856 }
4857
4858 EAPI void
4859 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
4860                                    const char       *style)
4861 {
4862    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4863    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4864
4865    eina_stringshare_replace(&_it->tooltip.style, style);
4866    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
4867 }
4868
4869 EAPI const char *
4870 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
4871 {
4872    return elm_object_item_tooltip_style_get(it);
4873 }
4874
4875 EAPI Eina_Bool
4876 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
4877                                          Eina_Bool disable)
4878 {
4879    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4880    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4881
4882    _it->tooltip.free_size = disable;
4883    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
4884    return EINA_TRUE;
4885 }
4886
4887 EAPI Eina_Bool
4888 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
4889 {
4890    return elm_object_tooltip_window_mode_get(VIEW(it));
4891 }
4892
4893 EAPI void
4894 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
4895                             const char       *cursor)
4896 {
4897    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4898    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4899    eina_stringshare_replace(&_it->mouse_cursor, cursor);
4900    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
4901 }
4902
4903 EAPI const char *
4904 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
4905 {
4906    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4907    return elm_widget_item_cursor_get(it);
4908 }
4909
4910 EAPI void
4911 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
4912 {
4913    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4914    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4915
4916    if (!_it->mouse_cursor) return;
4917
4918    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
4919
4920    eina_stringshare_del(_it->mouse_cursor);
4921    _it->mouse_cursor = NULL;
4922 }
4923
4924 EAPI void
4925 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
4926                                   const char       *style)
4927 {
4928    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4929    elm_widget_item_cursor_style_set(it, style);
4930 }
4931
4932 EAPI const char *
4933 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
4934 {
4935    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4936    return elm_widget_item_cursor_style_get(it);
4937 }
4938
4939 EAPI void
4940 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
4941                                         Eina_Bool        engine_only)
4942 {
4943    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4944    elm_widget_item_cursor_engine_only_set(it, engine_only);
4945 }
4946
4947 EAPI Eina_Bool
4948 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
4949 {
4950    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4951    return elm_widget_item_cursor_engine_only_get(it);
4952 }
4953
4954 EAPI int
4955 elm_genlist_item_index_get(Elm_Object_Item *it)
4956 {
4957    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
4958    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4959
4960    if (_it->item->block)
4961      return _it->position + _it->item->block->position;
4962    return -1;
4963 }
4964
4965 EAPI void
4966 elm_genlist_mode_set(Evas_Object  *obj,
4967                      Elm_List_Mode mode)
4968 {
4969    ELM_CHECK_WIDTYPE(obj, widtype);
4970    Widget_Data *wd = elm_widget_data_get(obj);
4971    if (!wd) return;
4972    if (wd->mode == mode) return;
4973    wd->mode = mode;
4974    _sizing_eval(obj);
4975 }
4976
4977 EAPI void
4978 elm_genlist_horizontal_set(Evas_Object  *obj,
4979                            Elm_List_Mode mode)
4980 {
4981    elm_genlist_mode_set(obj, mode);
4982 }
4983
4984 EAPI void
4985 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4986                                 Elm_List_Mode mode)
4987 {
4988    elm_genlist_mode_set(obj, mode);
4989 }
4990
4991 EAPI Elm_List_Mode
4992 elm_genlist_mode_get(const Evas_Object *obj)
4993 {
4994    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4995    Widget_Data *wd = elm_widget_data_get(obj);
4996    if (!wd) return ELM_LIST_LAST;
4997    return wd->mode;
4998 }
4999
5000 EAPI Elm_List_Mode
5001 elm_genlist_horizontal_get(const Evas_Object *obj)
5002 {
5003    return elm_genlist_mode_get(obj);
5004 }
5005
5006 EAPI Elm_List_Mode
5007 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
5008 {
5009    return elm_genlist_mode_get(obj);
5010 }
5011
5012 EAPI void
5013 elm_genlist_always_select_mode_set(Evas_Object *obj,
5014                                    Eina_Bool    always_select)
5015 {
5016    ELM_CHECK_WIDTYPE(obj, widtype);
5017    Widget_Data *wd = elm_widget_data_get(obj);
5018    if (!wd) return;
5019    wd->always_select = always_select;
5020 }
5021
5022 EAPI Eina_Bool
5023 elm_genlist_always_select_mode_get(const Evas_Object *obj)
5024 {
5025    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5026    Widget_Data *wd = elm_widget_data_get(obj);
5027    if (!wd) return EINA_FALSE;
5028    return wd->always_select;
5029 }
5030
5031 EAPI void
5032 elm_genlist_no_select_mode_set(Evas_Object *obj,
5033                                Eina_Bool    no_select)
5034 {
5035    ELM_CHECK_WIDTYPE(obj, widtype);
5036    Widget_Data *wd = elm_widget_data_get(obj);
5037    if (!wd) return;
5038    wd->no_select = no_select;
5039 }
5040
5041 EAPI Eina_Bool
5042 elm_genlist_no_select_mode_get(const Evas_Object *obj)
5043 {
5044    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5045    Widget_Data *wd = elm_widget_data_get(obj);
5046    if (!wd) return EINA_FALSE;
5047    return wd->no_select;
5048 }
5049
5050 EAPI void
5051 elm_genlist_compress_mode_set(Evas_Object *obj,
5052                               Eina_Bool    compress)
5053 {
5054    ELM_CHECK_WIDTYPE(obj, widtype);
5055    Widget_Data *wd = elm_widget_data_get(obj);
5056    if (!wd) return;
5057    wd->compress = compress;
5058    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
5059 }
5060
5061 EAPI Eina_Bool
5062 elm_genlist_compress_mode_get(const Evas_Object *obj)
5063 {
5064    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5065    Widget_Data *wd = elm_widget_data_get(obj);
5066    if (!wd) return EINA_FALSE;
5067    return wd->compress;
5068 }
5069
5070 EAPI void
5071 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5072                                       Eina_Bool    height_for_width)
5073 {
5074    ELM_CHECK_WIDTYPE(obj, widtype);
5075    Widget_Data *wd = elm_widget_data_get(obj);
5076    if (!wd) return;
5077    wd->height_for_width = !!height_for_width;
5078    if (wd->height_for_width)
5079      {
5080         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5081         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5082      }
5083 }
5084
5085 EAPI Eina_Bool
5086 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5087 {
5088    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5089    Widget_Data *wd = elm_widget_data_get(obj);
5090    if (!wd) return EINA_FALSE;
5091    return wd->height_for_width;
5092 }
5093
5094 EAPI void
5095 elm_genlist_bounce_set(Evas_Object *obj,
5096                        Eina_Bool    h_bounce,
5097                        Eina_Bool    v_bounce)
5098 {
5099    ELM_CHECK_WIDTYPE(obj, widtype);
5100    Widget_Data *wd = elm_widget_data_get(obj);
5101    if (!wd) return;
5102    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
5103    wd->h_bounce = h_bounce;
5104    wd->v_bounce = v_bounce;
5105 }
5106
5107 EAPI void
5108 elm_genlist_bounce_get(const Evas_Object *obj,
5109                        Eina_Bool         *h_bounce,
5110                        Eina_Bool         *v_bounce)
5111 {
5112    ELM_CHECK_WIDTYPE(obj, widtype);
5113    Widget_Data *wd = elm_widget_data_get(obj);
5114    if (!wd) return;
5115    if (h_bounce) *h_bounce = wd->h_bounce;
5116    if (v_bounce) *v_bounce = wd->v_bounce;
5117 }
5118
5119 EAPI void
5120 elm_genlist_homogeneous_set(Evas_Object *obj,
5121                             Eina_Bool    homogeneous)
5122 {
5123    ELM_CHECK_WIDTYPE(obj, widtype);
5124    Widget_Data *wd = elm_widget_data_get(obj);
5125    if (!wd) return;
5126    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5127    wd->homogeneous = homogeneous;
5128 }
5129
5130 EAPI Eina_Bool
5131 elm_genlist_homogeneous_get(const Evas_Object *obj)
5132 {
5133    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5134    Widget_Data *wd = elm_widget_data_get(obj);
5135    if (!wd) return EINA_FALSE;
5136    return wd->homogeneous;
5137 }
5138
5139 EAPI void
5140 elm_genlist_block_count_set(Evas_Object *obj,
5141                             int          n)
5142 {
5143    ELM_CHECK_WIDTYPE(obj, widtype);
5144    Widget_Data *wd = elm_widget_data_get(obj);
5145    if (!wd) return;
5146    wd->max_items_per_block = n;
5147    wd->item_cache_max = wd->max_items_per_block * 2;
5148    _item_cache_clean(wd);
5149 }
5150
5151 EAPI int
5152 elm_genlist_block_count_get(const Evas_Object *obj)
5153 {
5154    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5155    Widget_Data *wd = elm_widget_data_get(obj);
5156    if (!wd) return 0;
5157    return wd->max_items_per_block;
5158 }
5159
5160 EAPI void
5161 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5162                                   double       timeout)
5163 {
5164    ELM_CHECK_WIDTYPE(obj, widtype);
5165    Widget_Data *wd = elm_widget_data_get(obj);
5166    if (!wd) return;
5167    wd->longpress_timeout = timeout;
5168 }
5169
5170 EAPI double
5171 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5172 {
5173    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5174    Widget_Data *wd = elm_widget_data_get(obj);
5175    if (!wd) return 0;
5176    return wd->longpress_timeout;
5177 }
5178
5179 EAPI void
5180 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5181                                 Elm_Scroller_Policy policy_h,
5182                                 Elm_Scroller_Policy policy_v)
5183 {
5184    ELM_CHECK_WIDTYPE(obj, widtype);
5185    Widget_Data *wd = elm_widget_data_get(obj);
5186    if ((!wd) || (!wd->scr)) return;
5187    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5188        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5189      return;
5190    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5191 }
5192
5193 EAPI void
5194 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5195                                 Elm_Scroller_Policy *policy_h,
5196                                 Elm_Scroller_Policy *policy_v)
5197 {
5198    ELM_CHECK_WIDTYPE(obj, widtype);
5199    Widget_Data *wd = elm_widget_data_get(obj);
5200    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5201    if ((!wd) || (!wd->scr)) return;
5202    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5203    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5204    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5205 }
5206
5207 EAPI void
5208 elm_genlist_realized_items_update(Evas_Object *obj)
5209 {
5210    ELM_CHECK_WIDTYPE(obj, widtype);
5211
5212    Eina_List *list, *l;
5213    Elm_Object_Item *it;
5214
5215    list = elm_genlist_realized_items_get(obj);
5216    EINA_LIST_FOREACH(list, l, it)
5217      elm_genlist_item_update(it);
5218 }
5219
5220 EAPI void
5221 elm_genlist_item_mode_set(Elm_Object_Item  *it,
5222                           const char       *mode_type,
5223                           Eina_Bool         mode_set)
5224 {
5225    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5226    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5227
5228    Widget_Data *wd = _it->wd;
5229    Eina_List *l;
5230    Elm_Object_Item *it2;
5231
5232    if (!wd) return;
5233    if (!mode_type) return;
5234    if ((_it->generation < _it->wd->generation) ||
5235        elm_widget_item_disabled_get(_it)) return;
5236
5237    if ((wd->mode_item == _it) &&
5238        (!strcmp(mode_type, wd->mode_type)) &&
5239        (mode_set))
5240       return;
5241    if (!wd->mode_item_style) return;
5242    _it->mode_set = mode_set;
5243
5244    if (wd->multi)
5245      {
5246         EINA_LIST_FOREACH(wd->selected, l, it2)
5247           if (((Elm_Gen_Item *) it2)->realized)
5248             elm_genlist_item_selected_set(it2, EINA_FALSE);
5249      }
5250    else
5251      {
5252         it2 = elm_genlist_selected_item_get(wd->obj);
5253         if ((it2) && (((Elm_Gen_Item *) it2)->realized))
5254           elm_genlist_item_selected_set(it2, EINA_FALSE);
5255      }
5256
5257    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5258        (mode_set) ||
5259        ((_it == wd->mode_item) && (!mode_set)))
5260      _item_mode_unset(wd);
5261
5262    eina_stringshare_replace(&wd->mode_type, mode_type);
5263    if (mode_set) _item_mode_set(_it);
5264 }
5265
5266
5267 EAPI const char *
5268 elm_genlist_mode_item_style_get(const Evas_Object *obj)
5269 {
5270    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5271    Widget_Data *wd = elm_widget_data_get(obj);
5272    if (!wd) return NULL;
5273    return wd->mode_item_style;
5274 }
5275
5276 EAPI void
5277 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
5278 {
5279    ELM_CHECK_WIDTYPE(obj, widtype);
5280    Widget_Data *wd = elm_widget_data_get(obj);
5281    if (!wd) return;
5282    if ((style == wd->mode_item_style) || (style && wd->mode_item_style &&
5283        (!strcmp(style, wd->mode_item_style))))
5284      return;
5285    eina_stringshare_replace(&wd->mode_item_style, style);
5286    elm_genlist_realized_items_update(obj);
5287 }
5288
5289 EAPI const char *
5290 elm_genlist_mode_type_get(const Evas_Object *obj)
5291 {
5292    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5293    Widget_Data *wd = elm_widget_data_get(obj);
5294    if (!wd) return NULL;
5295    return wd->mode_type;
5296 }
5297
5298 EAPI const Elm_Object_Item *
5299 elm_genlist_mode_item_get(const Evas_Object *obj)
5300 {
5301    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5302    Widget_Data *wd = elm_widget_data_get(obj);
5303    if (!wd) return NULL;
5304    return (Elm_Object_Item *) wd->mode_item;
5305 }
5306
5307 EAPI void
5308 elm_genlist_reorder_mode_set(Evas_Object *obj,
5309                              Eina_Bool    reorder_mode)
5310 {
5311    ELM_CHECK_WIDTYPE(obj, widtype);
5312    Widget_Data *wd = elm_widget_data_get(obj);
5313    if (!wd) return;
5314    wd->reorder_mode = reorder_mode;
5315 }
5316
5317 EAPI Eina_Bool
5318 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5319 {
5320    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5321    Widget_Data *wd = elm_widget_data_get(obj);
5322    if (!wd) return EINA_FALSE;
5323    return wd->reorder_mode;
5324 }
5325
5326 /* for gengrid as of now */
5327 void
5328 _elm_genlist_page_relative_set(Evas_Object *obj,
5329                                double       h_pagerel,
5330                                double       v_pagerel)
5331 {
5332    Evas_Coord pagesize_h;
5333    Evas_Coord pagesize_v;
5334
5335    ELM_CHECK_WIDTYPE(obj, widtype);
5336    Widget_Data *wd = elm_widget_data_get(obj);
5337    if (!wd) return;
5338
5339    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5340    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5341                                  pagesize_v);
5342 }
5343
5344 /* for gengrid as of now */
5345 void
5346 _elm_genlist_page_relative_get(const Evas_Object *obj,
5347                                double            *h_pagerel,
5348                                double            *v_pagerel)
5349 {
5350    ELM_CHECK_WIDTYPE(obj, widtype);
5351    Widget_Data *wd = elm_widget_data_get(obj);
5352    if (!wd) return;
5353
5354    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5355 }
5356
5357 /* for gengrid as of now */
5358 void
5359 _elm_genlist_page_size_set(Evas_Object *obj,
5360                            Evas_Coord   h_pagesize,
5361                            Evas_Coord   v_pagesize)
5362 {
5363    double pagerel_h;
5364    double pagerel_v;
5365
5366    ELM_CHECK_WIDTYPE(obj, widtype);
5367    Widget_Data *wd = elm_widget_data_get(obj);
5368    if (!wd) return;
5369    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5370    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5371                                  v_pagesize);
5372 }
5373
5374 /* for gengrid as of now */
5375 void
5376 _elm_genlist_current_page_get(const Evas_Object *obj,
5377                               int               *h_pagenumber,
5378                               int               *v_pagenumber)
5379 {
5380    ELM_CHECK_WIDTYPE(obj, widtype);
5381    Widget_Data *wd = elm_widget_data_get(obj);
5382    if (!wd) return;
5383    if (wd->scr)
5384      elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5385 }
5386
5387 /* for gengrid as of now */
5388 void
5389 _elm_genlist_last_page_get(const Evas_Object *obj,
5390                            int               *h_pagenumber,
5391                            int               *v_pagenumber)
5392 {
5393    ELM_CHECK_WIDTYPE(obj, widtype);
5394    Widget_Data *wd = elm_widget_data_get(obj);
5395    if (!wd) return;
5396    if (wd->scr)
5397      elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5398 }
5399
5400 /* for gengrid as of now */
5401 void
5402 _elm_genlist_page_show(const Evas_Object *obj,
5403                        int                h_pagenumber,
5404                        int                v_pagenumber)
5405 {
5406    ELM_CHECK_WIDTYPE(obj, widtype);
5407    Widget_Data *wd = elm_widget_data_get(obj);
5408    if (!wd) return;
5409    if (wd->scr)
5410      elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5411 }
5412
5413 /* for gengrid as of now */
5414 void
5415 _elm_genlist_page_bring_in(const Evas_Object *obj,
5416                            int                h_pagenumber,
5417                            int                v_pagenumber)
5418 {
5419    ELM_CHECK_WIDTYPE(obj, widtype);
5420    Widget_Data *wd = elm_widget_data_get(obj);
5421    if (!wd) return;
5422    if (wd->scr)
5423      elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5424 }
5425
5426 void
5427 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5428                             Eina_Bool     calc)
5429 {
5430    Evas_Object *content;
5431
5432    if (!it->realized) return;
5433    if (it->wd->reorder_it == it) return;
5434    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5435    if (!calc)
5436      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5437    if (it->long_timer)
5438      {
5439         ecore_timer_del(it->long_timer);
5440         it->long_timer = NULL;
5441      }
5442
5443    elm_widget_stringlist_free(it->texts);
5444    it->texts = NULL;
5445    elm_widget_stringlist_free(it->contents);
5446    it->contents = NULL;
5447    elm_widget_stringlist_free(it->states);
5448    it->states = NULL;
5449
5450    EINA_LIST_FREE(it->content_objs, content)
5451      evas_object_del(content);
5452
5453    it->unrealize_cb(it);
5454
5455    it->realized = EINA_FALSE;
5456    it->want_unrealize = EINA_FALSE;
5457    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5458    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5459 }
5460
5461 void
5462 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5463 {
5464    elm_widget_item_pre_notify_del(it);
5465    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5466    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5467
5468    if (it->itc->func.del)
5469      it->itc->func.del((void *)it->base.data, WIDGET(it));
5470 }
5471
5472 void
5473 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5474 {
5475    _elm_genlist_item_del_notserious(it);
5476    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5477    if (it->tooltip.del_cb)
5478      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5479    it->wd->walking -= it->walking;
5480    if (it->long_timer) ecore_timer_del(it->long_timer);
5481    if (it->group)
5482      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5483
5484    if (it->wd->state)
5485      {
5486         eina_inlist_sorted_state_free(it->wd->state);
5487         it->wd->state = NULL;
5488      }
5489    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5490    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5491    free(it->item);
5492
5493    it->item = NULL;
5494    if (it->wd->last_selected_item == (Elm_Object_Item *) it)
5495      it->wd->last_selected_item = NULL;
5496 }