[Genlist] When genlist is clearing, do not push item into cache
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <fnmatch.h>
2 #include <Elementary.h>
3 #include <Elementary_Cursor.h>
4 #include "elm_priv.h"
5 #include "elm_widget_genlist.h"
6
7 #define GROUP_ITEMS_FEATURE 0
8 // internally allocated
9 #define CLASS_ALLOCATED     0x3a70f11f
10
11 #define MAX_ITEMS_PER_BLOCK 32
12 #define REORDER_EFFECT_TIME 0.1
13 #define FX_MOVE_TIME 0.5
14
15 EAPI const char ELM_GENLIST_SMART_NAME[] = "elm_genlist";
16 EAPI const char ELM_GENLIST_PAN_SMART_NAME[] = "elm_genlist_pan";
17
18 #define ERR_ABORT(_msg) \
19   ERR(_msg);            \
20   if (getenv("ELM_ERROR_ABORT")) abort();
21
22 #define GL_IT(_it) (_it->item)
23
24 #define IS_ROOT_PARENT_IT(_it) \
25    ((_it->group) || (GL_IT(_it)->items && GL_IT(_it)->expanded_depth == 0)) \
26
27 static const Evas_Smart_Interface *_smart_interfaces[] =
28 {
29    (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
30 };
31
32 static const char SIG_ACTIVATED[] = "activated";
33 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
34 static const char SIG_SELECTED[] = "selected";
35 static const char SIG_UNSELECTED[] = "unselected";
36 static const char SIG_EXPANDED[] = "expanded";
37 static const char SIG_CONTRACTED[] = "contracted";
38 static const char SIG_EXPAND_REQUEST[] = "expand,request";
39 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
40 static const char SIG_REALIZED[] = "realized";
41 static const char SIG_UNREALIZED[] = "unrealized";
42 static const char SIG_DRAG_START_UP[] = "drag,start,up";
43 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
44 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
45 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
46 static const char SIG_DRAG_STOP[] = "drag,stop";
47 static const char SIG_DRAG[] = "drag";
48 static const char SIG_LONGPRESSED[] = "longpressed";
49 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
50 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
51 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
52 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
53 static const char SIG_EDGE_TOP[] = "edge,top";
54 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
55 static const char SIG_EDGE_LEFT[] = "edge,left";
56 static const char SIG_EDGE_RIGHT[] = "edge,right";
57 static const char SIG_VBAR_DRAG[] = "vbar,drag";
58 static const char SIG_VBAR_PRESS[] = "vbar,press";
59 static const char SIG_VBAR_UNPRESS[] = "vbar,unpress";
60 static const char SIG_HBAR_DRAG[] = "hbar,drag";
61 static const char SIG_HBAR_PRESS[] = "hbar,press";
62 static const char SIG_HBAR_UNPRESS[] = "hbar,unpress";
63 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
64 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
65 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
66 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
67 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
68 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
69 static const char SIG_SWIPE[] = "swipe";
70 static const char SIG_MOVED[] = "moved";
71 static const char SIG_MOVED_AFTER[] = "moved,after";
72 static const char SIG_MOVED_BEFORE[] = "moved,before";
73 static const char SIG_INDEX_UPDATE[] = "index,update";
74 static const char SIG_TREE_EFFECT_FINISHED [] = "tree,effect,finished";
75 static const char SIG_HIGHLIGHTED[] = "highlighted";
76 static const char SIG_UNHIGHLIGHTED[] = "unhighlighted";
77
78 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
79    {SIG_CLICKED_DOUBLE, ""},
80    {SIG_ACTIVATED, ""},
81    {SIG_SELECTED, ""},
82    {SIG_UNSELECTED, ""},
83    {SIG_EXPANDED, ""},
84    {SIG_CONTRACTED, ""},
85    {SIG_EXPAND_REQUEST, ""},
86    {SIG_CONTRACT_REQUEST, ""},
87    {SIG_REALIZED, ""},
88    {SIG_UNREALIZED, ""},
89    {SIG_DRAG_START_UP, ""},
90    {SIG_DRAG_START_DOWN, ""},
91    {SIG_DRAG_START_LEFT, ""},
92    {SIG_DRAG_START_RIGHT, ""},
93    {SIG_DRAG_STOP, ""},
94    {SIG_DRAG, ""},
95    {SIG_LONGPRESSED, ""},
96    {SIG_SCROLL_ANIM_START, ""},
97    {SIG_SCROLL_ANIM_STOP, ""},
98    {SIG_SCROLL_DRAG_START, ""},
99    {SIG_SCROLL_DRAG_STOP, ""},
100    {SIG_EDGE_TOP, ""},
101    {SIG_EDGE_BOTTOM, ""},
102    {SIG_EDGE_LEFT, ""},
103    {SIG_EDGE_RIGHT, ""},
104    {SIG_VBAR_DRAG, ""},
105    {SIG_VBAR_PRESS, ""},
106    {SIG_VBAR_UNPRESS, ""},
107    {SIG_HBAR_DRAG, ""},
108    {SIG_HBAR_PRESS, ""},
109    {SIG_HBAR_UNPRESS, ""},
110    {SIG_MULTI_SWIPE_LEFT, ""},
111    {SIG_MULTI_SWIPE_RIGHT, ""},
112    {SIG_MULTI_SWIPE_UP, ""},
113    {SIG_MULTI_SWIPE_DOWN, ""},
114    {SIG_MULTI_PINCH_OUT, ""},
115    {SIG_MULTI_PINCH_IN, ""},
116    {SIG_SWIPE, ""},
117    {SIG_MOVED, ""},
118    {SIG_MOVED_AFTER, ""},
119    {SIG_MOVED_BEFORE, ""},
120    {SIG_TREE_EFFECT_FINISHED, ""},
121    {SIG_HIGHLIGHTED, ""},
122    {SIG_UNHIGHLIGHTED, ""},
123    {NULL, NULL}
124 };
125
126 EVAS_SMART_SUBCLASS_IFACE_NEW
127   (ELM_GENLIST_SMART_NAME, _elm_genlist, Elm_Genlist_Smart_Class,
128   Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks,
129   _smart_interfaces);
130
131 ELM_INTERNAL_SMART_SUBCLASS_NEW
132   (ELM_GENLIST_PAN_SMART_NAME, _elm_genlist_pan, Elm_Genlist_Pan_Smart_Class,
133   Elm_Pan_Smart_Class, elm_pan_smart_class_get, NULL);
134
135 static void      _calc_job(void *);
136 static Eina_Bool _item_block_recalc(Item_Block *, int, Eina_Bool);
137 static void      _item_mouse_callbacks_add(Elm_Gen_Item *, Evas_Object *);
138 static void      _item_mouse_callbacks_del(Elm_Gen_Item *, Evas_Object *);
139 static void      _access_activate_cb(void *data __UNUSED__,
140                                      Evas_Object *part_obj __UNUSED__,
141                                      Elm_Object_Item *item);
142 static void _item_select(Elm_Gen_Item *it);
143
144 static void     _expand_toggle_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__);
145 static void     _expand_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__);
146 static void     _contract_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__);
147 static void _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *ic);
148 static void _decorate_item_unrealize(Elm_Gen_Item *it);
149 static void _decorate_all_item_unrealize(Elm_Gen_Item *it);
150 static void _decorate_item_set(Elm_Gen_Item *it);
151
152 #if GENLIST_FX_SUPPORT
153 static Eina_Bool      _elm_genlist_fx_capture(Evas_Object *obj, int level);
154 static void           _elm_genlist_fx_play(Evas_Object *obj);
155 static void           _elm_genlist_fx_clear(Evas_Object *obj);
156 static void           _elm_genlist_proxy_item_del(const Elm_Object_Item *item);
157 #endif
158
159 #if GENLIST_PINCH_ZOOM_SUPPORT
160 EAPI Eina_Bool          elm_genlist_pinch_zoom_mode_set(Evas_Object *obj, Elm_Gen_Pinch_Zoom_Mode mode);
161 #endif
162
163 static void
164 _item_cache_all_free(Elm_Genlist_Smart_Data *sd)
165 {
166    // It would be better not to use
167    // EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE
168    while (sd->item_cache)
169      {
170         Item_Cache *ic = EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache);
171         if (ic->spacer) evas_object_del(ic->spacer);
172         if (ic->base_view) evas_object_del(ic->base_view);
173         if (ic->item_style) eina_stringshare_del(ic->item_style);
174         sd->item_cache = eina_inlist_remove(sd->item_cache, EINA_INLIST_GET(ic));
175         // Free should be performed after inlist is poped
176         free(ic);
177      }
178    sd->item_cache = NULL;
179    sd->item_cache_count = 0;
180 }
181
182 static void
183 _item_cache_push(Elm_Gen_Item *it)
184 {
185    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
186    Item_Cache *ic = NULL;
187
188    if (sd->item_cache_count >= sd->item_cache_max)
189     {
190         ic = EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache);
191         if (ic->spacer) evas_object_del(ic->spacer);
192         if (ic->base_view) evas_object_del(ic->base_view);
193         eina_stringshare_del(ic->item_style);
194         sd->item_cache = eina_inlist_remove(sd->item_cache,
195                                              sd->item_cache->last);
196         sd->item_cache_count--;
197         // Free should be performed after inlist is poped
198         free(ic);
199      }
200    //evas_event_freeze(evas_object_evas_get(obj));
201
202    edje_object_mirrored_set(VIEW(it),
203                             elm_widget_mirrored_get(WIDGET(it)));
204    edje_object_scale_set(VIEW(it),
205                          elm_widget_scale_get(WIDGET(it))
206                          * elm_config_scale_get());
207
208    // FIXME: other callbacks?
209    edje_object_signal_callback_del_full(VIEW(it), "elm,action,expand,toggle",
210                                         "elm", _expand_toggle_signal_cb, it);
211    edje_object_signal_callback_del_full(VIEW(it), "elm,action,expand", "elm",
212                                         _expand_signal_cb, it);
213    edje_object_signal_callback_del_full(VIEW(it), "elm,action,contract", "elm",
214                                         _contract_signal_cb, it);
215    _item_mouse_callbacks_del(it, VIEW(it));
216
217 #if GENLIST_FX_SUPPORT
218    if ((it->item->nocache_once) || (it->item->nocache) || (sd->pending_del_items))
219 #else
220    if ((it->item->nocache_once) || (it->item->nocache))
221 #endif
222      {
223         if (VIEW(it)) evas_object_del(VIEW(it));
224         if (it->spacer) evas_object_del(it->spacer);
225         goto _ITEM_CLEAN;
226      }
227    ic = ELM_NEW(Item_Cache);
228    if (!ic)
229      {
230         if (VIEW(it)) evas_object_del(VIEW(it));
231         if (it->spacer) evas_object_del(it->spacer);
232         goto _ITEM_CLEAN;
233      }
234    if (it->long_timer)
235      {
236         ecore_timer_del(it->long_timer);
237         it->long_timer = NULL;
238      }
239    if (it->item->swipe_timer)
240      {
241         ecore_timer_del(it->item->swipe_timer);
242         it->item->swipe_timer = NULL;
243      }
244
245    ic->base_view = VIEW(it);
246    ic->spacer = it->spacer;
247    ic->item_style = eina_stringshare_add(it->itc->item_style);
248    if (it->item->type & ELM_GENLIST_ITEM_TREE) ic->tree = 1;
249
250    ic->selected = it->selected;
251    ic->disabled = elm_widget_item_disabled_get(it);
252    ic->expanded = it->item->expanded;
253    if (it->item->type & ELM_GENLIST_ITEM_TREE) ic->tree = 1;
254
255    edje_object_signal_emit(ic->base_view, "elm,state,unselected", "elm");
256    evas_object_hide(ic->base_view);
257
258    sd->item_cache = eina_inlist_prepend(sd->item_cache, EINA_INLIST_GET(ic));
259    sd->item_cache_count++;
260
261 _ITEM_CLEAN:
262    VIEW(it) = NULL;
263    it->spacer = NULL;
264    it->states = NULL;
265    it->realized = EINA_FALSE;
266    it->want_unrealize = EINA_FALSE;
267
268    //evas_event_thaw(evas_object_evas_get(obj));
269    //evas_event_thaw_eval(evas_object_evas_get(obj));
270 }
271
272 static Eina_Bool
273 _item_cache_pop(Elm_Gen_Item *it)
274 {
275    Item_Cache *ic = NULL;
276    Eina_Inlist *l;
277    Eina_Bool tree = 0;
278    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
279
280    if (it->item->nocache_once) {
281         it->item->nocache_once = EINA_FALSE;
282         return EINA_FALSE;
283    }
284    if (it->item->nocache) return EINA_FALSE;
285
286    if (it->item->type & ELM_GENLIST_ITEM_TREE) tree = 1;
287    EINA_INLIST_FOREACH_SAFE(sd->item_cache, l, ic)
288      {
289         if ((ic->selected) || (ic->disabled) || (ic->expanded))
290           continue;
291
292         if ((ic->tree == tree) &&
293             (((!it->itc->item_style) && (!ic->item_style)) ||
294              (it->itc->item_style && ic->item_style &&
295               (!strcmp(it->itc->item_style, ic->item_style)))))
296           {
297              sd->item_cache =
298                 eina_inlist_remove(sd->item_cache, EINA_INLIST_GET(ic));
299              sd->item_cache_count--;
300
301              VIEW(it) = ic->base_view;
302              it->spacer = ic->spacer;
303
304 #if 1 // FIXME: different from upstream
305              // Because of item cache, set state as default after cache item
306              // is popped.
307              edje_object_signal_emit(VIEW(it),"elm,state,default", "elm");
308 #endif
309              edje_object_signal_callback_add
310                 (VIEW(it), "elm,action,expand,toggle", "elm",
311                  _expand_toggle_signal_cb, it);
312              edje_object_signal_callback_add
313                 (VIEW(it), "elm,action,expand", "elm", _expand_signal_cb, it);
314              edje_object_signal_callback_add
315                 (VIEW(it), "elm,action,contract", "elm", _contract_signal_cb, it);
316              _item_mouse_callbacks_add(it, VIEW(it));
317
318              eina_stringshare_del(ic->item_style);
319              free(ic);
320
321              return EINA_TRUE;
322           }
323      }
324    return EINA_FALSE;
325 }
326
327 static void
328 _elm_genlist_pan_smart_pos_set(Evas_Object *obj,
329                                Evas_Coord x,
330                                Evas_Coord y)
331 {
332    Item_Block *itb;
333
334    ELM_GENLIST_PAN_DATA_GET(obj, psd);
335
336    if ((x == psd->wsd->pan_x) && (y == psd->wsd->pan_y)) return;
337    psd->wsd->pan_x = x;
338    psd->wsd->pan_y = y;
339
340    EINA_INLIST_FOREACH(psd->wsd->blocks, itb)
341      {
342         if ((itb->y + itb->h) > y)
343           {
344              Elm_Gen_Item *it;
345              Eina_List *l2;
346
347              EINA_LIST_FOREACH(itb->items, l2, it)
348                {
349                   if ((itb->y + it->y) >= y)
350                     {
351                        psd->wsd->anchor_item = it;
352                        psd->wsd->anchor_y = -(itb->y + it->y - y);
353                        goto done;
354                     }
355                }
356           }
357      }
358 done:
359    if (!psd->wsd->reorder_move_animator) evas_object_smart_changed(obj);
360 }
361
362 static void
363 _elm_genlist_pan_smart_pos_get(const Evas_Object *obj,
364                                Evas_Coord *x,
365                                Evas_Coord *y)
366 {
367    ELM_GENLIST_PAN_DATA_GET(obj, psd);
368
369    if (x) *x = psd->wsd->pan_x;
370    if (y) *y = psd->wsd->pan_y;
371 }
372
373 static void
374 _elm_genlist_pan_smart_pos_max_get(const Evas_Object *obj,
375                                    Evas_Coord *x,
376                                    Evas_Coord *y)
377 {
378    Evas_Coord ow, oh;
379
380    ELM_GENLIST_PAN_DATA_GET(obj, psd);
381
382    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
383    ow = psd->wsd->minw - ow;
384    if (ow < 0) ow = 0;
385    oh = psd->wsd->minh - oh;
386    if (oh < 0) oh = 0;
387    if (x) *x = ow;
388    if (y) *y = oh;
389
390 #if GENLIST_PINCH_ZOOM_SUPPORT
391    if (psd->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
392      {
393         evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
394         if (psd->wsd->pinch_zoom_h > oh)
395           *y = psd->wsd->pinch_zoom_h - oh;
396         else *y = 0;
397      }
398 #endif
399 }
400
401 static void
402 _elm_genlist_pan_smart_pos_min_get(const Evas_Object *obj __UNUSED__,
403                                    Evas_Coord *x,
404                                    Evas_Coord *y)
405 {
406    if (x) *x = 0;
407    if (y) *y = 0;
408 }
409
410 static void
411 _elm_genlist_pan_smart_content_size_get(const Evas_Object *obj,
412                                         Evas_Coord *w,
413                                         Evas_Coord *h)
414 {
415    ELM_GENLIST_PAN_DATA_GET(obj, psd);
416
417    if (w) *w = psd->wsd->minw;
418    if (h) *h = psd->wsd->minh;
419 }
420
421 static void
422 _elm_genlist_pan_smart_add(Evas_Object *obj)
423 {
424    /* here just to allocate our extended data */
425    EVAS_SMART_DATA_ALLOC(obj, Elm_Genlist_Pan_Smart_Data);
426
427    ELM_PAN_CLASS(_elm_genlist_pan_parent_sc)->base.add(obj);
428 }
429
430 static void
431 _elm_genlist_pan_smart_del(Evas_Object *obj)
432 {
433    ELM_GENLIST_PAN_DATA_GET(obj, psd);
434
435    if (psd->resize_job)
436      {
437         ecore_job_del(psd->resize_job);
438         psd->resize_job = NULL;
439      }
440
441    _elm_genlist_pan_parent_sc->base.del(obj);
442 }
443
444 static void
445 _elm_genlist_pan_smart_move(Evas_Object *obj,
446                             Evas_Coord x __UNUSED__,
447                             Evas_Coord y __UNUSED__)
448 {
449    ELM_GENLIST_PAN_DATA_GET(obj, psd);
450
451    psd->wsd->pan_changed = EINA_TRUE;
452    evas_object_smart_changed(obj);
453    if (psd->wsd->calc_job) ecore_job_del(psd->wsd->calc_job);
454    psd->wsd->calc_job = NULL;
455 }
456
457 static void
458 _elm_genlist_pan_smart_resize_job(void *data)
459 {
460    Elm_Genlist_Pan_Smart_Data *psd = data;
461
462    elm_layout_sizing_eval(ELM_WIDGET_DATA(psd->wsd)->obj);
463    psd->resize_job = NULL;
464 }
465
466 static void
467 _elm_genlist_pan_smart_resize(Evas_Object *obj,
468                               Evas_Coord w,
469                               Evas_Coord h)
470 {
471    Evas_Coord ow, oh;
472
473    ELM_GENLIST_PAN_DATA_GET(obj, psd);
474
475    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
476    if ((ow == w) && (oh == h)) return;
477    if ((psd->wsd->mode == ELM_LIST_COMPRESS) && (ow != w))
478      {
479         /* fix me later */
480         if (psd->resize_job) ecore_job_del(psd->resize_job);
481         psd->resize_job =
482           ecore_job_add(_elm_genlist_pan_smart_resize_job, psd);
483      }
484    psd->wsd->pan_changed = EINA_TRUE;
485    evas_object_smart_changed(obj);
486    if (psd->wsd->calc_job) ecore_job_del(psd->wsd->calc_job);
487    // if the widht changed we may have to resize content if scrollbar went
488    // away or appesared to queue a job to deal with it. it should settle in
489    // the end to a steady-state
490    if (ow != w)
491      psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wsd);
492    else
493      psd->wsd->calc_job = NULL;
494 }
495
496 static void
497 _item_scroll(Elm_Genlist_Smart_Data *sd)
498 {
499    Evas_Coord gith = 0;
500    Elm_Gen_Item *it = NULL;
501    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
502
503    if (!sd->show_item) return;
504
505    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &oh);
506    it = sd->show_item;
507    dx = it->x + it->item->block->x;
508    dy = it->y + it->item->block->y;
509    dw = it->item->block->w;
510    dh = oh;
511
512    switch (sd->scroll_to_type)
513      {
514       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
515         if (it->item->group_item) gith = it->item->group_item->item->h;
516         dy -= gith;
517         break;
518
519       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
520         dy += ((it->item->h / 2) - (oh / 2));
521         break;
522
523       case ELM_GENLIST_ITEM_SCROLLTO_IN:
524       default:
525         if ((sd->expanded_item) &&
526             ((sd->show_item->y + sd->show_item->item->block->y
527               + sd->show_item->item->h) -
528              (sd->expanded_item->y + sd->expanded_item->item->block->y) > oh))
529           {
530              it = sd->expanded_item;
531              if (it->item->group_item) gith = it->item->group_item->item->h;
532              dx = it->x + it->item->block->x;
533              dy = it->y + it->item->block->y - gith;
534              dw = it->item->block->w;
535           }
536         else
537           {
538              if ((it->item->group_item) &&
539                  (sd->pan_y > (it->y + it->item->block->y)))
540                gith = it->item->group_item->item->h;
541              dy -= gith;
542              dh = it->item->h;
543           }
544         break;
545      }
546    if (sd->bring_in)
547      sd->s_iface->region_bring_in(ELM_WIDGET_DATA(sd)->obj, dx, dy, dw, dh);
548    else
549      sd->s_iface->content_region_show
550        (ELM_WIDGET_DATA(sd)->obj, dx, dy, dw, dh);
551
552    it->item->show_me = EINA_FALSE;
553    sd->show_item = NULL;
554    sd->auto_scroll_enabled = EINA_FALSE;
555    sd->check_scroll = EINA_FALSE;
556 }
557
558 static void
559 _item_unrealize(Elm_Gen_Item *it,
560                 Eina_Bool calc)
561 {
562    Evas_Object *content;
563    Eina_List *l;
564    const char *part;
565
566    if (!it->realized) return;
567    if (GL_IT(it)->wsd->reorder_it == it) return;
568
569 #if GENLIST_FX_SUPPORT
570    if ((GL_IT(it)->has_proxy_it) && (!GL_IT(it)->wsd->genlist_clearing))
571      {
572         if (!eina_list_data_find(GL_IT(it)->wsd->pending_unrealized_items, it))
573           GL_IT(it)->wsd->pending_unrealized_items =
574              eina_list_append(GL_IT(it)->wsd->pending_unrealized_items, it);
575         return;
576      }
577 #endif
578 #if GENLIST_ENTRY_SUPPORT
579    if (it->item->unrealize_disabled)
580      {
581         evas_object_hide(VIEW(it));
582         return;
583      }
584 #endif
585
586    //evas_event_freeze(evas_object_evas_get(WIDGET(it)));
587    if (!calc)
588      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
589    if (it->long_timer)
590      {
591         ecore_timer_del(it->long_timer);
592         it->long_timer = NULL;
593      }
594    if (it->item->swipe_timer)
595      {
596         ecore_timer_del(it->item->swipe_timer);
597         it->item->swipe_timer = NULL;
598      }
599
600    // Free view item
601    EINA_LIST_FOREACH(it->texts, l, part)
602      edje_object_part_text_set(VIEW(it), part, NULL);
603
604    elm_widget_stringlist_free(it->texts);
605    it->texts = NULL;
606    elm_widget_stringlist_free(it->contents);
607    it->contents = NULL;
608    elm_widget_stringlist_free(it->states);
609    it->states = NULL;
610    EINA_LIST_FREE(it->content_objs, content)
611      {
612         // FIXME: If parent-child relationship was broken before 'ic'
613         // is deleted, freeze_pop will not be called. ex) elm_slider
614         // If layout is used instead of edje, this problme can be
615         // solved.
616         if (0 != elm_widget_scroll_freeze_get(content))
617           elm_widget_scroll_freeze_pop(content);
618         evas_object_del(content);
619      }
620
621    // Free flip item
622    elm_widget_stringlist_free(it->item->flip_contents);
623    it->item->flip_contents = NULL;
624    EINA_LIST_FREE(it->item->flip_content_objs, content)
625      evas_object_del(content);
626
627    /* access */
628    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
629      _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
630
631    // unswallow VIEW(it) first then manipulate VIEW(it)
632    _decorate_item_unrealize(it);
633    _decorate_all_item_unrealize(it);
634
635    it->realized = EINA_FALSE;
636    _item_cache_push(it);
637
638 #if GENLIST_ENTRY_SUPPORT
639    it->item->unrealize_disabled = EINA_FALSE;
640 #endif
641    it->want_unrealize = EINA_FALSE;
642
643    //evas_event_thaw(evas_object_evas_get(WIDGET(it)));
644    //evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
645 }
646
647 static void
648 _item_block_unrealize(Item_Block *itb)
649 {
650    Elm_Gen_Item *it;
651    const Eina_List *l;
652    Eina_Bool dragging = EINA_FALSE;
653
654    if (!itb->realized) return;
655    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj));
656
657    EINA_LIST_FOREACH(itb->items, l, it)
658      {
659         if (itb->must_recalc || !it->group)
660           {
661              if (it->dragging)
662                {
663                   dragging = EINA_TRUE;
664                   it->want_unrealize = EINA_TRUE;
665                }
666              else
667                _item_unrealize(it, EINA_FALSE);
668           }
669      }
670    if (!dragging)
671      {
672         itb->realized = EINA_FALSE;
673         itb->want_unrealize = EINA_TRUE;
674      }
675    else
676      itb->want_unrealize = EINA_FALSE;
677    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj));
678    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj));
679 }
680
681 static Eina_Bool
682 _must_recalc_idler(void *data)
683 {
684    Elm_Genlist_Smart_Data *sd = data;
685
686    if (sd->calc_job) ecore_job_del(sd->calc_job);
687    sd->calc_job = ecore_job_add(_calc_job, sd);
688    sd->must_recalc_idler = NULL;
689    return ECORE_CALLBACK_CANCEL;
690 }
691
692 static void
693 _calc_job(void *data)
694 {
695    int in = 0;
696    Item_Block *itb, *chb = NULL;
697    Evas_Coord pan_w = 0, pan_h = 0;
698    Elm_Genlist_Smart_Data *sd = data;
699    Eina_Bool minw_change = EINA_FALSE;
700    Eina_Bool did_must_recalc = EINA_FALSE;
701    Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw = 0;
702
703    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &sd->h);
704    if (sd->mode == ELM_LIST_COMPRESS)
705      sd->s_iface->content_viewport_size_get(ELM_WIDGET_DATA(sd)->obj, &vw, NULL);
706
707    if (sd->w != ow) sd->w = ow;
708
709    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
710    EINA_INLIST_FOREACH(sd->blocks, itb)
711      {
712         Eina_Bool show_me = EINA_FALSE;
713
714         itb->num = in;
715         show_me = itb->show_me;
716         itb->show_me = EINA_FALSE;
717         if (chb)
718           {
719              if (itb->realized) _item_block_unrealize(itb);
720           }
721         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
722           {
723              if (itb->must_recalc)
724                {
725                   Eina_List *l;
726                   Elm_Gen_Item *it;
727
728                   EINA_LIST_FOREACH(itb->items, l, it)
729                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
730                   itb->changed = EINA_TRUE;
731                   did_must_recalc = EINA_TRUE;
732                   if (itb->realized) _item_block_unrealize(itb);
733                   itb->must_recalc = EINA_FALSE;
734                }
735              show_me = _item_block_recalc(itb, in, EINA_FALSE);
736              chb = itb;
737           }
738         itb->y = y;
739         itb->x = 0;
740         minh += itb->minh;
741         if (minw == -1) minw = itb->minw;
742         else if ((!itb->must_recalc) && (minw < itb->minw))
743           {
744              minw = itb->minw;
745              minw_change = EINA_TRUE;
746           }
747         if ((sd->mode == ELM_LIST_COMPRESS) && (minw > vw))
748           {
749              minw = vw;
750              minw_change = EINA_TRUE;
751           }
752         itb->w = minw;
753         itb->h = itb->minh;
754         y += itb->h;
755         in += itb->count;
756         if ((show_me) && (sd->show_item) && (!sd->show_item->item->queued))
757           sd->check_scroll = EINA_TRUE;
758      }
759    if (minw_change)
760      {
761         EINA_INLIST_FOREACH(sd->blocks, itb)
762           {
763              itb->minw = minw;
764              itb->w = itb->minw;
765           }
766      }
767    if ((chb) && (EINA_INLIST_GET(chb)->next))
768      {
769         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
770           {
771              if (itb->realized) _item_block_unrealize(itb);
772           }
773      }
774    sd->realminw = minw;
775    if (minw < sd->w) minw = sd->w;
776    if ((minw != sd->minw) || (minh != sd->minh))
777      {
778         sd->minw = minw;
779         sd->minh = minh;
780         evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
781         elm_layout_sizing_eval(ELM_WIDGET_DATA(sd)->obj);
782         if (sd->reorder_it)
783           {
784               Elm_Gen_Item *it;
785               it = sd->reorder_it;
786               it->item->w = minw;
787           }
788         if ((sd->anchor_item) && (sd->anchor_item->item->block)
789             && (!sd->auto_scroll_enabled))
790           {
791              Elm_Gen_Item *it;
792              Evas_Coord it_y;
793
794              it = sd->anchor_item;
795              it_y = sd->anchor_y;
796              sd->s_iface->content_pos_set
797                (ELM_WIDGET_DATA(sd)->obj, sd->pan_x, it->item->block->y
798                + it->y + it_y, EINA_TRUE);
799              sd->anchor_item = it;
800              sd->anchor_y = it_y;
801           }
802      }
803    if (did_must_recalc)
804      {
805         if (!sd->must_recalc_idler)
806           sd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, sd);
807      }
808    if (sd->check_scroll)
809      {
810         _elm_genlist_pan_smart_content_size_get(sd->pan_obj, &pan_w, &pan_h);
811         if (EINA_INLIST_GET(sd->show_item) == sd->items->last)
812           sd->scroll_to_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
813
814         switch (sd->scroll_to_type)
815           {
816            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
817              dy = sd->h;
818              break;
819
820            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
821              dy = sd->h / 2;
822              break;
823
824            case ELM_GENLIST_ITEM_SCROLLTO_IN:
825            default:
826              dy = 0;
827              break;
828           }
829         if ((sd->show_item) && (sd->show_item->item->block))
830           {
831              if ((pan_w > (sd->show_item->x + sd->show_item->item->block->x))
832                  && (pan_h > (sd->show_item->y + sd->show_item->item->block->y
833                               + dy)))
834                {
835                   _item_scroll(sd);
836                }
837           }
838      }
839
840    sd->calc_job = NULL;
841    evas_object_smart_changed(sd->pan_obj);
842    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
843    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
844 }
845
846 static void
847 _elm_genlist_smart_sizing_eval(Evas_Object *obj)
848 {
849    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
850    Evas_Coord vmw = 0, vmh = 0;
851
852    ELM_GENLIST_DATA_GET(obj, sd);
853
854    /* parent class' early call */
855    if (!sd->s_iface) return;
856
857    if (sd->on_sub_del) return;;
858
859    evas_object_size_hint_min_get(obj, &minw, NULL);
860    evas_object_size_hint_max_get(obj, &maxw, &maxh);
861
862    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &vmw, &vmh);
863
864    if (sd->mode == ELM_LIST_COMPRESS)
865      {
866         Evas_Coord vw, vh;
867
868         sd->s_iface->content_viewport_size_get(obj, &vw, &vh);
869         if ((vw != 0) && (vw != sd->prev_viewport_w))
870           {
871              Item_Block *itb;
872
873              sd->prev_viewport_w = vw;
874
875              EINA_INLIST_FOREACH(sd->blocks, itb)
876                {
877                   itb->must_recalc = EINA_TRUE;
878                }
879              if (sd->calc_job) ecore_job_del(sd->calc_job);
880              sd->calc_job = ecore_job_add(_calc_job, sd);
881           }
882         minw = vmw;
883         minh = vmh;
884      }
885    else if (sd->mode == ELM_LIST_LIMIT)
886      {
887         maxw = -1;
888         minw = vmw + sd->realminw;
889      }
890    else
891      {
892         minw = vmw;
893         minh = vmh;
894      }
895
896    evas_object_size_hint_min_set(obj, minw, minh);
897    evas_object_size_hint_max_set(obj, maxw, maxh);
898 }
899
900 static void
901 _item_position(Elm_Gen_Item *it,
902                Evas_Object *view,
903                Evas_Coord it_x,
904                Evas_Coord it_y)
905 {
906    if (!it) return;
907    if (!view) return;
908
909    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj));
910    evas_object_resize(view, it->item->w, it->item->h);
911    evas_object_move(view, it_x, it_y);
912    evas_object_show(view);
913    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj));
914    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj));
915 }
916
917 static void
918 _item_subitems_clear(Elm_Gen_Item *it)
919 {
920    Eina_List *l, *ll;
921    Elm_Object_Item *it2;
922
923    EINA_LIST_FOREACH_SAFE(it->item->items, l, ll, it2)
924      elm_widget_item_del(it2);
925 }
926
927 static void
928 _item_auto_scroll(Elm_Genlist_Smart_Data *sd)
929 {
930    Elm_Gen_Item *tmp_item = NULL;
931
932 #if GENLIST_FX_SUPPORT
933    if (sd->fx_first_captured) return;
934 #endif
935    if ((sd->expanded_item) && (sd->auto_scroll_enabled))
936      {
937         tmp_item = eina_list_data_get
938             (eina_list_last(sd->expanded_item->item->items));
939         if (!tmp_item) return;
940         sd->show_item = tmp_item;
941         sd->bring_in = EINA_TRUE;
942         sd->scroll_to_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
943         if ((sd->show_item->item->queued) || (!sd->show_item->item->mincalcd))
944           {
945              sd->show_item->item->show_me = EINA_TRUE;
946              sd->auto_scroll_enabled = EINA_FALSE;
947           }
948         else
949           _item_scroll(sd);
950      }
951 }
952
953 static void
954 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
955 {
956    if (!it->item->nostacking)
957      {
958         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
959           {
960              if (it->deco_all_view) evas_object_lower(it->deco_all_view);
961              else evas_object_lower(VIEW(it));
962           }
963         else
964           {
965              if (it->deco_all_view) evas_object_raise(it->deco_all_view);
966              else evas_object_raise(VIEW(it));
967           }
968      }
969
970    if (it->item->order_num_in & 0x1)
971      {
972         edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
973         if (it->deco_all_view)
974           edje_object_signal_emit(it->deco_all_view, "elm,state,odd", "elm");
975      }
976    else
977      {
978         edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
979         if (it->deco_all_view)
980           edje_object_signal_emit(it->deco_all_view, "elm,state,even", "elm");
981      }
982 }
983
984 static void
985 _item_order_update(const Eina_Inlist *l,
986                    int start)
987 {
988    Elm_Gen_Item *it, *it2;
989
990    for (it = ELM_GEN_ITEM_FROM_INLIST(l); l; l = l->next,
991         it = ELM_GEN_ITEM_FROM_INLIST(l))
992      {
993         it->item->order_num_in = start++;
994         _elm_genlist_item_odd_even_update(it);
995         it2 = ELM_GEN_ITEM_FROM_INLIST(l->next);
996         if (it2 && (it->item->order_num_in != it2->item->order_num_in))
997           return;
998      }
999 }
1000
1001 static void
1002 _elm_genlist_item_state_update(Elm_Gen_Item *it,
1003                                Item_Cache *itc)
1004 {
1005    if (itc)
1006      {
1007         if (it->selected != itc->selected)
1008           {
1009              if (it->selected)
1010                {
1011                   if (it->deco_all_view)
1012                     edje_object_signal_emit
1013                       (it->deco_all_view, "elm,state,selected", "elm,nosound");
1014                   edje_object_signal_emit
1015                     (VIEW(it), "elm,state,selected", "elm,nosound");
1016                   evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
1017                }
1018           }
1019         if (elm_widget_item_disabled_get(it) != itc->disabled)
1020           {
1021              if (elm_widget_item_disabled_get(it))
1022                edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
1023              if (it->deco_all_view)
1024                edje_object_signal_emit
1025                  (it->deco_all_view, "elm,state,disabled", "elm");
1026           }
1027         if (it->item->expanded != itc->expanded)
1028           {
1029              if (it->item->expanded)
1030                edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
1031              if (it->deco_all_view)
1032                edje_object_signal_emit
1033                  (it->deco_all_view, "elm,state,expanded", "elm");
1034           }
1035      }
1036    else
1037      {
1038         if (it->selected)
1039           {
1040              if (it->deco_all_view)
1041                edje_object_signal_emit
1042                  (it->deco_all_view, "elm,state,selected", "elm,nosound");
1043              edje_object_signal_emit
1044                (VIEW(it), "elm,state,selected", "elm,nosound");
1045              evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
1046           }
1047         if (elm_widget_item_disabled_get(it))
1048           {
1049              edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
1050              if (it->deco_all_view)
1051                edje_object_signal_emit
1052                  (it->deco_all_view, "elm,state,disabled", "elm");
1053           }
1054         if (it->item->expanded)
1055           {
1056              edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
1057              if (it->deco_all_view)
1058                edje_object_signal_emit
1059                  (it->deco_all_view, "elm,state,expanded", "elm");
1060           }
1061      }
1062 }
1063
1064 static void
1065 _elm_genlist_item_index_update(Elm_Gen_Item *it)
1066 {
1067    if (it->position_update || it->item->block->position_update)
1068      {
1069         evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
1070         it->position_update = EINA_FALSE;
1071      }
1072 }
1073
1074 static void
1075 _item_text_realize(Elm_Gen_Item *it,
1076                    Evas_Object *target,
1077                    Eina_List **source,
1078                    const char *parts)
1079 {
1080    if (it->itc->func.text_get)
1081      {
1082         const Eina_List *l;
1083         const char *key;
1084
1085         if (!(*source))
1086           *source = elm_widget_stringlist_get
1087               (edje_object_data_get(target, "texts"));
1088         EINA_LIST_FOREACH(*source, l, key)
1089           {
1090              if (parts && fnmatch(parts, key, FNM_PERIOD))
1091                continue;
1092
1093              char *s = it->itc->func.text_get
1094                  ((void *)it->base.data, WIDGET(it), key);
1095
1096              if (s)
1097                {
1098                   edje_object_part_text_escaped_set(target, key, s);
1099                   free(s);
1100                }
1101              else
1102                {
1103                   edje_object_part_text_set(target, key, "");
1104                }
1105           }
1106      }
1107 }
1108
1109 #if 0
1110 // FIXME: difference from upstream
1111 static void
1112 _content_focused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1113 {
1114    Elm_Gen_Item *it = data;
1115    if (it) it->defer_unrealize = EINA_TRUE;
1116 }
1117
1118 static void
1119 _content_unfocused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1120 {
1121    Elm_Gen_Item *it = data;
1122    if (it) it->defer_unrealize = EINA_FALSE;
1123 }
1124 #endif
1125
1126 static Eina_List *
1127 _item_mode_content_realize(Elm_Gen_Item *it,
1128                            Evas_Object *target,
1129                            Eina_List **source,
1130                            const char *parts,
1131                            Eina_List **contents_list)
1132 {
1133    Eina_List *res = *contents_list;
1134
1135    if (it->itc->func.content_get)
1136      {
1137         const Eina_List *l;
1138         const char *key;
1139         Evas_Object *ic;
1140
1141         EINA_LIST_FOREACH(*source, l, key)
1142           {
1143              if (parts && fnmatch(parts, key, FNM_PERIOD))
1144                continue;
1145
1146              ic = it->itc->func.content_get
1147                  ((void *)it->base.data, WIDGET(it), key);
1148
1149              if (ic)
1150                {
1151                   res = eina_list_append(res, ic);
1152                   edje_object_part_swallow(target, key, ic);
1153                   evas_object_show(ic);
1154 #if GENLIST_ENTRY_SUPPORT
1155                   if (it->flipped)
1156                     {
1157                        // For entry or editfield
1158                        // 1. Add resize callback for multiline entry.
1159                        // 2. Do not unrealize it for focus issue
1160                        // ps. Only for entry because of performnace
1161                        if (!strcmp("elm_layout", evas_object_type_get(ic)))
1162                          {
1163                             // If editfield style, it can have entry.
1164                             const char *group;
1165                             edje_object_file_get(elm_layout_edje_get(ic), NULL, &group);
1166                             if (group && !strncmp("elm/layout/editfield/", group, 20))
1167                               it->item->unrealize_disabled = EINA_TRUE;
1168                          }
1169                        else if (!strcmp("elm_entry", evas_object_type_get(ic)))
1170                           it->item->unrealize_disabled = EINA_TRUE;
1171                     }
1172 #endif
1173 #if 0
1174                   // FIXME: difference from upstream
1175                   if (it->flipped)
1176                     {
1177                        // FIXME: if entry calcuates its cursor position correctly and conformant works,
1178                        //        genlist does not need to handle this focus thing.
1179                        evas_object_smart_callback_add(ic, "focused", _content_focused, it);
1180                        evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
1181                     }
1182 #endif
1183                   if (elm_widget_item_disabled_get(it))
1184                     elm_widget_disabled_set(ic, EINA_TRUE);
1185                }
1186           }
1187      }
1188
1189    return res;
1190 }
1191
1192 static void
1193 _item_state_realize(Elm_Gen_Item *it,
1194                     Evas_Object *target,
1195                     Eina_List **source,
1196                     const char *parts)
1197 {
1198    if (it->itc->func.state_get)
1199      {
1200         const Eina_List *l;
1201         const char *key;
1202         char buf[4096];
1203
1204         if (!(*source))
1205           *source = elm_widget_stringlist_get
1206               (edje_object_data_get(target, "states"));
1207         EINA_LIST_FOREACH(*source, l, key)
1208           {
1209              if (parts && fnmatch(parts, key, FNM_PERIOD))
1210                continue;
1211
1212              Eina_Bool on = it->itc->func.state_get
1213                  ((void *)it->base.data, WIDGET(it), key);
1214
1215              if (on)
1216                {
1217                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1218                   edje_object_signal_emit(target, buf, "elm");
1219                }
1220              else
1221                {
1222                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
1223                   edje_object_signal_emit(target, buf, "elm");
1224                }
1225           }
1226      }
1227 }
1228
1229 static void
1230 _decorate_item_unrealize(Elm_Gen_Item *it)
1231 {
1232    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
1233    Evas_Object *content;
1234
1235    if (!it->item->deco_it_view) return;
1236
1237    //evas_event_freeze(evas_object_evas_get(obj));
1238    elm_widget_stringlist_free(it->item->deco_it_texts);
1239    it->item->deco_it_texts = NULL;
1240    elm_widget_stringlist_free(it->item->deco_it_contents);
1241    it->item->deco_it_contents = NULL;
1242    elm_widget_stringlist_free(it->item->deco_it_states);
1243
1244    EINA_LIST_FREE (it->item->deco_it_content_objs, content)
1245      evas_object_del(content);
1246
1247    edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
1248    evas_object_smart_member_add(VIEW(it), sd->pan_obj);
1249    evas_object_del(it->item->deco_it_view);
1250    it->item->deco_it_view = NULL;
1251
1252    if (sd->mode_item == it) sd->mode_item = NULL;
1253    //evas_event_thaw(evas_object_evas_get(obj));
1254    //evas_event_thaw_eval(evas_object_evas_get(obj));
1255 }
1256
1257
1258 static void
1259 _decorate_all_item_position(Elm_Gen_Item *it,
1260                             int itx,
1261                             int ity)
1262 {
1263    evas_object_resize(it->deco_all_view, it->item->w, it->item->h);
1264    evas_object_move(it->deco_all_view, itx, ity);
1265 }
1266
1267 static void
1268 _decorate_all_item_realize(Elm_Gen_Item *it,
1269                            Eina_Bool effect_on)
1270 {
1271    char buf[1024];
1272    const char *stacking;
1273    const char *stacking_even;
1274
1275    if ((!it) || (it->item->decorate_all_item_realized)) return;
1276
1277    if (it->item->deco_it_view) _decorate_item_unrealize(it);
1278
1279    it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
1280    edje_object_scale_set(it->deco_all_view, elm_widget_scale_get(WIDGET(it)) *
1281                          elm_config_scale_get());
1282    evas_object_smart_member_add(it->deco_all_view, GL_IT(it)->wsd->pan_obj);
1283    elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
1284
1285    if (it->item->type & ELM_GENLIST_ITEM_TREE)
1286      strncpy(buf, "tree", sizeof(buf));
1287    else strncpy(buf, "item", sizeof(buf));
1288    if (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)
1289      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
1290
1291    strncat(buf, "/", sizeof(buf) - strlen(buf));
1292    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
1293
1294    elm_widget_theme_object_set(WIDGET(it), it->deco_all_view, "genlist", buf,
1295                                elm_widget_style_get(WIDGET(it)));
1296
1297    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1298    if (!stacking_even) stacking_even = "above";
1299    it->item->stacking_even = !!strcmp("above", stacking_even);
1300
1301    stacking = edje_object_data_get(VIEW(it), "stacking");
1302    if (!stacking) stacking = "yes";
1303    it->item->nostacking = !!strcmp("yes", stacking);
1304
1305    edje_object_mirrored_set
1306      (it->deco_all_view, elm_widget_mirrored_get(WIDGET(it)));
1307
1308    _elm_genlist_item_odd_even_update(it);
1309    _elm_genlist_item_state_update(it, NULL);
1310
1311 #if 1 // FIXME: difference from upstream
1312    if (GL_IT(it)->wsd->reorder_mode)
1313      {
1314         edje_object_signal_emit
1315           (VIEW(it), "elm,state,reorder,mode_unset", "elm");
1316         edje_object_signal_emit
1317           (it->deco_all_view, "elm,state,reorder,mode_set", "elm");
1318      }
1319 #endif
1320    if (effect_on)
1321      {
1322         edje_object_signal_emit
1323            (it->deco_all_view, "elm,state,decorate,enabled,effect", "elm");
1324         edje_object_signal_emit
1325            (VIEW(it), "elm,state,decorate,enabled,effect", "elm");
1326      }
1327    else
1328      {
1329         edje_object_signal_emit
1330            (it->deco_all_view, "elm,state,decorate,enabled", "elm");
1331         edje_object_signal_emit
1332            (VIEW(it), "elm,state,decorate,enabled", "elm");
1333      }
1334    _item_mouse_callbacks_del(it, VIEW(it));
1335    _item_mouse_callbacks_add(it, it->deco_all_view);
1336
1337    _item_text_realize(it, it->deco_all_view, &it->item->deco_all_texts, NULL);
1338    if (it->flipped)
1339      edje_object_signal_emit
1340        (it->deco_all_view, "elm,state,flip,enabled", "elm");
1341    if (!it->item->deco_all_contents)
1342      it->item->deco_all_contents = elm_widget_stringlist_get
1343          (edje_object_data_get(it->deco_all_view, "contents"));
1344    it->item->deco_all_content_objs =
1345      _item_mode_content_realize(it, it->deco_all_view,
1346                                 &it->item->deco_all_contents, NULL,
1347                                 &it->item->deco_all_content_objs);
1348    _item_state_realize
1349      (it, it->deco_all_view, &it->item->deco_all_states, NULL);
1350    edje_object_part_swallow
1351      (it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
1352
1353    _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
1354    evas_object_show(it->deco_all_view);
1355
1356    if (it->selected)
1357      {
1358         edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
1359         evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
1360      }
1361
1362    it->item->decorate_all_item_realized = EINA_TRUE;
1363    it->want_unrealize = EINA_FALSE;
1364 }
1365
1366 static void
1367 _expand_toggle_signal_cb(void *data,
1368                          Evas_Object *obj __UNUSED__,
1369                          const char *emission __UNUSED__,
1370                          const char *source __UNUSED__)
1371 {
1372    Elm_Gen_Item *it = data;
1373
1374    if (it->item->expanded)
1375      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1376    else
1377      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1378 }
1379
1380 static void
1381 _expand_signal_cb(void *data,
1382                   Evas_Object *obj __UNUSED__,
1383                   const char *emission __UNUSED__,
1384                   const char *source __UNUSED__)
1385 {
1386    Elm_Gen_Item *it = data;
1387
1388    if (!it->item->expanded)
1389      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1390 }
1391
1392 static void
1393 _contract_signal_cb(void *data,
1394                     Evas_Object *obj __UNUSED__,
1395                     const char *emission __UNUSED__,
1396                     const char *source __UNUSED__)
1397 {
1398    Elm_Gen_Item *it = data;
1399
1400    if (it->item->expanded)
1401      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1402 }
1403
1404 #if GENLIST_ENTRY_SUPPORT
1405 static void
1406 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1407 {
1408    Elm_Gen_Item *it = data;
1409    if (!it) return;
1410    if (it->want_unrealize) return;
1411    it->item->mincalcd = EINA_FALSE;
1412    it->item->block->changeme = EINA_TRUE;
1413    GL_IT(it)->wsd->size_changed = EINA_TRUE;
1414    evas_object_smart_changed(GL_IT(it)->wsd->pan_obj);
1415 }
1416 #endif
1417
1418 static Eina_List *
1419 _item_content_realize(Elm_Gen_Item *it,
1420                       Evas_Object *target,
1421                       Eina_List **source,
1422                       const char *parts)
1423 {
1424    Eina_List *res = it->content_objs;
1425
1426    if (it->itc->func.content_get)
1427      {
1428         const Eina_List *l;
1429         const char *key;
1430         Evas_Object *ic = NULL;
1431
1432         if (!(*source))
1433           *source = elm_widget_stringlist_get
1434               (edje_object_data_get(target, "contents"));
1435
1436         EINA_LIST_FOREACH(*source, l, key)
1437           {
1438              if (parts && fnmatch(parts, key, FNM_PERIOD))
1439                continue;
1440
1441              if (it->itc->func.content_get)
1442                ic = it->itc->func.content_get
1443                    ((void *)it->base.data, WIDGET(it), key);
1444              if (ic)
1445                {
1446                   res = eina_list_append(res, ic);
1447                   edje_object_part_swallow(target, key, ic);
1448                   evas_object_show(ic);
1449
1450 #if GENLIST_ENTRY_SUPPORT
1451                   // For entry or editfield
1452                   // 1. Add resize callback for multiline entry.
1453                   // 2. Do not unrealize it for focus issue
1454                   // ps. Only for entry because of performnace
1455                   if (!strcmp("elm_layout", evas_object_type_get(ic)))
1456                     {
1457                        // If editfield style, it can have entry.
1458                        const char *group;
1459                        edje_object_file_get(elm_layout_edje_get(ic), NULL, &group);
1460                        if (group && !strncmp("elm/layout/editfield/", group, 20))
1461                          {
1462                             evas_object_event_callback_add
1463                                (ic, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1464                                 _changed_size_hints, it);
1465                             it->item->unrealize_disabled = EINA_TRUE;
1466                          }
1467
1468                     }
1469                   else if (!strcmp("elm_entry", evas_object_type_get(ic)))
1470                     {
1471                        evas_object_event_callback_add
1472                           (ic, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1473                            _changed_size_hints, it);
1474                        it->item->unrealize_disabled = EINA_TRUE;
1475                     }
1476 #endif
1477 #if 0 // FIXME: difference from upstream
1478                   if (it->flipped)
1479                     {
1480                        // FIXME: if entry calcuates its cursor position correctly and conformant works,
1481                        //        genlist does not need to handle this focus thing.
1482                        evas_object_smart_callback_add(ic, "focused", _content_focused, it);
1483                        evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
1484                     }
1485 #endif
1486                   if (elm_widget_item_disabled_get(it))
1487                     elm_widget_disabled_set(ic, EINA_TRUE);
1488                }
1489           }
1490      }
1491
1492    return res;
1493 }
1494
1495 static char *
1496 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
1497 {
1498    char *ret;
1499    Eina_Strbuf *buf;
1500
1501    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1502    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
1503
1504    buf = eina_strbuf_new();
1505
1506    if (it->itc->func.text_get)
1507      {
1508         const Eina_List *l;
1509         const char *key;
1510
1511         if (!(it->texts)) it->texts =
1512           elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
1513
1514         EINA_LIST_FOREACH(it->texts, l, key)
1515           {
1516              char *s = it->itc->func.text_get
1517                 ((void *)it->base.data, WIDGET(it), key);
1518
1519              s = _elm_util_mkup_to_text(s);
1520
1521              if (s)
1522                {
1523                   if (eina_strbuf_length_get(buf) > 0) eina_strbuf_append(buf, ", ");
1524                   eina_strbuf_append(buf, s);
1525                   free(s);
1526                }
1527           }
1528      }
1529
1530    ret = eina_strbuf_string_steal(buf);
1531    eina_strbuf_free(buf);
1532    return ret;
1533 }
1534
1535 static char *
1536 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
1537 {
1538    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1539    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
1540
1541    if (it->base.disabled)
1542      return strdup(E_("State: Disabled"));
1543
1544    return NULL;
1545 }
1546
1547 static void
1548 _access_on_highlight_cb(void *data)
1549 {
1550    Evas_Coord x, y, w, h;
1551    Evas_Coord sx, sy, sw, sh;
1552    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1553    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
1554
1555    ELM_GENLIST_DATA_GET(it->base.widget, sd);
1556
1557    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
1558    // XXX There would be a reason.
1559    if ((w == 0) && (h == 0)) return;
1560
1561    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->obj, &sx, &sy, &sw, &sh);
1562    if ((x < sx) || (y < sy) || ((x + w) > (sx + sw)) || ((y + h) > (sy + sh)))
1563      elm_genlist_item_bring_in((Elm_Object_Item *)it,
1564                                ELM_GENLIST_ITEM_SCROLLTO_IN);
1565 }
1566
1567 static void
1568 _access_widget_item_register(Elm_Gen_Item *it)
1569 {
1570    Elm_Access_Info *ai;
1571
1572    _elm_access_widget_item_register((Elm_Widget_Item *)it);
1573
1574    ai = _elm_access_object_get(it->base.access_obj);
1575
1576    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
1577    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
1578    _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, it);
1579    _elm_access_activate_callback_set(ai, _access_activate_cb, it);
1580 }
1581
1582 static void
1583 _item_realize(Elm_Gen_Item *it,
1584               int in,
1585               Eina_Bool calc)
1586 {
1587    Item_Cache *itc = NULL;
1588    const char *treesize;
1589    char buf[1024];
1590    int tsize = 20;
1591
1592    if (it->realized)
1593      {
1594         if (it->item->order_num_in != in)
1595           {
1596              _item_order_update(EINA_INLIST_GET(it), in);
1597              _elm_genlist_item_state_update(it, NULL);
1598              _elm_genlist_item_index_update(it);
1599           }
1600         return;
1601      }
1602    it->item->order_num_in = in;
1603
1604    if (it->item->nocache_once | it->item->nocache ||
1605        it->item->type == ELM_GENLIST_ITEM_TREE || it->parent ||
1606        !_item_cache_pop(it))
1607      {
1608         const char *stacking_even;
1609         const char *stacking;
1610
1611         it->item->nocache_once = EINA_FALSE;
1612
1613         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
1614         edje_object_scale_set(VIEW(it),
1615                               elm_widget_scale_get(WIDGET(it)) *
1616                               elm_config_scale_get());
1617         evas_object_smart_member_add(VIEW(it), GL_IT(it)->wsd->pan_obj);
1618         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
1619
1620         if (it->item->type & ELM_GENLIST_ITEM_TREE)
1621           snprintf(buf, sizeof(buf), "tree%s/%s",
1622                    GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS ? "_compress" :
1623                    "", it->itc->item_style ? : "default");
1624         else
1625           snprintf(buf, sizeof(buf), "item%s/%s",
1626                    GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS ? "_compress" :
1627                    "", it->itc->item_style ? : "default");
1628
1629         elm_widget_theme_object_set
1630           (WIDGET(it), VIEW(it), "genlist", buf,
1631           elm_widget_style_get(WIDGET(it)));
1632
1633         if (it->item->expanded_depth > 0)
1634           edje_object_signal_emit(VIEW(it), "bg_color_change", "elm");
1635
1636         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1637         if (!stacking_even) stacking_even = "above";
1638         it->item->stacking_even = !!strcmp("above", stacking_even);
1639
1640         stacking = edje_object_data_get(VIEW(it), "stacking");
1641         if (!stacking) stacking = "yes";
1642         it->item->nostacking = !!strcmp("yes", stacking);
1643
1644         edje_object_mirrored_set
1645           (VIEW(it), elm_widget_mirrored_get(WIDGET(it)));
1646
1647         edje_object_signal_callback_add
1648           (VIEW(it), "elm,action,expand,toggle", "elm",
1649           _expand_toggle_signal_cb, it);
1650         edje_object_signal_callback_add
1651           (VIEW(it), "elm,action,expand", "elm", _expand_signal_cb, it);
1652         edje_object_signal_callback_add
1653           (VIEW(it), "elm,action,contract", "elm", _contract_signal_cb, it);
1654         _item_mouse_callbacks_add(it, VIEW(it));
1655      }
1656
1657    /* access */
1658    if (_elm_config->access_mode) _access_widget_item_register(it);
1659
1660    _item_order_update(EINA_INLIST_GET(it), in);
1661 #if 1 // FIXME: difference from upstream
1662    if (!(it->deco_all_view) && (it->item->type != ELM_GENLIST_ITEM_GROUP))
1663      {
1664         if (GL_IT(it)->wsd->reorder_mode)
1665           edje_object_signal_emit
1666             (VIEW(it), "elm,state,reorder,mode_set", "elm");
1667         else
1668           edje_object_signal_emit
1669             (VIEW(it), "elm,state,reorder,mode_unset", "elm");
1670     }
1671 #endif
1672    treesize = edje_object_data_get(VIEW(it), "treesize");
1673    if (treesize) tsize = atoi(treesize);
1674    if (it->parent && GL_IT(it->parent)->type == ELM_GENLIST_ITEM_TREE &&
1675        !it->spacer && treesize)
1676      {
1677         it->spacer =
1678           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1679         evas_object_color_set(it->spacer, 0, 0, 0, 0);
1680      }
1681    if (it->spacer)
1682      {
1683         evas_object_size_hint_min_set
1684           (it->spacer, (it->item->expanded_depth * tsize) *
1685           elm_config_scale_get(), 1);
1686         edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1687      }
1688    if (!calc)
1689      {
1690         if ((GL_IT(it)->wsd->decorate_all_mode) && (!it->deco_all_view) &&
1691             (it->item->type != ELM_GENLIST_ITEM_GROUP) &&
1692             (it->itc->decorate_all_item_style))
1693           _decorate_all_item_realize(it, EINA_FALSE);
1694
1695         _elm_genlist_item_state_update(it, itc);
1696         _elm_genlist_item_index_update(it);
1697      }
1698
1699    /* homogenous genlist shortcut */
1700    if ((calc) && (GL_IT(it)->wsd->homogeneous) && (!it->item->mincalcd) &&
1701        ((it->group && GL_IT(it)->wsd->group_item_width) ||
1702         (!it->group && GL_IT(it)->wsd->item_width)))
1703      {
1704         if (it->group)
1705           {
1706              it->item->w = it->item->minw = GL_IT(it)->wsd->group_item_width;
1707              it->item->h = it->item->minh = GL_IT(it)->wsd->group_item_height;
1708           }
1709         else
1710           {
1711              it->item->w = it->item->minw = GL_IT(it)->wsd->item_width;
1712              it->item->h = it->item->minh = GL_IT(it)->wsd->item_height;
1713           }
1714         it->item->mincalcd = EINA_TRUE;
1715      }
1716    else
1717      {
1718         if (eina_list_count(it->content_objs) != 0)
1719           ERR_ABORT("If you see this error, please notify us and we"
1720                     "will fix it");
1721
1722         _item_text_realize(it, VIEW(it), &it->texts, NULL);
1723         it->content_objs =
1724           _item_content_realize(it, VIEW(it), &it->contents, NULL);
1725         _item_state_realize(it, VIEW(it), &it->states, NULL);
1726         if (it->flipped)
1727           {
1728              edje_object_signal_emit
1729                (VIEW(it), "elm,state,flip,enabled", "elm");
1730              // This is needed before contents are swallowed
1731              edje_object_message_signal_process(VIEW(it));
1732
1733              if (!(it->item->flip_contents))
1734                it->item->flip_contents = elm_widget_stringlist_get
1735                    (edje_object_data_get(VIEW(it), "flips"));
1736              it->item->flip_content_objs = _item_mode_content_realize
1737                  (it, VIEW(it), &it->item->flip_contents, NULL,
1738                  &it->item->flip_content_objs);
1739           }
1740
1741         /* access: unregister item which have no text and content */
1742         if (_elm_config->access_mode && !it->texts && !it->contents)
1743           _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
1744
1745 #if 0
1746         // FIXME: difference from upstream
1747         if (!it->item->mincalcd || ((GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS) && (it->item->w != it->item->minw)))
1748 #else
1749         if (!it->item->mincalcd)
1750 #endif
1751           {
1752              Evas_Coord mw = -1, mh = -1;
1753
1754              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
1755                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1756              if (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)
1757                mw = GL_IT(it)->wsd->prev_viewport_w;
1758              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
1759
1760              it->item->w = it->item->minw = mw;
1761              it->item->h = it->item->minh = mh;
1762              it->item->mincalcd = EINA_TRUE;
1763
1764              if ((!GL_IT(it)->wsd->group_item_width) && (it->group))
1765                {
1766                   GL_IT(it)->wsd->group_item_width = mw;
1767                   GL_IT(it)->wsd->group_item_height = mh;
1768                }
1769              else if ((!GL_IT(it)->wsd->item_width) &&
1770                       (it->item->type == ELM_GENLIST_ITEM_NONE))
1771                {
1772                   GL_IT(it)->wsd->item_width = mw;
1773                   GL_IT(it)->wsd->item_height = mh;
1774                }
1775           }
1776         if (!calc) evas_object_show(VIEW(it));
1777      }
1778
1779    if (it->tooltip.content_cb)
1780      {
1781         elm_widget_item_tooltip_content_cb_set
1782           (it, it->tooltip.content_cb, it->tooltip.data, NULL);
1783         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
1784         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
1785      }
1786
1787    if (it->mouse_cursor)
1788      elm_widget_item_cursor_set(it, it->mouse_cursor);
1789
1790    it->realized = EINA_TRUE;
1791    it->want_unrealize = EINA_FALSE;
1792
1793    if (!calc || it->item->unrealize_disabled)
1794      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1795
1796    if ((!calc) && (GL_IT(it)->wsd->decorate_all_mode) &&
1797        (it->item->type != ELM_GENLIST_ITEM_GROUP))
1798      {
1799         if (it->itc->decorate_all_item_style)
1800           {
1801              if (!it->deco_all_view)
1802                _decorate_all_item_realize(it, EINA_FALSE);
1803              edje_object_message_signal_process(it->deco_all_view);
1804           }
1805      }
1806    if ((!calc) && (it->decorate_it_set) &&
1807        (it->item->type != ELM_GENLIST_ITEM_GROUP))
1808      {
1809         if (it->itc->decorate_item_style)
1810           {
1811              if (!it->item->deco_it_view)
1812                _decorate_item_set(it);
1813              edje_object_message_signal_process(it->item->deco_it_view);
1814           }
1815      }
1816    edje_object_message_signal_process(VIEW(it));
1817 }
1818
1819 #if GENLIST_PINCH_ZOOM_SUPPORT
1820 static void
1821 _pinch_items_recalc(void *data)
1822 {
1823    Elm_Genlist_Smart_Data *sd = data;
1824    Item_Block *itb;
1825    Eina_List *l;
1826    Elm_Gen_Item *it;
1827
1828    Evas_Coord tot_y = 0, ox, oy;
1829    evas_object_geometry_get(sd->pan_obj, &ox, &oy, NULL, NULL);
1830
1831    EINA_INLIST_FOREACH(sd->blocks, itb)
1832      {
1833         EINA_LIST_FOREACH(itb->items, l, it)
1834           {
1835
1836              if (IS_ROOT_PARENT_IT(it))
1837                {
1838                   if (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
1839                     {
1840                        if (!it->realized) _item_realize(it, 0, EINA_FALSE);
1841                        it->item->scrl_y = oy + tot_y - sd->pan_y;
1842                        evas_object_resize(VIEW(it), sd->minw, it->item->h);
1843                        evas_object_move(VIEW(it), it->item->scrl_x, it->item->scrl_y);
1844                        evas_object_show(VIEW(it));
1845                        evas_object_raise(VIEW(it));
1846                        tot_y += it->item->h;
1847                        sd->pinch_zoom_h = tot_y;
1848                     }
1849
1850                   else if (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_EXPAND)
1851                     {
1852                        evas_object_resize(VIEW(it), sd->minw, it->item->h);
1853                        it->item->scrl_y = oy + it->item->pan_scrl_y - sd->pan_y;
1854                        evas_object_move(VIEW(it), it->item->scrl_x, it->item->scrl_y);
1855                     }
1856
1857                }
1858           }
1859      }
1860 }
1861 #endif
1862
1863 #if GROUP_ITEMS_FEATURE
1864 static void
1865 _group_items_recalc(void *data)
1866 {
1867    Eina_List *l;
1868    Elm_Gen_Item *git;
1869    Elm_Genlist_Smart_Data *sd = data;
1870
1871    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
1872    EINA_LIST_FOREACH(sd->group_items, l, git)
1873      {
1874         if (git->item->want_realize)
1875           {
1876              if (!git->realized) _item_realize(git, 0, EINA_FALSE);
1877              evas_object_resize(VIEW(git), sd->minw, git->item->h);
1878              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
1879              evas_object_show(VIEW(git));
1880              evas_object_raise(VIEW(git));
1881           }
1882         else if (!git->item->want_realize)
1883           {
1884              if (!git->dragging)
1885                _item_unrealize(git, EINA_FALSE);
1886           }
1887      }
1888    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
1889    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
1890 }
1891 #endif
1892
1893 static Eina_Bool
1894 _reorder_move_animator_cb(void *data)
1895 {
1896    double t;
1897    Elm_Gen_Item *it = data;
1898    Eina_Bool down = EINA_FALSE;
1899    int y, dy, diff;
1900
1901    dy = 6 * elm_config_scale_get();
1902    t = ((0.0 > (t = ecore_loop_time_get()
1903                   - GL_IT(it)->wsd->start_time)) ? 0.0 : t);
1904
1905    if (t <= REORDER_EFFECT_TIME)
1906      y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
1907    else y = dy;
1908
1909    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
1910    if (diff < dy) y = diff;
1911
1912    if (it->item->old_scrl_y < it->item->scrl_y)
1913      {
1914         it->item->old_scrl_y += y;
1915         down = EINA_TRUE;
1916      }
1917    else if (it->item->old_scrl_y > it->item->scrl_y)
1918      {
1919         it->item->old_scrl_y -= y;
1920         down = EINA_FALSE;
1921      }
1922
1923    if (it->deco_all_view)
1924      _item_position
1925        (it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
1926    else if (it->item->deco_it_view)
1927       _item_position
1928          (it, it->item->deco_it_view, it->item->scrl_x, it->item->old_scrl_y);
1929    else
1930      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
1931
1932    if ((GL_IT(it)->wsd->reorder_pan_move) ||
1933        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
1934        (!down && it->item->old_scrl_y <= it->item->scrl_y))
1935      {
1936         it->item->old_scrl_y = it->item->scrl_y;
1937         it->item->move_effect_enabled = EINA_FALSE;
1938         GL_IT(it)->wsd->reorder_move_animator = NULL;
1939         return ECORE_CALLBACK_CANCEL;
1940      }
1941
1942    return ECORE_CALLBACK_RENEW;
1943 }
1944
1945 static int
1946 _reorder_item_space_get(Elm_Gen_Item *it)
1947 {
1948    Elm_Gen_Item *reorder_it = GL_IT(it)->wsd->reorder_it;
1949    Evas_Coord rox, roy, row, roh, oy, oh;
1950    Eina_Bool top = EINA_FALSE;
1951
1952    if (!reorder_it) return 0;
1953    if(it->deco_all_view) evas_object_lower(it->deco_all_view);
1954
1955    evas_object_geometry_get(GL_IT(it)->wsd->pan_obj, NULL, &oy, NULL, &oh);
1956    evas_object_geometry_get
1957      (GL_IT(it)->wsd->VIEW(reorder_it), &rox, &roy, &row, &roh);
1958
1959    if ((GL_IT(it)->wsd->reorder_start_y < it->item->block->y) &&
1960        (roy - oy + (roh / 2) >= it->item->block->y - GL_IT(it)->wsd->pan_y))
1961      {
1962         it->item->block->reorder_offset =
1963           GL_IT(it)->wsd->reorder_it->item->h * -1;
1964         if (it->item->block->count == 1)
1965           GL_IT(it)->wsd->reorder_rel = it;
1966      }
1967    else if ((GL_IT(it)->wsd->reorder_start_y >= it->item->block->y) &&
1968             (roy - oy + (roh / 2) <= it->item->block->y -
1969              GL_IT(it)->wsd->pan_y))
1970      {
1971         it->item->block->reorder_offset = GL_IT(it)->wsd->reorder_it->item->h;
1972      }
1973    else
1974      it->item->block->reorder_offset = 0;
1975
1976    it->item->scrl_y += it->item->block->reorder_offset;
1977
1978    top = (ELM_RECTS_INTERSECT
1979             (it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
1980             rox, roy + (roh / 2), row, 1));
1981    if (top)
1982      {
1983         GL_IT(it)->wsd->reorder_rel = it;
1984         it->item->scrl_y += GL_IT(it)->wsd->reorder_it->item->h;
1985         return GL_IT(it)->wsd->reorder_it->item->h;
1986      }
1987    else
1988      return 0;
1989 }
1990
1991 static void
1992 _item_block_position(Item_Block *itb,
1993                      int in)
1994 {
1995    Elm_Gen_Item *it;
1996    Elm_Gen_Item *git;
1997    const Eina_List *l;
1998    Eina_Bool vis = EINA_FALSE;
1999    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2000
2001    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj));
2002    evas_object_geometry_get(itb->sd->pan_obj, &ox, &oy, &ow, &oh);
2003    evas_output_viewport_get
2004      (evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj),
2005      &cvx, &cvy, &cvw, &cvh);
2006
2007    EINA_LIST_FOREACH(itb->items, l, it)
2008      {
2009         if ((GL_IT(it)->wsd->reorder_it == it) && it->highlighted) continue;
2010
2011         it->x = 0;
2012         it->y = y;
2013         it->item->w = itb->w;
2014         it->item->scrl_x = itb->x + it->x - GL_IT(it)->wsd->pan_x + ox;
2015         it->item->scrl_y = itb->y + it->y - GL_IT(it)->wsd->pan_y + oy;
2016
2017         vis = (ELM_RECTS_INTERSECT
2018                  (it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2019                  cvx, cvy, cvw, cvh));
2020         if (1)
2021           {
2022              if ((itb->realized) && (!it->realized))
2023                {
2024                   if (vis) _item_realize(it, in, EINA_FALSE);
2025                }
2026              if (it->realized)
2027                {
2028                   if (vis || it->dragging)
2029                     {
2030 #if GENLIST_ENTRY_SUPPORT
2031                        evas_object_show(VIEW(it));
2032 #endif
2033                        if (GL_IT(it)->wsd->reorder_mode &&
2034                                 GL_IT(it)->wsd->reorder_it &&
2035                                   GL_IT(it)->wsd->reorder_it->highlighted)
2036                          y += _reorder_item_space_get(it);
2037                        git = it->item->group_item;
2038                        if (git)
2039                          {
2040                             if (git->item->scrl_y < oy)
2041                               git->item->scrl_y = oy;
2042                             if ((git->item->scrl_y + git->item->h) >
2043                                 (it->item->scrl_y + it->item->h))
2044                               git->item->scrl_y = (it->item->scrl_y +
2045                                                    it->item->h) - git->item->h;
2046                             git->item->scrl_x = it->item->scrl_x;
2047                             git->item->want_realize = EINA_TRUE;
2048                          }
2049                        if ((GL_IT(it)->wsd->reorder_it) &&
2050                                 GL_IT(it)->wsd->reorder_it->highlighted &&
2051                                 (it->item->old_scrl_y != it->item->scrl_y))
2052                          {
2053                             if (!it->item->move_effect_enabled)
2054                               {
2055                                  it->item->move_effect_enabled = EINA_TRUE;
2056                                  GL_IT(it)->wsd->reorder_move_animator =
2057                                    ecore_animator_add(
2058                                       _reorder_move_animator_cb, it);
2059                               }
2060                          }
2061                        if (!it->item->move_effect_enabled)
2062                          {
2063                             if ((GL_IT(it)->wsd->decorate_all_mode) &&
2064                                 (it->itc->decorate_all_item_style))
2065                               _decorate_all_item_position
2066                                  (it, it->item->scrl_x, it->item->scrl_y);
2067                             else
2068                               {
2069                                  if (it->item->deco_it_view)
2070                                    _item_position
2071                                       (it, it->item->deco_it_view,
2072                                        it->item->scrl_x,
2073                                        it->item->scrl_y);
2074                                  else
2075                                    _item_position
2076                                       (it, VIEW(it), it->item->scrl_x,
2077                                        it->item->scrl_y);
2078                               }
2079                             it->item->old_scrl_y = it->item->scrl_y;
2080 #if GENLIST_PINCH_ZOOM_SUPPORT
2081                             if (((GL_IT(it)->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
2082                                  && (!IS_ROOT_PARENT_IT(it))) || (GL_IT(it)->wsd->sorting))
2083                               {
2084                                  if (it->deco_all_view) evas_object_hide(it->deco_all_view);
2085                                  else evas_object_hide(VIEW(it));
2086                               }
2087 #endif
2088
2089                          }
2090                     }
2091                   else
2092                     {
2093                        if ((GL_IT(it)->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
2094                            && (!IS_ROOT_PARENT_IT(it)))
2095                          {
2096                             if (it->deco_all_view) evas_object_hide(it->deco_all_view);
2097                             else evas_object_hide(VIEW(it));
2098                          }
2099                        else
2100                          _item_unrealize(it, EINA_FALSE);
2101                     }
2102                }
2103              in++;
2104           }
2105         else
2106           {
2107              if (vis) it->item->want_realize = EINA_TRUE;
2108           }
2109         y += it->item->h;
2110 #if 0
2111         // FIXME: diffrence from upstream
2112         minh += it->item->minh;
2113 #endif
2114
2115      }
2116    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj));
2117    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(itb->sd)->obj));
2118 }
2119
2120 static void
2121 _item_block_realize(Item_Block *itb)
2122 {
2123    if (itb->realized) return;
2124
2125    itb->realized = EINA_TRUE;
2126    itb->want_unrealize = EINA_FALSE;
2127 }
2128
2129 #if GENLIST_ENTRY_SUPPORT
2130 static void
2131 _changed_job(Elm_Genlist_Smart_Data *sd)
2132 {
2133    Eina_List *l2;
2134
2135    Item_Block *itb;
2136    int num = 0, num0;
2137    Eina_Bool anything_changed = EINA_FALSE;
2138    Eina_Bool width_changed = EINA_FALSE;
2139    Eina_Bool height_changed = EINA_FALSE;
2140    sd->size_changed = EINA_FALSE;
2141
2142    EINA_INLIST_FOREACH(sd->blocks, itb)
2143      {
2144         Elm_Gen_Item *it;
2145
2146         if (!itb->changeme)
2147           {
2148              num += itb->count;
2149              if (anything_changed)
2150                _item_block_position(itb, num);
2151              continue;
2152           }
2153         num0 = num;
2154         width_changed = height_changed = EINA_FALSE;
2155         EINA_LIST_FOREACH(itb->items, l2, it)
2156           {
2157              if ((!it->item->mincalcd) && (it->realized))
2158                {
2159                   Evas_Coord fw = -1, fh = -1;
2160                   Evas_Coord mw = -1, mh = -1;
2161
2162                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2163                      elm_coords_finger_size_adjust(1, &fw, 1, &fh);
2164
2165                   // FIXME: why compressmode do this?
2166                   if (sd->mode == ELM_LIST_COMPRESS) mw = sd->prev_viewport_w;
2167
2168                   edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, fw, fh);
2169
2170                   if (it->item->w != mw)
2171                     {
2172                        it->item->w = it->item->minw = mw;
2173                        width_changed = EINA_TRUE;
2174                     }
2175                   if (it->item->h != mh)
2176                     {
2177                        it->item->h = it->item->minh = mh;
2178                        height_changed = EINA_TRUE;
2179                     }
2180                   if (mw > itb->w)
2181                     {
2182                        itb->w = mw;
2183                     }
2184
2185                   it->item->mincalcd = EINA_TRUE;
2186
2187                   if ((!sd->group_item_width) && (it->group))
2188                     {
2189                        sd->group_item_width = mw;
2190                        sd->group_item_height = mh;
2191                     }
2192                   else if ((!sd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
2193                     {
2194                        sd->item_width = mw;
2195                        sd->item_height = mh;
2196                     }
2197                }
2198              num++;
2199           }
2200         itb->changeme = EINA_FALSE;
2201         if (height_changed)
2202           {
2203              anything_changed = EINA_TRUE;
2204              itb->changed = EINA_TRUE;
2205              _item_block_recalc(itb, num0, 0);
2206              _item_block_position(itb, num0);
2207           }
2208         else if (width_changed)
2209           {
2210              _item_block_position(itb, num0);
2211           }
2212      }
2213    if (anything_changed)
2214      {
2215         if (sd->calc_job) ecore_job_del(sd->calc_job);
2216         sd->calc_job = ecore_job_add(_calc_job, sd);
2217      }
2218 }
2219 #endif
2220
2221 static void
2222 _elm_genlist_pan_smart_calculate(Evas_Object *obj)
2223 {
2224    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2225    Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0;
2226    Elm_Gen_Item *git;
2227    Item_Block *itb;
2228    Eina_List *l;
2229    int in = 0;
2230
2231    ELM_GENLIST_PAN_DATA_GET(obj, psd);
2232
2233    //evas_event_freeze(evas_object_evas_get(obj));
2234
2235 #if GENLIST_FX_SUPPORT
2236    if (psd->wsd->fx_playing) return;
2237 #endif
2238    if (psd->wsd->pan_changed)
2239      {
2240         _calc_job(psd->wsd);
2241         psd->wsd->pan_changed = EINA_FALSE;
2242      }
2243
2244    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2245    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2246    EINA_LIST_FOREACH(psd->wsd->group_items, l, git)
2247     {
2248 #if GROUP_ITEMS_FEATURE
2249        git->item->want_realize = EINA_FALSE;
2250 #else
2251        _item_unrealize(git, EINA_TRUE);
2252 #endif
2253     }
2254
2255    EINA_INLIST_FOREACH(psd->wsd->blocks, itb)
2256      {
2257         itb->w = psd->wsd->minw;
2258         if (ELM_RECTS_INTERSECT(itb->x - psd->wsd->pan_x + ox,
2259                                 itb->y - psd->wsd->pan_y + oy,
2260                                 itb->w, itb->h,
2261                                 cvx, cvy, cvw, cvh))
2262           {
2263              if ((!itb->realized) || (itb->changed))
2264                {
2265                   _item_block_realize(itb);
2266 #if 0
2267                   // FIXME: difference from opensource
2268                   if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2269                   sd->wd->calc_job = NULL;
2270                   _calc_job(sd->wd);
2271 #endif
2272                }
2273              _item_block_position(itb, in);
2274           }
2275         else
2276           {
2277              if (itb->realized) _item_block_unrealize(itb);
2278           }
2279         in += itb->count;
2280      }
2281 #if GENLIST_PINCH_ZOOM_SUPPORT
2282    if (psd->wsd->pinch_zoom_mode) _pinch_items_recalc(psd->wsd);
2283 #endif
2284
2285 #if GROUP_ITEMS_FEATURE
2286    if ((!psd->wsd->reorder_it) || (psd->wsd->reorder_pan_move))
2287      _group_items_recalc(psd->wsd);
2288 #endif
2289    if ((psd->wsd->reorder_mode) && (psd->wsd->reorder_it))
2290      {
2291         if (psd->wsd->pan_y != psd->wsd->reorder_old_pan_y)
2292           psd->wsd->reorder_pan_move = EINA_TRUE;
2293         else psd->wsd->reorder_pan_move = EINA_FALSE;
2294
2295         evas_object_raise(psd->wsd->VIEW(reorder_it));
2296         psd->wsd->reorder_old_pan_y = psd->wsd->pan_y;
2297         psd->wsd->start_time = ecore_loop_time_get();
2298      }
2299      _item_auto_scroll(psd->wsd);
2300
2301    psd->wsd->s_iface->content_pos_get(ELM_WIDGET_DATA(psd->wsd)->obj, &vx, &vy);
2302    psd->wsd->s_iface->content_viewport_size_get(ELM_WIDGET_DATA(psd->wsd)->obj,
2303                                                 &vw, &vh);
2304
2305    if (psd->wsd->reorder_fast == 1)
2306      psd->wsd->s_iface->content_region_show(ELM_WIDGET_DATA(psd->wsd)->obj,
2307                                             vx,vy - 10, vw, vh);
2308    else if (psd->wsd->reorder_fast == -1)
2309      psd->wsd->s_iface->content_region_show(ELM_WIDGET_DATA(psd->wsd)->obj,
2310                                             vx, vy + 10, vw, vh);
2311
2312 #if GENLIST_ENTRY_SUPPORT
2313    if (psd->wsd->size_changed) _changed_job(psd->wsd);
2314 #endif
2315
2316 #if GENLIST_FX_SUPPORT
2317    psd->wsd->rendered = EINA_TRUE;
2318    if ((psd->wsd->fx_mode) && (!psd->wsd->queue))
2319      {
2320         if (_elm_genlist_fx_capture(ELM_WIDGET_DATA(psd->wsd)->obj, 1))
2321           _elm_genlist_fx_play(ELM_WIDGET_DATA(psd->wsd)->obj);
2322      }
2323 #endif
2324 #if GENLIST_PINCH_ZOOM_SUPPORT
2325    if (psd->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_EXPAND)
2326      psd->wsd->pinch_zoom_mode = ELM_GEN_PINCH_ZOOM_NONE;
2327 #endif
2328    //evas_event_thaw(evas_object_evas_get(obj));
2329    //evas_event_thaw_eval(evas_object_evas_get(obj));
2330 }
2331
2332 static void
2333 _elm_genlist_pan_smart_set_user(Elm_Genlist_Pan_Smart_Class *sc)
2334 {
2335    ELM_PAN_CLASS(sc)->base.add = _elm_genlist_pan_smart_add;
2336    ELM_PAN_CLASS(sc)->base.del = _elm_genlist_pan_smart_del;
2337    ELM_PAN_CLASS(sc)->base.move = _elm_genlist_pan_smart_move;
2338    ELM_PAN_CLASS(sc)->base.resize = _elm_genlist_pan_smart_resize;
2339    ELM_PAN_CLASS(sc)->base.calculate = _elm_genlist_pan_smart_calculate;
2340
2341    ELM_PAN_CLASS(sc)->pos_set = _elm_genlist_pan_smart_pos_set;
2342    ELM_PAN_CLASS(sc)->pos_get = _elm_genlist_pan_smart_pos_get;
2343    ELM_PAN_CLASS(sc)->pos_max_get = _elm_genlist_pan_smart_pos_max_get;
2344    ELM_PAN_CLASS(sc)->pos_min_get = _elm_genlist_pan_smart_pos_min_get;
2345    ELM_PAN_CLASS(sc)->content_size_get =
2346      _elm_genlist_pan_smart_content_size_get;
2347 }
2348
2349 static Eina_Bool
2350 _item_multi_select_up(Elm_Genlist_Smart_Data *sd)
2351 {
2352    Elm_Object_Item *prev;
2353
2354    if (!sd->selected) return EINA_FALSE;
2355    if (!sd->multi) return EINA_FALSE;
2356
2357    prev = elm_genlist_item_prev_get(sd->last_selected_item);
2358    if (!prev) return EINA_TRUE;
2359
2360    if (elm_genlist_item_selected_get(prev))
2361      {
2362         elm_genlist_item_selected_set(sd->last_selected_item, EINA_FALSE);
2363         sd->last_selected_item = prev;
2364         elm_genlist_item_show
2365           (sd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
2366      }
2367    else
2368      {
2369         elm_genlist_item_selected_set(prev, EINA_TRUE);
2370         elm_genlist_item_show(prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
2371      }
2372    return EINA_TRUE;
2373 }
2374
2375 static Eina_Bool
2376 _item_multi_select_down(Elm_Genlist_Smart_Data *sd)
2377 {
2378    Elm_Object_Item *next;
2379
2380    if (!sd->selected) return EINA_FALSE;
2381    if (!sd->multi) return EINA_FALSE;
2382
2383    next = elm_genlist_item_next_get(sd->last_selected_item);
2384    if (!next) return EINA_TRUE;
2385
2386    if (elm_genlist_item_selected_get(next))
2387      {
2388         elm_genlist_item_selected_set(sd->last_selected_item, EINA_FALSE);
2389         sd->last_selected_item = next;
2390         elm_genlist_item_show
2391           (sd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
2392      }
2393    else
2394      {
2395         elm_genlist_item_selected_set(next, EINA_TRUE);
2396         elm_genlist_item_show(next, ELM_GENLIST_ITEM_SCROLLTO_IN);
2397      }
2398
2399    return EINA_TRUE;
2400 }
2401
2402 static Eina_Bool
2403 _all_items_deselect(Elm_Genlist_Smart_Data *sd)
2404 {
2405    if (!sd->selected) return EINA_FALSE;
2406
2407    while (sd->selected)
2408      elm_genlist_item_selected_set(sd->selected->data, EINA_FALSE);
2409
2410    return EINA_TRUE;
2411 }
2412
2413 static Eina_Bool
2414 _item_single_select_up(Elm_Genlist_Smart_Data *sd)
2415 {
2416    Elm_Gen_Item *prev;
2417
2418    if (!sd->selected)
2419      {
2420         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2421         while (prev)
2422           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
2423      }
2424    else
2425      prev = (Elm_Gen_Item *)elm_genlist_item_prev_get
2426          (sd->last_selected_item);
2427
2428    if (!prev) return EINA_FALSE;
2429
2430    _all_items_deselect(sd);
2431
2432    elm_genlist_item_selected_set((Elm_Object_Item *)prev, EINA_TRUE);
2433    elm_genlist_item_show((Elm_Object_Item *)prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
2434    return EINA_TRUE;
2435 }
2436
2437 static Eina_Bool
2438 _item_single_select_down(Elm_Genlist_Smart_Data *sd)
2439 {
2440    Elm_Gen_Item *next;
2441
2442    if (!sd->selected)
2443      {
2444         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2445         while (next)
2446           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
2447      }
2448    else
2449      next = (Elm_Gen_Item *)elm_genlist_item_next_get
2450          (sd->last_selected_item);
2451
2452    if (!next) return EINA_FALSE;
2453
2454    _all_items_deselect(sd);
2455
2456    elm_genlist_item_selected_set((Elm_Object_Item *)next, EINA_TRUE);
2457    elm_genlist_item_show
2458      ((Elm_Object_Item *)next, ELM_GENLIST_ITEM_SCROLLTO_IN);
2459
2460    return EINA_TRUE;
2461 }
2462
2463 static Eina_Bool
2464 _elm_genlist_smart_event(Evas_Object *obj,
2465                          Evas_Object *src __UNUSED__,
2466                          Evas_Callback_Type type,
2467                          void *event_info)
2468 {
2469    Evas_Coord x = 0;
2470    Evas_Coord y = 0;
2471    Evas_Coord v_w = 0;
2472    Evas_Coord v_h = 0;
2473    Evas_Coord step_x = 0;
2474    Evas_Coord step_y = 0;
2475    Evas_Coord page_x = 0;
2476    Evas_Coord page_y = 0;
2477    Elm_Object_Item *it;
2478    Evas_Event_Key_Down *ev = event_info;
2479    Evas_Coord pan_max_x = 0, pan_max_y = 0;
2480
2481    ELM_GENLIST_DATA_GET(obj, sd);
2482
2483    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
2484    if (!sd->items) return EINA_FALSE;
2485    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
2486    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
2487
2488    sd->s_iface->content_pos_get(obj, &x, &y);
2489    sd->s_iface->step_size_get(obj, &step_x, &step_y);
2490    sd->s_iface->page_size_get(obj, &page_x, &page_y);
2491    sd->s_iface->content_viewport_size_get(obj, &v_w, &v_h);
2492
2493    if ((!strcmp(ev->keyname, "Left")) ||
2494        ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
2495      {
2496         x -= step_x;
2497      }
2498    else if ((!strcmp(ev->keyname, "Right")) ||
2499             ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
2500      {
2501         x += step_x;
2502      }
2503    else if ((!strcmp(ev->keyname, "Up")) ||
2504             ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
2505      {
2506         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
2507              (_item_multi_select_up(sd)))
2508             || (_item_single_select_up(sd)))
2509           {
2510              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2511              return EINA_TRUE;
2512           }
2513         else
2514           y -= step_y;
2515      }
2516    else if ((!strcmp(ev->keyname, "Down")) ||
2517             ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
2518      {
2519         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
2520              (_item_multi_select_down(sd)))
2521             || (_item_single_select_down(sd)))
2522           {
2523              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2524              return EINA_TRUE;
2525           }
2526         else
2527           y += step_y;
2528      }
2529    else if ((!strcmp(ev->keyname, "Home")) ||
2530             ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
2531      {
2532         it = elm_genlist_first_item_get(obj);
2533         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
2534         elm_genlist_item_selected_set(it, EINA_TRUE);
2535         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2536         return EINA_TRUE;
2537      }
2538    else if ((!strcmp(ev->keyname, "End")) ||
2539             ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
2540      {
2541         it = elm_genlist_last_item_get(obj);
2542         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
2543         elm_genlist_item_selected_set(it, EINA_TRUE);
2544         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2545         return EINA_TRUE;
2546      }
2547    else if ((!strcmp(ev->keyname, "Prior")) ||
2548             ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
2549      {
2550         if (page_y < 0)
2551           y -= -(page_y * v_h) / 100;
2552         else
2553           y -= page_y;
2554      }
2555    else if ((!strcmp(ev->keyname, "Next")) ||
2556             ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
2557      {
2558         if (page_y < 0)
2559           y += -(page_y * v_h) / 100;
2560         else
2561           y += page_y;
2562      }
2563    else if (!strcmp(ev->keyname, "Escape"))
2564      {
2565         if (!_all_items_deselect(sd)) return EINA_FALSE;
2566         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2567         return EINA_TRUE;
2568      }
2569    else if (((!strcmp(ev->keyname, "Return")) ||
2570              (!strcmp(ev->keyname, "KP_Enter")) ||
2571              (!strcmp(ev->keyname, "space")))
2572             && (!sd->multi) && (sd->selected))
2573      {
2574         it = elm_genlist_selected_item_get(obj);
2575         elm_genlist_item_expanded_set(it, !elm_genlist_item_expanded_get(it));
2576         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
2577      }
2578    else return EINA_FALSE;
2579
2580    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2581    _elm_genlist_pan_smart_pos_max_get(sd->pan_obj, &pan_max_x, &pan_max_y);
2582    if (x < 0) x = 0;
2583    if (x > pan_max_x) x = pan_max_x;
2584    if (y < 0) y = 0;
2585    if (y > pan_max_y) y = pan_max_y;
2586
2587    sd->s_iface->content_pos_set(obj, x, y, EINA_TRUE);
2588
2589    return EINA_TRUE;
2590 }
2591
2592 static Eina_Bool
2593 _elm_genlist_smart_sub_object_add(Evas_Object *obj,
2594                                   Evas_Object *sobj)
2595 {
2596    Elm_Widget_Smart_Class *parent_parent;
2597
2598    parent_parent = (Elm_Widget_Smart_Class *)((Evas_Smart_Class *)
2599                                               _elm_genlist_parent_sc)->parent;
2600
2601    /* skipping layout's code, which registers size hint changing
2602     * callback on sub objects. this is here because items'
2603     * content_get() routines may change hints on the objects after
2604     * creation, thus issuing TOO MANY sizing_eval()'s here. they are
2605     * not needed at here anyway, so let's skip listening to those
2606     * hints changes */
2607    if (!parent_parent->sub_object_add(obj, sobj))
2608      return EINA_FALSE;
2609
2610    return EINA_TRUE;
2611 }
2612
2613 static Eina_Bool
2614 _elm_genlist_smart_sub_object_del(Evas_Object *obj,
2615                                   Evas_Object *sobj)
2616 {
2617    ELM_GENLIST_DATA_GET(obj, sd);
2618
2619    /* XXX: hack -- also skipping sizing recalculation on
2620     * sub-object-del. genlist's crazy code paths (like groups and
2621     * such) seem to issue a whole lot of deletions and Evas bitches
2622     * about too many recalculations */
2623    sd->on_sub_del = EINA_TRUE;
2624
2625    if (!ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->sub_object_del(obj, sobj))
2626      return EINA_FALSE;
2627
2628    sd->on_sub_del = EINA_FALSE;
2629
2630    return EINA_TRUE;
2631 }
2632
2633 static Eina_Bool
2634 _elm_genlist_smart_on_focus(Evas_Object *obj)
2635 {
2636    ELM_GENLIST_DATA_GET(obj, sd);
2637
2638    if (!ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->on_focus(obj))
2639      return EINA_FALSE;
2640
2641    if (elm_widget_focus_get(obj) && (sd->items) && (sd->selected) &&
2642        (!sd->last_selected_item))
2643      sd->last_selected_item = eina_list_data_get(sd->selected);
2644
2645    return EINA_TRUE;
2646 }
2647
2648 static Eina_Bool
2649 _elm_genlist_smart_focus_next(const Evas_Object *obj,
2650                            Elm_Focus_Direction dir,
2651                            Evas_Object **next)
2652 {
2653    Evas_Coord x, y, w, h;
2654    Evas_Coord sx, sy, sw, sh;
2655    Item_Block *itb;
2656    Eina_List *items = NULL;
2657    Eina_Bool done = EINA_FALSE;
2658
2659    ELM_GENLIST_CHECK(obj) EINA_FALSE;
2660    ELM_GENLIST_DATA_GET(obj, sd);
2661
2662    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->obj, &sx, &sy, &sw, &sh);
2663
2664    EINA_INLIST_FOREACH(sd->blocks, itb)
2665      {
2666         if (itb->realized)
2667           {
2668              Eina_List *l;
2669              Elm_Gen_Item *it;
2670
2671              done = EINA_TRUE;
2672              EINA_LIST_FOREACH(itb->items, l, it)
2673                {
2674                   if (it->realized)
2675                     {
2676                        evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
2677
2678                        /* check item which displays more than half of its size */
2679                        if (ELM_RECTS_INTERSECT
2680                              (x + (w / 2), y + (h / 2), 0, 0, sx, sy, sw, sh))
2681                          items = eina_list_append(items, it->base.access_obj);
2682
2683                        if (!it->base.access_order) continue;
2684
2685                        Eina_List *subl;
2686                        Evas_Object *subo;
2687                        EINA_LIST_FOREACH(it->base.access_order, subl, subo)
2688                          items = eina_list_append(items, subo);
2689                     }
2690                }
2691           }
2692         else if (done) break;
2693      }
2694
2695    return elm_widget_focus_list_next_get
2696             (obj, items, eina_list_data_get, dir, next);
2697 }
2698
2699 static void
2700 _mirrored_set(Evas_Object *obj,
2701               Eina_Bool rtl)
2702 {
2703    ELM_GENLIST_DATA_GET(obj, sd);
2704
2705    sd->s_iface->mirrored_set(obj, rtl);
2706 }
2707
2708 static Eina_Bool
2709 _elm_genlist_smart_theme(Evas_Object *obj)
2710 {
2711    Item_Block *itb;
2712
2713    ELM_GENLIST_DATA_GET(obj, sd);
2714
2715    if (!ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->theme(obj))
2716      return EINA_FALSE;
2717
2718    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2719    _item_cache_all_free(sd);
2720    _mirrored_set(obj, elm_widget_mirrored_get(obj));
2721
2722 #if 0
2723    // FIXME: difference from opensource
2724    elm_layout_theme_set(obj, "genlist", "base", elm_widget_style_get(obj));
2725 #endif
2726
2727    sd->item_width = sd->item_height = 0;
2728    sd->group_item_width = sd->group_item_height = 0;
2729    sd->minw = sd->minh = sd->realminw = 0;
2730    EINA_INLIST_FOREACH(sd->blocks, itb)
2731      {
2732         Eina_List *l;
2733         Elm_Gen_Item *it;
2734
2735         if (itb->realized) _item_block_unrealize(itb);
2736         EINA_LIST_FOREACH(itb->items, l, it)
2737           it->item->mincalcd = EINA_FALSE;
2738
2739         itb->changed = EINA_TRUE;
2740      }
2741    if (sd->calc_job) ecore_job_del(sd->calc_job);
2742    sd->calc_job = NULL;
2743    elm_layout_sizing_eval(obj);
2744    sd->pan_changed = EINA_TRUE;
2745    evas_object_smart_changed(sd->pan_obj);
2746    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2747    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2748
2749    return EINA_TRUE;
2750 }
2751
2752 /* FIXME: take off later. maybe this show region coords belong in the
2753  * interface (new api functions, set/get)? */
2754 static void
2755 _show_region_hook(void *data,
2756                   Evas_Object *obj)
2757 {
2758    Evas_Coord x, y, w, h;
2759
2760    ELM_GENLIST_DATA_GET(data, sd);
2761
2762    elm_widget_show_region_get(obj, &x, &y, &w, &h);
2763    //x & y are screen coordinates, Add with pan coordinates
2764    x += sd->pan_x;
2765    y += sd->pan_y;
2766    sd->s_iface->content_region_show(obj, x, y, w, h);
2767 }
2768
2769 static Eina_Bool
2770 _elm_genlist_smart_translate(Evas_Object *obj)
2771 {
2772    evas_object_smart_callback_call(obj, "language,changed", NULL);
2773
2774    return EINA_TRUE;
2775 }
2776
2777 static void
2778 _item_highlight(Elm_Gen_Item *it)
2779 {
2780    const char *selectraise;
2781    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2782
2783    if (elm_widget_item_disabled_get(it)) return;
2784    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2785        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ) ||
2786        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2787        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ))
2788      return;
2789
2790    if (!sd->highlight || it->highlighted) return;
2791 #if GENLIST_PINCH_ZOOM_SUPPORT
2792    if (sd->pinch_zoom_mode) return;
2793 #endif
2794
2795    selectraise = edje_object_data_get(VIEW(it), "selectraise");
2796    if ((selectraise) && (!strcmp(selectraise, "on")))
2797      {
2798         if (it->deco_all_view) evas_object_raise(it->deco_all_view);
2799         else evas_object_raise(VIEW(it));
2800         if ((it->item->group_item) && (it->item->group_item->realized))
2801           evas_object_raise(it->item->VIEW(group_item));
2802      }
2803    it->highlighted = EINA_TRUE;
2804
2805    if (it->deco_all_view)
2806      edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
2807    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
2808    evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
2809 }
2810
2811 static void
2812 _item_unhighlight(Elm_Gen_Item *it)
2813 {
2814    if (!it->highlighted) return;
2815
2816    if (!it->item->nostacking)
2817      {
2818         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
2819           {
2820              if (it->deco_all_view) evas_object_lower(it->deco_all_view);
2821              else evas_object_lower(VIEW(it));
2822           }
2823         else
2824           {
2825              if (it->deco_all_view) evas_object_raise(it->deco_all_view);
2826              else evas_object_raise(VIEW(it));
2827           }
2828      }
2829    it->highlighted = EINA_FALSE;
2830
2831    if (it->deco_all_view)
2832      edje_object_signal_emit(it->deco_all_view, "elm,state,unselected", "elm");
2833    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
2834    evas_object_smart_callback_call(WIDGET(it), SIG_UNHIGHLIGHTED, it);
2835 }
2836
2837 static void
2838 _item_unselect(Elm_Gen_Item *it)
2839 {
2840    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2841    _item_unhighlight(it);
2842    if (!it->selected) return;
2843
2844    it->selected = EINA_FALSE;
2845    sd->selected = eina_list_remove(sd->selected, it);
2846    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
2847 }
2848
2849 static void
2850 _item_select(Elm_Gen_Item *it)
2851 {
2852    Evas_Object *obj = WIDGET(it);
2853    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2854    if (elm_widget_item_disabled_get(it)) return;
2855    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2856        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
2857        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2858        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
2859      return;
2860
2861 #if GENLIST_PINCH_ZOOM_SUPPORT
2862    if (IS_ROOT_PARENT_IT(it) && (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT))
2863      {
2864         elm_genlist_pinch_zoom_mode_set(obj, ELM_GEN_PINCH_ZOOM_EXPAND);
2865         elm_genlist_item_show((Elm_Object_Item *)it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
2866         return;
2867      }
2868 #endif
2869
2870 #if 0
2871    // FIXME: difference from upstream
2872    if ((GL_IT(it)->wsd->last_selected_item) &&
2873        (it != (Elm_Gen_Item *) GL_IT(it)->wsd->last_selected_item))
2874      _item_unfocusable_set
2875        ((Elm_Gen_Item *)GL_IT(it)->wsd->last_selected_item, EINA_TRUE);
2876 #endif
2877
2878    // Do not check selected because always select mode can be used
2879    _item_highlight(it);
2880    it->selected = EINA_TRUE;
2881    sd->selected = eina_list_append(sd->selected, it);
2882    sd->last_selected_item = (Elm_Object_Item *)it;
2883
2884    if (it->func.func) it->func.func((void *)it->func.data, obj, it);
2885    if (!EINA_MAGIC_CHECK((Elm_Widget_Item *)it, ELM_WIDGET_ITEM_MAGIC))
2886      return;
2887    evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
2888 }
2889
2890 static void
2891 _item_select_unselect(Elm_Gen_Item *it, Eina_Bool selected)
2892 {
2893    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2894    Evas_Object *obj = ELM_WIDGET_DATA(sd)->obj;
2895    if (elm_widget_item_disabled_get(it)) return;
2896
2897    evas_object_ref(obj);
2898    if (!sd->multi)
2899      {
2900         const Eina_List *l, *ll;
2901         Elm_Gen_Item *it2;
2902         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, it2)
2903            if (it2 != it) _item_unselect(it2);
2904      }
2905    if (selected) _item_select(it);
2906    else _item_unselect(it);
2907    evas_object_unref(obj);
2908 }
2909
2910 static void
2911 _item_block_position_update(Eina_Inlist *list,
2912                             int idx)
2913 {
2914    Item_Block *tmp;
2915
2916    EINA_INLIST_FOREACH(list, tmp)
2917      {
2918         tmp->position = idx++;
2919         tmp->position_update = EINA_TRUE;
2920      }
2921 }
2922
2923 static void
2924 _item_position_update(Eina_List *list,
2925                       int idx)
2926 {
2927    Elm_Gen_Item *it;
2928    Eina_List *l;
2929
2930    EINA_LIST_FOREACH(list, l, it)
2931      {
2932         it->position = idx++;
2933         it->position_update = EINA_TRUE;
2934      }
2935 }
2936
2937 static void
2938 _item_block_merge(Item_Block *left,
2939                   Item_Block *right)
2940 {
2941    Eina_List *l;
2942    Elm_Gen_Item *it2;
2943
2944    EINA_LIST_FOREACH(right->items, l, it2)
2945      {
2946         it2->item->block = left;
2947         left->count++;
2948         left->changed = EINA_TRUE;
2949      }
2950    left->items = eina_list_merge(left->items, right->items);
2951 }
2952
2953 static void
2954 _item_block_del(Elm_Gen_Item *it)
2955 {
2956    Eina_Inlist *il;
2957    Item_Block *itb = it->item->block;
2958    Eina_Bool block_changed = EINA_FALSE;
2959
2960    itb->items = eina_list_remove(itb->items, it);
2961    itb->count--;
2962    itb->changed = EINA_TRUE;
2963    if (GL_IT(it)->wsd->calc_job) ecore_job_del(GL_IT(it)->wsd->calc_job);
2964    GL_IT(it)->wsd->calc_job = ecore_job_add(_calc_job, GL_IT(it)->wsd);
2965    if (itb->count < 1)
2966      {
2967         Item_Block *itbn;
2968
2969         il = EINA_INLIST_GET(itb);
2970         itbn = (Item_Block *)(il->next);
2971         if (it->parent)
2972           it->parent->item->items =
2973             eina_list_remove(it->parent->item->items, it);
2974         else
2975           {
2976              _item_block_position_update(il->next, itb->position);
2977           }
2978         GL_IT(it)->wsd->blocks =
2979           eina_inlist_remove(GL_IT(it)->wsd->blocks, il);
2980         free(itb);
2981         itb = NULL;
2982         if (itbn) itbn->changed = EINA_TRUE;
2983      }
2984    else
2985      {
2986         if (itb->count < (itb->sd->max_items_per_block / 2))
2987           {
2988              Item_Block *itbp;
2989              Item_Block *itbn;
2990
2991              il = EINA_INLIST_GET(itb);
2992              itbp = (Item_Block *)(il->prev);
2993              itbn = (Item_Block *)(il->next);
2994
2995              /* merge block with previous */
2996              if ((itbp) &&
2997                  ((itbp->count + itb->count) <
2998                   (itb->sd->max_items_per_block +
2999                    (itb->sd->max_items_per_block / 2))))
3000                {
3001                   _item_block_merge(itbp, itb);
3002                   _item_block_position_update
3003                     (EINA_INLIST_GET(itb)->next, itb->position);
3004                   GL_IT(it)->wsd->blocks = eina_inlist_remove
3005                       (GL_IT(it)->wsd->blocks, EINA_INLIST_GET(itb));
3006                   free(itb);
3007                   block_changed = EINA_TRUE;
3008                }
3009              /* merge block with next */
3010              else if ((itbn) &&
3011                       ((itbn->count + itb->count) <
3012                        (itb->sd->max_items_per_block +
3013                         (itb->sd->max_items_per_block / 2))))
3014                {
3015                   _item_block_merge(itb, itbn);
3016                   _item_block_position_update
3017                     (EINA_INLIST_GET(itbn)->next, itbn->position);
3018                   GL_IT(it)->wsd->blocks =
3019                     eina_inlist_remove(GL_IT(it)->wsd->blocks,
3020                                        EINA_INLIST_GET(itbn));
3021                   free(itbn);
3022                   block_changed = EINA_TRUE;
3023                }
3024           }
3025      }
3026
3027    if (block_changed)
3028      {
3029         GL_IT(it)->wsd->pan_changed = EINA_TRUE;
3030         evas_object_smart_changed(GL_IT(it)->wsd->pan_obj);
3031         if (GL_IT(it)->wsd->calc_job) ecore_job_del(GL_IT(it)->wsd->calc_job);
3032         GL_IT(it)->wsd->calc_job = NULL;
3033      }
3034 #if GENLIST_FX_SUPPORT
3035    it->item->block = NULL;
3036 #endif
3037 }
3038
3039 static void
3040 _decorate_all_item_unrealize(Elm_Gen_Item *it)
3041 {
3042    Evas_Object *icon;
3043
3044    if ((!it) || (!it->item->decorate_all_item_realized)) return;
3045
3046 #if GENLIST_FX_SUPPORT
3047    if ((GL_IT(it)->has_proxy_it) && (!GL_IT(it)->wsd->genlist_clearing))
3048      {
3049         if (!eina_list_data_find(GL_IT(it)->wsd->pending_unrealized_decorate_all_items, it))
3050           GL_IT(it)->wsd->pending_unrealized_decorate_all_items =
3051              eina_list_append(GL_IT(it)->wsd->pending_unrealized_decorate_all_items, it);
3052         return;
3053      }
3054 #endif
3055
3056    edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3057    evas_object_smart_member_add(VIEW(it), GL_IT(it)->wsd->pan_obj);
3058    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3059    _elm_genlist_item_odd_even_update(it);
3060    _elm_genlist_item_state_update(it, NULL);
3061
3062    edje_object_signal_emit
3063      (it->deco_all_view, "elm,state,decorate,disabled", "elm");
3064    edje_object_signal_emit
3065      (VIEW(it), "elm,state,decorate,disabled", "elm");
3066    if (it->item->wsd->reorder_mode)
3067      {
3068         edje_object_signal_emit
3069           (VIEW(it), "elm,state,reorder,mode_set", "elm");
3070         edje_object_signal_emit
3071           (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
3072      }
3073
3074    edje_object_message_signal_process(VIEW(it));
3075    edje_object_message_signal_process(it->deco_all_view);
3076
3077    evas_object_del(it->deco_all_view);
3078    it->deco_all_view = NULL;
3079    elm_widget_stringlist_free(it->item->deco_all_texts);
3080    it->item->deco_all_texts = NULL;
3081    elm_widget_stringlist_free(it->item->deco_all_contents);
3082    it->item->deco_all_contents = NULL;
3083    elm_widget_stringlist_free(it->item->deco_all_states);
3084    it->item->deco_all_states = NULL;
3085    EINA_LIST_FREE (it->item->deco_all_content_objs, icon)
3086      evas_object_del(icon);
3087
3088    _item_mouse_callbacks_del(it, it->deco_all_view);
3089    _item_mouse_callbacks_add(it, VIEW(it));
3090
3091    it->item->decorate_all_item_realized = EINA_FALSE;
3092 }
3093
3094 static void
3095 _item_free_common(Elm_Gen_Item *it)
3096 {
3097    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
3098    elm_widget_item_pre_notify_del(it);
3099    if (it->itc->func.del)
3100      it->itc->func.del((void *)it->base.data, WIDGET(it));
3101    if (it->tooltip.del_cb)
3102      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3103    if (it->item->block) _item_block_del(it);
3104    if (it->parent)
3105      it->parent->item->items =
3106         eina_list_remove(it->parent->item->items, it);
3107    if (it->item->queued) sd->queue = eina_list_remove(sd->queue, it);
3108    if (it->group) sd->group_items = eina_list_remove(sd->group_items, it);
3109
3110    // FIXME: relative will be better to be fixed. it is too harsh.
3111    if (it->item->rel)
3112      it->item->rel->item->rel_revs =
3113         eina_list_remove(it->item->rel->item->rel_revs, it);
3114    if (it->item->rel_revs)
3115      {
3116         Elm_Gen_Item *tmp;
3117         EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = NULL;
3118      }
3119    _item_subitems_clear(it);
3120
3121 #if GENLIST_ENTRY_SUPPORT
3122    it->item->unrealize_disabled = EINA_FALSE;
3123 #endif
3124
3125    if (it->selected) sd->selected = eina_list_remove(sd->selected, it);
3126    if (sd->show_item == it) sd->show_item = NULL;
3127    if (sd->anchor_item == it)
3128      {
3129         sd->anchor_item =
3130            ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3131         if (!sd->anchor_item)          sd->anchor_item =
3132           ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3133      }
3134    if (sd->expanded_item == it) sd->expanded_item = NULL;
3135    if (sd->expanded_next_item == it) sd->expanded_next_item = NULL;
3136    if (sd->state) eina_inlist_sorted_state_free(sd->state);
3137
3138    if (sd->last_selected_item == (Elm_Object_Item *)it)
3139      sd->last_selected_item = NULL;
3140
3141    if (it->long_timer)
3142      {
3143         ecore_timer_del(it->long_timer);
3144         it->long_timer = NULL;
3145      }
3146    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
3147
3148    sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
3149    sd->item_count--;
3150 }
3151
3152 static void
3153 _item_free(Elm_Gen_Item *it)
3154 {
3155    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
3156
3157 #if GENLIST_FX_SUPPORT
3158    if (sd->fx_mode) GL_IT(it)->has_proxy_it = EINA_FALSE;
3159    _elm_genlist_proxy_item_del((Elm_Object_Item *)it);
3160    if ((!sd->fx_mode) || (sd->genlist_clearing))
3161 #endif
3162      {
3163         _item_free_common(it);
3164      }
3165    _item_unrealize(it, EINA_FALSE);
3166    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
3167    free(it->item);
3168
3169    if (sd->calc_job) ecore_job_del(sd->calc_job);
3170    sd->calc_job = ecore_job_add(_calc_job, sd);
3171 }
3172
3173 #if GENLIST_FX_SUPPORT
3174 static void
3175 _item_del_pre_fx_process(Elm_Gen_Item *it)
3176 {
3177    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
3178
3179    sd->fx_items_deleted = EINA_TRUE;
3180    _elm_genlist_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
3181    if (!eina_list_data_find(sd->pending_del_items, it))
3182      sd->pending_del_items = eina_list_append(sd->pending_del_items, it);
3183
3184    _item_free_common(it);
3185
3186 }
3187 #endif
3188
3189 static void
3190 _item_mouse_move_cb(void *data,
3191                     Evas *evas __UNUSED__,
3192                     Evas_Object *obj,
3193                     void *event_info)
3194 {
3195    EINA_SAFETY_ON_NULL_RETURN(data);
3196    Elm_Gen_Item *it = data;
3197    Elm_Genlist_Smart_Data *sd;
3198    Evas_Event_Mouse_Move *ev = event_info;
3199    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
3200    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
3201
3202    sd = GL_IT(it)->wsd;
3203
3204    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3205      {
3206         if (!sd->on_hold) _item_unselect(it);
3207         sd->on_hold = EINA_TRUE;
3208      }
3209    if (sd->multi_touched)
3210      {
3211         sd->cur_x = ev->cur.canvas.x;
3212         sd->cur_y = ev->cur.canvas.y;
3213         return;
3214      }
3215    if ((it->dragging) && (it->down))
3216      {
3217         if (sd->movements == SWIPE_MOVES)
3218           sd->swipe = EINA_TRUE;
3219         else
3220           {
3221              sd->history[sd->movements].x = ev->cur.canvas.x;
3222              sd->history[sd->movements].y = ev->cur.canvas.y;
3223              if (abs((sd->history[sd->movements].x -
3224                       sd->history[0].x)) > 40)
3225                sd->swipe = EINA_TRUE;
3226              else
3227                sd->movements++;
3228           }
3229         if (it->long_timer)
3230           {
3231              ecore_timer_del(it->long_timer);
3232              it->long_timer = NULL;
3233           }
3234         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
3235         return;
3236      }
3237    if ((!it->down) || (sd->longpressed))
3238      {
3239         if (it->long_timer)
3240           {
3241              ecore_timer_del(it->long_timer);
3242              it->long_timer = NULL;
3243           }
3244         if ((sd->reorder_mode) && (sd->reorder_it))
3245           {
3246              evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
3247
3248              if (ev->cur.canvas.y < (oy + (sd->reorder_it->item->h / 2)))
3249                 sd->reorder_fast = 1;
3250              else if (ev->cur.canvas.y > (oy + oh - (sd->reorder_it->item->h  / 2)))
3251                 sd->reorder_fast = -1;
3252              else sd->reorder_fast = 0;
3253
3254              it_scrl_y = ev->cur.canvas.y - sd->reorder_it->dy;
3255
3256              if (!sd->reorder_start_y)
3257                sd->reorder_start_y = it->item->block->y + it->y;
3258
3259              if (it_scrl_y < oy)
3260                y_pos = oy;
3261              else if (it_scrl_y + sd->reorder_it->item->h > oy + oh)
3262                y_pos = oy + oh - sd->reorder_it->item->h;
3263              else
3264                y_pos = it_scrl_y;
3265
3266              if (it->deco_all_view)
3267                _item_position(it, it->deco_all_view, it->item->scrl_x, y_pos);
3268              else if (it->item->deco_it_view)
3269                _item_position
3270                   (it, it->item->deco_it_view, it->item->scrl_x, y_pos);
3271              else
3272                _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
3273
3274              if (sd->calc_job) ecore_job_del(sd->calc_job);
3275              sd->calc_job = ecore_job_add(_calc_job, sd);
3276           }
3277         return;
3278      }
3279    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3280      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
3281
3282    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3283    x = ev->cur.canvas.x - x;
3284    y = ev->cur.canvas.y - y;
3285    dx = x - it->dx;
3286    adx = dx;
3287    if (adx < 0) adx = -dx;
3288
3289    dy = y - it->dy;
3290    ady = dy;
3291    if (ady < 0) ady = -dy;
3292
3293    minw *= 2;
3294    minh *= 2;
3295    if ((adx > minw) || (ady > minh))
3296      {
3297         it->dragging = EINA_TRUE;
3298         if (it->long_timer)
3299           {
3300              ecore_timer_del(it->long_timer);
3301              it->long_timer = NULL;
3302           }
3303         if (dy < 0)
3304           {
3305              if (ady > adx)
3306                evas_object_smart_callback_call
3307                  (WIDGET(it), SIG_DRAG_START_UP, it);
3308              else
3309                {
3310                   if (dx < 0)
3311                     evas_object_smart_callback_call
3312                       (WIDGET(it), SIG_DRAG_START_LEFT, it);
3313                   else
3314                     evas_object_smart_callback_call
3315                       (WIDGET(it), SIG_DRAG_START_RIGHT, it);
3316                }
3317           }
3318         else
3319           {
3320              if (ady > adx)
3321                evas_object_smart_callback_call
3322                  (WIDGET(it), SIG_DRAG_START_DOWN, it);
3323              else
3324                {
3325                   if (dx < 0)
3326                     evas_object_smart_callback_call
3327                       (WIDGET(it), SIG_DRAG_START_LEFT, it);
3328                   else
3329                     evas_object_smart_callback_call
3330                       (WIDGET(it), SIG_DRAG_START_RIGHT, it);
3331                }
3332           }
3333      }
3334 }
3335
3336 static Eina_Bool
3337 _long_press_cb(void *data)
3338 {
3339    Elm_Gen_Item *it = data, *it2;
3340    Elm_Genlist_Smart_Data *sd;
3341    Eina_List *l, *ll;
3342
3343    sd = GL_IT(it)->wsd;
3344
3345    it->long_timer = NULL;
3346    if (elm_widget_item_disabled_get(it) || (it->dragging) ||
3347        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
3348      return ECORE_CALLBACK_CANCEL;
3349
3350    GL_IT(it)->wsd->longpressed = EINA_TRUE;
3351    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
3352    if ((GL_IT(it)->wsd->reorder_mode) && (!it->group))
3353      {
3354         GL_IT(it)->wsd->reorder_it = it;
3355         GL_IT(it)->wsd->reorder_start_y = 0;
3356         if (it->deco_all_view)
3357           evas_object_raise(it->deco_all_view);
3358         else
3359           evas_object_raise(VIEW(it));
3360
3361         sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_TRUE);
3362         sd->s_iface->bounce_allow_set
3363           (ELM_WIDGET_DATA(sd)->obj, EINA_FALSE, EINA_FALSE);
3364
3365         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, it2)
3366           {
3367              if (it != it2) _item_unselect(it2);
3368           }
3369 #if 0
3370         // FIXME: difference from opensource
3371         if (it->item->items)
3372           {
3373              EINA_LIST_FOREACH(it->item->items, l, it_tmp)
3374                {
3375                   if (elm_genlist_item_expanded_get((Elm_Object_Item *) it_tmp))
3376                     {
3377                        elm_genlist_item_expanded_set((Elm_Object_Item *)it_tmp,
3378                                                      EINA_FALSE);
3379                        return ECORE_CALLBACK_RENEW;
3380                     }
3381                }
3382           }
3383 #endif
3384         if (elm_genlist_item_expanded_get((Elm_Object_Item *)it))
3385           {
3386              elm_genlist_item_expanded_set((Elm_Object_Item *)it, EINA_FALSE);
3387              return ECORE_CALLBACK_RENEW;
3388           }
3389
3390         if (!GL_IT(it)->wsd->decorate_all_mode)
3391           edje_object_signal_emit
3392             (VIEW(it), "elm,state,reorder,enabled", "elm");
3393      }
3394
3395    return ECORE_CALLBACK_CANCEL;
3396 }
3397
3398 static void
3399 _swipe_do(Elm_Gen_Item *it)
3400 {
3401    int i, sum = 0;
3402
3403    if (!it) return;
3404    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
3405        elm_widget_item_disabled_get(it)) return;
3406
3407    GL_IT(it)->wsd->swipe = EINA_FALSE;
3408    for (i = 0; i < GL_IT(it)->wsd->movements; i++)
3409      {
3410         sum += GL_IT(it)->wsd->history[i].x;
3411         if (abs(GL_IT(it)->wsd->history[0].y -
3412                 GL_IT(it)->wsd->history[i].y) > 10) return;
3413      }
3414
3415    sum /= GL_IT(it)->wsd->movements;
3416    if (abs(sum - GL_IT(it)->wsd->history[0].x) <= 10) return;
3417    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
3418 }
3419
3420 static Eina_Bool
3421 _swipe_cancel(void *data)
3422 {
3423    Elm_Gen_Item *it = data;
3424
3425    if (!it) return ECORE_CALLBACK_CANCEL;
3426    GL_IT(it)->wsd->swipe = EINA_FALSE;
3427    GL_IT(it)->wsd->movements = 0;
3428
3429    return ECORE_CALLBACK_RENEW;
3430 }
3431
3432 static Eina_Bool
3433 _multi_cancel(void *data)
3434 {
3435    Elm_Genlist_Smart_Data *sd = data;
3436
3437    if (!sd) return ECORE_CALLBACK_CANCEL;
3438    sd->multi_timeout = EINA_TRUE;
3439
3440    return ECORE_CALLBACK_RENEW;
3441 }
3442
3443 static void
3444 _multi_touch_gesture_eval(void *data)
3445 {
3446    Elm_Gen_Item *it = data;
3447    Evas_Coord minw = 0, minh = 0;
3448    Evas_Coord off_x, off_y, off_mx, off_my;
3449
3450    GL_IT(it)->wsd->multi_touched = EINA_FALSE;
3451    if (GL_IT(it)->wsd->multi_timer)
3452      {
3453         ecore_timer_del(GL_IT(it)->wsd->multi_timer);
3454         GL_IT(it)->wsd->multi_timer = NULL;
3455      }
3456    if (GL_IT(it)->wsd->multi_timeout)
3457      {
3458         GL_IT(it)->wsd->multi_timeout = EINA_FALSE;
3459         return;
3460      }
3461
3462    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
3463    off_x = abs(GL_IT(it)->wsd->cur_x - GL_IT(it)->wsd->prev_x);
3464    off_y = abs(GL_IT(it)->wsd->cur_y - GL_IT(it)->wsd->prev_y);
3465    off_mx = abs(GL_IT(it)->wsd->cur_mx - GL_IT(it)->wsd->prev_mx);
3466    off_my = abs(GL_IT(it)->wsd->cur_my - GL_IT(it)->wsd->prev_my);
3467
3468    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw)
3469                                               || (off_my > minh)))
3470      {
3471         if ((off_x + off_mx) > (off_y + off_my))
3472           {
3473              if ((GL_IT(it)->wsd->cur_x > GL_IT(it)->wsd->prev_x)
3474                  && (GL_IT(it)->wsd->cur_mx > GL_IT(it)->wsd->prev_mx))
3475                evas_object_smart_callback_call
3476                  (WIDGET(it), SIG_MULTI_SWIPE_RIGHT, it);
3477              else if ((GL_IT(it)->wsd->cur_x < GL_IT(it)->wsd->prev_x)
3478                       && (GL_IT(it)->wsd->cur_mx < GL_IT(it)->wsd->prev_mx))
3479                evas_object_smart_callback_call
3480                  (WIDGET(it), SIG_MULTI_SWIPE_LEFT, it);
3481              else if (abs(GL_IT(it)->wsd->cur_x - GL_IT(it)->wsd->cur_mx) >
3482                       abs(GL_IT(it)->wsd->prev_x - GL_IT(it)->wsd->prev_mx))
3483                evas_object_smart_callback_call
3484                  (WIDGET(it), SIG_MULTI_PINCH_OUT, it);
3485              else
3486                evas_object_smart_callback_call
3487                  (WIDGET(it), SIG_MULTI_PINCH_IN, it);
3488           }
3489         else
3490           {
3491              if ((GL_IT(it)->wsd->cur_y > GL_IT(it)->wsd->prev_y)
3492                  && (GL_IT(it)->wsd->cur_my > GL_IT(it)->wsd->prev_my))
3493                evas_object_smart_callback_call
3494                  (WIDGET(it), SIG_MULTI_SWIPE_DOWN, it);
3495              else if ((GL_IT(it)->wsd->cur_y < GL_IT(it)->wsd->prev_y)
3496                       && (GL_IT(it)->wsd->cur_my < GL_IT(it)->wsd->prev_my))
3497                evas_object_smart_callback_call
3498                  (WIDGET(it), SIG_MULTI_SWIPE_UP, it);
3499              else if (abs(GL_IT(it)->wsd->cur_y - GL_IT(it)->wsd->cur_my) >
3500                       abs(GL_IT(it)->wsd->prev_y - GL_IT(it)->wsd->prev_my))
3501                {
3502                   evas_object_smart_callback_call
3503                      (WIDGET(it), SIG_MULTI_PINCH_OUT, it);
3504 #if GENLIST_PINCH_ZOOM_SUPPORT
3505                   if (IS_ROOT_PARENT_IT(it) && (GL_IT(it)->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT))
3506                     {
3507                        elm_genlist_pinch_zoom_mode_set(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj, ELM_GEN_PINCH_ZOOM_EXPAND);
3508                        elm_genlist_item_show((Elm_Object_Item *)it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
3509                     }
3510 #endif
3511                }
3512              else
3513                {
3514                   evas_object_smart_callback_call
3515                      (WIDGET(it), SIG_MULTI_PINCH_IN, it);
3516 #if GENLIST_PINCH_ZOOM_SUPPORT
3517                   elm_genlist_pinch_zoom_mode_set(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj,
3518                                                   ELM_GEN_PINCH_ZOOM_CONTRACT);
3519 #endif
3520                }
3521           }
3522      }
3523
3524    GL_IT(it)->wsd->multi_timeout = EINA_FALSE;
3525 }
3526
3527 static void
3528 _item_multi_down_cb(void *data,
3529                     Evas *evas __UNUSED__,
3530                     Evas_Object *obj __UNUSED__,
3531                     void *event_info)
3532 {
3533    Elm_Gen_Item *it = data;
3534    Evas_Event_Multi_Down *ev = event_info;
3535
3536    if ((GL_IT(it)->wsd->multi_device != 0) || (GL_IT(it)->wsd->multi_touched)
3537        || (GL_IT(it)->wsd->multi_timeout))
3538      return;
3539
3540    GL_IT(it)->wsd->multi_device = ev->device;
3541    GL_IT(it)->wsd->multi_down = EINA_TRUE;
3542    GL_IT(it)->wsd->multi_touched = EINA_TRUE;
3543    GL_IT(it)->wsd->prev_mx = ev->canvas.x;
3544    GL_IT(it)->wsd->prev_my = ev->canvas.y;
3545    /*
3546    if (!GL_IT(it)->wsd->wasselected)
3547      _item_unselect(it);
3548    GL_IT(it)->wsd->wasselected = EINA_FALSE;
3549      */
3550    if (it->long_timer)
3551      {
3552         ecore_timer_del(it->long_timer);
3553         it->long_timer = NULL;
3554      }
3555    if (it->dragging)
3556      {
3557         it->dragging = EINA_FALSE;
3558         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
3559      }
3560    if (it->item->swipe_timer)
3561      {
3562         ecore_timer_del(it->item->swipe_timer);
3563         it->item->swipe_timer = NULL;
3564      }
3565    GL_IT(it)->wsd->longpressed = EINA_FALSE;
3566    if (GL_IT(it)->wsd->on_hold)
3567      {
3568         GL_IT(it)->wsd->swipe = EINA_FALSE;
3569         GL_IT(it)->wsd->movements = 0;
3570         GL_IT(it)->wsd->on_hold = EINA_FALSE;
3571      }
3572 }
3573
3574 static void
3575 _item_multi_up_cb(void *data,
3576                   Evas *evas __UNUSED__,
3577                   Evas_Object *obj __UNUSED__,
3578                   void *event_info)
3579 {
3580    Elm_Gen_Item *it = data;
3581    Evas_Event_Multi_Up *ev = event_info;
3582
3583    if (GL_IT(it)->wsd->multi_device != ev->device) return;
3584    GL_IT(it)->wsd->multi_device = 0;
3585    GL_IT(it)->wsd->multi_down = EINA_FALSE;
3586    if (GL_IT(it)->wsd->mouse_down) return;
3587    _multi_touch_gesture_eval(data);
3588 }
3589
3590 static void
3591 _item_multi_move_cb(void *data,
3592                     Evas *evas __UNUSED__,
3593                     Evas_Object *obj __UNUSED__,
3594                     void *event_info)
3595 {
3596    Elm_Gen_Item *it = data;
3597    Evas_Event_Multi_Move *ev = event_info;
3598
3599    if (GL_IT(it)->wsd->multi_device != ev->device) return;
3600    GL_IT(it)->wsd->cur_mx = ev->cur.canvas.x;
3601    GL_IT(it)->wsd->cur_my = ev->cur.canvas.y;
3602 }
3603
3604 #if 0
3605 // FIXME: difference from upstream
3606 static void
3607 _item_unfocusable_set(Elm_Gen_Item *it, Eina_Bool unfocus)
3608 {
3609    Eina_List *l;
3610    Evas_Object *item_obj;
3611    Evas_Object *obj = WIDGET(it);
3612
3613    if (!it->can_focus)
3614      {
3615         EINA_LIST_FOREACH(it->content_objs, l, item_obj)
3616           {
3617             if (unfocus) elm_widget_focused_object_clear(item_obj);
3618             elm_widget_tree_unfocusable_set(item_obj, unfocus);
3619           }
3620         EINA_LIST_FOREACH(it->item->flip_content_objs, l, item_obj)
3621           {
3622              if (unfocus) elm_widget_focused_object_clear(item_obj);
3623              elm_widget_tree_unfocusable_set(item_obj, unfocus);
3624           }
3625         EINA_LIST_FOREACH(it->item->deco_all_content_objs, l, item_obj)
3626           {
3627              if (unfocus) elm_widget_focused_object_clear(item_obj);
3628              elm_widget_tree_unfocusable_set(item_obj, unfocus);
3629           }
3630         it->can_focus = !unfocus;
3631      }
3632 }
3633 #endif
3634
3635 static void
3636 _item_mouse_down_cb(void *data,
3637                     Evas *evas __UNUSED__,
3638                     Evas_Object *obj,
3639                     void *event_info)
3640 {
3641    Evas_Event_Mouse_Down *ev = event_info;
3642    Elm_Gen_Item *it = data;
3643    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
3644    Evas_Coord x, y;
3645
3646    if (ev->button != 1) return;
3647 #if 0
3648    _item_unfocusable_set(it, EINA_FALSE);
3649 #endif
3650    it->down = EINA_TRUE;
3651    it->dragging = EINA_FALSE;
3652    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3653    it->dx = ev->canvas.x - x;
3654    it->dy = ev->canvas.y - y;
3655    sd->mouse_down = EINA_TRUE;
3656    if (!sd->multi_touched)
3657      {
3658         sd->prev_x = ev->canvas.x;
3659         sd->prev_y = ev->canvas.y;
3660         sd->multi_timeout = EINA_FALSE;
3661         if (sd->multi_timer) ecore_timer_del(sd->multi_timer);
3662         sd->multi_timer = ecore_timer_add(1, _multi_cancel, sd);
3663      }
3664    sd->longpressed = EINA_FALSE;
3665    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3666      {
3667         sd->on_hold = EINA_TRUE;
3668         return;
3669      }
3670    else sd->on_hold = EINA_FALSE;
3671    _item_highlight(it);
3672    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
3673      if ((!elm_widget_item_disabled_get(it)) &&
3674          (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
3675        {
3676           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
3677           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
3678        }
3679    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
3680    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
3681    if (it->long_timer) ecore_timer_del(it->long_timer);
3682    if (it->realized)
3683      it->long_timer = ecore_timer_add
3684          (sd->longpress_timeout, _long_press_cb, it);
3685    else
3686      it->long_timer = NULL;
3687    sd->swipe = EINA_FALSE;
3688    sd->movements = 0;
3689 }
3690
3691 static Item_Block *
3692 _item_block_new(Elm_Genlist_Smart_Data *sd,
3693                 Eina_Bool prepend)
3694 {
3695    Item_Block *itb;
3696
3697    itb = calloc(1, sizeof(Item_Block));
3698    if (!itb) return NULL;
3699    itb->sd = sd;
3700    if (prepend)
3701      {
3702         sd->blocks = eina_inlist_prepend(sd->blocks, EINA_INLIST_GET(itb));
3703         _item_block_position_update(sd->blocks, 0);
3704      }
3705    else
3706      {
3707         sd->blocks = eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
3708         itb->position_update = EINA_TRUE;
3709         if (sd->blocks != EINA_INLIST_GET(itb))
3710           {
3711              itb->position =
3712                ((Item_Block *)(EINA_INLIST_GET(itb)->prev))->position + 1;
3713           }
3714         else
3715           {
3716              itb->position = 0;
3717           }
3718      }
3719
3720    return itb;
3721 }
3722
3723 static Eina_Bool
3724 _item_block_add(Elm_Genlist_Smart_Data *sd,
3725                 Elm_Gen_Item *it)
3726 {
3727    Item_Block *itb = NULL;
3728
3729    if (!it->item->rel)
3730      {
3731 newblock:
3732         if (it->item->rel)
3733           {
3734              itb = calloc(1, sizeof(Item_Block));
3735              if (!itb) return EINA_FALSE;
3736              itb->sd = sd;
3737              if (!it->item->rel->item->block)
3738                {
3739                   sd->blocks =
3740                     eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
3741                   itb->items = eina_list_append(itb->items, it);
3742                   itb->position_update = EINA_TRUE;
3743                   it->position = eina_list_count(itb->items);
3744                   it->position_update = EINA_TRUE;
3745
3746                   if (sd->blocks != EINA_INLIST_GET(itb))
3747                     {
3748                        itb->position =
3749                          ((Item_Block *)
3750                           (EINA_INLIST_GET(itb)->prev))->position + 1;
3751                     }
3752                   else
3753                     {
3754                        itb->position = 0;
3755                     }
3756                }
3757              else
3758                {
3759                   Eina_List *tmp;
3760
3761                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3762                   if (it->item->before)
3763                     {
3764                        sd->blocks = eina_inlist_prepend_relative
3765                            (sd->blocks, EINA_INLIST_GET(itb),
3766                            EINA_INLIST_GET(it->item->rel->item->block));
3767                        itb->items =
3768                          eina_list_prepend_relative_list(itb->items, it, tmp);
3769
3770                        /* Update index from where we prepended */
3771                        _item_position_update
3772                          (eina_list_prev(tmp), it->item->rel->position);
3773                        _item_block_position_update
3774                          (EINA_INLIST_GET(itb),
3775                          it->item->rel->item->block->position);
3776                     }
3777                   else
3778                     {
3779                        sd->blocks = eina_inlist_append_relative
3780                            (sd->blocks, EINA_INLIST_GET(itb),
3781                            EINA_INLIST_GET(it->item->rel->item->block));
3782                        itb->items =
3783                          eina_list_append_relative_list(itb->items, it, tmp);
3784
3785                        /* Update block index from where we appended */
3786                        _item_position_update
3787                          (eina_list_next(tmp), it->item->rel->position + 1);
3788                        _item_block_position_update
3789                          (EINA_INLIST_GET(itb),
3790                          it->item->rel->item->block->position + 1);
3791                     }
3792                }
3793           }
3794         else
3795           {
3796              if (it->item->before)
3797                {
3798                   if (sd->blocks)
3799                     {
3800                        itb = (Item_Block *)(sd->blocks);
3801                        if (itb->count >= sd->max_items_per_block)
3802                          {
3803                             itb = _item_block_new(sd, EINA_TRUE);
3804                             if (!itb) return EINA_FALSE;
3805                          }
3806                     }
3807                   else
3808                     {
3809                        itb = _item_block_new(sd, EINA_TRUE);
3810                        if (!itb) return EINA_FALSE;
3811                     }
3812                   itb->items = eina_list_prepend(itb->items, it);
3813
3814                   _item_position_update(itb->items, 0);
3815                }
3816              else
3817                {
3818                   if (sd->blocks)
3819                     {
3820                        itb = (Item_Block *)(sd->blocks->last);
3821                        if (itb->count >= sd->max_items_per_block)
3822                          {
3823                             itb = _item_block_new(sd, EINA_FALSE);
3824                             if (!itb) return EINA_FALSE;
3825                          }
3826                     }
3827                   else
3828                     {
3829                        itb = _item_block_new(sd, EINA_FALSE);
3830                        if (!itb) return EINA_FALSE;
3831                     }
3832                   itb->items = eina_list_append(itb->items, it);
3833                   it->position = eina_list_count(itb->items);
3834                }
3835           }
3836      }
3837    else
3838      {
3839         Eina_List *tmp;
3840
3841         if (it->item->rel->item->queued)
3842           {
3843              /* NOTE: for a strange reason eina_list and eina_inlist
3844                 don't have the same property on sorted insertion
3845                 order, so the queue is not always ordered like the
3846                 item list.  This lead to issue where we depend on an
3847                 item that is not yet created. As a quick work around,
3848                 we reschedule the calc of the item and stop reordering
3849                 the list to prevent any nasty issue to show up here.
3850               */
3851              sd->queue = eina_list_append(sd->queue, it);
3852              sd->requeued = EINA_TRUE;
3853              it->item->queued = EINA_TRUE;
3854
3855              return EINA_FALSE;
3856           }
3857         itb = it->item->rel->item->block;
3858         if (!itb) goto newblock;
3859         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3860         if (it->item->before)
3861           {
3862              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3863              _item_position_update
3864                (eina_list_prev(tmp), it->item->rel->position);
3865           }
3866         else
3867           {
3868              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3869              _item_position_update
3870                (eina_list_next(tmp), it->item->rel->position + 1);
3871           }
3872      }
3873
3874    itb->count++;
3875    itb->changed = EINA_TRUE;
3876    it->item->block = itb;
3877    if (itb->sd->calc_job) ecore_job_del(itb->sd->calc_job);
3878    itb->sd->calc_job = ecore_job_add(_calc_job, itb->sd);
3879 /*
3880    if (it->item->rel)
3881      {
3882         it->item->rel->relcount--;
3883         // FIXME: relcount should be removed.
3884         if (((Elm_Widget_Item *)it->item->rel)->on_deletion &&
3885             (!it->item->rel->relcount))
3886           {
3887              elm_widget_item_del(it->item->rel);
3888           }
3889         it->item->rel = NULL;
3890      }
3891 */
3892    if (itb->count > itb->sd->max_items_per_block)
3893      {
3894         int newc;
3895         Item_Block *itb2;
3896         Elm_Gen_Item *it2;
3897         Eina_Bool done = EINA_FALSE;
3898
3899         newc = itb->count / 2;
3900
3901         if (EINA_INLIST_GET(itb)->prev)
3902           {
3903              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3904
3905              if (itbp->count + newc < sd->max_items_per_block / 2)
3906                {
3907                   /* moving items to previous block */
3908                   while ((itb->count > newc) && (itb->items))
3909                     {
3910                        it2 = eina_list_data_get(itb->items);
3911                        itb->items = eina_list_remove_list
3912                            (itb->items, itb->items);
3913                        itb->count--;
3914
3915                        itbp->items = eina_list_append(itbp->items, it2);
3916                        it2->item->block = itbp;
3917                        itbp->count++;
3918                     }
3919
3920                   done = EINA_TRUE;
3921                }
3922           }
3923
3924         if (!done && EINA_INLIST_GET(itb)->next)
3925           {
3926              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3927
3928              if (itbn->count + newc < sd->max_items_per_block / 2)
3929                {
3930                   /* moving items to next block */
3931                   while ((itb->count > newc) && (itb->items))
3932                     {
3933                        Eina_List *l;
3934
3935                        l = eina_list_last(itb->items);
3936                        it2 = eina_list_data_get(l);
3937                        itb->items = eina_list_remove_list(itb->items, l);
3938                        itb->count--;
3939
3940                        itbn->items = eina_list_prepend(itbn->items, it2);
3941                        it2->item->block = itbn;
3942                        itbn->count++;
3943                     }
3944
3945                   done = EINA_TRUE;
3946                }
3947           }
3948
3949         if (!done)
3950           {
3951              /* moving items to new block */
3952              itb2 = calloc(1, sizeof(Item_Block));
3953              if (!itb2) return EINA_FALSE;
3954              itb2->sd = sd;
3955              sd->blocks =
3956                eina_inlist_append_relative(sd->blocks, EINA_INLIST_GET(itb2),
3957                                            EINA_INLIST_GET(itb));
3958              itb2->changed = EINA_TRUE;
3959              while ((itb->count > newc) && (itb->items))
3960                {
3961                   Eina_List *l;
3962
3963                   l = eina_list_last(itb->items);
3964                   it2 = l->data;
3965                   itb->items = eina_list_remove_list(itb->items, l);
3966                   itb->count--;
3967
3968                   itb2->items = eina_list_prepend(itb2->items, it2);
3969                   it2->item->block = itb2;
3970                   itb2->count++;
3971                }
3972           }
3973      }
3974
3975    return EINA_TRUE;
3976 }
3977
3978 static int
3979 _item_process(Elm_Genlist_Smart_Data *sd,
3980               Elm_Gen_Item *it)
3981 {
3982    if (!_item_block_add(sd, it)) return 1;
3983    if (!sd->blocks)
3984      _item_block_realize(it->item->block);
3985
3986    return 0;
3987 }
3988
3989 static void
3990 _item_process_post(Elm_Genlist_Smart_Data *sd,
3991                    Elm_Gen_Item *it,
3992                    Eina_Bool qadd)
3993 {
3994    Eina_Bool show_me = EINA_FALSE;
3995
3996    if (it->item->block->changed)
3997      {
3998         show_me = _item_block_recalc
3999             (it->item->block, it->item->block->num, qadd);
4000         it->item->block->changed = 0;
4001         if (sd->pan_changed)
4002           {
4003              if (sd->calc_job) ecore_job_del(sd->calc_job);
4004              sd->calc_job = NULL;
4005              _calc_job(sd);
4006              sd->pan_changed = EINA_FALSE;
4007           }
4008      }
4009    if (show_me) it->item->block->show_me = EINA_TRUE;
4010
4011    /* when prepending, move the scroller along with the first selected
4012     * item to create the illusion that we're watching the selected
4013     * item this prevents the selected item being scrolled off the
4014     * viewport
4015     */
4016    if (sd->selected && it->item->before)
4017      {
4018         int y, h;
4019         Elm_Gen_Item *it2;
4020
4021         it2 = sd->selected->data;
4022         if (!it2->item->block) return;
4023         sd->s_iface->content_pos_get(ELM_WIDGET_DATA(sd)->obj, NULL, &y);
4024         evas_object_geometry_get(sd->pan_obj, NULL, NULL, NULL, &h);
4025         if ((it->y + it->item->block->y > y + h) ||
4026             (it->y + it->item->block->y + it->item->h < y))
4027           /* offscreen, just update */
4028           sd->s_iface->content_region_show
4029             (ELM_WIDGET_DATA(sd)->obj, it2->x + it2->item->block->x, y,
4030             it2->item->block->w, h);
4031         else
4032           sd->s_iface->content_region_show
4033             (ELM_WIDGET_DATA(sd)->obj, it->x + it->item->block->x,
4034             y + it->item->h, it->item->block->w, h);
4035      }
4036 }
4037
4038 static int
4039 _queue_process(Elm_Genlist_Smart_Data *sd)
4040 {
4041    int n;
4042    double t0, t;
4043
4044    t0 = ecore_loop_time_get();
4045    for (n = 0; (sd->queue) && (n < 128); n++)
4046      {
4047         Elm_Gen_Item *it;
4048
4049         it = eina_list_data_get(sd->queue);
4050         sd->queue = eina_list_remove_list(sd->queue, sd->queue);
4051         it->item->queued = EINA_FALSE;
4052         if (_item_process(sd, it)) continue;
4053         t = ecore_time_get();
4054         _item_process_post(sd, it, EINA_TRUE);
4055         /* same as eina_inlist_count > 1 */
4056         if (sd->blocks && sd->blocks->next)
4057           {
4058              if ((t - t0) > (ecore_animator_frametime_get())) break;
4059           }
4060      }
4061    return n;
4062 }
4063
4064 static Eina_Bool
4065 _idle_process(void *data,
4066               Eina_Bool *wakeup)
4067 {
4068    Elm_Genlist_Smart_Data *sd = data;
4069
4070    if (_queue_process(sd) > 0) *wakeup = EINA_TRUE;
4071    if (!sd->queue)
4072      {
4073         return ECORE_CALLBACK_CANCEL;
4074      }
4075 #if GENLIST_FX_SUPPORT
4076    if (sd->fx_first_captured)
4077      _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj);
4078 #endif
4079    return ECORE_CALLBACK_RENEW;
4080 }
4081
4082 static Eina_Bool
4083 _item_idle_enterer(void *data)
4084 {
4085    Eina_Bool wakeup = EINA_FALSE;
4086    Elm_Genlist_Smart_Data *sd = data;
4087    Eina_Bool ok = _idle_process(data, &wakeup);
4088
4089    if (wakeup)
4090      {
4091         // wake up mainloop
4092         if (sd->calc_job) ecore_job_del(sd->calc_job);
4093         sd->calc_job = ecore_job_add(_calc_job, sd);
4094      }
4095    if (ok == ECORE_CALLBACK_CANCEL) sd->queue_idle_enterer = NULL;
4096
4097    return ok;
4098 }
4099
4100 static void
4101 _item_queue(Elm_Genlist_Smart_Data *sd,
4102             Elm_Gen_Item *it,
4103             Eina_Compare_Cb cb)
4104 {
4105    if (it->item->queued) return;
4106    it->item->queued = EINA_TRUE;
4107    if (cb && !sd->requeued)
4108      sd->queue = eina_list_sorted_insert(sd->queue, cb, it);
4109    else
4110      sd->queue = eina_list_append(sd->queue, it);
4111 // FIXME: why does a freeze then thaw here cause some genlist
4112 // elm_genlist_item_append() to be much much slower?
4113 //   evas_event_freeze(evas_object_evas_get(sd->obj));
4114    while ((sd->queue) && ((!sd->blocks) || (!sd->blocks->next)))
4115      {
4116         if (sd->queue_idle_enterer)
4117           {
4118              ecore_idle_enterer_del(sd->queue_idle_enterer);
4119              sd->queue_idle_enterer = NULL;
4120           }
4121         _queue_process(sd);
4122      }
4123    while ((sd->queue) && (sd->blocks) &&
4124           (sd->homogeneous) && (sd->mode == ELM_LIST_COMPRESS))
4125      {
4126         if (sd->queue_idle_enterer)
4127           {
4128              ecore_idle_enterer_del(sd->queue_idle_enterer);
4129              sd->queue_idle_enterer = NULL;
4130           }
4131         _queue_process(sd);
4132      }
4133
4134 //   evas_event_thaw(evas_object_evas_get(sd->obj));
4135 //   evas_event_thaw_eval(evas_object_evas_get(sd->obj));
4136    if (!sd->queue_idle_enterer)
4137      sd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, sd);
4138 }
4139
4140 /* If the application wants to know the relative item, use
4141  * elm_genlist_item_prev_get(it)*/
4142 static void
4143 _item_move_after(Elm_Gen_Item *it,
4144                  Elm_Gen_Item *after)
4145 {
4146    if (!it) return;
4147    if (!after) return;
4148    if (it == after) return;
4149
4150    GL_IT(it)->wsd->items =
4151      eina_inlist_remove(GL_IT(it)->wsd->items, EINA_INLIST_GET(it));
4152    if (it->item->block) _item_block_del(it);
4153
4154    GL_IT(it)->wsd->items = eina_inlist_append_relative
4155        (GL_IT(it)->wsd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4156    it->item->rel = after;
4157    after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
4158    it->item->before = EINA_FALSE;
4159    if (after->item->group_item) it->item->group_item = after->item->group_item;
4160    _item_queue(GL_IT(it)->wsd, it, NULL);
4161
4162    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_AFTER, it);
4163 }
4164
4165 static void
4166 _access_activate_cb(void *data __UNUSED__,
4167                     Evas_Object *part_obj __UNUSED__,
4168                     Elm_Object_Item *item)
4169 {
4170    _item_select_unselect((Elm_Gen_Item *)item, EINA_TRUE);
4171 }
4172
4173 /* If the application wants to know the relative item, use
4174  * elm_genlist_item_next_get(it)*/
4175 static void
4176 _item_move_before(Elm_Gen_Item *it,
4177                   Elm_Gen_Item *before)
4178 {
4179    if (!it) return;
4180    if (!before) return;
4181    if (it == before) return;
4182
4183    GL_IT(it)->wsd->items =
4184      eina_inlist_remove(GL_IT(it)->wsd->items, EINA_INLIST_GET(it));
4185    if (it->item->block) _item_block_del(it);
4186    GL_IT(it)->wsd->items = eina_inlist_prepend_relative
4187        (GL_IT(it)->wsd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4188    it->item->rel = before;
4189    before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
4190    it->item->before = EINA_TRUE;
4191    if (before->item->group_item)
4192      it->item->group_item = before->item->group_item;
4193    _item_queue(GL_IT(it)->wsd, it, NULL);
4194
4195    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_BEFORE, it);
4196 }
4197
4198 static void
4199 _item_mouse_up_cb(void *data,
4200                   Evas *evas __UNUSED__,
4201                   Evas_Object *obj __UNUSED__,
4202                   void *event_info)
4203 {
4204    Evas_Event_Mouse_Up *ev = event_info;
4205    Eina_Bool dragged = EINA_FALSE;
4206    Elm_Genlist_Smart_Data *sd;
4207    Elm_Gen_Item *it = data;
4208
4209    if (ev->button != 1) return;
4210    it->down = EINA_FALSE;
4211    sd = GL_IT(it)->wsd;
4212
4213    sd->mouse_down = EINA_FALSE;
4214    if (sd->multi_touched)
4215      {
4216         if ((!sd->multi) && (!it->selected) && (it->highlighted))
4217           _item_unhighlight(it);
4218         if (sd->multi_down) return;
4219         _multi_touch_gesture_eval(data);
4220         return;
4221      }
4222    if (it->long_timer)
4223      {
4224         ecore_timer_del(it->long_timer);
4225         it->long_timer = NULL;
4226      }
4227    if (it->dragging)
4228      {
4229         it->dragging = EINA_FALSE;
4230         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
4231         dragged = 1;
4232      }
4233    if (it->item->swipe_timer)
4234      {
4235         ecore_timer_del(it->item->swipe_timer);
4236         it->item->swipe_timer = NULL;
4237      }
4238    if (sd->multi_timer)
4239      {
4240         ecore_timer_del(sd->multi_timer);
4241         sd->multi_timer = NULL;
4242         sd->multi_timeout = EINA_FALSE;
4243      }
4244    sd->on_hold = EINA_FALSE;
4245    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
4246      {
4247         if (sd->swipe) _swipe_do(data);
4248         sd->longpressed = EINA_FALSE;
4249         return;
4250      }
4251    if ((sd->reorder_mode) && (sd->reorder_it))
4252      {
4253         Evas_Coord it_scrl_y = ev->canvas.y - sd->reorder_it->dy;
4254         sd->reorder_fast = 0;
4255
4256         if (sd->reorder_rel &&
4257             (sd->reorder_it->parent == sd->reorder_rel->parent))
4258           {
4259              if (it_scrl_y <= sd->reorder_rel->item->scrl_y)
4260                _item_move_before(sd->reorder_it, sd->reorder_rel);
4261              else
4262                _item_move_after(sd->reorder_it, sd->reorder_rel);
4263              evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4264           }
4265         else
4266           {
4267              if (sd->calc_job) ecore_job_del(sd->calc_job);
4268              sd->calc_job = ecore_job_add(_calc_job, sd);
4269           }
4270         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
4271         sd->reorder_it = sd->reorder_rel = NULL;
4272         sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
4273         sd->s_iface->bounce_allow_set
4274           (ELM_WIDGET_DATA(sd)->obj, sd->h_bounce, sd->v_bounce);
4275      }
4276    if (dragged)
4277      {
4278         if (it->want_unrealize && !(it->item->unrealize_disabled))
4279           {
4280              _item_unrealize(it, EINA_FALSE);
4281              if (it->item->block->want_unrealize)
4282                _item_block_unrealize(it->item->block);
4283           }
4284         return;
4285      }
4286
4287    if (!sd->longpressed)
4288      if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) ||
4289               (it->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS))
4290               _item_select_unselect(it, EINA_TRUE);
4291      else _item_select_unselect(it, !it->selected);
4292    else
4293      _item_unhighlight(it);
4294 }
4295
4296 static void
4297 _item_mouse_callbacks_add(Elm_Gen_Item *it,
4298                           Evas_Object *view)
4299 {
4300    evas_object_event_callback_add
4301      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
4302    evas_object_event_callback_add
4303      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
4304    evas_object_event_callback_add
4305      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
4306    evas_object_event_callback_add
4307      (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
4308    evas_object_event_callback_add
4309      (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
4310    evas_object_event_callback_add
4311      (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
4312 }
4313
4314 static void
4315 _item_mouse_callbacks_del(Elm_Gen_Item *it,
4316                           Evas_Object *view)
4317 {
4318    evas_object_event_callback_del_full
4319      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
4320    evas_object_event_callback_del_full
4321      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
4322    evas_object_event_callback_del_full
4323      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
4324    evas_object_event_callback_del_full
4325      (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
4326    evas_object_event_callback_del_full
4327      (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
4328    evas_object_event_callback_del_full
4329      (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
4330 }
4331
4332 static Eina_Bool
4333 _scroll_hold_timer_cb(void *data)
4334 {
4335    Elm_Genlist_Smart_Data *sd = data;
4336
4337    if (!data) return ECORE_CALLBACK_CANCEL;
4338
4339    sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
4340    sd->scr_hold_timer = NULL;
4341
4342    return ECORE_CALLBACK_CANCEL;
4343 }
4344
4345 static void
4346 _decorate_item_finished_signal_cb(void *data,
4347                                   Evas_Object *obj,
4348                                   const char *emission __UNUSED__,
4349                                   const char *source __UNUSED__)
4350 {
4351    Elm_Gen_Item *it = data;
4352    char buf[1024];
4353
4354    if (!data || !obj) return;
4355    if ((!it->realized) || (!it->item->deco_it_view)) return;
4356
4357    it->item->nocache_once = EINA_FALSE;
4358    _decorate_item_unrealize(it);
4359    if (it->item->group_item)
4360      evas_object_raise(it->item->VIEW(group_item));
4361
4362    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished",
4363             GL_IT(it)->wsd->decorate_it_type);
4364    edje_object_signal_callback_del_full
4365      (obj, buf, "elm", _decorate_item_finished_signal_cb, it);
4366 }
4367
4368 static Eina_List *
4369 _item_mode_content_unrealize(Elm_Gen_Item *it,
4370                              Evas_Object *target,
4371                              Eina_List **source,
4372                              const char *parts,
4373                              Eina_List **contents_list)
4374 {
4375    Eina_List *res = *contents_list;
4376
4377    if (it->itc->func.content_get)
4378      {
4379         const Eina_List *l;
4380         const char *key;
4381         Evas_Object *ic = NULL;
4382
4383         EINA_LIST_FOREACH(*source, l, key)
4384           {
4385              if (parts && fnmatch(parts, key, FNM_PERIOD))
4386                continue;
4387
4388              ic = edje_object_part_swallow_get(target, key);
4389              if (ic)
4390                {
4391                   res = eina_list_remove(res, ic);
4392                   edje_object_part_unswallow(target, ic);
4393                   evas_object_del(ic);
4394                }
4395           }
4396      }
4397
4398    return res;
4399 }
4400
4401 static Eina_List *
4402 _item_content_unrealize(Elm_Gen_Item *it,
4403                         Evas_Object *target,
4404                         Eina_List **source,
4405                         const char *parts)
4406 {
4407    Eina_List *res = it->content_objs;
4408
4409    if (it->itc->func.content_get)
4410      {
4411         const Eina_List *l;
4412         const char *key;
4413         Evas_Object *ic = NULL;
4414
4415         EINA_LIST_FOREACH(*source, l, key)
4416           {
4417              if (parts && fnmatch(parts, key, FNM_PERIOD))
4418                continue;
4419
4420              ic = edje_object_part_swallow_get(target, key);
4421              if (ic)
4422                {
4423                   res = eina_list_remove(res, ic);
4424                   edje_object_part_unswallow(target, ic);
4425                   // FIXME: If parent-child relationship was broken before 'ic'
4426                   // is deleted, freeze_pop will not be called. ex) elm_slider
4427                   // If layout is used instead of edje, this problme can be
4428                   // solved.
4429                   if (0 != elm_widget_scroll_freeze_get(ic))
4430                     elm_widget_scroll_freeze_pop(ic);
4431                   evas_object_del(ic);
4432                }
4433           }
4434      }
4435
4436    return res;
4437 }
4438
4439 static Eina_Bool
4440 _item_block_recalc(Item_Block *itb,
4441                    int in,
4442                    Eina_Bool qadd)
4443 {
4444    const Eina_List *l, *ll;
4445    Elm_Gen_Item *it;
4446    Evas_Coord minw = 0, minh = 0;
4447    Eina_Bool show_me = EINA_FALSE, changed = EINA_FALSE;
4448    Evas_Coord y = 0;
4449
4450    itb->num = in;
4451    EINA_LIST_FOREACH_SAFE(itb->items, l, ll, it)
4452      {
4453         show_me |= it->item->show_me;
4454         if (!itb->realized)
4455           {
4456              if (qadd)
4457                {
4458                   if (!it->item->mincalcd) changed = EINA_TRUE;
4459                   if (changed)
4460                     {
4461                        _item_realize(it, in, EINA_TRUE);
4462                        _item_unrealize(it, EINA_TRUE);
4463                     }
4464                }
4465              else
4466                {
4467                   if ((itb->sd->homogeneous) &&
4468                       (itb->sd->mode == ELM_LIST_COMPRESS))
4469                     {
4470                        if (it->group)
4471                          {
4472                             it->item->w = it->item->minw =
4473                                 GL_IT(it)->wsd->group_item_width;
4474                             it->item->h = it->item->minh =
4475                                 GL_IT(it)->wsd->group_item_height;
4476                          }
4477                        else
4478                          {
4479                             it->item->w = it->item->minw =
4480                                 GL_IT(it)->wsd->item_width;
4481                             it->item->h = it->item->minh =
4482                                 GL_IT(it)->wsd->item_height;
4483                          }
4484                     }
4485                   else
4486                     {
4487                        _item_realize(it, in, EINA_TRUE);
4488                        _item_unrealize(it, EINA_TRUE);
4489                     }
4490                }
4491           }
4492         else
4493           {
4494              if (!it->item->mincalcd) changed = EINA_TRUE;
4495              _item_realize(it, in, EINA_FALSE);
4496           }
4497         minh += it->item->minh;
4498         if (minw < it->item->minw) minw = it->item->minw;
4499         in++;
4500         it->x = 0;
4501         it->y = y;
4502 #if GENLIST_PINCH_ZOOM_SUPPORT
4503         if (IS_ROOT_PARENT_IT(it))
4504           it->item->pan_scrl_y = itb->y + it->y;
4505 #endif
4506         y += it->item->h;
4507      }
4508    if (changed) itb->sd->pan_changed = changed;
4509    itb->minw = minw;
4510    itb->minh = minh;
4511    itb->changed = EINA_FALSE;
4512    itb->position_update = EINA_FALSE;
4513
4514    return show_me;
4515 }
4516
4517 static void
4518 _update_job(void *data)
4519 {
4520    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
4521    Elm_Genlist_Smart_Data *sd = data;
4522    Item_Block *itb;
4523    Eina_List *l2;
4524    int num, num0;
4525
4526    sd->update_job = NULL;
4527    num = 0;
4528
4529    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4530    EINA_INLIST_FOREACH(sd->blocks, itb)
4531      {
4532         Evas_Coord itminw, itminh;
4533         Elm_Gen_Item *it;
4534
4535         if (!itb->updateme)
4536           {
4537              num += itb->count;
4538              if (position)
4539                _item_block_position(itb, num);
4540              continue;
4541           }
4542         num0 = num;
4543         recalc = EINA_FALSE;
4544         EINA_LIST_FOREACH(itb->items, l2, it)
4545           {
4546              if (it->item->updateme)
4547                {
4548                   itminw = it->item->minw;
4549                   itminh = it->item->minh;
4550
4551                   it->item->updateme = EINA_FALSE;
4552                   if (it->realized)
4553                     {
4554                        _item_unrealize(it, EINA_FALSE);
4555                        _item_realize(it, num, EINA_FALSE);
4556                        position = EINA_TRUE;
4557                     }
4558                   else
4559                     {
4560                        _item_realize(it, num, EINA_TRUE);
4561                        _item_unrealize(it, EINA_TRUE);
4562                     }
4563                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
4564                     recalc = EINA_TRUE;
4565                }
4566              num++;
4567           }
4568         itb->updateme = EINA_FALSE;
4569         if (recalc)
4570           {
4571              position = EINA_TRUE;
4572              itb->changed = EINA_TRUE;
4573              _item_block_recalc(itb, num0, EINA_FALSE);
4574              _item_block_position(itb, num0);
4575           }
4576      }
4577    if (position)
4578      {
4579         if (sd->calc_job) ecore_job_del(sd->calc_job);
4580         sd->calc_job = ecore_job_add(_calc_job, sd);
4581      }
4582    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4583    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4584 }
4585
4586 static void
4587 _scroll_animate_start_cb(Evas_Object *obj,
4588                          void *data __UNUSED__)
4589 {
4590    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
4591 }
4592
4593 static void
4594 _scroll_animate_stop_cb(Evas_Object *obj,
4595                         void *data __UNUSED__)
4596 {
4597    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
4598 }
4599
4600 static void
4601 _scroll_drag_start_cb(Evas_Object *obj,
4602                       void *data __UNUSED__)
4603 {
4604    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_START, NULL);
4605 }
4606
4607 static void
4608 _scroll_drag_stop_cb(Evas_Object *obj,
4609                      void *data __UNUSED__)
4610 {
4611    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_STOP, NULL);
4612 }
4613
4614 static void
4615 _edge_left_cb(Evas_Object *obj,
4616               void *data __UNUSED__)
4617 {
4618    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
4619 }
4620
4621 static void
4622 _edge_right_cb(Evas_Object *obj,
4623                void *data __UNUSED__)
4624 {
4625    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
4626 }
4627
4628 static void
4629 _edge_top_cb(Evas_Object *obj,
4630              void *data __UNUSED__)
4631 {
4632    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
4633 }
4634
4635 static void
4636 _edge_bottom_cb(Evas_Object *obj,
4637                 void *data __UNUSED__)
4638 {
4639    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
4640 }
4641
4642 static void
4643 _vbar_drag_cb(Evas_Object *obj,
4644                 void *data __UNUSED__)
4645 {
4646    evas_object_smart_callback_call(obj, SIG_VBAR_DRAG, NULL);
4647 }
4648
4649 static void
4650 _vbar_press_cb(Evas_Object *obj,
4651                 void *data __UNUSED__)
4652 {
4653    evas_object_smart_callback_call(obj, SIG_VBAR_PRESS, NULL);
4654 }
4655
4656 static void
4657 _vbar_unpress_cb(Evas_Object *obj,
4658                 void *data __UNUSED__)
4659 {
4660    evas_object_smart_callback_call(obj, SIG_VBAR_UNPRESS, NULL);
4661 }
4662
4663 static void
4664 _hbar_drag_cb(Evas_Object *obj,
4665                 void *data __UNUSED__)
4666 {
4667    evas_object_smart_callback_call(obj, SIG_HBAR_DRAG, NULL);
4668 }
4669
4670 static void
4671 _hbar_press_cb(Evas_Object *obj,
4672                 void *data __UNUSED__)
4673 {
4674    evas_object_smart_callback_call(obj, SIG_HBAR_PRESS, NULL);
4675 }
4676
4677 static void
4678 _hbar_unpress_cb(Evas_Object *obj,
4679                 void *data __UNUSED__)
4680 {
4681    evas_object_smart_callback_call(obj, SIG_HBAR_UNPRESS, NULL);
4682 }
4683
4684 static void
4685 _decorate_item_realize(Elm_Gen_Item *it)
4686 {
4687    char buf[1024];
4688    if (it->item->deco_it_view) return;
4689
4690    //evas_event_freeze(evas_object_evas_get(obj));
4691    it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
4692    edje_object_scale_set
4693      (it->item->deco_it_view, elm_widget_scale_get(WIDGET(it)) *
4694      elm_config_scale_get());
4695    evas_object_smart_member_add
4696      (it->item->deco_it_view, GL_IT(it)->wsd->pan_obj);
4697    elm_widget_sub_object_add(WIDGET(it), it->item->deco_it_view);
4698
4699    strncpy(buf, "item", sizeof(buf));
4700    if (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)
4701      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
4702
4703    if (it->item->order_num_in & 0x1)
4704      strncat(buf, "_odd", sizeof(buf) - strlen(buf));
4705    strncat(buf, "/", sizeof(buf) - strlen(buf));
4706    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
4707
4708    elm_widget_theme_object_set
4709      (WIDGET(it), it->item->deco_it_view, "genlist", buf,
4710      elm_widget_style_get(WIDGET(it)));
4711    edje_object_mirrored_set
4712      (it->item->deco_it_view, elm_widget_mirrored_get(WIDGET(it)));
4713
4714    /* signal callback add */
4715    evas_object_event_callback_add
4716      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb,
4717      it);
4718    evas_object_event_callback_add
4719      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
4720    evas_object_event_callback_add
4721      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb,
4722      it);
4723
4724    if (eina_list_count(it->item->deco_it_content_objs) != 0)
4725      ERR_ABORT("If you see this error, please notify us and we"
4726                "will fix it");
4727
4728    /* text_get, content_get, state_get */
4729    _item_text_realize
4730      (it, it->item->deco_it_view, &it->item->deco_it_texts, NULL);
4731    if (!it->item->deco_it_contents)
4732      it->item->deco_it_contents =
4733        elm_widget_stringlist_get
4734          (edje_object_data_get(it->item->deco_it_view, "contents"));
4735    it->item->deco_it_content_objs =
4736      _item_mode_content_realize
4737        (it, it->item->deco_it_view, &it->item->deco_it_contents, NULL,
4738        &it->item->deco_it_content_objs);
4739    _item_state_realize
4740      (it, it->item->deco_it_view, &it->item->deco_it_states, NULL);
4741    edje_object_part_swallow
4742      (it->item->deco_it_view,
4743      edje_object_data_get(it->item->deco_it_view, "mode_part"), VIEW(it));
4744
4745    it->want_unrealize = EINA_FALSE;
4746    //evas_event_thaw(evas_object_evas_get(obj));
4747    //evas_event_thaw_eval(evas_object_evas_get(obj));
4748 }
4749
4750 static void
4751 _decorate_item_set(Elm_Gen_Item *it)
4752 {
4753    Elm_Genlist_Smart_Data *sd;
4754    char buf[1024];
4755
4756    if (!it) return;
4757
4758    sd = GL_IT(it)->wsd;
4759
4760    sd->mode_item = it;
4761    it->item->nocache_once = EINA_TRUE;
4762
4763    if (sd->scr_hold_timer)
4764      {
4765         ecore_timer_del(sd->scr_hold_timer);
4766         sd->scr_hold_timer = NULL;
4767      }
4768    sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_TRUE);
4769    sd->scr_hold_timer = ecore_timer_add(0.1, _scroll_hold_timer_cb, sd);
4770
4771    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4772    _decorate_item_realize(it);
4773    if (it->item->group_item)
4774      evas_object_raise(it->item->VIEW(group_item));
4775    _item_position
4776      (it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
4777    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4778    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4779
4780    snprintf(buf, sizeof(buf), "elm,state,%s,active", sd->decorate_it_type);
4781    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
4782 }
4783
4784 static void
4785 _decorate_item_unset(Elm_Genlist_Smart_Data *sd)
4786 {
4787    char buf[1024], buf2[1024];
4788    Elm_Gen_Item *it;
4789
4790    if (!sd->mode_item) return;
4791
4792    it = sd->mode_item;
4793    it->item->nocache_once = EINA_TRUE;
4794
4795    snprintf(buf, sizeof(buf), "elm,state,%s,passive", sd->decorate_it_type);
4796    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished",
4797             sd->decorate_it_type);
4798    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
4799    edje_object_signal_callback_add
4800      (it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb,
4801      it);
4802    sd->mode_item = NULL;
4803 }
4804
4805 #if 0
4806 // FIXME: difference from upstream
4807 static void
4808 _mouse_down_scroller(void        *data,
4809                      Evas        *evas __UNUSED__,
4810                      Evas_Object *obj __UNUSED__,
4811                      void        *event_info __UNUSED__)
4812 {
4813    Widget_Data *wd = elm_widget_data_get(data);
4814
4815    if (!wd) return;
4816    wd->drag_started = EINA_FALSE;
4817 }
4818
4819 static void
4820 _mouse_up_scroller(void        *data,
4821                    Evas        *evas __UNUSED__,
4822                    Evas_Object *obj __UNUSED__,
4823                    void        *event_info __UNUSED__)
4824 {
4825    Widget_Data *wd = elm_widget_data_get(data);
4826
4827    if (!wd) return;
4828    wd->drag_started = EINA_FALSE;
4829 }
4830
4831 static void
4832 _mouse_move_scroller(void        *data,
4833                      Evas        *evas __UNUSED__,
4834                      Evas_Object *obj __UNUSED__,
4835                      void        *event_info)
4836 {
4837    Widget_Data *wd = elm_widget_data_get(data);
4838    Evas_Event_Mouse_Move *ev = event_info;
4839    Evas_Coord minw = 0, minh = 0, dx, dy, adx, ady;
4840
4841    if (!wd) return;
4842    if (wd->drag_started) return;
4843
4844    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
4845    dx = ev->cur.canvas.x - ev->prev.canvas.x;
4846    dy = ev->cur.canvas.y - ev->prev.canvas.y;
4847    adx = dx;
4848    ady = dy;
4849    if (adx < 0) adx = -dx;
4850    if (ady < 0) ady = -dy;
4851    if (((ady < minh) && (ady > minh / 2)) && (ady > adx))
4852      {
4853         if (dy < 0)
4854           {
4855              evas_object_smart_callback_call(data, SIG_DRAG_START_UP, NULL);
4856              wd->drag_started = EINA_TRUE;
4857           }
4858         else
4859           {
4860              evas_object_smart_callback_call(data, SIG_DRAG_START_DOWN, NULL);
4861              wd->drag_started = EINA_TRUE;
4862           }
4863      }
4864 }
4865 #endif
4866
4867 static void
4868 _elm_genlist_smart_add(Evas_Object *obj)
4869 {
4870    Evas_Coord minw, minh;
4871    Elm_Genlist_Pan_Smart_Data *pan_data;
4872
4873    EVAS_SMART_DATA_ALLOC(obj, Elm_Genlist_Smart_Data);
4874
4875    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.add(obj);
4876
4877    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
4878    evas_object_smart_member_add(priv->hit_rect, obj);
4879    elm_widget_sub_object_add(obj, priv->hit_rect);
4880
4881    /* common scroller hit rectangle setup */
4882    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
4883    evas_object_show(priv->hit_rect);
4884    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
4885
4886    elm_widget_can_focus_set(obj, EINA_TRUE);
4887    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
4888
4889    elm_layout_theme_set(obj, "genlist", "base", elm_widget_style_get(obj));
4890
4891    /* interface's add() routine issued AFTER the object's smart_add() */
4892    priv->s_iface = evas_object_smart_interface_get
4893        (obj, ELM_SCROLLABLE_IFACE_NAME);
4894
4895    priv->s_iface->objects_set
4896      (obj, ELM_WIDGET_DATA(priv)->resize_obj, priv->hit_rect);
4897
4898    priv->s_iface->bounce_allow_set
4899      (obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable);
4900    priv->v_bounce = _elm_config->thumbscroll_bounce_enable;
4901
4902    priv->s_iface->animate_start_cb_set(obj, _scroll_animate_start_cb);
4903    priv->s_iface->animate_stop_cb_set(obj, _scroll_animate_stop_cb);
4904    priv->s_iface->drag_start_cb_set(obj, _scroll_drag_start_cb);
4905    priv->s_iface->drag_stop_cb_set(obj, _scroll_drag_stop_cb);
4906    priv->s_iface->edge_left_cb_set(obj, _edge_left_cb);
4907    priv->s_iface->edge_right_cb_set(obj, _edge_right_cb);
4908    priv->s_iface->edge_top_cb_set(obj, _edge_top_cb);
4909    priv->s_iface->edge_bottom_cb_set(obj, _edge_bottom_cb);
4910    priv->s_iface->vbar_drag_cb_set(obj, _vbar_drag_cb);
4911    priv->s_iface->vbar_press_cb_set(obj, _vbar_press_cb);
4912    priv->s_iface->vbar_unpress_cb_set(obj, _vbar_unpress_cb);
4913    priv->s_iface->hbar_drag_cb_set(obj, _hbar_drag_cb);
4914    priv->s_iface->hbar_press_cb_set(obj, _hbar_press_cb);
4915    priv->s_iface->hbar_unpress_cb_set(obj, _hbar_unpress_cb);
4916
4917    priv->mode = ELM_LIST_SCROLL;
4918    priv->max_items_per_block = MAX_ITEMS_PER_BLOCK;
4919    priv->item_cache_max = priv->max_items_per_block * 2;
4920    priv->longpress_timeout = _elm_config->longpress_timeout;
4921    priv->highlight = EINA_TRUE;
4922
4923 #if GENLIST_FX_SUPPORT
4924    priv->fx_mode = EINA_FALSE;
4925    priv->rendered = EINA_FALSE;
4926    priv->fx_first_captured = EINA_FALSE;
4927    priv->fx_playing = EINA_FALSE;
4928    priv->fx_items_deleted = EINA_FALSE;
4929    priv->genlist_clearing = EINA_FALSE;
4930 #endif
4931
4932    priv->pan_obj = evas_object_smart_add
4933        (evas_object_evas_get(obj), _elm_genlist_pan_smart_class_new());
4934    pan_data = evas_object_smart_data_get(priv->pan_obj);
4935    pan_data->wsd = priv;
4936
4937 #if 0
4938    // FIXME: difference from upstream
4939    evas_object_event_callback_add(pan_obj, EVAS_CALLBACK_MOUSE_DOWN,
4940                                   _mouse_down_scroller, obj);
4941    evas_object_event_callback_add(pan_obj, EVAS_CALLBACK_MOUSE_UP,
4942                                   _mouse_up_scroller, obj);
4943    evas_object_event_callback_add(pan_obj, EVAS_CALLBACK_MOUSE_MOVE,
4944                                   _mouse_move_scroller, obj);
4945 #endif
4946
4947    priv->s_iface->extern_pan_set(obj, priv->pan_obj);
4948
4949    edje_object_size_min_calc(ELM_WIDGET_DATA(priv)->resize_obj, &minw, &minh);
4950    evas_object_size_hint_min_set(obj, minw, minh);
4951
4952    _item_cache_all_free(priv);
4953    _mirrored_set(obj, elm_widget_mirrored_get(obj));
4954
4955    elm_layout_sizing_eval(obj);
4956 }
4957
4958 static void
4959 _elm_genlist_smart_del(Evas_Object *obj)
4960 {
4961    ELM_GENLIST_DATA_GET(obj, sd);
4962
4963    elm_genlist_clear(obj);
4964    if (sd->calc_job) ecore_job_del(sd->calc_job);
4965    if (sd->update_job) ecore_job_del(sd->update_job);
4966    if (sd->queue_idle_enterer) ecore_idle_enterer_del(sd->queue_idle_enterer);
4967    if (sd->must_recalc_idler) ecore_idler_del(sd->must_recalc_idler);
4968    if (sd->multi_timer) ecore_timer_del(sd->multi_timer);
4969    if (sd->decorate_it_type) eina_stringshare_del(sd->decorate_it_type);
4970    if (sd->scr_hold_timer) ecore_timer_del(sd->scr_hold_timer);
4971
4972    evas_object_del(sd->pan_obj);
4973    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.del(obj);
4974 }
4975
4976 static void
4977 _elm_genlist_smart_move(Evas_Object *obj,
4978                         Evas_Coord x,
4979                         Evas_Coord y)
4980 {
4981    ELM_GENLIST_DATA_GET(obj, sd);
4982
4983    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.move(obj, x, y);
4984
4985    evas_object_move(sd->hit_rect, x, y);
4986 }
4987
4988 static void
4989 _elm_genlist_smart_resize(Evas_Object *obj,
4990                           Evas_Coord w,
4991                           Evas_Coord h)
4992 {
4993    ELM_GENLIST_DATA_GET(obj, sd);
4994
4995    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.resize(obj, w, h);
4996
4997    evas_object_resize(sd->hit_rect, w, h);
4998 }
4999
5000 static void
5001 _elm_genlist_smart_member_add(Evas_Object *obj,
5002                               Evas_Object *member)
5003 {
5004    ELM_GENLIST_DATA_GET(obj, sd);
5005
5006    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.member_add(obj, member);
5007
5008    if (sd->hit_rect)
5009      evas_object_raise(sd->hit_rect);
5010 }
5011
5012 static void
5013 _access_obj_process(Elm_Genlist_Smart_Data *sd, Eina_Bool is_access)
5014 {
5015    Item_Block *itb;
5016    Eina_Bool done = EINA_FALSE;
5017
5018    EINA_INLIST_FOREACH(sd->blocks, itb)
5019      {
5020         if (itb->realized)
5021           {
5022              Eina_List *l;
5023              Elm_Gen_Item *it;
5024
5025              done = EINA_TRUE;
5026              EINA_LIST_FOREACH(itb->items, l, it)
5027                {
5028                   if (!it->realized) continue;
5029                   if (is_access) _access_widget_item_register(it);
5030                   else
5031                     _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
5032                }
5033           }
5034         else if (done) break;
5035      }
5036 }
5037
5038 static void
5039 _elm_genlist_smart_access(Evas_Object *obj, Eina_Bool is_access)
5040 {
5041    ELM_GENLIST_CHECK(obj);
5042    ELM_GENLIST_DATA_GET(obj, sd);
5043
5044    if (is_access)
5045      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
5046      _elm_genlist_smart_focus_next;
5047    else
5048      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
5049    _access_obj_process(sd, is_access);
5050 }
5051
5052 static void
5053 _elm_genlist_smart_set_user(Elm_Genlist_Smart_Class *sc)
5054 {
5055    ELM_WIDGET_CLASS(sc)->base.add = _elm_genlist_smart_add;
5056    ELM_WIDGET_CLASS(sc)->base.del = _elm_genlist_smart_del;
5057    ELM_WIDGET_CLASS(sc)->base.move = _elm_genlist_smart_move;
5058    ELM_WIDGET_CLASS(sc)->base.resize = _elm_genlist_smart_resize;
5059    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_genlist_smart_member_add;
5060
5061    ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_genlist_smart_sub_object_add;
5062    ELM_WIDGET_CLASS(sc)->sub_object_del = _elm_genlist_smart_sub_object_del;
5063    ELM_WIDGET_CLASS(sc)->on_focus = _elm_genlist_smart_on_focus;
5064    ELM_WIDGET_CLASS(sc)->theme = _elm_genlist_smart_theme;
5065    ELM_WIDGET_CLASS(sc)->event = _elm_genlist_smart_event;
5066    ELM_WIDGET_CLASS(sc)->translate = _elm_genlist_smart_translate;
5067
5068    /* not a 'focus chain manager' */
5069    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
5070    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
5071
5072    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_genlist_smart_sizing_eval;
5073
5074    // ACCESS
5075    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
5076      ELM_WIDGET_CLASS(sc)->focus_next = _elm_genlist_smart_focus_next;
5077
5078    ELM_WIDGET_CLASS(sc)->access = _elm_genlist_smart_access;
5079 }
5080
5081 EAPI const Elm_Genlist_Smart_Class *
5082 elm_genlist_smart_class_get(void)
5083 {
5084    static Elm_Genlist_Smart_Class _sc =
5085      ELM_GENLIST_SMART_CLASS_INIT_NAME_VERSION(ELM_GENLIST_SMART_NAME);
5086    static const Elm_Genlist_Smart_Class *class = NULL;
5087    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
5088
5089    if (class)
5090      return class;
5091
5092    _elm_genlist_smart_set(&_sc);
5093    esc->callbacks = _smart_callbacks;
5094    class = &_sc;
5095
5096    return class;
5097 }
5098
5099 EAPI Evas_Object *
5100 elm_genlist_add(Evas_Object *parent)
5101 {
5102    Evas_Object *obj;
5103
5104    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
5105
5106    obj = elm_widget_add(_elm_genlist_smart_class_new(), parent);
5107    if (!obj) return NULL;
5108
5109    if (!elm_widget_sub_object_add(parent, obj))
5110      ERR("could not add %p as sub object of %p", obj, parent);
5111
5112    return obj;
5113 }
5114
5115
5116 static Evas_Object *
5117 _item_content_get_hook(Elm_Gen_Item *it,
5118                        const char *part)
5119 {
5120    Evas_Object *ret = NULL;
5121    if (it->deco_all_view)
5122      ret = edje_object_part_swallow_get(it->deco_all_view, part);
5123    else if (it->decorate_it_set)
5124      ret = edje_object_part_swallow_get(it->item->deco_it_view, part);
5125    if (!ret)
5126      ret = edje_object_part_swallow_get(VIEW(it), part);
5127    return ret;
5128 }
5129
5130 static const char *
5131 _item_text_get_hook(Elm_Gen_Item *it,
5132                     const char *part)
5133 {
5134    if (!it->itc->func.text_get) return NULL;
5135    const char *ret = NULL;
5136    if (it->deco_all_view)
5137      ret = edje_object_part_text_get(it->deco_all_view, part);
5138    else if (it->decorate_it_set)
5139      ret = edje_object_part_text_get(it->item->deco_it_view, part);
5140    if (!ret)
5141      ret = edje_object_part_text_get(VIEW(it), part);
5142    return ret;
5143 }
5144
5145 static void
5146 _item_disable_hook(Elm_Object_Item *item)
5147 {
5148    Eina_List *l;
5149    Evas_Object *obj;
5150    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5151
5152    if (it->selected)
5153      elm_genlist_item_selected_set(item, EINA_FALSE);
5154
5155    if (it->realized)
5156      {
5157         if (elm_widget_item_disabled_get(it))
5158           {
5159              edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
5160              if (it->deco_all_view)
5161                edje_object_signal_emit
5162                  (it->deco_all_view, "elm,state,disabled", "elm");
5163           }
5164         else
5165           {
5166              edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
5167              if (it->deco_all_view)
5168                edje_object_signal_emit
5169                  (it->deco_all_view, "elm,state,enabled", "elm");
5170           }
5171         EINA_LIST_FOREACH(it->content_objs, l, obj)
5172           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(it));
5173      }
5174 }
5175
5176 static Eina_Bool
5177 _item_del_pre_hook(Elm_Object_Item *item)
5178 {
5179    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5180
5181 #if GENLIST_FX_SUPPORT
5182    if ((GL_IT(it)->wsd->fx_mode) && (!GL_IT(it)->wsd->genlist_clearing))
5183      {
5184         _item_del_pre_fx_process(it);
5185         return EINA_FALSE;
5186      }
5187 #endif
5188    _item_free(it);
5189    return EINA_TRUE;
5190 }
5191
5192 static void
5193 _item_signal_emit_hook(Elm_Object_Item *it,
5194                        const char *emission,
5195                        const char *source)
5196 {
5197    edje_object_signal_emit(VIEW(it), emission, source);
5198 }
5199
5200 static Elm_Gen_Item *
5201 _elm_genlist_item_new(Elm_Genlist_Smart_Data *sd,
5202                       const Elm_Genlist_Item_Class *itc,
5203                       const void *data,
5204                       Elm_Gen_Item *parent,
5205                       Elm_Genlist_Item_Type type,
5206                       Evas_Smart_Cb func,
5207                       const void *func_data)
5208 {
5209    Elm_Gen_Item *it, *it2;
5210    int depth = 0;
5211
5212    if (!itc) return NULL;
5213
5214    it = elm_widget_item_new(ELM_WIDGET_DATA(sd)->obj, Elm_Gen_Item);
5215    if (!it) return NULL;
5216
5217    it->itc = itc;
5218    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
5219
5220    it->base.data = data;
5221    it->parent = parent;
5222    it->func.func = func;
5223    it->func.data = func_data;
5224
5225    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
5226    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
5227    elm_widget_item_disable_hook_set(it, _item_disable_hook);
5228    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
5229    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
5230
5231 #if 0 // FIXME: difference from upstream
5232    it->can_focus = EINA_TRUE;
5233 #endif
5234    //it->del_cb = (Ecore_Cb)_item_free;
5235    //it->highlight_cb = (Ecore_Cb)_item_highlight;
5236    //it->unhighlight_cb = (Ecore_Cb)_item_unhighlight;
5237    //it->sel_cb = (Ecore_Cb)_item_select;
5238    //it->unsel_cb = (Ecore_Cb)_item_unselect;
5239    //it->unrealize_cb = (Ecore_Cb)_item_unrealize_cb;
5240
5241    GL_IT(it) = ELM_NEW(Elm_Gen_Item_Type);
5242    GL_IT(it)->wsd = sd;
5243    GL_IT(it)->type = type;
5244    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
5245
5246    if (it->parent)
5247      {
5248         if (it->parent->group)
5249           GL_IT(it)->group_item = parent;
5250         else if (GL_IT(it->parent)->group_item)
5251           GL_IT(it)->group_item = GL_IT(it->parent)->group_item;
5252      }
5253    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
5254      {
5255         if (!it2->parent->group) depth += 1;
5256      }
5257    GL_IT(it)->expanded_depth = depth;
5258    sd->item_count++;
5259
5260 #if GENLIST_FX_SUPPORT
5261    it->item->num = sd->item_count;
5262    if (sd->fx_mode)
5263      {
5264         sd->fx_items_deleted = EINA_FALSE;
5265         _elm_genlist_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
5266      }
5267 #endif
5268    return it;
5269 }
5270
5271 static int
5272 _elm_genlist_item_compare(const void *data,
5273                           const void *data1)
5274 {
5275    const Elm_Gen_Item *it, *item1;
5276
5277    it = ELM_GEN_ITEM_FROM_INLIST(data);
5278    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
5279    return GL_IT(it)->wsd->item_compare_cb(it, item1);
5280 }
5281
5282 static int
5283 _elm_genlist_item_list_compare(const void *data,
5284                                const void *data1)
5285 {
5286    const Elm_Gen_Item *it = data;
5287    const Elm_Gen_Item *item1 = data1;
5288
5289    return GL_IT(it)->wsd->item_compare_cb(it, item1);
5290 }
5291
5292 EAPI unsigned int
5293 elm_genlist_items_count(const Evas_Object *obj)
5294 {
5295    ELM_GENLIST_CHECK(obj) 0;
5296    ELM_GENLIST_DATA_GET(obj, sd);
5297
5298    return sd->item_count;
5299 }
5300
5301 EAPI Elm_Object_Item *
5302 elm_genlist_item_append(Evas_Object *obj,
5303                         const Elm_Genlist_Item_Class *itc,
5304                         const void *data,
5305                         Elm_Object_Item *parent,
5306                         Elm_Genlist_Item_Type type,
5307                         Evas_Smart_Cb func,
5308                         const void *func_data)
5309 {
5310    Elm_Gen_Item *it;
5311
5312    ELM_GENLIST_CHECK(obj) NULL;
5313    ELM_GENLIST_DATA_GET(obj, sd);
5314    if (parent)
5315      ELM_WIDGET_ITEM_RETURN_IF_ONDEL(((Elm_Widget_Item *)parent),NULL);
5316
5317    it = _elm_genlist_item_new
5318        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5319    if (!it) return NULL;
5320
5321    if (!it->parent)
5322      {
5323         if (it->group)
5324           sd->group_items = eina_list_append(sd->group_items, it);
5325         sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
5326         it->item->rel = NULL;
5327      }
5328    else
5329      {
5330         Elm_Gen_Item *it2 = NULL;
5331         Eina_List *ll = eina_list_last(it->parent->item->items);
5332
5333         if (ll) it2 = ll->data;
5334         it->parent->item->items =
5335           eina_list_append(it->parent->item->items, it);
5336         if (!it2) it2 = it->parent;
5337         sd->items = eina_inlist_append_relative
5338           (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
5339         it->item->rel = it2;
5340         it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
5341      }
5342    it->item->before = EINA_FALSE;
5343    _item_queue(sd, it, NULL);
5344
5345    return (Elm_Object_Item *)it;
5346 }
5347
5348 EAPI Elm_Object_Item *
5349 elm_genlist_item_prepend(Evas_Object *obj,
5350                          const Elm_Genlist_Item_Class *itc,
5351                          const void *data,
5352                          Elm_Object_Item *parent,
5353                          Elm_Genlist_Item_Type type,
5354                          Evas_Smart_Cb func,
5355                          const void *func_data)
5356 {
5357    Elm_Gen_Item *it;
5358
5359    ELM_GENLIST_CHECK(obj) NULL;
5360    ELM_GENLIST_DATA_GET(obj, sd);
5361    it = _elm_genlist_item_new
5362        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5363    if (!it) return NULL;
5364
5365    if (!it->parent)
5366      {
5367         if (it->group)
5368           sd->group_items = eina_list_prepend(sd->group_items, it);
5369         sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
5370         it->item->rel = NULL;
5371      }
5372    else
5373      {
5374         Elm_Gen_Item *it2 = NULL;
5375         Eina_List *ll = it->parent->item->items;
5376
5377         if (ll) it2 = ll->data;
5378         it->parent->item->items =
5379           eina_list_prepend(it->parent->item->items, it);
5380         if (!it2) it2 = it->parent;
5381         sd->items = eina_inlist_prepend_relative
5382             (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
5383         it->item->rel = it2;
5384         it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
5385      }
5386    it->item->before = EINA_TRUE;
5387    _item_queue(sd, it, NULL);
5388
5389    return (Elm_Object_Item *)it;
5390 }
5391
5392 EAPI Elm_Object_Item *
5393 elm_genlist_item_insert_after(Evas_Object *obj,
5394                               const Elm_Genlist_Item_Class *itc,
5395                               const void *data,
5396                               Elm_Object_Item *parent,
5397                               Elm_Object_Item *after_it,
5398                               Elm_Genlist_Item_Type type,
5399                               Evas_Smart_Cb func,
5400                               const void *func_data)
5401 {
5402    Elm_Gen_Item *after = (Elm_Gen_Item *)after_it;
5403    Elm_Gen_Item *it;
5404
5405    ELM_GENLIST_CHECK(obj) NULL;
5406    ELM_GENLIST_ITEM_CHECK_OR_RETURN(after_it, NULL);
5407    ELM_GENLIST_DATA_GET(obj, sd);
5408
5409    /* It makes no sense to insert after in an empty list with after !=
5410     * NULL, something really bad is happening in your app. */
5411    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
5412
5413    it = _elm_genlist_item_new
5414        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5415    if (!it) return NULL;
5416
5417    if (!it->parent)
5418      {
5419         if ((it->group) && (after->group))
5420           sd->group_items = eina_list_append_relative
5421               (sd->group_items, it, after);
5422      }
5423    else
5424      {
5425         it->parent->item->items =
5426           eina_list_append_relative(it->parent->item->items, it, after);
5427      }
5428    sd->items = eina_inlist_append_relative
5429        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
5430
5431    it->item->rel = after;
5432    after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
5433    it->item->before = EINA_FALSE;
5434    _item_queue(sd, it, NULL);
5435
5436    return (Elm_Object_Item *)it;
5437 }
5438
5439 EAPI Elm_Object_Item *
5440 elm_genlist_item_insert_before(Evas_Object *obj,
5441                                const Elm_Genlist_Item_Class *itc,
5442                                const void *data,
5443                                Elm_Object_Item *parent,
5444                                Elm_Object_Item *before_it,
5445                                Elm_Genlist_Item_Type type,
5446                                Evas_Smart_Cb func,
5447                                const void *func_data)
5448 {
5449    Elm_Gen_Item *before = (Elm_Gen_Item *)before_it;
5450    Elm_Gen_Item *it;
5451
5452    ELM_GENLIST_CHECK(obj) NULL;
5453    ELM_GENLIST_ITEM_CHECK_OR_RETURN(before_it, NULL);
5454    ELM_GENLIST_DATA_GET(obj, sd);
5455
5456    /* It makes no sense to insert before in an empty list with before
5457     * != NULL, something really bad is happening in your app. */
5458    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
5459
5460    it = _elm_genlist_item_new
5461        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5462    if (!it) return NULL;
5463
5464    if (!it->parent)
5465      {
5466         if (it->group && before->group)
5467           sd->group_items =
5468             eina_list_prepend_relative(sd->group_items, it, before);
5469      }
5470    else
5471      {
5472         it->parent->item->items =
5473           eina_list_prepend_relative(it->parent->item->items, it, before);
5474      }
5475    sd->items = eina_inlist_prepend_relative
5476        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
5477
5478    it->item->rel = before;
5479    before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
5480    it->item->before = EINA_TRUE;
5481    _item_queue(sd, it, NULL);
5482
5483    return (Elm_Object_Item *)it;
5484 }
5485
5486 EAPI Elm_Object_Item *
5487 elm_genlist_item_sorted_insert(Evas_Object *obj,
5488                                const Elm_Genlist_Item_Class *itc,
5489                                const void *data,
5490                                Elm_Object_Item *parent,
5491                                Elm_Genlist_Item_Type type,
5492                                Eina_Compare_Cb comp,
5493                                Evas_Smart_Cb func,
5494                                const void *func_data)
5495 {
5496    Elm_Gen_Item *rel = NULL;
5497    Elm_Gen_Item *it;
5498
5499    ELM_GENLIST_CHECK(obj) NULL;
5500    ELM_GENLIST_DATA_GET(obj, sd);
5501
5502    it = _elm_genlist_item_new
5503        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5504    if (!it) return NULL;
5505
5506    sd->item_compare_cb = comp;
5507
5508    if (it->parent)
5509      {
5510         Eina_List *l;
5511         int cmp_result;
5512
5513         l = eina_list_search_sorted_near_list
5514             (it->parent->item->items, _elm_genlist_item_list_compare, it,
5515             &cmp_result);
5516
5517         if (l)
5518           rel = eina_list_data_get(l);
5519         else
5520           rel = it->parent;
5521
5522         if (cmp_result >= 0)
5523           {
5524              it->parent->item->items = eina_list_prepend_relative_list
5525                  (it->parent->item->items, it, l);
5526              sd->items = eina_inlist_prepend_relative
5527                  (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
5528              it->item->before = EINA_FALSE;
5529           }
5530         else if (cmp_result < 0)
5531           {
5532              it->parent->item->items = eina_list_append_relative_list
5533                  (it->parent->item->items, it, l);
5534              sd->items = eina_inlist_append_relative
5535                  (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
5536              it->item->before = EINA_TRUE;
5537           }
5538      }
5539    else
5540      {
5541         if (!sd->state)
5542           {
5543              sd->state = eina_inlist_sorted_state_new();
5544              eina_inlist_sorted_state_init(sd->state, sd->items);
5545              sd->requeued = EINA_FALSE;
5546           }
5547
5548         if (it->group)
5549           sd->group_items = eina_list_append(sd->group_items, it);
5550
5551         sd->items = eina_inlist_sorted_state_insert
5552             (sd->items, EINA_INLIST_GET(it), _elm_genlist_item_compare,
5553             sd->state);
5554
5555         if (EINA_INLIST_GET(it)->next)
5556           {
5557              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5558              it->item->before = EINA_TRUE;
5559           }
5560         else if (EINA_INLIST_GET(it)->prev)
5561           {
5562              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5563              it->item->before = EINA_FALSE;
5564           }
5565      }
5566
5567    if (rel)
5568      {
5569         it->item->rel = rel;
5570         rel->item->rel_revs = eina_list_append(rel->item->rel_revs, it);
5571      }
5572
5573    _item_queue(sd, it, _elm_genlist_item_list_compare);
5574
5575    return (Elm_Object_Item *)it;
5576 }
5577
5578 static void
5579 _elm_genlist_fx_clear(Evas_Object *obj)
5580 {
5581    ELM_GENLIST_DATA_GET(obj, sd);
5582
5583    Elm_Gen_FX_Item *fi;
5584    Proxy_Item *pi;
5585    Elm_Gen_Item *it;
5586
5587    EINA_LIST_FREE(sd->capture_before_items, pi)
5588      {
5589         if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
5590         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
5591         if (pi->proxy) evas_object_del(pi->proxy);
5592         free(pi);
5593      }
5594    EINA_LIST_FREE(sd->capture_after_items, pi)
5595      {
5596         if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
5597         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
5598         if (pi->proxy) evas_object_del(pi->proxy);
5599         free(pi);
5600      }
5601
5602    EINA_LIST_FREE(sd->fx_items, fi)
5603      {
5604         if (fi->trans) elm_transit_del(fi->trans);
5605         free(fi);
5606      }
5607
5608    EINA_LIST_FREE (sd->pending_unrealized_items, it)
5609       _item_unrealize(it, EINA_FALSE);
5610
5611    EINA_LIST_FREE (sd->pending_unrealized_decorate_all_items, it)
5612       _decorate_all_item_unrealize(it);
5613
5614    EINA_LIST_FREE (sd->pending_del_items, it)
5615      {
5616         _item_free(it);
5617         _elm_widget_item_free((Elm_Widget_Item *)it);
5618      }
5619    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
5620    sd->alpha_bg = NULL;
5621    if (sd->fx_timer) ecore_timer_del(sd->fx_timer);
5622    sd->fx_timer = NULL;
5623
5624    sd->genlist_clearing = EINA_TRUE;
5625    sd->fx_playing = EINA_FALSE;
5626    sd->sorting = EINA_FALSE;
5627    sd->fx_first_captured = EINA_FALSE;
5628    sd->fx_items_deleted = EINA_FALSE;
5629 }
5630
5631 EAPI void
5632 elm_genlist_clear(Evas_Object *obj)
5633 {
5634    ELM_GENLIST_CHECK(obj);
5635    ELM_GENLIST_DATA_GET(obj, sd);
5636    Elm_Gen_Item *it;
5637
5638    if (sd->state)
5639      {
5640         eina_inlist_sorted_state_free(sd->state);
5641         sd->state = NULL;
5642      }
5643
5644 #if GENLIST_FX_SUPPORT
5645    if (sd->fx_mode)
5646      {
5647         _elm_genlist_fx_clear(obj);
5648         sd->genlist_clearing = EINA_TRUE;
5649         sd->rendered = EINA_FALSE;
5650      }
5651 #endif
5652 #if GENLIST_PINCH_ZOOM_SUPPORT
5653    sd->pinch_zoom_h = 0;
5654    sd->realized_top_item = NULL;
5655    sd->pinch_zoom_mode = ELM_GEN_PINCH_ZOOM_NONE;
5656 #endif
5657
5658    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5659
5660    // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE
5661    // because sd->items can be modified inside elm_widget_item_del()
5662    while (sd->items)
5663      {
5664         it = EINA_INLIST_CONTAINER_GET(sd->items->last, Elm_Gen_Item);
5665         it->item->nocache_once = EINA_TRUE;
5666         elm_widget_item_del(it);
5667      }
5668    sd->items = NULL;
5669    sd->blocks = NULL;
5670    _item_cache_all_free(sd);
5671
5672    sd->pan_changed = EINA_TRUE;
5673    if (sd->selected) sd->selected = eina_list_free(sd->selected);
5674    sd->selected = NULL;
5675
5676    sd->anchor_item = NULL;
5677    if (sd->multi_timer)
5678      {
5679         ecore_timer_del(sd->multi_timer);
5680         sd->multi_timer = NULL;
5681      }
5682    if (sd->update_job)
5683      {
5684         ecore_job_del(sd->update_job);
5685         sd->update_job = NULL;
5686      }
5687    if (sd->calc_job)
5688      {
5689         ecore_job_del(sd->calc_job);
5690         sd->calc_job = NULL;
5691      }
5692    if (sd->queue_idle_enterer)
5693      {
5694         ecore_idle_enterer_del(sd->queue_idle_enterer);
5695         sd->queue_idle_enterer = NULL;
5696      }
5697    if (sd->must_recalc_idler)
5698      {
5699         ecore_idler_del(sd->must_recalc_idler);
5700         sd->must_recalc_idler = NULL;
5701      }
5702    if (sd->queue) sd->queue = eina_list_free(sd->queue);
5703    if (sd->reorder_move_animator)
5704      {
5705         ecore_animator_del(sd->reorder_move_animator);
5706         sd->reorder_move_animator = NULL;
5707      }
5708    sd->show_item = NULL;
5709    sd->reorder_old_pan_y = 0;
5710
5711    sd->pan_x = 0;
5712    sd->pan_y = 0;
5713    sd->minw = 0;
5714    sd->minh = 0;
5715
5716    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
5717    sd->alpha_bg = NULL;
5718
5719    if (sd->pan_obj)
5720      {
5721         evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
5722         evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
5723      }
5724    elm_layout_sizing_eval(ELM_WIDGET_DATA(sd)->obj);
5725    sd->s_iface->content_region_show(obj, 0, 0, 0, 0);
5726
5727 #if GENLIST_FX_SUPPORT
5728    sd->genlist_clearing = EINA_FALSE;
5729 #endif
5730    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5731    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5732 }
5733
5734 EAPI void
5735 elm_genlist_multi_select_set(Evas_Object *obj,
5736                              Eina_Bool multi)
5737 {
5738    ELM_GENLIST_CHECK(obj);
5739    ELM_GENLIST_DATA_GET(obj, sd);
5740
5741    sd->multi = !!multi;
5742 }
5743
5744 EAPI Eina_Bool
5745 elm_genlist_multi_select_get(const Evas_Object *obj)
5746 {
5747    ELM_GENLIST_CHECK(obj) EINA_FALSE;
5748    ELM_GENLIST_DATA_GET(obj, sd);
5749
5750    return sd->multi;
5751 }
5752
5753 EAPI Elm_Object_Item *
5754 elm_genlist_selected_item_get(const Evas_Object *obj)
5755 {
5756    ELM_GENLIST_CHECK(obj) NULL;
5757    ELM_GENLIST_DATA_GET(obj, sd);
5758
5759    if (sd->selected)
5760      return sd->selected->data;
5761
5762    return NULL;
5763 }
5764
5765 EAPI Eina_List *
5766 elm_genlist_selected_items_get(const Evas_Object *obj)
5767 {
5768    ELM_GENLIST_CHECK(obj) NULL;
5769    ELM_GENLIST_DATA_GET(obj, sd);
5770
5771    return sd->selected;
5772 }
5773
5774 EAPI Eina_List *
5775 elm_genlist_realized_items_get(const Evas_Object *obj)
5776 {
5777    Item_Block *itb;
5778    Eina_List *list = NULL;
5779    Eina_Bool done = EINA_FALSE;
5780
5781    ELM_GENLIST_CHECK(obj) NULL;
5782    ELM_GENLIST_DATA_GET(obj, sd);
5783
5784    EINA_INLIST_FOREACH(sd->blocks, itb)
5785      {
5786         if (itb->realized)
5787           {
5788              Eina_List *l;
5789              Elm_Gen_Item *it;
5790
5791              done = EINA_TRUE;
5792              EINA_LIST_FOREACH(itb->items, l, it)
5793                {
5794                   if (it->realized) list = eina_list_append(list, it);
5795                }
5796           }
5797         else
5798           {
5799              if (done) break;
5800           }
5801      }
5802    return list;
5803 }
5804
5805 EAPI Elm_Object_Item *
5806 elm_genlist_at_xy_item_get(const Evas_Object *obj,
5807                            Evas_Coord x,
5808                            Evas_Coord y,
5809                            int *posret)
5810 {
5811    Evas_Coord ox, oy, ow, oh;
5812    Evas_Coord lasty;
5813    Item_Block *itb;
5814
5815    ELM_GENLIST_CHECK(obj) NULL;
5816    ELM_GENLIST_DATA_GET(obj, sd);
5817
5818    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
5819    lasty = oy;
5820    EINA_INLIST_FOREACH(sd->blocks, itb)
5821      {
5822         Eina_List *l;
5823         Elm_Gen_Item *it;
5824
5825         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->sd->pan_x,
5826                                  oy + itb->y - itb->sd->pan_y,
5827                                  itb->w, itb->h, x, y, 1, 1))
5828           continue;
5829         EINA_LIST_FOREACH(itb->items, l, it)
5830           {
5831              Evas_Coord itx, ity;
5832
5833              itx = ox + itb->x + it->x - itb->sd->pan_x;
5834              ity = oy + itb->y + it->y - itb->sd->pan_y;
5835              if (ELM_RECTS_INTERSECT
5836                    (itx, ity, it->item->w, it->item->h, x, y, 1, 1))
5837                {
5838                   if (posret)
5839                     {
5840                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
5841                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
5842                          *posret = 1;
5843                        else *posret = 0;
5844                     }
5845
5846                   return (Elm_Object_Item *)it;
5847                }
5848              lasty = ity + it->item->h;
5849           }
5850      }
5851    if (posret)
5852      {
5853         if (y > lasty) *posret = 1;
5854         else *posret = -1;
5855      }
5856
5857    return NULL;
5858 }
5859
5860 EAPI Elm_Object_Item *
5861 elm_genlist_first_item_get(const Evas_Object *obj)
5862 {
5863    Elm_Gen_Item *tit, *it = NULL;
5864
5865    ELM_GENLIST_CHECK(obj) NULL;
5866    ELM_GENLIST_DATA_GET(obj, sd);
5867
5868    EINA_INLIST_REVERSE_FOREACH(sd->items, tit) it = tit;
5869
5870    return (Elm_Object_Item *)it;
5871 }
5872
5873 EAPI Elm_Object_Item *
5874 elm_genlist_last_item_get(const Evas_Object *obj)
5875 {
5876    Elm_Gen_Item *it;
5877
5878    ELM_GENLIST_CHECK(obj) NULL;
5879    ELM_GENLIST_DATA_GET(obj, sd);
5880    if (!sd->items) return NULL;
5881
5882    it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
5883    return (Elm_Object_Item *)it;
5884 }
5885
5886 EAPI Elm_Object_Item *
5887 elm_genlist_item_next_get(const Elm_Object_Item *item)
5888 {
5889    Elm_Gen_Item *it;
5890
5891    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
5892
5893    it = (Elm_Gen_Item *)item;
5894    while (it)
5895      {
5896         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5897         if (it) break;
5898      }
5899
5900    return (Elm_Object_Item *)it;
5901 }
5902
5903 EAPI Elm_Object_Item *
5904 elm_genlist_item_prev_get(const Elm_Object_Item *item)
5905 {
5906    Elm_Gen_Item *it;
5907
5908    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
5909
5910    it = (Elm_Gen_Item *)item;
5911    while (it)
5912      {
5913         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5914         if (it) break;
5915      }
5916
5917    return (Elm_Object_Item *)it;
5918 }
5919
5920 EAPI Elm_Object_Item *
5921 elm_genlist_item_parent_get(const Elm_Object_Item *it)
5922 {
5923    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
5924
5925    return (Elm_Object_Item *)((Elm_Gen_Item *)it)->parent;
5926 }
5927
5928 EAPI void
5929 elm_genlist_item_subitems_clear(Elm_Object_Item *item)
5930 {
5931    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5932
5933    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5934    _item_subitems_clear(it);
5935 }
5936
5937 EAPI void
5938 elm_genlist_item_selected_set(Elm_Object_Item *item,
5939                               Eina_Bool selected)
5940 {
5941    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5942    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5943
5944    if (elm_widget_item_disabled_get(it)) return;
5945    selected = !!selected;
5946    if (it->selected == selected) return;
5947
5948    _item_select_unselect(it, selected);
5949 }
5950
5951 EAPI Eina_Bool
5952 elm_genlist_item_selected_get(const Elm_Object_Item *it)
5953 {
5954    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5955
5956    return ((Elm_Gen_Item *)it)->selected;
5957 }
5958
5959 static Elm_Gen_Item *
5960 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
5961 {
5962    Elm_Gen_Item *it2;
5963
5964    if (it->item->expanded)
5965      {
5966         it2 = (Elm_Gen_Item *)elm_genlist_item_next_get((Elm_Object_Item *)it);
5967      }
5968    else
5969      {
5970         it2 = (Elm_Gen_Item *)elm_genlist_item_next_get((Elm_Object_Item *)it);
5971         while (it2)
5972           {
5973              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
5974              it2 = (Elm_Gen_Item *)
5975                elm_genlist_item_next_get((Elm_Object_Item *)it2);
5976           }
5977      }
5978    return it2;
5979 }
5980
5981 static Evas_Object *
5982 _tray_alpha_bg_create(const Evas_Object *obj)
5983 {
5984    Evas_Object *bg = NULL;
5985    Evas_Coord ox, oy, ow, oh;
5986
5987    ELM_GENLIST_CHECK(obj) NULL;
5988    ELM_GENLIST_DATA_GET(obj, sd);
5989
5990    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
5991    bg = evas_object_rectangle_add
5992        (evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5993    evas_object_color_set(bg, 0, 0, 0, 0);
5994    evas_object_resize(bg, ow, oh);
5995    evas_object_move(bg, ox, oy);
5996
5997    return bg;
5998 }
5999
6000 EAPI void
6001 elm_genlist_item_expanded_set(Elm_Object_Item *item,
6002                               Eina_Bool expanded)
6003 {
6004    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6005
6006    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6007
6008    expanded = !!expanded;
6009    if (it->item->expanded == expanded) return;
6010    if (it->item->type != ELM_GENLIST_ITEM_TREE) return;
6011    it->item->expanded = expanded;
6012    GL_IT(it)->wsd->expanded_item = it;
6013    GL_IT(it)->wsd->expanded_next_item =
6014      _elm_genlist_expanded_next_item_get(it);
6015
6016    if (it->item->expanded)
6017      {
6018         if (it->realized)
6019           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
6020         evas_object_smart_callback_call(WIDGET(it), SIG_EXPANDED, it);
6021         GL_IT(it)->wsd->auto_scroll_enabled = EINA_TRUE;
6022      }
6023    else
6024      {
6025         if (it->realized)
6026           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
6027         evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACTED, it);
6028         GL_IT(it)->wsd->auto_scroll_enabled = EINA_FALSE;
6029      }
6030 }
6031
6032 EAPI Eina_Bool
6033 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
6034 {
6035    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
6036
6037    return ((Elm_Gen_Item *)it)->item->expanded;
6038 }
6039
6040 EAPI int
6041 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
6042 {
6043    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, 0);
6044
6045    return ((Elm_Gen_Item *)it)->item->expanded_depth;
6046 }
6047
6048 static Eina_Bool
6049 _elm_genlist_item_coordinates_calc(Elm_Object_Item *item,
6050                                    Elm_Genlist_Item_Scrollto_Type type,
6051                                    Eina_Bool bring_in,
6052                                    Evas_Coord *x,
6053                                    Evas_Coord *y,
6054                                    Evas_Coord *w,
6055                                    Evas_Coord *h)
6056 {
6057    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6058    Evas_Coord gith = 0;
6059
6060    if (!((GL_IT(it)->wsd->homogeneous) &&
6061          (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)))
6062      {
6063         if ((it->item->queued) || (!it->item->mincalcd))
6064           {
6065              GL_IT(it)->wsd->show_item = it;
6066              GL_IT(it)->wsd->bring_in = bring_in;
6067              GL_IT(it)->wsd->scroll_to_type = type;
6068              it->item->show_me = EINA_TRUE;
6069              return EINA_FALSE;
6070           }
6071      }
6072    if (GL_IT(it)->wsd->show_item)
6073      {
6074         GL_IT(it)->wsd->show_item->item->show_me = EINA_FALSE;
6075         GL_IT(it)->wsd->show_item = NULL;
6076      }
6077
6078    evas_object_geometry_get(GL_IT(it)->wsd->pan_obj, NULL, NULL, w, h);
6079    switch (type)
6080      {
6081       case ELM_GENLIST_ITEM_SCROLLTO_IN:
6082         if ((it->item->group_item) &&
6083             (GL_IT(it)->wsd->pan_y > (it->y + it->item->block->y)))
6084           gith = it->item->group_item->item->h;
6085         *h = it->item->h;
6086         *y = it->y + it->item->block->y - gith;
6087         break;
6088
6089       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
6090         if (it->item->group_item) gith = it->item->group_item->item->h;
6091         *y = it->y + it->item->block->y - gith;
6092         break;
6093
6094       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
6095         *y = it->y + it->item->block->y - (*h / 2) + (it->item->h / 2);
6096         break;
6097
6098       default:
6099         return EINA_FALSE;
6100      }
6101
6102    *x = it->x + it->item->block->x;
6103    *w = it->item->block->w;
6104
6105    return EINA_TRUE;
6106 }
6107
6108 EAPI void
6109 elm_genlist_item_promote(Elm_Object_Item *item)
6110 {
6111    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6112    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6113    _item_move_before
6114      (it, (Elm_Gen_Item *)elm_genlist_first_item_get(WIDGET(it)));
6115 }
6116
6117 EAPI void
6118 elm_genlist_item_demote(Elm_Object_Item *item)
6119 {
6120    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6121    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6122    _item_move_after(it, (Elm_Gen_Item *)elm_genlist_last_item_get(WIDGET(it)));
6123 }
6124
6125 EAPI void
6126 elm_genlist_item_show(Elm_Object_Item *item,
6127                       Elm_Genlist_Item_Scrollto_Type type)
6128 {
6129    Evas_Coord x, y, w, h;
6130    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6131    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6132
6133    if (_elm_genlist_item_coordinates_calc
6134          (item, type, EINA_FALSE, &x, &y, &w, &h))
6135      GL_IT(it)->wsd->s_iface->content_region_show(WIDGET(item), x, y, w, h);
6136 }
6137
6138 EAPI void
6139 elm_genlist_item_bring_in(Elm_Object_Item *item,
6140                           Elm_Genlist_Item_Scrollto_Type type)
6141 {
6142    Evas_Coord x, y, w, h;
6143    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6144    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6145
6146    if (_elm_genlist_item_coordinates_calc
6147          (item, type, EINA_TRUE, &x, &y, &w, &h))
6148      GL_IT(it)->wsd->s_iface->region_bring_in(WIDGET(item), x, y, w, h);
6149 }
6150
6151 EAPI void
6152 elm_genlist_item_all_contents_unset(Elm_Object_Item *item,
6153                                     Eina_List **l)
6154 {
6155    Evas_Object *content;
6156
6157    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6158    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6159
6160    EINA_LIST_FREE (it->content_objs, content)
6161      {
6162         evas_object_smart_member_del(content);
6163         evas_object_hide(content);
6164         if (l) *l = eina_list_append(*l, content);
6165      }
6166 }
6167
6168 EAPI void
6169 elm_genlist_item_update(Elm_Object_Item *item)
6170 {
6171    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6172    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6173
6174    if (!it->item->block) return;
6175    it->item->mincalcd = EINA_FALSE;
6176    it->item->updateme = EINA_TRUE;
6177    it->item->block->updateme = EINA_TRUE;
6178 #if GENLIST_ENTRY_SUPPORT
6179    it->item->unrealize_disabled = EINA_FALSE;
6180 #endif
6181
6182 #if GENLIST_FX_SUPPORT
6183    if (GL_IT(it)->wsd->fx_first_captured)
6184      _elm_genlist_fx_clear(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj);
6185 #endif
6186
6187    if (GL_IT(it)->wsd->update_job) ecore_job_del(GL_IT(it)->wsd->update_job);
6188    GL_IT(it)->wsd->update_job = ecore_job_add(_update_job, GL_IT(it)->wsd);
6189 }
6190
6191 EAPI void
6192 elm_genlist_item_fields_update(Elm_Object_Item *item,
6193                                const char *parts,
6194                                Elm_Genlist_Item_Field_Type itf)
6195 {
6196    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6197    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6198
6199    if (!it->item->block) return;
6200
6201 #if GENLIST_ENTRY_SUPPORT
6202    it->item->unrealize_disabled = EINA_FALSE;
6203 #endif
6204    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
6205      {
6206         _item_text_realize(it, VIEW(it), &it->texts, parts);
6207      }
6208    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
6209      {
6210         it->content_objs = _item_content_unrealize(it, VIEW(it),
6211                                                    &it->contents, parts);
6212         it->content_objs = _item_content_realize(it, VIEW(it),
6213                                                  &it->contents, parts);
6214
6215         if (it->flipped)
6216           {
6217              it->item->flip_content_objs =
6218                _item_mode_content_unrealize(it, VIEW(it),
6219                                             &it->item->flip_contents, parts,
6220                                             &it->item->flip_content_objs);
6221              it->item->flip_content_objs =
6222                _item_mode_content_realize(it, VIEW(it),
6223                                           &it->item->flip_contents, parts,
6224                                           &it->item->flip_content_objs);
6225           }
6226         if (it->item->deco_it_view)
6227           {
6228              it->item->deco_it_content_objs =
6229                _item_mode_content_unrealize(it, it->item->deco_it_view,
6230                                             &it->item->deco_it_contents, parts,
6231                                             &it->item->deco_it_content_objs);
6232              it->item->deco_it_content_objs =
6233                _item_mode_content_realize(it, it->item->deco_it_view,
6234                                           &it->item->deco_it_contents, parts,
6235                                           &it->item->deco_it_content_objs);
6236           }
6237         if (GL_IT(it)->wsd->decorate_all_mode)
6238           {
6239              it->item->deco_all_content_objs =
6240                _item_mode_content_unrealize
6241                  (it, it->deco_all_view, &it->item->deco_all_contents, parts,
6242                  &it->item->deco_all_content_objs);
6243              it->item->deco_all_content_objs =
6244                _item_mode_content_realize(it, it->deco_all_view,
6245                                           &it->item->deco_all_contents, parts,
6246                                           &it->item->deco_all_content_objs);
6247           }
6248      }
6249
6250    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
6251      _item_state_realize(it, VIEW(it), &it->states, parts);
6252 }
6253
6254 EAPI void
6255 elm_genlist_item_item_class_update(Elm_Object_Item *item,
6256                                    const Elm_Genlist_Item_Class *itc)
6257 {
6258    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6259    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6260
6261    if (!it->item->block) return;
6262    EINA_SAFETY_ON_NULL_RETURN(itc);
6263    it->itc = itc;
6264    it->item->nocache_once = EINA_TRUE;
6265
6266    elm_widget_stringlist_free(it->texts);
6267    it->texts = NULL;
6268    elm_widget_stringlist_free(it->contents);
6269    it->contents = NULL;
6270    elm_widget_stringlist_free(it->states);
6271    it->states = NULL;
6272
6273    if (it->flipped)
6274      {
6275         elm_widget_stringlist_free(it->item->flip_contents);
6276         it->item->flip_contents = NULL;
6277      }
6278    if (it->item->deco_it_view)
6279      {
6280         elm_widget_stringlist_free(it->item->deco_it_texts);
6281         it->item->deco_it_texts = NULL;
6282         elm_widget_stringlist_free(it->item->deco_it_contents);
6283         it->item->deco_it_contents = NULL;
6284      }
6285    if (GL_IT(it)->wsd->decorate_all_mode)
6286      {
6287         elm_widget_stringlist_free(it->item->deco_all_texts);
6288         it->item->deco_all_texts = NULL;
6289         elm_widget_stringlist_free(it->item->deco_all_contents);
6290         it->item->deco_all_contents = NULL;
6291      }
6292
6293    elm_genlist_item_update(item);
6294 }
6295
6296 EAPI const Elm_Genlist_Item_Class *
6297 elm_genlist_item_item_class_get(const Elm_Object_Item *item)
6298 {
6299    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
6300    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6301    return it->itc;
6302 }
6303
6304 static Evas_Object *
6305 _elm_genlist_item_label_create(void *data,
6306                                Evas_Object *obj __UNUSED__,
6307                                Evas_Object *tooltip,
6308                                void *it __UNUSED__)
6309 {
6310    Evas_Object *label = elm_label_add(tooltip);
6311
6312    if (!label)
6313      return NULL;
6314
6315    elm_object_style_set(label, "tooltip");
6316    elm_object_text_set(label, data);
6317
6318    return label;
6319 }
6320
6321 static void
6322 _elm_genlist_item_label_del_cb(void *data,
6323                                Evas_Object *obj __UNUSED__,
6324                                void *event_info __UNUSED__)
6325 {
6326    eina_stringshare_del(data);
6327 }
6328
6329 EAPI void
6330 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
6331                                   const char *text)
6332 {
6333    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
6334
6335    text = eina_stringshare_add(text);
6336    elm_genlist_item_tooltip_content_cb_set
6337      (it, _elm_genlist_item_label_create, text,
6338      _elm_genlist_item_label_del_cb);
6339 }
6340
6341 EAPI void
6342 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item *item,
6343                                         Elm_Tooltip_Item_Content_Cb func,
6344                                         const void *data,
6345                                         Evas_Smart_Cb del_cb)
6346 {
6347    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6348
6349    ELM_GENLIST_ITEM_CHECK_OR_GOTO(item, error);
6350
6351    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
6352      return;
6353
6354    if (it->tooltip.del_cb)
6355      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6356
6357    it->tooltip.content_cb = func;
6358    it->tooltip.data = data;
6359    it->tooltip.del_cb = del_cb;
6360
6361    if (VIEW(it))
6362      {
6363         elm_widget_item_tooltip_content_cb_set
6364           (it, it->tooltip.content_cb, it->tooltip.data, NULL);
6365         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
6366         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
6367      }
6368
6369    return;
6370
6371 error:
6372    if (del_cb) del_cb((void *)data, NULL, NULL);
6373 }
6374
6375 EAPI void
6376 elm_genlist_item_tooltip_unset(Elm_Object_Item *item)
6377 {
6378    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6379
6380    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6381
6382    if ((VIEW(it)) && (it->tooltip.content_cb))
6383      elm_widget_item_tooltip_unset(it);
6384
6385    if (it->tooltip.del_cb)
6386      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6387    it->tooltip.del_cb = NULL;
6388    it->tooltip.content_cb = NULL;
6389    it->tooltip.data = NULL;
6390    it->tooltip.free_size = EINA_FALSE;
6391    if (it->tooltip.style)
6392      elm_genlist_item_tooltip_style_set(item, NULL);
6393 }
6394
6395 EAPI void
6396 elm_genlist_item_tooltip_style_set(Elm_Object_Item *item,
6397                                    const char *style)
6398 {
6399    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6400
6401    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6402
6403    eina_stringshare_replace(&it->tooltip.style, style);
6404    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
6405 }
6406
6407 EAPI const char *
6408 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
6409 {
6410    return elm_object_item_tooltip_style_get(it);
6411 }
6412
6413 EAPI Eina_Bool
6414 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *item,
6415                                          Eina_Bool disable)
6416 {
6417    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6418
6419    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
6420
6421    it->tooltip.free_size = disable;
6422    if (VIEW(it)) return elm_widget_item_tooltip_window_mode_set(it, disable);
6423
6424    return EINA_TRUE;
6425 }
6426
6427 EAPI Eina_Bool
6428 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
6429 {
6430    return elm_object_tooltip_window_mode_get(VIEW(it));
6431 }
6432
6433 EAPI void
6434 elm_genlist_item_cursor_set(Elm_Object_Item *item,
6435                             const char *cursor)
6436 {
6437    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6438
6439    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6440    eina_stringshare_replace(&it->mouse_cursor, cursor);
6441    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
6442 }
6443
6444 EAPI const char *
6445 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
6446 {
6447    return elm_widget_item_cursor_get(it);
6448 }
6449
6450 EAPI void
6451 elm_genlist_item_cursor_unset(Elm_Object_Item *item)
6452 {
6453    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6454
6455    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6456
6457    if (!it->mouse_cursor) return;
6458
6459    if (VIEW(it)) elm_widget_item_cursor_unset(it);
6460
6461    eina_stringshare_del(it->mouse_cursor);
6462    it->mouse_cursor = NULL;
6463 }
6464
6465 EAPI void
6466 elm_genlist_item_cursor_style_set(Elm_Object_Item *it,
6467                                   const char *style)
6468 {
6469    elm_widget_item_cursor_style_set(it, style);
6470 }
6471
6472 EAPI const char *
6473 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
6474 {
6475    return elm_widget_item_cursor_style_get(it);
6476 }
6477
6478 EAPI void
6479 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
6480                                         Eina_Bool engine_only)
6481 {
6482    elm_widget_item_cursor_engine_only_set(it, engine_only);
6483 }
6484
6485 EAPI Eina_Bool
6486 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
6487 {
6488    return elm_widget_item_cursor_engine_only_get(it);
6489 }
6490
6491 EAPI int
6492 elm_genlist_item_index_get(const Elm_Object_Item *item)
6493 {
6494    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6495
6496    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, -1);
6497
6498    if (it->item->block)
6499      return it->position + (it->item->block->position *
6500                             GL_IT(it)->wsd->max_items_per_block);
6501    return -1;
6502 }
6503
6504 EAPI void
6505 elm_genlist_mode_set(Evas_Object *obj,
6506                      Elm_List_Mode mode)
6507 {
6508    ELM_GENLIST_CHECK(obj);
6509    ELM_GENLIST_DATA_GET(obj, sd);
6510
6511    if (sd->mode == mode) return;
6512    sd->mode = mode;
6513    elm_layout_sizing_eval(obj);
6514 }
6515
6516 EAPI Elm_List_Mode
6517 elm_genlist_mode_get(const Evas_Object *obj)
6518 {
6519    ELM_GENLIST_CHECK(obj) ELM_LIST_LAST;
6520    ELM_GENLIST_DATA_GET(obj, sd);
6521
6522    return sd->mode;
6523 }
6524
6525 EAPI void
6526 elm_genlist_bounce_set(Evas_Object *obj,
6527                        Eina_Bool h_bounce,
6528                        Eina_Bool v_bounce)
6529 {
6530    ELM_GENLIST_CHECK(obj);
6531    ELM_GENLIST_DATA_GET(obj, sd);
6532
6533    sd->h_bounce = !!h_bounce;
6534    sd->v_bounce = !!v_bounce;
6535    sd->s_iface->bounce_allow_set(obj, sd->h_bounce, sd->v_bounce);
6536 }
6537
6538 EAPI void
6539 elm_genlist_bounce_get(const Evas_Object *obj,
6540                        Eina_Bool *h_bounce,
6541                        Eina_Bool *v_bounce)
6542 {
6543    ELM_GENLIST_CHECK(obj);
6544    ELM_GENLIST_DATA_GET(obj, sd);
6545
6546    if (h_bounce) *h_bounce = sd->h_bounce;
6547    if (v_bounce) *v_bounce = sd->v_bounce;
6548 }
6549
6550 EAPI void
6551 elm_genlist_homogeneous_set(Evas_Object *obj,
6552                             Eina_Bool homogeneous)
6553 {
6554    ELM_GENLIST_CHECK(obj);
6555    ELM_GENLIST_DATA_GET(obj, sd);
6556
6557    sd->homogeneous = !!homogeneous;
6558 }
6559
6560 EAPI Eina_Bool
6561 elm_genlist_homogeneous_get(const Evas_Object *obj)
6562 {
6563    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6564    ELM_GENLIST_DATA_GET(obj, sd);
6565
6566    return sd->homogeneous;
6567 }
6568
6569 EAPI void
6570 elm_genlist_block_count_set(Evas_Object *obj,
6571                             int count)
6572 {
6573    ELM_GENLIST_CHECK(obj);
6574    ELM_GENLIST_DATA_GET(obj, sd);
6575    EINA_SAFETY_ON_TRUE_RETURN(count < 1);
6576
6577    sd->max_items_per_block = count;
6578    sd->item_cache_max = sd->max_items_per_block * 2;
6579    _item_cache_all_free(sd);
6580 }
6581
6582 EAPI int
6583 elm_genlist_block_count_get(const Evas_Object *obj)
6584 {
6585    ELM_GENLIST_CHECK(obj) 0;
6586    ELM_GENLIST_DATA_GET(obj, sd);
6587
6588    return sd->max_items_per_block;
6589 }
6590
6591 EAPI void
6592 elm_genlist_longpress_timeout_set(Evas_Object *obj,
6593                                   double timeout)
6594 {
6595    ELM_GENLIST_CHECK(obj);
6596    ELM_GENLIST_DATA_GET(obj, sd);
6597
6598    sd->longpress_timeout = timeout;
6599 }
6600
6601 EAPI double
6602 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
6603 {
6604    ELM_GENLIST_CHECK(obj) 0;
6605    ELM_GENLIST_DATA_GET(obj, sd);
6606
6607    return sd->longpress_timeout;
6608 }
6609
6610 EAPI void
6611 elm_genlist_scroller_policy_set(Evas_Object *obj,
6612                                 Elm_Scroller_Policy policy_h,
6613                                 Elm_Scroller_Policy policy_v)
6614 {
6615    ELM_GENLIST_CHECK(obj);
6616    ELM_GENLIST_DATA_GET(obj, sd);
6617
6618    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
6619        (policy_v >= ELM_SCROLLER_POLICY_LAST))
6620      return;
6621
6622    sd->s_iface->policy_set(obj, policy_h, policy_v);
6623 }
6624
6625 EAPI void
6626 elm_genlist_scroller_policy_get(const Evas_Object *obj,
6627                                 Elm_Scroller_Policy *policy_h,
6628                                 Elm_Scroller_Policy *policy_v)
6629 {
6630    Elm_Scroller_Policy s_policy_h, s_policy_v;
6631
6632    ELM_GENLIST_CHECK(obj);
6633    ELM_GENLIST_DATA_GET(obj, sd);
6634
6635    sd->s_iface->policy_get(obj, &s_policy_h, &s_policy_v);
6636    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
6637    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
6638 }
6639
6640 EAPI void
6641 elm_genlist_realized_items_update(Evas_Object *obj)
6642 {
6643    Eina_List *list, *l;
6644    Elm_Object_Item *it;
6645
6646    ELM_GENLIST_CHECK(obj);
6647
6648    list = elm_genlist_realized_items_get(obj);
6649    EINA_LIST_FOREACH(list, l, it)
6650      elm_genlist_item_update(it);
6651 }
6652
6653 EAPI void
6654 elm_genlist_item_decorate_mode_set(Elm_Object_Item *item,
6655                                    const char *decorate_it_type,
6656                                    Eina_Bool decorate_it_set)
6657 {
6658    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6659    Elm_Genlist_Smart_Data *sd;
6660
6661    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6662    sd = GL_IT(it)->wsd;
6663
6664    if (elm_widget_item_disabled_get(it)) return;
6665    if (!decorate_it_type) return;
6666    if (sd->decorate_all_mode) return;
6667
6668    if ((sd->mode_item == it) &&
6669        (!strcmp(decorate_it_type, sd->decorate_it_type)) &&
6670        (decorate_it_set))
6671      return;
6672    if (!it->itc->decorate_item_style) return;
6673    it->decorate_it_set = decorate_it_set;
6674
6675    _item_unselect(it);
6676    if (((sd->decorate_it_type)
6677         && (strcmp(decorate_it_type, sd->decorate_it_type))) ||
6678        (decorate_it_set) || ((it == sd->mode_item) && (!decorate_it_set)))
6679      _decorate_item_unset(sd);
6680
6681    eina_stringshare_replace(&sd->decorate_it_type, decorate_it_type);
6682    if (decorate_it_set) _decorate_item_set(it);
6683 }
6684
6685 EAPI const char *
6686 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *item)
6687 {
6688    Elm_Gen_Item *i = (Elm_Gen_Item *)item;
6689
6690    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
6691    return GL_IT(i)->wsd->decorate_it_type;
6692 }
6693
6694 EAPI Elm_Object_Item *
6695 elm_genlist_decorated_item_get(const Evas_Object *obj)
6696 {
6697    ELM_GENLIST_CHECK(obj) NULL;
6698    ELM_GENLIST_DATA_GET(obj, sd);
6699
6700    return (Elm_Object_Item *)sd->mode_item;
6701 }
6702
6703 EAPI Eina_Bool
6704 elm_genlist_decorate_mode_get(const Evas_Object *obj)
6705 {
6706    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6707    ELM_GENLIST_DATA_GET(obj, sd);
6708
6709    return sd->decorate_all_mode;
6710 }
6711
6712 EAPI void
6713 elm_genlist_decorate_mode_set(Evas_Object *obj,
6714                               Eina_Bool decorated)
6715 {
6716    Elm_Gen_Item *it;
6717    Eina_List *list, *l;
6718
6719    ELM_GENLIST_CHECK(obj);
6720    ELM_GENLIST_DATA_GET(obj, sd);
6721
6722    decorated = !!decorated;
6723    if (sd->decorate_all_mode == decorated) return;
6724    // decorate_all_mode should be set first
6725    // because content_get func. will be called after this
6726    // and user can check whether deocrate_all_mode is enabeld.
6727    sd->decorate_all_mode = decorated;
6728
6729    list = elm_genlist_realized_items_get(obj);
6730    if (!sd->decorate_all_mode)
6731      {
6732         EINA_LIST_FOREACH(list, l, it)
6733           {
6734              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6735                _decorate_all_item_unrealize(it);
6736           }
6737         _item_cache_all_free(sd);
6738      }
6739    else
6740      {
6741         EINA_LIST_FOREACH(list, l, it)
6742           {
6743              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6744                {
6745                   if (it->itc->decorate_all_item_style)
6746                     _decorate_all_item_realize(it, EINA_TRUE);
6747                }
6748           }
6749      }
6750 #if GENLIST_FX_SUPPORT
6751    if (sd->fx_first_captured)
6752      _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj);
6753
6754 #endif
6755    if (sd->calc_job) ecore_job_del(sd->calc_job);
6756    sd->calc_job = ecore_job_add(_calc_job, sd);
6757 }
6758
6759 EAPI void
6760 elm_genlist_reorder_mode_set(Evas_Object *obj,
6761                              Eina_Bool reorder_mode)
6762 {
6763 #if 1 // FIXME: difference from upstream
6764    Eina_List *list, *l;
6765    Elm_Gen_Item *it;
6766 #endif
6767    ELM_GENLIST_CHECK(obj);
6768    ELM_GENLIST_DATA_GET(obj, sd);
6769
6770    if (sd->reorder_mode == !!reorder_mode) return;
6771    sd->reorder_mode = !!reorder_mode;
6772 #if 1 // FIXME: difference from upstream
6773    list = elm_genlist_realized_items_get(obj);
6774    EINA_LIST_FOREACH(list, l, it)
6775      {
6776         if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6777           {
6778              Evas_Object *view;
6779              if (it->deco_all_view) view = it->deco_all_view;
6780              else view = VIEW(it);
6781
6782              if (sd->reorder_mode)
6783                edje_object_signal_emit
6784                  (view, "elm,state,reorder,mode_set", "elm");
6785              else
6786                edje_object_signal_emit
6787                  (view, "elm,state,reorder,mode_unset", "elm");
6788           }
6789      }
6790    eina_list_free(list);
6791 #endif
6792 }
6793
6794 EAPI Eina_Bool
6795 elm_genlist_reorder_mode_get(const Evas_Object *obj)
6796 {
6797    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6798    ELM_GENLIST_DATA_GET(obj, sd);
6799
6800    return sd->reorder_mode;
6801 }
6802
6803 EAPI Elm_Genlist_Item_Type
6804 elm_genlist_item_type_get(const Elm_Object_Item *item)
6805 {
6806    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6807
6808    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, ELM_GENLIST_ITEM_MAX);
6809
6810    return it->item->type;
6811 }
6812
6813 EAPI Elm_Genlist_Item_Class *
6814 elm_genlist_item_class_new(void)
6815 {
6816    Elm_Genlist_Item_Class *itc = ELM_NEW(Elm_Genlist_Item_Class);
6817    EINA_SAFETY_ON_NULL_RETURN_VAL(itc, NULL);
6818
6819    itc->version = CLASS_ALLOCATED;
6820    itc->refcount = 1;
6821    itc->delete_me = EINA_FALSE;
6822
6823    return itc;
6824 }
6825
6826 EAPI void
6827 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
6828 {
6829    if (itc && (itc->version == CLASS_ALLOCATED))
6830      {
6831         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
6832         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
6833         else
6834           {
6835              itc->version = 0;
6836              free(itc);
6837           }
6838      }
6839 }
6840
6841 EAPI void
6842 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
6843 {
6844    if (itc && (itc->version == CLASS_ALLOCATED))
6845      {
6846         itc->refcount++;
6847         if (itc->refcount == 0) itc->refcount--;
6848      }
6849 }
6850
6851 EAPI void
6852 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
6853 {
6854    if (itc && (itc->version == CLASS_ALLOCATED))
6855      {
6856         if (itc->refcount > 0) itc->refcount--;
6857         if (itc->delete_me && (!itc->refcount))
6858           elm_genlist_item_class_free(itc);
6859      }
6860 }
6861
6862 EAPI void
6863 elm_genlist_item_flip_set(Elm_Object_Item *item,
6864                           Eina_Bool flip)
6865 {
6866    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6867    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6868    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
6869
6870    flip = !!flip;
6871    if (it->flipped == flip) return;
6872
6873    it->item->unrealize_disabled = EINA_FALSE;
6874    if (flip)
6875      {
6876         _item_unselect(it);
6877         _item_unrealize(it, EINA_FALSE);
6878         it->flipped = EINA_TRUE;
6879         it->item->nocache = EINA_TRUE;
6880      }
6881    else
6882      {
6883         _item_unrealize(it, EINA_FALSE);
6884         it->flipped = EINA_FALSE;
6885         it->item->nocache = EINA_FALSE;
6886      }
6887    if (sd->calc_job) ecore_job_del(sd->calc_job);
6888    sd->calc_job = ecore_job_add(_calc_job, sd);
6889 }
6890
6891 EAPI Eina_Bool
6892 elm_genlist_item_flip_get(const Elm_Object_Item *item)
6893 {
6894    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6895
6896    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
6897
6898    return it->flipped;
6899 }
6900
6901 EAPI void
6902 elm_genlist_select_mode_set(Evas_Object *obj,
6903                             Elm_Object_Select_Mode mode)
6904 {
6905    ELM_GENLIST_CHECK(obj);
6906    ELM_GENLIST_DATA_GET(obj, sd);
6907
6908    if (mode >= ELM_OBJECT_SELECT_MODE_MAX || (sd->select_mode == mode))
6909      return;
6910
6911    sd->select_mode = mode;
6912    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
6913        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ))
6914      {
6915         Eina_List *l, *ll;
6916         Elm_Gen_Item *it;
6917         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, it)
6918           _item_unselect(it);
6919      }
6920 }
6921
6922 EAPI Elm_Object_Select_Mode
6923 elm_genlist_select_mode_get(const Evas_Object *obj)
6924 {
6925    ELM_GENLIST_CHECK(obj) ELM_OBJECT_SELECT_MODE_MAX;
6926    ELM_GENLIST_DATA_GET(obj, sd);
6927
6928    return sd->select_mode;
6929 }
6930
6931 EAPI void
6932 elm_genlist_highlight_mode_set(Evas_Object *obj,
6933                                Eina_Bool highlight)
6934 {
6935    ELM_GENLIST_CHECK(obj);
6936    ELM_GENLIST_DATA_GET(obj, sd);
6937
6938    sd->highlight = !!highlight;
6939 }
6940
6941 EAPI Eina_Bool
6942 elm_genlist_highlight_mode_get(const Evas_Object *obj)
6943 {
6944    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6945    ELM_GENLIST_DATA_GET(obj, sd);
6946
6947    return sd->highlight;
6948 }
6949
6950 EAPI void
6951 elm_genlist_item_select_mode_set(Elm_Object_Item *item,
6952                                  Elm_Object_Select_Mode mode)
6953 {
6954    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6955
6956    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6957    if (!it) return;
6958    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6959      return;
6960    if (it->select_mode != mode)
6961      it->select_mode = mode;
6962
6963    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
6964        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ))
6965       _item_unselect(it);
6966
6967    if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
6968      {
6969         it->item->mincalcd = EINA_FALSE;
6970         it->item->updateme = EINA_TRUE;
6971         if (it->item->block) it->item->block->updateme = EINA_TRUE;
6972         if (GL_IT(it)->wsd->update_job)
6973           ecore_job_del(GL_IT(it)->wsd->update_job);
6974         GL_IT(it)->wsd->update_job =
6975           ecore_job_add(_update_job, GL_IT(it)->wsd);
6976
6977         // reset homogeneous item size
6978         if (GL_IT(it)->wsd->homogeneous)
6979           {
6980              if (it->group)
6981                GL_IT(it)->wsd->group_item_width =
6982                  GL_IT(it)->wsd->group_item_height = 0;
6983              else
6984                GL_IT(it)->wsd->item_width = GL_IT(it)->wsd->item_height = 0;
6985           }
6986      }
6987 }
6988
6989 EAPI Elm_Object_Select_Mode
6990 elm_genlist_item_select_mode_get(const Elm_Object_Item *item)
6991 {
6992    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6993
6994    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, ELM_OBJECT_SELECT_MODE_MAX);
6995
6996    if (!it) return ELM_OBJECT_SELECT_MODE_MAX;
6997
6998    return it->select_mode;
6999 }
7000
7001 // will be deprecated
7002 EAPI void
7003 elm_genlist_tree_effect_enabled_set(Evas_Object *obj __UNUSED__,
7004                                     Eina_Bool enabled __UNUSED__)
7005 {
7006    ELM_GENLIST_CHECK(obj);
7007 }
7008
7009 // will be deprecated
7010 EAPI Eina_Bool
7011 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj __UNUSED__)
7012 {
7013    ELM_GENLIST_CHECK(obj) EINA_FALSE;
7014
7015    return EINA_FALSE;
7016 }
7017
7018 EAPI Elm_Object_Item *
7019 elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
7020 {
7021    Elm_Gen_Item *it = NULL;
7022    Eina_Accessor *a;
7023    void *data;
7024
7025    ELM_GENLIST_CHECK(obj) NULL;
7026    ELM_GENLIST_DATA_GET(obj, sd);
7027
7028    if (!sd->items) return NULL;
7029
7030    a = eina_inlist_accessor_new(sd->items);
7031    if (!a) return NULL;
7032    if (eina_accessor_data_get(a, nth, &data))
7033      it = ELM_GEN_ITEM_FROM_INLIST(data);
7034    eina_accessor_free(a);
7035    return (Elm_Object_Item *)it;
7036 }
7037
7038 #if GENLIST_FX_SUPPORT
7039 EAPI void
7040 elm_genlist_fx_mode_set(Evas_Object *obj, Eina_Bool mode)
7041 {
7042    ELM_GENLIST_CHECK(obj);
7043    ELM_GENLIST_DATA_GET(obj, sd);
7044
7045    sd->fx_mode = mode;
7046 }
7047
7048 EAPI Eina_Bool
7049 elm_genlist_fx_mode_get(const Evas_Object *obj)
7050 {
7051    ELM_GENLIST_CHECK(obj) EINA_FALSE;
7052    ELM_GENLIST_DATA_GET(obj, sd);
7053
7054    return sd->fx_mode;
7055 }
7056
7057 static void
7058 _elm_genlist_proxy_item_del(const Elm_Object_Item *item)
7059 {
7060    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
7061    if ((!it) || (!it->item)) return;
7062
7063    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
7064    Proxy_Item *pi;
7065    Eina_List *l;
7066
7067    EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
7068       if (pi->it == it) pi->it = NULL;
7069
7070    EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
7071       if (pi->it == it) pi->it = NULL;
7072 }
7073
7074 static Proxy_Item *
7075 _elm_genlist_proxy_item_new(const Elm_Object_Item *item)
7076 {
7077    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
7078    if ((!it) || (!it->item)) return EINA_FALSE;
7079    int w, h;
7080
7081    Proxy_Item *pi = NULL;
7082    pi = calloc(1, sizeof(Proxy_Item));
7083    if (!pi) return NULL;
7084
7085    pi->proxy = evas_object_image_filled_add
7086       (evas_object_evas_get(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj));
7087    if (!pi->proxy) return EINA_FALSE;
7088    evas_object_clip_set(pi->proxy, evas_object_clip_get(GL_IT(it)->wsd->pan_obj));
7089    evas_object_smart_member_add(pi->proxy, GL_IT(it)->wsd->pan_obj);
7090    evas_object_hide(pi->proxy);
7091
7092    if ((GL_IT(it)->wsd->decorate_all_mode) && (it->deco_all_view))
7093      evas_object_image_source_set(pi->proxy, it->deco_all_view);
7094    else
7095      evas_object_image_source_set(pi->proxy, VIEW(it));
7096
7097    GL_IT(it)->has_proxy_it = EINA_TRUE;
7098    pi->it = it;
7099    pi->num = it->item->num;
7100    pi->x = it->item->scrl_x;
7101    pi->y = it->item->scrl_y;
7102    pi->w = it->item->w;
7103    pi->h = it->item->h;
7104
7105    evas_object_geometry_get(VIEW(it), NULL, NULL, &w, &h);
7106
7107    if (w <= 0 || h <= 0)
7108      {
7109         evas_object_size_hint_min_get(VIEW(it), &w, &h);
7110         evas_object_size_hint_min_set(pi->proxy, w, h);
7111      }
7112    else evas_object_resize(pi->proxy, w, h);
7113
7114    return pi;
7115 }
7116
7117 static Eina_Bool
7118 _elm_genlist_fx_capture(Evas_Object *obj, int level)
7119 {
7120    ELM_GENLIST_DATA_GET(obj, sd);
7121
7122    Item_Block *itb;
7123    Eina_List *l;
7124    Eina_Bool done = EINA_FALSE;
7125    Elm_Gen_Item *it;
7126    Proxy_Item *pi;
7127    Evas_Coord ox, oy, ow, oh;
7128
7129    if (!sd->sorting)
7130      {
7131         if ((!sd->rendered) || (sd->fx_playing)) return EINA_FALSE;
7132         if ((!level) && (sd->fx_first_captured)) return EINA_FALSE;
7133         if ((level) && (!sd->fx_first_captured)) return EINA_FALSE;
7134      }
7135    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7136
7137    if (!level)
7138      {
7139         sd->fx_first_captured = EINA_TRUE;
7140         EINA_LIST_FREE(sd->capture_before_items, pi)
7141           {
7142              if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
7143              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
7144              if (pi->proxy) evas_object_del(pi->proxy);
7145              free(pi);
7146           }
7147      }
7148    else
7149      {
7150         EINA_LIST_FREE(sd->capture_after_items, pi)
7151           {
7152              if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
7153              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
7154              if (pi->proxy) evas_object_del(pi->proxy);
7155              free(pi);
7156           }
7157
7158         EINA_INLIST_FOREACH(sd->blocks, itb)
7159           {
7160              if (itb->realized)
7161                {
7162                   EINA_LIST_FOREACH(itb->items, l, it)
7163                     {
7164                        if (it->realized && it->item->scrl_y >= oy)
7165                          {
7166                             sd->realized_top_item = it;
7167                             break;
7168                          }
7169                     }
7170                }
7171              if (sd->realized_top_item) break;
7172           }
7173      }
7174
7175 #if GENLIST_PINCH_ZOOM_SUPPORT
7176    if (sd->pinch_zoom_mode)
7177      {
7178         EINA_INLIST_FOREACH(sd->blocks, itb)
7179           {
7180              EINA_LIST_FOREACH(itb->items, l, it)
7181                {
7182
7183                   if (IS_ROOT_PARENT_IT(it) && it->realized
7184                       && (GL_IT(it)->scrl_y + GL_IT(it)->h >= oy && GL_IT(it)->scrl_y <= oy + oh))
7185                     {
7186                        pi = _elm_genlist_proxy_item_new((Elm_Object_Item *)it);
7187                        if (!level) sd->capture_before_items = eina_list_append(sd->capture_before_items, pi);
7188                        else sd->capture_after_items = eina_list_append(sd->capture_after_items, pi);
7189                     }
7190                }
7191           }
7192         if ((sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT) && (level)) return EINA_TRUE;
7193         if ((sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_EXPAND) && (!level)) return EINA_TRUE;
7194      }
7195 #endif
7196
7197    EINA_INLIST_FOREACH(sd->blocks, itb)
7198      {
7199         if (itb->realized)
7200           {
7201              done = EINA_TRUE;
7202              EINA_LIST_FOREACH(itb->items, l, it)
7203                {
7204 #if GENLIST_PINCH_ZOOM_SUPPORT
7205                   if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(it))) continue;
7206 #endif
7207                   if (it->realized)
7208                     {
7209                        pi = _elm_genlist_proxy_item_new((Elm_Object_Item *)it);
7210                        if (!pi) continue;
7211                        if (!level)
7212                          sd->capture_before_items = eina_list_append(sd->capture_before_items, pi);
7213                        else
7214                          sd->capture_after_items = eina_list_append(sd->capture_after_items, pi);
7215                     }
7216                }
7217           }
7218         else if (done) break;
7219      }
7220    return EINA_TRUE;
7221 }
7222
7223 static Elm_Gen_FX_Item *
7224 _elm_genlist_fx_item_find(const Elm_Object_Item *item)
7225 {
7226    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
7227    if (!it) return EINA_FALSE;
7228
7229    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
7230    if (!sd) return NULL;
7231
7232    Elm_Gen_FX_Item *fi = NULL;
7233    Eina_List *l;
7234
7235    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7236      {
7237         if (fi->it == it) return fi;
7238      }
7239    return NULL;
7240 }
7241
7242 static Elm_Gen_FX_Item *
7243 _elm_genlist_fx_item_new(const Proxy_Item *pi)
7244 {
7245    if ((!pi) || (!pi->it)) return NULL;
7246
7247    Elm_Gen_FX_Item *fi = NULL;
7248    fi = calloc(1, sizeof(Elm_Gen_FX_Item));
7249    if (!fi) return NULL;
7250
7251    fi->it = pi->it;
7252    GL_IT(fi->it)->fi = fi;
7253    fi->proxy = pi->proxy;
7254    fi->num = pi->num;
7255    fi->from.x = fi->to.x = pi->x;
7256    fi->from.y = fi->to.y = pi->y;
7257    fi->from.w = fi->to.w = pi->w;
7258    fi->from.h = fi->to.h = pi->h;
7259    fi->update = EINA_FALSE;
7260
7261    return fi;
7262 }
7263
7264 static Elm_Object_Item *
7265 _elm_genlist_fx_item_prev_get(const Elm_Object_Item *item)
7266 {
7267    Elm_Gen_Item *it;
7268    it = (Elm_Gen_Item *)item;
7269    if (!it) return NULL;
7270    if (GL_IT(it)->wsd->pinch_zoom_mode) return NULL;
7271
7272    while (it)
7273      {
7274         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
7275         if (it) break;
7276      }
7277
7278    return (Elm_Object_Item *)it;
7279 }
7280
7281 EAPI Eina_Bool
7282 _elm_genlist_fx_items_make(Evas_Object *obj)
7283 {
7284    ELM_GENLIST_CHECK(obj) EINA_FALSE;
7285    ELM_GENLIST_DATA_GET(obj, sd);
7286
7287    Elm_Gen_FX_Item *fi;
7288    Proxy_Item *pi;
7289    Eina_List *l;
7290    Elm_Gen_Item *prev = NULL;
7291    Evas_Coord ox, oy, ow, oh, mv_dist, max_mv_dist = 0;
7292
7293    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7294
7295    EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
7296      {
7297         fi = _elm_genlist_fx_item_new(pi);
7298         if (fi) sd->fx_items = eina_list_append(sd->fx_items, fi);
7299      }
7300
7301    EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
7302      {
7303         fi = _elm_genlist_fx_item_find((Elm_Object_Item *)pi->it);
7304
7305         if (fi) // pi exists in both before and after capture items
7306           {
7307              fi->type = ELM_GEN_ITEM_FX_TYPE_SAME;
7308              fi->update = EINA_TRUE;
7309              fi->to.x = pi->x;
7310              fi->to.y = pi->y;
7311              fi->to.w = pi->w;
7312              fi->to.h = pi->h;
7313
7314              // find the max distance between before and after capture items
7315              mv_dist = abs(fi->to.y - fi->from.y);
7316              if (max_mv_dist < mv_dist) max_mv_dist = mv_dist;
7317           }
7318         else  // pi only exists in after capture items
7319           {
7320              fi = _elm_genlist_fx_item_new(pi);
7321              if (fi)
7322                {
7323                   fi->type = ELM_GEN_ITEM_FX_TYPE_ADD;
7324                   fi->update = EINA_TRUE;
7325                   sd->fx_items = eina_list_append(sd->fx_items, fi);
7326                }
7327           }
7328      }
7329
7330    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7331      {
7332         // find deleted items
7333         if (!fi->update) // pi only exists in before capture items
7334           {
7335              fi->type = ELM_GEN_ITEM_FX_TYPE_DEL;
7336              fi->update = EINA_TRUE;
7337
7338              prev = (Elm_Gen_Item *)_elm_genlist_fx_item_prev_get((Elm_Object_Item *)fi->it);
7339              if ((prev) && (GL_IT(prev)->fi))
7340                {
7341                   fi->to.y = GL_IT(prev)->fi->to.y + GL_IT(prev)->fi->to.h;
7342                }
7343           }
7344         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_ADD)
7345           {
7346              prev = (Elm_Gen_Item *)_elm_genlist_fx_item_prev_get((Elm_Object_Item *)fi->it);
7347              if ((prev) && (prev->realized) && (GL_IT(prev)->fi))
7348                {
7349                   fi->from.y = GL_IT(prev)->fi->from.y + GL_IT(prev)->fi->from.h;
7350                }
7351              else
7352                {
7353                   if (sd->realized_top_item)
7354                     {
7355
7356                        if (fi->num <= sd->realized_top_item->item->num)
7357                          fi->from.y -= max_mv_dist;
7358                        else
7359                          fi->from.y += max_mv_dist;
7360                     }
7361                }
7362           }
7363      }
7364
7365    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7366      {
7367         if ((GL_IT(fi->it)->items) && (GL_IT(fi->it)->expanded_depth == 0))
7368           {
7369 #if GENLIST_PINCH_ZOOM_SUPPORT
7370              if (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
7371                {
7372                   fi->from.y = oy + GL_IT(fi->it)->pan_scrl_y - sd->pinch_pan_y;
7373                }
7374 #endif
7375              if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
7376                {
7377                   if (sd->realized_top_item)
7378                     {
7379                        if (fi->num <= sd->realized_top_item->item->num)
7380                          fi->to.y = oy - fi->from.h;
7381                        else
7382                          fi->to.y = oy + oh;
7383                     }
7384                }
7385           }
7386      }
7387
7388    return EINA_TRUE;
7389 }
7390
7391 static Elm_Gen_FX_Item *
7392 _fx_cover_item_get(const Elm_Gen_FX_Item *fi)
7393 {
7394    Elm_Gen_FX_Item *cover_fi;
7395    Eina_List *l;
7396    if (!fi) return NULL;
7397
7398    Elm_Genlist_Smart_Data *sd = GL_IT(fi->it)->wsd;
7399    Evas_Coord ox, oy, ow, oh;
7400    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7401
7402    EINA_LIST_FOREACH(sd->fx_items, l, cover_fi)
7403      {
7404         if (fi == cover_fi) continue;
7405         if (sd->fx_items_deleted)
7406           {
7407              if ((cover_fi->from.y >= oy+oh || cover_fi->from.y > fi->to.y) && (cover_fi->from.y - cover_fi->to.y > 0))
7408                return cover_fi;
7409           }
7410         else
7411           {
7412              if ((cover_fi->to.y > fi->to.y) && (cover_fi->from.y - cover_fi->to.y < 0))
7413                return cover_fi;
7414           }
7415      }
7416    return NULL;
7417 }
7418
7419 static void
7420 _item_fx_op(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__, double progress __UNUSED__)
7421 {
7422    Elm_Gen_FX_Item *fi = data, *cover_it;
7423    Elm_Genlist_Smart_Data *sd = GL_IT(fi->it)->wsd;
7424    Evas_Coord fi_ox, fi_oy, cover_it_ox, cover_it_oy, ox, oy, ow, oh;
7425
7426    evas_object_show(VIEW(fi->it));
7427    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7428    evas_object_geometry_get(fi->proxy, &fi_ox, &fi_oy, NULL, NULL);
7429    evas_object_move(fi->proxy, ox, fi_oy);
7430    evas_object_show(fi->proxy);
7431 #if GENLIST_PINCH_ZOOM_SUPPORT
7432    if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(fi->it))) evas_object_raise(fi->proxy);
7433 #endif
7434
7435    if ((!sd->expanded_next_item) || (sd->expanded_next_item == fi->it)) goto raise_event_block;
7436    if (fi->type == ELM_GEN_ITEM_FX_TYPE_SAME) goto raise_event_block;
7437
7438    // find the closest item that cover current item when deleting
7439    cover_it = _fx_cover_item_get(fi);
7440    if (cover_it)
7441      {
7442         evas_object_geometry_get(cover_it->proxy, &cover_it_ox, &cover_it_oy, NULL, NULL);
7443
7444         if (sd->fx_items_deleted)
7445           {
7446              if (cover_it_oy
7447                  && (fi_oy + fi->to.h >= cover_it_oy + cover_it->to.h ) && (fi->from.y < cover_it->from.y))
7448                evas_object_hide(fi->proxy);
7449           }
7450         else if (cover_it_oy && (fi_oy >= cover_it_oy))
7451           evas_object_hide(fi->proxy);
7452         else
7453           evas_object_show(fi->proxy);
7454      }
7455
7456 raise_event_block:
7457    evas_object_raise(sd->alpha_bg);
7458
7459    return;
7460 }
7461
7462
7463 static void
7464 _item_fx_done(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__)
7465 {
7466    Elm_Gen_FX_Item *fx_done_it = data;
7467    Elm_Genlist_Smart_Data *sd = GL_IT(fx_done_it->it)->wsd;
7468
7469    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
7470
7471    evas_object_image_source_visible_set(fx_done_it->proxy, EINA_TRUE);
7472    evas_object_lower(fx_done_it->proxy);
7473
7474    if ((sd->decorate_all_mode) && (fx_done_it->it->deco_all_view))
7475      evas_object_move(fx_done_it->it->deco_all_view, fx_done_it->to.x, fx_done_it->to.y);
7476    else
7477      evas_object_move(VIEW(fx_done_it->it), fx_done_it->to.x, fx_done_it->to.y);
7478    GL_IT(fx_done_it->it)->has_proxy_it = EINA_FALSE;
7479
7480    evas_object_clip_unset(fx_done_it->proxy);
7481 }
7482
7483 static void
7484 _item_fx_del_cb(void *data, Elm_Transit *transit __UNUSED__)
7485 {
7486    Elm_Gen_FX_Item *fx_done_it = data;
7487    Elm_Gen_Item *it = NULL;
7488    Proxy_Item *pi = NULL;
7489    Eina_List *l;
7490    Elm_Genlist_Smart_Data *sd = GL_IT(fx_done_it->it)->wsd;
7491
7492    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
7493
7494    sd->fx_items = eina_list_remove(sd->fx_items, fx_done_it);
7495    GL_IT(fx_done_it->it)->fi = NULL;
7496    free(fx_done_it);
7497
7498    if (!eina_list_count(sd->fx_items))
7499      {
7500         EINA_LIST_FREE (sd->pending_unrealized_items, it)
7501           {
7502              if (GL_IT(it)) GL_IT(it)->has_proxy_it = EINA_FALSE;
7503 #if GENLIST_PINCH_ZOOM_SUPPORT
7504              if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(it))) continue;
7505 #endif
7506              _item_unrealize(it, EINA_FALSE);
7507           }
7508         EINA_LIST_FREE (sd->pending_unrealized_decorate_all_items, it)
7509           {
7510              if (GL_IT(it)) GL_IT(it)->has_proxy_it = EINA_FALSE;
7511 #if GENLIST_PINCH_ZOOM_SUPPORT
7512              if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(it))) continue;
7513 #endif
7514              _decorate_all_item_unrealize(it);
7515           }
7516
7517         EINA_LIST_FREE (sd->pending_del_items, it)
7518           {
7519              _item_free(it);
7520              _elm_widget_item_free((Elm_Widget_Item *)it);
7521           }
7522
7523         EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
7524            evas_object_hide(pi->proxy);
7525         EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
7526            evas_object_hide(pi->proxy);
7527
7528         sd->fx_playing = EINA_FALSE;
7529         sd->sorting = EINA_FALSE;
7530         sd->fx_first_captured = EINA_FALSE;
7531         evas_object_hide(sd->alpha_bg);
7532
7533         sd->realized_top_item = NULL;
7534         sd->pan_changed = EINA_TRUE;
7535         evas_object_smart_changed(sd->pan_obj);
7536      }
7537 }
7538
7539 static Eina_Bool
7540 _sorting_effect_animator_cb(void *data)
7541 {
7542    Elm_Genlist_Smart_Data *sd = data;
7543    Elm_Gen_FX_Item *fi;
7544    Eina_List *l;
7545
7546    Evas_Coord ox, oy, ow, oh;
7547    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7548
7549    sd->fx_timer = NULL;
7550    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7551      {
7552         if (!fi->changed)
7553           {
7554              fi->changed = EINA_TRUE;
7555              evas_object_resize(fi->proxy, ow, fi->to.h);
7556
7557              fi->trans = elm_transit_add();
7558              elm_transit_object_add(fi->trans, fi->proxy);
7559              evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
7560              elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
7561
7562              elm_transit_effect_translation_add(fi->trans, fi->to.x, fi->to.y - 30 * elm_config_scale_get(), fi->to.x, fi->to.y);
7563              elm_transit_effect_color_add(fi->trans,0, 0, 0, 0, 255,255,255,255);
7564
7565              elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
7566              elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
7567              elm_transit_duration_set(fi->trans,0.3);
7568              elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
7569              elm_transit_go(fi->trans);
7570
7571              return ECORE_CALLBACK_RENEW;
7572           }
7573      }
7574    return ECORE_CALLBACK_CANCEL;
7575 }
7576
7577 static void
7578 _elm_genlist_fx_play(Evas_Object *obj)
7579 {
7580    ELM_GENLIST_CHECK(obj);
7581    ELM_GENLIST_DATA_GET(obj, sd);
7582
7583    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
7584    Elm_Gen_FX_Item *fi;
7585    Eina_List *l;
7586
7587    if (!sd->fx_mode) return;
7588
7589    EINA_LIST_FREE(sd->fx_items, fi)
7590      {
7591         if (fi->trans) elm_transit_del(fi->trans);
7592         free(fi);
7593      }
7594    _item_cache_all_free(sd);
7595
7596    _elm_genlist_fx_items_make(obj);
7597    if (!eina_list_count(sd->fx_items) || (sd->queue))
7598      {
7599         _elm_genlist_fx_clear(obj);
7600         return;
7601      }
7602
7603    sd->fx_playing = EINA_TRUE;
7604
7605    if (!sd->alpha_bg) sd->alpha_bg = _tray_alpha_bg_create(obj);
7606    evas_object_show(sd->alpha_bg);
7607
7608    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7609    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
7610
7611    if (sd->sorting)
7612      {
7613         EINA_LIST_FOREACH(sd->fx_items, l, fi)
7614            evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
7615         if (sd->fx_timer) ecore_timer_del(sd->fx_timer);
7616         sd->fx_timer = ecore_timer_add(0.05, _sorting_effect_animator_cb, sd);
7617         return;
7618      }
7619
7620    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7621      {
7622         if (!fi->proxy) continue;
7623
7624         if ((fi->from.y <= oy) || (fi->from.y + fi->from.h >= oy + oh))
7625           {
7626              if ((sd->decorate_all_mode) && (fi->it->deco_all_view))
7627                evas_object_move(fi->it->deco_all_view, cvx, fi->to.y);
7628              else
7629                evas_object_move(VIEW(fi->it), cvx, fi->to.y);
7630           }
7631         else if ((fi->to.y <= oy) || (fi->to.y + fi->to.h >= oy + oh))
7632           {
7633              if ((sd->decorate_all_mode) && (fi->it->deco_all_view))
7634                evas_object_move(fi->it->deco_all_view, cvx, fi->from.y);
7635              else
7636                evas_object_move(VIEW(fi->it), cvx, fi->from.y);
7637           }
7638
7639         evas_object_resize(fi->proxy, ow, fi->to.h);
7640         evas_object_show(fi->proxy);
7641
7642         fi->trans = elm_transit_add();
7643         elm_transit_object_add(fi->trans, fi->proxy);
7644
7645         evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
7646         elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
7647
7648         if (fi->type == ELM_GEN_ITEM_FX_TYPE_SAME)
7649           {
7650              evas_object_raise(fi->proxy);
7651              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
7652           }
7653
7654         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_ADD)
7655           {
7656              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
7657              elm_transit_effect_color_add(fi->trans, 0, 0, 0, 0, 255, 255, 255, 255);
7658           }
7659         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
7660           {
7661              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
7662              elm_transit_effect_color_add(fi->trans, 255, 255, 255, 255, 0, 0, 0, 0);
7663           }
7664         elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
7665         elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
7666
7667         elm_transit_duration_set(fi->trans, FX_MOVE_TIME);
7668         elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
7669         elm_transit_go(fi->trans);
7670      }
7671 }
7672 #endif
7673
7674 #if GENLIST_PINCH_ZOOM_SUPPORT
7675 EAPI Eina_Bool
7676 elm_genlist_pinch_zoom_mode_set(Evas_Object *obj, Elm_Gen_Pinch_Zoom_Mode mode)
7677 {
7678    ELM_GENLIST_DATA_GET(obj, sd);
7679
7680    Item_Block *itb;
7681    Eina_List *l;
7682    Elm_Gen_Item *it;
7683    Eina_Bool done = EINA_FALSE;
7684
7685    if ((sd->queue) || (!sd->rendered) || (sd->queue_idle_enterer)) return EINA_FALSE;
7686
7687    EINA_INLIST_FOREACH(sd->blocks, itb)
7688      {
7689         EINA_LIST_FOREACH(itb->items, l, it)
7690           {
7691
7692              if (IS_ROOT_PARENT_IT(it))
7693                {
7694                   done = EINA_TRUE;
7695                   break;
7696                }
7697           }
7698         if (done) break;
7699      }
7700    if (!done) return EINA_FALSE;
7701
7702    sd->pinch_zoom_mode = mode;
7703
7704    _item_cache_all_free(sd);
7705    _elm_genlist_fx_capture(obj, 0);
7706
7707    sd->pinch_pan_y = sd->pan_y;
7708
7709    if (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
7710      sd->s_iface->content_region_show(obj, 0,0,0,0);
7711
7712    sd->pan_changed = EINA_TRUE;
7713    evas_object_smart_changed(sd->pan_obj);
7714
7715    return EINA_TRUE;
7716 }
7717 #endif
7718
7719 static Eina_List *
7720 eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func)
7721 {
7722    Eina_List *first, *last;
7723
7724    if (func(a->data, b->data) > 0)
7725      {
7726         _item_move_after(a->data, b->data);
7727         a = (last = first = a)->next;
7728
7729      }
7730    else
7731      b = (last = first = b)->next;
7732
7733    while (a && b)
7734      if (func(a->data, b->data) > 0)
7735        {
7736           _item_move_after(a->data, b->data);
7737           a = (last = last->next = a)->next;
7738        }
7739      else
7740        b = (last = last->next = b)->next;
7741
7742    last->next = a ? a : b;
7743
7744    return first;
7745 }
7746
7747 EAPI Eina_List *
7748 elm_genlist_sort(Evas_Object *obj, Eina_Compare_Cb func)
7749 {
7750    ELM_GENLIST_CHECK(obj) NULL;
7751    ELM_GENLIST_DATA_GET(obj, sd);
7752    Eina_List *list = NULL;
7753    Elm_Gen_Item  *it, *next;
7754    unsigned int limit = 0, i = 0, n = 0;
7755    Eina_List *tail = NULL, *unsort = NULL, *stack[32], *prev = NULL;
7756
7757    sd->sorting = EINA_TRUE;
7758
7759    it = (Elm_Gen_Item*)elm_genlist_first_item_get(obj);
7760    while(1)
7761      {
7762         list = eina_list_append(list, it);
7763         next = (Elm_Gen_Item*)elm_genlist_item_next_get((Elm_Object_Item *)it);
7764         if (!next) break;
7765         it = next;
7766      }
7767
7768    if (!list)
7769      return NULL;
7770
7771    limit = eina_list_count(list);
7772    tail = list;
7773
7774    if ((limit == 0) ||
7775        (limit > list->accounting->count))
7776      limit = list->accounting->count;
7777
7778    if (limit != list->accounting->count)
7779      {
7780         unsort = eina_list_nth_list(list, limit);
7781         if (unsort)
7782           unsort->prev->next = NULL;
7783      }
7784
7785    while (tail)
7786      {
7787         unsigned int idx, tmp;
7788
7789         Eina_List *a = tail;
7790         Eina_List *b = tail->next;
7791
7792         if (!b)
7793           {
7794              stack[i++] = a;
7795              break;
7796           }
7797
7798         tail = b->next;
7799
7800         if (func(a->data, b->data) > 0)
7801           ((stack[i++] = a)->next = b)->next = 0;
7802         else
7803              ((stack[i++] = b)->next = a)->next = 0;
7804
7805         tmp = n++;
7806         for (idx = n ^ tmp; idx &= idx - 1; i--)
7807           stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func);
7808      }
7809
7810    while (i-- > 1)
7811      stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func);
7812
7813    list = stack[0];
7814
7815    for (; stack[0]; stack[0] = stack[0]->next)
7816      {
7817         stack[0]->prev = prev;
7818         prev = stack[0];
7819      }
7820    tail = prev;
7821
7822    if (unsort)
7823      {
7824         tail->next = unsort;
7825         unsort->prev = tail;
7826      }
7827    else
7828      list->accounting->last = tail;
7829
7830    if (!sd->fx_mode) sd->sorting = EINA_FALSE;
7831    if (sd->decorate_all_mode) sd->sorting = EINA_FALSE;
7832    sd->s_iface->content_region_show(obj, 0,0,0,0);
7833    sd->pan_changed = EINA_TRUE;
7834    evas_object_smart_changed(sd->pan_obj);
7835
7836    return list;
7837 }