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