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