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