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