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