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