Refactor genlist and deprecate top/middle item_show() API.
[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, ELM_GENLIST_ITEM_SCROLLTO_IN);
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, ELM_GENLIST_ITEM_SCROLLTO_IN);
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, ELM_GENLIST_ITEM_SCROLLTO_IN);
431      }
432    else
433      {
434         elm_genlist_item_selected_set(prev, EINA_TRUE);
435         elm_genlist_item_show(prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
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, ELM_GENLIST_ITEM_SCROLLTO_IN);
455      }
456    else
457      {
458         elm_genlist_item_selected_set(next, EINA_TRUE);
459         elm_genlist_item_show(next, ELM_GENLIST_ITEM_SCROLLTO_IN);
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, ELM_GENLIST_ITEM_SCROLLTO_IN);
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, ELM_GENLIST_ITEM_SCROLLTO_IN);
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 EAPI Elm_Object_Item *
4594 elm_genlist_item_parent_get(const Elm_Object_Item *it)
4595 {
4596    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4597    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
4598 }
4599
4600 EAPI void
4601 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4602 {
4603    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4604    Eina_List *tl = NULL, *l;
4605    Elm_Gen_Item *_it;
4606    Elm_Object_Item *it2;
4607    _it = (Elm_Gen_Item *)it;
4608
4609    EINA_LIST_FOREACH(_it->item->items, l, it2)
4610      tl = eina_list_append(tl, it2);
4611    EINA_LIST_FREE(tl, it2)
4612      elm_object_item_del(it2);
4613 }
4614
4615 EAPI void
4616 elm_genlist_item_selected_set(Elm_Object_Item *it,
4617                               Eina_Bool selected)
4618 {
4619    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4620    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4621    Widget_Data *wd = _it->wd;
4622    if (!wd) return;
4623    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4624      return;
4625    selected = !!selected;
4626    if (_it->selected == selected) return;
4627
4628    if (selected)
4629      {
4630         if (!wd->multi)
4631           {
4632              while (wd->selected)
4633                {
4634                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4635                   _it->unsel_cb(wd->selected->data);
4636                }
4637           }
4638         _it->highlight_cb(_it);
4639         _item_select(_it);
4640         return;
4641      }
4642    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4643    _it->unsel_cb(_it);
4644 }
4645
4646 EAPI Eina_Bool
4647 elm_genlist_item_selected_get(const Elm_Object_Item *it)
4648 {
4649    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4650    return ((Elm_Gen_Item *)it)->selected;
4651 }
4652
4653 EAPI void
4654 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
4655                               Eina_Bool         expanded)
4656 {
4657    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4658    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4659    expanded = !!expanded;
4660    if (_it->item->expanded == expanded) return;
4661    _it->item->expanded = expanded;
4662    if (_it->item->expanded)
4663      {
4664         if (_it->realized)
4665           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4666         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4667         _it->wd->auto_scroll_enabled = EINA_TRUE;
4668         _it->wd->expanded_item = _it;
4669      }
4670    else
4671      {
4672         if (_it->realized)
4673           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4674         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4675         _it->wd->auto_scroll_enabled = EINA_FALSE;
4676         _it->wd->expanded_item = NULL;
4677      }
4678 }
4679
4680 EAPI Eina_Bool
4681 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4682 {
4683    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4684    return ((Elm_Gen_Item *)it)->item->expanded;
4685 }
4686
4687 EAPI int
4688 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4689 {
4690    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4691    return ((Elm_Gen_Item *)it)->item->expanded_depth;
4692 }
4693
4694 EAPI void
4695 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
4696                                   Eina_Bool         display_only)
4697 {
4698    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4699    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4700    display_only = !!display_only;
4701    if (_it->display_only == display_only) return;
4702    if (_it->generation < _it->wd->generation) return;
4703    _it->display_only = display_only;
4704    _it->item->mincalcd = EINA_FALSE;
4705    _it->item->updateme = EINA_TRUE;
4706    if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
4707    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4708    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4709 }
4710
4711 EAPI Eina_Bool
4712 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
4713 {
4714    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4715    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4716    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4717    return _it->display_only;
4718 }
4719
4720 static Eina_Bool _elm_genlist_item_compute_coordinates(
4721                   Elm_Object_Item *it,
4722                   Elm_Genlist_Item_Scrollto_Type type,
4723                   Evas_Coord *x,
4724                   Evas_Coord *y,
4725                   Evas_Coord *w,
4726                   Evas_Coord *h)
4727 {
4728    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4729    Evas_Coord gith = 0;
4730    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4731    if ((_it->item->queued) || (!_it->item->mincalcd))
4732      {
4733         _it->wd->show_item = _it;
4734         _it->wd->bring_in = EINA_FALSE;
4735         _it->wd->scrollto_type = type;
4736         _it->item->showme = EINA_TRUE;
4737         return EINA_FALSE;
4738      }
4739    if (_it->wd->show_item)
4740      {
4741         _it->wd->show_item->item->showme = EINA_FALSE;
4742         _it->wd->show_item = NULL;
4743      }
4744
4745    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
4746    if (type==ELM_GENLIST_ITEM_SCROLLTO_IN)
4747      {
4748         if ((_it->item->group_item) &&
4749            (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4750             gith = _it->item->group_item->item->h;
4751
4752         *h = _it->item->h;
4753         *y = _it->y + _it->item->block->y - gith;
4754      }
4755    else if (type==ELM_GENLIST_ITEM_SCROLLTO_TOP)
4756      {
4757         if (_it->item->group_item) gith = _it->item->group_item->item->h;
4758         *y = _it->y + _it->item->block->y - gith;
4759      }
4760    else if (type==ELM_GENLIST_ITEM_SCROLLTO_MIDDLE)
4761      {
4762         *y = _it->y + _it->item->block->y - *h / 2 + _it->item->h / 2;
4763      }
4764    else
4765      return EINA_FALSE;
4766
4767    *x = _it->x + _it->item->block->x;
4768    *w = _it->item->block->w;
4769    return EINA_TRUE;
4770 }
4771
4772 EAPI void
4773 elm_genlist_item_promote(Elm_Object_Item *it)
4774 {
4775    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4776    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4777    if (_it->generation < _it->wd->generation) return;
4778    _item_move_before(_it,
4779                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4780 }
4781
4782 EAPI void
4783 elm_genlist_item_demote(Elm_Object_Item *it)
4784 {
4785    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4786    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4787    if (_it->generation < _it->wd->generation) return;
4788    _item_move_after(_it,
4789                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4790 }
4791
4792 EAPI void
4793 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4794 {
4795    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4796    Evas_Coord x, y, w, h;
4797    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4798
4799    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
4800      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
4801 }
4802
4803 EAPI void
4804 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4805 {
4806
4807    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4808    Evas_Coord x, y, w, h;
4809    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4810
4811    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
4812      elm_smart_scroller_region_bring_in(_it->wd->scr,x, y, w, h);
4813 }
4814
4815 EINA_DEPRECATED EAPI void
4816 elm_genlist_item_top_show(Elm_Object_Item *it)
4817 {
4818    elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
4819 }
4820
4821 EINA_DEPRECATED EAPI void
4822 elm_genlist_item_top_bring_in(Elm_Object_Item *it)
4823 {
4824    elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
4825 }
4826
4827 EINA_DEPRECATED EAPI void
4828 elm_genlist_item_middle_show(Elm_Object_Item *it)
4829 {
4830    elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
4831 }
4832
4833 EINA_DEPRECATED EAPI void
4834 elm_genlist_item_middle_bring_in(Elm_Object_Item *it)
4835 {
4836    elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
4837 }
4838
4839 EINA_DEPRECATED EAPI void
4840 elm_genlist_item_contents_orphan(Elm_Object_Item *it)
4841 {
4842    elm_genlist_item_all_contents_unset(it, NULL);
4843 }
4844
4845 EAPI void
4846 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
4847 {
4848    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4849
4850    Evas_Object *content;
4851    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
4852      {
4853         elm_widget_sub_object_del(WIDGET(it), content);
4854         evas_object_smart_member_del(content);
4855         evas_object_hide(content);
4856         if (l)
4857           *l = eina_list_append(*l, content);
4858      }
4859 }
4860
4861 EINA_DEPRECATED EAPI const Evas_Object *
4862 elm_genlist_item_object_get(const Elm_Object_Item *it)
4863 {
4864    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4865    return VIEW(it);
4866 }
4867
4868 EAPI void
4869 elm_genlist_item_update(Elm_Object_Item *it)
4870 {
4871    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4872    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4873
4874    if (!_it->item->block) return;
4875    if (_it->generation < _it->wd->generation) return;
4876    _it->item->mincalcd = EINA_FALSE;
4877    _it->item->updateme = EINA_TRUE;
4878    _it->item->block->updateme = EINA_TRUE;
4879    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4880    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4881 }
4882
4883 EAPI void
4884 elm_genlist_item_fields_update(Elm_Object_Item *it,
4885                                const char *parts,
4886                                Elm_Genlist_Item_Field_Type itf)
4887 {
4888    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4889    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4890
4891    if (!_it->item->block) return;
4892    if (_it->generation < _it->wd->generation) return;
4893
4894    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
4895      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
4896    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4897      {
4898         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
4899                                                    &_it->contents, parts);
4900         _it->content_objs = _item_content_realize(_it, VIEW(_it),
4901                                                  &_it->contents, parts);
4902      }
4903    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4904      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
4905 }
4906
4907 EAPI void
4908 elm_genlist_item_item_class_update(Elm_Object_Item *it,
4909                                    const Elm_Genlist_Item_Class *itc)
4910 {
4911    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4912    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4913
4914    if (!_it->item->block) return;
4915    EINA_SAFETY_ON_NULL_RETURN(itc);
4916    if (_it->generation < _it->wd->generation) return;
4917    _it->itc = itc;
4918    _it->item->nocache_once = EINA_TRUE;
4919    elm_genlist_item_update(it);
4920 }
4921
4922 EAPI const Elm_Genlist_Item_Class *
4923 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
4924 {
4925    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4926    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4927    if (_it->generation < _it->wd->generation) return NULL;
4928    return _it->itc;
4929 }
4930
4931 static Evas_Object *
4932 _elm_genlist_item_label_create(void        *data,
4933                                Evas_Object *obj __UNUSED__,
4934                                Evas_Object *tooltip,
4935                                void        *it __UNUSED__)
4936 {
4937    Evas_Object *label = elm_label_add(tooltip);
4938    if (!label)
4939      return NULL;
4940    elm_object_style_set(label, "tooltip");
4941    elm_object_text_set(label, data);
4942    return label;
4943 }
4944
4945 static void
4946 _elm_genlist_item_label_del_cb(void        *data,
4947                                Evas_Object *obj __UNUSED__,
4948                                void        *event_info __UNUSED__)
4949 {
4950    eina_stringshare_del(data);
4951 }
4952
4953 EAPI void
4954 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
4955                                   const char      *text)
4956 {
4957    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4958    text = eina_stringshare_add(text);
4959    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4960                                            text,
4961                                            _elm_genlist_item_label_del_cb);
4962 }
4963
4964 EAPI void
4965 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
4966                                         Elm_Tooltip_Item_Content_Cb func,
4967                                         const void                 *data,
4968                                         Evas_Smart_Cb               del_cb)
4969 {
4970    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
4971    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4972
4973    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
4974      return;
4975
4976    if (_it->tooltip.del_cb)
4977      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
4978
4979    _it->tooltip.content_cb = func;
4980    _it->tooltip.data = data;
4981    _it->tooltip.del_cb = del_cb;
4982
4983    if (VIEW(_it))
4984      {
4985         elm_widget_item_tooltip_content_cb_set(_it,
4986                                                _it->tooltip.content_cb,
4987                                                _it->tooltip.data, NULL);
4988         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
4989         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
4990      }
4991
4992    return;
4993
4994 error:
4995    if (del_cb) del_cb((void *)data, NULL, NULL);
4996 }
4997
4998 EAPI void
4999 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5000 {
5001    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5002    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5003
5004    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5005      elm_widget_item_tooltip_unset(_it);
5006
5007    if (_it->tooltip.del_cb)
5008      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5009    _it->tooltip.del_cb = NULL;
5010    _it->tooltip.content_cb = NULL;
5011    _it->tooltip.data = NULL;
5012    _it->tooltip.free_size = EINA_FALSE;
5013    if (_it->tooltip.style)
5014      elm_genlist_item_tooltip_style_set(it, NULL);
5015 }
5016
5017 EAPI void
5018 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5019                                    const char       *style)
5020 {
5021    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5022    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5023
5024    eina_stringshare_replace(&_it->tooltip.style, style);
5025    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5026 }
5027
5028 EAPI const char *
5029 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5030 {
5031    return elm_object_item_tooltip_style_get(it);
5032 }
5033
5034 EAPI Eina_Bool
5035 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5036                                          Eina_Bool disable)
5037 {
5038    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5039    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5040
5041    _it->tooltip.free_size = disable;
5042    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5043    return EINA_TRUE;
5044 }
5045
5046 EAPI Eina_Bool
5047 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5048 {
5049    return elm_object_tooltip_window_mode_get(VIEW(it));
5050 }
5051
5052 EAPI void
5053 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5054                             const char       *cursor)
5055 {
5056    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5057    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5058    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5059    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5060 }
5061
5062 EAPI const char *
5063 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5064 {
5065    return elm_widget_item_cursor_get(it);
5066 }
5067
5068 EAPI void
5069 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5070 {
5071    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5072    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5073
5074    if (!_it->mouse_cursor) return;
5075
5076    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5077
5078    eina_stringshare_del(_it->mouse_cursor);
5079    _it->mouse_cursor = NULL;
5080 }
5081
5082 EAPI void
5083 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
5084                                   const char       *style)
5085 {
5086    elm_widget_item_cursor_style_set(it, style);
5087 }
5088
5089 EAPI const char *
5090 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5091 {
5092    return elm_widget_item_cursor_style_get(it);
5093 }
5094
5095 EAPI void
5096 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5097                                         Eina_Bool        engine_only)
5098 {
5099    elm_widget_item_cursor_engine_only_set(it, engine_only);
5100 }
5101
5102 EAPI Eina_Bool
5103 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5104 {
5105    return elm_widget_item_cursor_engine_only_get(it);
5106 }
5107
5108 EAPI int
5109 elm_genlist_item_index_get(const Elm_Object_Item *it)
5110 {
5111    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5112    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5113
5114    if (_it->item->block)
5115      return _it->position + _it->item->block->position;
5116    return -1;
5117 }
5118
5119 EAPI void
5120 elm_genlist_mode_set(Evas_Object  *obj,
5121                      Elm_List_Mode mode)
5122 {
5123    ELM_CHECK_WIDTYPE(obj, widtype);
5124    Widget_Data *wd = elm_widget_data_get(obj);
5125    if (!wd) return;
5126    if (wd->mode == mode) return;
5127    wd->mode = mode;
5128    _sizing_eval(obj);
5129 }
5130
5131
5132 EAPI Elm_List_Mode
5133 elm_genlist_mode_get(const Evas_Object *obj)
5134 {
5135    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5136    Widget_Data *wd = elm_widget_data_get(obj);
5137    if (!wd) return ELM_LIST_LAST;
5138    return wd->mode;
5139 }
5140
5141 EAPI void
5142 elm_genlist_always_select_mode_set(Evas_Object *obj,
5143                                    Eina_Bool    always_select)
5144 {
5145    ELM_CHECK_WIDTYPE(obj, widtype);
5146    Widget_Data *wd = elm_widget_data_get(obj);
5147    if (!wd) return;
5148    wd->always_select = !!always_select;
5149 }
5150
5151 EAPI Eina_Bool
5152 elm_genlist_always_select_mode_get(const Evas_Object *obj)
5153 {
5154    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5155    Widget_Data *wd = elm_widget_data_get(obj);
5156    if (!wd) return EINA_FALSE;
5157    return wd->always_select;
5158 }
5159
5160 EAPI void
5161 elm_genlist_no_select_mode_set(Evas_Object *obj,
5162                                Eina_Bool    no_select)
5163 {
5164    ELM_CHECK_WIDTYPE(obj, widtype);
5165    Widget_Data *wd = elm_widget_data_get(obj);
5166    if (!wd) return;
5167    wd->no_select = !!no_select;
5168 }
5169
5170 EAPI Eina_Bool
5171 elm_genlist_no_select_mode_get(const Evas_Object *obj)
5172 {
5173    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5174    Widget_Data *wd = elm_widget_data_get(obj);
5175    if (!wd) return EINA_FALSE;
5176    return wd->no_select;
5177 }
5178
5179 EAPI void
5180 elm_genlist_compress_mode_set(Evas_Object *obj,
5181                               Eina_Bool    compress)
5182 {
5183    ELM_CHECK_WIDTYPE(obj, widtype);
5184    Widget_Data *wd = elm_widget_data_get(obj);
5185    if (!wd) return;
5186    wd->compress = !!compress;
5187    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
5188 }
5189
5190 EAPI Eina_Bool
5191 elm_genlist_compress_mode_get(const Evas_Object *obj)
5192 {
5193    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5194    Widget_Data *wd = elm_widget_data_get(obj);
5195    if (!wd) return EINA_FALSE;
5196    return wd->compress;
5197 }
5198
5199 EAPI void
5200 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5201                                       Eina_Bool    height_for_width)
5202 {
5203    ELM_CHECK_WIDTYPE(obj, widtype);
5204    Widget_Data *wd = elm_widget_data_get(obj);
5205    if (!wd) return;
5206    wd->height_for_width = !!height_for_width;
5207    if (wd->height_for_width)
5208      {
5209         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5210         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5211      }
5212 }
5213
5214 EAPI Eina_Bool
5215 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5216 {
5217    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5218    Widget_Data *wd = elm_widget_data_get(obj);
5219    if (!wd) return EINA_FALSE;
5220    return wd->height_for_width;
5221 }
5222
5223 EAPI void
5224 elm_genlist_bounce_set(Evas_Object *obj,
5225                        Eina_Bool    h_bounce,
5226                        Eina_Bool    v_bounce)
5227 {
5228    ELM_CHECK_WIDTYPE(obj, widtype);
5229    Widget_Data *wd = elm_widget_data_get(obj);
5230    if (!wd) return;
5231    wd->h_bounce = !!h_bounce;
5232    wd->v_bounce = !!v_bounce;
5233    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5234 }
5235
5236 EAPI void
5237 elm_genlist_bounce_get(const Evas_Object *obj,
5238                        Eina_Bool         *h_bounce,
5239                        Eina_Bool         *v_bounce)
5240 {
5241    ELM_CHECK_WIDTYPE(obj, widtype);
5242    Widget_Data *wd = elm_widget_data_get(obj);
5243    if (!wd) return;
5244    if (h_bounce) *h_bounce = wd->h_bounce;
5245    if (v_bounce) *v_bounce = wd->v_bounce;
5246 }
5247
5248 EAPI void
5249 elm_genlist_homogeneous_set(Evas_Object *obj,
5250                             Eina_Bool    homogeneous)
5251 {
5252    ELM_CHECK_WIDTYPE(obj, widtype);
5253    Widget_Data *wd = elm_widget_data_get(obj);
5254    if (!wd) return;
5255    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5256    wd->homogeneous = !!homogeneous;
5257 }
5258
5259 EAPI Eina_Bool
5260 elm_genlist_homogeneous_get(const Evas_Object *obj)
5261 {
5262    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5263    Widget_Data *wd = elm_widget_data_get(obj);
5264    if (!wd) return EINA_FALSE;
5265    return wd->homogeneous;
5266 }
5267
5268 EAPI void
5269 elm_genlist_block_count_set(Evas_Object *obj,
5270                             int          count)
5271 {
5272    ELM_CHECK_WIDTYPE(obj, widtype);
5273    Widget_Data *wd = elm_widget_data_get(obj);
5274    if (!wd) return;
5275    wd->max_items_per_block = count;
5276    wd->item_cache_max = wd->max_items_per_block * 2;
5277    _item_cache_clean(wd);
5278 }
5279
5280 EAPI int
5281 elm_genlist_block_count_get(const Evas_Object *obj)
5282 {
5283    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5284    Widget_Data *wd = elm_widget_data_get(obj);
5285    if (!wd) return 0;
5286    return wd->max_items_per_block;
5287 }
5288
5289 EAPI void
5290 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5291                                   double       timeout)
5292 {
5293    ELM_CHECK_WIDTYPE(obj, widtype);
5294    Widget_Data *wd = elm_widget_data_get(obj);
5295    if (!wd) return;
5296    wd->longpress_timeout = timeout;
5297 }
5298
5299 EAPI double
5300 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5301 {
5302    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5303    Widget_Data *wd = elm_widget_data_get(obj);
5304    if (!wd) return 0;
5305    return wd->longpress_timeout;
5306 }
5307
5308 EAPI void
5309 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5310                                 Elm_Scroller_Policy policy_h,
5311                                 Elm_Scroller_Policy policy_v)
5312 {
5313    ELM_CHECK_WIDTYPE(obj, widtype);
5314    Widget_Data *wd = elm_widget_data_get(obj);
5315    if ((!wd) || (!wd->scr)) return;
5316    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5317        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5318      return;
5319    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5320 }
5321
5322 EAPI void
5323 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5324                                 Elm_Scroller_Policy *policy_h,
5325                                 Elm_Scroller_Policy *policy_v)
5326 {
5327    ELM_CHECK_WIDTYPE(obj, widtype);
5328    Widget_Data *wd = elm_widget_data_get(obj);
5329    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5330    if ((!wd) || (!wd->scr)) return;
5331    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5332    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5333    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5334 }
5335
5336 EAPI void
5337 elm_genlist_realized_items_update(Evas_Object *obj)
5338 {
5339    ELM_CHECK_WIDTYPE(obj, widtype);
5340
5341    Eina_List *list, *l;
5342    Elm_Object_Item *it;
5343
5344    list = elm_genlist_realized_items_get(obj);
5345    EINA_LIST_FOREACH(list, l, it)
5346      elm_genlist_item_update(it);
5347 }
5348
5349 EAPI void
5350 elm_genlist_item_mode_set(Elm_Object_Item  *it,
5351                           const char       *mode_type,
5352                           Eina_Bool         mode_set)
5353 {
5354    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5355    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5356
5357    Widget_Data *wd = _it->wd;
5358    Eina_List *l;
5359    Elm_Object_Item *it2;
5360
5361    if (!wd) return;
5362    if (!mode_type) return;
5363    if ((_it->generation < _it->wd->generation) ||
5364        elm_widget_item_disabled_get(_it)) return;
5365    if (wd->edit_mode) return;
5366
5367    if ((wd->mode_item == _it) &&
5368        (!strcmp(mode_type, wd->mode_type)) &&
5369        (mode_set))
5370       return;
5371    if (!_it->itc->mode_item_style) return;
5372    _it->mode_set = mode_set;
5373
5374    if (wd->multi)
5375      {
5376         EINA_LIST_FOREACH(wd->selected, l, it2)
5377           if (((Elm_Gen_Item *)it2)->realized)
5378             elm_genlist_item_selected_set(it2, EINA_FALSE);
5379      }
5380    else
5381      {
5382         it2 = elm_genlist_selected_item_get(wd->obj);
5383         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5384           elm_genlist_item_selected_set(it2, EINA_FALSE);
5385      }
5386
5387    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5388        (mode_set) ||
5389        ((_it == wd->mode_item) && (!mode_set)))
5390      _item_mode_unset(wd);
5391
5392    eina_stringshare_replace(&wd->mode_type, mode_type);
5393    if (mode_set) _item_mode_set(_it);
5394 }
5395
5396 EAPI const char *
5397 elm_genlist_mode_type_get(const Evas_Object *obj)
5398 {
5399    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5400    Widget_Data *wd = elm_widget_data_get(obj);
5401    if (!wd) return NULL;
5402    return wd->mode_type;
5403 }
5404
5405 EAPI const Elm_Object_Item *
5406 elm_genlist_mode_item_get(const Evas_Object *obj)
5407 {
5408    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5409    Widget_Data *wd = elm_widget_data_get(obj);
5410    if (!wd) return NULL;
5411    return (Elm_Object_Item *) wd->mode_item;
5412 }
5413
5414 EAPI Eina_Bool
5415 elm_genlist_edit_mode_get(const Evas_Object *obj)
5416 {
5417    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5418    Widget_Data *wd = elm_widget_data_get(obj);
5419    if (!wd) return EINA_FALSE;
5420
5421    return wd->edit_mode;
5422 }
5423
5424 EAPI void
5425 elm_genlist_edit_mode_set(Evas_Object *obj, Eina_Bool edit_mode)
5426 {
5427    ELM_CHECK_WIDTYPE(obj, widtype);
5428    Eina_List *list, *l;
5429    Elm_Gen_Item *it;
5430
5431    Widget_Data *wd = elm_widget_data_get(obj);
5432    if (!wd) return;
5433    edit_mode = !!edit_mode;
5434    if (wd->edit_mode == edit_mode) return;
5435    wd->edit_mode = edit_mode;
5436
5437    list = elm_genlist_realized_items_get(obj);
5438    if (!wd->edit_mode)
5439      {
5440         EINA_LIST_FOREACH(list, l, it)
5441           {
5442              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5443                _edit_mode_item_unrealize(it);
5444           }
5445         _item_cache_zero(wd);
5446      }
5447    else
5448      {
5449         EINA_LIST_FOREACH(list, l, it)
5450           {
5451              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5452                {
5453                   if (it->selected) _item_unselect(it);
5454                   if (it->itc->edit_item_style)
5455                      _edit_mode_item_realize(it, EINA_TRUE);
5456                }
5457           }
5458      }
5459    if (wd->calc_job) ecore_job_del(wd->calc_job);
5460    wd->calc_job = ecore_job_add(_calc_job, wd);
5461 }
5462
5463 EAPI void
5464 elm_genlist_reorder_mode_set(Evas_Object *obj,
5465                              Eina_Bool    reorder_mode)
5466 {
5467    ELM_CHECK_WIDTYPE(obj, widtype);
5468    Widget_Data *wd = elm_widget_data_get(obj);
5469    if (!wd) return;
5470    wd->reorder_mode = !!reorder_mode;
5471 }
5472
5473 EAPI Eina_Bool
5474 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5475 {
5476    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5477    Widget_Data *wd = elm_widget_data_get(obj);
5478    if (!wd) return EINA_FALSE;
5479    return wd->reorder_mode;
5480 }
5481
5482 EAPI Elm_Genlist_Item_Type
5483 elm_genlist_item_type_get(const Elm_Object_Item *it)
5484 {
5485    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5486    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5487    return _it->item->type;
5488 }
5489
5490 EINA_DEPRECATED EAPI Elm_Genlist_Item_Type
5491 elm_genlist_item_flags_get(const Elm_Object_Item *it)
5492 {
5493    return elm_genlist_item_type_get(it);
5494 }
5495
5496 EAPI Elm_Genlist_Item_Class *
5497 elm_genlist_item_class_new(void)
5498 {
5499    Elm_Genlist_Item_Class *itc;
5500
5501    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5502    if (!itc)
5503      return NULL;
5504    itc->version = CLASS_ALLOCATED;
5505    itc->refcount = 1;
5506    itc->delete_me = EINA_FALSE;
5507
5508    return itc;
5509 }
5510
5511 EAPI void
5512 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5513 {
5514    if (itc && (itc->version == CLASS_ALLOCATED))
5515      {
5516         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5517         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5518         else
5519           {
5520              itc->version = 0;
5521              free(itc);
5522           }
5523      }
5524 }
5525
5526 EAPI void
5527 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5528 {
5529    if (itc && (itc->version == CLASS_ALLOCATED))
5530      {
5531         itc->refcount++;
5532         if (itc->refcount == 0) itc->refcount--;
5533      }
5534 }
5535
5536 EAPI void
5537 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5538 {
5539    if (itc && (itc->version == CLASS_ALLOCATED))
5540      {
5541         if (itc->refcount > 0) itc->refcount--;
5542         if (itc->delete_me && (!itc->refcount))
5543           elm_genlist_item_class_free(itc);
5544      }
5545 }
5546
5547 void _flip_job(void *data)
5548 {
5549    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
5550    _elm_genlist_item_unrealize(it, EINA_FALSE);
5551    if (it->selected) _item_unselect(it);
5552    it->flipped = EINA_TRUE;
5553    it->item->nocache = EINA_TRUE;
5554 }
5555
5556 EAPI void
5557 elm_genlist_item_flip_set(Elm_Object_Item *it,
5558                           Eina_Bool flip)
5559 {
5560    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5561    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5562
5563    flip = !!flip;
5564    if (_it->flipped == flip) return;
5565
5566    if (flip)
5567      {
5568         ecore_job_add(_flip_job, _it);
5569         if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
5570         _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
5571      }
5572    else
5573      {
5574         _it->flipped = flip;
5575         _item_cache_zero(_it->wd);
5576         elm_genlist_item_update(it);
5577         _it->item->nocache = EINA_FALSE;
5578      }
5579 }
5580
5581 EAPI Eina_Bool
5582 elm_genlist_item_flip_get(const Elm_Object_Item *it)
5583 {
5584    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5585    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5586    return _it->flipped;
5587 }
5588
5589 /* for gengrid as of now */
5590 void
5591 _elm_genlist_page_relative_set(Evas_Object *obj,
5592                                double       h_pagerel,
5593                                double       v_pagerel)
5594 {
5595    Evas_Coord pagesize_h;
5596    Evas_Coord pagesize_v;
5597
5598    ELM_CHECK_WIDTYPE(obj, widtype);
5599    Widget_Data *wd = elm_widget_data_get(obj);
5600    if (!wd) return;
5601
5602    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5603    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5604                                  pagesize_v);
5605 }
5606
5607 /* for gengrid as of now */
5608 void
5609 _elm_genlist_page_relative_get(const Evas_Object *obj,
5610                                double            *h_pagerel,
5611                                double            *v_pagerel)
5612 {
5613    ELM_CHECK_WIDTYPE(obj, widtype);
5614    Widget_Data *wd = elm_widget_data_get(obj);
5615    if (!wd) return;
5616
5617    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5618 }
5619
5620 /* for gengrid as of now */
5621 void
5622 _elm_genlist_page_size_set(Evas_Object *obj,
5623                            Evas_Coord   h_pagesize,
5624                            Evas_Coord   v_pagesize)
5625 {
5626    double pagerel_h;
5627    double pagerel_v;
5628
5629    ELM_CHECK_WIDTYPE(obj, widtype);
5630    Widget_Data *wd = elm_widget_data_get(obj);
5631    if (!wd) return;
5632    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5633    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5634                                  v_pagesize);
5635 }
5636
5637 /* for gengrid as of now */
5638 void
5639 _elm_genlist_current_page_get(const Evas_Object *obj,
5640                               int               *h_pagenumber,
5641                               int               *v_pagenumber)
5642 {
5643    ELM_CHECK_WIDTYPE(obj, widtype);
5644    Widget_Data *wd = elm_widget_data_get(obj);
5645    if (!wd) return;
5646    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5647 }
5648
5649 /* for gengrid as of now */
5650 void
5651 _elm_genlist_last_page_get(const Evas_Object *obj,
5652                            int               *h_pagenumber,
5653                            int               *v_pagenumber)
5654 {
5655    ELM_CHECK_WIDTYPE(obj, widtype);
5656    Widget_Data *wd = elm_widget_data_get(obj);
5657    if (!wd) return;
5658    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5659 }
5660
5661 /* for gengrid as of now */
5662 void
5663 _elm_genlist_page_show(const Evas_Object *obj,
5664                        int                h_pagenumber,
5665                        int                v_pagenumber)
5666 {
5667    ELM_CHECK_WIDTYPE(obj, widtype);
5668    Widget_Data *wd = elm_widget_data_get(obj);
5669    if (!wd) return;
5670    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5671 }
5672
5673 /* for gengrid as of now */
5674 void
5675 _elm_genlist_page_bring_in(const Evas_Object *obj,
5676                            int                h_pagenumber,
5677                            int                v_pagenumber)
5678 {
5679    ELM_CHECK_WIDTYPE(obj, widtype);
5680    Widget_Data *wd = elm_widget_data_get(obj);
5681    if (!wd) return;
5682    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5683 }
5684
5685 void
5686 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5687                             Eina_Bool     calc)
5688 {
5689    Evas_Object *content;
5690
5691    if (!it->realized) return;
5692    if (it->wd->reorder_it == it) return;
5693
5694    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5695    if (!calc)
5696      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5697    if (it->long_timer)
5698      {
5699         ecore_timer_del(it->long_timer);
5700         it->long_timer = NULL;
5701      }
5702
5703    elm_widget_stringlist_free(it->texts);
5704    it->texts = NULL;
5705    elm_widget_stringlist_free(it->contents);
5706    it->contents = NULL;
5707    elm_widget_stringlist_free(it->states);
5708    it->states = NULL;
5709
5710    EINA_LIST_FREE(it->content_objs, content)
5711      evas_object_del(content);
5712
5713    it->unrealize_cb(it);
5714
5715    it->realized = EINA_FALSE;
5716    it->want_unrealize = EINA_FALSE;
5717    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5718    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5719 }
5720
5721 void
5722 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5723 {
5724    elm_widget_item_pre_notify_del(it);
5725    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5726    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5727
5728    if (it->itc->func.del)
5729      it->itc->func.del((void *)it->base.data, WIDGET(it));
5730 }
5731
5732 void
5733 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5734 {
5735    _elm_genlist_item_del_notserious(it);
5736    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5737    if (it->tooltip.del_cb)
5738      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5739    it->wd->walking -= it->walking;
5740    if (it->long_timer) ecore_timer_del(it->long_timer);
5741    if (it->group)
5742      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5743
5744    if (it->wd->state)
5745      {
5746         eina_inlist_sorted_state_free(it->wd->state);
5747         it->wd->state = NULL;
5748      }
5749    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5750    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5751    free(it->item);
5752
5753    it->item = NULL;
5754    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
5755      it->wd->last_selected_item = NULL;
5756    it->wd->item_count--;
5757 }