9d3f8cdbdea2ff09b2db39b59589778ca741c62e
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2 #include <fnmatch.h>
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_gen_common.h"
8
9 // internally allocated
10 #define CLASS_ALLOCATED 0x3a70f11f
11
12 #define MAX_ITEMS_PER_BLOCK 32
13 #define REORDER_EFFECT_TIME 0.5
14
15 #define ELM_GEN_SETUP(wd) \
16    (wd)->calc_cb = (Ecore_Cb)_calc_job; \
17    (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
18    (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
19
20 #define ELM_GEN_ITEM_SETUP(it) \
21    (it)->del_cb = (Ecore_Cb)_item_del; \
22    (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
23    (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
24    (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
25    (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
26
27 #define ELM_GENLIST_CHECK_ITC_VER(itc) \
28    do \
29      { \
30         if (!itc) \
31           { \
32              ERR("Genlist_Item_Class(itc) is NULL"); \
33              return; \
34           } \
35         if ((itc->version != ELM_GENLIST_ITEM_CLASS_VERSION) && \
36             (itc->version != CLASS_ALLOCATED)) \
37           { \
38              ERR("Genlist_Item_Class version mismatched! current = (%d), required = (%d) or (%d)", itc->version, ELM_GENLIST_ITEM_CLASS_VERSION, CLASS_ALLOCATED); \
39              return; \
40           } \
41      } \
42    while(0)
43
44 typedef struct _Item_Block  Item_Block;
45 typedef struct _Item_Cache  Item_Cache;
46
47 struct Elm_Gen_Item_Type
48 {
49    Elm_Gen_Item                 *it;
50    Item_Block                   *block;
51    Eina_List                    *items;
52    Evas_Coord                    w, h, minw, minh;
53    Elm_Gen_Item                 *group_item;
54    Elm_Genlist_Item_Type        type;
55    Eina_List                    *mode_texts, *mode_contents, *mode_states, *mode_content_objs;
56    Eina_List                    *edit_texts, *edit_contents, *edit_states, *edit_content_objs;
57    Ecore_Timer                  *swipe_timer;
58    Evas_Coord                    scrl_x, scrl_y, old_scrl_y;
59
60    Elm_Gen_Item                 *rel;
61    Evas_Object                  *mode_view;
62    int                           expanded_depth;
63    int                           order_num_in;
64
65    Eina_Bool                     before : 1;
66
67    Eina_Bool                     want_realize : 1;
68    Eina_Bool                     expanded : 1;
69    Eina_Bool                     mincalcd : 1;
70    Eina_Bool                     queued : 1;
71    Eina_Bool                     showme : 1;
72    Eina_Bool                     updateme : 1;
73    Eina_Bool                     nocache : 1; /* do not use cache for this item */
74    Eina_Bool                     nocache_once : 1; /* do not use cache for this item only once */
75    Eina_Bool                     stacking_even : 1;
76    Eina_Bool                     nostacking : 1;
77    Eina_Bool                     move_effect_enabled : 1;
78    Eina_Bool                     decorate_mode_item_realized : 1;
79    Eina_Bool                     tree_effect_finished : 1; /* tree effect */
80 };
81
82 struct _Item_Block
83 {
84    EINA_INLIST;
85    int          count;
86    int          num;
87    int          reorder_offset;
88    Widget_Data *wd;
89    Eina_List   *items;
90    Evas_Coord   x, y, w, h, minw, minh;
91    int          position;
92    int          item_position_stamp;
93
94    Eina_Bool    position_update : 1;
95    Eina_Bool    want_unrealize : 1;
96    Eina_Bool    realized : 1;
97    Eina_Bool    changed : 1;
98    Eina_Bool    updateme : 1;
99    Eina_Bool    changeme : 1;
100    Eina_Bool    showme : 1;
101    Eina_Bool    must_recalc : 1;
102 };
103
104 struct _Item_Cache
105 {
106    EINA_INLIST;
107
108    Evas_Object *base_view, *spacer;
109
110    const char  *item_style; // it->itc->item_style
111    Eina_Bool    tree : 1; // it->group
112
113    Eina_Bool    selected : 1; // it->selected
114    Eina_Bool    disabled : 1; // it->disabled
115    Eina_Bool    expanded : 1; // it->item->expanded
116 };
117
118 static const char *widtype = NULL;
119 static void      _item_cache_zero(Widget_Data *wd);
120 static void      _del_hook(Evas_Object *obj);
121 static void      _mirrored_set(Evas_Object *obj,
122                                Eina_Bool    rtl);
123 static void      _theme_hook(Evas_Object *obj);
124 static void      _show_region_hook(void        *data,
125                                    Evas_Object *obj);
126 static void      _sizing_eval(Evas_Object *obj);
127 static void      _item_realize(Elm_Gen_Item *it,
128                                int           in,
129                                Eina_Bool     calc);
130 static void      _item_unrealize_cb(Elm_Gen_Item *it);
131 static void      _item_block_unrealize(Item_Block *itb);
132 static void      _calc_job(void *data);
133 static void      _on_focus_hook(void        *data,
134                                 Evas_Object *obj);
135 static void      _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
136 static void      _changed_job(void *data);
137 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
138 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
139 static Eina_Bool _item_single_select_up(Widget_Data *wd);
140 static Eina_Bool _item_single_select_down(Widget_Data *wd);
141 static Eina_Bool _event_hook(Evas_Object       *obj,
142                              Evas_Object       *src,
143                              Evas_Callback_Type type,
144                              void              *event_info);
145 static void      _signal_emit_hook(Evas_Object *obj,
146                                    const char  *emission,
147                                    const char  *source);
148 static Eina_Bool _deselect_all_items(Widget_Data *wd);
149 static void      _pan_calculate(Evas_Object *obj);
150 static void      _pan_max_get(Evas_Object *obj,
151                               Evas_Coord  *x,
152                               Evas_Coord  *y);
153 static void      _item_position(Elm_Gen_Item *it,
154                                 Evas_Object  *obj,
155                                 Evas_Coord    it_x,
156                                 Evas_Coord    it_y);
157 static void      _mode_item_realize(Elm_Gen_Item *it);
158 static void      _mode_item_unrealize(Elm_Gen_Item *it);
159 static void      _item_mode_set(Elm_Gen_Item *it);
160 static void      _item_mode_unset(Widget_Data *wd);
161 static void      _decorate_mode_item_position(Elm_Gen_Item *it, int itx, int ity);
162 static void      _decorate_mode_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on);
163 static void      _decorate_mode_item_unrealize(Elm_Gen_Item *it);
164 //FIXME: group raise
165 #if 0
166 static void      _group_items_recalc(void *data);
167 #endif
168 static void      _item_move_after(Elm_Gen_Item *it,
169                                   Elm_Gen_Item *after);
170 static void      _item_move_before(Elm_Gen_Item *it,
171                                    Elm_Gen_Item *before);
172 static void      _item_auto_scroll(Widget_Data *wd);
173 static void      _elm_genlist_clear(Evas_Object *obj,
174                                     Eina_Bool    standby);
175 static void      _pan_child_size_get(Evas_Object *obj,
176                                      Evas_Coord  *w,
177                                      Evas_Coord  *h);
178 static Evas_Object* _create_tray_alpha_bg(const Evas_Object *obj);
179 static void         _item_contract_emit(Elm_Gen_Item *it);
180 static int          _item_tree_effect_before(Elm_Gen_Item *it);
181 static void         _item_tree_effect(Widget_Data *wd, int y);
182 static void         _item_tree_effect_finish(Widget_Data *wd);
183 static Eina_Bool    _item_moving_effect_timer_cb(void *data);
184
185 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
186
187 static const char SIG_ACTIVATED[] = "activated";
188 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
189 static const char SIG_SELECTED[] = "selected";
190 static const char SIG_UNSELECTED[] = "unselected";
191 static const char SIG_EXPANDED[] = "expanded";
192 static const char SIG_CONTRACTED[] = "contracted";
193 static const char SIG_EXPAND_REQUEST[] = "expand,request";
194 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
195 static const char SIG_REALIZED[] = "realized";
196 static const char SIG_UNREALIZED[] = "unrealized";
197 static const char SIG_DRAG_START_UP[] = "drag,start,up";
198 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
199 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
200 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
201 static const char SIG_DRAG_STOP[] = "drag,stop";
202 static const char SIG_DRAG[] = "drag";
203 static const char SIG_LONGPRESSED[] = "longpressed";
204 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
205 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
206 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
207 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
208 static const char SIG_EDGE_TOP[] = "edge,top";
209 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
210 static const char SIG_EDGE_LEFT[] = "edge,left";
211 static const char SIG_EDGE_RIGHT[] = "edge,right";
212 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
213 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
214 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
215 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
216 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
217 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
218 static const char SIG_SWIPE[] = "swipe";
219 static const char SIG_MOVED[] = "moved";
220 static const char SIG_INDEX_UPDATE[] = "index,update";
221 static const char SIG_TREE_EFFECT_FINISHED [] = "tree,effect,finished";
222
223 static const Evas_Smart_Cb_Description _signals[] = {
224    {SIG_CLICKED_DOUBLE, ""},
225    {SIG_ACTIVATED, ""},
226    {SIG_SELECTED, ""},
227    {SIG_UNSELECTED, ""},
228    {SIG_EXPANDED, ""},
229    {SIG_CONTRACTED, ""},
230    {SIG_EXPAND_REQUEST, ""},
231    {SIG_CONTRACT_REQUEST, ""},
232    {SIG_REALIZED, ""},
233    {SIG_UNREALIZED, ""},
234    {SIG_DRAG_START_UP, ""},
235    {SIG_DRAG_START_DOWN, ""},
236    {SIG_DRAG_START_LEFT, ""},
237    {SIG_DRAG_START_RIGHT, ""},
238    {SIG_DRAG_STOP, ""},
239    {SIG_DRAG, ""},
240    {SIG_LONGPRESSED, ""},
241    {SIG_SCROLL_ANIM_START, ""},
242    {SIG_SCROLL_ANIM_STOP, ""},
243    {SIG_SCROLL_DRAG_START, ""},
244    {SIG_SCROLL_DRAG_STOP, ""},
245    {SIG_EDGE_TOP, ""},
246    {SIG_EDGE_BOTTOM, ""},
247    {SIG_EDGE_LEFT, ""},
248    {SIG_EDGE_RIGHT, ""},
249    {SIG_MULTI_SWIPE_LEFT, ""},
250    {SIG_MULTI_SWIPE_RIGHT, ""},
251    {SIG_MULTI_SWIPE_UP, ""},
252    {SIG_MULTI_SWIPE_DOWN, ""},
253    {SIG_MULTI_PINCH_OUT, ""},
254    {SIG_MULTI_PINCH_IN, ""},
255    {SIG_SWIPE, ""},
256    {SIG_MOVED, ""},
257    {SIG_TREE_EFFECT_FINISHED, ""},
258    {NULL, NULL}
259 };
260
261 /* TEMPORARY */
262 #undef ELM_CHECK_WIDTYPE
263 #define ELM_CHECK_WIDTYPE(obj, widtype) \
264    if ((!obj) || (!elm_genlist_type_check((obj), __func__))) return
265 #undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
266 #define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
267    ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
268    ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
269
270 static const char *_gengrid = NULL;
271 static const char *_genlist = NULL;
272
273 /* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
274 Eina_Bool
275 elm_genlist_type_check(const Evas_Object *obj,
276                        const char        *func)
277 {
278    const char *provided, *expected = "(unknown)";
279    static int abort_on_warn = -1;
280    provided = elm_widget_type_get(obj);
281    if (!_genlist) _genlist = eina_stringshare_add("genlist");
282    if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
283    if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
284      return EINA_TRUE;
285    if ((!provided) || (!provided[0]))
286      {
287         provided = evas_object_type_get(obj);
288         if ((!provided) || (!provided[0]))
289           provided = "(unknown)";
290      }
291    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
292    if (abort_on_warn == -1)
293      {
294         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
295         else abort_on_warn = 0;
296      }
297    if (abort_on_warn == 1) abort();
298    return EINA_FALSE;
299 }
300
301 static Eina_Bool
302 _event_hook(Evas_Object       *obj,
303             Evas_Object       *src __UNUSED__,
304             Evas_Callback_Type type,
305             void              *event_info)
306 {
307    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
308    Evas_Event_Key_Down *ev = event_info;
309    Widget_Data *wd = elm_widget_data_get(obj);
310    Evas_Coord pan_max_x = 0, pan_max_y = 0;
311    if (!wd) return EINA_FALSE;
312    if (!wd->items) return EINA_FALSE;
313    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
314    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
315
316    Elm_Object_Item *it = NULL;
317    Evas_Coord x = 0;
318    Evas_Coord y = 0;
319    Evas_Coord step_x = 0;
320    Evas_Coord step_y = 0;
321    Evas_Coord v_w = 0;
322    Evas_Coord v_h = 0;
323    Evas_Coord page_x = 0;
324    Evas_Coord page_y = 0;
325
326    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
327    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
328    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
329    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
330
331    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
332      {
333         x -= step_x;
334      }
335    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
336      {
337         x += step_x;
338      }
339    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
340      {
341         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
342              (_item_multi_select_up(wd)))
343             || (_item_single_select_up(wd)))
344           {
345              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
346              return EINA_TRUE;
347           }
348         else
349           y -= step_y;
350      }
351    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
352      {
353         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
354              (_item_multi_select_down(wd)))
355             || (_item_single_select_down(wd)))
356           {
357              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
358              return EINA_TRUE;
359           }
360         else
361           y += step_y;
362      }
363    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
364      {
365         it = elm_genlist_first_item_get(obj);
366         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
367         elm_genlist_item_selected_set(it, EINA_TRUE);
368         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
369         return EINA_TRUE;
370      }
371    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
372      {
373         it = elm_genlist_last_item_get(obj);
374         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
375         elm_genlist_item_selected_set(it, EINA_TRUE);
376         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
377         return EINA_TRUE;
378      }
379    else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
380      {
381         if (page_y < 0)
382           y -= -(page_y * v_h) / 100;
383         else
384           y -= page_y;
385      }
386    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
387      {
388         if (page_y < 0)
389           y += -(page_y * v_h) / 100;
390         else
391           y += page_y;
392      }
393    else if (!strcmp(ev->keyname, "Escape"))
394      {
395         if (!_deselect_all_items(wd)) return EINA_FALSE;
396         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
397         return EINA_TRUE;
398      }
399    else if (((!strcmp(ev->keyname, "Return")) ||
400              (!strcmp(ev->keyname, "KP_Enter")) ||
401              (!strcmp(ev->keyname, "space")))
402             && (!wd->multi) && (wd->selected))
403      {
404         it = elm_genlist_selected_item_get(obj);
405         elm_genlist_item_expanded_set(it,
406                                       !elm_genlist_item_expanded_get(it));
407         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
408      }
409    else return EINA_FALSE;
410
411    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
412    _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
413    if (x < 0) x = 0;
414    if (x > pan_max_x) x = pan_max_x;
415    if (y < 0) y = 0;
416    if (y > pan_max_y) y = pan_max_y;
417    elm_smart_scroller_child_pos_set(wd->scr, x, y);
418    return EINA_TRUE;
419 }
420
421 static Eina_Bool
422 _deselect_all_items(Widget_Data *wd)
423 {
424    if (!wd->selected) return EINA_FALSE;
425    while (wd->selected)
426      elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
427
428    return EINA_TRUE;
429 }
430
431 static Eina_Bool
432 _item_multi_select_up(Widget_Data *wd)
433 {
434    if (!wd->selected) return EINA_FALSE;
435    if (!wd->multi) return EINA_FALSE;
436
437    Elm_Object_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
438    if (!prev) return EINA_TRUE;
439
440    if (elm_genlist_item_selected_get(prev))
441      {
442         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
443         wd->last_selected_item = prev;
444         elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
445      }
446    else
447      {
448         elm_genlist_item_selected_set(prev, EINA_TRUE);
449         elm_genlist_item_show(prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
450      }
451    return EINA_TRUE;
452 }
453
454 static Eina_Bool
455 _item_multi_select_down(Widget_Data *wd)
456 {
457    if (!wd->selected) return EINA_FALSE;
458    if (!wd->multi) return EINA_FALSE;
459
460    Elm_Object_Item *next;
461    next = elm_genlist_item_next_get(wd->last_selected_item);
462    if (!next) return EINA_TRUE;
463
464    if (elm_genlist_item_selected_get(next))
465      {
466         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
467         wd->last_selected_item = next;
468         elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
469      }
470    else
471      {
472         elm_genlist_item_selected_set(next, EINA_TRUE);
473         elm_genlist_item_show(next, ELM_GENLIST_ITEM_SCROLLTO_IN);
474      }
475    return EINA_TRUE;
476 }
477
478 static Eina_Bool
479 _item_single_select_up(Widget_Data *wd)
480 {
481    Elm_Gen_Item *prev;
482    if (!wd->selected)
483      {
484         prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
485         while ((prev) && (prev->generation < wd->generation))
486           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
487      }
488    else prev = (Elm_Gen_Item *) elm_genlist_item_prev_get(wd->last_selected_item);
489
490    if (!prev) return EINA_FALSE;
491
492    _deselect_all_items(wd);
493
494    elm_genlist_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
495    elm_genlist_item_show((Elm_Object_Item *) prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
496    return EINA_TRUE;
497 }
498
499 static Eina_Bool
500 _item_single_select_down(Widget_Data *wd)
501 {
502    Elm_Gen_Item *next;
503    if (!wd->selected)
504      {
505         next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
506         while ((next) && (next->generation < wd->generation))
507           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
508      }
509    else next = (Elm_Gen_Item *) elm_genlist_item_next_get(wd->last_selected_item);
510
511    if (!next) return EINA_FALSE;
512
513    _deselect_all_items(wd);
514
515    elm_genlist_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
516    elm_genlist_item_show((Elm_Object_Item *) next, ELM_GENLIST_ITEM_SCROLLTO_IN);
517    return EINA_TRUE;
518 }
519
520 static void
521 _on_focus_hook(void        *data __UNUSED__,
522                Evas_Object *obj)
523 {
524    Widget_Data *wd = elm_widget_data_get(obj);
525    if (!wd) return;
526    if (elm_widget_focus_get(obj))
527      {
528         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
529         evas_object_focus_set(wd->obj, EINA_TRUE);
530         if ((wd->items) && (wd->selected) && (!wd->last_selected_item))
531           wd->last_selected_item = eina_list_data_get(wd->selected);
532      }
533    else
534      {
535         elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
536         evas_object_focus_set(wd->obj, EINA_FALSE);
537      }
538 }
539
540 static void
541 _del_hook(Evas_Object *obj)
542 {
543    Widget_Data *wd = elm_widget_data_get(obj);
544    if (!wd) return;
545    _item_cache_zero(wd);
546    if (wd->calc_job) ecore_job_del(wd->calc_job);
547    if (wd->update_job) ecore_job_del(wd->update_job);
548    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
549    if (wd->changed_job) ecore_job_del(wd->changed_job);
550    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
551    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
552    if (wd->decorate_type) eina_stringshare_del(wd->decorate_type);
553    if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
554    free(wd);
555 }
556
557 static void
558 _del_pre_hook(Evas_Object *obj)
559 {
560    Widget_Data *wd = elm_widget_data_get(obj);
561    if (!wd) return;
562    if (wd->decorate_mode) elm_genlist_decorate_mode_set(wd->obj, EINA_FALSE);
563    elm_genlist_clear(obj);
564    evas_object_del(wd->pan_smart);
565    wd->pan_smart = NULL;
566 }
567
568 static void
569 _mirrored_set(Evas_Object *obj,
570               Eina_Bool    rtl)
571 {
572    Widget_Data *wd = elm_widget_data_get(obj);
573    if (!wd) return;
574    _item_cache_zero(wd);
575    elm_smart_scroller_mirrored_set(wd->scr, rtl);
576 }
577
578 static void
579 _theme_hook(Evas_Object *obj)
580 {
581    Widget_Data *wd = elm_widget_data_get(obj);
582    Item_Block *itb;
583    if (!wd) return;
584    evas_event_freeze(evas_object_evas_get(wd->obj));
585    _item_cache_zero(wd);
586    _elm_widget_mirrored_reload(obj);
587    _mirrored_set(obj, elm_widget_mirrored_get(obj));
588    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
589                                        elm_widget_style_get(obj));
590    //edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
591    wd->item_width = wd->item_height = 0;
592    wd->group_item_width = wd->group_item_height = 0;
593    wd->minw = wd->minh = wd->realminw = 0;
594    EINA_INLIST_FOREACH(wd->blocks, itb)
595      {
596         Eina_List *l;
597         Elm_Gen_Item *it;
598
599         if (itb->realized) _item_block_unrealize(itb);
600         EINA_LIST_FOREACH(itb->items, l, it)
601           it->item->mincalcd = EINA_FALSE;
602
603         itb->changed = EINA_TRUE;
604      }
605    if (wd->calc_job) ecore_job_del(wd->calc_job);
606    wd->calc_job = ecore_job_add(_calc_job, wd);
607    _sizing_eval(obj);
608    evas_event_thaw(evas_object_evas_get(wd->obj));
609    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
610 }
611
612 static void
613 _show_region_hook(void        *data,
614                   Evas_Object *obj)
615 {
616    Widget_Data *wd = elm_widget_data_get(data);
617    Evas_Coord x, y, w, h;
618    if (!wd) return;
619    elm_widget_show_region_get(obj, &x, &y, &w, &h);
620    //x & y are screen coordinates, Add with pan coordinates
621    x += wd->pan_x;
622    y += wd->pan_y;
623    elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
624 }
625
626 static void
627 _translate_hook(Evas_Object *obj)
628 {
629    evas_object_smart_callback_call(obj, "language,changed", NULL);
630 }
631
632 static void
633 _sizing_eval(Evas_Object *obj)
634 {
635    Widget_Data *wd = elm_widget_data_get(obj);
636    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
637    Evas_Coord vmw = 0, vmh = 0;
638    if (!wd) return;
639
640    evas_object_size_hint_min_get(wd->scr, &minw, NULL);
641    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
642
643    edje_object_size_min_calc
644       (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
645
646    if (wd->mode == ELM_LIST_COMPRESS)
647      {
648         Evas_Coord vw, vh;
649
650         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
651         if ((vw != 0) && (vw != wd->prev_viewport_w))
652           {
653              Item_Block *itb;
654
655              wd->prev_viewport_w = vw;
656              EINA_INLIST_FOREACH(wd->blocks, itb)
657                {
658                   itb->must_recalc = EINA_TRUE;
659                }
660              if (wd->calc_job) ecore_job_del(wd->calc_job);
661              wd->calc_job = ecore_job_add(_calc_job, wd);
662           }
663         edje_object_size_min_calc
664           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
665         minw = vmw;
666         minh = vmh;
667      }
668    else if (wd->mode == ELM_LIST_LIMIT)
669      {
670         maxw = -1;
671         minw = vmw + minw;
672      }
673    else
674      {
675         minw = vmw;
676         minh = vmh;
677      }
678
679    evas_object_size_hint_min_set(obj, minw, minh);
680    evas_object_size_hint_max_set(obj, maxw, maxh);
681 }
682
683 static void
684 _signal_emit_hook(Evas_Object *obj,
685                   const char  *emission,
686                   const char  *source)
687 {
688    Widget_Data *wd = elm_widget_data_get(obj);
689    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
690                            emission, source);
691 }
692
693 static void
694 _item_highlight(Elm_Gen_Item *it)
695 {
696    const char *selectraise;
697    if ((it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
698        (!it->wd->highlight) ||
699        (it->generation < it->wd->generation) ||
700        (it->highlighted) || elm_widget_item_disabled_get(it) ||
701        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (it->item->mode_view) ||
702        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
703      return;
704    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
705    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,selected", "elm");
706    selectraise = edje_object_data_get(VIEW(it), "selectraise");
707    if ((selectraise) && (!strcmp(selectraise, "on")))
708      {
709         if (it->edit_obj) evas_object_raise(it->edit_obj);
710         else evas_object_raise(VIEW(it));
711 //FIXME: group raise
712 #if 0
713         if ((it->item->group_item) && (it->item->group_item->realized))
714           evas_object_raise(it->item->VIEW(group_item));
715 #endif
716      }
717    it->highlighted = EINA_TRUE;
718 }
719
720 static void
721 _item_unhighlight(Elm_Gen_Item *it)
722 {
723    if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
724    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
725    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,unselected", "elm");
726    if (!it->item->nostacking)
727      {
728        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
729          {
730             if (it->edit_obj) evas_object_lower(it->edit_obj);
731             else evas_object_lower(VIEW(it));
732          }
733        else
734          {
735             if (it->edit_obj) evas_object_raise(it->edit_obj);
736             else evas_object_raise(VIEW(it));
737          }
738      }
739    it->highlighted = EINA_FALSE;
740 }
741
742 static void
743 _item_block_position_update(Eina_Inlist *list, int idx)
744 {
745    Item_Block *tmp;
746
747    EINA_INLIST_FOREACH(list, tmp)
748      {
749         tmp->position = idx++;
750         tmp->position_update = EINA_TRUE;
751      }
752 }
753
754 static void
755 _item_position_update(Eina_List *list, int idx)
756 {
757    Elm_Gen_Item *it;
758    Eina_List *l;
759
760    EINA_LIST_FOREACH(list, l, it)
761      {
762         it->position = idx++;
763         it->position_update = EINA_TRUE;
764      }
765 }
766
767 static void
768 _item_block_del(Elm_Gen_Item *it)
769 {
770    Eina_Inlist *il;
771    Item_Block *itb = it->item->block;
772    Eina_Bool block_changed;
773
774    itb->items = eina_list_remove(itb->items, it);
775    itb->count--;
776    itb->changed = EINA_TRUE;
777    if (!it->wd->reorder_deleted)
778      {
779         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
780         it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
781      }
782    if (itb->count < 1)
783      {
784         il = EINA_INLIST_GET(itb);
785         Item_Block *itbn = (Item_Block *)(il->next);
786         if (it->parent)
787           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
788         else
789           {
790              _item_block_position_update(il->next, itb->position);
791              it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
792           }
793         free(itb);
794         if (itbn) itbn->changed = EINA_TRUE;
795      }
796    else
797      {
798         if (itb->count < itb->wd->max_items_per_block/2)
799           {
800              il = EINA_INLIST_GET(itb);
801              Item_Block *itbp = (Item_Block *)(il->prev);
802              Item_Block *itbn = (Item_Block *)(il->next);
803              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
804                {
805                   Elm_Gen_Item *it2;
806
807                   EINA_LIST_FREE(itb->items, it2)
808                     {
809                        it2->item->block = itbp;
810                        itbp->items = eina_list_append(itbp->items, it2);
811                        itbp->count++;
812                        itbp->changed = EINA_TRUE;
813                     }
814                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
815                                               itb->position);
816                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
817                                                       EINA_INLIST_GET(itb));
818                   free(itb);
819                   block_changed = EINA_TRUE;
820                }
821              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
822                {
823                   while (itb->items)
824                     {
825                        Eina_List *last = eina_list_last(itb->items);
826                        Elm_Gen_Item *it2 = last->data;
827
828                        it2->item->block = itbn;
829                        itb->items = eina_list_remove_list(itb->items, last);
830                        itbn->items = eina_list_prepend(itbn->items, it2);
831                        itbn->count++;
832                        itbn->changed = EINA_TRUE;
833                     }
834                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
835                                               itb->position);
836                   it->wd->blocks =
837                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
838                   free(itb);
839                   block_changed = EINA_TRUE;
840                }
841           }
842      }
843    if (block_changed)
844      {
845         it->wd->pan_changed = EINA_TRUE;
846         evas_object_smart_changed(it->wd->pan_smart);
847         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
848         it->wd->calc_job = NULL;
849      }
850 }
851
852 static void
853 _item_subitems_clear(Elm_Gen_Item *it)
854 {
855    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
856    Eina_List *tl = NULL, *l;
857    Elm_Object_Item *it2;
858
859    EINA_LIST_FOREACH(it->item->items, l, it2)
860      tl = eina_list_append(tl, it2);
861    EINA_LIST_FREE(tl, it2)
862      elm_object_item_del(it2);
863 }
864
865 static void
866 _item_del(Elm_Gen_Item *it)
867 {
868    Evas_Object *obj = WIDGET(it);
869
870    evas_event_freeze(evas_object_evas_get(obj));
871    elm_genlist_item_subitems_clear((Elm_Object_Item *)it);
872    if (it->wd->show_item == it) it->wd->show_item = NULL;
873    if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
874    if (it->item->decorate_mode_item_realized) _decorate_mode_item_unrealize(it);
875    if (it->item->block) _item_block_del(it);
876    if (it->item->queued)
877      it->wd->queue = eina_list_remove(it->wd->queue, it);
878    if (it->wd->anchor_item == it)
879      {
880         it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
881         if (!it->wd->anchor_item)
882           it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
883      }
884    if (it->wd->expanded_item == it) it->wd->expanded_item = NULL;
885    if (it->parent)
886      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
887    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
888    _elm_genlist_item_del_serious(it);
889    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
890    evas_event_thaw(evas_object_evas_get(obj));
891    evas_event_thaw_eval(evas_object_evas_get(obj));
892 }
893
894 static void
895 _clear_cb(Widget_Data *wd)
896 {
897    wd->anchor_item = NULL;
898    while (wd->blocks)
899      {
900         Item_Block *itb = (Item_Block *)(wd->blocks);
901
902         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
903         if (itb->items) eina_list_free(itb->items);
904         free(itb);
905      }
906    if (wd->queue_idle_enterer)
907      {
908         ecore_idle_enterer_del(wd->queue_idle_enterer);
909         wd->queue_idle_enterer = NULL;
910      }
911    if (wd->must_recalc_idler)
912      {
913         ecore_idler_del(wd->must_recalc_idler);
914         wd->must_recalc_idler = NULL;
915      }
916    if (wd->queue) wd->queue = eina_list_free(wd->queue);
917    if (wd->reorder_move_animator)
918      {
919         ecore_animator_del(wd->reorder_move_animator);
920         wd->reorder_move_animator = NULL;
921      }
922    wd->show_item = NULL;
923    wd->reorder_old_pan_y = 0;
924 }
925
926 static void
927 _item_unselect(Elm_Gen_Item *it)
928 {
929    if ((it->generation < it->wd->generation) || (!it->selected)) return;
930    it->selected = EINA_FALSE;
931    it->wd->selected = eina_list_remove(it->wd->selected, it);
932    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
933 }
934
935 static void
936 _mouse_move(void        *data,
937             Evas        *evas __UNUSED__,
938             Evas_Object *obj,
939             void        *event_info)
940 {
941    Elm_Gen_Item *it = data;
942    Evas_Event_Mouse_Move *ev = event_info;
943    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
944    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
945
946    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
947      {
948         if (!it->wd->on_hold)
949           {
950              it->wd->on_hold = EINA_TRUE;
951              if ((!it->wd->wasselected) && (!it->flipped))
952                {
953                   _item_unhighlight(it);
954                   _item_unselect(it);
955                }
956           }
957      }
958    if (it->wd->multitouched)
959      {
960         it->wd->cur_x = ev->cur.canvas.x;
961         it->wd->cur_y = ev->cur.canvas.y;
962         return;
963      }
964    if ((it->dragging) && (it->down))
965      {
966         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
967         else
968           {
969              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
970              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
971              if (abs((it->wd->history[it->wd->movements].x -
972                       it->wd->history[0].x)) > 40)
973                it->wd->swipe = EINA_TRUE;
974              else
975                it->wd->movements++;
976           }
977         if (it->long_timer)
978           {
979              ecore_timer_del(it->long_timer);
980              it->long_timer = NULL;
981           }
982         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
983         return;
984      }
985    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
986      {
987         if (it->long_timer)
988           {
989              ecore_timer_del(it->long_timer);
990              it->long_timer = NULL;
991           }
992         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
993           {
994              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
995              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
996
997              if (!it->wd->reorder_start_y)
998                it->wd->reorder_start_y = it->item->block->y + it->y;
999
1000              if (it_scrl_y < oy)
1001                y_pos = oy;
1002              else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
1003                y_pos = oy + oh - it->wd->reorder_it->item->h;
1004              else
1005                y_pos = it_scrl_y;
1006
1007              if (it->edit_obj)
1008                _item_position(it, it->edit_obj, it->item->scrl_x, y_pos);
1009              else
1010                _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
1011
1012              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1013              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1014           }
1015         return;
1016      }
1017    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
1018      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1019    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1020    x = ev->cur.canvas.x - x;
1021    y = ev->cur.canvas.y - y;
1022    dx = x - it->dx;
1023    adx = dx;
1024    if (adx < 0) adx = -dx;
1025    dy = y - it->dy;
1026    ady = dy;
1027    if (ady < 0) ady = -dy;
1028    minw /= 2;
1029    minh /= 2;
1030    if ((adx > minw) || (ady > minh))
1031      {
1032         it->dragging = EINA_TRUE;
1033         if (it->long_timer)
1034           {
1035              ecore_timer_del(it->long_timer);
1036              it->long_timer = NULL;
1037           }
1038         if ((!it->wd->wasselected) && (!it->flipped))
1039           {
1040              _item_unhighlight(it);
1041              _item_unselect(it);
1042           }
1043         if (dy < 0)
1044           {
1045              if ((ady > adx) && (!it->wd->drag_started))
1046                evas_object_smart_callback_call(WIDGET(it),
1047                                                SIG_DRAG_START_UP, it);
1048              else
1049                {
1050                   if (dx < 0)
1051                     evas_object_smart_callback_call(WIDGET(it),
1052                                                     SIG_DRAG_START_LEFT, it);
1053                   else
1054                     evas_object_smart_callback_call(WIDGET(it),
1055                                                     SIG_DRAG_START_RIGHT, it);
1056                }
1057           }
1058         else
1059           {
1060              if ((ady > adx) && (!it->wd->drag_started))
1061                evas_object_smart_callback_call(WIDGET(it),
1062                                                SIG_DRAG_START_DOWN, it);
1063              else
1064                {
1065                   if (dx < 0)
1066                     evas_object_smart_callback_call(WIDGET(it),
1067                                                     SIG_DRAG_START_LEFT, it);
1068                   else
1069                     evas_object_smart_callback_call(WIDGET(it),
1070                                                     SIG_DRAG_START_RIGHT, it);
1071                }
1072           }
1073      }
1074 }
1075
1076 static Eina_Bool
1077 _long_press(void *data)
1078 {
1079    Elm_Gen_Item *it = data, *it_tmp;
1080    Eina_List *list, *l;
1081
1082    it->long_timer = NULL;
1083    if (elm_widget_item_disabled_get(it) || (it->dragging) ||
1084        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1085      return ECORE_CALLBACK_CANCEL;
1086    it->wd->longpressed = EINA_TRUE;
1087    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1088    if ((it->wd->reorder_mode) && (!it->group))
1089      {
1090         it->wd->reorder_it = it;
1091         it->wd->reorder_start_y = 0;
1092         if (it->edit_obj)
1093           evas_object_raise(it->edit_obj);
1094         else
1095           evas_object_raise(VIEW(it));
1096
1097         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1098         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1099
1100         list = elm_genlist_realized_items_get(it->wd->obj);
1101         EINA_LIST_FOREACH(list, l, it_tmp)
1102           {
1103              if (it != it_tmp) _item_unselect(it_tmp);
1104           }
1105         if (it->item->items)
1106           {
1107              EINA_LIST_FOREACH(it->item->items, l, it_tmp)
1108                {
1109                   if (elm_genlist_item_expanded_get((Elm_Object_Item *) it_tmp))
1110                     {
1111                        elm_genlist_item_expanded_set((Elm_Object_Item *)it_tmp,
1112                                                      EINA_FALSE);
1113                        return ECORE_CALLBACK_RENEW;
1114                     }
1115                }
1116           }
1117         if (elm_genlist_item_expanded_get((Elm_Object_Item *)it))
1118           {
1119              elm_genlist_item_expanded_set((Elm_Object_Item *)it, EINA_FALSE);
1120              return ECORE_CALLBACK_RENEW;
1121           }
1122
1123         if (!it->wd->decorate_mode)
1124           edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1125      }
1126    return ECORE_CALLBACK_CANCEL;
1127 }
1128
1129 static void
1130 _swipe(Elm_Gen_Item *it)
1131 {
1132    int i, sum = 0;
1133
1134    if (!it) return;
1135    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
1136        elm_widget_item_disabled_get(it)) return;
1137    it->wd->swipe = EINA_FALSE;
1138    for (i = 0; i < it->wd->movements; i++)
1139      {
1140         sum += it->wd->history[i].x;
1141         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1142      }
1143
1144    sum /= it->wd->movements;
1145    if (abs(sum - it->wd->history[0].x) <= 10) return;
1146    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1147 }
1148
1149 static Eina_Bool
1150 _swipe_cancel(void *data)
1151 {
1152    Elm_Gen_Item *it = data;
1153
1154    if (!it) return ECORE_CALLBACK_CANCEL;
1155    it->wd->swipe = EINA_FALSE;
1156    it->wd->movements = 0;
1157    return ECORE_CALLBACK_RENEW;
1158 }
1159
1160 static Eina_Bool
1161 _multi_cancel(void *data)
1162 {
1163    Widget_Data *wd = data;
1164
1165    if (!wd) return ECORE_CALLBACK_CANCEL;
1166    wd->multi_timeout = EINA_TRUE;
1167    return ECORE_CALLBACK_RENEW;
1168 }
1169
1170 static void
1171 _multi_touch_gesture_eval(void *data)
1172 {
1173    Elm_Gen_Item *it = data;
1174
1175    it->wd->multitouched = EINA_FALSE;
1176    if (it->wd->multi_timer)
1177      {
1178         ecore_timer_del(it->wd->multi_timer);
1179         it->wd->multi_timer = NULL;
1180      }
1181    if (it->wd->multi_timeout)
1182      {
1183         it->wd->multi_timeout = EINA_FALSE;
1184         return;
1185      }
1186
1187    Evas_Coord minw = 0, minh = 0;
1188    Evas_Coord off_x, off_y, off_mx, off_my;
1189
1190    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1191    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1192    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1193    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1194    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1195
1196    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1197      {
1198         if ((off_x + off_mx) > (off_y + off_my))
1199           {
1200              if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1201                evas_object_smart_callback_call(WIDGET(it),
1202                                                SIG_MULTI_SWIPE_RIGHT, it);
1203              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1204                evas_object_smart_callback_call(WIDGET(it),
1205                                                SIG_MULTI_SWIPE_LEFT, it);
1206              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1207                evas_object_smart_callback_call(WIDGET(it),
1208                                                SIG_MULTI_PINCH_OUT, it);
1209              else
1210                evas_object_smart_callback_call(WIDGET(it),
1211                                                SIG_MULTI_PINCH_IN, it);
1212           }
1213         else
1214           {
1215              if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1216                evas_object_smart_callback_call(WIDGET(it),
1217                                                SIG_MULTI_SWIPE_DOWN, it);
1218              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1219                evas_object_smart_callback_call(WIDGET(it),
1220                                                SIG_MULTI_SWIPE_UP, it);
1221              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1222                evas_object_smart_callback_call(WIDGET(it),
1223                                                SIG_MULTI_PINCH_OUT, it);
1224              else
1225                evas_object_smart_callback_call(WIDGET(it),
1226                                                SIG_MULTI_PINCH_IN, it);
1227           }
1228      }
1229    it->wd->multi_timeout = EINA_FALSE;
1230 }
1231
1232 static void
1233 _multi_down(void        *data,
1234             Evas        *evas __UNUSED__,
1235             Evas_Object *obj __UNUSED__,
1236             void        *event_info)
1237 {
1238    Elm_Gen_Item *it = data;
1239    Evas_Event_Multi_Down *ev = event_info;
1240
1241    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1242    it->wd->multi_device = ev->device;
1243    it->wd->multi_down = EINA_TRUE;
1244    it->wd->multitouched = EINA_TRUE;
1245    it->wd->prev_mx = ev->canvas.x;
1246    it->wd->prev_my = ev->canvas.y;
1247    if (!it->wd->wasselected)
1248      {
1249         _item_unhighlight(it);
1250         _item_unselect(it);
1251      }
1252    it->wd->wasselected = EINA_FALSE;
1253    it->wd->longpressed = EINA_FALSE;
1254    if (it->long_timer)
1255      {
1256         ecore_timer_del(it->long_timer);
1257         it->long_timer = NULL;
1258      }
1259    if (it->dragging)
1260      {
1261         it->dragging = EINA_FALSE;
1262         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1263      }
1264    if (it->item->swipe_timer)
1265      {
1266         ecore_timer_del(it->item->swipe_timer);
1267         it->item->swipe_timer = NULL;
1268      }
1269    if (it->wd->on_hold)
1270      {
1271         it->wd->swipe = EINA_FALSE;
1272         it->wd->movements = 0;
1273         it->wd->on_hold = EINA_FALSE;
1274      }
1275 }
1276
1277 static void
1278 _multi_up(void        *data,
1279           Evas        *evas __UNUSED__,
1280           Evas_Object *obj __UNUSED__,
1281           void        *event_info)
1282 {
1283    Elm_Gen_Item *it = data;
1284    Evas_Event_Multi_Up *ev = event_info;
1285
1286    if (it->wd->multi_device != ev->device) return;
1287    it->wd->multi_device = 0;
1288    it->wd->multi_down = EINA_FALSE;
1289    if (it->wd->mouse_down) return;
1290    _multi_touch_gesture_eval(data);
1291 }
1292
1293 static void
1294 _multi_move(void        *data,
1295             Evas        *evas __UNUSED__,
1296             Evas_Object *obj __UNUSED__,
1297             void        *event_info)
1298 {
1299    Elm_Gen_Item *it = data;
1300    Evas_Event_Multi_Move *ev = event_info;
1301
1302    if (it->wd->multi_device != ev->device) return;
1303    it->wd->cur_mx = ev->cur.canvas.x;
1304    it->wd->cur_my = ev->cur.canvas.y;
1305 }
1306
1307 static void
1308 _mouse_down(void        *data,
1309             Evas        *evas __UNUSED__,
1310             Evas_Object *obj,
1311             void        *event_info)
1312 {
1313    Elm_Gen_Item *it = data;
1314    Evas_Event_Mouse_Down *ev = event_info;
1315    Evas_Coord x, y;
1316    Eina_List *l;
1317    Evas_Object *iobj;
1318
1319    if (ev->button != 1) return;
1320    if (!it->can_focus)
1321      {
1322         EINA_LIST_FOREACH(it->content_objs, l, iobj)
1323           {
1324              elm_widget_tree_unfocusable_set(iobj, EINA_FALSE);
1325           }
1326         it->can_focus = EINA_TRUE;
1327      }
1328    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1329      {
1330         it->wd->on_hold = EINA_TRUE;
1331      }
1332
1333    it->down = EINA_TRUE;
1334    it->dragging = EINA_FALSE;
1335    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1336    it->dx = ev->canvas.x - x;
1337    it->dy = ev->canvas.y - y;
1338    it->wd->mouse_down = EINA_TRUE;
1339    if (!it->wd->multitouched)
1340      {
1341         it->wd->prev_x = ev->canvas.x;
1342         it->wd->prev_y = ev->canvas.y;
1343         it->wd->multi_timeout = EINA_FALSE;
1344         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1345         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1346      }
1347    it->wd->longpressed = EINA_FALSE;
1348    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1349    else it->wd->on_hold = EINA_FALSE;
1350    if (it->wd->on_hold) return;
1351    it->wd->wasselected = it->selected;
1352    _item_highlight(it);
1353    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1354      if ((!elm_widget_item_disabled_get(it)) &&
1355          (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1356        {
1357           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1358           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1359        }
1360    if (it->long_timer) ecore_timer_del(it->long_timer);
1361    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1362    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1363    if (it->realized)
1364      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1365                                       it);
1366    else
1367      it->long_timer = NULL;
1368    it->wd->swipe = EINA_FALSE;
1369    it->wd->movements = 0;
1370 }
1371
1372 static void
1373 _mouse_up(void        *data,
1374           Evas        *evas __UNUSED__,
1375           Evas_Object *obj __UNUSED__,
1376           void        *event_info)
1377 {
1378    Elm_Gen_Item *it = data;
1379    Evas_Event_Mouse_Up *ev = event_info;
1380    Eina_Bool dragged = EINA_FALSE;
1381
1382    if (ev->button != 1) return;
1383    it->down = EINA_FALSE;
1384    it->wd->mouse_down = EINA_FALSE;
1385    if (it->wd->multitouched)
1386      {
1387         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1388         if (it->wd->multi_down) return;
1389         _multi_touch_gesture_eval(data);
1390         return;
1391      }
1392    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1393    else it->wd->on_hold = EINA_FALSE;
1394    if (it->long_timer)
1395      {
1396         ecore_timer_del(it->long_timer);
1397         it->long_timer = NULL;
1398      }
1399    if (it->dragging)
1400      {
1401         it->dragging = EINA_FALSE;
1402         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1403         dragged = 1;
1404      }
1405    if (it->item->swipe_timer)
1406      {
1407         ecore_timer_del(it->item->swipe_timer);
1408         it->item->swipe_timer = NULL;
1409      }
1410    if (it->wd->multi_timer)
1411      {
1412         ecore_timer_del(it->wd->multi_timer);
1413         it->wd->multi_timer = NULL;
1414         it->wd->multi_timeout = EINA_FALSE;
1415      }
1416    if (it->wd->on_hold)
1417      {
1418         if (it->wd->swipe) _swipe(data);
1419         it->wd->longpressed = EINA_FALSE;
1420         it->wd->on_hold = EINA_FALSE;
1421         return;
1422      }
1423    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1424      {
1425         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1426
1427         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1428           {
1429              if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1430                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1431              else
1432                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1433           }
1434         else
1435           {
1436              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1437              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1438           }
1439         it->wd->reorder_deleted = EINA_FALSE;
1440         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1441         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1442         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1443         elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1444      }
1445    if (it->wd->longpressed)
1446      {
1447         it->wd->longpressed = EINA_FALSE;
1448         if ((!it->wd->wasselected) && (!it->flipped))
1449           {
1450              _item_unhighlight(it);
1451              _item_unselect(it);
1452           }
1453         it->wd->wasselected = EINA_FALSE;
1454         return;
1455      }
1456    if (dragged)
1457      {
1458         if (it->want_unrealize)
1459           {
1460              _elm_genlist_item_unrealize(it, EINA_FALSE);
1461              if (it->item->block->want_unrealize)
1462                _item_block_unrealize(it->item->block);
1463           }
1464      }
1465    if (elm_widget_item_disabled_get(it) || (dragged) ||
1466        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1467      return;
1468    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1469    if (it->wd->multi)
1470      {
1471         if (!it->selected)
1472           {
1473              _item_highlight(it);
1474              it->sel_cb(it);
1475           }
1476         else
1477           {
1478              _item_unhighlight(it);
1479              _item_unselect(it);
1480           }
1481      }
1482    else
1483      {
1484         if (!it->selected)
1485           {
1486              Widget_Data *wd = it->wd;
1487              if (wd)
1488                {
1489                   while (wd->selected)
1490                     {
1491                        _item_unhighlight(wd->selected->data);
1492                        _item_unselect(wd->selected->data);
1493                     }
1494                }
1495           }
1496         else
1497           {
1498              const Eina_List *l, *l_next;
1499              Elm_Gen_Item *it2;
1500
1501              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1502                if (it2 != it)
1503                   {
1504                      _item_unhighlight(it2);
1505                      _item_unselect(it2);
1506                   }
1507              //_item_highlight(it);
1508              //_item_select(it);
1509           }
1510         _item_highlight(it);
1511         it->sel_cb(it);
1512      }
1513 }
1514
1515 static void
1516 _mouse_down_scroller(void        *data,
1517                      Evas        *evas __UNUSED__,
1518                      Evas_Object *obj __UNUSED__,
1519                      void        *event_info __UNUSED__)
1520 {
1521    Widget_Data *wd = elm_widget_data_get(data);
1522
1523    if (!wd) return;
1524    wd->drag_started = EINA_FALSE;
1525 }
1526
1527 static void
1528 _mouse_up_scroller(void        *data,
1529                    Evas        *evas __UNUSED__,
1530                    Evas_Object *obj __UNUSED__,
1531                    void        *event_info __UNUSED__)
1532 {
1533    Widget_Data *wd = elm_widget_data_get(data);
1534
1535    if (!wd) return;
1536    wd->drag_started = EINA_FALSE;
1537 }
1538
1539 static void
1540 _mouse_move_scroller(void        *data,
1541                      Evas        *evas __UNUSED__,
1542                      Evas_Object *obj __UNUSED__,
1543                      void        *event_info)
1544 {
1545    Widget_Data *wd = elm_widget_data_get(data);
1546    Evas_Event_Mouse_Move *ev = event_info;
1547    Evas_Coord minw = 0, minh = 0, dx, dy, adx, ady;
1548
1549    if (!wd) return;
1550    if (wd->drag_started) return;
1551
1552    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1553    dx = ev->cur.canvas.x - ev->prev.canvas.x;
1554    dy = ev->cur.canvas.y - ev->prev.canvas.y;
1555    adx = dx;
1556    ady = dy;
1557    if (adx < 0) adx = -dx;
1558    if (ady < 0) ady = -dy;
1559    if (((ady < minh) && (ady > minh / 2)) && (ady > adx))
1560      {
1561         if (dy < 0)
1562           {
1563              evas_object_smart_callback_call(data, SIG_DRAG_START_UP, NULL);
1564              wd->drag_started = EINA_TRUE;
1565           }
1566         else
1567           {
1568              evas_object_smart_callback_call(data, SIG_DRAG_START_DOWN, NULL);
1569              wd->drag_started = EINA_TRUE;
1570           }
1571      }
1572 }
1573
1574 static void
1575 _signal_expand_toggle(void        *data,
1576                       Evas_Object *obj __UNUSED__,
1577                       const char  *emission __UNUSED__,
1578                       const char  *source __UNUSED__)
1579 {
1580    Elm_Gen_Item *it = data;
1581
1582    if (it->item->expanded)
1583      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1584    else
1585      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1586 }
1587
1588 static void
1589 _signal_expand(void        *data,
1590                Evas_Object *obj __UNUSED__,
1591                const char  *emission __UNUSED__,
1592                const char  *source __UNUSED__)
1593 {
1594    Elm_Gen_Item *it = data;
1595
1596    if (!it->item->expanded)
1597      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1598 }
1599
1600 static void
1601 _signal_contract(void        *data,
1602                  Evas_Object *obj __UNUSED__,
1603                  const char  *emission __UNUSED__,
1604                  const char  *source __UNUSED__)
1605 {
1606    Elm_Gen_Item *it = data;
1607
1608    if (it->item->expanded)
1609      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1610 }
1611
1612 static Eina_Bool
1613 _scr_hold_timer_cb(void *data)
1614 {
1615    if (!data) return ECORE_CALLBACK_CANCEL;
1616    Widget_Data *wd = data;
1617    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1618    wd->scr_hold_timer = NULL;
1619    return ECORE_CALLBACK_CANCEL;
1620 }
1621
1622 static void
1623 _mode_finished_signal_cb(void        *data,
1624                          Evas_Object *obj,
1625                          const char  *emission __UNUSED__,
1626                          const char  *source __UNUSED__)
1627 {
1628    if (!data) return;
1629    if (!obj) return;
1630    Elm_Gen_Item *it = data;
1631    if ((it->generation < it->wd->generation) || (!it->realized) || (!it->item->mode_view)) return;
1632    char buf[1024];
1633    Evas *te = evas_object_evas_get(obj);
1634
1635    evas_event_freeze(te);
1636    it->item->nocache_once = EINA_FALSE;
1637    _mode_item_unrealize(it);
1638 //FIXME: group raise
1639 #if 0
1640    if (it->item->group_item)
1641      evas_object_raise(it->item->VIEW(group_item));
1642 #endif
1643    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->decorate_type);
1644    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1645    evas_event_thaw(te);
1646    evas_event_thaw_eval(te);
1647 }
1648
1649 static void
1650 _item_cache_clean(Widget_Data *wd)
1651 {
1652    evas_event_freeze(evas_object_evas_get(wd->obj));
1653    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1654      {
1655         Item_Cache *itc;
1656
1657         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1658         wd->item_cache = eina_inlist_remove(wd->item_cache,
1659                                             wd->item_cache->last);
1660         wd->item_cache_count--;
1661         if (itc->spacer) evas_object_del(itc->spacer);
1662         if (itc->base_view) evas_object_del(itc->base_view);
1663         eina_stringshare_del(itc->item_style);
1664         free(itc);
1665      }
1666    evas_event_thaw(evas_object_evas_get(wd->obj));
1667    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1668 }
1669
1670 static void
1671 _item_cache_zero(Widget_Data *wd)
1672 {
1673    int pmax = wd->item_cache_max;
1674    wd->item_cache_max = 0;
1675    _item_cache_clean(wd);
1676    wd->item_cache_max = pmax;
1677 }
1678
1679 static void
1680 _item_cache_add(Elm_Gen_Item *it)
1681 {
1682    Item_Cache *itc;
1683
1684    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1685    if (it->wd->item_cache_max <= 0)
1686      {
1687         evas_object_del(VIEW(it));
1688         VIEW(it) = NULL;
1689         evas_object_del(it->spacer);
1690         it->spacer = NULL;
1691         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1692         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1693         return;
1694      }
1695
1696    it->wd->item_cache_count++;
1697    itc = calloc(1, sizeof(Item_Cache));
1698    if (!itc)
1699      {
1700         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1701         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1702         return;
1703      }
1704    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1705                                             EINA_INLIST_GET(itc));
1706    itc->spacer = it->spacer;
1707    it->spacer = NULL;
1708    itc->base_view = VIEW(it);
1709    VIEW(it) = NULL;
1710    edje_object_signal_emit(itc->base_view, "elm,state,unselected", "elm");
1711    evas_object_hide(itc->base_view);
1712    evas_object_move(itc->base_view, -9999, -9999);
1713    itc->item_style = eina_stringshare_add(it->itc->item_style);
1714    if (it->item->type & ELM_GENLIST_ITEM_TREE) itc->tree = 1;
1715    itc->selected = it->selected;
1716    itc->disabled = elm_widget_item_disabled_get(it);
1717    itc->expanded = it->item->expanded;
1718    if (it->long_timer)
1719      {
1720         ecore_timer_del(it->long_timer);
1721         it->long_timer = NULL;
1722      }
1723    if (it->item->swipe_timer)
1724      {
1725         ecore_timer_del(it->item->swipe_timer);
1726         it->item->swipe_timer = NULL;
1727      }
1728    // FIXME: other callbacks?
1729    edje_object_signal_callback_del_full(itc->base_view,
1730                                         "elm,action,expand,toggle",
1731                                         "elm", _signal_expand_toggle, it);
1732    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1733                                         "elm",
1734                                         _signal_expand, it);
1735    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1736                                         "elm", _signal_contract, it);
1737    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
1738                                        _mouse_down, it);
1739    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
1740                                        _mouse_up, it);
1741    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
1742                                        _mouse_move, it);
1743    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
1744                                        _multi_down, it);
1745    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
1746                                        _multi_up, it);
1747    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
1748                                        _multi_move, it);
1749    _item_cache_clean(it->wd);
1750    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1751    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1752 }
1753
1754 static Item_Cache *
1755 _item_cache_find(Elm_Gen_Item *it)
1756 {
1757    Item_Cache *itc;
1758    Eina_Bool tree = 0;
1759
1760    if (it->item->type & ELM_GENLIST_ITEM_TREE) tree = 1;
1761    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1762      {
1763         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1764           continue;
1765         if ((itc->tree == tree) &&
1766             (((!it->itc->item_style) && (!itc->item_style)) ||
1767              (it->itc->item_style && itc->item_style &&
1768             (!strcmp(it->itc->item_style, itc->item_style)))))
1769           {
1770              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1771                                                      EINA_INLIST_GET(itc));
1772              it->wd->item_cache_count--;
1773              return itc;
1774           }
1775      }
1776    return NULL;
1777 }
1778
1779 static void
1780 _elm_genlist_item_index_update(Elm_Gen_Item *it)
1781 {
1782    if (it->position_update || it->item->block->position_update)
1783      {
1784         evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
1785         it->position_update = EINA_FALSE;
1786      }
1787 }
1788
1789 static void
1790 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1791 {
1792    if (!it->item->nostacking)
1793      {
1794         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1795           {
1796              if (it->edit_obj) evas_object_lower(it->edit_obj);
1797              else evas_object_lower(VIEW(it));
1798           }
1799         else
1800           {
1801              if (it->edit_obj) evas_object_raise(it->edit_obj);
1802              else evas_object_raise(VIEW(it));
1803           }
1804      }
1805
1806    if (it->item->order_num_in & 0x1)
1807      {
1808         edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1809         if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,odd", "elm");
1810      }
1811    else
1812      {
1813         edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1814         if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,even", "elm");
1815      }
1816 }
1817
1818 static void
1819 _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1820 {
1821    if (itc)
1822      {
1823         if (it->selected != itc->selected)
1824           {
1825              if (it->selected)
1826                {
1827                   edje_object_signal_emit(VIEW(it),
1828                                           "elm,state,selected", "elm");
1829
1830                   if (it->edit_obj)
1831                     edje_object_signal_emit(it->edit_obj,
1832                                             "elm,state,selected", "elm");
1833                }
1834           }
1835         if (elm_widget_item_disabled_get(it) != itc->disabled)
1836           {
1837              if (elm_widget_item_disabled_get(it))
1838                edje_object_signal_emit(VIEW(it),
1839                                        "elm,state,disabled", "elm");
1840              if (it->edit_obj)
1841                edje_object_signal_emit(it->edit_obj,
1842                                        "elm,state,disabled", "elm");
1843           }
1844         if (it->item->expanded != itc->expanded)
1845           {
1846              if (it->item->expanded)
1847                edje_object_signal_emit(VIEW(it),
1848                                        "elm,state,expanded", "elm");
1849              if (it->edit_obj)
1850                edje_object_signal_emit(it->edit_obj,
1851                                        "elm,state,expanded", "elm");
1852           }
1853      }
1854    else
1855      {
1856         if (it->selected)
1857           {
1858              edje_object_signal_emit(VIEW(it),
1859                                      "elm,state,selected", "elm");
1860              if (it->edit_obj)
1861                edje_object_signal_emit(it->edit_obj,
1862                                        "elm,state,selected", "elm");
1863           }
1864         if (elm_widget_item_disabled_get(it))
1865           {
1866              edje_object_signal_emit(VIEW(it),
1867                                      "elm,state,disabled", "elm");
1868              if (it->edit_obj)
1869                edje_object_signal_emit(it->edit_obj,
1870                                        "elm,state,disabled", "elm");
1871           }
1872         if (it->item->expanded)
1873           {
1874              edje_object_signal_emit(VIEW(it),
1875                                      "elm,state,expanded", "elm");
1876              if (it->edit_obj)
1877                edje_object_signal_emit(it->edit_obj,
1878                                        "elm,state,expanded", "elm");
1879           }
1880      }
1881 }
1882
1883 static void
1884 _content_focused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1885 {
1886    Elm_Gen_Item *it = data;
1887    if (it) it->defer_unrealize = EINA_TRUE;
1888 }
1889
1890 static void
1891 _content_unfocused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1892 {
1893    Elm_Gen_Item *it = data;
1894    if (it) it->defer_unrealize = EINA_FALSE;
1895 }
1896
1897
1898 static Eina_List *
1899 _item_mode_content_realize(Elm_Gen_Item *it,
1900                            Evas_Object *target,
1901                            Eina_List **source,
1902                            const char *parts,
1903                            Eina_List **contents_list,
1904                            const char *contents_part)
1905
1906 {
1907    Eina_List *res = NULL;
1908
1909    if (it->itc->func.content_get)
1910      {
1911         const Eina_List *l;
1912         const char *key;
1913
1914         *source = elm_widget_stringlist_get(edje_object_data_get(target, contents_part));
1915         if (parts && (eina_list_count(*source) != eina_list_count(*contents_list)))
1916              res = *contents_list;
1917         EINA_LIST_FOREACH(*source, l, key)
1918           {
1919              if (parts && fnmatch(parts, key, FNM_PERIOD))
1920                continue;
1921
1922              Evas_Object *ic = it->itc->func.content_get
1923                 ((void *)it->base.data, WIDGET(it), l->data);
1924
1925              if (ic)
1926                {
1927                   res = eina_list_append(res, ic);
1928                   edje_object_part_swallow(target, key, ic);
1929                   evas_object_show(ic);
1930                   elm_widget_sub_object_add(WIDGET(it), ic);
1931                   if (it->item->mode_view || it->wd->decorate_mode)
1932                     {
1933                        if (elm_widget_item_disabled_get(it))
1934                          elm_widget_disabled_set(ic, EINA_TRUE);
1935                     }
1936                   else if (it->flipped)
1937                     {
1938                        // FIXME: if entry calcuates its cursor position correctly and conformant works,
1939                        //        genlist does not need to handle this focus thing.
1940                        evas_object_smart_callback_add(ic, "focused", _content_focused, it);
1941                        evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
1942                     }
1943                }
1944           }
1945      }
1946
1947    return res;
1948 }
1949
1950 static Eina_List *
1951 _item_mode_content_unrealize(Elm_Gen_Item *it,
1952                              Evas_Object *target,
1953                              Eina_List **source,
1954                              const char *parts,
1955                              Eina_List **contents_list,
1956                              const char *contents_part)
1957 {
1958    Eina_List *res = *contents_list;
1959
1960    if (it->itc->func.content_get)
1961      {
1962         const Eina_List *l;
1963         const char *key;
1964         Evas_Object *ic = NULL;
1965
1966         *source = elm_widget_stringlist_get(edje_object_data_get(target, contents_part));
1967         EINA_LIST_FOREACH(*source, l, key)
1968           {
1969              if (parts && fnmatch(parts, key, FNM_PERIOD))
1970                continue;
1971
1972              ic = edje_object_part_swallow_get(target, key);
1973              if (ic)
1974                {
1975                   res = eina_list_remove(res, ic);
1976                   edje_object_part_unswallow(target, ic);
1977                   evas_object_del(ic);
1978                }
1979           }
1980      }
1981
1982    return res;
1983 }
1984
1985 static void
1986 _item_cache_free(Item_Cache *itc)
1987 {
1988    if (itc->spacer) evas_object_del(itc->spacer);
1989    if (itc->base_view) evas_object_del(itc->base_view);
1990    eina_stringshare_del(itc->item_style);
1991    free(itc);
1992 }
1993
1994 static void
1995 _item_text_realize(Elm_Gen_Item *it,
1996                    Evas_Object *target,
1997                    Eina_List **source,
1998                    const char *parts)
1999 {
2000    if (it->itc->func.text_get)
2001      {
2002         const Eina_List *l;
2003         const char *key;
2004
2005         *source = elm_widget_stringlist_get(edje_object_data_get(target, "texts"));
2006         EINA_LIST_FOREACH(*source, l, key)
2007           {
2008              if (parts && fnmatch(parts, key, FNM_PERIOD))
2009                continue;
2010
2011              char *s = it->itc->func.text_get
2012                 ((void *)it->base.data, WIDGET(it), key);
2013
2014              if (s)
2015                {
2016                   edje_object_part_text_set(target, key, s);
2017                   free(s);
2018                }
2019              else
2020                {
2021                   edje_object_part_text_set(target, key, "");
2022                }
2023           }
2024      }
2025 }
2026
2027 static Eina_List *
2028 _item_content_unrealize(Elm_Gen_Item *it,
2029                         Evas_Object *target,
2030                         Eina_List **source,
2031                         const char *parts)
2032 {
2033    Eina_List *res = it->content_objs;
2034
2035    if (it->itc->func.content_get)
2036      {
2037         const Eina_List *l;
2038         const char *key;
2039         Evas_Object *ic = NULL;
2040
2041         EINA_LIST_FOREACH(*source, l, key)
2042           {
2043              if (parts && fnmatch(parts, key, FNM_PERIOD))
2044                continue;
2045
2046              ic = edje_object_part_swallow_get(target, key);
2047              if (ic)
2048                {
2049                   res = eina_list_remove(res, ic);
2050                   edje_object_part_unswallow(target, ic);
2051                   evas_object_del(ic);
2052                }
2053           }
2054      }
2055
2056    return res;
2057 }
2058
2059 static Eina_List *
2060 _item_content_realize(Elm_Gen_Item *it,
2061                       Evas_Object *target,
2062                       Eina_List **source,
2063                       const char *parts)
2064 {
2065    Eina_List *res = NULL;
2066
2067    if (it->itc->func.content_get)
2068      {
2069         const Eina_List *l;
2070         const char *key;
2071         Evas_Object *ic = NULL;
2072
2073         *source = elm_widget_stringlist_get(edje_object_data_get(target, "contents"));
2074
2075         if (parts && (eina_list_count(*source) != eina_list_count(it->content_objs)))
2076           res = it->content_objs;
2077
2078         EINA_LIST_FOREACH(*source, l, key)
2079           {
2080              if (parts && fnmatch(parts, key, FNM_PERIOD))
2081                continue;
2082
2083              if (it->itc->func.content_get)
2084                ic = it->itc->func.content_get
2085                   ((void *)it->base.data, WIDGET(it), key);
2086              if (ic)
2087                {
2088                   res = eina_list_append(res, ic);
2089                   edje_object_part_swallow(target, key, ic);
2090                   evas_object_show(ic);
2091                   elm_widget_sub_object_add(WIDGET(it), ic);
2092                   evas_object_event_callback_add(ic,
2093                                                  EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2094                                                  _changed_size_hints, it);
2095                   if (it->flipped)
2096                     {
2097                        // FIXME: if entry calcuates its cursor position correctly and conformant works,
2098                        //        genlist does not need to handle this focus thing.
2099                        evas_object_smart_callback_add(ic, "focused", _content_focused, it);
2100                        evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
2101                     }
2102
2103                   if (elm_widget_item_disabled_get(it))
2104                     elm_widget_disabled_set(ic, EINA_TRUE);
2105                }
2106           }
2107      }
2108
2109    return res;
2110 }
2111
2112 static void
2113 _item_state_realize(Elm_Gen_Item *it,
2114                     Evas_Object *target,
2115                     Eina_List **source,
2116                     const char *parts)
2117 {
2118    if (it->itc->func.state_get)
2119      {
2120         const Eina_List *l;
2121         const char *key;
2122         char buf[4096];
2123
2124         *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
2125         EINA_LIST_FOREACH(*source, l, key)
2126           {
2127              if (parts && fnmatch(parts, key, FNM_PERIOD))
2128                continue;
2129
2130              Eina_Bool on = it->itc->func.state_get
2131                 ((void *)it->base.data, WIDGET(it), key);
2132
2133              if (on)
2134                {
2135                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
2136                   edje_object_signal_emit(target, buf, "elm");
2137                }
2138              else
2139                {
2140                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
2141                   edje_object_signal_emit(target, buf, "elm");
2142                }
2143           }
2144      }
2145 }
2146
2147 static Eina_List *
2148 _item_flips_realize(Elm_Gen_Item *it,
2149                     Evas_Object *target,
2150                     Eina_List **source)
2151 {
2152    Eina_List *res = NULL;
2153
2154    if (it->itc->func.content_get)
2155      {
2156         const Eina_List *l;
2157         const char *key;
2158         Evas_Object *ic = NULL;
2159
2160         *source = elm_widget_stringlist_get(edje_object_data_get(target, "flips"));
2161
2162         EINA_LIST_FOREACH(*source, l, key)
2163           {
2164              if (it->itc->func.content_get)
2165                ic = it->itc->func.content_get
2166                   ((void *)it->base.data, WIDGET(it), key);
2167              if (ic)
2168                {
2169                   res = eina_list_append(res, ic);
2170                   edje_object_part_swallow(target, key, ic);
2171                   evas_object_show(ic);
2172                   elm_widget_sub_object_add(WIDGET(it), ic);
2173                   // FIXME: if entry calcuates its cursor position correctly and conformant works,
2174                   //        genlist does not need to handle this focus thing.
2175                   evas_object_smart_callback_add(ic, "focused", _content_focused, it);
2176                   evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
2177                   if (elm_widget_item_disabled_get(it))
2178                     elm_widget_disabled_set(ic, EINA_TRUE);
2179                }
2180           }
2181      }
2182
2183    return res;
2184 }
2185
2186 static void
2187 _item_realize(Elm_Gen_Item *it,
2188               int               in,
2189               Eina_Bool         calc)
2190 {
2191    const char *treesize;
2192    char buf[1024];
2193    int tsize = 20;
2194    Item_Cache *itc = NULL;
2195
2196    if (it->generation < it->wd->generation) return;
2197    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
2198    if (it->realized)
2199      {
2200         if (it->item->order_num_in != in)
2201           {
2202              it->item->order_num_in = in;
2203              _elm_genlist_item_odd_even_update(it);
2204              _elm_genlist_item_state_update(it, NULL);
2205              _elm_genlist_item_index_update(it);
2206           }
2207         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2208         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2209         return;
2210      }
2211    it->item->order_num_in = in;
2212
2213    if ((it->item->nocache_once) && (!it->flipped))
2214      it->item->nocache_once = EINA_FALSE;
2215    else if (!it->item->nocache)
2216      itc = _item_cache_find(it);
2217    if (itc && (!it->wd->tree_effect_enabled))
2218      {
2219         VIEW(it) = itc->base_view;
2220         itc->base_view = NULL;
2221         it->spacer = itc->spacer;
2222         itc->spacer = NULL;
2223      }
2224    else
2225      {
2226         const char *stacking_even;
2227         const char *stacking;
2228
2229         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
2230         edje_object_scale_set(VIEW(it),
2231                               elm_widget_scale_get(WIDGET(it)) *
2232                               _elm_config->scale);
2233         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
2234         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
2235
2236         if (it->item->type & ELM_GENLIST_ITEM_TREE)
2237           snprintf(buf, sizeof(buf), "tree%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2238         else
2239           snprintf(buf, sizeof(buf), "item%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2240
2241         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
2242                               elm_widget_style_get(WIDGET(it)));
2243
2244         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
2245         if (!stacking_even) stacking_even = "above";
2246         it->item->stacking_even = !!strcmp("above", stacking_even);
2247
2248         stacking = edje_object_data_get(VIEW(it), "stacking");
2249         if (!stacking) stacking = "yes";
2250         it->item->nostacking = !!strcmp("yes", stacking);
2251
2252         edje_object_mirrored_set(VIEW(it),
2253                                  elm_widget_mirrored_get(WIDGET(it)));
2254         it->spacer =
2255           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
2256         evas_object_color_set(it->spacer, 0, 0, 0, 0);
2257         elm_widget_sub_object_add(WIDGET(it), it->spacer);
2258      }
2259
2260    _elm_genlist_item_odd_even_update(it);
2261
2262    treesize = edje_object_data_get(VIEW(it), "treesize");
2263    if (treesize) tsize = atoi(treesize);
2264    evas_object_size_hint_min_set(it->spacer,
2265                                  (it->item->expanded_depth * tsize) * _elm_config->scale, 1);
2266    edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
2267    if (!calc)
2268      {
2269         edje_object_signal_callback_add(VIEW(it),
2270                                         "elm,action,expand,toggle",
2271                                         "elm", _signal_expand_toggle, it);
2272         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
2273                                         "elm", _signal_expand, it);
2274         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
2275                                         "elm", _signal_contract, it);
2276         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
2277                                        _mouse_down, it);
2278         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
2279                                        _mouse_up, it);
2280         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
2281                                        _mouse_move, it);
2282         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
2283                                        _multi_down, it);
2284         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_UP,
2285                                        _multi_up, it);
2286         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
2287                                        _multi_move, it);
2288
2289         if ((it->wd->decorate_mode) && (!it->edit_obj) &&
2290             (it->item->type != ELM_GENLIST_ITEM_GROUP) && (it->itc->decorate_all_item_style))
2291           _decorate_mode_item_realize(it, EINA_FALSE);
2292
2293         _elm_genlist_item_state_update(it, itc);
2294         _elm_genlist_item_index_update(it);
2295      }
2296
2297    if ((calc) && (it->wd->homogeneous) &&
2298        ((it->wd->item_width) ||
2299         ((it->wd->item_width) && (it->wd->group_item_width))))
2300      {
2301         /* homogenous genlist shortcut */
2302         if (!it->item->mincalcd)
2303           {
2304              if (it->group)
2305                {
2306                   it->item->w = it->item->minw = it->wd->group_item_width;
2307                   it->item->h = it->item->minh = it->wd->group_item_height;
2308                }
2309              else
2310                {
2311                   it->item->w = it->item->minw = it->wd->item_width;
2312                   it->item->h = it->item->minh = it->wd->item_height;
2313                }
2314              it->item->mincalcd = EINA_TRUE;
2315           }
2316      }
2317    else
2318      {
2319         /* FIXME: If you see that assert, please notify us and we
2320            will clean our mess */
2321         assert(eina_list_count(it->content_objs) == 0);
2322
2323         _item_text_realize(it, VIEW(it), &it->texts, NULL);
2324         it->content_objs = _item_content_realize(it, VIEW(it), &it->contents, NULL);
2325         _item_state_realize(it, VIEW(it), &it->states, NULL);
2326         if (it->flipped)
2327           {
2328              edje_object_signal_emit(VIEW(it), "elm,state,flip,enabled", "elm");
2329              it->content_objs = _item_flips_realize(it, VIEW(it), &it->contents);
2330           }
2331
2332         if (!it->item->mincalcd || ((it->wd->mode == ELM_LIST_COMPRESS) && (it->item->w != it->item->minw)))
2333           {
2334              Evas_Coord mw = -1, mh = -1;
2335
2336              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2337                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2338              if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
2339              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
2340                                                   mh);
2341              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2342                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2343              it->item->w = it->item->minw = mw;
2344              it->item->h = it->item->minh = mh;
2345              it->item->mincalcd = EINA_TRUE;
2346
2347              if ((!it->wd->group_item_width) && (it->group))
2348                {
2349                   it->wd->group_item_width = mw;
2350                   it->wd->group_item_height = mh;
2351                }
2352              else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
2353                {
2354                   it->wd->item_width = mw;
2355                   it->wd->item_height = mh;
2356                }
2357           }
2358         if (!calc) evas_object_show(VIEW(it));
2359      }
2360
2361    if (it->tooltip.content_cb)
2362      {
2363         elm_widget_item_tooltip_content_cb_set(it,
2364                                                it->tooltip.content_cb,
2365                                                it->tooltip.data, NULL);
2366         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
2367         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
2368      }
2369
2370    if (it->mouse_cursor)
2371      elm_widget_item_cursor_set(it, it->mouse_cursor);
2372
2373    it->realized = EINA_TRUE;
2374    it->want_unrealize = EINA_FALSE;
2375
2376    if (itc) _item_cache_free(itc);
2377    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2378    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2379    if (!calc)
2380      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
2381
2382    if ((!calc) && (it->wd->decorate_mode) && (it->item->type != ELM_GENLIST_ITEM_GROUP))
2383      {
2384         if (it->itc->decorate_all_item_style)
2385           {
2386              if (!it->edit_obj) _decorate_mode_item_realize(it, EINA_FALSE);
2387              edje_object_message_signal_process(it->edit_obj);
2388           }
2389      }
2390    edje_object_message_signal_process(VIEW(it));
2391 }
2392
2393 static void
2394 _item_unrealize_cb(Elm_Gen_Item *it)
2395 {
2396    if (it->item->nocache_once || it->item->nocache)
2397      {
2398         evas_object_del(VIEW(it));
2399         VIEW(it) = NULL;
2400         evas_object_del(it->spacer);
2401         it->spacer = NULL;
2402      }
2403    else
2404      {
2405         edje_object_mirrored_set(VIEW(it),
2406                                  elm_widget_mirrored_get(WIDGET(it)));
2407         edje_object_scale_set(VIEW(it),
2408                               elm_widget_scale_get(WIDGET(it))
2409                               * _elm_config->scale);
2410         _item_cache_add(it);
2411      }
2412
2413    _mode_item_unrealize(it);
2414    it->states = NULL;
2415    it->realized = EINA_FALSE;
2416    it->want_unrealize = EINA_FALSE;
2417    if (it->wd->decorate_mode) _decorate_mode_item_unrealize(it);
2418 }
2419
2420 static Eina_Bool
2421 _item_block_recalc(Item_Block *itb,
2422                    int         in,
2423                    Eina_Bool   qadd)
2424 {
2425    const Eina_List *l;
2426    Elm_Gen_Item *it;
2427    Evas_Coord minw = 0, minh = 0;
2428    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
2429    Evas_Coord y = 0;
2430
2431    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2432    itb->num = in;
2433    EINA_LIST_FOREACH(itb->items, l, it)
2434      {
2435         if (it->generation < it->wd->generation) continue;
2436         showme |= it->item->showme;
2437         if (!itb->realized)
2438           {
2439              if (qadd)
2440                {
2441                   if (!it->item->mincalcd) changed = EINA_TRUE;
2442                   if (changed)
2443                     {
2444                        _item_realize(it, in, EINA_TRUE);
2445                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2446                     }
2447                }
2448              else
2449                {
2450                   _item_realize(it, in, EINA_TRUE);
2451                   _elm_genlist_item_unrealize(it, EINA_TRUE);
2452                }
2453           }
2454         else
2455           _item_realize(it, in, EINA_FALSE);
2456         minh += it->item->minh;
2457         if (minw < it->item->minw) minw = it->item->minw;
2458         in++;
2459         it->x = 0;
2460         it->y = y;
2461         y += it->item->h;
2462      }
2463    itb->minw = minw;
2464    itb->minh = minh;
2465    itb->changed = EINA_FALSE;
2466    itb->position_update = EINA_FALSE;
2467    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2468    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2469    return showme;
2470 }
2471
2472 static void
2473 _item_block_realize(Item_Block *itb)
2474 {
2475    if (itb->realized) return;
2476    itb->realized = EINA_TRUE;
2477    itb->want_unrealize = EINA_FALSE;
2478 }
2479
2480 static void
2481 _item_block_unrealize(Item_Block *itb)
2482 {
2483    const Eina_List *l;
2484    Elm_Gen_Item *it;
2485    Eina_Bool dragging = EINA_FALSE;
2486
2487    if (!itb->realized) return;
2488    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2489    EINA_LIST_FOREACH(itb->items, l, it)
2490      {
2491         if (itb->must_recalc || !it->group)
2492           {
2493              if (it->dragging)
2494                {
2495                   dragging = EINA_TRUE;
2496                   it->want_unrealize = EINA_TRUE;
2497                }
2498              else
2499                _elm_genlist_item_unrealize(it, EINA_FALSE);
2500           }
2501      }
2502    if (!dragging)
2503      {
2504         itb->realized = EINA_FALSE;
2505         itb->want_unrealize = EINA_TRUE;
2506      }
2507    else
2508      itb->want_unrealize = EINA_FALSE;
2509    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2510    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2511 }
2512
2513 static int
2514 _get_space_for_reorder_item(Elm_Gen_Item *it)
2515 {
2516    Evas_Coord rox, roy, row, roh, oy, oh;
2517    Eina_Bool top = EINA_FALSE;
2518    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2519    if (!reorder_it) return 0;
2520
2521    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2522    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2523
2524    if ((it->wd->reorder_start_y < it->item->block->y) &&
2525        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2526      {
2527         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2528         if (it->item->block->count == 1)
2529           it->wd->reorder_rel = it;
2530      }
2531    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2532             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2533      {
2534         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2535      }
2536    else
2537      it->item->block->reorder_offset = 0;
2538
2539    it->item->scrl_y += it->item->block->reorder_offset;
2540
2541    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2542                               rox, roy + (roh / 2), row, 1));
2543    if (top)
2544      {
2545         it->wd->reorder_rel = it;
2546         it->item->scrl_y += it->wd->reorder_it->item->h;
2547         return it->wd->reorder_it->item->h;
2548      }
2549    else
2550      return 0;
2551 }
2552
2553 static Eina_Bool
2554 _reorder_move_animator_cb(void *data)
2555 {
2556    Elm_Gen_Item *it = data;
2557    Eina_Bool down = EINA_FALSE;
2558    double t;
2559    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2560
2561    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2562
2563    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2564    else y = dy;
2565
2566    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2567    if (diff > it->item->h) y = diff / 2;
2568
2569    if (it->item->old_scrl_y < it->item->scrl_y)
2570      {
2571         it->item->old_scrl_y += y;
2572         down = EINA_TRUE;
2573      }
2574    else if (it->item->old_scrl_y > it->item->scrl_y)
2575      {
2576         it->item->old_scrl_y -= y;
2577         down = EINA_FALSE;
2578      }
2579
2580    if (it->edit_obj)
2581      _item_position(it, it->edit_obj, it->item->scrl_x, it->item->old_scrl_y);
2582    else
2583      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2584 //FIXME : group raise
2585 #if 0
2586    _group_items_recalc(it->wd);
2587 #endif
2588
2589    if ((it->wd->reorder_pan_move) ||
2590        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2591        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2592      {
2593         it->item->old_scrl_y = it->item->scrl_y;
2594         it->item->move_effect_enabled = EINA_FALSE;
2595         it->wd->reorder_move_animator = NULL;
2596         return ECORE_CALLBACK_CANCEL;
2597      }
2598    return ECORE_CALLBACK_RENEW;
2599 }
2600
2601 static void
2602 _item_position(Elm_Gen_Item *it,
2603                Evas_Object      *view,
2604                Evas_Coord        it_x,
2605                Evas_Coord        it_y)
2606 {
2607    if (!it) return;
2608    if (!view) return;
2609
2610    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2611    evas_object_resize(view, it->item->w, it->item->h);
2612    evas_object_move(view, it_x, it_y);
2613    evas_object_show(view);
2614    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2615    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2616 }
2617
2618 static void
2619 _item_block_position(Item_Block *itb,
2620                      int         in)
2621 {
2622    const Eina_List *l;
2623    Elm_Gen_Item *it;
2624 //FIXME : group raise
2625 #if 0
2626    Elm_Gen_Item *git;
2627 #endif
2628    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2629    Eina_Bool vis = EINA_FALSE;
2630    Evas_Coord minh = 0;
2631
2632    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2633    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2634    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2635                             &cvw, &cvh);
2636    EINA_LIST_FOREACH(itb->items, l, it)
2637      {
2638         if (it->generation < it->wd->generation) continue;
2639         else if (it->wd->reorder_it == it) continue;
2640         it->x = 0;
2641         it->y = y;
2642         it->item->w = itb->w;
2643         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2644         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2645
2646         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2647                                    cvx, cvy, cvw, cvh));
2648 //FIXME : group raise
2649 #if 0
2650         if (!it->group)
2651 #endif
2652           {
2653              if ((itb->realized) && (!it->realized))
2654                {
2655                   if (vis) _item_realize(it, in, EINA_FALSE);
2656                }
2657              if (it->realized)
2658                {
2659                   if (vis || it->dragging)
2660                     {
2661                        if (it->wd->reorder_mode)
2662                          y += _get_space_for_reorder_item(it);
2663 //FIXME : group raise
2664 #if 0
2665                        git = it->item->group_item;
2666                        if (git)
2667                          {
2668                             if (git->item->scrl_y < oy)
2669                               git->item->scrl_y = oy;
2670                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2671                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2672                             git->item->want_realize = EINA_TRUE;
2673                          }
2674 #endif
2675                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2676                          {
2677                             if (!it->item->move_effect_enabled)
2678                               {
2679                                  it->item->move_effect_enabled = EINA_TRUE;
2680                                  it->wd->reorder_move_animator =
2681                                     ecore_animator_add(
2682                                        _reorder_move_animator_cb, it);
2683                               }
2684                          }
2685                        if (!it->item->move_effect_enabled)
2686                          {
2687                             if ((it->wd->decorate_mode) && (it->itc->decorate_all_item_style))
2688                               _decorate_mode_item_position(it, it->item->scrl_x,
2689                                                        it->item->scrl_y);
2690                             else
2691                               {
2692                                  if (it->item->mode_view)
2693                                    _item_position(it, it->item->mode_view,
2694                                                   it->item->scrl_x,
2695                                                   it->item->scrl_y);
2696                                  else
2697                                    _item_position(it, VIEW(it), it->item->scrl_x,
2698                                                   it->item->scrl_y);
2699                               }
2700                             it->item->old_scrl_y = it->item->scrl_y;
2701                          }
2702                     }
2703                   else
2704                     {
2705                        if (!it->wd->item_moving_effect_timer)
2706                          _elm_genlist_item_unrealize(it, EINA_FALSE);
2707                     }
2708                }
2709              in++;
2710           }
2711 //FIXME : group raise
2712 #if 0
2713         else
2714           {
2715              if (vis) it->item->want_realize = EINA_TRUE;
2716           }
2717 #endif
2718         y += it->item->h;
2719         minh += it->item->minh;
2720      }
2721    if (!itb->wd->reorder_it) itb->minh = minh;
2722    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2723    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2724 }
2725
2726 //FIXME: group raise
2727 #if 0
2728 static void
2729 _group_items_recalc(void *data)
2730 {
2731    Widget_Data *wd = data;
2732    Eina_List *l;
2733    Elm_Gen_Item *git;
2734
2735    evas_event_freeze(evas_object_evas_get(wd->obj));
2736    EINA_LIST_FOREACH(wd->group_items, l, git)
2737      {
2738         if (git->item->want_realize)
2739           {
2740              if (!git->realized)
2741                _item_realize(git, 0, EINA_FALSE);
2742              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2743              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2744              evas_object_show(VIEW(git));
2745              evas_object_raise(VIEW(git));
2746           }
2747         else if (!git->item->want_realize && git->realized)
2748           {
2749              if (!git->dragging)
2750                _elm_genlist_item_unrealize(git, EINA_FALSE);
2751           }
2752      }
2753    evas_event_thaw(evas_object_evas_get(wd->obj));
2754    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2755 }
2756 #endif
2757
2758 static void
2759 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2760 {
2761    Elm_Gen_Item *it = data;
2762    if (!it) return;
2763    it->item->mincalcd = EINA_FALSE;
2764    it->item->block->changeme = EINA_TRUE;
2765    if (it->wd->changed_job) ecore_job_del(it->wd->changed_job);
2766    it->wd->changed_job = ecore_job_add(_changed_job, it->wd);
2767 }
2768
2769 static Eina_Bool
2770 _must_recalc_idler(void *data)
2771 {
2772    Widget_Data *wd = data;
2773    if (wd->calc_job) ecore_job_del(wd->calc_job);
2774    wd->calc_job = ecore_job_add(_calc_job, wd);
2775    wd->must_recalc_idler = NULL;
2776    return ECORE_CALLBACK_CANCEL;
2777 }
2778
2779 static void
2780 _scroll_item(Widget_Data *wd)
2781 {
2782    Elm_Gen_Item *it = NULL;
2783 //FIXME: group raise
2784 #if 0
2785    Evas_Coord gith = 0;
2786 #endif
2787    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
2788    if (!wd->show_item) return;
2789
2790    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
2791    it = wd->show_item;
2792    dx = it->x + it->item->block->x;
2793    dy = it->y + it->item->block->y;
2794    dw = it->item->block->w;
2795    dh = oh;
2796    switch (wd->scrollto_type)
2797      {
2798       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2799 //FIXME: group raise
2800 #if 0
2801          if (it->item->group_item) gith = it->item->group_item->item->h;
2802          dy -= gith;
2803 #endif
2804          break;
2805       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2806          dy += (it->item->h / 2 - oh / 2);
2807          break;
2808       case ELM_GENLIST_ITEM_SCROLLTO_IN:
2809       default:
2810          if ((wd->expanded_item) &&
2811              ((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
2812               - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
2813            {
2814               it = wd->expanded_item;
2815               dx = it->x + it->item->block->x;
2816               dy = it->y + it->item->block->y;
2817 //FIXME: group raise
2818 #if 0
2819               if (it->item->group_item) gith = it->item->group_item->item->h;
2820               dx = it->x + it->item->block->x;
2821               dy = it->y + it->item->block->y - gith;
2822 #endif
2823               dw = it->item->block->w;
2824            }
2825          else
2826            {
2827 //FIXME: group raise
2828 #if 0
2829               if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
2830                 gith = it->item->group_item->item->h;
2831               dy -= gith;
2832 #endif
2833               dh = it->item->h;
2834            }
2835          break;
2836      }
2837    if (wd->bring_in)
2838      elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
2839    else
2840      elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
2841
2842    it->item->showme = EINA_FALSE;
2843    wd->show_item = NULL;
2844    wd->auto_scroll_enabled = EINA_FALSE;
2845    wd->check_scroll = EINA_FALSE;
2846 }
2847
2848 static void
2849 _calc_job(void *data)
2850 {
2851    Widget_Data *wd = data;
2852    Item_Block *itb, *chb = NULL;
2853    Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw;
2854    Evas_Coord pan_w = 0, pan_h = 0;
2855    int in = 0;
2856    Eina_Bool minw_change = EINA_FALSE;
2857    Eina_Bool did_must_recalc = EINA_FALSE;
2858    if (!wd) return;
2859
2860    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2861    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2862
2863    if (wd->w != ow)
2864      wd->w = ow;
2865
2866    evas_event_freeze(evas_object_evas_get(wd->obj));
2867    EINA_INLIST_FOREACH(wd->blocks, itb)
2868      {
2869         Eina_Bool showme = EINA_FALSE;
2870
2871         itb->num = in;
2872         showme = itb->showme;
2873         itb->showme = EINA_FALSE;
2874         if (chb)
2875           {
2876              if (itb->realized) _item_block_unrealize(itb);
2877           }
2878         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2879           {
2880              if (itb->must_recalc)
2881                {
2882                   Eina_List *l;
2883                   Elm_Gen_Item *it;
2884                   EINA_LIST_FOREACH(itb->items, l, it)
2885                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2886                   itb->changed = EINA_TRUE;
2887                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2888                   if (itb->realized) _item_block_unrealize(itb);
2889                   itb->must_recalc = EINA_FALSE;
2890                }
2891              showme = _item_block_recalc(itb, in, EINA_FALSE);
2892              chb = itb;
2893           }
2894         itb->y = y;
2895         itb->x = 0;
2896         minh += itb->minh;
2897         if (minw == -1) minw = itb->minw;
2898         else if ((!itb->must_recalc) && (minw < itb->minw))
2899           {
2900              minw = itb->minw;
2901              minw_change = EINA_TRUE;
2902           }
2903         if (minw > vw)
2904           {
2905              minw = vw;
2906              minw_change = EINA_TRUE;
2907           }
2908         itb->w = minw;
2909         itb->h = itb->minh;
2910         y += itb->h;
2911         in += itb->count;
2912         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2913           wd->check_scroll = EINA_TRUE;
2914      }
2915    if (minw_change)
2916      {
2917         EINA_INLIST_FOREACH(wd->blocks, itb)
2918           {
2919              itb->minw = minw;
2920              itb->w = itb->minw;
2921           }
2922      }
2923    if ((chb) && (EINA_INLIST_GET(chb)->next))
2924      {
2925         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2926           {
2927              if (itb->realized) _item_block_unrealize(itb);
2928           }
2929      }
2930    wd->realminw = minw;
2931    if (minw < wd->w) minw = wd->w;
2932    if ((minw != wd->minw) || (minh != wd->minh))
2933      {
2934         wd->minw = minw;
2935         wd->minh = minh;
2936         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2937         _sizing_eval(wd->obj);
2938         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2939           {
2940              Elm_Gen_Item *it;
2941              Evas_Coord it_y;
2942
2943              it = wd->anchor_item;
2944              it_y = wd->anchor_y;
2945              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2946                                               it->item->block->y + it->y + it_y);
2947              wd->anchor_item = it;
2948              wd->anchor_y = it_y;
2949           }
2950      }
2951    if (did_must_recalc)
2952      {
2953         if (!wd->must_recalc_idler)
2954           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2955      }
2956    if (wd->check_scroll)
2957      {
2958         _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
2959         if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
2960           wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
2961        switch (wd->scrollto_type)
2962           {
2963            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2964               dy = wd->h;
2965               break;
2966            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2967               dy = wd->h / 2;
2968               break;
2969            case ELM_GENLIST_ITEM_SCROLLTO_IN:
2970            default:
2971               dy = 0;
2972               break;
2973           }
2974         if (wd->show_item)
2975           {
2976              if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
2977                  (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
2978                {
2979                   _scroll_item(wd);
2980                }
2981           }
2982      }
2983    wd->calc_job = NULL;
2984    evas_object_smart_changed(wd->pan_smart);
2985    evas_event_thaw(evas_object_evas_get(wd->obj));
2986    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2987 }
2988
2989 static void
2990 _update_job(void *data)
2991 {
2992    Widget_Data *wd = data;
2993    Eina_List *l2;
2994    Item_Block *itb;
2995    int num, num0;
2996    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2997    if (!wd) return;
2998    wd->update_job = NULL;
2999    num = 0;
3000
3001    evas_event_freeze(evas_object_evas_get(wd->obj));
3002    EINA_INLIST_FOREACH(wd->blocks, itb)
3003      {
3004         Evas_Coord itminw, itminh;
3005         Elm_Gen_Item *it;
3006
3007         if (!itb->updateme)
3008           {
3009              num += itb->count;
3010              if (position)
3011                _item_block_position(itb, num);
3012              continue;
3013           }
3014         num0 = num;
3015         recalc = EINA_FALSE;
3016         EINA_LIST_FOREACH(itb->items, l2, it)
3017           {
3018              if (it->item->updateme)
3019                {
3020                   itminw = it->item->minw;
3021                   itminh = it->item->minh;
3022
3023                   if (it->realized)
3024                     {
3025                        _elm_genlist_item_unrealize(it, EINA_FALSE);
3026                        _item_realize(it, num, EINA_FALSE);
3027                        position = EINA_TRUE;
3028                     }
3029                   else
3030                     {
3031                        _item_realize(it, num, EINA_TRUE);
3032                        _elm_genlist_item_unrealize(it, EINA_TRUE);
3033                     }
3034                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
3035                     recalc = EINA_TRUE;
3036                   it->item->updateme = EINA_FALSE;
3037                }
3038              num++;
3039           }
3040         itb->updateme = EINA_FALSE;
3041         if (recalc)
3042           {
3043              position = EINA_TRUE;
3044              itb->changed = EINA_TRUE;
3045              _item_block_recalc(itb, num0, EINA_FALSE);
3046              _item_block_position(itb, num0);
3047           }
3048      }
3049    if (position)
3050      {
3051         if (wd->calc_job) ecore_job_del(wd->calc_job);
3052         wd->calc_job = ecore_job_add(_calc_job, wd);
3053      }
3054    evas_event_thaw(evas_object_evas_get(wd->obj));
3055    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3056 }
3057
3058 static void
3059 _changed_job(void *data)
3060 {
3061    Widget_Data *wd = data; Eina_List *l2;
3062    Item_Block *itb;
3063    int num, num0, position = 0;
3064    Eina_Bool width_changed = EINA_FALSE, height_changed = EINA_FALSE;
3065    if (!wd) return;
3066    wd->changed_job = NULL;
3067    num = 0;
3068    EINA_INLIST_FOREACH(wd->blocks, itb)
3069      {
3070         Evas_Coord itminw, itminh;
3071         Elm_Gen_Item *it;
3072
3073         if (!itb->changeme)
3074           {
3075              num += itb->count;
3076              if (position)
3077                _item_block_position(itb, num);
3078              continue;
3079           }
3080         num0 = num;
3081         width_changed = height_changed = EINA_FALSE;
3082         EINA_LIST_FOREACH(itb->items, l2, it)
3083           {
3084              if ((!it->item->mincalcd) && (it->realized))
3085                {
3086                   Evas_Coord mw = -1, mh = -1;
3087                   itminw = it->item->minw;
3088                   itminh = it->item->minh;
3089
3090                   if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->w;
3091                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3092                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
3093                   if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
3094                   edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
3095                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3096                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
3097                   if (mw > itb->w)
3098                     width_changed = EINA_TRUE;
3099                   else
3100                     mw = itb->w;
3101                   it->item->w = it->item->minw = mw;
3102                   it->item->h = it->item->minh = mh;
3103                   it->item->mincalcd = EINA_TRUE;
3104
3105                   //if ((it->item->minw != itminw) || (it->item->minh != itminh))
3106                   //if ((it->item->minh != itminh))
3107                   //  recalc = 1;
3108                   if ((it->item->minw != itminw))
3109                     width_changed = EINA_TRUE;
3110                   if ((it->item->minh != itminh))
3111                     height_changed = EINA_TRUE;
3112
3113                   if ((!it->wd->group_item_width) && (it->group))
3114                     {
3115                        it->wd->group_item_width = mw;
3116                        it->wd->group_item_height = mh;
3117                     }
3118                   else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
3119                     {
3120                        it->wd->item_width = mw;
3121                        it->wd->item_height = mh;
3122                     }
3123                }
3124              num++;
3125           }
3126         itb->changeme = EINA_FALSE;
3127         // TODO: why this is separated.
3128         if (height_changed)
3129           {
3130              position = 1;
3131              itb->changed = EINA_TRUE;
3132              _item_block_recalc(itb, num0, 0);
3133              _item_block_position(itb, num0);
3134           }
3135         else if (width_changed)
3136           {
3137              _item_block_position(itb, num0);
3138           }
3139      }
3140    if (position)
3141      {
3142         if (wd->calc_job) ecore_job_del(wd->calc_job);
3143         wd->calc_job = ecore_job_add(_calc_job, wd);
3144      }
3145 }
3146
3147 static void
3148 _pan_set(Evas_Object *obj,
3149          Evas_Coord   x,
3150          Evas_Coord   y)
3151 {
3152    Pan *sd = evas_object_smart_data_get(obj);
3153    Item_Block *itb;
3154
3155    if (!sd) return;
3156    //   Evas_Coord ow, oh;
3157    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3158    //   ow = sd->wd->minw - ow;
3159    //   if (ow < 0) ow = 0;
3160    //   oh = sd->wd->minh - oh;
3161    //   if (oh < 0) oh = 0;
3162    //   if (x < 0) x = 0;
3163    //   if (y < 0) y = 0;
3164    //   if (x > ow) x = ow;
3165    //   if (y > oh) y = oh;
3166    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
3167    sd->wd->pan_x = x;
3168    sd->wd->pan_y = y;
3169
3170    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3171      {
3172         if ((itb->y + itb->h) > y)
3173           {
3174              Elm_Gen_Item *it;
3175              Eina_List *l2;
3176
3177              EINA_LIST_FOREACH(itb->items, l2, it)
3178                {
3179                   if ((itb->y + it->y) >= y)
3180                     {
3181                        sd->wd->anchor_item = it;
3182                        sd->wd->anchor_y = -(itb->y + it->y - y);
3183                        goto done;
3184                     }
3185                }
3186           }
3187      }
3188 done:
3189    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
3190 }
3191
3192 static void
3193 _pan_get(Evas_Object *obj,
3194          Evas_Coord  *x,
3195          Evas_Coord  *y)
3196 {
3197    Pan *sd = evas_object_smart_data_get(obj);
3198
3199    if (!sd) return;
3200    if (x) *x = sd->wd->pan_x;
3201    if (y) *y = sd->wd->pan_y;
3202 }
3203
3204 static void
3205 _pan_max_get(Evas_Object *obj,
3206              Evas_Coord  *x,
3207              Evas_Coord  *y)
3208 {
3209    Pan *sd = evas_object_smart_data_get(obj);
3210    Evas_Coord ow, oh;
3211
3212    if (!sd) return;
3213    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3214    ow = sd->wd->minw - ow;
3215    if (ow < 0) ow = 0;
3216    oh = sd->wd->minh - oh;
3217    if (oh < 0) oh = 0;
3218    if (x) *x = ow;
3219    if (y) *y = oh;
3220 }
3221
3222 static void
3223 _pan_min_get(Evas_Object *obj __UNUSED__,
3224              Evas_Coord  *x,
3225              Evas_Coord  *y)
3226 {
3227    if (x) *x = 0;
3228    if (y) *y = 0;
3229 }
3230
3231 static void
3232 _pan_child_size_get(Evas_Object *obj,
3233                     Evas_Coord  *w,
3234                     Evas_Coord  *h)
3235 {
3236    Pan *sd = evas_object_smart_data_get(obj);
3237
3238    if (!sd) return;
3239    if (w) *w = sd->wd->minw;
3240    if (h) *h = sd->wd->minh;
3241 }
3242
3243 static void
3244 _pan_add(Evas_Object *obj)
3245 {
3246    Pan *sd;
3247    Evas_Object_Smart_Clipped_Data *cd;
3248
3249    _pan_sc.add(obj);
3250    cd = evas_object_smart_data_get(obj);
3251    sd = ELM_NEW(Pan);
3252    if (!sd) return;
3253    sd->__clipped_data = *cd;
3254    free(cd);
3255    evas_object_smart_data_set(obj, sd);
3256 }
3257
3258 static void
3259 _pan_del(Evas_Object *obj)
3260 {
3261    Pan *sd = evas_object_smart_data_get(obj);
3262
3263    if (!sd) return;
3264    if (sd->resize_job)
3265      {
3266         ecore_job_del(sd->resize_job);
3267         sd->resize_job = NULL;
3268      }
3269    _pan_sc.del(obj);
3270 }
3271
3272 static void
3273 _pan_resize_job(void *data)
3274 {
3275    Pan *sd = data;
3276    if (!sd) return;
3277    _sizing_eval(sd->wd->obj);
3278    sd->resize_job = NULL;
3279 }
3280
3281 static void
3282 _pan_resize(Evas_Object *obj,
3283             Evas_Coord   w,
3284             Evas_Coord   h)
3285 {
3286    Pan *sd = evas_object_smart_data_get(obj);
3287    Evas_Coord ow, oh;
3288
3289    if (!sd) return;
3290    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3291    if ((ow == w) && (oh == h)) return;
3292    if ((sd->wd->mode == ELM_LIST_COMPRESS) && (ow != w))
3293      {
3294         /* fix me later */
3295         if (sd->resize_job) ecore_job_del(sd->resize_job);
3296         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
3297      }
3298    sd->wd->pan_changed = EINA_TRUE;
3299    evas_object_smart_changed(obj);
3300    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3301    sd->wd->calc_job = NULL;
3302 }
3303
3304 static void
3305 _pan_calculate(Evas_Object *obj)
3306 {
3307    Pan *sd = evas_object_smart_data_get(obj);
3308    Item_Block *itb;
3309    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
3310    int in = 0;
3311 //FIXME: group raise
3312 #if 0
3313    Elm_Gen_Item *git;
3314    Eina_List *l;
3315 #endif
3316
3317    if (!sd) return;
3318    evas_event_freeze(evas_object_evas_get(obj));
3319
3320    if (sd->wd->pan_changed)
3321      {
3322         _calc_job(sd->wd);
3323         sd->wd->pan_changed = EINA_FALSE;
3324      }
3325
3326    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3327    sd->wd->prev_viewport_w = ow;
3328    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
3329 //FIXME: group raise
3330 #if 0
3331    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
3332      {
3333         git->item->want_realize = EINA_FALSE;
3334      }
3335 #endif
3336    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3337      {
3338         itb->w = sd->wd->minw;
3339         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3340                                 itb->y - sd->wd->pan_y + oy,
3341                                 itb->w, itb->h,
3342                                 cvx, cvy, cvw, cvh))
3343           {
3344              if ((!itb->realized) || (itb->changed))
3345                {
3346                   _item_block_realize(itb);
3347
3348                   if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3349                   sd->wd->calc_job = NULL;
3350                   _calc_job(sd->wd);
3351                }
3352              _item_block_position(itb, in);
3353           }
3354         else
3355           {
3356              if (itb->realized) _item_block_unrealize(itb);
3357           }
3358         in += itb->count;
3359      }
3360 //FIXME: group raise
3361 #if 0
3362    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
3363       _group_items_recalc(sd->wd);
3364 #endif
3365    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3366      {
3367         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
3368            sd->wd->reorder_pan_move = EINA_TRUE;
3369         else sd->wd->reorder_pan_move = EINA_FALSE;
3370         evas_object_raise(sd->wd->VIEW(reorder_it));
3371         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
3372         sd->wd->start_time = ecore_loop_time_get();
3373      }
3374
3375    if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
3376      {
3377         if (!sd->wd->item_moving_effect_timer)
3378           {
3379              _item_tree_effect_before(sd->wd->expanded_item);
3380              evas_object_raise(sd->wd->alpha_bg);
3381              evas_object_show(sd->wd->alpha_bg);
3382              sd->wd->start_time = ecore_time_get();
3383              sd->wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, sd->wd);
3384           }
3385      }
3386    else
3387      _item_auto_scroll(sd->wd);
3388
3389    evas_event_thaw(evas_object_evas_get(obj));
3390    evas_event_thaw_eval(evas_object_evas_get(obj));
3391 }
3392
3393 static void
3394 _pan_move(Evas_Object *obj,
3395           Evas_Coord   x __UNUSED__,
3396           Evas_Coord   y __UNUSED__)
3397 {
3398    Pan *sd = evas_object_smart_data_get(obj);
3399
3400    if (!sd) return;
3401
3402    sd->wd->pan_changed = EINA_TRUE;
3403    evas_object_smart_changed(obj);
3404    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3405    sd->wd->calc_job = NULL;
3406 }
3407
3408 static void
3409 _hold_on(void        *data __UNUSED__,
3410          Evas_Object *obj,
3411          void        *event_info __UNUSED__)
3412 {
3413    Widget_Data *wd = elm_widget_data_get(obj);
3414    if (!wd) return;
3415    elm_smart_scroller_hold_set(wd->scr, 1);
3416 }
3417
3418 static void
3419 _hold_off(void        *data __UNUSED__,
3420           Evas_Object *obj,
3421           void        *event_info __UNUSED__)
3422 {
3423    Widget_Data *wd = elm_widget_data_get(obj);
3424    if (!wd) return;
3425    elm_smart_scroller_hold_set(wd->scr, 0);
3426 }
3427
3428 static void
3429 _freeze_on(void        *data __UNUSED__,
3430            Evas_Object *obj,
3431            void        *event_info __UNUSED__)
3432 {
3433    Widget_Data *wd = elm_widget_data_get(obj);
3434    if (!wd) return;
3435    elm_smart_scroller_freeze_set(wd->scr, 1);
3436 }
3437
3438 static void
3439 _freeze_off(void        *data __UNUSED__,
3440             Evas_Object *obj,
3441             void        *event_info __UNUSED__)
3442 {
3443    Widget_Data *wd = elm_widget_data_get(obj);
3444    if (!wd) return;
3445    elm_smart_scroller_freeze_set(wd->scr, 0);
3446 }
3447
3448 static void
3449 _scr_anim_start(void        *data,
3450                 Evas_Object *obj __UNUSED__,
3451                 void        *event_info __UNUSED__)
3452 {
3453    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3454 }
3455
3456 static void
3457 _scr_anim_stop(void        *data,
3458                Evas_Object *obj __UNUSED__,
3459                void        *event_info __UNUSED__)
3460 {
3461    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3462 }
3463
3464 static void
3465 _scr_drag_start(void            *data,
3466                 Evas_Object     *obj __UNUSED__,
3467                 void            *event_info __UNUSED__)
3468 {
3469    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3470 }
3471
3472 static void
3473 _scr_drag_stop(void            *data,
3474                Evas_Object     *obj __UNUSED__,
3475                void            *event_info __UNUSED__)
3476 {
3477    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3478 }
3479
3480 static void
3481 _edge_left(void        *data,
3482            Evas_Object *scr __UNUSED__,
3483            void        *event_info __UNUSED__)
3484 {
3485    Evas_Object *obj = data;
3486    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3487 }
3488
3489 static void
3490 _edge_right(void        *data,
3491             Evas_Object *scr __UNUSED__,
3492             void        *event_info __UNUSED__)
3493 {
3494    Evas_Object *obj = data;
3495    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3496 }
3497
3498 static void
3499 _edge_top(void        *data,
3500           Evas_Object *scr __UNUSED__,
3501           void        *event_info __UNUSED__)
3502 {
3503    Evas_Object *obj = data;
3504    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3505 }
3506
3507 static void
3508 _edge_bottom(void        *data,
3509              Evas_Object *scr __UNUSED__,
3510              void        *event_info __UNUSED__)
3511 {
3512    Evas_Object *obj = data;
3513    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3514 }
3515
3516 static void
3517 _mode_item_realize(Elm_Gen_Item *it)
3518 {
3519    char buf[1024];
3520
3521    if ((it->item->mode_view) || (it->generation < it->wd->generation)) return;
3522
3523    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3524    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3525    edje_object_scale_set(it->item->mode_view,
3526                          elm_widget_scale_get(WIDGET(it)) *
3527                          _elm_config->scale);
3528    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
3529    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
3530
3531    strncpy(buf, "item", sizeof(buf));
3532    if (it->wd->mode == ELM_LIST_COMPRESS)
3533      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3534
3535    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3536    strncat(buf, "/", sizeof(buf) - strlen(buf));
3537    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
3538
3539    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
3540                          elm_widget_style_get(WIDGET(it)));
3541    edje_object_mirrored_set(it->item->mode_view,
3542                             elm_widget_mirrored_get(WIDGET(it)));
3543
3544    /* signal callback add */
3545    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
3546                                   _mouse_down, it);
3547    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
3548                                   _mouse_up, it);
3549    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
3550                                   _mouse_move, it);
3551
3552    /* text_get, content_get, state_get */
3553    /* FIXME: If you see that assert, please notify us and we
3554       will clean our mess */
3555    assert(eina_list_count(it->item->mode_content_objs) == 0);
3556
3557    _item_text_realize(it, it->item->mode_view, &it->item->mode_texts, NULL);
3558    it->item->mode_content_objs =
3559      _item_content_realize(it, it->item->mode_view,
3560                            &it->item->mode_contents, NULL);
3561    _item_state_realize(it, it->item->mode_view, &it->item->mode_states, NULL);
3562
3563    edje_object_part_swallow(it->item->mode_view,
3564                             edje_object_data_get(it->item->mode_view, "mode_part"),
3565                             VIEW(it));
3566
3567    it->want_unrealize = EINA_FALSE;
3568    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3569    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3570 }
3571
3572 static void
3573 _mode_item_unrealize(Elm_Gen_Item *it)
3574 {
3575    Widget_Data *wd = it->wd;
3576    Evas_Object *content;
3577    if (!it->item->mode_view) return;
3578
3579    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3580    elm_widget_stringlist_free(it->item->mode_texts);
3581    it->item->mode_texts = NULL;
3582    elm_widget_stringlist_free(it->item->mode_contents);
3583    it->item->mode_contents = NULL;
3584    elm_widget_stringlist_free(it->item->mode_states);
3585
3586    EINA_LIST_FREE(it->item->mode_content_objs, content)
3587      evas_object_del(content);
3588
3589    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
3590    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3591    evas_object_del(it->item->mode_view);
3592    it->item->mode_view = NULL;
3593
3594    if (wd->mode_item == it)
3595      wd->mode_item = NULL;
3596    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3597    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3598 }
3599
3600 static void
3601 _item_mode_set(Elm_Gen_Item *it)
3602 {
3603    if (!it) return;
3604    Widget_Data *wd = it->wd;
3605    if (!wd) return;
3606    char buf[1024];
3607
3608    wd->mode_item = it;
3609    it->item->nocache_once = EINA_TRUE;
3610
3611    if (wd->scr_hold_timer)
3612      {
3613         ecore_timer_del(wd->scr_hold_timer);
3614         wd->scr_hold_timer = NULL;
3615      }
3616    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3617    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3618
3619    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3620    _mode_item_realize(it);
3621    if (it->item->group_item)
3622      evas_object_raise(it->item->VIEW(group_item));
3623    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
3624    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3625    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3626
3627    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->decorate_type);
3628    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3629 }
3630
3631 static void
3632 _item_mode_unset(Widget_Data *wd)
3633 {
3634    if (!wd) return;
3635    if (!wd->mode_item) return;
3636    char buf[1024], buf2[1024];
3637    Elm_Gen_Item *it;
3638
3639    it = wd->mode_item;
3640    it->item->nocache_once = EINA_TRUE;
3641
3642    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->decorate_type);
3643    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->decorate_type);
3644
3645    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3646    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
3647
3648    wd->mode_item = NULL;
3649 }
3650
3651 static void
3652 _decorate_mode_item_position(Elm_Gen_Item *it, int itx, int ity)
3653 {
3654    if ((!it) || (!it->wd->decorate_mode)) return;
3655    evas_object_resize(it->edit_obj, it->item->w, it->item->h);
3656    evas_object_move(it->edit_obj, itx, ity);
3657 }
3658
3659 static void
3660 _decorate_mode_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3661 {
3662    char buf[1024];
3663    const char *stacking_even;
3664    const char *stacking;
3665
3666    if ((!it) || (it->item->decorate_mode_item_realized) ||
3667        (it->generation < it->wd->generation))
3668      return;
3669
3670    it->edit_obj = edje_object_add(evas_object_evas_get(WIDGET(it)));
3671    edje_object_scale_set(it->edit_obj, elm_widget_scale_get(WIDGET(it)) *
3672                          _elm_config->scale);
3673    evas_object_smart_member_add(it->edit_obj, it->wd->pan_smart);
3674    elm_widget_sub_object_add(WIDGET(it), it->edit_obj);
3675
3676    if (it->item->type & ELM_GENLIST_ITEM_TREE)
3677       strncpy(buf, "tree", sizeof(buf));
3678    else strncpy(buf, "item", sizeof(buf));
3679    if (it->wd->mode == ELM_LIST_COMPRESS)
3680       strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3681
3682    strncat(buf, "/", sizeof(buf) - strlen(buf));
3683    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
3684
3685    _elm_theme_object_set(WIDGET(it),  it->edit_obj, "genlist", buf,
3686                          elm_widget_style_get(WIDGET(it)));
3687
3688    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3689    if (!stacking_even) stacking_even = "above";
3690    it->item->stacking_even = !!strcmp("above", stacking_even);
3691
3692    stacking = edje_object_data_get(VIEW(it), "stacking");
3693    if (!stacking) stacking = "yes";
3694    it->item->nostacking = !!strcmp("yes", stacking);
3695
3696    edje_object_mirrored_set(it->edit_obj,
3697                             elm_widget_mirrored_get(WIDGET(it)));
3698
3699    _elm_genlist_item_odd_even_update(it);
3700    _elm_genlist_item_state_update(it, NULL);
3701
3702    if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,decorate,enabled,effect", "elm");
3703    else edje_object_signal_emit(it->edit_obj, "elm,state,decorate,enabled", "elm");
3704
3705    evas_object_event_callback_del_full(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
3706                                        _mouse_down, it);
3707    evas_object_event_callback_del_full(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
3708                                        _mouse_up, it);
3709    evas_object_event_callback_del_full(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
3710                                        _mouse_move, it);
3711    evas_object_event_callback_del_full(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
3712                                        _multi_down, it);
3713    evas_object_event_callback_del_full(VIEW(it), EVAS_CALLBACK_MULTI_UP,
3714                                        _multi_up, it);
3715    evas_object_event_callback_del_full(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
3716                                        _multi_move, it);
3717
3718    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MOUSE_DOWN,
3719                                   _mouse_down, it);
3720    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MOUSE_UP,
3721                                   _mouse_up, it);
3722    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MOUSE_MOVE,
3723                                   _mouse_move, it);
3724    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MULTI_DOWN,
3725                                   _multi_down, it);
3726    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MULTI_UP,
3727                                   _multi_up, it);
3728    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MULTI_MOVE,
3729                                   _multi_move, it);
3730
3731    _item_text_realize(it, it->edit_obj, &it->item->edit_texts, NULL);
3732    if (it->flipped) edje_object_signal_emit(it->edit_obj, "elm,state,flip,enabled", "elm");
3733    it->item->edit_content_objs =
3734      _item_mode_content_realize(it, it->edit_obj, &it->contents,
3735                                 NULL, &it->item->edit_content_objs,
3736                                 "decorate_contents"); //FIXME
3737    _item_state_realize(it, it->edit_obj, &it->item->edit_states, NULL);
3738    edje_object_part_swallow(it->edit_obj, "elm.swallow.decorate.content", VIEW(it));
3739
3740    _decorate_mode_item_position(it, it->item->scrl_x, it->item->scrl_y);
3741    evas_object_show(it->edit_obj);
3742
3743    it->item->decorate_mode_item_realized = EINA_TRUE;
3744    it->want_unrealize = EINA_FALSE;
3745 }
3746
3747 static void
3748 _decorate_mode_item_unrealize(Elm_Gen_Item *it)
3749 {
3750    Evas_Object *icon;
3751    if ((!it) || (!it->item->decorate_mode_item_realized)) return;
3752
3753    edje_object_part_unswallow(it->edit_obj, VIEW(it));
3754    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3755    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3756    _elm_genlist_item_odd_even_update(it);
3757    _elm_genlist_item_state_update(it, NULL);
3758
3759    evas_object_del(it->edit_obj);
3760    it->edit_obj = NULL;
3761    elm_widget_stringlist_free(it->item->edit_texts);
3762    it->item->edit_texts = NULL;
3763    elm_widget_stringlist_free(it->item->edit_contents);
3764    it->item->edit_contents = NULL;
3765    elm_widget_stringlist_free(it->item->edit_states);
3766    it->item->edit_states = NULL;
3767    EINA_LIST_FREE(it->item->edit_content_objs, icon)
3768      evas_object_del(icon);
3769    edje_object_message_signal_process(it->edit_obj);
3770
3771    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MOUSE_DOWN,
3772                                        _mouse_down, it);
3773    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MOUSE_UP,
3774                                        _mouse_up, it);
3775    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MOUSE_MOVE,
3776                                        _mouse_move, it);
3777    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MULTI_DOWN,
3778                                        _multi_down, it);
3779    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MULTI_UP,
3780                                        _multi_up, it);
3781    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MULTI_MOVE,
3782                                        _multi_move, it);
3783
3784    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
3785                                   _mouse_down, it);
3786    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
3787                                   _mouse_up, it);
3788    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
3789                                   _mouse_move, it);
3790    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
3791                                   _multi_down, it);
3792    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_UP,
3793                                   _multi_up, it);
3794    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
3795                                   _multi_move, it);
3796
3797    it->item->decorate_mode_item_realized = EINA_FALSE;
3798 }
3799
3800 static void
3801 _item_auto_scroll(Widget_Data *wd)
3802 {
3803    if (!wd) return;
3804    Elm_Gen_Item  *tmp_item = NULL;
3805
3806    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3807      {
3808         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3809         if (!tmp_item) return;
3810         wd->show_item = tmp_item;
3811         wd->bring_in = EINA_TRUE;
3812         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3813         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3814           {
3815              wd->show_item->item->showme = EINA_TRUE;
3816              wd->auto_scroll_enabled = EINA_FALSE;
3817           }
3818         else
3819           _scroll_item(wd);
3820      }
3821 }
3822
3823 EAPI Evas_Object *
3824 elm_genlist_add(Evas_Object *parent)
3825 {
3826    Evas_Object *obj;
3827    Evas *e;
3828    Widget_Data *wd;
3829    Evas_Coord minw, minh;
3830    static Evas_Smart *smart = NULL;
3831
3832    if (!smart)
3833      {
3834         static Evas_Smart_Class sc;
3835
3836         evas_object_smart_clipped_smart_set(&_pan_sc);
3837         sc = _pan_sc;
3838         sc.name = "elm_genlist_pan";
3839         sc.version = EVAS_SMART_CLASS_VERSION;
3840         sc.add = _pan_add;
3841         sc.del = _pan_del;
3842         sc.resize = _pan_resize;
3843         sc.move = _pan_move;
3844         sc.calculate = _pan_calculate;
3845         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3846      }
3847
3848    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3849
3850    ELM_SET_WIDTYPE(widtype, "genlist");
3851    ELM_GEN_SETUP(wd);
3852    elm_widget_type_set(obj, "genlist");
3853    elm_widget_sub_object_add(parent, obj);
3854    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3855    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3856    elm_widget_data_set(obj, wd);
3857    elm_widget_del_hook_set(obj, _del_hook);
3858    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3859    elm_widget_theme_hook_set(obj, _theme_hook);
3860    elm_widget_can_focus_set(obj, EINA_TRUE);
3861    elm_widget_event_hook_set(obj, _event_hook);
3862    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3863    elm_widget_translate_hook_set(obj, _translate_hook);
3864
3865    wd->generation = 1;
3866    wd->scr = elm_smart_scroller_add(e);
3867    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_DOWN,
3868                                   _mouse_down_scroller, obj);
3869    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_UP,
3870                                   _mouse_up_scroller, obj);
3871    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_MOVE,
3872                                   _mouse_move_scroller, obj);
3873    elm_smart_scroller_widget_set(wd->scr, obj);
3874    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3875                                        elm_widget_style_get(obj));
3876    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3877                                        _elm_config->thumbscroll_bounce_enable);
3878    elm_widget_resize_object_set(obj, wd->scr);
3879
3880    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3881    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3882    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3883    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3884    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3885    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3886    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3887    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3888
3889    wd->obj = obj;
3890    wd->mode = ELM_LIST_SCROLL;
3891    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3892    wd->item_cache_max = wd->max_items_per_block * 2;
3893    wd->longpress_timeout = _elm_config->longpress_timeout;
3894    wd->highlight = EINA_TRUE;
3895    wd->tree_effect_enabled = _elm_config->effect_enable;
3896
3897    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3898    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3899    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3900    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3901
3902    wd->pan_smart = evas_object_smart_add(e, smart);
3903    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3904    wd->pan->wd = wd;
3905
3906    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3907                                      _pan_set, _pan_get, _pan_max_get,
3908                                      _pan_min_get, _pan_child_size_get);
3909
3910    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3911                              &minw, &minh);
3912    evas_object_size_hint_min_set(obj, minw, minh);
3913
3914    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3915
3916    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3917    _sizing_eval(obj);
3918    return obj;
3919 }
3920
3921 void
3922 _item_select(Elm_Gen_Item *it)
3923 {
3924    Eina_List *l;
3925    Evas_Object *obj;
3926
3927    if ((it->generation < it->wd->generation) || (it->mode_set) ||
3928        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
3929        (it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
3930      return;
3931    if (!it->selected)
3932      {
3933         it->selected = EINA_TRUE;
3934         it->wd->selected = eina_list_append(it->wd->selected, it);
3935      }
3936    else if (it->wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) return;
3937
3938    evas_object_ref(WIDGET(it));
3939    it->walking++;
3940    it->wd->walking++;
3941    if (it->wd->last_selected_item &&
3942        (it != (Elm_Gen_Item *) it->wd->last_selected_item))
3943      {
3944         EINA_LIST_FOREACH(((Elm_Gen_Item *)it->wd->last_selected_item)->content_objs, l, obj)
3945           {
3946              elm_widget_focused_object_clear(obj);
3947              elm_widget_tree_unfocusable_set(obj, EINA_TRUE);
3948           }
3949         ((Elm_Gen_Item *)it->wd->last_selected_item)->can_focus = EINA_FALSE;
3950      }
3951    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3952    if (it->generation == it->wd->generation)
3953      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3954    it->walking--;
3955    it->wd->walking--;
3956    if ((it->wd->clear_me) && (!it->wd->walking))
3957      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3958    else
3959      {
3960         if ((!it->walking) && (it->generation < it->wd->generation))
3961           {
3962              if (!it->relcount)
3963                {
3964                   it->del_cb(it);
3965                   elm_widget_item_free(it);
3966                }
3967           }
3968         else
3969           it->wd->last_selected_item = (Elm_Object_Item *)it;
3970      }
3971    evas_object_unref(WIDGET(it));
3972 }
3973
3974 static Evas_Object *
3975 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
3976 {
3977    return edje_object_part_swallow_get(VIEW(it), part);
3978 }
3979
3980 static void
3981 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
3982 {
3983    if (content && part)
3984      {
3985         it->content_objs = eina_list_append(it->content_objs, content);
3986         edje_object_part_swallow(VIEW(it), part, content);
3987      }
3988 }
3989
3990 static Evas_Object *
3991 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
3992 {
3993    Evas_Object *obj;
3994    obj = edje_object_part_swallow_get(VIEW(it), part);
3995    if (!obj) return NULL;
3996    it->content_objs = eina_list_remove(it->content_objs, obj);
3997    edje_object_part_unswallow(VIEW(it), obj);
3998    return obj;
3999 }
4000
4001 static const char *
4002 _item_text_hook(Elm_Gen_Item *it, const char *part)
4003 {
4004    if (!it->itc->func.text_get) return NULL;
4005    return edje_object_part_text_get(VIEW(it), part);
4006 }
4007
4008 static void
4009 _item_disable_hook(Elm_Object_Item *it)
4010 {
4011    Eina_List *l;
4012    Evas_Object *obj;
4013    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4014
4015    if (_it->generation < _it->wd->generation) return;
4016
4017    if (_it->selected)
4018      elm_genlist_item_selected_set(it, EINA_FALSE);
4019
4020    if (_it->realized)
4021      {
4022         if (elm_widget_item_disabled_get(it))
4023           {
4024              edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
4025              if (_it->edit_obj)
4026                edje_object_signal_emit(_it->edit_obj, "elm,state,disabled", "elm");
4027           }
4028         else
4029           {
4030              edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
4031              if (_it->edit_obj)
4032                edje_object_signal_emit(_it->edit_obj, "elm,state,enabled", "elm");
4033           }
4034         EINA_LIST_FOREACH(_it->content_objs, l, obj)
4035           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
4036      }
4037 }
4038
4039 static Eina_Bool
4040 _item_del_pre_hook(Elm_Object_Item *it)
4041 {
4042    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4043
4044    if ((_it->relcount > 0) || (_it->walking > 0))
4045      {
4046         if (!_it->item->block && (_it->relcount == 1)) goto del;
4047         elm_genlist_item_subitems_clear(it);
4048         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
4049         _elm_genlist_item_del_notserious(_it);
4050         if (_it->item->block)
4051           {
4052              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
4053              _it->item->block->changed = EINA_TRUE;
4054              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
4055              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
4056           }
4057         if (_it->parent)
4058           {
4059              _it->parent->item->items =
4060                 eina_list_remove(_it->parent->item->items, it);
4061              _it->parent = NULL;
4062           }
4063         return EINA_FALSE;
4064      }
4065 del:
4066    _item_del(_it);
4067    return EINA_TRUE;
4068 }
4069
4070 static void
4071 _item_signal_emit_hook(Elm_Object_Item *it,
4072                        const char *emission,
4073                        const char *source)
4074 {
4075    edje_object_signal_emit(VIEW(it), emission, source);
4076 }
4077
4078 Elm_Gen_Item *
4079 _elm_genlist_item_new(Widget_Data              *wd,
4080                       const Elm_Gen_Item_Class *itc,
4081                       const void               *data,
4082                       Elm_Gen_Item             *parent,
4083                       Evas_Smart_Cb             func,
4084                       const void               *func_data)
4085 {
4086    Elm_Gen_Item *it;
4087
4088    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
4089    if (!it) return NULL;
4090    it->wd = wd;
4091    it->generation = wd->generation;
4092    it->itc = itc;
4093    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
4094    it->base.data = data;
4095    it->parent = parent;
4096    it->func.func = func;
4097    it->func.data = func_data;
4098    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
4099    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
4100    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
4101    elm_widget_item_text_get_hook_set(it, _item_text_hook);
4102    elm_widget_item_disable_hook_set(it, _item_disable_hook);
4103    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
4104    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
4105
4106    /* TEMPORARY */
4107    it->sel_cb = (Ecore_Cb)_item_select;
4108
4109    return it;
4110 }
4111
4112 static Elm_Gen_Item *
4113 _item_new(Widget_Data                  *wd,
4114           const Elm_Genlist_Item_Class *itc,
4115           const void                   *data,
4116           Elm_Gen_Item                 *parent,
4117           Elm_Genlist_Item_Type         type,
4118           Evas_Smart_Cb                 func,
4119           const void                   *func_data)
4120 {
4121    Elm_Gen_Item *it, *it2;
4122    int depth = 0;
4123
4124    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
4125    if (!it) return NULL;
4126    it->item = ELM_NEW(Elm_Gen_Item_Type);
4127    it->item->type = type;
4128    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
4129    it->item->expanded_depth = 0;
4130    ELM_GEN_ITEM_SETUP(it);
4131    it->mouse_cursor = NULL;
4132    it->can_focus = EINA_TRUE;
4133    if (it->parent)
4134      {
4135         if (it->parent->group)
4136           it->item->group_item = parent;
4137         else if (it->parent->item->group_item)
4138           it->item->group_item = it->parent->item->group_item;
4139      }
4140    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
4141      {
4142         if (!it2->parent->group) depth += 1;
4143      }
4144    it->item->expanded_depth = depth;
4145    wd->item_count++;
4146    return it;
4147 }
4148
4149 static Item_Block *
4150 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
4151 {
4152    Item_Block *itb;
4153
4154    itb = calloc(1, sizeof(Item_Block));
4155    if (!itb) return NULL;
4156    itb->wd = wd;
4157    if (prepend)
4158      {
4159         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
4160         _item_block_position_update(wd->blocks, 0);
4161      }
4162    else
4163      {
4164         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4165         itb->position_update = EINA_TRUE;
4166         if (wd->blocks != EINA_INLIST_GET(itb))
4167           {
4168              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4169           }
4170         else
4171           {
4172              itb->position = 0;
4173           }
4174      }
4175    return itb;
4176 }
4177
4178 static Eina_Bool
4179 _item_block_add(Widget_Data *wd,
4180                 Elm_Gen_Item *it)
4181 {
4182    Item_Block *itb = NULL;
4183
4184    if (!it->item->rel)
4185      {
4186 newblock:
4187         if (it->item->rel)
4188           {
4189              itb = calloc(1, sizeof(Item_Block));
4190              if (!itb) return EINA_FALSE;
4191              itb->wd = wd;
4192              if (!it->item->rel->item->block)
4193                {
4194                   wd->blocks =
4195                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4196                   itb->items = eina_list_append(itb->items, it);
4197                   itb->position_update = EINA_TRUE;
4198                   it->position = eina_list_count(itb->items);
4199                   it->position_update = EINA_TRUE;
4200
4201                   if (wd->blocks != EINA_INLIST_GET(itb))
4202                     {
4203                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4204                     }
4205                   else
4206                     {
4207                        itb->position = 0;
4208                     }
4209                }
4210              else
4211                {
4212                   Eina_List *tmp;
4213
4214                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
4215                   if (it->item->before)
4216                     {
4217                        wd->blocks = eina_inlist_prepend_relative
4218                            (wd->blocks, EINA_INLIST_GET(itb),
4219                            EINA_INLIST_GET(it->item->rel->item->block));
4220                        itb->items =
4221                          eina_list_prepend_relative_list(itb->items, it, tmp);
4222
4223                        /* Update index from where we prepended */
4224                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4225                        _item_block_position_update(EINA_INLIST_GET(itb),
4226                                                    it->item->rel->item->block->position);
4227                     }
4228                   else
4229                     {
4230                        wd->blocks = eina_inlist_append_relative
4231                            (wd->blocks, EINA_INLIST_GET(itb),
4232                            EINA_INLIST_GET(it->item->rel->item->block));
4233                        itb->items =
4234                          eina_list_append_relative_list(itb->items, it, tmp);
4235
4236                        /* Update block index from where we appended */
4237                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4238                        _item_block_position_update(EINA_INLIST_GET(itb),
4239                                                    it->item->rel->item->block->position + 1);
4240                     }
4241                }
4242           }
4243         else
4244           {
4245              if (it->item->before)
4246                {
4247                   if (wd->blocks)
4248                     {
4249                        itb = (Item_Block *)(wd->blocks);
4250                        if (itb->count >= wd->max_items_per_block)
4251                          {
4252                             itb = _item_block_new(wd, EINA_TRUE);
4253                             if (!itb) return EINA_FALSE;
4254                          }
4255                     }
4256                   else
4257                     {
4258                        itb = _item_block_new(wd, EINA_TRUE);
4259                        if (!itb) return EINA_FALSE;
4260                     }
4261                   itb->items = eina_list_prepend(itb->items, it);
4262
4263                   _item_position_update(itb->items, 0);
4264                }
4265              else
4266                {
4267                   if (wd->blocks)
4268                     {
4269                        itb = (Item_Block *)(wd->blocks->last);
4270                        if (itb->count >= wd->max_items_per_block)
4271                          {
4272                             itb = _item_block_new(wd, EINA_FALSE);
4273                             if (!itb) return EINA_FALSE;
4274                          }
4275                     }
4276                   else
4277                     {
4278                        itb = _item_block_new(wd, EINA_FALSE);
4279                        if (!itb) return EINA_FALSE;
4280                     }
4281                   itb->items = eina_list_append(itb->items, it);
4282                   it->position = eina_list_count(itb->items);
4283                }
4284           }
4285      }
4286    else
4287      {
4288         Eina_List *tmp;
4289
4290         if (it->item->rel->item->queued)
4291           {
4292              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
4293                 on sorted insertion order, so the queue is not always ordered like the item list.
4294                 This lead to issue where we depend on an item that is not yet created. As a quick
4295                 work around, we reschedule the calc of the item and stop reordering the list to
4296                 prevent any nasty issue to show up here.
4297               */
4298              wd->queue = eina_list_append(wd->queue, it);
4299              wd->requeued = EINA_TRUE;
4300              it->item->queued = EINA_TRUE;
4301              return EINA_FALSE;
4302           }
4303         itb = it->item->rel->item->block;
4304         if (!itb) goto newblock;
4305         tmp = eina_list_data_find_list(itb->items, it->item->rel);
4306         if (it->item->before)
4307           {
4308              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
4309              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4310           }
4311         else
4312           {
4313              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
4314              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4315           }
4316      }
4317    itb->count++;
4318    itb->changed = EINA_TRUE;
4319    it->item->block = itb;
4320    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
4321    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
4322    if (it->item->rel)
4323      {
4324         it->item->rel->relcount--;
4325         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
4326           {
4327              _item_del(it->item->rel);
4328              elm_widget_item_free(it->item->rel);
4329           }
4330         it->item->rel = NULL;
4331      }
4332    if (itb->count > itb->wd->max_items_per_block)
4333      {
4334         Item_Block *itb2;
4335         Elm_Gen_Item *it2;
4336         int newc;
4337         Eina_Bool done = EINA_FALSE;
4338
4339         newc = itb->count / 2;
4340
4341         if (EINA_INLIST_GET(itb)->prev)
4342           {
4343              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
4344
4345              if (itbp->count + newc < wd->max_items_per_block / 2)
4346                {
4347                   /* moving items to previous block */
4348                   while ((itb->count > newc) && (itb->items))
4349                     {
4350                        it2 = eina_list_data_get(itb->items);
4351                        itb->items = eina_list_remove_list(itb->items, itb->items);
4352                        itb->count--;
4353
4354                        itbp->items = eina_list_append(itbp->items, it2);
4355                        it2->item->block = itbp;
4356                        itbp->count++;
4357                     }
4358
4359                   done = EINA_TRUE;
4360                }
4361           }
4362
4363         if (!done && EINA_INLIST_GET(itb)->next)
4364           {
4365              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4366
4367              if (itbn->count + newc < wd->max_items_per_block / 2)
4368                {
4369                   /* moving items to next block */
4370                   while ((itb->count > newc) && (itb->items))
4371                     {
4372                        Eina_List *l;
4373
4374                        l = eina_list_last(itb->items);
4375                        it2 = eina_list_data_get(l);
4376                        itb->items = eina_list_remove_list(itb->items, l);
4377                        itb->count--;
4378
4379                        itbn->items = eina_list_prepend(itbn->items, it2);
4380                        it2->item->block = itbn;
4381                        itbn->count++;
4382                     }
4383
4384                   done = EINA_TRUE;
4385                }
4386           }
4387
4388         if (!done)
4389           {
4390              /* moving items to new block */
4391              itb2 = calloc(1, sizeof(Item_Block));
4392              if (!itb2) return EINA_FALSE;
4393              itb2->wd = wd;
4394              wd->blocks =
4395                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
4396                                            EINA_INLIST_GET(itb));
4397              itb2->changed = EINA_TRUE;
4398              while ((itb->count > newc) && (itb->items))
4399                {
4400                   Eina_List *l;
4401
4402                   l = eina_list_last(itb->items);
4403                   it2 = l->data;
4404                   itb->items = eina_list_remove_list(itb->items, l);
4405                   itb->count--;
4406
4407                   itb2->items = eina_list_prepend(itb2->items, it2);
4408                   it2->item->block = itb2;
4409                   itb2->count++;
4410                }
4411           }
4412      }
4413
4414    return EINA_TRUE;
4415 }
4416
4417 static int
4418 _queue_process(Widget_Data *wd)
4419 {
4420    int n;
4421    Eina_Bool showme = EINA_FALSE;
4422    double t0, t;
4423
4424    t0 = ecore_loop_time_get();
4425    //evas_event_freeze(evas_object_evas_get(wd->obj));
4426    for (n = 0; (wd->queue) && (n < 128); n++)
4427      {
4428         Elm_Gen_Item *it;
4429
4430         it = eina_list_data_get(wd->queue);
4431         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4432         it->item->queued = EINA_FALSE;
4433         if (!_item_block_add(wd, it)) continue;
4434         if (!wd->blocks)
4435           _item_block_realize(it->item->block);
4436         t = ecore_time_get();
4437         if (it->item->block->changed)
4438           {
4439              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
4440              it->item->block->changed = 0;
4441              if (wd->pan_changed)
4442                {
4443                   if (wd->calc_job) ecore_job_del(wd->calc_job);
4444                   wd->calc_job = NULL;
4445                   _calc_job(wd);
4446                   wd->pan_changed = EINA_FALSE;
4447                }
4448           }
4449         if (showme) it->item->block->showme = EINA_TRUE;
4450         /* same as eina_inlist_count > 1 */
4451         if (wd->blocks && wd->blocks->next)
4452           {
4453              if ((t - t0) > (ecore_animator_frametime_get())) break;
4454           }
4455      }
4456    //evas_event_thaw(evas_object_evas_get(wd->obj));
4457    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4458    return n;
4459 }
4460
4461 static Eina_Bool
4462 _idle_process(void *data, Eina_Bool *wakeup)
4463 {
4464    Widget_Data *wd = data;
4465
4466    //xxx
4467    //static double q_start = 0.0;
4468    //if (q_start == 0.0) q_start = ecore_time_get();
4469    //xxx
4470    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4471    if (!wd->queue)
4472      {
4473         //xxx
4474         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4475         //xxx
4476         return ECORE_CALLBACK_CANCEL;
4477      }
4478    return ECORE_CALLBACK_RENEW;
4479 }
4480
4481 static Eina_Bool
4482 _item_idle_enterer(void *data)
4483 {
4484    Widget_Data *wd = data;
4485    Eina_Bool wakeup = EINA_FALSE;
4486    Eina_Bool ok = _idle_process(data, &wakeup);
4487
4488    if (wakeup)
4489      {
4490         // wake up mainloop
4491         if (wd->calc_job) ecore_job_del(wd->calc_job);
4492         wd->calc_job = ecore_job_add(_calc_job, wd);
4493      }
4494    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4495    return ok;
4496 }
4497
4498 static void
4499 _item_queue(Widget_Data *wd,
4500             Elm_Gen_Item *it,
4501             Eina_Compare_Cb cb)
4502 {
4503    if (it->item->queued) return;
4504    it->item->queued = EINA_TRUE;
4505    if (cb && !wd->requeued)
4506      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4507    else
4508      wd->queue = eina_list_append(wd->queue, it);
4509 // FIXME: why does a freeze then thaw here cause some genlist
4510 // elm_genlist_item_append() to be much much slower?
4511 //   evas_event_freeze(evas_object_evas_get(wd->obj));
4512    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4513      {
4514         if (wd->queue_idle_enterer)
4515           {
4516              ecore_idle_enterer_del(wd->queue_idle_enterer);
4517              wd->queue_idle_enterer = NULL;
4518           }
4519         _queue_process(wd);
4520      }
4521 //   evas_event_thaw(evas_object_evas_get(wd->obj));
4522 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4523    if (!wd->queue_idle_enterer)
4524      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4525 }
4526
4527 static int
4528 _elm_genlist_item_compare(const void *data, const void *data1)
4529 {
4530    const Elm_Gen_Item *it, *item1;
4531    it = ELM_GEN_ITEM_FROM_INLIST(data);
4532    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4533    return it->wd->item_compare_cb(it, item1);
4534 }
4535
4536 static int
4537 _elm_genlist_item_list_compare(const void *data, const void *data1)
4538 {
4539    const Elm_Gen_Item *it = data;
4540    const Elm_Gen_Item *item1 = data1;
4541    return it->wd->item_compare_cb(it, item1);
4542 }
4543
4544 static void
4545 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4546 {
4547    if (!it) return;
4548    if (!after) return;
4549
4550    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4551    _item_block_del(it);
4552
4553    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4554    it->item->rel = after;
4555    it->item->rel->relcount++;
4556    it->item->before = EINA_FALSE;
4557    if (after->item->group_item) it->item->group_item = after->item->group_item;
4558    _item_queue(it->wd, it, NULL);
4559
4560    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4561 }
4562
4563 static void
4564 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4565 {
4566    if (!it) return;
4567    if (!before) return;
4568
4569    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4570    _item_block_del(it);
4571    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4572    it->item->rel = before;
4573    it->item->rel->relcount++;
4574    it->item->before = EINA_TRUE;
4575    if (before->item->group_item) it->item->group_item = before->item->group_item;
4576    _item_queue(it->wd, it, NULL);
4577
4578    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4579 }
4580
4581 EAPI unsigned int
4582 elm_genlist_items_count(const Evas_Object *obj)
4583 {
4584    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4585    Widget_Data *wd = elm_widget_data_get(obj);
4586    if (!wd) return 0;
4587    return wd->item_count;
4588 }
4589
4590 EAPI Elm_Object_Item *
4591 elm_genlist_item_append(Evas_Object                  *obj,
4592                         const Elm_Genlist_Item_Class *itc,
4593                         const void                   *data,
4594                         Elm_Object_Item              *parent,
4595                         Elm_Genlist_Item_Type         type,
4596                         Evas_Smart_Cb                 func,
4597                         const void                   *func_data)
4598 {
4599    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4600    Widget_Data *wd = elm_widget_data_get(obj);
4601    if (!wd) return NULL;
4602    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4603                                 func, func_data);
4604    if (!it) return NULL;
4605    if (!it->parent)
4606      {
4607         if (it->group)
4608           wd->group_items = eina_list_append(wd->group_items, it);
4609         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4610         it->item->rel = NULL;
4611      }
4612    else
4613      {
4614         Elm_Gen_Item *it2 = NULL;
4615         Eina_List *ll = eina_list_last(it->parent->item->items);
4616         if (ll) it2 = ll->data;
4617         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4618         if (!it2) it2 = it->parent;
4619         wd->items =
4620           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4621                                       EINA_INLIST_GET(it2));
4622         it->item->rel = it2;
4623         it->item->rel->relcount++;
4624      }
4625    it->item->before = EINA_FALSE;
4626    _item_queue(wd, it, NULL);
4627    return (Elm_Object_Item *)it;
4628 }
4629
4630 EAPI Elm_Object_Item *
4631 elm_genlist_item_prepend(Evas_Object                  *obj,
4632                          const Elm_Genlist_Item_Class *itc,
4633                          const void                   *data,
4634                          Elm_Object_Item              *parent,
4635                          Elm_Genlist_Item_Type         type,
4636                          Evas_Smart_Cb                 func,
4637                          const void                   *func_data)
4638 {
4639    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4640    Widget_Data *wd = elm_widget_data_get(obj);
4641    if (!wd) return NULL;
4642    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4643                                 func, func_data);
4644    if (!it) return NULL;
4645    if (!it->parent)
4646      {
4647         if (it->group)
4648           wd->group_items = eina_list_prepend(wd->group_items, it);
4649         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4650         it->item->rel = NULL;
4651      }
4652    else
4653      {
4654         Elm_Gen_Item *it2 = NULL;
4655         Eina_List *ll = it->parent->item->items;
4656         if (ll) it2 = ll->data;
4657         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4658         if (!it2) it2 = it->parent;
4659         wd->items =
4660           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4661                                        EINA_INLIST_GET(it2));
4662         it->item->rel = it2;
4663         it->item->rel->relcount++;
4664      }
4665    it->item->before = EINA_TRUE;
4666    _item_queue(wd, it, NULL);
4667    return (Elm_Object_Item *)it;
4668 }
4669
4670 EAPI Elm_Object_Item *
4671 elm_genlist_item_insert_after(Evas_Object                  *obj,
4672                               const Elm_Genlist_Item_Class *itc,
4673                               const void                   *data,
4674                               Elm_Object_Item              *parent,
4675                               Elm_Object_Item              *after,
4676                               Elm_Genlist_Item_Type         type,
4677                               Evas_Smart_Cb                 func,
4678                               const void                   *func_data)
4679 {
4680    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4681    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4682    Widget_Data *wd = elm_widget_data_get(obj);
4683    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4684    if (!wd) return NULL;
4685    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4686    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4687
4688    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4689                                 func, func_data);
4690    if (!it) return NULL;
4691    if (!it->parent)
4692      {
4693         if ((it->group) && (_after->group))
4694           wd->group_items = eina_list_append_relative(wd->group_items, it,
4695                                                       _after);
4696      }
4697    else
4698      {
4699         it->parent->item->items =
4700            eina_list_append_relative(it->parent->item->items, it, _after);
4701      }
4702    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4703                                            EINA_INLIST_GET(_after));
4704    it->item->rel = _after;
4705    it->item->rel->relcount++;
4706    it->item->before = EINA_FALSE;
4707    _item_queue(wd, it, NULL);
4708    return (Elm_Object_Item *)it;
4709 }
4710
4711 EAPI Elm_Object_Item *
4712 elm_genlist_item_insert_before(Evas_Object                  *obj,
4713                                const Elm_Genlist_Item_Class *itc,
4714                                const void                   *data,
4715                                Elm_Object_Item              *parent,
4716                                Elm_Object_Item              *before,
4717                                Elm_Genlist_Item_Type         type,
4718                                Evas_Smart_Cb                 func,
4719                                const void                   *func_data)
4720 {
4721    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4722    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4723    Widget_Data *wd = elm_widget_data_get(obj);
4724    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4725    if (!wd) return NULL;
4726    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4727    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4728
4729    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4730                                 func, func_data);
4731    if (!it) return NULL;
4732    if (!it->parent)
4733      {
4734         if (it->group && _before->group)
4735           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4736                                                        _before);
4737      }
4738    else
4739      {
4740         it->parent->item->items =
4741            eina_list_prepend_relative(it->parent->item->items, it, _before);
4742      }
4743    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4744                                             EINA_INLIST_GET(_before));
4745    it->item->rel = _before;
4746    it->item->rel->relcount++;
4747    it->item->before = EINA_TRUE;
4748    _item_queue(wd, it, NULL);
4749    return (Elm_Object_Item *)it;
4750 }
4751
4752 EAPI Elm_Object_Item *
4753 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4754                                const Elm_Genlist_Item_Class *itc,
4755                                const void                   *data,
4756                                Elm_Object_Item              *parent,
4757                                Elm_Genlist_Item_Type         type,
4758                                Eina_Compare_Cb               comp,
4759                                Evas_Smart_Cb                 func,
4760                                const void                   *func_data)
4761 {
4762    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4763    Widget_Data *wd = elm_widget_data_get(obj);
4764    if (!wd) return NULL;
4765    Elm_Gen_Item *rel = NULL;
4766    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4767                                 func, func_data);
4768    if (!it) return NULL;
4769
4770    wd->item_compare_cb = comp;
4771
4772    if (it->parent)
4773      {
4774         Eina_List *l;
4775         int cmp_result;
4776
4777         l = eina_list_search_sorted_near_list(it->parent->item->items,
4778                                               _elm_genlist_item_list_compare,
4779                                               it,
4780                                               &cmp_result);
4781         if (l)
4782           rel = eina_list_data_get(l);
4783         else
4784           rel = it->parent;
4785
4786         if (cmp_result >= 0)
4787           {
4788              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4789              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4790              it->item->before = EINA_FALSE;
4791           }
4792         else if (cmp_result < 0)
4793           {
4794              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4795              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4796              it->item->before = EINA_TRUE;
4797           }
4798      }
4799    else
4800      {
4801         if (!wd->state)
4802           {
4803              wd->state = eina_inlist_sorted_state_new();
4804              eina_inlist_sorted_state_init(wd->state, wd->items);
4805              wd->requeued = EINA_FALSE;
4806           }
4807
4808         if (it->group)
4809           wd->group_items = eina_list_append(wd->group_items, it);
4810
4811         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4812                                                     _elm_genlist_item_compare, wd->state);
4813
4814         if (EINA_INLIST_GET(it)->next)
4815           {
4816              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4817              it->item->before = EINA_TRUE;
4818           }
4819         else if (EINA_INLIST_GET(it)->prev)
4820           {
4821              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4822              it->item->before = EINA_FALSE;
4823           }
4824      }
4825
4826    if (rel)
4827      {
4828         it->item->rel = rel;
4829         it->item->rel->relcount++;
4830      }
4831
4832    _item_queue(wd, it, _elm_genlist_item_list_compare);
4833
4834    return (Elm_Object_Item *)it;
4835 }
4836
4837 static void
4838 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4839 {
4840    Eina_Inlist *next, *l;
4841    Widget_Data *wd = elm_widget_data_get(obj);
4842    if (!wd) return;
4843
4844    if (!standby) wd->generation++;
4845
4846    if (wd->state)
4847      {
4848         eina_inlist_sorted_state_free(wd->state);
4849         wd->state = NULL;
4850      }
4851
4852    if (wd->walking > 0)
4853      {
4854         wd->clear_me = EINA_TRUE;
4855         return;
4856      }
4857    evas_event_freeze(evas_object_evas_get(wd->obj));
4858    for (l = wd->items, next = l ? l->next : NULL;
4859         l;
4860         l = next, next = next ? next->next : NULL)
4861      {
4862         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4863
4864         if (it->generation < wd->generation)
4865           {
4866              Elm_Gen_Item *itn = NULL;
4867
4868              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4869              if (itn) itn->walking++; /* prevent early death of subitem */
4870              it->del_cb(it);
4871              elm_widget_item_free(it);
4872              if (itn) itn->walking--;
4873           }
4874      }
4875    wd->clear_me = EINA_FALSE;
4876    wd->pan_changed = EINA_TRUE;
4877    if (wd->calc_job)
4878      {
4879         ecore_job_del(wd->calc_job);
4880         wd->calc_job = NULL;
4881      }
4882    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4883    if (wd->clear_cb) wd->clear_cb(wd);
4884    wd->pan_x = 0;
4885    wd->pan_y = 0;
4886    wd->minw = 0;
4887    wd->minh = 0;
4888
4889    if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4890    wd->alpha_bg = NULL;
4891
4892    if (wd->pan_smart)
4893      {
4894         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4895         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4896      }
4897    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4898    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4899    evas_event_thaw(evas_object_evas_get(wd->obj));
4900    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4901 }
4902
4903 EAPI void
4904 elm_genlist_clear(Evas_Object *obj)
4905 {
4906    ELM_CHECK_WIDTYPE(obj, widtype);
4907    _elm_genlist_clear(obj, EINA_FALSE);
4908 }
4909
4910 EAPI void
4911 elm_genlist_multi_select_set(Evas_Object *obj,
4912                              Eina_Bool    multi)
4913 {
4914    ELM_CHECK_WIDTYPE(obj, widtype);
4915    Widget_Data *wd = elm_widget_data_get(obj);
4916    if (!wd) return;
4917    wd->multi = !!multi;
4918 }
4919
4920 EAPI Eina_Bool
4921 elm_genlist_multi_select_get(const Evas_Object *obj)
4922 {
4923    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4924    Widget_Data *wd = elm_widget_data_get(obj);
4925    if (!wd) return EINA_FALSE;
4926    return wd->multi;
4927 }
4928
4929 EAPI Elm_Object_Item *
4930 elm_genlist_selected_item_get(const Evas_Object *obj)
4931 {
4932    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4933    Widget_Data *wd = elm_widget_data_get(obj);
4934    if (!wd) return NULL;
4935    if (wd->selected) return wd->selected->data;
4936    return NULL;
4937 }
4938
4939 EAPI const Eina_List *
4940 elm_genlist_selected_items_get(const Evas_Object *obj)
4941 {
4942    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4943    Widget_Data *wd = elm_widget_data_get(obj);
4944    if (!wd) return NULL;
4945    return wd->selected;
4946 }
4947
4948 EAPI Eina_List *
4949 elm_genlist_realized_items_get(const Evas_Object *obj)
4950 {
4951    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4952    Widget_Data *wd = elm_widget_data_get(obj);
4953    Eina_List *list = NULL;
4954    Item_Block *itb;
4955    Eina_Bool done = EINA_FALSE;
4956    if (!wd) return NULL;
4957    EINA_INLIST_FOREACH(wd->blocks, itb)
4958      {
4959         if (itb->realized)
4960           {
4961              Eina_List *l;
4962              Elm_Gen_Item *it;
4963
4964              done = EINA_TRUE;
4965              EINA_LIST_FOREACH(itb->items, l, it)
4966                {
4967                   if (it->realized) list = eina_list_append(list, it);
4968                }
4969           }
4970         else
4971           {
4972              if (done) break;
4973           }
4974      }
4975    return list;
4976 }
4977
4978 EAPI Elm_Object_Item *
4979 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4980                            Evas_Coord         x,
4981                            Evas_Coord         y,
4982                            int               *posret)
4983 {
4984    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4985    Widget_Data *wd = elm_widget_data_get(obj);
4986    Evas_Coord ox, oy, ow, oh;
4987    Item_Block *itb;
4988    Evas_Coord lasty;
4989    if (!wd) return NULL;
4990    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4991    lasty = oy;
4992    EINA_INLIST_FOREACH(wd->blocks, itb)
4993      {
4994         Eina_List *l;
4995         Elm_Gen_Item *it;
4996
4997         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4998                                  oy + itb->y - itb->wd->pan_y,
4999                                  itb->w, itb->h, x, y, 1, 1))
5000           continue;
5001         EINA_LIST_FOREACH(itb->items, l, it)
5002           {
5003              Evas_Coord itx, ity;
5004
5005              itx = ox + itb->x + it->x - itb->wd->pan_x;
5006              ity = oy + itb->y + it->y - itb->wd->pan_y;
5007              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
5008                {
5009                   if (posret)
5010                     {
5011                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
5012                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
5013                          *posret = 1;
5014                        else *posret = 0;
5015                     }
5016                   return (Elm_Object_Item *)it;
5017                }
5018              lasty = ity + it->item->h;
5019           }
5020      }
5021    if (posret)
5022      {
5023         if (y > lasty) *posret = 1;
5024         else *posret = -1;
5025      }
5026    return NULL;
5027 }
5028
5029 EAPI Elm_Object_Item *
5030 elm_genlist_first_item_get(const Evas_Object *obj)
5031 {
5032    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5033    Widget_Data *wd = elm_widget_data_get(obj);
5034    if (!wd) return NULL;
5035    if (!wd->items) return NULL;
5036    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
5037    while ((it) && (it->generation < wd->generation))
5038      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5039    return (Elm_Object_Item *)it;
5040 }
5041
5042 EAPI Elm_Object_Item *
5043 elm_genlist_last_item_get(const Evas_Object *obj)
5044 {
5045    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5046    Widget_Data *wd = elm_widget_data_get(obj);
5047    if (!wd) return NULL;
5048    if (!wd->items) return NULL;
5049    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
5050    while ((it) && (it->generation < wd->generation))
5051      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5052    return (Elm_Object_Item *)it;
5053 }
5054
5055 EAPI Elm_Object_Item *
5056 elm_genlist_item_next_get(const Elm_Object_Item *it)
5057 {
5058    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5059    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5060    while (_it)
5061      {
5062         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
5063         if ((_it) && (_it->generation == _it->wd->generation)) break;
5064      }
5065    return (Elm_Object_Item *) _it;
5066 }
5067
5068 EAPI Elm_Object_Item *
5069 elm_genlist_item_prev_get(const Elm_Object_Item *it)
5070 {
5071    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5072    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5073    while (_it)
5074      {
5075         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
5076         if ((_it) && (_it->generation == _it->wd->generation)) break;
5077      }
5078    return (Elm_Object_Item *) _it;
5079 }
5080
5081 EAPI Elm_Object_Item *
5082 elm_genlist_item_parent_get(const Elm_Object_Item *it)
5083 {
5084    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5085    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
5086 }
5087
5088 EAPI void
5089 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
5090 {
5091    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5092    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
5093    if (!wd) return;
5094    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5095
5096    if (!wd->tree_effect_enabled || !wd->move_effect_mode)
5097      _item_subitems_clear(_it);
5098    else
5099      {
5100         if (!wd->item_moving_effect_timer)
5101           {
5102              wd->expanded_item = _it;
5103              _item_tree_effect_before(_it);
5104              evas_object_raise(wd->alpha_bg);
5105              evas_object_show(wd->alpha_bg);
5106              wd->start_time = ecore_time_get();
5107              wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, wd);
5108           }
5109         else
5110            _item_subitems_clear(_it);
5111      }
5112 }
5113
5114 EAPI void
5115 elm_genlist_item_selected_set(Elm_Object_Item *it,
5116                               Eina_Bool selected)
5117 {
5118    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5119    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5120    Widget_Data *wd = _it->wd;
5121    if (!wd) return;
5122    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
5123      return;
5124    selected = !!selected;
5125    if (_it->selected == selected) return;
5126
5127    if (selected)
5128      {
5129         if (!wd->multi)
5130           {
5131              while (wd->selected)
5132                {
5133                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
5134                   _it->unsel_cb(wd->selected->data);
5135                }
5136           }
5137         _it->highlight_cb(_it);
5138         _item_select(_it);
5139         return;
5140      }
5141    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
5142    _it->unsel_cb(_it);
5143 }
5144
5145 EAPI Eina_Bool
5146 elm_genlist_item_selected_get(const Elm_Object_Item *it)
5147 {
5148    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5149    return ((Elm_Gen_Item *)it)->selected;
5150 }
5151
5152 Elm_Gen_Item *
5153 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
5154 {
5155    Elm_Gen_Item *it2;
5156    if (it->item->expanded)
5157      {
5158         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5159      }
5160    else
5161      {
5162         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5163         while (it2)
5164           {
5165              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
5166              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5167           }
5168      }
5169    return it2;
5170 }
5171
5172 static void
5173 _elm_genlist_move_items_set(Elm_Gen_Item *it)
5174 {
5175    Eina_List *l;
5176    Elm_Gen_Item *it2 = NULL;
5177    Evas_Coord ox, oy, ow, oh, dh = 0;
5178
5179    it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
5180
5181    if (it->item->expanded)
5182      {
5183         it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
5184         EINA_LIST_FOREACH(it->wd->move_items, l, it2)
5185           {
5186              if (it2 == it->wd->expanded_next_item) break;
5187              it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
5188           }
5189      }
5190    else
5191      {
5192         evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
5193         it2 = it->wd->expanded_next_item;
5194         while (it2 && (dh < oy + oh))
5195           {
5196              dh += it2->item->h;
5197              it->wd->move_items = eina_list_append(it->wd->move_items, it2);
5198              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5199           }
5200      }
5201 }
5202
5203 EAPI void
5204 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
5205                               Eina_Bool         expanded)
5206 {
5207    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5208    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5209    expanded = !!expanded;
5210    if (_it->item->expanded == expanded) return;
5211    _it->item->expanded = expanded;
5212    _it->wd->expanded_item = _it;
5213    _elm_genlist_move_items_set(_it);
5214
5215    if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
5216       _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
5217
5218    if (_it->item->expanded)
5219      {
5220         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
5221         if (_it->realized)
5222           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
5223         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
5224         _it->wd->auto_scroll_enabled = EINA_TRUE;
5225      }
5226    else
5227      {
5228         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
5229         if (_it->realized)
5230           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
5231         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
5232         _it->wd->auto_scroll_enabled = EINA_FALSE;
5233      }
5234 }
5235
5236 EAPI Eina_Bool
5237 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
5238 {
5239    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5240    return ((Elm_Gen_Item *)it)->item->expanded;
5241 }
5242
5243 EAPI int
5244 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
5245 {
5246    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
5247    return ((Elm_Gen_Item *)it)->item->expanded_depth;
5248 }
5249
5250 EINA_DEPRECATED EAPI void
5251 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
5252                                   Eina_Bool         display_only)
5253 {
5254    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5255    display_only = !!display_only;
5256
5257    if (display_only)
5258      elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
5259    else
5260      {
5261         Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5262         if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5263           elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DEFAULT);
5264      }
5265 }
5266
5267 EINA_DEPRECATED EAPI Eina_Bool
5268 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
5269 {
5270    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5271    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5272    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5273    Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5274    if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5275      return EINA_TRUE;
5276    return EINA_FALSE;
5277 }
5278
5279 static Eina_Bool
5280 _elm_genlist_item_compute_coordinates(Elm_Object_Item *it,
5281                                       Elm_Genlist_Item_Scrollto_Type type,
5282                                       Evas_Coord *x,
5283                                       Evas_Coord *y,
5284                                       Evas_Coord *w,
5285                                       Evas_Coord *h)
5286 {
5287    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5288    Evas_Coord gith = 0;
5289    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5290    if ((_it->item->queued) || (!_it->item->mincalcd))
5291      {
5292         _it->wd->show_item = _it;
5293         _it->wd->bring_in = EINA_FALSE;
5294         _it->wd->scrollto_type = type;
5295         _it->item->showme = EINA_TRUE;
5296         return EINA_FALSE;
5297      }
5298    if (_it->wd->show_item)
5299      {
5300         _it->wd->show_item->item->showme = EINA_FALSE;
5301         _it->wd->show_item = NULL;
5302      }
5303
5304    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
5305    if (type==ELM_GENLIST_ITEM_SCROLLTO_IN)
5306      {
5307         if ((_it->item->group_item) &&
5308            (_it->wd->pan_y > (_it->y + _it->item->block->y)))
5309             gith = _it->item->group_item->item->h;
5310
5311         *h = _it->item->h;
5312         *y = _it->y + _it->item->block->y - gith;
5313      }
5314    else if (type==ELM_GENLIST_ITEM_SCROLLTO_TOP)
5315      {
5316         if (_it->item->group_item) gith = _it->item->group_item->item->h;
5317         *y = _it->y + _it->item->block->y - gith;
5318      }
5319    else if (type==ELM_GENLIST_ITEM_SCROLLTO_MIDDLE)
5320      {
5321         *y = _it->y + _it->item->block->y - *h / 2 + _it->item->h / 2;
5322      }
5323    else
5324      return EINA_FALSE;
5325
5326    *x = _it->x + _it->item->block->x;
5327    *w = _it->item->block->w;
5328    return EINA_TRUE;
5329 }
5330
5331 EAPI void
5332 elm_genlist_item_promote(Elm_Object_Item *it)
5333 {
5334    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5335    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5336    if (_it->generation < _it->wd->generation) return;
5337    _item_move_before(_it,
5338                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
5339 }
5340
5341 EAPI void
5342 elm_genlist_item_demote(Elm_Object_Item *it)
5343 {
5344    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5345    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5346    if (_it->generation < _it->wd->generation) return;
5347    _item_move_after(_it,
5348                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
5349 }
5350
5351 EAPI void
5352 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5353 {
5354    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5355    Evas_Coord x, y, w, h;
5356    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5357
5358    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
5359      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
5360 }
5361
5362 EAPI void
5363 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5364 {
5365
5366    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5367    Evas_Coord x, y, w, h;
5368    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5369
5370    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
5371      elm_smart_scroller_region_bring_in(_it->wd->scr,x, y, w, h);
5372 }
5373
5374 EAPI void
5375 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
5376 {
5377    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5378
5379    Evas_Object *content;
5380    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
5381      {
5382         elm_widget_sub_object_del(WIDGET(it), content);
5383         evas_object_smart_member_del(content);
5384         evas_object_hide(content);
5385         if (l)
5386           *l = eina_list_append(*l, content);
5387      }
5388 }
5389
5390 EAPI void
5391 elm_genlist_item_update(Elm_Object_Item *it)
5392 {
5393    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5394    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5395
5396    if (!_it->item->block) return;
5397    if (_it->generation < _it->wd->generation) return;
5398    _it->item->mincalcd = EINA_FALSE;
5399    _it->item->updateme = EINA_TRUE;
5400    _it->item->block->updateme = EINA_TRUE;
5401    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5402    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5403 }
5404
5405 EAPI void
5406 elm_genlist_item_fields_update(Elm_Object_Item *it,
5407                                const char *parts,
5408                                Elm_Genlist_Item_Field_Type itf)
5409 {
5410    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5411    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5412
5413    if (!_it->item->block) return;
5414    if (_it->generation < _it->wd->generation) return;
5415
5416    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
5417      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
5418    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
5419      {
5420         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
5421                                                    &_it->contents, parts);
5422         _it->content_objs = _item_content_realize(_it, VIEW(_it),
5423                                                  &_it->contents, parts);
5424
5425         if (_it->flipped)
5426           {
5427              _it->content_objs = _item_mode_content_unrealize(_it, VIEW(_it),
5428                                                               &_it->contents, parts, &_it->content_objs, "flips");
5429              _it->content_objs = _item_mode_content_realize(_it, VIEW(_it),
5430                                                             &_it->contents, parts, &_it->content_objs, "flips");
5431           }
5432
5433         if (_it->item->mode_view)
5434           {
5435              _it->item->mode_content_objs = _item_mode_content_unrealize(_it, _it->item->mode_view,
5436                                                                          &_it->item->mode_contents, parts, &_it->item->mode_content_objs, "contents");
5437              _it->item->mode_content_objs = _item_mode_content_realize(_it, _it->item->mode_view,
5438                                                                  &_it->item->mode_contents, parts, &_it->item->mode_content_objs, "contents");
5439           }
5440
5441         if (_it->wd->decorate_mode)
5442           {
5443              _it->item->edit_content_objs = _item_mode_content_unrealize(_it, _it->edit_obj,
5444                                                                          &_it->contents, parts, &_it->item->edit_content_objs, "decorate_contents");
5445              _it->item->edit_content_objs = _item_mode_content_realize(_it, _it->edit_obj,
5446                                                                  &_it->contents, parts, &_it->item->edit_content_objs, "decorate_contents"); // FIXME: is it "decorate_contents"??
5447           }
5448      }
5449    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
5450      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
5451 }
5452
5453 EAPI void
5454 elm_genlist_item_item_class_update(Elm_Object_Item *it,
5455                                    const Elm_Genlist_Item_Class *itc)
5456 {
5457    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5458    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5459
5460    if (!_it->item->block) return;
5461    EINA_SAFETY_ON_NULL_RETURN(itc);
5462    if (_it->generation < _it->wd->generation) return;
5463    _it->itc = itc;
5464    _it->item->nocache_once = EINA_TRUE;
5465    elm_genlist_item_update(it);
5466 }
5467
5468 EAPI const Elm_Genlist_Item_Class *
5469 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
5470 {
5471    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5472    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5473    if (_it->generation < _it->wd->generation) return NULL;
5474    return _it->itc;
5475 }
5476
5477 static Evas_Object *
5478 _elm_genlist_item_label_create(void        *data,
5479                                Evas_Object *obj __UNUSED__,
5480                                Evas_Object *tooltip,
5481                                void        *it __UNUSED__)
5482 {
5483    Evas_Object *label = elm_label_add(tooltip);
5484    if (!label)
5485      return NULL;
5486    elm_object_style_set(label, "tooltip");
5487    elm_object_text_set(label, data);
5488    return label;
5489 }
5490
5491 static void
5492 _elm_genlist_item_label_del_cb(void        *data,
5493                                Evas_Object *obj __UNUSED__,
5494                                void        *event_info __UNUSED__)
5495 {
5496    eina_stringshare_del(data);
5497 }
5498
5499 EAPI void
5500 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5501                                   const char      *text)
5502 {
5503    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5504    text = eina_stringshare_add(text);
5505    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5506                                            text,
5507                                            _elm_genlist_item_label_del_cb);
5508 }
5509
5510 EAPI void
5511 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
5512                                         Elm_Tooltip_Item_Content_Cb func,
5513                                         const void                 *data,
5514                                         Evas_Smart_Cb               del_cb)
5515 {
5516    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5517    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5518
5519    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5520      return;
5521
5522    if (_it->tooltip.del_cb)
5523      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5524
5525    _it->tooltip.content_cb = func;
5526    _it->tooltip.data = data;
5527    _it->tooltip.del_cb = del_cb;
5528
5529    if (VIEW(_it))
5530      {
5531         elm_widget_item_tooltip_content_cb_set(_it,
5532                                                _it->tooltip.content_cb,
5533                                                _it->tooltip.data, NULL);
5534         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5535         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5536      }
5537
5538    return;
5539
5540 error:
5541    if (del_cb) del_cb((void *)data, NULL, NULL);
5542 }
5543
5544 EAPI void
5545 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5546 {
5547    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5548    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5549
5550    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5551      elm_widget_item_tooltip_unset(_it);
5552
5553    if (_it->tooltip.del_cb)
5554      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5555    _it->tooltip.del_cb = NULL;
5556    _it->tooltip.content_cb = NULL;
5557    _it->tooltip.data = NULL;
5558    _it->tooltip.free_size = EINA_FALSE;
5559    if (_it->tooltip.style)
5560      elm_genlist_item_tooltip_style_set(it, NULL);
5561 }
5562
5563 EAPI void
5564 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5565                                    const char       *style)
5566 {
5567    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5568    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5569
5570    eina_stringshare_replace(&_it->tooltip.style, style);
5571    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5572 }
5573
5574 EAPI const char *
5575 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5576 {
5577    return elm_object_item_tooltip_style_get(it);
5578 }
5579
5580 EAPI Eina_Bool
5581 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5582                                          Eina_Bool disable)
5583 {
5584    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5585    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5586
5587    _it->tooltip.free_size = disable;
5588    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5589    return EINA_TRUE;
5590 }
5591
5592 EAPI Eina_Bool
5593 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5594 {
5595    return elm_object_tooltip_window_mode_get(VIEW(it));
5596 }
5597
5598 EAPI void
5599 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5600                             const char       *cursor)
5601 {
5602    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5603    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5604    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5605    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5606 }
5607
5608 EAPI const char *
5609 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5610 {
5611    return elm_widget_item_cursor_get(it);
5612 }
5613
5614 EAPI void
5615 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5616 {
5617    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5618    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5619
5620    if (!_it->mouse_cursor) return;
5621
5622    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5623
5624    eina_stringshare_del(_it->mouse_cursor);
5625    _it->mouse_cursor = NULL;
5626 }
5627
5628 EAPI void
5629 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
5630                                   const char       *style)
5631 {
5632    elm_widget_item_cursor_style_set(it, style);
5633 }
5634
5635 EAPI const char *
5636 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5637 {
5638    return elm_widget_item_cursor_style_get(it);
5639 }
5640
5641 EAPI void
5642 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5643                                         Eina_Bool        engine_only)
5644 {
5645    elm_widget_item_cursor_engine_only_set(it, engine_only);
5646 }
5647
5648 EAPI Eina_Bool
5649 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5650 {
5651    return elm_widget_item_cursor_engine_only_get(it);
5652 }
5653
5654 EAPI int
5655 elm_genlist_item_index_get(const Elm_Object_Item *it)
5656 {
5657    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5658    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5659
5660    if (_it->item->block)
5661      return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5662    return -1;
5663 }
5664
5665 EAPI void
5666 elm_genlist_mode_set(Evas_Object  *obj,
5667                      Elm_List_Mode mode)
5668 {
5669    ELM_CHECK_WIDTYPE(obj, widtype);
5670    Widget_Data *wd = elm_widget_data_get(obj);
5671    if (!wd) return;
5672    if (wd->mode == mode) return;
5673    wd->mode = mode;
5674    if (wd->mode == ELM_LIST_COMPRESS)
5675      elm_genlist_homogeneous_set(obj, EINA_FALSE);
5676    _sizing_eval(obj);
5677 }
5678
5679
5680 EAPI Elm_List_Mode
5681 elm_genlist_mode_get(const Evas_Object *obj)
5682 {
5683    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5684    Widget_Data *wd = elm_widget_data_get(obj);
5685    if (!wd) return ELM_LIST_LAST;
5686    return wd->mode;
5687 }
5688
5689 EAPI void
5690 elm_genlist_bounce_set(Evas_Object *obj,
5691                        Eina_Bool    h_bounce,
5692                        Eina_Bool    v_bounce)
5693 {
5694    ELM_CHECK_WIDTYPE(obj, widtype);
5695    Widget_Data *wd = elm_widget_data_get(obj);
5696    if (!wd) return;
5697    wd->h_bounce = !!h_bounce;
5698    wd->v_bounce = !!v_bounce;
5699    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5700 }
5701
5702 EAPI void
5703 elm_genlist_bounce_get(const Evas_Object *obj,
5704                        Eina_Bool         *h_bounce,
5705                        Eina_Bool         *v_bounce)
5706 {
5707    ELM_CHECK_WIDTYPE(obj, widtype);
5708    Widget_Data *wd = elm_widget_data_get(obj);
5709    if (!wd) return;
5710    if (h_bounce) *h_bounce = wd->h_bounce;
5711    if (v_bounce) *v_bounce = wd->v_bounce;
5712 }
5713
5714 EAPI void
5715 elm_genlist_homogeneous_set(Evas_Object *obj,
5716                             Eina_Bool    homogeneous)
5717 {
5718    ELM_CHECK_WIDTYPE(obj, widtype);
5719    Widget_Data *wd = elm_widget_data_get(obj);
5720    if (!wd) return;
5721    wd->homogeneous = !!homogeneous;
5722 }
5723
5724 EAPI Eina_Bool
5725 elm_genlist_homogeneous_get(const Evas_Object *obj)
5726 {
5727    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5728    Widget_Data *wd = elm_widget_data_get(obj);
5729    if (!wd) return EINA_FALSE;
5730    return wd->homogeneous;
5731 }
5732
5733 EAPI void
5734 elm_genlist_block_count_set(Evas_Object *obj,
5735                             int          count)
5736 {
5737    ELM_CHECK_WIDTYPE(obj, widtype);
5738    Widget_Data *wd = elm_widget_data_get(obj);
5739    if (!wd) return;
5740    wd->max_items_per_block = count;
5741    wd->item_cache_max = wd->max_items_per_block * 2;
5742    _item_cache_clean(wd);
5743 }
5744
5745 EAPI int
5746 elm_genlist_block_count_get(const Evas_Object *obj)
5747 {
5748    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5749    Widget_Data *wd = elm_widget_data_get(obj);
5750    if (!wd) return 0;
5751    return wd->max_items_per_block;
5752 }
5753
5754 EAPI void
5755 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5756                                   double       timeout)
5757 {
5758    ELM_CHECK_WIDTYPE(obj, widtype);
5759    Widget_Data *wd = elm_widget_data_get(obj);
5760    if (!wd) return;
5761    wd->longpress_timeout = timeout;
5762 }
5763
5764 EAPI double
5765 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5766 {
5767    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5768    Widget_Data *wd = elm_widget_data_get(obj);
5769    if (!wd) return 0;
5770    return wd->longpress_timeout;
5771 }
5772
5773 EAPI void
5774 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5775                                 Elm_Scroller_Policy policy_h,
5776                                 Elm_Scroller_Policy policy_v)
5777 {
5778    ELM_CHECK_WIDTYPE(obj, widtype);
5779    Widget_Data *wd = elm_widget_data_get(obj);
5780    if ((!wd) || (!wd->scr)) return;
5781    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5782        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5783      return;
5784    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5785 }
5786
5787 EAPI void
5788 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5789                                 Elm_Scroller_Policy *policy_h,
5790                                 Elm_Scroller_Policy *policy_v)
5791 {
5792    ELM_CHECK_WIDTYPE(obj, widtype);
5793    Widget_Data *wd = elm_widget_data_get(obj);
5794    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5795    if ((!wd) || (!wd->scr)) return;
5796    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5797    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5798    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5799 }
5800
5801 EAPI void
5802 elm_genlist_realized_items_update(Evas_Object *obj)
5803 {
5804    ELM_CHECK_WIDTYPE(obj, widtype);
5805
5806    Eina_List *list, *l;
5807    Elm_Object_Item *it;
5808
5809    list = elm_genlist_realized_items_get(obj);
5810    EINA_LIST_FOREACH(list, l, it)
5811      elm_genlist_item_update(it);
5812 }
5813
5814 EAPI void
5815 elm_genlist_item_decorate_mode_set(Elm_Object_Item  *it,
5816                                    const char       *decorate_type,
5817                                    Eina_Bool         mode_set)
5818 {
5819    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5820    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5821
5822    Widget_Data *wd = _it->wd;
5823    Eina_List *l;
5824    Elm_Object_Item *it2;
5825
5826    if (!wd) return;
5827    if (!decorate_type) return;
5828    if ((_it->generation < _it->wd->generation) ||
5829        elm_widget_item_disabled_get(_it)) return;
5830    if (wd->decorate_mode) return;
5831
5832    if ((wd->mode_item == _it) &&
5833        (!strcmp(decorate_type, wd->decorate_type)) &&
5834        (mode_set))
5835       return;
5836    if (!_it->itc->decorate_item_style) return;
5837    _it->mode_set = mode_set;
5838
5839    if (wd->multi)
5840      {
5841         EINA_LIST_FOREACH(wd->selected, l, it2)
5842           if (((Elm_Gen_Item *)it2)->realized)
5843             elm_genlist_item_selected_set(it2, EINA_FALSE);
5844      }
5845    else
5846      {
5847         it2 = elm_genlist_selected_item_get(wd->obj);
5848         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5849           elm_genlist_item_selected_set(it2, EINA_FALSE);
5850      }
5851
5852    if (((wd->decorate_type) && (strcmp(decorate_type, wd->decorate_type))) ||
5853        (mode_set) ||
5854        ((_it == wd->mode_item) && (!mode_set)))
5855      _item_mode_unset(wd);
5856
5857    eina_stringshare_replace(&wd->decorate_type, decorate_type);
5858    if (mode_set) _item_mode_set(_it);
5859 }
5860
5861 EAPI const char *
5862 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5863 {
5864    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5865    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5866    return _it->wd->decorate_type;
5867 }
5868
5869 EAPI const Elm_Object_Item *
5870 elm_genlist_decorated_item_get(const Evas_Object *obj)
5871 {
5872    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5873    Widget_Data *wd = elm_widget_data_get(obj);
5874    if (!wd) return NULL;
5875    return (Elm_Object_Item *) wd->mode_item;
5876 }
5877
5878 EAPI Eina_Bool
5879 elm_genlist_decorate_mode_get(const Evas_Object *obj)
5880 {
5881    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5882    Widget_Data *wd = elm_widget_data_get(obj);
5883    if (!wd) return EINA_FALSE;
5884
5885    return wd->decorate_mode;
5886 }
5887
5888 EAPI void
5889 elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
5890 {
5891    ELM_CHECK_WIDTYPE(obj, widtype);
5892    Eina_List *list, *l;
5893    Elm_Gen_Item *it;
5894
5895    Widget_Data *wd = elm_widget_data_get(obj);
5896    if (!wd) return;
5897    decorated = !!decorated;
5898    if (wd->decorate_mode == decorated) return;
5899    wd->decorate_mode = decorated;
5900
5901    list = elm_genlist_realized_items_get(obj);
5902    if (!wd->decorate_mode)
5903      {
5904         EINA_LIST_FOREACH(list, l, it)
5905           {
5906              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5907                _decorate_mode_item_unrealize(it);
5908           }
5909         _item_cache_zero(wd);
5910      }
5911    else
5912      {
5913         EINA_LIST_FOREACH(list, l, it)
5914           {
5915              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5916                {
5917                   if (it->selected) _item_unselect(it);
5918                   if (it->itc->decorate_all_item_style)
5919                      _decorate_mode_item_realize(it, EINA_TRUE);
5920                }
5921           }
5922      }
5923    if (wd->calc_job) ecore_job_del(wd->calc_job);
5924    wd->calc_job = ecore_job_add(_calc_job, wd);
5925 }
5926
5927 EAPI void
5928 elm_genlist_reorder_mode_set(Evas_Object *obj,
5929                              Eina_Bool    reorder_mode)
5930 {
5931    ELM_CHECK_WIDTYPE(obj, widtype);
5932    Widget_Data *wd = elm_widget_data_get(obj);
5933    if (!wd) return;
5934    wd->reorder_mode = !!reorder_mode;
5935 }
5936
5937 EAPI Eina_Bool
5938 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5939 {
5940    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5941    Widget_Data *wd = elm_widget_data_get(obj);
5942    if (!wd) return EINA_FALSE;
5943    return wd->reorder_mode;
5944 }
5945
5946 EAPI Elm_Genlist_Item_Type
5947 elm_genlist_item_type_get(const Elm_Object_Item *it)
5948 {
5949    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5950    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5951    return _it->item->type;
5952 }
5953
5954 EAPI Elm_Genlist_Item_Class *
5955 elm_genlist_item_class_new(void)
5956 {
5957    Elm_Genlist_Item_Class *itc;
5958
5959    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5960    if (!itc)
5961      return NULL;
5962    itc->version = CLASS_ALLOCATED;
5963    itc->refcount = 1;
5964    itc->delete_me = EINA_FALSE;
5965
5966    return itc;
5967 }
5968
5969 EAPI void
5970 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5971 {
5972    if (itc && (itc->version == CLASS_ALLOCATED))
5973      {
5974         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5975         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5976         else
5977           {
5978              itc->version = 0;
5979              free(itc);
5980           }
5981      }
5982 }
5983
5984 EAPI void
5985 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5986 {
5987    if (itc && (itc->version == CLASS_ALLOCATED))
5988      {
5989         itc->refcount++;
5990         if (itc->refcount == 0) itc->refcount--;
5991      }
5992 }
5993
5994 EAPI void
5995 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5996 {
5997    if (itc && (itc->version == CLASS_ALLOCATED))
5998      {
5999         if (itc->refcount > 0) itc->refcount--;
6000         if (itc->delete_me && (!itc->refcount))
6001           elm_genlist_item_class_free(itc);
6002      }
6003 }
6004
6005 void _flip_job(void *data)
6006 {
6007    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
6008    _elm_genlist_item_unrealize(it, EINA_FALSE);
6009    if (it->selected) _item_unselect(it);
6010    it->flipped = EINA_TRUE;
6011    it->item->nocache = EINA_TRUE;
6012 }
6013
6014 EAPI void
6015 elm_genlist_item_flip_set(Elm_Object_Item *it,
6016                           Eina_Bool flip)
6017 {
6018    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6019    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6020
6021    flip = !!flip;
6022    if (_it->flipped == flip) return;
6023
6024    if (flip)
6025      {
6026         ecore_job_add(_flip_job, _it);
6027         if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
6028         _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
6029      }
6030    else
6031      {
6032         _it->flipped = flip;
6033         _item_cache_zero(_it->wd);
6034         elm_genlist_item_update(it);
6035         _it->item->nocache = EINA_FALSE;
6036      }
6037 }
6038
6039 EAPI Eina_Bool
6040 elm_genlist_item_flip_get(const Elm_Object_Item *it)
6041 {
6042    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
6043    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6044    return _it->flipped;
6045 }
6046
6047 EAPI void
6048 elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
6049 {
6050    ELM_CHECK_WIDTYPE(obj, widtype);
6051    Widget_Data *wd = elm_widget_data_get(obj);
6052    if (!wd) return;
6053    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6054      return;
6055    if (wd->select_mode != mode)
6056      wd->select_mode = mode;
6057 }
6058
6059 EAPI Elm_Object_Select_Mode
6060 elm_genlist_select_mode_get(const Evas_Object *obj)
6061 {
6062    ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
6063    Widget_Data *wd = elm_widget_data_get(obj);
6064    if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
6065    return wd->select_mode;
6066 }
6067
6068 EAPI void
6069 elm_genlist_highlight_mode_set(Evas_Object *obj,
6070                                Eina_Bool    highlight)
6071 {
6072    ELM_CHECK_WIDTYPE(obj, widtype);
6073    Widget_Data *wd = elm_widget_data_get(obj);
6074    if (!wd) return;
6075    wd->highlight = !!highlight;
6076 }
6077
6078 EAPI Eina_Bool
6079 elm_genlist_highlight_mode_get(const Evas_Object *obj)
6080 {
6081    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6082    Widget_Data *wd = elm_widget_data_get(obj);
6083    if (!wd) return EINA_FALSE;
6084    return wd->highlight;
6085 }
6086
6087 EAPI void
6088 elm_genlist_item_select_mode_set(Elm_Object_Item *it,
6089                                  Elm_Object_Select_Mode mode)
6090 {
6091    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6092    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6093    if (!_it) return;
6094    if (_it->generation < _it->wd->generation) return;
6095    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6096      return;
6097    if (_it->select_mode != mode)
6098      _it->select_mode = mode;
6099
6100    if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
6101      {
6102         _it->item->mincalcd = EINA_FALSE;
6103         _it->item->updateme = EINA_TRUE;
6104         if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
6105         if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
6106         _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
6107      }
6108 }
6109
6110 EAPI Elm_Object_Select_Mode
6111 elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
6112 {
6113    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
6114    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6115    if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
6116    return _it->select_mode;
6117 }
6118
6119 /* for gengrid as of now */
6120 void
6121 _elm_genlist_page_relative_set(Evas_Object *obj,
6122                                double       h_pagerel,
6123                                double       v_pagerel)
6124 {
6125    Evas_Coord pagesize_h;
6126    Evas_Coord pagesize_v;
6127
6128    ELM_CHECK_WIDTYPE(obj, widtype);
6129    Widget_Data *wd = elm_widget_data_get(obj);
6130    if (!wd) return;
6131
6132    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
6133    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
6134                                  pagesize_v);
6135 }
6136
6137 /* for gengrid as of now */
6138 void
6139 _elm_genlist_page_relative_get(const Evas_Object *obj,
6140                                double            *h_pagerel,
6141                                double            *v_pagerel)
6142 {
6143    ELM_CHECK_WIDTYPE(obj, widtype);
6144    Widget_Data *wd = elm_widget_data_get(obj);
6145    if (!wd) return;
6146
6147    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
6148 }
6149
6150 /* for gengrid as of now */
6151 void
6152 _elm_genlist_page_size_set(Evas_Object *obj,
6153                            Evas_Coord   h_pagesize,
6154                            Evas_Coord   v_pagesize)
6155 {
6156    double pagerel_h;
6157    double pagerel_v;
6158
6159    ELM_CHECK_WIDTYPE(obj, widtype);
6160    Widget_Data *wd = elm_widget_data_get(obj);
6161    if (!wd) return;
6162    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
6163    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
6164                                  v_pagesize);
6165 }
6166
6167 /* for gengrid as of now */
6168 void
6169 _elm_genlist_current_page_get(const Evas_Object *obj,
6170                               int               *h_pagenumber,
6171                               int               *v_pagenumber)
6172 {
6173    ELM_CHECK_WIDTYPE(obj, widtype);
6174    Widget_Data *wd = elm_widget_data_get(obj);
6175    if (!wd) return;
6176    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
6177 }
6178
6179 /* for gengrid as of now */
6180 void
6181 _elm_genlist_last_page_get(const Evas_Object *obj,
6182                            int               *h_pagenumber,
6183                            int               *v_pagenumber)
6184 {
6185    ELM_CHECK_WIDTYPE(obj, widtype);
6186    Widget_Data *wd = elm_widget_data_get(obj);
6187    if (!wd) return;
6188    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
6189 }
6190
6191 /* for gengrid as of now */
6192 void
6193 _elm_genlist_page_show(const Evas_Object *obj,
6194                        int                h_pagenumber,
6195                        int                v_pagenumber)
6196 {
6197    ELM_CHECK_WIDTYPE(obj, widtype);
6198    Widget_Data *wd = elm_widget_data_get(obj);
6199    if (!wd) return;
6200    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
6201 }
6202
6203 /* for gengrid as of now */
6204 void
6205 _elm_genlist_page_bring_in(const Evas_Object *obj,
6206                            int                h_pagenumber,
6207                            int                v_pagenumber)
6208 {
6209    ELM_CHECK_WIDTYPE(obj, widtype);
6210    Widget_Data *wd = elm_widget_data_get(obj);
6211    if (!wd) return;
6212    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
6213 }
6214
6215 void
6216 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
6217                             Eina_Bool     calc)
6218 {
6219    Evas_Object *content;
6220
6221    if (!it->realized) return;
6222    if (it->wd->reorder_it == it) return;
6223    if (it->defer_unrealize && !it->item->updateme) return;
6224
6225    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
6226    if (!calc)
6227      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
6228    if (it->long_timer)
6229      {
6230         ecore_timer_del(it->long_timer);
6231         it->long_timer = NULL;
6232      }
6233
6234    elm_widget_stringlist_free(it->texts);
6235    it->texts = NULL;
6236    elm_widget_stringlist_free(it->contents);
6237    it->contents = NULL;
6238    elm_widget_stringlist_free(it->states);
6239    it->states = NULL;
6240
6241    EINA_LIST_FREE(it->content_objs, content)
6242      evas_object_del(content);
6243
6244    it->unrealize_cb(it);
6245
6246    it->realized = EINA_FALSE;
6247    it->want_unrealize = EINA_FALSE;
6248    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
6249    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
6250 }
6251
6252 void
6253 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
6254 {
6255    elm_widget_item_pre_notify_del(it);
6256    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
6257
6258    if ((it->relcount > 0) || (it->walking > 0))
6259      {
6260         if (!it->item->block && (it->relcount == 1))
6261           {
6262              if (it->item->rel && it->item->rel->item)
6263                {
6264                   it->item->rel->relcount--;
6265                   if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
6266                     {
6267                        _item_del(it->item->rel);
6268                        elm_widget_item_free(it->item->rel);
6269                     }
6270                   it->item->rel = NULL;
6271                }
6272           }
6273         else return;
6274      }
6275    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
6276
6277    if (it->itc->func.del)
6278      it->itc->func.del((void *)it->base.data, WIDGET(it));
6279 }
6280
6281 void
6282 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
6283 {
6284    _elm_genlist_item_del_notserious(it);
6285    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
6286    if (it->tooltip.del_cb)
6287      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6288    it->wd->walking -= it->walking;
6289    if (it->long_timer) ecore_timer_del(it->long_timer);
6290    if (it->group)
6291      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
6292
6293    if (it->wd->state)
6294      {
6295         eina_inlist_sorted_state_free(it->wd->state);
6296         it->wd->state = NULL;
6297      }
6298    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
6299    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
6300    free(it->item);
6301
6302    it->item = NULL;
6303    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
6304      it->wd->last_selected_item = NULL;
6305    it->wd->item_count--;
6306 }
6307
6308 EAPI void
6309 elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
6310 {
6311    ELM_CHECK_WIDTYPE(obj, widtype);
6312    Widget_Data *wd = elm_widget_data_get(obj);
6313    if (!wd) return;
6314    wd->tree_effect_enabled = !!enabled;
6315 }
6316
6317 EAPI Eina_Bool
6318 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
6319 {
6320    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6321    Widget_Data *wd = elm_widget_data_get(obj);
6322    if (!wd) return EINA_FALSE;
6323    return wd->tree_effect_enabled;
6324 }
6325
6326 static Evas_Object*
6327 _create_tray_alpha_bg(const Evas_Object *obj)
6328 {
6329    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
6330    Widget_Data *wd = elm_widget_data_get(obj);
6331    if (!wd) return NULL;
6332
6333    Evas_Object *bg = NULL;
6334    Evas_Coord ox, oy, ow, oh;
6335
6336    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6337    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
6338    evas_object_color_set(bg,0,0,0,0);
6339    evas_object_resize(bg , ow, oh);
6340    evas_object_move(bg , ox, oy);
6341    return bg ;
6342 }
6343
6344 static void
6345 _item_contract_emit(Elm_Gen_Item *it)
6346 {
6347    Elm_Gen_Item *it2;
6348    Eina_List *l;
6349
6350    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
6351    it->item->tree_effect_finished = EINA_FALSE;
6352
6353    EINA_LIST_FOREACH(it->item->items, l, it2)
6354      if (it2) _item_contract_emit(it2);
6355 }
6356
6357 static int
6358 _item_tree_effect_before(Elm_Gen_Item *it)
6359 {
6360    Elm_Gen_Item *it2;
6361    Eina_List *l;
6362
6363    EINA_LIST_FOREACH(it->item->items, l, it2)
6364      {
6365         if (it2->parent && (it == it2->parent))
6366           {
6367              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6368                edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
6369              else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6370                _item_contract_emit(it2);
6371           }
6372      }
6373    return ECORE_CALLBACK_CANCEL;
6374 }
6375
6376 static void
6377 _item_tree_effect(Widget_Data *wd, int y)
6378 {
6379    Elm_Gen_Item *it = NULL, *expanded_next_it;
6380
6381    expanded_next_it = wd->expanded_next_item;
6382
6383    if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6384      {
6385         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6386         while (it)
6387           {
6388              if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
6389              if (it->item->scrl_y && (it->item->scrl_y < expanded_next_it->item->old_scrl_y + y) &&
6390                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6391                {
6392                   if (!it->item->tree_effect_finished)
6393                     {
6394                        edje_object_signal_emit(VIEW(it), "flip_item", "");
6395                        evas_object_show(VIEW(it));
6396                        it->item->tree_effect_finished = EINA_TRUE;
6397                     }
6398                }
6399              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6400           }
6401      }
6402    else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6403      {
6404         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6405         while (it)
6406           {
6407              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
6408                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6409                {
6410                   if (!it->item->tree_effect_finished)
6411                     {
6412                        edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
6413                        it->item->tree_effect_finished = EINA_TRUE;
6414                     }
6415                }
6416              else
6417                break;
6418              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6419           }
6420      }
6421 }
6422
6423 static void
6424 _item_tree_effect_finish(Widget_Data *wd)
6425 {
6426    Item_Block *itb;
6427    Elm_Gen_Item *it = NULL;
6428    const Eina_List *l;
6429
6430    if (wd->item_moving_effect_timer)
6431      {
6432         if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6433            _item_subitems_clear(wd->expanded_item);
6434         EINA_INLIST_FOREACH(wd->blocks, itb)
6435           {
6436              EINA_LIST_FOREACH(itb->items, l, it)
6437                {
6438                   it->item->tree_effect_finished = EINA_TRUE;
6439                   it->item->old_scrl_y = it->item->scrl_y;
6440                }
6441           }
6442      }
6443    _item_auto_scroll(wd);
6444    evas_object_lower(wd->alpha_bg);
6445    evas_object_hide(wd->alpha_bg);
6446    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6447    if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
6448
6449    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
6450    evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
6451    evas_object_smart_changed(wd->pan_smart);
6452
6453    wd->item_moving_effect_timer = NULL;
6454 }
6455
6456 static Eina_Bool
6457 _item_moving_effect_timer_cb(void *data)
6458 {
6459    Widget_Data *wd = data;
6460    if (!wd) return EINA_FALSE;
6461    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
6462    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
6463    const Eina_List *l;
6464    double effect_duration = 0.5, t;
6465    int y = 0, dy = 0, dh = 0;
6466    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
6467    int in = 0;
6468
6469    t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
6470    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6471    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
6472    if (t > effect_duration) end = EINA_TRUE;
6473
6474    // Below while statement is needed, when the genlist is resized.
6475    it2 = wd->expanded_item;
6476    while (it2 && vis)
6477      {
6478         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
6479         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
6480                                    cvx, cvy, cvw, cvh));
6481         it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
6482      }
6483
6484    if (wd->expanded_next_item)
6485      {
6486         expanded_next_it = wd->expanded_next_item;
6487
6488         /* move items */
6489         EINA_LIST_FOREACH(wd->move_items, l, it)
6490           {
6491              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6492                {
6493                   expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6494                   if (expanded_next_it->item->scrl_y < expanded_next_it->item->old_scrl_y) //did not calculate next item position
6495                     expanded_next_it->item->scrl_y = cvy + cvh;
6496
6497                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6498                          cvy + cvh : expanded_next_it->item->scrl_y) -
6499                          expanded_next_it->item->old_scrl_y;
6500                }
6501              else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6502                {
6503                   if (expanded_next_it->item->scrl_y > expanded_next_it->item->old_scrl_y) //did not calculate next item position
6504                      expanded_next_it->item->old_scrl_y = cvy + cvh;
6505
6506                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6507                     {
6508                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6509                        cvy + cvh;
6510                        expanded_next_it->item->old_scrl_y = cvy + cvh;
6511                     }
6512                   else
6513                     {
6514                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6515                              expanded_next_it->item->old_scrl_y;
6516                     }
6517                }
6518
6519              if (t <= effect_duration)
6520                {
6521                   y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6522                }
6523              else
6524                {
6525                   end = EINA_TRUE;
6526                   y = dy;
6527                }
6528
6529              if (!it->realized)
6530                {
6531                   _item_realize(it, in, 0);
6532                }
6533              in++;
6534
6535              if (it != expanded_next_it)
6536                {
6537                   it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6538                   dh += it->item->h;
6539                }
6540
6541              if ((it->item->old_scrl_y + y) < (cvy + cvh))
6542                _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6543           }
6544         /* tree effect */
6545         _item_tree_effect(wd, y);
6546      }
6547    else
6548      {
6549         int expanded_item_num = 0;
6550         int num = 0;
6551
6552         if (wd->expanded_item)
6553           it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6554
6555         it2 = it;
6556         while (it2)
6557           {
6558              expanded_item_num++;
6559              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6560           }
6561
6562         while (it)
6563           {
6564              num++;
6565              if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6566              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6567                {
6568                   if (!it->item->tree_effect_finished)
6569                     {
6570                        if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6571                          {
6572                             edje_object_signal_emit(VIEW(it), "flip_item", "");
6573                             evas_object_show(VIEW(it));
6574                             it->item->tree_effect_finished = EINA_TRUE;
6575                          }
6576                     }
6577                }
6578              it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6579           }
6580      }
6581
6582    if (end)
6583      {
6584         _item_tree_effect_finish(wd);
6585         return ECORE_CALLBACK_CANCEL;
6586      }
6587    return ECORE_CALLBACK_RENEW;
6588 }