deprecate all genlist/gengrid functions related to 64281
[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_icons, *mode_states, *mode_icon_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    const char *stacking, *selectraise;
710    if ((it->delete_me) || (!it->highlighted)) return;
711    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
712    stacking = edje_object_data_get(VIEW(it), "stacking");
713    selectraise = edje_object_data_get(VIEW(it), "selectraise");
714    if (!it->item->nostacking)
715      {
716        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even) evas_object_lower(VIEW(it));
717        else evas_object_raise(VIEW(it));
718      }
719    it->highlighted = EINA_FALSE;
720 }
721
722 static void
723 _item_block_del(Elm_Gen_Item *it)
724 {
725    Eina_Inlist *il;
726    Item_Block *itb = it->item->block;
727
728    itb->items = eina_list_remove(itb->items, it);
729    itb->count--;
730    itb->changed = EINA_TRUE;
731    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
732    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
733    if (itb->count < 1)
734      {
735         il = EINA_INLIST_GET(itb);
736         Item_Block *itbn = (Item_Block *)(il->next);
737         if (it->parent)
738           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
739         else
740           it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
741         free(itb);
742         if (itbn) itbn->changed = EINA_TRUE;
743      }
744    else
745      {
746         if (itb->count < itb->wd->max_items_per_block/2)
747           {
748              il = EINA_INLIST_GET(itb);
749              Item_Block *itbp = (Item_Block *)(il->prev);
750              Item_Block *itbn = (Item_Block *)(il->next);
751              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
752                {
753                   Elm_Gen_Item *it2;
754
755                   EINA_LIST_FREE(itb->items, it2)
756                     {
757                        it2->item->block = itbp;
758                        itbp->items = eina_list_append(itbp->items, it2);
759                        itbp->count++;
760                        itbp->changed = EINA_TRUE;
761                     }
762                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
763                                                       EINA_INLIST_GET(itb));
764                   free(itb);
765                }
766              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
767                {
768                   while (itb->items)
769                     {
770                        Eina_List *last = eina_list_last(itb->items);
771                        Elm_Gen_Item *it2 = last->data;
772
773                        it2->item->block = itbn;
774                        itb->items = eina_list_remove_list(itb->items, last);
775                        itbn->items = eina_list_prepend(itbn->items, it2);
776                        itbn->count++;
777                        itbn->changed = EINA_TRUE;
778                     }
779                   it->wd->blocks =
780                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
781                   free(itb);
782                }
783           }
784      }
785 }
786
787 static void
788 _item_del(Elm_Gen_Item *it)
789 {
790    Evas_Object *obj = WIDGET(it);
791
792    evas_event_freeze(evas_object_evas_get(obj));
793    elm_genlist_item_subitems_clear(it);
794    if (it->wd->show_item == it) it->wd->show_item = NULL;
795    if (it->realized) elm_gen_item_unrealize(it, EINA_FALSE);
796    if (it->item->block) _item_block_del(it);
797    if (it->item->queued)
798      it->wd->queue = eina_list_remove(it->wd->queue, it);
799    if (it->wd->anchor_item == it)
800      {
801         it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
802         if (!it->wd->anchor_item)
803           it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
804      }
805    if (it->parent)
806      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
807    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
808    elm_gen_item_del_serious(it);
809    evas_event_thaw(evas_object_evas_get(obj));
810    evas_event_thaw_eval(evas_object_evas_get(obj));
811 }
812
813 static void
814 _clear_cb(Widget_Data *wd)
815 {
816    wd->anchor_item = NULL;
817    while (wd->blocks)
818      {
819         Item_Block *itb = (Item_Block *)(wd->blocks);
820
821         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
822         if (itb->items) eina_list_free(itb->items);
823         free(itb);
824      }
825    if (wd->queue_idle_enterer)
826      {
827         ecore_idle_enterer_del(wd->queue_idle_enterer);
828         wd->queue_idle_enterer = NULL;
829      }
830    if (wd->must_recalc_idler)
831      {
832         ecore_idler_del(wd->must_recalc_idler);
833         wd->must_recalc_idler = NULL;
834      }
835    if (wd->queue) wd->queue = eina_list_free(wd->queue);
836    if (wd->reorder_move_animator)
837      {
838         ecore_animator_del(wd->reorder_move_animator);
839         wd->reorder_move_animator = NULL;
840      }
841    wd->show_item = NULL;
842    wd->reorder_old_pan_y = 0;
843 }
844
845 static void
846 _item_unselect(Elm_Gen_Item *it)
847 {
848    if ((it->delete_me) || (!it->selected)) return;
849    it->selected = EINA_FALSE;
850    it->wd->selected = eina_list_remove(it->wd->selected, it);
851    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
852 }
853
854 static void
855 _mouse_move(void        *data,
856             Evas        *evas __UNUSED__,
857             Evas_Object *obj,
858             void        *event_info)
859 {
860    Elm_Gen_Item *it = data;
861    Evas_Event_Mouse_Move *ev = event_info;
862    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
863    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
864
865    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
866      {
867         if (!it->wd->on_hold)
868           {
869              it->wd->on_hold = EINA_TRUE;
870              if (!it->wd->wasselected)
871                {
872                   _item_unhighlight(it);
873                   _item_unselect(it);
874                }
875           }
876      }
877    if (it->wd->multitouched)
878      {
879         it->wd->cur_x = ev->cur.canvas.x;
880         it->wd->cur_y = ev->cur.canvas.y;
881         return;
882      }
883    if ((it->dragging) && (it->down))
884      {
885         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
886         else
887           {
888              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
889              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
890              if (abs((it->wd->history[it->wd->movements].x -
891                       it->wd->history[0].x)) > 40)
892                it->wd->swipe = EINA_TRUE;
893              else
894                it->wd->movements++;
895           }
896         if (it->long_timer)
897           {
898              ecore_timer_del(it->long_timer);
899              it->long_timer = NULL;
900           }
901         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
902         return;
903      }
904    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
905      {
906         if (it->long_timer)
907           {
908              ecore_timer_del(it->long_timer);
909              it->long_timer = NULL;
910           }
911         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
912           {
913              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
914              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
915
916              if (!it->wd->reorder_start_y)
917                it->wd->reorder_start_y = it->item->block->y + it->y;
918
919              if (it_scrl_y < oy)
920                y_pos = oy;
921              else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
922                y_pos = oy + oh - it->wd->reorder_it->item->h;
923              else
924                y_pos = it_scrl_y;
925
926              _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
927
928              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
929              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
930           }
931         return;
932      }
933    if (!it->display_only)
934      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
935    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
936    x = ev->cur.canvas.x - x;
937    y = ev->cur.canvas.y - y;
938    dx = x - it->dx;
939    adx = dx;
940    if (adx < 0) adx = -dx;
941    dy = y - it->dy;
942    ady = dy;
943    if (ady < 0) ady = -dy;
944    minw /= 2;
945    minh /= 2;
946    if ((adx > minw) || (ady > minh))
947      {
948         it->dragging = EINA_TRUE;
949         if (it->long_timer)
950           {
951              ecore_timer_del(it->long_timer);
952              it->long_timer = NULL;
953           }
954         if (!it->wd->wasselected)
955           {
956              _item_unhighlight(it);
957              _item_unselect(it);
958           }
959         if (dy < 0)
960           {
961              if (ady > adx)
962                evas_object_smart_callback_call(WIDGET(it),
963                                                SIG_DRAG_START_UP, it);
964              else
965                {
966                   if (dx < 0)
967                     evas_object_smart_callback_call(WIDGET(it),
968                                                     SIG_DRAG_START_LEFT, it);
969                   else
970                     evas_object_smart_callback_call(WIDGET(it),
971                                                     SIG_DRAG_START_RIGHT, it);
972                }
973           }
974         else
975           {
976              if (ady > adx)
977                evas_object_smart_callback_call(WIDGET(it),
978                                                SIG_DRAG_START_DOWN, it);
979              else
980                {
981                   if (dx < 0)
982                     evas_object_smart_callback_call(WIDGET(it),
983                                                     SIG_DRAG_START_LEFT, it);
984                   else
985                     evas_object_smart_callback_call(WIDGET(it),
986                                                     SIG_DRAG_START_RIGHT, it);
987                }
988           }
989      }
990 }
991
992 static Eina_Bool
993 _long_press(void *data)
994 {
995    Elm_Gen_Item *it = data, *it_tmp;
996    Eina_List *list, *l;
997
998    it->long_timer = NULL;
999    if ((it->disabled) || (it->dragging) || (it->display_only))
1000      return ECORE_CALLBACK_CANCEL;
1001    it->wd->longpressed = EINA_TRUE;
1002    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1003    if ((it->wd->reorder_mode) && (it->item->flags != ELM_GENLIST_ITEM_GROUP))
1004      {
1005         it->wd->reorder_it = it;
1006         it->wd->reorder_start_y = 0;
1007
1008         evas_object_raise(VIEW(it));
1009         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1010         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1011
1012         list = elm_genlist_realized_items_get(it->wd->obj);
1013         EINA_LIST_FOREACH(list, l, it_tmp)
1014           {
1015              if (it != it_tmp) _item_unselect(it_tmp);
1016           }
1017         if (elm_genlist_item_expanded_get(it))
1018           {
1019              elm_genlist_item_expanded_set(it, EINA_FALSE);
1020              return ECORE_CALLBACK_RENEW;
1021           }
1022         edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1023      }
1024    return ECORE_CALLBACK_CANCEL;
1025 }
1026
1027 static void
1028 _swipe(Elm_Gen_Item *it)
1029 {
1030    int i, sum = 0;
1031
1032    if (!it) return;
1033    if ((it->display_only) || (it->disabled)) return;
1034    it->wd->swipe = EINA_FALSE;
1035    for (i = 0; i < it->wd->movements; i++)
1036      {
1037         sum += it->wd->history[i].x;
1038         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1039      }
1040
1041    sum /= it->wd->movements;
1042    if (abs(sum - it->wd->history[0].x) <= 10) return;
1043    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1044 }
1045
1046 static Eina_Bool
1047 _swipe_cancel(void *data)
1048 {
1049    Elm_Gen_Item *it = data;
1050
1051    if (!it) return ECORE_CALLBACK_CANCEL;
1052    it->wd->swipe = EINA_FALSE;
1053    it->wd->movements = 0;
1054    return ECORE_CALLBACK_RENEW;
1055 }
1056
1057 static Eina_Bool
1058 _multi_cancel(void *data)
1059 {
1060    Widget_Data *wd = data;
1061
1062    if (!wd) return ECORE_CALLBACK_CANCEL;
1063    wd->multi_timeout = EINA_TRUE;
1064    return ECORE_CALLBACK_RENEW;
1065 }
1066
1067 static void
1068 _multi_touch_gesture_eval(void *data)
1069 {
1070    Elm_Gen_Item *it = data;
1071
1072    it->wd->multitouched = EINA_FALSE;
1073    if (it->wd->multi_timer)
1074      {
1075         ecore_timer_del(it->wd->multi_timer);
1076         it->wd->multi_timer = NULL;
1077      }
1078    if (it->wd->multi_timeout)
1079      {
1080         it->wd->multi_timeout = EINA_FALSE;
1081         return;
1082      }
1083
1084    Evas_Coord minw = 0, minh = 0;
1085    Evas_Coord off_x, off_y, off_mx, off_my;
1086
1087    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1088    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1089    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1090    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1091    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1092
1093    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1094      {
1095         if ((off_x + off_mx) > (off_y + off_my))
1096           {
1097              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_RIGHT, it);
1100              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1101                evas_object_smart_callback_call(WIDGET(it),
1102                                                SIG_MULTI_SWIPE_LEFT, it);
1103              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1104                evas_object_smart_callback_call(WIDGET(it),
1105                                                SIG_MULTI_PINCH_OUT, it);
1106              else
1107                evas_object_smart_callback_call(WIDGET(it),
1108                                                SIG_MULTI_PINCH_IN, it);
1109           }
1110         else
1111           {
1112              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_DOWN, it);
1115              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1116                evas_object_smart_callback_call(WIDGET(it),
1117                                                SIG_MULTI_SWIPE_UP, it);
1118              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1119                evas_object_smart_callback_call(WIDGET(it),
1120                                                SIG_MULTI_PINCH_OUT, it);
1121              else
1122                evas_object_smart_callback_call(WIDGET(it),
1123                                                SIG_MULTI_PINCH_IN, it);
1124           }
1125      }
1126    it->wd->multi_timeout = EINA_FALSE;
1127 }
1128
1129 static void
1130 _multi_down(void        *data,
1131             Evas        *evas __UNUSED__,
1132             Evas_Object *obj __UNUSED__,
1133             void        *event_info)
1134 {
1135    Elm_Gen_Item *it = data;
1136    Evas_Event_Multi_Down *ev = event_info;
1137
1138    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1139    it->wd->multi_device = ev->device;
1140    it->wd->multi_down = EINA_TRUE;
1141    it->wd->multitouched = EINA_TRUE;
1142    it->wd->prev_mx = ev->canvas.x;
1143    it->wd->prev_my = ev->canvas.y;
1144    if (!it->wd->wasselected)
1145      {
1146         _item_unhighlight(it);
1147         _item_unselect(it);
1148      }
1149    it->wd->wasselected = EINA_FALSE;
1150    it->wd->longpressed = EINA_FALSE;
1151    if (it->long_timer)
1152      {
1153         ecore_timer_del(it->long_timer);
1154         it->long_timer = NULL;
1155      }
1156    if (it->dragging)
1157      {
1158         it->dragging = EINA_FALSE;
1159         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1160      }
1161    if (it->item->swipe_timer)
1162      {
1163         ecore_timer_del(it->item->swipe_timer);
1164         it->item->swipe_timer = NULL;
1165      }
1166    if (it->wd->on_hold)
1167      {
1168         it->wd->swipe = EINA_FALSE;
1169         it->wd->movements = 0;
1170         it->wd->on_hold = EINA_FALSE;
1171      }
1172 }
1173
1174 static void
1175 _multi_up(void        *data,
1176           Evas        *evas __UNUSED__,
1177           Evas_Object *obj __UNUSED__,
1178           void        *event_info)
1179 {
1180    Elm_Gen_Item *it = data;
1181    Evas_Event_Multi_Up *ev = event_info;
1182
1183    if (it->wd->multi_device != ev->device) return;
1184    it->wd->multi_device = 0;
1185    it->wd->multi_down = EINA_FALSE;
1186    if (it->wd->mouse_down) return;
1187    _multi_touch_gesture_eval(data);
1188 }
1189
1190 static void
1191 _multi_move(void        *data,
1192             Evas        *evas __UNUSED__,
1193             Evas_Object *obj __UNUSED__,
1194             void        *event_info)
1195 {
1196    Elm_Gen_Item *it = data;
1197    Evas_Event_Multi_Move *ev = event_info;
1198
1199    if (it->wd->multi_device != ev->device) return;
1200    it->wd->cur_mx = ev->cur.canvas.x;
1201    it->wd->cur_my = ev->cur.canvas.y;
1202 }
1203
1204 static void
1205 _mouse_down(void        *data,
1206             Evas        *evas __UNUSED__,
1207             Evas_Object *obj,
1208             void        *event_info)
1209 {
1210    Elm_Gen_Item *it = data;
1211    Evas_Event_Mouse_Down *ev = event_info;
1212    Evas_Coord x, y;
1213
1214    if (ev->button != 1) return;
1215    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1216      {
1217         it->wd->on_hold = EINA_TRUE;
1218      }
1219
1220    it->down = EINA_TRUE;
1221    it->dragging = EINA_FALSE;
1222    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1223    it->dx = ev->canvas.x - x;
1224    it->dy = ev->canvas.y - y;
1225    it->wd->mouse_down = EINA_TRUE;
1226    if (!it->wd->multitouched)
1227      {
1228         it->wd->prev_x = ev->canvas.x;
1229         it->wd->prev_y = ev->canvas.y;
1230         it->wd->multi_timeout = EINA_FALSE;
1231         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1232         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1233      }
1234    it->wd->longpressed = EINA_FALSE;
1235    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1236    else it->wd->on_hold = EINA_FALSE;
1237    if (it->wd->on_hold) return;
1238    it->wd->wasselected = it->selected;
1239    _item_highlight(it);
1240    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1241      if ((!it->disabled) && (!it->display_only))
1242        {
1243           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1244           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1245        }
1246    if (it->long_timer) ecore_timer_del(it->long_timer);
1247    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1248    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1249    if (it->realized)
1250      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1251                                       it);
1252    else
1253      it->long_timer = NULL;
1254    it->wd->swipe = EINA_FALSE;
1255    it->wd->movements = 0;
1256 }
1257
1258 static void
1259 _mouse_up(void        *data,
1260           Evas        *evas __UNUSED__,
1261           Evas_Object *obj __UNUSED__,
1262           void        *event_info)
1263 {
1264    Elm_Gen_Item *it = data;
1265    Evas_Event_Mouse_Up *ev = event_info;
1266    Eina_Bool dragged = EINA_FALSE;
1267
1268    if (ev->button != 1) return;
1269    it->down = EINA_FALSE;
1270    it->wd->mouse_down = EINA_FALSE;
1271    if (it->wd->multitouched)
1272      {
1273         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1274         if (it->wd->multi_down) return;
1275         _multi_touch_gesture_eval(data);
1276         return;
1277      }
1278    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1279    else it->wd->on_hold = EINA_FALSE;
1280    if (it->long_timer)
1281      {
1282         ecore_timer_del(it->long_timer);
1283         it->long_timer = NULL;
1284      }
1285    if (it->dragging)
1286      {
1287         it->dragging = EINA_FALSE;
1288         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1289         dragged = 1;
1290      }
1291    if (it->item->swipe_timer)
1292      {
1293         ecore_timer_del(it->item->swipe_timer);
1294         it->item->swipe_timer = NULL;
1295      }
1296    if (it->wd->multi_timer)
1297      {
1298         ecore_timer_del(it->wd->multi_timer);
1299         it->wd->multi_timer = NULL;
1300         it->wd->multi_timeout = EINA_FALSE;
1301      }
1302    if (it->wd->on_hold)
1303      {
1304         if (it->wd->swipe) _swipe(data);
1305         it->wd->longpressed = EINA_FALSE;
1306         it->wd->on_hold = EINA_FALSE;
1307         return;
1308      }
1309    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1310      {
1311         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1312
1313         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1314           {
1315              if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1316                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1317              else
1318                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1319           }
1320         else
1321           {
1322              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1323              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1324           }
1325         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1326         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1327         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1328         elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1329      }
1330    if (it->wd->longpressed)
1331      {
1332         it->wd->longpressed = EINA_FALSE;
1333         if (!it->wd->wasselected)
1334           {
1335              _item_unhighlight(it);
1336              _item_unselect(it);
1337           }
1338         it->wd->wasselected = EINA_FALSE;
1339         return;
1340      }
1341    if (dragged)
1342      {
1343         if (it->want_unrealize)
1344           {
1345              elm_gen_item_unrealize(it, EINA_FALSE);
1346              if (it->item->block->want_unrealize)
1347                _item_block_unrealize(it->item->block);
1348           }
1349      }
1350    if ((it->disabled) || (dragged) || (it->display_only)) return;
1351    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1352    if (it->wd->multi)
1353      {
1354         if (!it->selected)
1355           {
1356              _item_highlight(it);
1357              it->sel_cb(it);
1358           }
1359         else
1360           {
1361              _item_unhighlight(it);
1362              _item_unselect(it);
1363           }
1364      }
1365    else
1366      {
1367         if (!it->selected)
1368           {
1369              Widget_Data *wd = it->wd;
1370              if (wd)
1371                {
1372                   while (wd->selected)
1373                     {
1374                        _item_unhighlight(wd->selected->data);
1375                        _item_unselect(wd->selected->data);
1376                     }
1377                }
1378           }
1379         else
1380           {
1381              const Eina_List *l, *l_next;
1382              Elm_Gen_Item *it2;
1383
1384              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1385                 if (it2 != it)
1386                   {
1387                      _item_unhighlight(it2);
1388                      _item_unselect(it2);
1389                   }
1390              //_item_highlight(it);
1391              //_item_select(it);
1392           }
1393         _item_highlight(it);
1394         it->sel_cb(it);
1395      }
1396 }
1397
1398 static void
1399 _signal_expand_toggle(void        *data,
1400                       Evas_Object *obj __UNUSED__,
1401                       const char  *emission __UNUSED__,
1402                       const char  *source __UNUSED__)
1403 {
1404    Elm_Gen_Item *it = data;
1405
1406    if (it->item->expanded)
1407      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1408    else
1409      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1410 }
1411
1412 static void
1413 _signal_expand(void        *data,
1414                Evas_Object *obj __UNUSED__,
1415                const char  *emission __UNUSED__,
1416                const char  *source __UNUSED__)
1417 {
1418    Elm_Gen_Item *it = data;
1419
1420    if (!it->item->expanded)
1421      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1422 }
1423
1424 static void
1425 _signal_contract(void        *data,
1426                  Evas_Object *obj __UNUSED__,
1427                  const char  *emission __UNUSED__,
1428                  const char  *source __UNUSED__)
1429 {
1430    Elm_Gen_Item *it = data;
1431
1432    if (it->item->expanded)
1433      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1434 }
1435
1436 static Eina_Bool
1437 _scr_hold_timer_cb(void *data)
1438 {
1439    if (!data) return ECORE_CALLBACK_CANCEL;
1440    Widget_Data *wd = data;
1441    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1442    wd->scr_hold_timer = NULL;
1443    return ECORE_CALLBACK_CANCEL;
1444 }
1445
1446 static void
1447 _mode_finished_signal_cb(void        *data,
1448                          Evas_Object *obj,
1449                          const char  *emission __UNUSED__,
1450                          const char  *source __UNUSED__)
1451 {
1452    if (!data) return;
1453    if (!obj) return;
1454    Elm_Gen_Item *it = data;
1455    if ((it->delete_me) || (!it->realized) || (!it->item->mode_view)) return;
1456    char buf[1024];
1457    Evas *te = evas_object_evas_get(obj);
1458
1459    evas_event_freeze(te);
1460    it->item->nocache = EINA_FALSE;
1461    _mode_item_unrealize(it);
1462    if (it->item->group_item)
1463      evas_object_raise(it->item->VIEW(group_item));
1464    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type);
1465    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1466    evas_event_thaw(te);
1467    evas_event_thaw_eval(te);
1468 }
1469
1470 static void
1471 _item_cache_clean(Widget_Data *wd)
1472 {
1473    evas_event_freeze(evas_object_evas_get(wd->obj));
1474    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1475      {
1476         Item_Cache *itc;
1477
1478         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1479         wd->item_cache = eina_inlist_remove(wd->item_cache,
1480                                             wd->item_cache->last);
1481         wd->item_cache_count--;
1482         if (itc->spacer) evas_object_del(itc->spacer);
1483         if (itc->base_view) evas_object_del(itc->base_view);
1484         if (itc->item_style) eina_stringshare_del(itc->item_style);
1485         free(itc);
1486      }
1487    evas_event_thaw(evas_object_evas_get(wd->obj));
1488    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1489 }
1490
1491 static void
1492 _item_cache_zero(Widget_Data *wd)
1493 {
1494    int pmax = wd->item_cache_max;
1495    wd->item_cache_max = 0;
1496    _item_cache_clean(wd);
1497    wd->item_cache_max = pmax;
1498 }
1499
1500 static void
1501 _item_cache_add(Elm_Gen_Item *it)
1502 {
1503    Item_Cache *itc;
1504
1505    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1506    if (it->wd->item_cache_max <= 0)
1507      {
1508         evas_object_del(VIEW(it));
1509         VIEW(it) = NULL;
1510         evas_object_del(it->spacer);
1511         it->spacer = NULL;
1512         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1513         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1514         return;
1515      }
1516
1517    it->wd->item_cache_count++;
1518    itc = calloc(1, sizeof(Item_Cache));
1519    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1520                                             EINA_INLIST_GET(itc));
1521    itc->spacer = it->spacer;
1522    it->spacer = NULL;
1523    itc->base_view = VIEW(it);
1524    VIEW(it) = NULL;
1525    evas_object_hide(itc->base_view);
1526    evas_object_move(itc->base_view, -9999, -9999);
1527    itc->item_style = eina_stringshare_add(it->itc->item_style);
1528    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) itc->tree = 1;
1529    itc->compress = (it->wd->compress);
1530    itc->selected = it->selected;
1531    itc->disabled = it->disabled;
1532    itc->expanded = it->item->expanded;
1533    if (it->long_timer)
1534      {
1535         ecore_timer_del(it->long_timer);
1536         it->long_timer = NULL;
1537      }
1538    if (it->item->swipe_timer)
1539      {
1540         ecore_timer_del(it->item->swipe_timer);
1541         it->item->swipe_timer = NULL;
1542      }
1543    // FIXME: other callbacks?
1544    edje_object_signal_callback_del_full(itc->base_view,
1545                                         "elm,action,expand,toggle",
1546                                         "elm", _signal_expand_toggle, it);
1547    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1548                                         "elm",
1549                                         _signal_expand, it);
1550    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1551                                         "elm", _signal_contract, it);
1552    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
1553                                        _mouse_down, it);
1554    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
1555                                        _mouse_up, it);
1556    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
1557                                        _mouse_move, it);
1558    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
1559                                        _multi_down, it);
1560    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
1561                                        _multi_up, it);
1562    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
1563                                        _multi_move, it);
1564    _item_cache_clean(it->wd);
1565    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1566    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1567 }
1568
1569 static Item_Cache *
1570 _item_cache_find(Elm_Gen_Item *it)
1571 {
1572    Item_Cache *itc;
1573    Eina_Bool tree = 0;
1574
1575    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) tree = 1;
1576    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1577      {
1578         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1579           continue;
1580         if ((itc->tree == tree) &&
1581             (itc->compress == it->wd->compress) &&
1582             (!strcmp(it->itc->item_style, itc->item_style)))
1583           {
1584              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1585                                                      EINA_INLIST_GET(itc));
1586              it->wd->item_cache_count--;
1587              return itc;
1588           }
1589      }
1590    return NULL;
1591 }
1592
1593 static void
1594 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1595 {
1596    if (!it->item->nostacking)
1597      {
1598         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1599           evas_object_lower(VIEW(it));
1600         else
1601           evas_object_raise(VIEW(it));
1602      }
1603
1604    if (it->item->order_num_in & 0x1)
1605      edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1606    else
1607      edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1608 }
1609
1610 static void
1611 _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1612 {
1613    if (itc)
1614      {
1615         if (it->selected != itc->selected)
1616           {
1617              if (it->selected)
1618                edje_object_signal_emit(VIEW(it),
1619                                        "elm,state,selected", "elm");
1620           }
1621         if (it->disabled != itc->disabled)
1622           {
1623              if (it->disabled)
1624                edje_object_signal_emit(VIEW(it),
1625                                        "elm,state,disabled", "elm");
1626           }
1627         if (it->item->expanded != itc->expanded)
1628           {
1629              if (it->item->expanded)
1630                edje_object_signal_emit(VIEW(it),
1631                                        "elm,state,expanded", "elm");
1632           }
1633      }
1634    else
1635      {
1636         if (it->selected)
1637           edje_object_signal_emit(VIEW(it),
1638                                   "elm,state,selected", "elm");
1639         if (it->disabled)
1640           edje_object_signal_emit(VIEW(it),
1641                                   "elm,state,disabled", "elm");
1642         if (it->item->expanded)
1643           edje_object_signal_emit(VIEW(it),
1644                                   "elm,state,expanded", "elm");
1645      }
1646 }
1647
1648 static void
1649 _item_cache_free(Item_Cache *itc)
1650 {
1651    if (itc->spacer) evas_object_del(itc->spacer);
1652    if (itc->base_view) evas_object_del(itc->base_view);
1653    if (itc->item_style) eina_stringshare_del(itc->item_style);
1654    free(itc);
1655 }
1656
1657 static void
1658 _item_del_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1659 {
1660    Elm_Gen_Item *it = event_info;
1661    if (!it) return;
1662    if (it->wd->last_selected_item == it)
1663      it->wd->last_selected_item = NULL;
1664 }
1665
1666 static void
1667 _item_label_realize(Elm_Gen_Item *it,
1668                     Evas_Object *target,
1669                     Eina_List **source)
1670 {
1671    if (it->itc->func.label_get)
1672      {
1673         const Eina_List *l;
1674         const char *key;
1675
1676         *source = elm_widget_stringlist_get(edje_object_data_get(target, "labels"));
1677         EINA_LIST_FOREACH(*source, l, key)
1678           {
1679              char *s = it->itc->func.label_get
1680                 ((void *)it->base.data, WIDGET(it), key);
1681
1682              if (s)
1683                {
1684                   edje_object_part_text_set(target, key, s);
1685                   free(s);
1686                }
1687              else
1688                {
1689                   edje_object_part_text_set(target, key, "");
1690                }
1691           }
1692      }
1693 }
1694
1695 static Eina_List *
1696 _item_icon_realize(Elm_Gen_Item *it,
1697                    Evas_Object *target,
1698                    Eina_List **source)
1699 {
1700    Eina_List *res = NULL;
1701
1702    if (it->itc->func.icon_get)
1703      {
1704         const Eina_List *l;
1705         const char *key;
1706
1707         *source = elm_widget_stringlist_get(edje_object_data_get(target, "icons"));
1708         EINA_LIST_FOREACH(*source, l, key)
1709           {
1710              Evas_Object *ic = it->itc->func.icon_get
1711                 ((void *)it->base.data, WIDGET(it), key);
1712
1713              if (ic)
1714                {
1715                   res = eina_list_append(res, ic);
1716                   edje_object_part_swallow(target, key, ic);
1717                   evas_object_show(ic);
1718                   elm_widget_sub_object_add(WIDGET(it), ic);
1719                   if (it->disabled)
1720                     elm_widget_disabled_set(ic, EINA_TRUE);
1721                }
1722           }
1723      }
1724
1725    return res;
1726 }
1727
1728 static void
1729 _item_state_realize(Elm_Gen_Item *it,
1730                     Evas_Object *target,
1731                     Eina_List **source)
1732 {
1733    if (it->itc->func.state_get)
1734      {
1735         const Eina_List *l;
1736         const char *key;
1737         char buf[4096];
1738
1739         *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
1740         EINA_LIST_FOREACH(*source, l, key)
1741           {
1742              Eina_Bool on = it->itc->func.state_get
1743                 ((void *)it->base.data, WIDGET(it), key);
1744
1745              if (on)
1746                {
1747                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1748                   edje_object_signal_emit(target, buf, "elm");
1749                }
1750              else
1751                {
1752                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
1753                   edje_object_signal_emit(target, buf, "elm");
1754                }
1755           }
1756      }
1757 }
1758
1759 static void
1760 _item_realize(Elm_Gen_Item *it,
1761               int               in,
1762               Eina_Bool         calc)
1763 {
1764    Elm_Gen_Item *it2;
1765    const char *treesize;
1766    char buf[1024];
1767    int depth, tsize = 20;
1768    Item_Cache *itc = NULL;
1769
1770    if (it->delete_me) return;
1771    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
1772    if (it->realized)
1773      {
1774         if (it->item->order_num_in != in)
1775           {
1776              it->item->order_num_in = in;
1777              _elm_genlist_item_odd_even_update(it);
1778              _elm_genlist_item_state_update(it, NULL);
1779           }
1780         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1781         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1782         return;
1783      }
1784    it->item->order_num_in = in;
1785
1786    if (it->item->nocache)
1787      it->item->nocache = EINA_FALSE;
1788    else
1789      itc = _item_cache_find(it);
1790    if (itc)
1791      {
1792         VIEW(it) = itc->base_view;
1793         itc->base_view = NULL;
1794         it->spacer = itc->spacer;
1795         itc->spacer = NULL;
1796      }
1797    else
1798      {
1799         const char *stacking_even;
1800         const char *stacking;
1801
1802         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
1803         edje_object_scale_set(VIEW(it),
1804                               elm_widget_scale_get(WIDGET(it)) *
1805                               _elm_config->scale);
1806         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
1807         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
1808
1809         if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS)
1810           strncpy(buf, "tree", sizeof(buf));
1811         else strncpy(buf, "item", sizeof(buf));
1812         if (it->wd->compress)
1813           strncat(buf, "_compress", sizeof(buf) - strlen(buf));
1814
1815         strncat(buf, "/", sizeof(buf) - strlen(buf));
1816         strncat(buf, it->itc->item_style, sizeof(buf) - strlen(buf));
1817
1818         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
1819                               elm_widget_style_get(WIDGET(it)));
1820
1821         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1822         if (!stacking_even) stacking_even = "above";
1823         it->item->stacking_even = !!strcmp("above", stacking_even);
1824
1825         stacking = edje_object_data_get(VIEW(it), "stacking");
1826         if (!stacking) stacking = "yes";
1827         it->item->nostacking = !!strcmp("yes", stacking);
1828
1829         edje_object_mirrored_set(VIEW(it),
1830                                  elm_widget_mirrored_get(WIDGET(it)));
1831         it->spacer =
1832           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1833         evas_object_color_set(it->spacer, 0, 0, 0, 0);
1834         elm_widget_sub_object_add(WIDGET(it), it->spacer);
1835      }
1836
1837    _elm_genlist_item_odd_even_update(it);
1838
1839    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
1840      {
1841         if (it2->parent->item->flags != ELM_GENLIST_ITEM_GROUP) depth += 1;
1842      }
1843    it->item->expanded_depth = depth;
1844    treesize = edje_object_data_get(VIEW(it), "treesize");
1845    if (treesize) tsize = atoi(treesize);
1846    evas_object_size_hint_min_set(it->spacer,
1847                                  (depth * tsize) * _elm_config->scale, 1);
1848    edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1849    if (!calc)
1850      {
1851         edje_object_signal_callback_add(VIEW(it),
1852                                         "elm,action,expand,toggle",
1853                                         "elm", _signal_expand_toggle, it);
1854         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
1855                                         "elm", _signal_expand, it);
1856         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
1857                                         "elm", _signal_contract, it);
1858         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1859                                        _mouse_down, it);
1860         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1861                                        _mouse_up, it);
1862         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1863                                        _mouse_move, it);
1864         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
1865                                        _multi_down, it);
1866         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_UP,
1867                                        _multi_up, it);
1868         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
1869                                        _multi_move, it);
1870
1871         _elm_genlist_item_state_update(it, itc);
1872      }
1873
1874    if ((calc) && (it->wd->homogeneous) &&
1875        ((it->wd->item_width) ||
1876         ((it->wd->item_width) && (it->wd->group_item_width))))
1877      {
1878         /* homogenous genlist shortcut */
1879         if (!it->item->mincalcd)
1880           {
1881              if (it->item->flags & ELM_GENLIST_ITEM_GROUP)
1882                {
1883                   it->item->w = it->item->minw = it->wd->group_item_width;
1884                   it->item->h = it->item->minh = it->wd->group_item_height;
1885                }
1886              else
1887                {
1888                   it->item->w = it->item->minw = it->wd->item_width;
1889                   it->item->h = it->item->minh = it->wd->item_height;
1890                }
1891              it->item->mincalcd = EINA_TRUE;
1892           }
1893      }
1894    else
1895      {
1896         /* FIXME: If you see that assert, please notify us and we
1897            will clean our mess */
1898         assert(eina_list_count(it->icon_objs) == 0);
1899
1900         _item_label_realize(it, VIEW(it), &it->labels);
1901         it->icon_objs = _item_icon_realize(it, VIEW(it), &it->icons);
1902         _item_state_realize(it, VIEW(it), &it->states);
1903
1904         if (!it->item->mincalcd)
1905           {
1906              Evas_Coord mw = -1, mh = -1;
1907
1908              if (!it->display_only)
1909                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1910              if (it->wd->height_for_width) mw = it->wd->prev_viewport_w;
1911              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
1912                                                   mh);
1913              if (!it->display_only)
1914                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1915              it->item->w = it->item->minw = mw;
1916              it->item->h = it->item->minh = mh;
1917              it->item->mincalcd = EINA_TRUE;
1918
1919              if ((!it->wd->group_item_width) && (it->item->flags == ELM_GENLIST_ITEM_GROUP))
1920                {
1921                   it->wd->group_item_width = mw;
1922                   it->wd->group_item_height = mh;
1923                }
1924              else if ((!it->wd->item_width) && (it->item->flags == ELM_GENLIST_ITEM_NONE))
1925                {
1926                   it->wd->item_width = mw;
1927                   it->wd->item_height = mh;
1928                }
1929           }
1930         if (!calc) evas_object_show(VIEW(it));
1931      }
1932
1933    if (it->tooltip.content_cb)
1934      {
1935         elm_widget_item_tooltip_content_cb_set(it,
1936                                                it->tooltip.content_cb,
1937                                                it->tooltip.data, NULL);
1938         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
1939         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
1940      }
1941
1942    if (it->mouse_cursor)
1943      elm_widget_item_cursor_set(it, it->mouse_cursor);
1944
1945    it->realized = EINA_TRUE;
1946    it->want_unrealize = EINA_FALSE;
1947
1948    if (itc) _item_cache_free(itc);
1949    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1950    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1951    if (!calc)
1952      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1953    edje_object_message_signal_process(VIEW(it));
1954 }
1955
1956 static void
1957 _item_unrealize_cb(Elm_Gen_Item *it)
1958 {
1959    if (it->item->nocache)
1960      {
1961         evas_object_del(VIEW(it));
1962         VIEW(it) = NULL;
1963         evas_object_del(it->spacer);
1964         it->spacer = NULL;
1965      }
1966    else
1967      {
1968         edje_object_mirrored_set(VIEW(it),
1969                                  elm_widget_mirrored_get(WIDGET(it)));
1970         edje_object_scale_set(VIEW(it),
1971                               elm_widget_scale_get(WIDGET(it))
1972                               * _elm_config->scale);
1973         _item_cache_add(it);
1974      }
1975
1976    _mode_item_unrealize(it);
1977    it->states = NULL;
1978    it->realized = EINA_FALSE;
1979    it->want_unrealize = EINA_FALSE;
1980 }
1981
1982 static Eina_Bool
1983 _item_block_recalc(Item_Block *itb,
1984                    int         in,
1985                    Eina_Bool   qadd)
1986 {
1987    const Eina_List *l;
1988    Elm_Gen_Item *it;
1989    Evas_Coord minw = 0, minh = 0;
1990    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
1991    Evas_Coord y = 0;
1992
1993    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
1994    itb->num = in;
1995    EINA_LIST_FOREACH(itb->items, l, it)
1996      {
1997         if (it->delete_me) continue;
1998         showme |= it->item->showme;
1999         if (!itb->realized)
2000           {
2001              if (qadd)
2002                {
2003                   if (!it->item->mincalcd) changed = EINA_TRUE;
2004                   if (changed)
2005                     {
2006                        _item_realize(it, in, EINA_TRUE);
2007                        elm_gen_item_unrealize(it, EINA_TRUE);
2008                     }
2009                }
2010              else
2011                {
2012                   _item_realize(it, in, EINA_TRUE);
2013                   elm_gen_item_unrealize(it, EINA_TRUE);
2014                }
2015           }
2016         else
2017           _item_realize(it, in, EINA_FALSE);
2018         minh += it->item->minh;
2019         if (minw < it->item->minw) minw = it->item->minw;
2020         in++;
2021         it->x = 0;
2022         it->y = y;
2023         y += it->item->h;
2024      }
2025    itb->minw = minw;
2026    itb->minh = minh;
2027    itb->changed = EINA_FALSE;
2028    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2029    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2030    return showme;
2031 }
2032
2033 static void
2034 _item_block_realize(Item_Block *itb)
2035 {
2036    if (itb->realized) return;
2037    itb->realized = EINA_TRUE;
2038    itb->want_unrealize = EINA_FALSE;
2039 }
2040
2041 static void
2042 _item_block_unrealize(Item_Block *itb)
2043 {
2044    const Eina_List *l;
2045    Elm_Gen_Item *it;
2046    Eina_Bool dragging = EINA_FALSE;
2047
2048    if (!itb->realized) return;
2049    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2050    EINA_LIST_FOREACH(itb->items, l, it)
2051      {
2052         if (it->item->flags != ELM_GENLIST_ITEM_GROUP)
2053           {
2054              if (it->dragging)
2055                {
2056                   dragging = EINA_TRUE;
2057                   it->want_unrealize = EINA_TRUE;
2058                }
2059              else
2060                elm_gen_item_unrealize(it, EINA_FALSE);
2061           }
2062      }
2063    if (!dragging)
2064      {
2065         itb->realized = EINA_FALSE;
2066         itb->want_unrealize = EINA_TRUE;
2067      }
2068    else
2069      itb->want_unrealize = EINA_FALSE;
2070    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2071    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2072 }
2073
2074 static int
2075 _get_space_for_reorder_item(Elm_Gen_Item *it)
2076 {
2077    Evas_Coord rox, roy, row, roh, oy, oh;
2078    Eina_Bool top = EINA_FALSE;
2079    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2080    if (!reorder_it) return 0;
2081
2082    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2083    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2084
2085    if ((it->wd->reorder_start_y < it->item->block->y) &&
2086        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2087      {
2088         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2089         if (it->item->block->count == 1)
2090           it->wd->reorder_rel = it;
2091      }
2092    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2093             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2094      {
2095         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2096      }
2097    else
2098      it->item->block->reorder_offset = 0;
2099
2100    it->item->scrl_y += it->item->block->reorder_offset;
2101
2102    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2103                               rox, roy + (roh / 2), row, 1));
2104    if (top)
2105      {
2106         it->wd->reorder_rel = it;
2107         it->item->scrl_y += it->wd->reorder_it->item->h;
2108         return it->wd->reorder_it->item->h;
2109      }
2110    else
2111      return 0;
2112 }
2113
2114 static Eina_Bool
2115 _reorder_move_animator_cb(void *data)
2116 {
2117    Elm_Gen_Item *it = data;
2118    Eina_Bool down = EINA_FALSE;
2119    double t;
2120    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2121
2122    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2123
2124    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2125    else y = dy;
2126
2127    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2128    if (diff > it->item->h) y = diff / 2;
2129
2130    if (it->item->old_scrl_y < it->item->scrl_y)
2131      {
2132         it->item->old_scrl_y += y;
2133         down = EINA_TRUE;
2134      }
2135    else if (it->item->old_scrl_y > it->item->scrl_y)
2136      {
2137         it->item->old_scrl_y -= y;
2138         down = EINA_FALSE;
2139      }
2140    _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2141    _group_items_recalc(it->wd);
2142
2143    if ((it->wd->reorder_pan_move) ||
2144        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2145        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2146      {
2147         it->item->old_scrl_y = it->item->scrl_y;
2148         it->item->move_effect_enabled = EINA_FALSE;
2149         it->wd->reorder_move_animator = NULL;
2150         return ECORE_CALLBACK_CANCEL;
2151      }
2152    return ECORE_CALLBACK_RENEW;
2153 }
2154
2155 static void
2156 _item_position(Elm_Gen_Item *it,
2157                Evas_Object      *view,
2158                Evas_Coord        it_x,
2159                Evas_Coord        it_y)
2160 {
2161    if (!it) return;
2162    if (!view) return;
2163
2164    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2165    evas_object_resize(view, it->item->w, it->item->h);
2166    evas_object_move(view, it_x, it_y);
2167    evas_object_show(view);
2168    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2169    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2170 }
2171
2172 static void
2173 _item_block_position(Item_Block *itb,
2174                      int         in)
2175 {
2176    const Eina_List *l;
2177    Elm_Gen_Item *it;
2178    Elm_Gen_Item *git;
2179    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2180    int vis;
2181
2182    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2183    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2184    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2185                             &cvw, &cvh);
2186    EINA_LIST_FOREACH(itb->items, l, it)
2187      {
2188         if (it->delete_me) continue;
2189         else if (it->wd->reorder_it == it) continue;
2190         it->x = 0;
2191         it->y = y;
2192         it->item->w = itb->w;
2193         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2194         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2195
2196         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2197                                    cvx, cvy, cvw, cvh));
2198         if (it->item->flags != ELM_GENLIST_ITEM_GROUP)
2199           {
2200              if ((itb->realized) && (!it->realized))
2201                {
2202                   if (vis) _item_realize(it, in, EINA_FALSE);
2203                }
2204              if (it->realized)
2205                {
2206                   if (vis)
2207                     {
2208                        if (it->wd->reorder_mode)
2209                          y += _get_space_for_reorder_item(it);
2210                        git = it->item->group_item;
2211                        if (git)
2212                          {
2213                             if (git->item->scrl_y < oy)
2214                               git->item->scrl_y = oy;
2215                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2216                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2217                             git->item->want_realize = EINA_TRUE;
2218                          }
2219                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2220                          {
2221                             if (!it->item->move_effect_enabled)
2222                               {
2223                                  it->item->move_effect_enabled = EINA_TRUE;
2224                                  it->wd->reorder_move_animator =
2225                                     ecore_animator_add(
2226                                        _reorder_move_animator_cb, it);
2227                               }
2228                          }
2229                        if (!it->item->move_effect_enabled)
2230                          {
2231                             if (it->item->mode_view)
2232                                _item_position(it, it->item->mode_view, it->item->scrl_x,
2233                                               it->item->scrl_y);
2234                             else
2235                                _item_position(it, VIEW(it), it->item->scrl_x,
2236                                               it->item->scrl_y);
2237                             it->item->old_scrl_y = it->item->scrl_y;
2238                          }
2239                     }
2240                   else
2241                     {
2242                        if (!it->dragging) elm_gen_item_unrealize(it, EINA_FALSE);
2243                     }
2244                }
2245              in++;
2246           }
2247         else
2248           {
2249              if (vis) it->item->want_realize = EINA_TRUE;
2250           }
2251         y += it->item->h;
2252      }
2253    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2254    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2255 }
2256
2257 static void
2258 _group_items_recalc(void *data)
2259 {
2260    Widget_Data *wd = data;
2261    Eina_List *l;
2262    Elm_Gen_Item *git;
2263
2264    evas_event_freeze(evas_object_evas_get(wd->obj));
2265    EINA_LIST_FOREACH(wd->group_items, l, git)
2266      {
2267         if (git->item->want_realize)
2268           {
2269              if (!git->realized)
2270                _item_realize(git, 0, EINA_FALSE);
2271              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2272              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2273              evas_object_show(VIEW(git));
2274              evas_object_raise(VIEW(git));
2275           }
2276         else if (!git->item->want_realize && git->realized)
2277           {
2278              if (!git->dragging)
2279                elm_gen_item_unrealize(git, EINA_FALSE);
2280           }
2281      }
2282    evas_event_thaw(evas_object_evas_get(wd->obj));
2283    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2284 }
2285
2286 static Eina_Bool
2287 _must_recalc_idler(void *data)
2288 {
2289    Widget_Data *wd = data;
2290    if (wd->calc_job) ecore_job_del(wd->calc_job);
2291    wd->calc_job = ecore_job_add(_calc_job, wd);
2292    wd->must_recalc_idler = NULL;
2293    return ECORE_CALLBACK_CANCEL;
2294 }
2295
2296 static void
2297 _calc_job(void *data)
2298 {
2299    Widget_Data *wd = data;
2300    Item_Block *itb, *chb = NULL;
2301    Evas_Coord minw = -1, minh = 0, y = 0, ow;
2302    int in = 0;
2303    double t0, t;
2304    Eina_Bool minw_change = EINA_FALSE;
2305    Eina_Bool did_must_recalc = EINA_FALSE;
2306    if (!wd) return;
2307
2308    t0 = ecore_time_get();
2309    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2310    if (wd->w != ow)
2311      wd->w = ow;
2312
2313    evas_event_freeze(evas_object_evas_get(wd->obj));
2314    EINA_INLIST_FOREACH(wd->blocks, itb)
2315      {
2316         Eina_Bool showme = EINA_FALSE;
2317
2318         itb->num = in;
2319         showme = itb->showme;
2320         itb->showme = EINA_FALSE;
2321         if (chb)
2322           {
2323              if (itb->realized) _item_block_unrealize(itb);
2324           }
2325         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2326           {
2327              if (itb->must_recalc)
2328                {
2329                   Eina_List *l;
2330                   Elm_Gen_Item *it;
2331                   EINA_LIST_FOREACH(itb->items, l, it)
2332                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2333                   itb->changed = EINA_TRUE;
2334                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2335                   itb->must_recalc = EINA_FALSE;
2336                }
2337              if (itb->realized) _item_block_unrealize(itb);
2338              showme = _item_block_recalc(itb, in, EINA_FALSE);
2339              chb = itb;
2340           }
2341         itb->y = y;
2342         itb->x = 0;
2343         minh += itb->minh;
2344         if (minw == -1) minw = itb->minw;
2345         else if ((!itb->must_recalc) && (minw < itb->minw))
2346           {
2347              minw = itb->minw;
2348              minw_change = EINA_TRUE;
2349           }
2350         itb->w = minw;
2351         itb->h = itb->minh;
2352         y += itb->h;
2353         in += itb->count;
2354         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2355           {
2356              wd->show_item->item->showme = EINA_FALSE;
2357              if (wd->bring_in)
2358                elm_smart_scroller_region_bring_in(wd->scr,
2359                                                   wd->show_item->x +
2360                                                   wd->show_item->item->block->x,
2361                                                   wd->show_item->y +
2362                                                   wd->show_item->item->block->y,
2363                                                   wd->show_item->item->block->w,
2364                                                   wd->show_item->item->h);
2365              else
2366                elm_smart_scroller_child_region_show(wd->scr,
2367                                                     wd->show_item->x +
2368                                                     wd->show_item->item->block->x,
2369                                                     wd->show_item->y +
2370                                                     wd->show_item->item->block->y,
2371                                                     wd->show_item->item->block->w,
2372                                                     wd->show_item->item->h);
2373              wd->show_item = NULL;
2374           }
2375      }
2376    if (minw_change)
2377      {
2378         EINA_INLIST_FOREACH(wd->blocks, itb)
2379           {
2380              itb->minw = minw;
2381              itb->w = itb->minw;
2382           }
2383      }
2384    if ((chb) && (EINA_INLIST_GET(chb)->next))
2385      {
2386         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2387           {
2388              if (itb->realized) _item_block_unrealize(itb);
2389           }
2390      }
2391    wd->realminw = minw;
2392    if (minw < wd->w) minw = wd->w;
2393    if ((minw != wd->minw) || (minh != wd->minh))
2394      {
2395         wd->minw = minw;
2396         wd->minh = minh;
2397         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2398         _sizing_eval(wd->obj);
2399         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2400           {
2401              Elm_Gen_Item *it;
2402              Evas_Coord it_y;
2403
2404              it = wd->anchor_item;
2405              it_y = wd->anchor_y;
2406              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2407                                               it->item->block->y + it->y + it_y);
2408              wd->anchor_item = it;
2409              wd->anchor_y = it_y;
2410           }
2411      }
2412    t = ecore_time_get();
2413    if (did_must_recalc)
2414      {
2415         if (!wd->must_recalc_idler)
2416           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2417      }
2418    wd->calc_job = NULL;
2419    evas_object_smart_changed(wd->pan_smart);
2420    evas_event_thaw(evas_object_evas_get(wd->obj));
2421    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2422 }
2423
2424 static void
2425 _update_job(void *data)
2426 {
2427    Widget_Data *wd = data;
2428    Eina_List *l2;
2429    Item_Block *itb;
2430    int num, num0;
2431    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2432    if (!wd) return;
2433    wd->update_job = NULL;
2434    num = 0;
2435
2436    evas_event_freeze(evas_object_evas_get(wd->obj));
2437    EINA_INLIST_FOREACH(wd->blocks, itb)
2438      {
2439         Evas_Coord itminw, itminh;
2440         Elm_Gen_Item *it;
2441
2442         if (!itb->updateme)
2443           {
2444              num += itb->count;
2445              if (position)
2446                _item_block_position(itb, num);
2447              continue;
2448           }
2449         num0 = num;
2450         recalc = EINA_FALSE;
2451         EINA_LIST_FOREACH(itb->items, l2, it)
2452           {
2453              if (it->item->updateme)
2454                {
2455                   itminw = it->item->minw;
2456                   itminh = it->item->minh;
2457
2458                   it->item->updateme = EINA_FALSE;
2459                   if (it->realized)
2460                     {
2461                        elm_gen_item_unrealize(it, EINA_FALSE);
2462                        _item_realize(it, num, EINA_FALSE);
2463                        position = EINA_TRUE;
2464                     }
2465                   else
2466                     {
2467                        _item_realize(it, num, EINA_TRUE);
2468                        elm_gen_item_unrealize(it, EINA_TRUE);
2469                     }
2470                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
2471                     recalc = EINA_TRUE;
2472                }
2473              num++;
2474           }
2475         itb->updateme = EINA_FALSE;
2476         if (recalc)
2477           {
2478              position = EINA_TRUE;
2479              itb->changed = EINA_TRUE;
2480              _item_block_recalc(itb, num0, EINA_FALSE);
2481              _item_block_position(itb, num0);
2482           }
2483      }
2484    if (position)
2485      {
2486         if (wd->calc_job) ecore_job_del(wd->calc_job);
2487         wd->calc_job = ecore_job_add(_calc_job, wd);
2488      }
2489    evas_event_thaw(evas_object_evas_get(wd->obj));
2490    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2491 }
2492
2493 static void
2494 _pan_set(Evas_Object *obj,
2495          Evas_Coord   x,
2496          Evas_Coord   y)
2497 {
2498    Pan *sd = evas_object_smart_data_get(obj);
2499    Item_Block *itb;
2500
2501    if (!sd) return;
2502    //   Evas_Coord ow, oh;
2503    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2504    //   ow = sd->wd->minw - ow;
2505    //   if (ow < 0) ow = 0;
2506    //   oh = sd->wd->minh - oh;
2507    //   if (oh < 0) oh = 0;
2508    //   if (x < 0) x = 0;
2509    //   if (y < 0) y = 0;
2510    //   if (x > ow) x = ow;
2511    //   if (y > oh) y = oh;
2512    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2513    sd->wd->pan_x = x;
2514    sd->wd->pan_y = y;
2515
2516    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2517      {
2518         if ((itb->y + itb->h) > y)
2519           {
2520              Elm_Gen_Item *it;
2521              Eina_List *l2;
2522
2523              EINA_LIST_FOREACH(itb->items, l2, it)
2524                {
2525                   if ((itb->y + it->y) >= y)
2526                     {
2527                        sd->wd->anchor_item = it;
2528                        sd->wd->anchor_y = -(itb->y + it->y - y);
2529                        goto done;
2530                     }
2531                }
2532           }
2533      }
2534 done:
2535    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2536 }
2537
2538 static void
2539 _pan_get(Evas_Object *obj,
2540          Evas_Coord  *x,
2541          Evas_Coord  *y)
2542 {
2543    Pan *sd = evas_object_smart_data_get(obj);
2544
2545    if (!sd) return;
2546    if (x) *x = sd->wd->pan_x;
2547    if (y) *y = sd->wd->pan_y;
2548 }
2549
2550 static void
2551 _pan_max_get(Evas_Object *obj,
2552              Evas_Coord  *x,
2553              Evas_Coord  *y)
2554 {
2555    Pan *sd = evas_object_smart_data_get(obj);
2556    Evas_Coord ow, oh;
2557
2558    if (!sd) return;
2559    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2560    ow = sd->wd->minw - ow;
2561    if (ow < 0) ow = 0;
2562    oh = sd->wd->minh - oh;
2563    if (oh < 0) oh = 0;
2564    if (x) *x = ow;
2565    if (y) *y = oh;
2566 }
2567
2568 static void
2569 _pan_min_get(Evas_Object *obj __UNUSED__,
2570              Evas_Coord  *x,
2571              Evas_Coord  *y)
2572 {
2573    if (x) *x = 0;
2574    if (y) *y = 0;
2575 }
2576
2577 static void
2578 _pan_child_size_get(Evas_Object *obj,
2579                     Evas_Coord  *w,
2580                     Evas_Coord  *h)
2581 {
2582    Pan *sd = evas_object_smart_data_get(obj);
2583
2584    if (!sd) return;
2585    if (w) *w = sd->wd->minw;
2586    if (h) *h = sd->wd->minh;
2587 }
2588
2589 static void
2590 _pan_add(Evas_Object *obj)
2591 {
2592    Pan *sd;
2593    Evas_Object_Smart_Clipped_Data *cd;
2594
2595    _pan_sc.add(obj);
2596    cd = evas_object_smart_data_get(obj);
2597    sd = ELM_NEW(Pan);
2598    if (!sd) return;
2599    sd->__clipped_data = *cd;
2600    free(cd);
2601    evas_object_smart_data_set(obj, sd);
2602 }
2603
2604 static void
2605 _pan_del(Evas_Object *obj)
2606 {
2607    Pan *sd = evas_object_smart_data_get(obj);
2608
2609    if (!sd) return;
2610    if (sd->resize_job)
2611      {
2612         ecore_job_del(sd->resize_job);
2613         sd->resize_job = NULL;
2614      }
2615    _pan_sc.del(obj);
2616 }
2617
2618 static void
2619 _pan_resize_job(void *data)
2620 {
2621    Pan *sd = data;
2622    if (!sd) return;
2623    _sizing_eval(sd->wd->obj);
2624    sd->resize_job = NULL;
2625 }
2626
2627 static void
2628 _pan_resize(Evas_Object *obj,
2629             Evas_Coord   w,
2630             Evas_Coord   h)
2631 {
2632    Pan *sd = evas_object_smart_data_get(obj);
2633    Evas_Coord ow, oh;
2634
2635    if (!sd) return;
2636    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2637    if ((ow == w) && (oh == h)) return;
2638    if ((sd->wd->height_for_width) && (ow != w))
2639      {
2640         /* fix me later */
2641         if (sd->resize_job) ecore_job_del(sd->resize_job);
2642         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
2643      }
2644    sd->wd->pan_resized = EINA_TRUE;
2645    evas_object_smart_changed(obj);
2646    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2647    sd->wd->calc_job = NULL;
2648 /* OLD
2649    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2650    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2651  */
2652 }
2653
2654 static void
2655 _pan_calculate(Evas_Object *obj)
2656 {
2657    Pan *sd = evas_object_smart_data_get(obj);
2658    Item_Block *itb;
2659    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2660    int in = 0;
2661    Elm_Gen_Item *git;
2662    Eina_List *l;
2663
2664    if (!sd) return;
2665    evas_event_freeze(evas_object_evas_get(obj));
2666
2667    if (sd->wd->pan_resized)
2668      {
2669         _calc_job(sd->wd);
2670         sd->wd->pan_resized = EINA_FALSE;
2671      }
2672
2673    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2674    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2675    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
2676      {
2677         git->item->want_realize = EINA_FALSE;
2678      }
2679    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2680      {
2681         itb->w = sd->wd->minw;
2682         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
2683                                 itb->y - sd->wd->pan_y + oy,
2684                                 itb->w, itb->h,
2685                                 cvx, cvy, cvw, cvh))
2686           {
2687              if ((!itb->realized) || (itb->changed))
2688                _item_block_realize(itb);
2689              _item_block_position(itb, in);
2690           }
2691         else
2692           {
2693              if (itb->realized) _item_block_unrealize(itb);
2694           }
2695         in += itb->count;
2696      }
2697    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
2698       _group_items_recalc(sd->wd);
2699    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
2700      {
2701         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
2702            sd->wd->reorder_pan_move = EINA_TRUE;
2703         else sd->wd->reorder_pan_move = EINA_FALSE;
2704         evas_object_raise(sd->wd->VIEW(reorder_it));
2705         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
2706         sd->wd->start_time = ecore_loop_time_get();
2707      }
2708    _item_auto_scroll(sd->wd);
2709    evas_event_thaw(evas_object_evas_get(obj));
2710    evas_event_thaw_eval(evas_object_evas_get(obj));
2711 }
2712
2713 static void
2714 _pan_move(Evas_Object *obj,
2715           Evas_Coord   x __UNUSED__,
2716           Evas_Coord   y __UNUSED__)
2717 {
2718    Pan *sd = evas_object_smart_data_get(obj);
2719
2720    if (!sd) return;
2721    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2722    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2723 }
2724
2725 static void
2726 _hold_on(void        *data __UNUSED__,
2727          Evas_Object *obj,
2728          void        *event_info __UNUSED__)
2729 {
2730    Widget_Data *wd = elm_widget_data_get(obj);
2731    if (!wd) return;
2732    elm_smart_scroller_hold_set(wd->scr, 1);
2733 }
2734
2735 static void
2736 _hold_off(void        *data __UNUSED__,
2737           Evas_Object *obj,
2738           void        *event_info __UNUSED__)
2739 {
2740    Widget_Data *wd = elm_widget_data_get(obj);
2741    if (!wd) return;
2742    elm_smart_scroller_hold_set(wd->scr, 0);
2743 }
2744
2745 static void
2746 _freeze_on(void        *data __UNUSED__,
2747            Evas_Object *obj,
2748            void        *event_info __UNUSED__)
2749 {
2750    Widget_Data *wd = elm_widget_data_get(obj);
2751    if (!wd) return;
2752    elm_smart_scroller_freeze_set(wd->scr, 1);
2753 }
2754
2755 static void
2756 _freeze_off(void        *data __UNUSED__,
2757             Evas_Object *obj,
2758             void        *event_info __UNUSED__)
2759 {
2760    Widget_Data *wd = elm_widget_data_get(obj);
2761    if (!wd) return;
2762    elm_smart_scroller_freeze_set(wd->scr, 0);
2763 }
2764
2765 static void
2766 _scr_anim_start(void        *data,
2767                 Evas_Object *obj __UNUSED__,
2768                 void        *event_info __UNUSED__)
2769 {
2770    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
2771 }
2772
2773 static void
2774 _scr_anim_stop(void        *data,
2775                Evas_Object *obj __UNUSED__,
2776                void        *event_info __UNUSED__)
2777 {
2778    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
2779 }
2780
2781 static void
2782 _scr_drag_start(void            *data,
2783                 Evas_Object     *obj __UNUSED__,
2784                 void            *event_info __UNUSED__)
2785 {
2786    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
2787 }
2788
2789 static void
2790 _scr_drag_stop(void            *data,
2791                Evas_Object     *obj __UNUSED__,
2792                void            *event_info __UNUSED__)
2793 {
2794    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
2795 }
2796
2797 static void
2798 _edge_left(void        *data,
2799            Evas_Object *scr __UNUSED__,
2800            void        *event_info __UNUSED__)
2801 {
2802    Evas_Object *obj = data;
2803    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_LEFT, NULL);
2804    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
2805 }
2806
2807 static void
2808 _edge_right(void        *data,
2809             Evas_Object *scr __UNUSED__,
2810             void        *event_info __UNUSED__)
2811 {
2812    Evas_Object *obj = data;
2813    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_RIGHT, NULL);
2814    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
2815 }
2816
2817 static void
2818 _edge_top(void        *data,
2819           Evas_Object *scr __UNUSED__,
2820           void        *event_info __UNUSED__)
2821 {
2822    Evas_Object *obj = data;
2823    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_TOP, NULL);
2824    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
2825 }
2826
2827 static void
2828 _edge_bottom(void        *data,
2829              Evas_Object *scr __UNUSED__,
2830              void        *event_info __UNUSED__)
2831 {
2832    Evas_Object *obj = data;
2833    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_BOTTOM, NULL);
2834    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
2835 }
2836
2837 static void
2838 _mode_item_realize(Elm_Gen_Item *it)
2839 {
2840    char buf[1024];
2841
2842    if ((it->item->mode_view) || (it->delete_me)) return;
2843
2844    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2845    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
2846    edje_object_scale_set(it->item->mode_view,
2847                          elm_widget_scale_get(WIDGET(it)) *
2848                          _elm_config->scale);
2849    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
2850    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
2851
2852    strncpy(buf, "item", sizeof(buf));
2853    if (it->wd->compress)
2854      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
2855
2856    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
2857    strncat(buf, "/", sizeof(buf) - strlen(buf));
2858    strncat(buf, it->wd->mode_item_style, sizeof(buf) - strlen(buf));
2859
2860    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
2861                          elm_widget_style_get(WIDGET(it)));
2862    edje_object_mirrored_set(it->item->mode_view,
2863                             elm_widget_mirrored_get(WIDGET(it)));
2864
2865    /* signal callback add */
2866    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
2867                                   _mouse_down, it);
2868    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
2869                                   _mouse_up, it);
2870    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
2871                                   _mouse_move, it);
2872
2873    /* label_get, icon_get, state_get */
2874    /* FIXME: If you see that assert, please notify us and we
2875       will clean our mess */
2876    assert(eina_list_count(it->item->mode_icon_objs) == 0);
2877
2878    _item_label_realize(it, it->item->mode_view, &it->item->mode_labels);
2879    it->item->mode_icon_objs = _item_icon_realize(it,
2880                                            it->item->mode_view,
2881                                            &it->item->mode_icons);
2882    _item_state_realize(it, it->item->mode_view, &it->item->mode_states);
2883
2884    edje_object_part_swallow(it->item->mode_view,
2885                             edje_object_data_get(it->item->mode_view, "mode_part"),
2886                             VIEW(it));
2887
2888    it->want_unrealize = EINA_FALSE;
2889    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2890    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2891 }
2892
2893 static void
2894 _mode_item_unrealize(Elm_Gen_Item *it)
2895 {
2896    Widget_Data *wd = it->wd;
2897    Evas_Object *icon;
2898    if (!it->item->mode_view) return;
2899
2900    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2901    elm_widget_stringlist_free(it->item->mode_labels);
2902    it->item->mode_labels = NULL;
2903    elm_widget_stringlist_free(it->item->mode_icons);
2904    it->item->mode_icons = NULL;
2905    elm_widget_stringlist_free(it->item->mode_states);
2906
2907    EINA_LIST_FREE(it->item->mode_icon_objs, icon)
2908      evas_object_del(icon);
2909
2910    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
2911    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
2912    evas_object_del(it->item->mode_view);
2913    it->item->mode_view = NULL;
2914
2915    if (wd->mode_item == it)
2916      wd->mode_item = NULL;
2917    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2918    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2919 }
2920
2921 static void
2922 _item_mode_set(Elm_Gen_Item *it)
2923 {
2924    if (!it) return;
2925    Widget_Data *wd = it->wd;
2926    if (!wd) return;
2927    char buf[1024];
2928
2929    wd->mode_item = it;
2930    it->item->nocache = EINA_TRUE;
2931
2932    if (wd->scr_hold_timer)
2933      {
2934         ecore_timer_del(wd->scr_hold_timer);
2935         wd->scr_hold_timer = NULL;
2936      }
2937    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
2938    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
2939
2940    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2941    _mode_item_realize(it);
2942    if (it->item->group_item)
2943      evas_object_raise(it->item->VIEW(group_item));
2944    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
2945    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2946    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2947
2948    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
2949    edje_object_signal_emit(it->item->mode_view, buf, "elm");
2950 }
2951
2952 static void
2953 _item_mode_unset(Widget_Data *wd)
2954 {
2955    if (!wd) return;
2956    if (!wd->mode_item) return;
2957    char buf[1024], buf2[1024];
2958    Elm_Gen_Item *it;
2959
2960    it = wd->mode_item;
2961    it->item->nocache = EINA_TRUE;
2962
2963    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type);
2964    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type);
2965
2966    edje_object_signal_emit(it->item->mode_view, buf, "elm");
2967    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
2968
2969    wd->mode_item = NULL;
2970 }
2971
2972 static void
2973 _item_auto_scroll(Widget_Data *wd)
2974 {
2975    if (!wd) return;
2976    Elm_Gen_Item  *it;
2977    Eina_List *l;
2978    Evas_Coord ox, oy, ow, oh;
2979
2980    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
2981      {
2982         evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
2983         if (wd->expanded_item->item->scrl_y > (oh + oy) / 2)
2984           {
2985              EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
2986                 elm_genlist_item_bring_in(it);
2987           }
2988         wd->auto_scroll_enabled = EINA_FALSE;
2989      }
2990 }
2991
2992 EAPI Evas_Object *
2993 elm_genlist_add(Evas_Object *parent)
2994 {
2995    Evas_Object *obj;
2996    Evas *e;
2997    Widget_Data *wd;
2998    Evas_Coord minw, minh;
2999    static Evas_Smart *smart = NULL;
3000
3001    if (!smart)
3002      {
3003         static Evas_Smart_Class sc;
3004
3005         evas_object_smart_clipped_smart_set(&_pan_sc);
3006         sc = _pan_sc;
3007         sc.name = "elm_genlist_pan";
3008         sc.version = EVAS_SMART_CLASS_VERSION;
3009         sc.add = _pan_add;
3010         sc.del = _pan_del;
3011         sc.resize = _pan_resize;
3012         sc.move = _pan_move;
3013         sc.calculate = _pan_calculate;
3014         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3015      }
3016
3017    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3018
3019    ELM_SET_WIDTYPE(widtype, "genlist");
3020    ELM_GEN_SETUP(wd);
3021    elm_widget_type_set(obj, "genlist");
3022    elm_widget_sub_object_add(parent, obj);
3023    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3024    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3025    elm_widget_data_set(obj, wd);
3026    elm_widget_del_hook_set(obj, _del_hook);
3027    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3028    elm_widget_theme_hook_set(obj, _theme_hook);
3029    elm_widget_can_focus_set(obj, EINA_TRUE);
3030    elm_widget_event_hook_set(obj, _event_hook);
3031    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3032    elm_widget_translate_hook_set(obj, _translate_hook);
3033
3034    wd->scr = elm_smart_scroller_add(e);
3035    elm_smart_scroller_widget_set(wd->scr, obj);
3036    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3037                                        elm_widget_style_get(obj));
3038    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3039                                        _elm_config->thumbscroll_bounce_enable);
3040    elm_widget_resize_object_set(obj, wd->scr);
3041
3042    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3043    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3044    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3045    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3046    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3047    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3048    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3049    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3050
3051    wd->obj = obj;
3052    wd->mode = ELM_LIST_SCROLL;
3053    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3054    wd->item_cache_max = wd->max_items_per_block * 2;
3055    wd->longpress_timeout = _elm_config->longpress_timeout;
3056
3057    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3058    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3059    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3060    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3061
3062    wd->pan_smart = evas_object_smart_add(e, smart);
3063    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3064    wd->pan->wd = wd;
3065
3066    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3067                                      _pan_set, _pan_get, _pan_max_get,
3068                                      _pan_min_get, _pan_child_size_get);
3069
3070    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3071                              &minw, &minh);
3072    evas_object_size_hint_min_set(obj, minw, minh);
3073
3074    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3075
3076    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3077    _sizing_eval(obj);
3078    return obj;
3079 }
3080
3081 static Elm_Gen_Item *
3082 _item_new(Widget_Data                  *wd,
3083           const Elm_Genlist_Item_Class *itc,
3084           const void                   *data,
3085           Elm_Gen_Item                 *parent,
3086           Elm_Genlist_Item_Flags        flags,
3087           Evas_Smart_Cb                 func,
3088           const void                   *func_data)
3089 {
3090    Elm_Gen_Item *it;
3091
3092    it = elm_gen_item_new(wd, itc, data, parent, func, func_data);
3093    if (!it) return NULL;
3094    it->item = ELM_NEW(Elm_Gen_Item_Type);
3095    it->item->flags = flags;
3096    if (flags & ELM_GENLIST_ITEM_GROUP) it->group++;
3097    it->item->expanded_depth = 0;
3098    elm_widget_item_del_cb_set(it, _item_del_hook);
3099    ELM_GEN_ITEM_SETUP(it);
3100    if (it->parent)
3101      {
3102         if (it->parent->group)
3103           it->item->group_item = parent;
3104         else if (it->parent->item->group_item)
3105           it->item->group_item = it->parent->item->group_item;
3106      }
3107    return it;
3108 }
3109
3110 static void
3111 _item_block_add(Widget_Data      *wd,
3112                 Elm_Gen_Item *it)
3113 {
3114    Item_Block *itb = NULL;
3115
3116    if (!it->item->rel)
3117      {
3118 newblock:
3119         if (it->item->rel)
3120           {
3121              itb = calloc(1, sizeof(Item_Block));
3122              if (!itb) return;
3123              itb->wd = wd;
3124              if (!it->item->rel->item->block)
3125                {
3126                   wd->blocks =
3127                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3128                   itb->items = eina_list_append(itb->items, it);
3129                }
3130              else
3131                {
3132                   if (it->item->before)
3133                     {
3134                        wd->blocks = eina_inlist_prepend_relative
3135                            (wd->blocks, EINA_INLIST_GET(itb),
3136                            EINA_INLIST_GET(it->item->rel->item->block));
3137                        itb->items =
3138                          eina_list_prepend_relative(itb->items, it, it->item->rel);
3139                     }
3140                   else
3141                     {
3142                        wd->blocks = eina_inlist_append_relative
3143                            (wd->blocks, EINA_INLIST_GET(itb),
3144                            EINA_INLIST_GET(it->item->rel->item->block));
3145                        itb->items =
3146                          eina_list_append_relative(itb->items, it, it->item->rel);
3147                     }
3148                }
3149           }
3150         else
3151           {
3152              if (it->item->before)
3153                {
3154                   if (wd->blocks)
3155                     {
3156                        itb = (Item_Block *)(wd->blocks);
3157                        if (itb->count >= wd->max_items_per_block)
3158                          {
3159                             itb = calloc(1, sizeof(Item_Block));
3160                             if (!itb) return;
3161                             itb->wd = wd;
3162                             wd->blocks =
3163                               eina_inlist_prepend(wd->blocks,
3164                                                   EINA_INLIST_GET(itb));
3165                          }
3166                     }
3167                   else
3168                     {
3169                        itb = calloc(1, sizeof(Item_Block));
3170                        if (!itb) return;
3171                        itb->wd = wd;
3172                        wd->blocks =
3173                          eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3174                     }
3175                   itb->items = eina_list_prepend(itb->items, it);
3176                }
3177              else
3178                {
3179                   if (wd->blocks)
3180                     {
3181                        itb = (Item_Block *)(wd->blocks->last);
3182                        if (itb->count >= wd->max_items_per_block)
3183                          {
3184                             itb = calloc(1, sizeof(Item_Block));
3185                             if (!itb) return;
3186                             itb->wd = wd;
3187                             wd->blocks =
3188                               eina_inlist_append(wd->blocks,
3189                                                  EINA_INLIST_GET(itb));
3190                          }
3191                     }
3192                   else
3193                     {
3194                        itb = calloc(1, sizeof(Item_Block));
3195                        if (!itb) return;
3196                        itb->wd = wd;
3197                        wd->blocks =
3198                          eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3199                     }
3200                   itb->items = eina_list_append(itb->items, it);
3201                }
3202           }
3203      }
3204    else
3205      {
3206         itb = it->item->rel->item->block;
3207         if (!itb) goto newblock;
3208         if (it->item->before)
3209           itb->items = eina_list_prepend_relative(itb->items, it, it->item->rel);
3210         else
3211           itb->items = eina_list_append_relative(itb->items, it, it->item->rel);
3212      }
3213    itb->count++;
3214    itb->changed = EINA_TRUE;
3215    it->item->block = itb;
3216    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3217    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3218    if (it->item->rel)
3219      {
3220         it->item->rel->relcount--;
3221         if ((it->item->rel->delete_me) && (!it->item->rel->relcount))
3222           _item_del(it->item->rel);
3223         it->item->rel = NULL;
3224      }
3225    if (itb->count > itb->wd->max_items_per_block)
3226      {
3227         int newc;
3228         Item_Block *itb2;
3229         Elm_Gen_Item *it2;
3230
3231         newc = itb->count / 2;
3232         itb2 = calloc(1, sizeof(Item_Block));
3233         if (!itb2) return;
3234         itb2->wd = wd;
3235         wd->blocks =
3236           eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3237                                       EINA_INLIST_GET(itb));
3238         itb2->changed = EINA_TRUE;
3239         while ((itb->count > newc) && (itb->items))
3240           {
3241              Eina_List *l;
3242
3243              l = eina_list_last(itb->items);
3244              it2 = l->data;
3245              itb->items = eina_list_remove_list(itb->items, l);
3246              itb->count--;
3247
3248              itb2->items = eina_list_prepend(itb2->items, it2);
3249              it2->item->block = itb2;
3250              itb2->count++;
3251           }
3252      }
3253 }
3254
3255 static int
3256 _queue_process(Widget_Data *wd)
3257 {
3258    int n;
3259    Eina_Bool showme = EINA_FALSE;
3260    double t0, t;
3261
3262    t0 = ecore_time_get();
3263    //evas_event_freeze(evas_object_evas_get(wd->obj));
3264    for (n = 0; (wd->queue) && (n < 128); n++)
3265      {
3266         Elm_Gen_Item *it;
3267
3268         it = wd->queue->data;
3269         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3270         it->item->queued = EINA_FALSE;
3271         _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 (flags & ELM_GENLIST_ITEM_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 (flags & ELM_GENLIST_ITEM_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 ((flags & ELM_GENLIST_ITEM_GROUP) &&
3517             (after->item->flags & ELM_GENLIST_ITEM_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 ((flags & ELM_GENLIST_ITEM_GROUP) &&
3558             (before->item->flags & ELM_GENLIST_ITEM_GROUP))
3559           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
3560                                                        before);
3561      }
3562    else
3563      {
3564         it->parent->item->items = eina_list_prepend_relative(it->parent->item->items, it,
3565                                                        before);
3566      }
3567    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3568                                             EINA_INLIST_GET(before));
3569    it->item->rel = before;
3570    it->item->rel->relcount++;
3571    it->item->before = EINA_TRUE;
3572    _item_queue(wd, it);
3573    return it;
3574 }
3575
3576 EAPI Elm_Gen_Item *
3577 elm_genlist_item_direct_sorted_insert(Evas_Object                  *obj,
3578                                       const Elm_Genlist_Item_Class *itc,
3579                                       const void                   *data,
3580                                       Elm_Gen_Item             *parent,
3581                                       Elm_Genlist_Item_Flags        flags,
3582                                       Eina_Compare_Cb               comp,
3583                                       Evas_Smart_Cb                 func,
3584                                       const void                   *func_data)
3585 {
3586    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3587    Widget_Data *wd = elm_widget_data_get(obj);
3588    if (!wd) return NULL;
3589    Elm_Gen_Item *rel = NULL;
3590    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3591                                     func_data);
3592    if (!it) return NULL;
3593
3594    _elm_genlist_item_compare_cb = comp;
3595
3596    if (it->parent)
3597      {
3598         Eina_List *l;
3599         int cmp_result;
3600
3601         l = eina_list_search_sorted_near_list(it->parent->item->items,
3602                                               _elm_genlist_item_list_compare, it,
3603                                               &cmp_result);
3604         if (l)
3605           rel = eina_list_data_get(l);
3606         else
3607           rel = it->parent;
3608
3609         if (cmp_result >= 0)
3610           {
3611              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
3612              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3613              it->item->before = EINA_FALSE;
3614           }
3615         else if (cmp_result < 0)
3616           {
3617              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
3618              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3619              it->item->before = EINA_TRUE;
3620           }
3621      }
3622    else
3623      {
3624         if (!wd->state)
3625           {
3626              wd->state = eina_inlist_sorted_state_new();
3627           }
3628
3629         if (flags & ELM_GENLIST_ITEM_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->icon_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    Evas_Object *icon;
4154    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4155    EINA_LIST_FREE(it->icon_objs, icon)
4156      {
4157         elm_widget_sub_object_del(WIDGET(it), icon);
4158         evas_object_smart_member_del(icon);
4159         evas_object_hide(icon);
4160      }
4161 }
4162
4163 EAPI const Evas_Object *
4164 elm_genlist_item_object_get(const Elm_Gen_Item *it)
4165 {
4166    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4167    return VIEW(it);
4168 }
4169
4170 EAPI void
4171 elm_genlist_item_update(Elm_Gen_Item *it)
4172 {
4173    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4174    if (!it->item->block) return;
4175    if (it->delete_me) return;
4176    it->item->mincalcd = EINA_FALSE;
4177    it->item->updateme = EINA_TRUE;
4178    it->item->block->updateme = EINA_TRUE;
4179    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4180    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4181 }
4182
4183 EAPI void
4184 elm_genlist_item_item_class_update(Elm_Gen_Item             *it,
4185                                    const Elm_Genlist_Item_Class *itc)
4186 {
4187    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4188    if (!it->item->block) return;
4189    EINA_SAFETY_ON_NULL_RETURN(itc);
4190    if (it->delete_me) return;
4191    it->itc = itc;
4192    it->item->nocache = EINA_TRUE;
4193    elm_genlist_item_update(it);
4194 }
4195
4196 EAPI const Elm_Genlist_Item_Class *
4197 elm_genlist_item_item_class_get(const Elm_Gen_Item *it)
4198 {
4199    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4200    if (it->delete_me) return NULL;
4201    return it->itc;
4202 }
4203
4204 static Evas_Object *
4205 _elm_genlist_item_label_create(void        *data,
4206                                Evas_Object *obj __UNUSED__,
4207                                Evas_Object *tooltip,
4208                                void        *it __UNUSED__)
4209 {
4210    Evas_Object *label = elm_label_add(tooltip);
4211    if (!label)
4212      return NULL;
4213    elm_object_style_set(label, "tooltip");
4214    elm_object_text_set(label, data);
4215    return label;
4216 }
4217
4218 static void
4219 _elm_genlist_item_label_del_cb(void        *data,
4220                                Evas_Object *obj __UNUSED__,
4221                                void        *event_info __UNUSED__)
4222 {
4223    eina_stringshare_del(data);
4224 }
4225
4226 EAPI void
4227 elm_genlist_item_tooltip_text_set(Elm_Gen_Item *it,
4228                                   const char       *text)
4229 {
4230    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4231    text = eina_stringshare_add(text);
4232    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4233                                            text,
4234                                            _elm_genlist_item_label_del_cb);
4235 }
4236
4237 EAPI void
4238 elm_genlist_item_tooltip_content_cb_set(Elm_Gen_Item           *it,
4239                                         Elm_Tooltip_Item_Content_Cb func,
4240                                         const void                 *data,
4241                                         Evas_Smart_Cb               del_cb)
4242 {
4243    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, error);
4244
4245    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
4246      return;
4247
4248    if (it->tooltip.del_cb)
4249      it->tooltip.del_cb((void *)it->tooltip.data,
4250                           WIDGET(it), it);
4251
4252    it->tooltip.content_cb = func;
4253    it->tooltip.data = data;
4254    it->tooltip.del_cb = del_cb;
4255
4256    if (VIEW(it))
4257      {
4258         elm_widget_item_tooltip_content_cb_set(it,
4259                                                it->tooltip.content_cb,
4260                                                it->tooltip.data, NULL);
4261         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
4262         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
4263      }
4264
4265    return;
4266
4267 error:
4268    if (del_cb) del_cb((void *)data, NULL, NULL);
4269 }
4270
4271 EAPI void
4272 elm_genlist_item_tooltip_unset(Elm_Gen_Item *it)
4273 {
4274    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4275    if ((VIEW(it)) && (it->tooltip.content_cb))
4276      elm_widget_item_tooltip_unset(it);
4277
4278    if (it->tooltip.del_cb)
4279      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
4280    it->tooltip.del_cb = NULL;
4281    it->tooltip.content_cb = NULL;
4282    it->tooltip.data = NULL;
4283    it->tooltip.free_size = EINA_FALSE;
4284    if (it->tooltip.style)
4285      elm_genlist_item_tooltip_style_set(it, NULL);
4286 }
4287
4288 EAPI void
4289 elm_genlist_item_tooltip_style_set(Elm_Gen_Item *it,
4290                                    const char       *style)
4291 {
4292    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4293    eina_stringshare_replace(&it->tooltip.style, style);
4294    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
4295 }
4296
4297 EAPI const char *
4298 elm_genlist_item_tooltip_style_get(const Elm_Gen_Item *it)
4299 {
4300    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4301    return it->tooltip.style;
4302 }
4303
4304 EAPI Eina_Bool
4305 elm_genlist_item_tooltip_size_restrict_disable(Elm_Gen_Item *it, Eina_Bool disable)
4306 {
4307    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4308    it->tooltip.free_size = disable;
4309    if (VIEW(it)) return elm_widget_item_tooltip_size_restrict_disable(it, disable);
4310    return EINA_TRUE;
4311 }
4312
4313 EAPI Eina_Bool
4314 elm_genlist_item_tooltip_size_restrict_disabled_get(const Elm_Gen_Item *it)
4315 {
4316    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4317    return it->tooltip.free_size;
4318 }
4319
4320 EAPI void
4321 elm_genlist_item_cursor_set(Elm_Gen_Item *it,
4322                             const char       *cursor)
4323 {
4324    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4325    eina_stringshare_replace(&it->mouse_cursor, cursor);
4326    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
4327 }
4328
4329 EAPI const char *
4330 elm_genlist_item_cursor_get(const Elm_Gen_Item *it)
4331 {
4332    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4333    return elm_widget_item_cursor_get(it);
4334 }
4335
4336 EAPI void
4337 elm_genlist_item_cursor_unset(Elm_Gen_Item *it)
4338 {
4339    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4340    if (!it->mouse_cursor)
4341      return;
4342
4343    if (VIEW(it))
4344      elm_widget_item_cursor_unset(it);
4345
4346    eina_stringshare_del(it->mouse_cursor);
4347    it->mouse_cursor = NULL;
4348 }
4349
4350 EAPI void
4351 elm_genlist_item_cursor_style_set(Elm_Gen_Item *it,
4352                                   const char       *style)
4353 {
4354    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4355    elm_widget_item_cursor_style_set(it, style);
4356 }
4357
4358 EAPI const char *
4359 elm_genlist_item_cursor_style_get(const Elm_Gen_Item *it)
4360 {
4361    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4362    return elm_widget_item_cursor_style_get(it);
4363 }
4364
4365 EAPI void
4366 elm_genlist_item_cursor_engine_only_set(Elm_Gen_Item *it,
4367                                         Eina_Bool         engine_only)
4368 {
4369    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4370    elm_widget_item_cursor_engine_only_set(it, engine_only);
4371 }
4372
4373 EAPI Eina_Bool
4374 elm_genlist_item_cursor_engine_only_get(const Elm_Gen_Item *it)
4375 {
4376    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4377    return elm_widget_item_cursor_engine_only_get(it);
4378 }
4379
4380 EAPI void
4381 elm_genlist_horizontal_set(Evas_Object  *obj,
4382                                 Elm_List_Mode mode)
4383 {
4384    ELM_CHECK_WIDTYPE(obj, widtype);
4385    Widget_Data *wd = elm_widget_data_get(obj);
4386    if (!wd) return;
4387    if (wd->mode == mode) return;
4388    wd->mode = mode;
4389    _sizing_eval(obj);
4390 }
4391
4392 EAPI void
4393 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4394                                 Elm_List_Mode mode)
4395 {
4396    elm_genlist_horizontal_set(obj, mode);
4397 }
4398
4399 EAPI Elm_List_Mode
4400 elm_genlist_horizontal_get(const Evas_Object *obj)
4401 {
4402    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4403    Widget_Data *wd = elm_widget_data_get(obj);
4404    if (!wd) return ELM_LIST_LAST;
4405    return wd->mode;
4406 }
4407
4408 EAPI Elm_List_Mode
4409 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
4410 {
4411    return elm_genlist_horizontal_get(obj);
4412 }
4413
4414 EAPI void
4415 elm_genlist_always_select_mode_set(Evas_Object *obj,
4416                                    Eina_Bool    always_select)
4417 {
4418    elm_gen_always_select_mode_set(obj, always_select);
4419 }
4420
4421 EAPI Eina_Bool
4422 elm_genlist_always_select_mode_get(const Evas_Object *obj)
4423 {
4424    return elm_gen_always_select_mode_get(obj);
4425 }
4426
4427 EAPI void
4428 elm_genlist_no_select_mode_set(Evas_Object *obj,
4429                                Eina_Bool    no_select)
4430 {
4431    elm_gen_no_select_mode_set(obj, no_select);
4432 }
4433
4434 EAPI Eina_Bool
4435 elm_genlist_no_select_mode_get(const Evas_Object *obj)
4436 {
4437    return elm_gen_no_select_mode_get(obj);
4438 }
4439
4440 EAPI void
4441 elm_genlist_compress_mode_set(Evas_Object *obj,
4442                               Eina_Bool    compress)
4443 {
4444    ELM_CHECK_WIDTYPE(obj, widtype);
4445    Widget_Data *wd = elm_widget_data_get(obj);
4446    if (!wd) return;
4447    wd->compress = compress;
4448    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
4449 }
4450
4451 EAPI Eina_Bool
4452 elm_genlist_compress_mode_get(const Evas_Object *obj)
4453 {
4454    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4455    Widget_Data *wd = elm_widget_data_get(obj);
4456    if (!wd) return EINA_FALSE;
4457    return wd->compress;
4458 }
4459
4460 EAPI void
4461 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
4462                                       Eina_Bool    height_for_width)
4463 {
4464    ELM_CHECK_WIDTYPE(obj, widtype);
4465    Widget_Data *wd = elm_widget_data_get(obj);
4466    if (!wd) return;
4467    wd->height_for_width = !!height_for_width;
4468    if (wd->height_for_width)
4469      {
4470         elm_genlist_homogeneous_set(obj, EINA_FALSE);
4471         elm_genlist_compress_mode_set(obj, EINA_TRUE);
4472      }
4473 }
4474
4475 EAPI Eina_Bool
4476 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
4477 {
4478    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4479    Widget_Data *wd = elm_widget_data_get(obj);
4480    if (!wd) return EINA_FALSE;
4481    return wd->height_for_width;
4482 }
4483
4484 EAPI void
4485 elm_genlist_bounce_set(Evas_Object *obj,
4486                        Eina_Bool    h_bounce,
4487                        Eina_Bool    v_bounce)
4488 {
4489    elm_gen_bounce_set(obj, h_bounce, v_bounce);
4490 }
4491
4492 EAPI void
4493 elm_genlist_bounce_get(const Evas_Object *obj,
4494                        Eina_Bool         *h_bounce,
4495                        Eina_Bool         *v_bounce)
4496 {
4497    elm_gen_bounce_get(obj, h_bounce, v_bounce);
4498 }
4499
4500 EAPI void
4501 elm_genlist_homogeneous_set(Evas_Object *obj,
4502                             Eina_Bool    homogeneous)
4503 {
4504    ELM_CHECK_WIDTYPE(obj, widtype);
4505    Widget_Data *wd = elm_widget_data_get(obj);
4506    if (!wd) return;
4507    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
4508    wd->homogeneous = homogeneous;
4509 }
4510
4511 EAPI Eina_Bool
4512 elm_genlist_homogeneous_get(const Evas_Object *obj)
4513 {
4514    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4515    Widget_Data *wd = elm_widget_data_get(obj);
4516    if (!wd) return EINA_FALSE;
4517    return wd->homogeneous;
4518 }
4519
4520 EAPI void
4521 elm_genlist_block_count_set(Evas_Object *obj,
4522                             int          n)
4523 {
4524    ELM_CHECK_WIDTYPE(obj, widtype);
4525    Widget_Data *wd = elm_widget_data_get(obj);
4526    if (!wd) return;
4527    wd->max_items_per_block = n;
4528    wd->item_cache_max = wd->max_items_per_block * 2;
4529    _item_cache_clean(wd);
4530 }
4531
4532 EAPI int
4533 elm_genlist_block_count_get(const Evas_Object *obj)
4534 {
4535    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4536    Widget_Data *wd = elm_widget_data_get(obj);
4537    if (!wd) return 0;
4538    return wd->max_items_per_block;
4539 }
4540
4541 EAPI void
4542 elm_genlist_longpress_timeout_set(Evas_Object *obj,
4543                                   double       timeout)
4544 {
4545    ELM_CHECK_WIDTYPE(obj, widtype);
4546    Widget_Data *wd = elm_widget_data_get(obj);
4547    if (!wd) return;
4548    wd->longpress_timeout = timeout;
4549 }
4550
4551 EAPI double
4552 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
4553 {
4554    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4555    Widget_Data *wd = elm_widget_data_get(obj);
4556    if (!wd) return 0;
4557    return wd->longpress_timeout;
4558 }
4559
4560 EAPI void
4561 elm_genlist_scroller_policy_set(Evas_Object        *obj,
4562                                 Elm_Scroller_Policy policy_h,
4563                                 Elm_Scroller_Policy policy_v)
4564 {
4565    ELM_CHECK_WIDTYPE(obj, widtype);
4566    Widget_Data *wd = elm_widget_data_get(obj);
4567    if ((!wd) || (!wd->scr)) return;
4568    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
4569        (policy_v >= ELM_SCROLLER_POLICY_LAST))
4570      return;
4571    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
4572 }
4573
4574 EAPI void
4575 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
4576                                 Elm_Scroller_Policy *policy_h,
4577                                 Elm_Scroller_Policy *policy_v)
4578 {
4579    ELM_CHECK_WIDTYPE(obj, widtype);
4580    Widget_Data *wd = elm_widget_data_get(obj);
4581    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
4582    if ((!wd) || (!wd->scr)) return;
4583    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
4584    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
4585    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
4586 }
4587
4588 EAPI void
4589 elm_genlist_realized_items_update(Evas_Object *obj)
4590 {
4591    ELM_CHECK_WIDTYPE(obj, widtype);
4592
4593    Eina_List *list, *l;
4594    Elm_Gen_Item *it;
4595
4596    list = elm_genlist_realized_items_get(obj);
4597    EINA_LIST_FOREACH(list, l, it)
4598      elm_genlist_item_update(it);
4599 }
4600
4601 EAPI void
4602 elm_genlist_item_mode_set(Elm_Gen_Item *it,
4603                           const char       *mode_type,
4604                           Eina_Bool         mode_set)
4605 {
4606    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4607    Widget_Data *wd = it->wd;
4608    Eina_List *l;
4609    Elm_Gen_Item *it2;
4610
4611    if (!wd) return;
4612    if (!mode_type) return;
4613    if ((it->delete_me) || (it->disabled)) return;
4614
4615    if ((wd->mode_item == it) &&
4616        (!strcmp(mode_type, wd->mode_type)) &&
4617        (mode_set))
4618       return;
4619    if (!wd->mode_item_style) return;
4620    it->mode_set = mode_set;
4621
4622    if (wd->multi)
4623      {
4624         EINA_LIST_FOREACH(wd->selected, l, it2)
4625           if (it2->realized)
4626             elm_gen_item_selected_set(it2, EINA_FALSE);
4627      }
4628    else
4629      {
4630         it2 = elm_genlist_selected_item_get(wd->obj);
4631         if ((it2) && (it2->realized))
4632           elm_gen_item_selected_set(it2, EINA_FALSE);
4633      }
4634
4635    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
4636        (mode_set) ||
4637        ((it == wd->mode_item) && (!mode_set)))
4638      _item_mode_unset(wd);
4639
4640    eina_stringshare_replace(&wd->mode_type, mode_type);
4641    if (mode_set) _item_mode_set(it);
4642 }
4643
4644
4645 EAPI const char *
4646 elm_genlist_mode_item_style_get(const Evas_Object *obj)
4647 {
4648    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4649    Widget_Data *wd = elm_widget_data_get(obj);
4650    if (!wd) return NULL;
4651    return wd->mode_item_style;
4652 }
4653
4654 EAPI void
4655 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
4656 {
4657    ELM_CHECK_WIDTYPE(obj, widtype);
4658    Widget_Data *wd = elm_widget_data_get(obj);
4659    if (!wd) return;
4660    if ((style == wd->mode_item_style) || (style && wd->mode_item_style &&
4661        (!strcmp(style, wd->mode_item_style))))
4662      return;
4663    eina_stringshare_replace(&wd->mode_item_style, style);
4664    elm_genlist_realized_items_update(obj);
4665 }
4666
4667 EAPI const char *
4668 elm_genlist_mode_get(const Evas_Object *obj)
4669 {
4670    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4671    Widget_Data *wd = elm_widget_data_get(obj);
4672    if (!wd) return NULL;
4673    return wd->mode_type;
4674 }
4675
4676 EAPI const Elm_Gen_Item *
4677 elm_genlist_mode_item_get(const Evas_Object *obj)
4678 {
4679    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4680    Widget_Data *wd = elm_widget_data_get(obj);
4681    if (!wd) return NULL;
4682    return wd->mode_item;
4683 }
4684
4685 EAPI void
4686 elm_genlist_reorder_mode_set(Evas_Object *obj,
4687                              Eina_Bool    reorder_mode)
4688 {
4689    ELM_CHECK_WIDTYPE(obj, widtype);
4690    Widget_Data *wd = elm_widget_data_get(obj);
4691    if (!wd) return;
4692    wd->reorder_mode = reorder_mode;
4693 }
4694
4695 EAPI Eina_Bool
4696 elm_genlist_reorder_mode_get(const Evas_Object *obj)
4697 {
4698    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4699    Widget_Data *wd = elm_widget_data_get(obj);
4700    if (!wd) return EINA_FALSE;
4701    return wd->reorder_mode;
4702 }