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