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