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