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