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