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