[Genlist] temp patch about elm_genlist_clear, item_del BS
[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         elm_genlist_item_subitems_clear(it);
4047         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
4048         _elm_genlist_item_del_notserious(_it);
4049         if (_it->item->block)
4050           {
4051              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
4052              _it->item->block->changed = EINA_TRUE;
4053              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
4054              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
4055           }
4056         if (_it->parent)
4057           {
4058              _it->parent->item->items =
4059                 eina_list_remove(_it->parent->item->items, it);
4060              _it->parent = NULL;
4061           }
4062         return EINA_FALSE;
4063      }
4064    _item_del(_it);
4065    return EINA_TRUE;
4066 }
4067
4068 static void
4069 _item_signal_emit_hook(Elm_Object_Item *it,
4070                        const char *emission,
4071                        const char *source)
4072 {
4073    edje_object_signal_emit(VIEW(it), emission, source);
4074 }
4075
4076 Elm_Gen_Item *
4077 _elm_genlist_item_new(Widget_Data              *wd,
4078                       const Elm_Gen_Item_Class *itc,
4079                       const void               *data,
4080                       Elm_Gen_Item             *parent,
4081                       Evas_Smart_Cb             func,
4082                       const void               *func_data)
4083 {
4084    Elm_Gen_Item *it;
4085
4086    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
4087    if (!it) return NULL;
4088    it->wd = wd;
4089    it->generation = wd->generation;
4090    it->itc = itc;
4091    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
4092    it->base.data = data;
4093    it->parent = parent;
4094    it->func.func = func;
4095    it->func.data = func_data;
4096    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
4097    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
4098    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
4099    elm_widget_item_text_get_hook_set(it, _item_text_hook);
4100    elm_widget_item_disable_hook_set(it, _item_disable_hook);
4101    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
4102    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
4103
4104    /* TEMPORARY */
4105    it->sel_cb = (Ecore_Cb)_item_select;
4106
4107    return it;
4108 }
4109
4110 static Elm_Gen_Item *
4111 _item_new(Widget_Data                  *wd,
4112           const Elm_Genlist_Item_Class *itc,
4113           const void                   *data,
4114           Elm_Gen_Item                 *parent,
4115           Elm_Genlist_Item_Type         type,
4116           Evas_Smart_Cb                 func,
4117           const void                   *func_data)
4118 {
4119    Elm_Gen_Item *it, *it2;
4120    int depth = 0;
4121
4122    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
4123    if (!it) return NULL;
4124    it->item = ELM_NEW(Elm_Gen_Item_Type);
4125    it->item->type = type;
4126    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
4127    it->item->expanded_depth = 0;
4128    ELM_GEN_ITEM_SETUP(it);
4129    it->mouse_cursor = NULL;
4130    it->can_focus = EINA_TRUE;
4131    if (it->parent)
4132      {
4133         if (it->parent->group)
4134           it->item->group_item = parent;
4135         else if (it->parent->item->group_item)
4136           it->item->group_item = it->parent->item->group_item;
4137      }
4138    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
4139      {
4140         if (!it2->parent->group) depth += 1;
4141      }
4142    it->item->expanded_depth = depth;
4143    wd->item_count++;
4144    return it;
4145 }
4146
4147 static Item_Block *
4148 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
4149 {
4150    Item_Block *itb;
4151
4152    itb = calloc(1, sizeof(Item_Block));
4153    if (!itb) return NULL;
4154    itb->wd = wd;
4155    if (prepend)
4156      {
4157         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
4158         _item_block_position_update(wd->blocks, 0);
4159      }
4160    else
4161      {
4162         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4163         itb->position_update = EINA_TRUE;
4164         if (wd->blocks != EINA_INLIST_GET(itb))
4165           {
4166              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4167           }
4168         else
4169           {
4170              itb->position = 0;
4171           }
4172      }
4173    return itb;
4174 }
4175
4176 static Eina_Bool
4177 _item_block_add(Widget_Data *wd,
4178                 Elm_Gen_Item *it)
4179 {
4180    Item_Block *itb = NULL;
4181
4182    if (!it->item->rel)
4183      {
4184 newblock:
4185         if (it->item->rel)
4186           {
4187              itb = calloc(1, sizeof(Item_Block));
4188              if (!itb) return EINA_FALSE;
4189              itb->wd = wd;
4190              if (!it->item->rel->item->block)
4191                {
4192                   wd->blocks =
4193                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
4194                   itb->items = eina_list_append(itb->items, it);
4195                   itb->position_update = EINA_TRUE;
4196                   it->position = eina_list_count(itb->items);
4197                   it->position_update = EINA_TRUE;
4198
4199                   if (wd->blocks != EINA_INLIST_GET(itb))
4200                     {
4201                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
4202                     }
4203                   else
4204                     {
4205                        itb->position = 0;
4206                     }
4207                }
4208              else
4209                {
4210                   Eina_List *tmp;
4211
4212                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
4213                   if (it->item->before)
4214                     {
4215                        wd->blocks = eina_inlist_prepend_relative
4216                            (wd->blocks, EINA_INLIST_GET(itb),
4217                            EINA_INLIST_GET(it->item->rel->item->block));
4218                        itb->items =
4219                          eina_list_prepend_relative_list(itb->items, it, tmp);
4220
4221                        /* Update index from where we prepended */
4222                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4223                        _item_block_position_update(EINA_INLIST_GET(itb),
4224                                                    it->item->rel->item->block->position);
4225                     }
4226                   else
4227                     {
4228                        wd->blocks = eina_inlist_append_relative
4229                            (wd->blocks, EINA_INLIST_GET(itb),
4230                            EINA_INLIST_GET(it->item->rel->item->block));
4231                        itb->items =
4232                          eina_list_append_relative_list(itb->items, it, tmp);
4233
4234                        /* Update block index from where we appended */
4235                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4236                        _item_block_position_update(EINA_INLIST_GET(itb),
4237                                                    it->item->rel->item->block->position + 1);
4238                     }
4239                }
4240           }
4241         else
4242           {
4243              if (it->item->before)
4244                {
4245                   if (wd->blocks)
4246                     {
4247                        itb = (Item_Block *)(wd->blocks);
4248                        if (itb->count >= wd->max_items_per_block)
4249                          {
4250                             itb = _item_block_new(wd, EINA_TRUE);
4251                             if (!itb) return EINA_FALSE;
4252                          }
4253                     }
4254                   else
4255                     {
4256                        itb = _item_block_new(wd, EINA_TRUE);
4257                        if (!itb) return EINA_FALSE;
4258                     }
4259                   itb->items = eina_list_prepend(itb->items, it);
4260
4261                   _item_position_update(itb->items, 0);
4262                }
4263              else
4264                {
4265                   if (wd->blocks)
4266                     {
4267                        itb = (Item_Block *)(wd->blocks->last);
4268                        if (itb->count >= wd->max_items_per_block)
4269                          {
4270                             itb = _item_block_new(wd, EINA_FALSE);
4271                             if (!itb) return EINA_FALSE;
4272                          }
4273                     }
4274                   else
4275                     {
4276                        itb = _item_block_new(wd, EINA_FALSE);
4277                        if (!itb) return EINA_FALSE;
4278                     }
4279                   itb->items = eina_list_append(itb->items, it);
4280                   it->position = eina_list_count(itb->items);
4281                }
4282           }
4283      }
4284    else
4285      {
4286         Eina_List *tmp;
4287
4288         if (it->item->rel->item->queued)
4289           {
4290              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
4291                 on sorted insertion order, so the queue is not always ordered like the item list.
4292                 This lead to issue where we depend on an item that is not yet created. As a quick
4293                 work around, we reschedule the calc of the item and stop reordering the list to
4294                 prevent any nasty issue to show up here.
4295               */
4296              wd->queue = eina_list_append(wd->queue, it);
4297              wd->requeued = EINA_TRUE;
4298              it->item->queued = EINA_TRUE;
4299              return EINA_FALSE;
4300           }
4301         itb = it->item->rel->item->block;
4302         if (!itb) goto newblock;
4303         tmp = eina_list_data_find_list(itb->items, it->item->rel);
4304         if (it->item->before)
4305           {
4306              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
4307              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
4308           }
4309         else
4310           {
4311              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
4312              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
4313           }
4314      }
4315    itb->count++;
4316    itb->changed = EINA_TRUE;
4317    it->item->block = itb;
4318    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
4319    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
4320    if (it->item->rel)
4321      {
4322         it->item->rel->relcount--;
4323         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
4324           {
4325              _item_del(it->item->rel);
4326              elm_widget_item_free(it->item->rel);
4327           }
4328         it->item->rel = NULL;
4329      }
4330    if (itb->count > itb->wd->max_items_per_block)
4331      {
4332         Item_Block *itb2;
4333         Elm_Gen_Item *it2;
4334         int newc;
4335         Eina_Bool done = EINA_FALSE;
4336
4337         newc = itb->count / 2;
4338
4339         if (EINA_INLIST_GET(itb)->prev)
4340           {
4341              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
4342
4343              if (itbp->count + newc < wd->max_items_per_block / 2)
4344                {
4345                   /* moving items to previous block */
4346                   while ((itb->count > newc) && (itb->items))
4347                     {
4348                        it2 = eina_list_data_get(itb->items);
4349                        itb->items = eina_list_remove_list(itb->items, itb->items);
4350                        itb->count--;
4351
4352                        itbp->items = eina_list_append(itbp->items, it2);
4353                        it2->item->block = itbp;
4354                        itbp->count++;
4355                     }
4356
4357                   done = EINA_TRUE;
4358                }
4359           }
4360
4361         if (!done && EINA_INLIST_GET(itb)->next)
4362           {
4363              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4364
4365              if (itbn->count + newc < wd->max_items_per_block / 2)
4366                {
4367                   /* moving items to next block */
4368                   while ((itb->count > newc) && (itb->items))
4369                     {
4370                        Eina_List *l;
4371
4372                        l = eina_list_last(itb->items);
4373                        it2 = eina_list_data_get(l);
4374                        itb->items = eina_list_remove_list(itb->items, l);
4375                        itb->count--;
4376
4377                        itbn->items = eina_list_prepend(itbn->items, it2);
4378                        it2->item->block = itbn;
4379                        itbn->count++;
4380                     }
4381
4382                   done = EINA_TRUE;
4383                }
4384           }
4385
4386         if (!done)
4387           {
4388              /* moving items to new block */
4389              itb2 = calloc(1, sizeof(Item_Block));
4390              if (!itb2) return EINA_FALSE;
4391              itb2->wd = wd;
4392              wd->blocks =
4393                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
4394                                            EINA_INLIST_GET(itb));
4395              itb2->changed = EINA_TRUE;
4396              while ((itb->count > newc) && (itb->items))
4397                {
4398                   Eina_List *l;
4399
4400                   l = eina_list_last(itb->items);
4401                   it2 = l->data;
4402                   itb->items = eina_list_remove_list(itb->items, l);
4403                   itb->count--;
4404
4405                   itb2->items = eina_list_prepend(itb2->items, it2);
4406                   it2->item->block = itb2;
4407                   itb2->count++;
4408                }
4409           }
4410      }
4411
4412    return EINA_TRUE;
4413 }
4414
4415 static int
4416 _queue_process(Widget_Data *wd)
4417 {
4418    int n;
4419    Eina_Bool showme = EINA_FALSE;
4420    double t0, t;
4421
4422    t0 = ecore_loop_time_get();
4423    //evas_event_freeze(evas_object_evas_get(wd->obj));
4424    for (n = 0; (wd->queue) && (n < 128); n++)
4425      {
4426         Elm_Gen_Item *it;
4427
4428         it = eina_list_data_get(wd->queue);
4429         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4430         it->item->queued = EINA_FALSE;
4431         if (!_item_block_add(wd, it)) continue;
4432         if (!wd->blocks)
4433           _item_block_realize(it->item->block);
4434         t = ecore_time_get();
4435         if (it->item->block->changed)
4436           {
4437              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
4438              it->item->block->changed = 0;
4439              if (wd->pan_changed)
4440                {
4441                   if (wd->calc_job) ecore_job_del(wd->calc_job);
4442                   wd->calc_job = NULL;
4443                   _calc_job(wd);
4444                   wd->pan_changed = EINA_FALSE;
4445                }
4446           }
4447         if (showme) it->item->block->showme = EINA_TRUE;
4448         /* same as eina_inlist_count > 1 */
4449         if (wd->blocks && wd->blocks->next)
4450           {
4451              if ((t - t0) > (ecore_animator_frametime_get())) break;
4452           }
4453      }
4454    //evas_event_thaw(evas_object_evas_get(wd->obj));
4455    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4456    return n;
4457 }
4458
4459 static Eina_Bool
4460 _idle_process(void *data, Eina_Bool *wakeup)
4461 {
4462    Widget_Data *wd = data;
4463
4464    //xxx
4465    //static double q_start = 0.0;
4466    //if (q_start == 0.0) q_start = ecore_time_get();
4467    //xxx
4468    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4469    if (!wd->queue)
4470      {
4471         //xxx
4472         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4473         //xxx
4474         return ECORE_CALLBACK_CANCEL;
4475      }
4476    return ECORE_CALLBACK_RENEW;
4477 }
4478
4479 static Eina_Bool
4480 _item_idle_enterer(void *data)
4481 {
4482    Widget_Data *wd = data;
4483    Eina_Bool wakeup = EINA_FALSE;
4484    Eina_Bool ok = _idle_process(data, &wakeup);
4485
4486    if (wakeup)
4487      {
4488         // wake up mainloop
4489         if (wd->calc_job) ecore_job_del(wd->calc_job);
4490         wd->calc_job = ecore_job_add(_calc_job, wd);
4491      }
4492    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4493    return ok;
4494 }
4495
4496 static void
4497 _item_queue(Widget_Data *wd,
4498             Elm_Gen_Item *it,
4499             Eina_Compare_Cb cb)
4500 {
4501    if (it->item->queued) return;
4502    it->item->queued = EINA_TRUE;
4503    if (cb && !wd->requeued)
4504      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4505    else
4506      wd->queue = eina_list_append(wd->queue, it);
4507 // FIXME: why does a freeze then thaw here cause some genlist
4508 // elm_genlist_item_append() to be much much slower?
4509 //   evas_event_freeze(evas_object_evas_get(wd->obj));
4510    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4511      {
4512         if (wd->queue_idle_enterer)
4513           {
4514              ecore_idle_enterer_del(wd->queue_idle_enterer);
4515              wd->queue_idle_enterer = NULL;
4516           }
4517         _queue_process(wd);
4518      }
4519 //   evas_event_thaw(evas_object_evas_get(wd->obj));
4520 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4521    if (!wd->queue_idle_enterer)
4522      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4523 }
4524
4525 static int
4526 _elm_genlist_item_compare(const void *data, const void *data1)
4527 {
4528    const Elm_Gen_Item *it, *item1;
4529    it = ELM_GEN_ITEM_FROM_INLIST(data);
4530    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4531    return it->wd->item_compare_cb(it, item1);
4532 }
4533
4534 static int
4535 _elm_genlist_item_list_compare(const void *data, const void *data1)
4536 {
4537    const Elm_Gen_Item *it = data;
4538    const Elm_Gen_Item *item1 = data1;
4539    return it->wd->item_compare_cb(it, item1);
4540 }
4541
4542 static void
4543 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4544 {
4545    if (!it) return;
4546    if (!after) return;
4547
4548    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4549    _item_block_del(it);
4550
4551    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4552    it->item->rel = after;
4553    it->item->rel->relcount++;
4554    it->item->before = EINA_FALSE;
4555    if (after->item->group_item) it->item->group_item = after->item->group_item;
4556    _item_queue(it->wd, it, NULL);
4557
4558    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4559 }
4560
4561 static void
4562 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4563 {
4564    if (!it) return;
4565    if (!before) return;
4566
4567    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4568    _item_block_del(it);
4569    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4570    it->item->rel = before;
4571    it->item->rel->relcount++;
4572    it->item->before = EINA_TRUE;
4573    if (before->item->group_item) it->item->group_item = before->item->group_item;
4574    _item_queue(it->wd, it, NULL);
4575
4576    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4577 }
4578
4579 EAPI unsigned int
4580 elm_genlist_items_count(const Evas_Object *obj)
4581 {
4582    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4583    Widget_Data *wd = elm_widget_data_get(obj);
4584    if (!wd) return 0;
4585    return wd->item_count;
4586 }
4587
4588 EAPI Elm_Object_Item *
4589 elm_genlist_item_append(Evas_Object                  *obj,
4590                         const Elm_Genlist_Item_Class *itc,
4591                         const void                   *data,
4592                         Elm_Object_Item              *parent,
4593                         Elm_Genlist_Item_Type         type,
4594                         Evas_Smart_Cb                 func,
4595                         const void                   *func_data)
4596 {
4597    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4598    Widget_Data *wd = elm_widget_data_get(obj);
4599    if (!wd) return NULL;
4600    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4601                                 func, func_data);
4602    if (!it) return NULL;
4603    if (!it->parent)
4604      {
4605         if (it->group)
4606           wd->group_items = eina_list_append(wd->group_items, it);
4607         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4608         it->item->rel = NULL;
4609      }
4610    else
4611      {
4612         Elm_Gen_Item *it2 = NULL;
4613         Eina_List *ll = eina_list_last(it->parent->item->items);
4614         if (ll) it2 = ll->data;
4615         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4616         if (!it2) it2 = it->parent;
4617         wd->items =
4618           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4619                                       EINA_INLIST_GET(it2));
4620         it->item->rel = it2;
4621         it->item->rel->relcount++;
4622      }
4623    it->item->before = EINA_FALSE;
4624    _item_queue(wd, it, NULL);
4625    return (Elm_Object_Item *)it;
4626 }
4627
4628 EAPI Elm_Object_Item *
4629 elm_genlist_item_prepend(Evas_Object                  *obj,
4630                          const Elm_Genlist_Item_Class *itc,
4631                          const void                   *data,
4632                          Elm_Object_Item              *parent,
4633                          Elm_Genlist_Item_Type         type,
4634                          Evas_Smart_Cb                 func,
4635                          const void                   *func_data)
4636 {
4637    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4638    Widget_Data *wd = elm_widget_data_get(obj);
4639    if (!wd) return NULL;
4640    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4641                                 func, func_data);
4642    if (!it) return NULL;
4643    if (!it->parent)
4644      {
4645         if (it->group)
4646           wd->group_items = eina_list_prepend(wd->group_items, it);
4647         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4648         it->item->rel = NULL;
4649      }
4650    else
4651      {
4652         Elm_Gen_Item *it2 = NULL;
4653         Eina_List *ll = it->parent->item->items;
4654         if (ll) it2 = ll->data;
4655         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4656         if (!it2) it2 = it->parent;
4657         wd->items =
4658           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4659                                        EINA_INLIST_GET(it2));
4660         it->item->rel = it2;
4661         it->item->rel->relcount++;
4662      }
4663    it->item->before = EINA_TRUE;
4664    _item_queue(wd, it, NULL);
4665    return (Elm_Object_Item *)it;
4666 }
4667
4668 EAPI Elm_Object_Item *
4669 elm_genlist_item_insert_after(Evas_Object                  *obj,
4670                               const Elm_Genlist_Item_Class *itc,
4671                               const void                   *data,
4672                               Elm_Object_Item              *parent,
4673                               Elm_Object_Item              *after,
4674                               Elm_Genlist_Item_Type         type,
4675                               Evas_Smart_Cb                 func,
4676                               const void                   *func_data)
4677 {
4678    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4679    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4680    Widget_Data *wd = elm_widget_data_get(obj);
4681    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4682    if (!wd) return NULL;
4683    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4684    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4685
4686    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4687                                 func, func_data);
4688    if (!it) return NULL;
4689    if (!it->parent)
4690      {
4691         if ((it->group) && (_after->group))
4692           wd->group_items = eina_list_append_relative(wd->group_items, it,
4693                                                       _after);
4694      }
4695    else
4696      {
4697         it->parent->item->items =
4698            eina_list_append_relative(it->parent->item->items, it, _after);
4699      }
4700    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4701                                            EINA_INLIST_GET(_after));
4702    it->item->rel = _after;
4703    it->item->rel->relcount++;
4704    it->item->before = EINA_FALSE;
4705    _item_queue(wd, it, NULL);
4706    return (Elm_Object_Item *)it;
4707 }
4708
4709 EAPI Elm_Object_Item *
4710 elm_genlist_item_insert_before(Evas_Object                  *obj,
4711                                const Elm_Genlist_Item_Class *itc,
4712                                const void                   *data,
4713                                Elm_Object_Item              *parent,
4714                                Elm_Object_Item              *before,
4715                                Elm_Genlist_Item_Type         type,
4716                                Evas_Smart_Cb                 func,
4717                                const void                   *func_data)
4718 {
4719    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4720    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4721    Widget_Data *wd = elm_widget_data_get(obj);
4722    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4723    if (!wd) return NULL;
4724    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4725    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4726
4727    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4728                                 func, func_data);
4729    if (!it) return NULL;
4730    if (!it->parent)
4731      {
4732         if (it->group && _before->group)
4733           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4734                                                        _before);
4735      }
4736    else
4737      {
4738         it->parent->item->items =
4739            eina_list_prepend_relative(it->parent->item->items, it, _before);
4740      }
4741    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4742                                             EINA_INLIST_GET(_before));
4743    it->item->rel = _before;
4744    it->item->rel->relcount++;
4745    it->item->before = EINA_TRUE;
4746    _item_queue(wd, it, NULL);
4747    return (Elm_Object_Item *)it;
4748 }
4749
4750 EAPI Elm_Object_Item *
4751 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4752                                const Elm_Genlist_Item_Class *itc,
4753                                const void                   *data,
4754                                Elm_Object_Item              *parent,
4755                                Elm_Genlist_Item_Type         type,
4756                                Eina_Compare_Cb               comp,
4757                                Evas_Smart_Cb                 func,
4758                                const void                   *func_data)
4759 {
4760    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4761    Widget_Data *wd = elm_widget_data_get(obj);
4762    if (!wd) return NULL;
4763    Elm_Gen_Item *rel = NULL;
4764    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4765                                 func, func_data);
4766    if (!it) return NULL;
4767
4768    wd->item_compare_cb = comp;
4769
4770    if (it->parent)
4771      {
4772         Eina_List *l;
4773         int cmp_result;
4774
4775         l = eina_list_search_sorted_near_list(it->parent->item->items,
4776                                               _elm_genlist_item_list_compare,
4777                                               it,
4778                                               &cmp_result);
4779         if (l)
4780           rel = eina_list_data_get(l);
4781         else
4782           rel = it->parent;
4783
4784         if (cmp_result >= 0)
4785           {
4786              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4787              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4788              it->item->before = EINA_FALSE;
4789           }
4790         else if (cmp_result < 0)
4791           {
4792              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4793              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4794              it->item->before = EINA_TRUE;
4795           }
4796      }
4797    else
4798      {
4799         if (!wd->state)
4800           {
4801              wd->state = eina_inlist_sorted_state_new();
4802              eina_inlist_sorted_state_init(wd->state, wd->items);
4803              wd->requeued = EINA_FALSE;
4804           }
4805
4806         if (it->group)
4807           wd->group_items = eina_list_append(wd->group_items, it);
4808
4809         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4810                                                     _elm_genlist_item_compare, wd->state);
4811
4812         if (EINA_INLIST_GET(it)->next)
4813           {
4814              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4815              it->item->before = EINA_TRUE;
4816           }
4817         else if (EINA_INLIST_GET(it)->prev)
4818           {
4819              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4820              it->item->before = EINA_FALSE;
4821           }
4822      }
4823
4824    if (rel)
4825      {
4826         it->item->rel = rel;
4827         it->item->rel->relcount++;
4828      }
4829
4830    _item_queue(wd, it, _elm_genlist_item_list_compare);
4831
4832    return (Elm_Object_Item *)it;
4833 }
4834
4835 static void
4836 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4837 {
4838    Eina_Inlist *next, *l;
4839    Widget_Data *wd = elm_widget_data_get(obj);
4840    if (!wd) return;
4841
4842    if (!standby) wd->generation++;
4843
4844    if (wd->state)
4845      {
4846         eina_inlist_sorted_state_free(wd->state);
4847         wd->state = NULL;
4848      }
4849
4850    if (wd->walking > 0)
4851      {
4852         wd->clear_me = EINA_TRUE;
4853         return;
4854      }
4855    evas_event_freeze(evas_object_evas_get(wd->obj));
4856    for (l = wd->items, next = l ? l->next : NULL;
4857         l;
4858         l = next, next = next ? next->next : NULL)
4859      {
4860         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4861
4862         if (it->generation < wd->generation)
4863           {
4864              Elm_Gen_Item *itn = NULL;
4865
4866              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4867              if (itn) itn->walking++; /* prevent early death of subitem */
4868              it->del_cb(it);
4869              elm_widget_item_free(it);
4870              if (itn) itn->walking--;
4871           }
4872      }
4873    wd->clear_me = EINA_FALSE;
4874    wd->pan_changed = EINA_TRUE;
4875    if (wd->calc_job)
4876      {
4877         ecore_job_del(wd->calc_job);
4878         wd->calc_job = NULL;
4879      }
4880    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4881    if (wd->clear_cb) wd->clear_cb(wd);
4882    wd->pan_x = 0;
4883    wd->pan_y = 0;
4884    wd->minw = 0;
4885    wd->minh = 0;
4886
4887    if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4888    wd->alpha_bg = NULL;
4889
4890    if (wd->pan_smart)
4891      {
4892         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4893         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4894      }
4895    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4896    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4897    evas_event_thaw(evas_object_evas_get(wd->obj));
4898    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4899 }
4900
4901 EAPI void
4902 elm_genlist_clear(Evas_Object *obj)
4903 {
4904    ELM_CHECK_WIDTYPE(obj, widtype);
4905    _elm_genlist_clear(obj, EINA_FALSE);
4906 }
4907
4908 EAPI void
4909 elm_genlist_multi_select_set(Evas_Object *obj,
4910                              Eina_Bool    multi)
4911 {
4912    ELM_CHECK_WIDTYPE(obj, widtype);
4913    Widget_Data *wd = elm_widget_data_get(obj);
4914    if (!wd) return;
4915    wd->multi = !!multi;
4916 }
4917
4918 EAPI Eina_Bool
4919 elm_genlist_multi_select_get(const Evas_Object *obj)
4920 {
4921    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4922    Widget_Data *wd = elm_widget_data_get(obj);
4923    if (!wd) return EINA_FALSE;
4924    return wd->multi;
4925 }
4926
4927 EAPI Elm_Object_Item *
4928 elm_genlist_selected_item_get(const Evas_Object *obj)
4929 {
4930    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4931    Widget_Data *wd = elm_widget_data_get(obj);
4932    if (!wd) return NULL;
4933    if (wd->selected) return wd->selected->data;
4934    return NULL;
4935 }
4936
4937 EAPI const Eina_List *
4938 elm_genlist_selected_items_get(const Evas_Object *obj)
4939 {
4940    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4941    Widget_Data *wd = elm_widget_data_get(obj);
4942    if (!wd) return NULL;
4943    return wd->selected;
4944 }
4945
4946 EAPI Eina_List *
4947 elm_genlist_realized_items_get(const Evas_Object *obj)
4948 {
4949    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4950    Widget_Data *wd = elm_widget_data_get(obj);
4951    Eina_List *list = NULL;
4952    Item_Block *itb;
4953    Eina_Bool done = EINA_FALSE;
4954    if (!wd) return NULL;
4955    EINA_INLIST_FOREACH(wd->blocks, itb)
4956      {
4957         if (itb->realized)
4958           {
4959              Eina_List *l;
4960              Elm_Gen_Item *it;
4961
4962              done = EINA_TRUE;
4963              EINA_LIST_FOREACH(itb->items, l, it)
4964                {
4965                   if (it->realized) list = eina_list_append(list, it);
4966                }
4967           }
4968         else
4969           {
4970              if (done) break;
4971           }
4972      }
4973    return list;
4974 }
4975
4976 EAPI Elm_Object_Item *
4977 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4978                            Evas_Coord         x,
4979                            Evas_Coord         y,
4980                            int               *posret)
4981 {
4982    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4983    Widget_Data *wd = elm_widget_data_get(obj);
4984    Evas_Coord ox, oy, ow, oh;
4985    Item_Block *itb;
4986    Evas_Coord lasty;
4987    if (!wd) return NULL;
4988    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4989    lasty = oy;
4990    EINA_INLIST_FOREACH(wd->blocks, itb)
4991      {
4992         Eina_List *l;
4993         Elm_Gen_Item *it;
4994
4995         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4996                                  oy + itb->y - itb->wd->pan_y,
4997                                  itb->w, itb->h, x, y, 1, 1))
4998           continue;
4999         EINA_LIST_FOREACH(itb->items, l, it)
5000           {
5001              Evas_Coord itx, ity;
5002
5003              itx = ox + itb->x + it->x - itb->wd->pan_x;
5004              ity = oy + itb->y + it->y - itb->wd->pan_y;
5005              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
5006                {
5007                   if (posret)
5008                     {
5009                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
5010                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
5011                          *posret = 1;
5012                        else *posret = 0;
5013                     }
5014                   return (Elm_Object_Item *)it;
5015                }
5016              lasty = ity + it->item->h;
5017           }
5018      }
5019    if (posret)
5020      {
5021         if (y > lasty) *posret = 1;
5022         else *posret = -1;
5023      }
5024    return NULL;
5025 }
5026
5027 EAPI Elm_Object_Item *
5028 elm_genlist_first_item_get(const Evas_Object *obj)
5029 {
5030    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5031    Widget_Data *wd = elm_widget_data_get(obj);
5032    if (!wd) return NULL;
5033    if (!wd->items) return NULL;
5034    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
5035    while ((it) && (it->generation < wd->generation))
5036      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5037    return (Elm_Object_Item *)it;
5038 }
5039
5040 EAPI Elm_Object_Item *
5041 elm_genlist_last_item_get(const Evas_Object *obj)
5042 {
5043    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5044    Widget_Data *wd = elm_widget_data_get(obj);
5045    if (!wd) return NULL;
5046    if (!wd->items) return NULL;
5047    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
5048    while ((it) && (it->generation < wd->generation))
5049      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5050    return (Elm_Object_Item *)it;
5051 }
5052
5053 EAPI Elm_Object_Item *
5054 elm_genlist_item_next_get(const Elm_Object_Item *it)
5055 {
5056    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5057    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5058    while (_it)
5059      {
5060         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
5061         if ((_it) && (_it->generation == _it->wd->generation)) break;
5062      }
5063    return (Elm_Object_Item *) _it;
5064 }
5065
5066 EAPI Elm_Object_Item *
5067 elm_genlist_item_prev_get(const Elm_Object_Item *it)
5068 {
5069    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5070    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5071    while (_it)
5072      {
5073         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
5074         if ((_it) && (_it->generation == _it->wd->generation)) break;
5075      }
5076    return (Elm_Object_Item *) _it;
5077 }
5078
5079 EAPI Elm_Object_Item *
5080 elm_genlist_item_parent_get(const Elm_Object_Item *it)
5081 {
5082    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5083    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
5084 }
5085
5086 EAPI void
5087 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
5088 {
5089    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5090    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
5091    if (!wd) return;
5092    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5093
5094    if (!wd->tree_effect_enabled || !wd->move_effect_mode)
5095      _item_subitems_clear(_it);
5096    else
5097      {
5098         if (!wd->item_moving_effect_timer)
5099           {
5100              wd->expanded_item = _it;
5101              _item_tree_effect_before(_it);
5102              evas_object_raise(wd->alpha_bg);
5103              evas_object_show(wd->alpha_bg);
5104              wd->start_time = ecore_time_get();
5105              wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, wd);
5106           }
5107         else
5108            _item_subitems_clear(_it);
5109      }
5110 }
5111
5112 EAPI void
5113 elm_genlist_item_selected_set(Elm_Object_Item *it,
5114                               Eina_Bool selected)
5115 {
5116    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5117    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5118    Widget_Data *wd = _it->wd;
5119    if (!wd) return;
5120    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
5121      return;
5122    selected = !!selected;
5123    if (_it->selected == selected) return;
5124
5125    if (selected)
5126      {
5127         if (!wd->multi)
5128           {
5129              while (wd->selected)
5130                {
5131                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
5132                   _it->unsel_cb(wd->selected->data);
5133                }
5134           }
5135         _it->highlight_cb(_it);
5136         _item_select(_it);
5137         return;
5138      }
5139    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
5140    _it->unsel_cb(_it);
5141 }
5142
5143 EAPI Eina_Bool
5144 elm_genlist_item_selected_get(const Elm_Object_Item *it)
5145 {
5146    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5147    return ((Elm_Gen_Item *)it)->selected;
5148 }
5149
5150 Elm_Gen_Item *
5151 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
5152 {
5153    Elm_Gen_Item *it2;
5154    if (it->item->expanded)
5155      {
5156         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5157      }
5158    else
5159      {
5160         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
5161         while (it2)
5162           {
5163              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
5164              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5165           }
5166      }
5167    return it2;
5168 }
5169
5170 static void
5171 _elm_genlist_move_items_set(Elm_Gen_Item *it)
5172 {
5173    Eina_List *l;
5174    Elm_Gen_Item *it2 = NULL;
5175    Evas_Coord ox, oy, ow, oh, dh = 0;
5176
5177    it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
5178
5179    if (it->item->expanded)
5180      {
5181         it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
5182         EINA_LIST_FOREACH(it->wd->move_items, l, it2)
5183           {
5184              if (it2 == it->wd->expanded_next_item) break;
5185              it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
5186           }
5187      }
5188    else
5189      {
5190         evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
5191         it2 = it->wd->expanded_next_item;
5192         while (it2 && (dh < oy + oh))
5193           {
5194              dh += it2->item->h;
5195              it->wd->move_items = eina_list_append(it->wd->move_items, it2);
5196              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
5197           }
5198      }
5199 }
5200
5201 EAPI void
5202 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
5203                               Eina_Bool         expanded)
5204 {
5205    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5206    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5207    expanded = !!expanded;
5208    if (_it->item->expanded == expanded) return;
5209    _it->item->expanded = expanded;
5210    _it->wd->expanded_item = _it;
5211    _elm_genlist_move_items_set(_it);
5212
5213    if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
5214       _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
5215
5216    if (_it->item->expanded)
5217      {
5218         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
5219         if (_it->realized)
5220           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
5221         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
5222         _it->wd->auto_scroll_enabled = EINA_TRUE;
5223      }
5224    else
5225      {
5226         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
5227         if (_it->realized)
5228           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
5229         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
5230         _it->wd->auto_scroll_enabled = EINA_FALSE;
5231      }
5232 }
5233
5234 EAPI Eina_Bool
5235 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
5236 {
5237    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5238    return ((Elm_Gen_Item *)it)->item->expanded;
5239 }
5240
5241 EAPI int
5242 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
5243 {
5244    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
5245    return ((Elm_Gen_Item *)it)->item->expanded_depth;
5246 }
5247
5248 EINA_DEPRECATED EAPI void
5249 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
5250                                   Eina_Bool         display_only)
5251 {
5252    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5253    display_only = !!display_only;
5254
5255    if (display_only)
5256      elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
5257    else
5258      {
5259         Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5260         if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5261           elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DEFAULT);
5262      }
5263 }
5264
5265 EINA_DEPRECATED EAPI Eina_Bool
5266 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
5267 {
5268    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5269    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5270    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5271    Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
5272    if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5273      return EINA_TRUE;
5274    return EINA_FALSE;
5275 }
5276
5277 static Eina_Bool
5278 _elm_genlist_item_compute_coordinates(Elm_Object_Item *it,
5279                                       Elm_Genlist_Item_Scrollto_Type type,
5280                                       Evas_Coord *x,
5281                                       Evas_Coord *y,
5282                                       Evas_Coord *w,
5283                                       Evas_Coord *h)
5284 {
5285    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5286    Evas_Coord gith = 0;
5287    if (_it->generation < _it->wd->generation) return EINA_FALSE;
5288    if ((_it->item->queued) || (!_it->item->mincalcd))
5289      {
5290         _it->wd->show_item = _it;
5291         _it->wd->bring_in = EINA_FALSE;
5292         _it->wd->scrollto_type = type;
5293         _it->item->showme = EINA_TRUE;
5294         return EINA_FALSE;
5295      }
5296    if (_it->wd->show_item)
5297      {
5298         _it->wd->show_item->item->showme = EINA_FALSE;
5299         _it->wd->show_item = NULL;
5300      }
5301
5302    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
5303    if (type==ELM_GENLIST_ITEM_SCROLLTO_IN)
5304      {
5305         if ((_it->item->group_item) &&
5306            (_it->wd->pan_y > (_it->y + _it->item->block->y)))
5307             gith = _it->item->group_item->item->h;
5308
5309         *h = _it->item->h;
5310         *y = _it->y + _it->item->block->y - gith;
5311      }
5312    else if (type==ELM_GENLIST_ITEM_SCROLLTO_TOP)
5313      {
5314         if (_it->item->group_item) gith = _it->item->group_item->item->h;
5315         *y = _it->y + _it->item->block->y - gith;
5316      }
5317    else if (type==ELM_GENLIST_ITEM_SCROLLTO_MIDDLE)
5318      {
5319         *y = _it->y + _it->item->block->y - *h / 2 + _it->item->h / 2;
5320      }
5321    else
5322      return EINA_FALSE;
5323
5324    *x = _it->x + _it->item->block->x;
5325    *w = _it->item->block->w;
5326    return EINA_TRUE;
5327 }
5328
5329 EAPI void
5330 elm_genlist_item_promote(Elm_Object_Item *it)
5331 {
5332    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5333    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5334    if (_it->generation < _it->wd->generation) return;
5335    _item_move_before(_it,
5336                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
5337 }
5338
5339 EAPI void
5340 elm_genlist_item_demote(Elm_Object_Item *it)
5341 {
5342    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5343    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5344    if (_it->generation < _it->wd->generation) return;
5345    _item_move_after(_it,
5346                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
5347 }
5348
5349 EAPI void
5350 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5351 {
5352    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5353    Evas_Coord x, y, w, h;
5354    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5355
5356    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
5357      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
5358 }
5359
5360 EAPI void
5361 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
5362 {
5363
5364    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5365    Evas_Coord x, y, w, h;
5366    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5367
5368    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
5369      elm_smart_scroller_region_bring_in(_it->wd->scr,x, y, w, h);
5370 }
5371
5372 EAPI void
5373 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
5374 {
5375    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5376
5377    Evas_Object *content;
5378    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
5379      {
5380         elm_widget_sub_object_del(WIDGET(it), content);
5381         evas_object_smart_member_del(content);
5382         evas_object_hide(content);
5383         if (l)
5384           *l = eina_list_append(*l, content);
5385      }
5386 }
5387
5388 EAPI void
5389 elm_genlist_item_update(Elm_Object_Item *it)
5390 {
5391    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5392    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5393
5394    if (!_it->item->block) return;
5395    if (_it->generation < _it->wd->generation) return;
5396    _it->item->mincalcd = EINA_FALSE;
5397    _it->item->updateme = EINA_TRUE;
5398    _it->item->block->updateme = EINA_TRUE;
5399    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5400    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5401 }
5402
5403 EAPI void
5404 elm_genlist_item_fields_update(Elm_Object_Item *it,
5405                                const char *parts,
5406                                Elm_Genlist_Item_Field_Type itf)
5407 {
5408    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5409    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5410
5411    if (!_it->item->block) return;
5412    if (_it->generation < _it->wd->generation) return;
5413
5414    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
5415      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
5416    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
5417      {
5418         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
5419                                                    &_it->contents, parts);
5420         _it->content_objs = _item_content_realize(_it, VIEW(_it),
5421                                                  &_it->contents, parts);
5422
5423         if (_it->flipped)
5424           {
5425              _it->content_objs = _item_mode_content_unrealize(_it, VIEW(_it),
5426                                                               &_it->contents, parts, &_it->content_objs, "flips");
5427              _it->content_objs = _item_mode_content_realize(_it, VIEW(_it),
5428                                                             &_it->contents, parts, &_it->content_objs, "flips");
5429           }
5430
5431         if (_it->item->mode_view)
5432           {
5433              _it->item->mode_content_objs = _item_mode_content_unrealize(_it, _it->item->mode_view,
5434                                                                          &_it->item->mode_contents, parts, &_it->item->mode_content_objs, "contents");
5435              _it->item->mode_content_objs = _item_mode_content_realize(_it, _it->item->mode_view,
5436                                                                  &_it->item->mode_contents, parts, &_it->item->mode_content_objs, "contents");
5437           }
5438
5439         if (_it->wd->decorate_mode)
5440           {
5441              _it->item->edit_content_objs = _item_mode_content_unrealize(_it, _it->edit_obj,
5442                                                                          &_it->contents, parts, &_it->item->edit_content_objs, "decorate_contents");
5443              _it->item->edit_content_objs = _item_mode_content_realize(_it, _it->edit_obj,
5444                                                                  &_it->contents, parts, &_it->item->edit_content_objs, "decorate_contents"); // FIXME: is it "decorate_contents"??
5445           }
5446      }
5447    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
5448      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
5449 }
5450
5451 EAPI void
5452 elm_genlist_item_item_class_update(Elm_Object_Item *it,
5453                                    const Elm_Genlist_Item_Class *itc)
5454 {
5455    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5456    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5457
5458    if (!_it->item->block) return;
5459    EINA_SAFETY_ON_NULL_RETURN(itc);
5460    if (_it->generation < _it->wd->generation) return;
5461    _it->itc = itc;
5462    _it->item->nocache_once = EINA_TRUE;
5463    elm_genlist_item_update(it);
5464 }
5465
5466 EAPI const Elm_Genlist_Item_Class *
5467 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
5468 {
5469    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5470    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5471    if (_it->generation < _it->wd->generation) return NULL;
5472    return _it->itc;
5473 }
5474
5475 static Evas_Object *
5476 _elm_genlist_item_label_create(void        *data,
5477                                Evas_Object *obj __UNUSED__,
5478                                Evas_Object *tooltip,
5479                                void        *it __UNUSED__)
5480 {
5481    Evas_Object *label = elm_label_add(tooltip);
5482    if (!label)
5483      return NULL;
5484    elm_object_style_set(label, "tooltip");
5485    elm_object_text_set(label, data);
5486    return label;
5487 }
5488
5489 static void
5490 _elm_genlist_item_label_del_cb(void        *data,
5491                                Evas_Object *obj __UNUSED__,
5492                                void        *event_info __UNUSED__)
5493 {
5494    eina_stringshare_del(data);
5495 }
5496
5497 EAPI void
5498 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5499                                   const char      *text)
5500 {
5501    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5502    text = eina_stringshare_add(text);
5503    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5504                                            text,
5505                                            _elm_genlist_item_label_del_cb);
5506 }
5507
5508 EAPI void
5509 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
5510                                         Elm_Tooltip_Item_Content_Cb func,
5511                                         const void                 *data,
5512                                         Evas_Smart_Cb               del_cb)
5513 {
5514    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5515    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5516
5517    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5518      return;
5519
5520    if (_it->tooltip.del_cb)
5521      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5522
5523    _it->tooltip.content_cb = func;
5524    _it->tooltip.data = data;
5525    _it->tooltip.del_cb = del_cb;
5526
5527    if (VIEW(_it))
5528      {
5529         elm_widget_item_tooltip_content_cb_set(_it,
5530                                                _it->tooltip.content_cb,
5531                                                _it->tooltip.data, NULL);
5532         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5533         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5534      }
5535
5536    return;
5537
5538 error:
5539    if (del_cb) del_cb((void *)data, NULL, NULL);
5540 }
5541
5542 EAPI void
5543 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5544 {
5545    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5546    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5547
5548    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5549      elm_widget_item_tooltip_unset(_it);
5550
5551    if (_it->tooltip.del_cb)
5552      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5553    _it->tooltip.del_cb = NULL;
5554    _it->tooltip.content_cb = NULL;
5555    _it->tooltip.data = NULL;
5556    _it->tooltip.free_size = EINA_FALSE;
5557    if (_it->tooltip.style)
5558      elm_genlist_item_tooltip_style_set(it, NULL);
5559 }
5560
5561 EAPI void
5562 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5563                                    const char       *style)
5564 {
5565    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5566    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5567
5568    eina_stringshare_replace(&_it->tooltip.style, style);
5569    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5570 }
5571
5572 EAPI const char *
5573 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5574 {
5575    return elm_object_item_tooltip_style_get(it);
5576 }
5577
5578 EAPI Eina_Bool
5579 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5580                                          Eina_Bool disable)
5581 {
5582    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5583    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5584
5585    _it->tooltip.free_size = disable;
5586    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5587    return EINA_TRUE;
5588 }
5589
5590 EAPI Eina_Bool
5591 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5592 {
5593    return elm_object_tooltip_window_mode_get(VIEW(it));
5594 }
5595
5596 EAPI void
5597 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5598                             const char       *cursor)
5599 {
5600    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5601    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5602    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5603    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5604 }
5605
5606 EAPI const char *
5607 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5608 {
5609    return elm_widget_item_cursor_get(it);
5610 }
5611
5612 EAPI void
5613 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5614 {
5615    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5616    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5617
5618    if (!_it->mouse_cursor) return;
5619
5620    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5621
5622    eina_stringshare_del(_it->mouse_cursor);
5623    _it->mouse_cursor = NULL;
5624 }
5625
5626 EAPI void
5627 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
5628                                   const char       *style)
5629 {
5630    elm_widget_item_cursor_style_set(it, style);
5631 }
5632
5633 EAPI const char *
5634 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5635 {
5636    return elm_widget_item_cursor_style_get(it);
5637 }
5638
5639 EAPI void
5640 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5641                                         Eina_Bool        engine_only)
5642 {
5643    elm_widget_item_cursor_engine_only_set(it, engine_only);
5644 }
5645
5646 EAPI Eina_Bool
5647 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5648 {
5649    return elm_widget_item_cursor_engine_only_get(it);
5650 }
5651
5652 EAPI int
5653 elm_genlist_item_index_get(const Elm_Object_Item *it)
5654 {
5655    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5656    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5657
5658    if (_it->item->block)
5659      return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5660    return -1;
5661 }
5662
5663 EAPI void
5664 elm_genlist_mode_set(Evas_Object  *obj,
5665                      Elm_List_Mode mode)
5666 {
5667    ELM_CHECK_WIDTYPE(obj, widtype);
5668    Widget_Data *wd = elm_widget_data_get(obj);
5669    if (!wd) return;
5670    if (wd->mode == mode) return;
5671    wd->mode = mode;
5672    if (wd->mode == ELM_LIST_COMPRESS)
5673      elm_genlist_homogeneous_set(obj, EINA_FALSE);
5674    _sizing_eval(obj);
5675 }
5676
5677
5678 EAPI Elm_List_Mode
5679 elm_genlist_mode_get(const Evas_Object *obj)
5680 {
5681    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5682    Widget_Data *wd = elm_widget_data_get(obj);
5683    if (!wd) return ELM_LIST_LAST;
5684    return wd->mode;
5685 }
5686
5687 EAPI void
5688 elm_genlist_bounce_set(Evas_Object *obj,
5689                        Eina_Bool    h_bounce,
5690                        Eina_Bool    v_bounce)
5691 {
5692    ELM_CHECK_WIDTYPE(obj, widtype);
5693    Widget_Data *wd = elm_widget_data_get(obj);
5694    if (!wd) return;
5695    wd->h_bounce = !!h_bounce;
5696    wd->v_bounce = !!v_bounce;
5697    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5698 }
5699
5700 EAPI void
5701 elm_genlist_bounce_get(const Evas_Object *obj,
5702                        Eina_Bool         *h_bounce,
5703                        Eina_Bool         *v_bounce)
5704 {
5705    ELM_CHECK_WIDTYPE(obj, widtype);
5706    Widget_Data *wd = elm_widget_data_get(obj);
5707    if (!wd) return;
5708    if (h_bounce) *h_bounce = wd->h_bounce;
5709    if (v_bounce) *v_bounce = wd->v_bounce;
5710 }
5711
5712 EAPI void
5713 elm_genlist_homogeneous_set(Evas_Object *obj,
5714                             Eina_Bool    homogeneous)
5715 {
5716    ELM_CHECK_WIDTYPE(obj, widtype);
5717    Widget_Data *wd = elm_widget_data_get(obj);
5718    if (!wd) return;
5719    wd->homogeneous = !!homogeneous;
5720 }
5721
5722 EAPI Eina_Bool
5723 elm_genlist_homogeneous_get(const Evas_Object *obj)
5724 {
5725    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5726    Widget_Data *wd = elm_widget_data_get(obj);
5727    if (!wd) return EINA_FALSE;
5728    return wd->homogeneous;
5729 }
5730
5731 EAPI void
5732 elm_genlist_block_count_set(Evas_Object *obj,
5733                             int          count)
5734 {
5735    ELM_CHECK_WIDTYPE(obj, widtype);
5736    Widget_Data *wd = elm_widget_data_get(obj);
5737    if (!wd) return;
5738    wd->max_items_per_block = count;
5739    wd->item_cache_max = wd->max_items_per_block * 2;
5740    _item_cache_clean(wd);
5741 }
5742
5743 EAPI int
5744 elm_genlist_block_count_get(const Evas_Object *obj)
5745 {
5746    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5747    Widget_Data *wd = elm_widget_data_get(obj);
5748    if (!wd) return 0;
5749    return wd->max_items_per_block;
5750 }
5751
5752 EAPI void
5753 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5754                                   double       timeout)
5755 {
5756    ELM_CHECK_WIDTYPE(obj, widtype);
5757    Widget_Data *wd = elm_widget_data_get(obj);
5758    if (!wd) return;
5759    wd->longpress_timeout = timeout;
5760 }
5761
5762 EAPI double
5763 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5764 {
5765    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5766    Widget_Data *wd = elm_widget_data_get(obj);
5767    if (!wd) return 0;
5768    return wd->longpress_timeout;
5769 }
5770
5771 EAPI void
5772 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5773                                 Elm_Scroller_Policy policy_h,
5774                                 Elm_Scroller_Policy policy_v)
5775 {
5776    ELM_CHECK_WIDTYPE(obj, widtype);
5777    Widget_Data *wd = elm_widget_data_get(obj);
5778    if ((!wd) || (!wd->scr)) return;
5779    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5780        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5781      return;
5782    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5783 }
5784
5785 EAPI void
5786 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5787                                 Elm_Scroller_Policy *policy_h,
5788                                 Elm_Scroller_Policy *policy_v)
5789 {
5790    ELM_CHECK_WIDTYPE(obj, widtype);
5791    Widget_Data *wd = elm_widget_data_get(obj);
5792    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5793    if ((!wd) || (!wd->scr)) return;
5794    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5795    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5796    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5797 }
5798
5799 EAPI void
5800 elm_genlist_realized_items_update(Evas_Object *obj)
5801 {
5802    ELM_CHECK_WIDTYPE(obj, widtype);
5803
5804    Eina_List *list, *l;
5805    Elm_Object_Item *it;
5806
5807    list = elm_genlist_realized_items_get(obj);
5808    EINA_LIST_FOREACH(list, l, it)
5809      elm_genlist_item_update(it);
5810 }
5811
5812 EAPI void
5813 elm_genlist_item_decorate_mode_set(Elm_Object_Item  *it,
5814                                    const char       *decorate_type,
5815                                    Eina_Bool         mode_set)
5816 {
5817    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5818    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5819
5820    Widget_Data *wd = _it->wd;
5821    Eina_List *l;
5822    Elm_Object_Item *it2;
5823
5824    if (!wd) return;
5825    if (!decorate_type) return;
5826    if ((_it->generation < _it->wd->generation) ||
5827        elm_widget_item_disabled_get(_it)) return;
5828    if (wd->decorate_mode) return;
5829
5830    if ((wd->mode_item == _it) &&
5831        (!strcmp(decorate_type, wd->decorate_type)) &&
5832        (mode_set))
5833       return;
5834    if (!_it->itc->decorate_item_style) return;
5835    _it->mode_set = mode_set;
5836
5837    if (wd->multi)
5838      {
5839         EINA_LIST_FOREACH(wd->selected, l, it2)
5840           if (((Elm_Gen_Item *)it2)->realized)
5841             elm_genlist_item_selected_set(it2, EINA_FALSE);
5842      }
5843    else
5844      {
5845         it2 = elm_genlist_selected_item_get(wd->obj);
5846         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5847           elm_genlist_item_selected_set(it2, EINA_FALSE);
5848      }
5849
5850    if (((wd->decorate_type) && (strcmp(decorate_type, wd->decorate_type))) ||
5851        (mode_set) ||
5852        ((_it == wd->mode_item) && (!mode_set)))
5853      _item_mode_unset(wd);
5854
5855    eina_stringshare_replace(&wd->decorate_type, decorate_type);
5856    if (mode_set) _item_mode_set(_it);
5857 }
5858
5859 EAPI const char *
5860 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5861 {
5862    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5863    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5864    return _it->wd->decorate_type;
5865 }
5866
5867 EAPI const Elm_Object_Item *
5868 elm_genlist_decorated_item_get(const Evas_Object *obj)
5869 {
5870    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5871    Widget_Data *wd = elm_widget_data_get(obj);
5872    if (!wd) return NULL;
5873    return (Elm_Object_Item *) wd->mode_item;
5874 }
5875
5876 EAPI Eina_Bool
5877 elm_genlist_decorate_mode_get(const Evas_Object *obj)
5878 {
5879    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5880    Widget_Data *wd = elm_widget_data_get(obj);
5881    if (!wd) return EINA_FALSE;
5882
5883    return wd->decorate_mode;
5884 }
5885
5886 EAPI void
5887 elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
5888 {
5889    ELM_CHECK_WIDTYPE(obj, widtype);
5890    Eina_List *list, *l;
5891    Elm_Gen_Item *it;
5892
5893    Widget_Data *wd = elm_widget_data_get(obj);
5894    if (!wd) return;
5895    decorated = !!decorated;
5896    if (wd->decorate_mode == decorated) return;
5897    wd->decorate_mode = decorated;
5898
5899    list = elm_genlist_realized_items_get(obj);
5900    if (!wd->decorate_mode)
5901      {
5902         EINA_LIST_FOREACH(list, l, it)
5903           {
5904              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5905                _decorate_mode_item_unrealize(it);
5906           }
5907         _item_cache_zero(wd);
5908      }
5909    else
5910      {
5911         EINA_LIST_FOREACH(list, l, it)
5912           {
5913              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5914                {
5915                   if (it->selected) _item_unselect(it);
5916                   if (it->itc->decorate_all_item_style)
5917                      _decorate_mode_item_realize(it, EINA_TRUE);
5918                }
5919           }
5920      }
5921    if (wd->calc_job) ecore_job_del(wd->calc_job);
5922    wd->calc_job = ecore_job_add(_calc_job, wd);
5923 }
5924
5925 EAPI void
5926 elm_genlist_reorder_mode_set(Evas_Object *obj,
5927                              Eina_Bool    reorder_mode)
5928 {
5929    ELM_CHECK_WIDTYPE(obj, widtype);
5930    Widget_Data *wd = elm_widget_data_get(obj);
5931    if (!wd) return;
5932    wd->reorder_mode = !!reorder_mode;
5933 }
5934
5935 EAPI Eina_Bool
5936 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5937 {
5938    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5939    Widget_Data *wd = elm_widget_data_get(obj);
5940    if (!wd) return EINA_FALSE;
5941    return wd->reorder_mode;
5942 }
5943
5944 EAPI Elm_Genlist_Item_Type
5945 elm_genlist_item_type_get(const Elm_Object_Item *it)
5946 {
5947    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5948    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5949    return _it->item->type;
5950 }
5951
5952 EAPI Elm_Genlist_Item_Class *
5953 elm_genlist_item_class_new(void)
5954 {
5955    Elm_Genlist_Item_Class *itc;
5956
5957    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5958    if (!itc)
5959      return NULL;
5960    itc->version = CLASS_ALLOCATED;
5961    itc->refcount = 1;
5962    itc->delete_me = EINA_FALSE;
5963
5964    return itc;
5965 }
5966
5967 EAPI void
5968 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5969 {
5970    if (itc && (itc->version == CLASS_ALLOCATED))
5971      {
5972         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5973         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5974         else
5975           {
5976              itc->version = 0;
5977              free(itc);
5978           }
5979      }
5980 }
5981
5982 EAPI void
5983 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5984 {
5985    if (itc && (itc->version == CLASS_ALLOCATED))
5986      {
5987         itc->refcount++;
5988         if (itc->refcount == 0) itc->refcount--;
5989      }
5990 }
5991
5992 EAPI void
5993 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5994 {
5995    if (itc && (itc->version == CLASS_ALLOCATED))
5996      {
5997         if (itc->refcount > 0) itc->refcount--;
5998         if (itc->delete_me && (!itc->refcount))
5999           elm_genlist_item_class_free(itc);
6000      }
6001 }
6002
6003 void _flip_job(void *data)
6004 {
6005    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
6006    _elm_genlist_item_unrealize(it, EINA_FALSE);
6007    if (it->selected) _item_unselect(it);
6008    it->flipped = EINA_TRUE;
6009    it->item->nocache = EINA_TRUE;
6010 }
6011
6012 EAPI void
6013 elm_genlist_item_flip_set(Elm_Object_Item *it,
6014                           Eina_Bool flip)
6015 {
6016    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6017    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6018
6019    flip = !!flip;
6020    if (_it->flipped == flip) return;
6021
6022    if (flip)
6023      {
6024         ecore_job_add(_flip_job, _it);
6025         if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
6026         _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
6027      }
6028    else
6029      {
6030         _it->flipped = flip;
6031         _item_cache_zero(_it->wd);
6032         elm_genlist_item_update(it);
6033         _it->item->nocache = EINA_FALSE;
6034      }
6035 }
6036
6037 EAPI Eina_Bool
6038 elm_genlist_item_flip_get(const Elm_Object_Item *it)
6039 {
6040    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
6041    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6042    return _it->flipped;
6043 }
6044
6045 EAPI void
6046 elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
6047 {
6048    ELM_CHECK_WIDTYPE(obj, widtype);
6049    Widget_Data *wd = elm_widget_data_get(obj);
6050    if (!wd) return;
6051    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6052      return;
6053    if (wd->select_mode != mode)
6054      wd->select_mode = mode;
6055 }
6056
6057 EAPI Elm_Object_Select_Mode
6058 elm_genlist_select_mode_get(const Evas_Object *obj)
6059 {
6060    ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
6061    Widget_Data *wd = elm_widget_data_get(obj);
6062    if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
6063    return wd->select_mode;
6064 }
6065
6066 EAPI void
6067 elm_genlist_highlight_mode_set(Evas_Object *obj,
6068                                Eina_Bool    highlight)
6069 {
6070    ELM_CHECK_WIDTYPE(obj, widtype);
6071    Widget_Data *wd = elm_widget_data_get(obj);
6072    if (!wd) return;
6073    wd->highlight = !!highlight;
6074 }
6075
6076 EAPI Eina_Bool
6077 elm_genlist_highlight_mode_get(const Evas_Object *obj)
6078 {
6079    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6080    Widget_Data *wd = elm_widget_data_get(obj);
6081    if (!wd) return EINA_FALSE;
6082    return wd->highlight;
6083 }
6084
6085 EAPI void
6086 elm_genlist_item_select_mode_set(Elm_Object_Item *it,
6087                                  Elm_Object_Select_Mode mode)
6088 {
6089    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
6090    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6091    if (!_it) return;
6092    if (_it->generation < _it->wd->generation) return;
6093    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6094      return;
6095    if (_it->select_mode != mode)
6096      _it->select_mode = mode;
6097
6098    if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
6099      {
6100         _it->item->mincalcd = EINA_FALSE;
6101         _it->item->updateme = EINA_TRUE;
6102         if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
6103         if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
6104         _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
6105      }
6106 }
6107
6108 EAPI Elm_Object_Select_Mode
6109 elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
6110 {
6111    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
6112    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
6113    if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
6114    return _it->select_mode;
6115 }
6116
6117 /* for gengrid as of now */
6118 void
6119 _elm_genlist_page_relative_set(Evas_Object *obj,
6120                                double       h_pagerel,
6121                                double       v_pagerel)
6122 {
6123    Evas_Coord pagesize_h;
6124    Evas_Coord pagesize_v;
6125
6126    ELM_CHECK_WIDTYPE(obj, widtype);
6127    Widget_Data *wd = elm_widget_data_get(obj);
6128    if (!wd) return;
6129
6130    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
6131    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
6132                                  pagesize_v);
6133 }
6134
6135 /* for gengrid as of now */
6136 void
6137 _elm_genlist_page_relative_get(const Evas_Object *obj,
6138                                double            *h_pagerel,
6139                                double            *v_pagerel)
6140 {
6141    ELM_CHECK_WIDTYPE(obj, widtype);
6142    Widget_Data *wd = elm_widget_data_get(obj);
6143    if (!wd) return;
6144
6145    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
6146 }
6147
6148 /* for gengrid as of now */
6149 void
6150 _elm_genlist_page_size_set(Evas_Object *obj,
6151                            Evas_Coord   h_pagesize,
6152                            Evas_Coord   v_pagesize)
6153 {
6154    double pagerel_h;
6155    double pagerel_v;
6156
6157    ELM_CHECK_WIDTYPE(obj, widtype);
6158    Widget_Data *wd = elm_widget_data_get(obj);
6159    if (!wd) return;
6160    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
6161    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
6162                                  v_pagesize);
6163 }
6164
6165 /* for gengrid as of now */
6166 void
6167 _elm_genlist_current_page_get(const Evas_Object *obj,
6168                               int               *h_pagenumber,
6169                               int               *v_pagenumber)
6170 {
6171    ELM_CHECK_WIDTYPE(obj, widtype);
6172    Widget_Data *wd = elm_widget_data_get(obj);
6173    if (!wd) return;
6174    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
6175 }
6176
6177 /* for gengrid as of now */
6178 void
6179 _elm_genlist_last_page_get(const Evas_Object *obj,
6180                            int               *h_pagenumber,
6181                            int               *v_pagenumber)
6182 {
6183    ELM_CHECK_WIDTYPE(obj, widtype);
6184    Widget_Data *wd = elm_widget_data_get(obj);
6185    if (!wd) return;
6186    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
6187 }
6188
6189 /* for gengrid as of now */
6190 void
6191 _elm_genlist_page_show(const Evas_Object *obj,
6192                        int                h_pagenumber,
6193                        int                v_pagenumber)
6194 {
6195    ELM_CHECK_WIDTYPE(obj, widtype);
6196    Widget_Data *wd = elm_widget_data_get(obj);
6197    if (!wd) return;
6198    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
6199 }
6200
6201 /* for gengrid as of now */
6202 void
6203 _elm_genlist_page_bring_in(const Evas_Object *obj,
6204                            int                h_pagenumber,
6205                            int                v_pagenumber)
6206 {
6207    ELM_CHECK_WIDTYPE(obj, widtype);
6208    Widget_Data *wd = elm_widget_data_get(obj);
6209    if (!wd) return;
6210    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
6211 }
6212
6213 void
6214 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
6215                             Eina_Bool     calc)
6216 {
6217    Evas_Object *content;
6218
6219    if (!it->realized) return;
6220    if (it->wd->reorder_it == it) return;
6221    if (it->defer_unrealize && !it->item->updateme) return;
6222
6223    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
6224    if (!calc)
6225      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
6226    if (it->long_timer)
6227      {
6228         ecore_timer_del(it->long_timer);
6229         it->long_timer = NULL;
6230      }
6231
6232    elm_widget_stringlist_free(it->texts);
6233    it->texts = NULL;
6234    elm_widget_stringlist_free(it->contents);
6235    it->contents = NULL;
6236    elm_widget_stringlist_free(it->states);
6237    it->states = NULL;
6238
6239    EINA_LIST_FREE(it->content_objs, content)
6240      evas_object_del(content);
6241
6242    it->unrealize_cb(it);
6243
6244    it->realized = EINA_FALSE;
6245    it->want_unrealize = EINA_FALSE;
6246    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
6247    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
6248 }
6249
6250 void
6251 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
6252 {
6253    elm_widget_item_pre_notify_del(it);
6254    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
6255
6256    if ((it->relcount > 0) || (it->walking > 0)) return;
6257
6258    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
6259
6260    if (it->itc->func.del)
6261      it->itc->func.del((void *)it->base.data, WIDGET(it));
6262 }
6263
6264 void
6265 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
6266 {
6267    _elm_genlist_item_del_notserious(it);
6268    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
6269    if (it->tooltip.del_cb)
6270      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6271    it->wd->walking -= it->walking;
6272    if (it->long_timer) ecore_timer_del(it->long_timer);
6273    if (it->group)
6274      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
6275
6276    if (it->wd->state)
6277      {
6278         eina_inlist_sorted_state_free(it->wd->state);
6279         it->wd->state = NULL;
6280      }
6281    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
6282    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
6283    free(it->item);
6284
6285    it->item = NULL;
6286    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
6287      it->wd->last_selected_item = NULL;
6288    it->wd->item_count--;
6289 }
6290
6291 EAPI void
6292 elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
6293 {
6294    ELM_CHECK_WIDTYPE(obj, widtype);
6295    Widget_Data *wd = elm_widget_data_get(obj);
6296    if (!wd) return;
6297    wd->tree_effect_enabled = !!enabled;
6298 }
6299
6300 EAPI Eina_Bool
6301 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
6302 {
6303    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
6304    Widget_Data *wd = elm_widget_data_get(obj);
6305    if (!wd) return EINA_FALSE;
6306    return wd->tree_effect_enabled;
6307 }
6308
6309 static Evas_Object*
6310 _create_tray_alpha_bg(const Evas_Object *obj)
6311 {
6312    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
6313    Widget_Data *wd = elm_widget_data_get(obj);
6314    if (!wd) return NULL;
6315
6316    Evas_Object *bg = NULL;
6317    Evas_Coord ox, oy, ow, oh;
6318
6319    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6320    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
6321    evas_object_color_set(bg,0,0,0,0);
6322    evas_object_resize(bg , ow, oh);
6323    evas_object_move(bg , ox, oy);
6324    return bg ;
6325 }
6326
6327 static void
6328 _item_contract_emit(Elm_Gen_Item *it)
6329 {
6330    Elm_Gen_Item *it2;
6331    Eina_List *l;
6332
6333    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
6334    it->item->tree_effect_finished = EINA_FALSE;
6335
6336    EINA_LIST_FOREACH(it->item->items, l, it2)
6337      if (it2) _item_contract_emit(it2);
6338 }
6339
6340 static int
6341 _item_tree_effect_before(Elm_Gen_Item *it)
6342 {
6343    Elm_Gen_Item *it2;
6344    Eina_List *l;
6345
6346    EINA_LIST_FOREACH(it->item->items, l, it2)
6347      {
6348         if (it2->parent && (it == it2->parent))
6349           {
6350              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6351                edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
6352              else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6353                _item_contract_emit(it2);
6354           }
6355      }
6356    return ECORE_CALLBACK_CANCEL;
6357 }
6358
6359 static void
6360 _item_tree_effect(Widget_Data *wd, int y)
6361 {
6362    Elm_Gen_Item *it = NULL, *expanded_next_it;
6363
6364    expanded_next_it = wd->expanded_next_item;
6365
6366    if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6367      {
6368         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6369         while (it)
6370           {
6371              if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
6372              if (it->item->scrl_y && (it->item->scrl_y < expanded_next_it->item->old_scrl_y + y) &&
6373                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6374                {
6375                   if (!it->item->tree_effect_finished)
6376                     {
6377                        edje_object_signal_emit(VIEW(it), "flip_item", "");
6378                        evas_object_show(VIEW(it));
6379                        it->item->tree_effect_finished = EINA_TRUE;
6380                     }
6381                }
6382              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6383           }
6384      }
6385    else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6386      {
6387         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6388         while (it)
6389           {
6390              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
6391                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6392                {
6393                   if (!it->item->tree_effect_finished)
6394                     {
6395                        edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
6396                        it->item->tree_effect_finished = EINA_TRUE;
6397                     }
6398                }
6399              else
6400                break;
6401              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6402           }
6403      }
6404 }
6405
6406 static void
6407 _item_tree_effect_finish(Widget_Data *wd)
6408 {
6409    Item_Block *itb;
6410    Elm_Gen_Item *it = NULL;
6411    const Eina_List *l;
6412
6413    if (wd->item_moving_effect_timer)
6414      {
6415         if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6416            _item_subitems_clear(wd->expanded_item);
6417         EINA_INLIST_FOREACH(wd->blocks, itb)
6418           {
6419              EINA_LIST_FOREACH(itb->items, l, it)
6420                {
6421                   it->item->tree_effect_finished = EINA_TRUE;
6422                   it->item->old_scrl_y = it->item->scrl_y;
6423                }
6424           }
6425      }
6426    _item_auto_scroll(wd);
6427    evas_object_lower(wd->alpha_bg);
6428    evas_object_hide(wd->alpha_bg);
6429    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6430    if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
6431
6432    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
6433    evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
6434    evas_object_smart_changed(wd->pan_smart);
6435
6436    wd->item_moving_effect_timer = NULL;
6437 }
6438
6439 static Eina_Bool
6440 _item_moving_effect_timer_cb(void *data)
6441 {
6442    Widget_Data *wd = data;
6443    if (!wd) return EINA_FALSE;
6444    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
6445    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
6446    const Eina_List *l;
6447    double effect_duration = 0.5, t;
6448    int y = 0, dy = 0, dh = 0;
6449    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
6450    int in = 0;
6451
6452    t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
6453    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6454    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
6455    if (t > effect_duration) end = EINA_TRUE;
6456
6457    // Below while statement is needed, when the genlist is resized.
6458    it2 = wd->expanded_item;
6459    while (it2 && vis)
6460      {
6461         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
6462         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
6463                                    cvx, cvy, cvw, cvh));
6464         it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
6465      }
6466
6467    if (wd->expanded_next_item)
6468      {
6469         expanded_next_it = wd->expanded_next_item;
6470
6471         /* move items */
6472         EINA_LIST_FOREACH(wd->move_items, l, it)
6473           {
6474              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6475                {
6476                   expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6477                   if (expanded_next_it->item->scrl_y < expanded_next_it->item->old_scrl_y) //did not calculate next item position
6478                     expanded_next_it->item->scrl_y = cvy + cvh;
6479
6480                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6481                          cvy + cvh : expanded_next_it->item->scrl_y) -
6482                          expanded_next_it->item->old_scrl_y;
6483                }
6484              else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6485                {
6486                   if (expanded_next_it->item->scrl_y > expanded_next_it->item->old_scrl_y) //did not calculate next item position
6487                      expanded_next_it->item->old_scrl_y = cvy + cvh;
6488
6489                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6490                     {
6491                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6492                        cvy + cvh;
6493                        expanded_next_it->item->old_scrl_y = cvy + cvh;
6494                     }
6495                   else
6496                     {
6497                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6498                              expanded_next_it->item->old_scrl_y;
6499                     }
6500                }
6501
6502              if (t <= effect_duration)
6503                {
6504                   y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6505                }
6506              else
6507                {
6508                   end = EINA_TRUE;
6509                   y = dy;
6510                }
6511
6512              if (!it->realized)
6513                {
6514                   _item_realize(it, in, 0);
6515                }
6516              in++;
6517
6518              if (it != expanded_next_it)
6519                {
6520                   it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6521                   dh += it->item->h;
6522                }
6523
6524              if ((it->item->old_scrl_y + y) < (cvy + cvh))
6525                _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6526           }
6527         /* tree effect */
6528         _item_tree_effect(wd, y);
6529      }
6530    else
6531      {
6532         int expanded_item_num = 0;
6533         int num = 0;
6534
6535         if (wd->expanded_item)
6536           it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6537
6538         it2 = it;
6539         while (it2)
6540           {
6541              expanded_item_num++;
6542              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6543           }
6544
6545         while (it)
6546           {
6547              num++;
6548              if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6549              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6550                {
6551                   if (!it->item->tree_effect_finished)
6552                     {
6553                        if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6554                          {
6555                             edje_object_signal_emit(VIEW(it), "flip_item", "");
6556                             evas_object_show(VIEW(it));
6557                             it->item->tree_effect_finished = EINA_TRUE;
6558                          }
6559                     }
6560                }
6561              it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6562           }
6563      }
6564
6565    if (end)
6566      {
6567         _item_tree_effect_finish(wd);
6568         return ECORE_CALLBACK_CANCEL;
6569      }
6570    return ECORE_CALLBACK_RENEW;
6571 }