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