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