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