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