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