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