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