[elm_genlist] add zoom effect while item is added or deleted.
[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 = 6 * 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
2583                        /* check item which displays more than half of its size */
2584                        if (ELM_RECTS_INTERSECT
2585                              (x + (w / 2), y + (h / 2), 0, 0, sx, sy, sw, sh))
2586                          items = eina_list_append(items, it->base.access_obj);
2587
2588                        if (!it->base.access_order) continue;
2589
2590                        Eina_List *subl;
2591                        Evas_Object *subo;
2592                        EINA_LIST_FOREACH(it->base.access_order, subl, subo)
2593                          items = eina_list_append(items, subo);
2594                     }
2595                }
2596           }
2597         else if (done) break;
2598      }
2599
2600    return elm_widget_focus_list_next_get
2601             (obj, items, eina_list_data_get, dir, next);
2602 }
2603
2604 static void
2605 _mirrored_set(Evas_Object *obj,
2606               Eina_Bool rtl)
2607 {
2608    ELM_GENLIST_DATA_GET(obj, sd);
2609
2610    sd->s_iface->mirrored_set(obj, rtl);
2611 }
2612
2613 static Eina_Bool
2614 _elm_genlist_smart_theme(Evas_Object *obj)
2615 {
2616    Item_Block *itb;
2617
2618    ELM_GENLIST_DATA_GET(obj, sd);
2619
2620    if (!ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->theme(obj))
2621      return EINA_FALSE;
2622
2623    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2624    _item_cache_all_free(sd);
2625    _mirrored_set(obj, elm_widget_mirrored_get(obj));
2626
2627 #if 0
2628    // FIXME: difference from opensource
2629    elm_layout_theme_set(obj, "genlist", "base", elm_widget_style_get(obj));
2630 #endif
2631
2632    sd->item_width = sd->item_height = 0;
2633    sd->group_item_width = sd->group_item_height = 0;
2634    sd->minw = sd->minh = sd->realminw = 0;
2635    EINA_INLIST_FOREACH(sd->blocks, itb)
2636      {
2637         Eina_List *l;
2638         Elm_Gen_Item *it;
2639
2640         if (itb->realized) _item_block_unrealize(itb);
2641         EINA_LIST_FOREACH(itb->items, l, it)
2642           it->item->mincalcd = EINA_FALSE;
2643
2644         itb->changed = EINA_TRUE;
2645      }
2646    if (sd->calc_job) ecore_job_del(sd->calc_job);
2647    sd->calc_job = NULL;
2648    elm_layout_sizing_eval(obj);
2649    sd->pan_changed = EINA_TRUE;
2650    evas_object_smart_changed(sd->pan_obj);
2651    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2652    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2653
2654    return EINA_TRUE;
2655 }
2656
2657 /* FIXME: take off later. maybe this show region coords belong in the
2658  * interface (new api functions, set/get)? */
2659 static void
2660 _show_region_hook(void *data,
2661                   Evas_Object *obj)
2662 {
2663    Evas_Coord x, y, w, h;
2664
2665    ELM_GENLIST_DATA_GET(data, sd);
2666
2667    elm_widget_show_region_get(obj, &x, &y, &w, &h);
2668    //x & y are screen coordinates, Add with pan coordinates
2669    x += sd->pan_x;
2670    y += sd->pan_y;
2671    sd->s_iface->content_region_show(obj, x, y, w, h);
2672 }
2673
2674 static Eina_Bool
2675 _elm_genlist_smart_translate(Evas_Object *obj)
2676 {
2677    evas_object_smart_callback_call(obj, "language,changed", NULL);
2678
2679    return EINA_TRUE;
2680 }
2681
2682 static void
2683 _item_highlight(Elm_Gen_Item *it)
2684 {
2685    const char *selectraise;
2686    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2687
2688    if (elm_widget_item_disabled_get(it)) return;
2689    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2690        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ) ||
2691        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2692        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ))
2693      return;
2694
2695    if (!sd->highlight || it->highlighted) return;
2696 #if GENLIST_PINCH_ZOOM_SUPPORT
2697    if (sd->pinch_zoom_mode) return;
2698 #endif
2699
2700    selectraise = edje_object_data_get(VIEW(it), "selectraise");
2701    if ((selectraise) && (!strcmp(selectraise, "on")))
2702      {
2703         if (it->deco_all_view) evas_object_raise(it->deco_all_view);
2704         else evas_object_raise(VIEW(it));
2705         if ((it->item->group_item) && (it->item->group_item->realized))
2706           evas_object_raise(it->item->VIEW(group_item));
2707      }
2708    it->highlighted = EINA_TRUE;
2709
2710    if (it->deco_all_view)
2711      edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
2712    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
2713    evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
2714 }
2715
2716 static void
2717 _item_unhighlight(Elm_Gen_Item *it)
2718 {
2719    if (!it->highlighted) return;
2720
2721    if (!it->item->nostacking)
2722      {
2723         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
2724           {
2725              if (it->deco_all_view) evas_object_lower(it->deco_all_view);
2726              else evas_object_lower(VIEW(it));
2727           }
2728         else
2729           {
2730              if (it->deco_all_view) evas_object_raise(it->deco_all_view);
2731              else evas_object_raise(VIEW(it));
2732           }
2733      }
2734    it->highlighted = EINA_FALSE;
2735
2736    if (it->deco_all_view)
2737      edje_object_signal_emit(it->deco_all_view, "elm,state,unselected", "elm");
2738    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
2739    evas_object_smart_callback_call(WIDGET(it), SIG_UNHIGHLIGHTED, it);
2740 }
2741
2742 static void
2743 _item_unselect(Elm_Gen_Item *it)
2744 {
2745    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2746    _item_unhighlight(it);
2747    if (!it->selected) return;
2748
2749    it->selected = EINA_FALSE;
2750    sd->selected = eina_list_remove(sd->selected, it);
2751    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
2752 }
2753
2754 static void
2755 _item_select(Elm_Gen_Item *it)
2756 {
2757    Evas_Object *obj = WIDGET(it);
2758    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2759    if (elm_widget_item_disabled_get(it)) return;
2760    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2761        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
2762        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
2763        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
2764      return;
2765
2766 #if GENLIST_PINCH_ZOOM_SUPPORT
2767    if (IS_ROOT_PARENT_IT(it) && (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT))
2768      {
2769         elm_genlist_pinch_zoom_mode_set(obj, ELM_GEN_PINCH_ZOOM_EXPAND);
2770         elm_genlist_item_show((Elm_Object_Item *)it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
2771         return;
2772      }
2773 #endif
2774
2775 #if 0
2776    // FIXME: difference from upstream
2777    if ((GL_IT(it)->wsd->last_selected_item) &&
2778        (it != (Elm_Gen_Item *) GL_IT(it)->wsd->last_selected_item))
2779      _item_unfocusable_set
2780        ((Elm_Gen_Item *)GL_IT(it)->wsd->last_selected_item, EINA_TRUE);
2781 #endif
2782
2783    // Do not check selected because always select mode can be used
2784    _item_highlight(it);
2785    it->selected = EINA_TRUE;
2786    sd->selected = eina_list_append(sd->selected, it);
2787    sd->last_selected_item = (Elm_Object_Item *)it;
2788
2789    if (it->func.func) it->func.func((void *)it->func.data, obj, it);
2790    if (!EINA_MAGIC_CHECK((Elm_Widget_Item *)it, ELM_WIDGET_ITEM_MAGIC))
2791      return;
2792    evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
2793 }
2794
2795 static void
2796 _item_select_unselect(Elm_Gen_Item *it, Eina_Bool selected)
2797 {
2798    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2799    Evas_Object *obj = ELM_WIDGET_DATA(sd)->obj;
2800    if (elm_widget_item_disabled_get(it)) return;
2801
2802    evas_object_ref(obj);
2803    if (!sd->multi)
2804      {
2805         const Eina_List *l, *ll;
2806         Elm_Gen_Item *it2;
2807         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, it2)
2808            if (it2 != it) _item_unselect(it2);
2809      }
2810    if (selected) _item_select(it);
2811    else _item_unselect(it);
2812    evas_object_unref(obj);
2813 }
2814
2815 static void
2816 _item_block_position_update(Eina_Inlist *list,
2817                             int idx)
2818 {
2819    Item_Block *tmp;
2820
2821    EINA_INLIST_FOREACH(list, tmp)
2822      {
2823         tmp->position = idx++;
2824         tmp->position_update = EINA_TRUE;
2825      }
2826 }
2827
2828 static void
2829 _item_position_update(Eina_List *list,
2830                       int idx)
2831 {
2832    Elm_Gen_Item *it;
2833    Eina_List *l;
2834
2835    EINA_LIST_FOREACH(list, l, it)
2836      {
2837         it->position = idx++;
2838         it->position_update = EINA_TRUE;
2839      }
2840 }
2841
2842 static void
2843 _item_block_merge(Item_Block *left,
2844                   Item_Block *right)
2845 {
2846    Eina_List *l;
2847    Elm_Gen_Item *it2;
2848
2849    EINA_LIST_FOREACH(right->items, l, it2)
2850      {
2851         it2->item->block = left;
2852         left->count++;
2853         left->changed = EINA_TRUE;
2854      }
2855    left->items = eina_list_merge(left->items, right->items);
2856 }
2857
2858 static void
2859 _item_block_del(Elm_Gen_Item *it)
2860 {
2861    Eina_Inlist *il;
2862    Item_Block *itb = it->item->block;
2863    Eina_Bool block_changed = EINA_FALSE;
2864
2865    itb->items = eina_list_remove(itb->items, it);
2866    itb->count--;
2867    itb->changed = EINA_TRUE;
2868    if (GL_IT(it)->wsd->calc_job) ecore_job_del(GL_IT(it)->wsd->calc_job);
2869    GL_IT(it)->wsd->calc_job = ecore_job_add(_calc_job, GL_IT(it)->wsd);
2870    if (itb->count < 1)
2871      {
2872         Item_Block *itbn;
2873
2874         il = EINA_INLIST_GET(itb);
2875         itbn = (Item_Block *)(il->next);
2876         if (it->parent)
2877           it->parent->item->items =
2878             eina_list_remove(it->parent->item->items, it);
2879         else
2880           {
2881              _item_block_position_update(il->next, itb->position);
2882           }
2883         GL_IT(it)->wsd->blocks =
2884           eina_inlist_remove(GL_IT(it)->wsd->blocks, il);
2885         free(itb);
2886         itb = NULL;
2887         if (itbn) itbn->changed = EINA_TRUE;
2888      }
2889    else
2890      {
2891         if (itb->count < (itb->sd->max_items_per_block / 2))
2892           {
2893              Item_Block *itbp;
2894              Item_Block *itbn;
2895
2896              il = EINA_INLIST_GET(itb);
2897              itbp = (Item_Block *)(il->prev);
2898              itbn = (Item_Block *)(il->next);
2899
2900              /* merge block with previous */
2901              if ((itbp) &&
2902                  ((itbp->count + itb->count) <
2903                   (itb->sd->max_items_per_block +
2904                    (itb->sd->max_items_per_block / 2))))
2905                {
2906                   _item_block_merge(itbp, itb);
2907                   _item_block_position_update
2908                     (EINA_INLIST_GET(itb)->next, itb->position);
2909                   GL_IT(it)->wsd->blocks = eina_inlist_remove
2910                       (GL_IT(it)->wsd->blocks, EINA_INLIST_GET(itb));
2911                   free(itb);
2912                   block_changed = EINA_TRUE;
2913                }
2914              /* merge block with next */
2915              else if ((itbn) &&
2916                       ((itbn->count + itb->count) <
2917                        (itb->sd->max_items_per_block +
2918                         (itb->sd->max_items_per_block / 2))))
2919                {
2920                   _item_block_merge(itb, itbn);
2921                   _item_block_position_update
2922                     (EINA_INLIST_GET(itbn)->next, itbn->position);
2923                   GL_IT(it)->wsd->blocks =
2924                     eina_inlist_remove(GL_IT(it)->wsd->blocks,
2925                                        EINA_INLIST_GET(itbn));
2926                   free(itbn);
2927                   block_changed = EINA_TRUE;
2928                }
2929           }
2930      }
2931
2932    if (block_changed)
2933      {
2934         GL_IT(it)->wsd->pan_changed = EINA_TRUE;
2935         evas_object_smart_changed(GL_IT(it)->wsd->pan_obj);
2936         if (GL_IT(it)->wsd->calc_job) ecore_job_del(GL_IT(it)->wsd->calc_job);
2937         GL_IT(it)->wsd->calc_job = NULL;
2938      }
2939 #if GENLIST_FX_SUPPORT
2940    it->item->block = NULL;
2941 #endif
2942 }
2943
2944 static void
2945 _decorate_all_item_unrealize(Elm_Gen_Item *it)
2946 {
2947    Evas_Object *icon;
2948
2949    if ((!it) || (!it->item->decorate_all_item_realized)) return;
2950
2951 #if GENLIST_FX_SUPPORT
2952    if ((GL_IT(it)->has_proxy_it) && (!GL_IT(it)->wsd->genlist_clearing))
2953      {
2954         if (!eina_list_data_find(GL_IT(it)->wsd->pending_unrealized_decorate_all_items, it))
2955           GL_IT(it)->wsd->pending_unrealized_decorate_all_items =
2956              eina_list_append(GL_IT(it)->wsd->pending_unrealized_decorate_all_items, it);
2957         return;
2958      }
2959 #endif
2960
2961    edje_object_part_unswallow(it->deco_all_view, VIEW(it));
2962    evas_object_smart_member_add(VIEW(it), GL_IT(it)->wsd->pan_obj);
2963    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
2964    _elm_genlist_item_odd_even_update(it);
2965    _elm_genlist_item_state_update(it);
2966
2967    edje_object_signal_emit
2968      (it->deco_all_view, "elm,state,decorate,disabled", "elm");
2969    edje_object_signal_emit
2970      (VIEW(it), "elm,state,decorate,disabled", "elm");
2971    edje_object_signal_emit
2972      (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
2973    edje_object_message_signal_process(VIEW(it));
2974    edje_object_message_signal_process(it->deco_all_view);
2975
2976    evas_object_del(it->deco_all_view);
2977    it->deco_all_view = NULL;
2978    elm_widget_stringlist_free(it->item->deco_all_texts);
2979    it->item->deco_all_texts = NULL;
2980    elm_widget_stringlist_free(it->item->deco_all_contents);
2981    it->item->deco_all_contents = NULL;
2982    elm_widget_stringlist_free(it->item->deco_all_states);
2983    it->item->deco_all_states = NULL;
2984    EINA_LIST_FREE (it->item->deco_all_content_objs, icon)
2985      evas_object_del(icon);
2986
2987    _item_mouse_callbacks_del(it, it->deco_all_view);
2988    _item_mouse_callbacks_add(it, VIEW(it));
2989
2990    it->item->decorate_all_item_realized = EINA_FALSE;
2991 }
2992
2993 static void
2994 _item_free_common(Elm_Gen_Item *it)
2995 {
2996    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
2997    elm_widget_item_pre_notify_del(it);
2998    if (it->itc->func.del)
2999      it->itc->func.del((void *)it->base.data, WIDGET(it));
3000    if (it->tooltip.del_cb)
3001      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3002    if (it->item->block) _item_block_del(it);
3003    if (it->parent)
3004      it->parent->item->items =
3005         eina_list_remove(it->parent->item->items, it);
3006    if (it->item->queued) sd->queue = eina_list_remove(sd->queue, it);
3007    if (it->group) sd->group_items = eina_list_remove(sd->group_items, it);
3008
3009    // FIXME: relative will be better to be fixed. it is too harsh.
3010    if (it->item->rel)
3011      it->item->rel->item->rel_revs =
3012         eina_list_remove(it->item->rel->item->rel_revs, it);
3013    if (it->item->rel_revs)
3014      {
3015         Elm_Gen_Item *tmp;
3016         EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = NULL;
3017      }
3018    _item_sub_items_clear(it);
3019
3020 #if GENLIST_ENTRY_SUPPORT
3021    it->item->unrealize_disabled = EINA_FALSE;
3022 #endif
3023
3024    if (it->selected) sd->selected = eina_list_remove(sd->selected, it);
3025    if (sd->show_item == it) sd->show_item = NULL;
3026    if (sd->anchor_item == it)
3027      {
3028         sd->anchor_item =
3029            ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3030         if (!sd->anchor_item)          sd->anchor_item =
3031           ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3032      }
3033    if (sd->expanded_item == it) sd->expanded_item = NULL;
3034    if (sd->expanded_next_item == it) sd->expanded_next_item = NULL;
3035    if (sd->state) eina_inlist_sorted_state_free(sd->state);
3036
3037    if (sd->last_selected_item == (Elm_Object_Item *)it)
3038      sd->last_selected_item = NULL;
3039
3040    if (it->long_timer)
3041      {
3042         ecore_timer_del(it->long_timer);
3043         it->long_timer = NULL;
3044      }
3045    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
3046
3047    sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
3048    sd->item_count--;
3049 }
3050
3051 static void
3052 _item_mouse_move_cb(void *data,
3053                     Evas *evas __UNUSED__,
3054                     Evas_Object *obj,
3055                     void *event_info)
3056 {
3057    EINA_SAFETY_ON_NULL_RETURN(data);
3058    Elm_Gen_Item *it = data;
3059    Elm_Genlist_Smart_Data *sd;
3060    Evas_Event_Mouse_Move *ev = event_info;
3061    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
3062    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
3063
3064    sd = GL_IT(it)->wsd;
3065
3066    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3067      {
3068         if (!sd->on_hold) _item_unselect(it);
3069         sd->on_hold = EINA_TRUE;
3070      }
3071    if (sd->multi_touched)
3072      {
3073         sd->cur_x = ev->cur.canvas.x;
3074         sd->cur_y = ev->cur.canvas.y;
3075         return;
3076      }
3077    if ((it->dragging) && (it->down))
3078      {
3079         if (sd->movements == SWIPE_MOVES)
3080           sd->swipe = EINA_TRUE;
3081         else
3082           {
3083              sd->history[sd->movements].x = ev->cur.canvas.x;
3084              sd->history[sd->movements].y = ev->cur.canvas.y;
3085              if (abs((sd->history[sd->movements].x -
3086                       sd->history[0].x)) > 40)
3087                sd->swipe = EINA_TRUE;
3088              else
3089                sd->movements++;
3090           }
3091         if (it->long_timer)
3092           {
3093              ecore_timer_del(it->long_timer);
3094              it->long_timer = NULL;
3095           }
3096         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
3097         return;
3098      }
3099    if ((!it->down) || (sd->longpressed))
3100      {
3101         if (it->long_timer)
3102           {
3103              ecore_timer_del(it->long_timer);
3104              it->long_timer = NULL;
3105           }
3106         if ((sd->reorder_mode) && (sd->reorder_it))
3107           {
3108              evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
3109
3110              if (ev->cur.canvas.y < (oy + (sd->reorder_it->item->h / 2)))
3111                 sd->reorder_fast = 1;
3112              else if (ev->cur.canvas.y > (oy + oh - (sd->reorder_it->item->h  / 2)))
3113                 sd->reorder_fast = -1;
3114              else sd->reorder_fast = 0;
3115
3116              it_scrl_y = ev->cur.canvas.y - sd->reorder_it->dy;
3117
3118              if (!sd->reorder_start_y)
3119                sd->reorder_start_y = it->item->block->y + it->y;
3120
3121              if (it_scrl_y < oy)
3122                y_pos = oy;
3123              else if (it_scrl_y + sd->reorder_it->item->h > oy + oh)
3124                y_pos = oy + oh - sd->reorder_it->item->h;
3125              else
3126                y_pos = it_scrl_y;
3127
3128              if (it->deco_all_view)
3129                _item_position(it, it->deco_all_view, it->item->scrl_x, y_pos);
3130              else if (it->item->deco_it_view)
3131                _item_position
3132                   (it, it->item->deco_it_view, it->item->scrl_x, y_pos);
3133              else
3134                _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
3135
3136              if (sd->calc_job) ecore_job_del(sd->calc_job);
3137              sd->calc_job = ecore_job_add(_calc_job, sd);
3138           }
3139         return;
3140      }
3141    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
3142      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
3143
3144    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3145    x = ev->cur.canvas.x - x;
3146    y = ev->cur.canvas.y - y;
3147    dx = x - it->dx;
3148    adx = dx;
3149    if (adx < 0) adx = -dx;
3150
3151    dy = y - it->dy;
3152    ady = dy;
3153    if (ady < 0) ady = -dy;
3154
3155    minw *= 2;
3156    minh *= 2;
3157    if ((adx > minw) || (ady > minh))
3158      {
3159         it->dragging = EINA_TRUE;
3160         if (it->long_timer)
3161           {
3162              ecore_timer_del(it->long_timer);
3163              it->long_timer = NULL;
3164           }
3165         if (dy < 0)
3166           {
3167              if (ady > adx)
3168                evas_object_smart_callback_call
3169                  (WIDGET(it), SIG_DRAG_START_UP, it);
3170              else
3171                {
3172                   if (dx < 0)
3173                     evas_object_smart_callback_call
3174                       (WIDGET(it), SIG_DRAG_START_LEFT, it);
3175                   else
3176                     evas_object_smart_callback_call
3177                       (WIDGET(it), SIG_DRAG_START_RIGHT, it);
3178                }
3179           }
3180         else
3181           {
3182              if (ady > adx)
3183                evas_object_smart_callback_call
3184                  (WIDGET(it), SIG_DRAG_START_DOWN, it);
3185              else
3186                {
3187                   if (dx < 0)
3188                     evas_object_smart_callback_call
3189                       (WIDGET(it), SIG_DRAG_START_LEFT, it);
3190                   else
3191                     evas_object_smart_callback_call
3192                       (WIDGET(it), SIG_DRAG_START_RIGHT, it);
3193                }
3194           }
3195      }
3196 }
3197
3198 static Eina_Bool
3199 _long_press_cb(void *data)
3200 {
3201    Elm_Gen_Item *it = data, *it2;
3202    Elm_Genlist_Smart_Data *sd;
3203    Eina_List *l, *ll;
3204
3205    sd = GL_IT(it)->wsd;
3206
3207    it->long_timer = NULL;
3208    if (elm_widget_item_disabled_get(it) || (it->dragging) ||
3209        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
3210      return ECORE_CALLBACK_CANCEL;
3211
3212    GL_IT(it)->wsd->longpressed = EINA_TRUE;
3213    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
3214    if ((GL_IT(it)->wsd->reorder_mode) && (!it->group))
3215      {
3216         GL_IT(it)->wsd->reorder_it = it;
3217         GL_IT(it)->wsd->reorder_start_y = 0;
3218         if (it->deco_all_view)
3219           evas_object_raise(it->deco_all_view);
3220         else
3221           evas_object_raise(VIEW(it));
3222
3223         sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_TRUE);
3224         sd->s_iface->bounce_allow_set
3225           (ELM_WIDGET_DATA(sd)->obj, EINA_FALSE, EINA_FALSE);
3226
3227         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, it2)
3228           {
3229              if (it != it2) _item_unselect(it2);
3230           }
3231 #if 0
3232         // FIXME: difference from opensource
3233         if (it->item->items)
3234           {
3235              EINA_LIST_FOREACH(it->item->items, l, it_tmp)
3236                {
3237                   if (elm_genlist_item_expanded_get((Elm_Object_Item *) it_tmp))
3238                     {
3239                        elm_genlist_item_expanded_set((Elm_Object_Item *)it_tmp,
3240                                                      EINA_FALSE);
3241                        return ECORE_CALLBACK_RENEW;
3242                     }
3243                }
3244           }
3245 #endif
3246         if (elm_genlist_item_expanded_get((Elm_Object_Item *)it))
3247           {
3248              elm_genlist_item_expanded_set((Elm_Object_Item *)it, EINA_FALSE);
3249              return ECORE_CALLBACK_RENEW;
3250           }
3251
3252         if (!GL_IT(it)->wsd->decorate_all_mode)
3253           edje_object_signal_emit
3254             (VIEW(it), "elm,state,reorder,enabled", "elm");
3255      }
3256
3257    return ECORE_CALLBACK_CANCEL;
3258 }
3259
3260 static void
3261 _swipe_do(Elm_Gen_Item *it)
3262 {
3263    int i, sum = 0;
3264
3265    if (!it) return;
3266    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
3267        elm_widget_item_disabled_get(it)) return;
3268
3269    GL_IT(it)->wsd->swipe = EINA_FALSE;
3270    for (i = 0; i < GL_IT(it)->wsd->movements; i++)
3271      {
3272         sum += GL_IT(it)->wsd->history[i].x;
3273         if (abs(GL_IT(it)->wsd->history[0].y -
3274                 GL_IT(it)->wsd->history[i].y) > 10) return;
3275      }
3276
3277    sum /= GL_IT(it)->wsd->movements;
3278    if (abs(sum - GL_IT(it)->wsd->history[0].x) <= 10) return;
3279    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
3280 }
3281
3282 static Eina_Bool
3283 _swipe_cancel(void *data)
3284 {
3285    Elm_Gen_Item *it = data;
3286
3287    if (!it) return ECORE_CALLBACK_CANCEL;
3288    GL_IT(it)->wsd->swipe = EINA_FALSE;
3289    GL_IT(it)->wsd->movements = 0;
3290
3291    return ECORE_CALLBACK_RENEW;
3292 }
3293
3294 static Eina_Bool
3295 _multi_cancel(void *data)
3296 {
3297    Elm_Genlist_Smart_Data *sd = data;
3298
3299    if (!sd) return ECORE_CALLBACK_CANCEL;
3300    sd->multi_timeout = EINA_TRUE;
3301
3302    return ECORE_CALLBACK_RENEW;
3303 }
3304
3305 static void
3306 _multi_touch_gesture_eval(void *data)
3307 {
3308    Elm_Gen_Item *it = data;
3309    Evas_Coord minw = 0, minh = 0;
3310    Evas_Coord off_x, off_y, off_mx, off_my;
3311
3312    GL_IT(it)->wsd->multi_touched = EINA_FALSE;
3313    if (GL_IT(it)->wsd->multi_timer)
3314      {
3315         ecore_timer_del(GL_IT(it)->wsd->multi_timer);
3316         GL_IT(it)->wsd->multi_timer = NULL;
3317      }
3318    if (GL_IT(it)->wsd->multi_timeout)
3319      {
3320         GL_IT(it)->wsd->multi_timeout = EINA_FALSE;
3321         return;
3322      }
3323
3324    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
3325    off_x = abs(GL_IT(it)->wsd->cur_x - GL_IT(it)->wsd->prev_x);
3326    off_y = abs(GL_IT(it)->wsd->cur_y - GL_IT(it)->wsd->prev_y);
3327    off_mx = abs(GL_IT(it)->wsd->cur_mx - GL_IT(it)->wsd->prev_mx);
3328    off_my = abs(GL_IT(it)->wsd->cur_my - GL_IT(it)->wsd->prev_my);
3329
3330    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw)
3331                                               || (off_my > minh)))
3332      {
3333         if ((off_x + off_mx) > (off_y + off_my))
3334           {
3335              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_RIGHT, it);
3339              else if ((GL_IT(it)->wsd->cur_x < GL_IT(it)->wsd->prev_x)
3340                       && (GL_IT(it)->wsd->cur_mx < GL_IT(it)->wsd->prev_mx))
3341                evas_object_smart_callback_call
3342                  (WIDGET(it), SIG_MULTI_SWIPE_LEFT, it);
3343              else if (abs(GL_IT(it)->wsd->cur_x - GL_IT(it)->wsd->cur_mx) >
3344                       abs(GL_IT(it)->wsd->prev_x - GL_IT(it)->wsd->prev_mx))
3345                evas_object_smart_callback_call
3346                  (WIDGET(it), SIG_MULTI_PINCH_OUT, it);
3347              else
3348                evas_object_smart_callback_call
3349                  (WIDGET(it), SIG_MULTI_PINCH_IN, it);
3350           }
3351         else
3352           {
3353              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_DOWN, it);
3357              else if ((GL_IT(it)->wsd->cur_y < GL_IT(it)->wsd->prev_y)
3358                       && (GL_IT(it)->wsd->cur_my < GL_IT(it)->wsd->prev_my))
3359                evas_object_smart_callback_call
3360                  (WIDGET(it), SIG_MULTI_SWIPE_UP, it);
3361              else if (abs(GL_IT(it)->wsd->cur_y - GL_IT(it)->wsd->cur_my) >
3362                       abs(GL_IT(it)->wsd->prev_y - GL_IT(it)->wsd->prev_my))
3363                {
3364                   evas_object_smart_callback_call
3365                      (WIDGET(it), SIG_MULTI_PINCH_OUT, it);
3366 #if GENLIST_PINCH_ZOOM_SUPPORT
3367                   if (IS_ROOT_PARENT_IT(it) && (GL_IT(it)->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT))
3368                     {
3369                        elm_genlist_pinch_zoom_mode_set(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj, ELM_GEN_PINCH_ZOOM_EXPAND);
3370                        elm_genlist_item_show((Elm_Object_Item *)it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
3371                     }
3372 #endif
3373                }
3374              else
3375                {
3376                   evas_object_smart_callback_call
3377                      (WIDGET(it), SIG_MULTI_PINCH_IN, it);
3378 #if GENLIST_PINCH_ZOOM_SUPPORT
3379                   elm_genlist_pinch_zoom_mode_set(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj,
3380                                                   ELM_GEN_PINCH_ZOOM_CONTRACT);
3381 #endif
3382                }
3383           }
3384      }
3385
3386    GL_IT(it)->wsd->multi_timeout = EINA_FALSE;
3387 }
3388
3389 static void
3390 _item_multi_down_cb(void *data,
3391                     Evas *evas __UNUSED__,
3392                     Evas_Object *obj __UNUSED__,
3393                     void *event_info)
3394 {
3395    Elm_Gen_Item *it = data;
3396    Evas_Event_Multi_Down *ev = event_info;
3397
3398    if ((GL_IT(it)->wsd->multi_device != 0) || (GL_IT(it)->wsd->multi_touched)
3399        || (GL_IT(it)->wsd->multi_timeout))
3400      return;
3401
3402    GL_IT(it)->wsd->multi_device = ev->device;
3403    GL_IT(it)->wsd->multi_down = EINA_TRUE;
3404    GL_IT(it)->wsd->multi_touched = EINA_TRUE;
3405    GL_IT(it)->wsd->prev_mx = ev->canvas.x;
3406    GL_IT(it)->wsd->prev_my = ev->canvas.y;
3407    /*
3408    if (!GL_IT(it)->wsd->wasselected)
3409      _item_unselect(it);
3410    GL_IT(it)->wsd->wasselected = EINA_FALSE;
3411      */
3412    if (it->long_timer)
3413      {
3414         ecore_timer_del(it->long_timer);
3415         it->long_timer = NULL;
3416      }
3417    if (it->dragging)
3418      {
3419         it->dragging = EINA_FALSE;
3420         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
3421      }
3422    if (it->item->swipe_timer)
3423      {
3424         ecore_timer_del(it->item->swipe_timer);
3425         it->item->swipe_timer = NULL;
3426      }
3427    GL_IT(it)->wsd->longpressed = EINA_FALSE;
3428    if (GL_IT(it)->wsd->on_hold)
3429      {
3430         GL_IT(it)->wsd->swipe = EINA_FALSE;
3431         GL_IT(it)->wsd->movements = 0;
3432         GL_IT(it)->wsd->on_hold = EINA_FALSE;
3433      }
3434 }
3435
3436 static void
3437 _item_multi_up_cb(void *data,
3438                   Evas *evas __UNUSED__,
3439                   Evas_Object *obj __UNUSED__,
3440                   void *event_info)
3441 {
3442    Elm_Gen_Item *it = data;
3443    Evas_Event_Multi_Up *ev = event_info;
3444
3445    if (GL_IT(it)->wsd->multi_device != ev->device) return;
3446    GL_IT(it)->wsd->multi_device = 0;
3447    GL_IT(it)->wsd->multi_down = EINA_FALSE;
3448    if (GL_IT(it)->wsd->mouse_down) return;
3449    _multi_touch_gesture_eval(data);
3450 }
3451
3452 static void
3453 _item_multi_move_cb(void *data,
3454                     Evas *evas __UNUSED__,
3455                     Evas_Object *obj __UNUSED__,
3456                     void *event_info)
3457 {
3458    Elm_Gen_Item *it = data;
3459    Evas_Event_Multi_Move *ev = event_info;
3460
3461    if (GL_IT(it)->wsd->multi_device != ev->device) return;
3462    GL_IT(it)->wsd->cur_mx = ev->cur.canvas.x;
3463    GL_IT(it)->wsd->cur_my = ev->cur.canvas.y;
3464 }
3465
3466 #if 0
3467 // FIXME: difference from upstream
3468 static void
3469 _item_unfocusable_set(Elm_Gen_Item *it, Eina_Bool unfocus)
3470 {
3471    Eina_List *l;
3472    Evas_Object *item_obj;
3473    Evas_Object *obj = WIDGET(it);
3474
3475    if (!it->can_focus)
3476      {
3477         EINA_LIST_FOREACH(it->content_objs, l, item_obj)
3478           {
3479             if (unfocus) elm_widget_focused_object_clear(item_obj);
3480             elm_widget_tree_unfocusable_set(item_obj, unfocus);
3481           }
3482         EINA_LIST_FOREACH(it->item->flip_content_objs, l, item_obj)
3483           {
3484              if (unfocus) elm_widget_focused_object_clear(item_obj);
3485              elm_widget_tree_unfocusable_set(item_obj, unfocus);
3486           }
3487         EINA_LIST_FOREACH(it->item->deco_all_content_objs, l, item_obj)
3488           {
3489              if (unfocus) elm_widget_focused_object_clear(item_obj);
3490              elm_widget_tree_unfocusable_set(item_obj, unfocus);
3491           }
3492         it->can_focus = !unfocus;
3493      }
3494 }
3495 #endif
3496
3497 static void
3498 _item_mouse_down_cb(void *data,
3499                     Evas *evas __UNUSED__,
3500                     Evas_Object *obj,
3501                     void *event_info)
3502 {
3503    Evas_Event_Mouse_Down *ev = event_info;
3504    Elm_Gen_Item *it = data;
3505    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
3506    Evas_Coord x, y;
3507
3508    if (ev->button != 1) return;
3509 #if 0
3510    _item_unfocusable_set(it, EINA_FALSE);
3511 #endif
3512    it->down = EINA_TRUE;
3513    it->dragging = EINA_FALSE;
3514    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
3515    it->dx = ev->canvas.x - x;
3516    it->dy = ev->canvas.y - y;
3517    sd->mouse_down = EINA_TRUE;
3518    if (!sd->multi_touched)
3519      {
3520         sd->prev_x = ev->canvas.x;
3521         sd->prev_y = ev->canvas.y;
3522         sd->multi_timeout = EINA_FALSE;
3523         if (sd->multi_timer) ecore_timer_del(sd->multi_timer);
3524         sd->multi_timer = ecore_timer_add(1, _multi_cancel, sd);
3525      }
3526    sd->longpressed = EINA_FALSE;
3527    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3528      {
3529         sd->on_hold = EINA_TRUE;
3530         return;
3531      }
3532    else sd->on_hold = EINA_FALSE;
3533    _item_highlight(it);
3534    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
3535      if ((!elm_widget_item_disabled_get(it)) &&
3536          (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
3537        {
3538           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
3539           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
3540        }
3541    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
3542    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
3543    if (it->long_timer) ecore_timer_del(it->long_timer);
3544    if (it->realized)
3545      it->long_timer = ecore_timer_add
3546          (sd->longpress_timeout, _long_press_cb, it);
3547    else
3548      it->long_timer = NULL;
3549    sd->swipe = EINA_FALSE;
3550    sd->movements = 0;
3551 }
3552
3553 static Item_Block *
3554 _item_block_new(Elm_Genlist_Smart_Data *sd,
3555                 Eina_Bool prepend)
3556 {
3557    Item_Block *itb;
3558
3559    itb = calloc(1, sizeof(Item_Block));
3560    if (!itb) return NULL;
3561    itb->sd = sd;
3562    if (prepend)
3563      {
3564         sd->blocks = eina_inlist_prepend(sd->blocks, EINA_INLIST_GET(itb));
3565         _item_block_position_update(sd->blocks, 0);
3566      }
3567    else
3568      {
3569         sd->blocks = eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
3570         itb->position_update = EINA_TRUE;
3571         if (sd->blocks != EINA_INLIST_GET(itb))
3572           {
3573              itb->position =
3574                ((Item_Block *)(EINA_INLIST_GET(itb)->prev))->position + 1;
3575           }
3576         else
3577           {
3578              itb->position = 0;
3579           }
3580      }
3581
3582    return itb;
3583 }
3584
3585 static Eina_Bool
3586 _item_block_add(Elm_Genlist_Smart_Data *sd,
3587                 Elm_Gen_Item *it)
3588 {
3589    Item_Block *itb = NULL;
3590
3591    if (!it->item->rel)
3592      {
3593 newblock:
3594         if (it->item->rel)
3595           {
3596              itb = calloc(1, sizeof(Item_Block));
3597              if (!itb) return EINA_FALSE;
3598              itb->sd = sd;
3599              if (!it->item->rel->item->block)
3600                {
3601                   sd->blocks =
3602                     eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
3603                   itb->items = eina_list_append(itb->items, it);
3604                   itb->position_update = EINA_TRUE;
3605                   it->position = eina_list_count(itb->items);
3606                   it->position_update = EINA_TRUE;
3607
3608                   if (sd->blocks != EINA_INLIST_GET(itb))
3609                     {
3610                        itb->position =
3611                          ((Item_Block *)
3612                           (EINA_INLIST_GET(itb)->prev))->position + 1;
3613                     }
3614                   else
3615                     {
3616                        itb->position = 0;
3617                     }
3618                }
3619              else
3620                {
3621                   Eina_List *tmp;
3622
3623                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3624                   if (it->item->before)
3625                     {
3626                        sd->blocks = eina_inlist_prepend_relative
3627                            (sd->blocks, EINA_INLIST_GET(itb),
3628                            EINA_INLIST_GET(it->item->rel->item->block));
3629                        itb->items =
3630                          eina_list_prepend_relative_list(itb->items, it, tmp);
3631
3632                        /* Update index from where we prepended */
3633                        _item_position_update
3634                          (eina_list_prev(tmp), it->item->rel->position);
3635                        _item_block_position_update
3636                          (EINA_INLIST_GET(itb),
3637                          it->item->rel->item->block->position);
3638                     }
3639                   else
3640                     {
3641                        sd->blocks = eina_inlist_append_relative
3642                            (sd->blocks, EINA_INLIST_GET(itb),
3643                            EINA_INLIST_GET(it->item->rel->item->block));
3644                        itb->items =
3645                          eina_list_append_relative_list(itb->items, it, tmp);
3646
3647                        /* Update block index from where we appended */
3648                        _item_position_update
3649                          (eina_list_next(tmp), it->item->rel->position + 1);
3650                        _item_block_position_update
3651                          (EINA_INLIST_GET(itb),
3652                          it->item->rel->item->block->position + 1);
3653                     }
3654                }
3655           }
3656         else
3657           {
3658              if (it->item->before)
3659                {
3660                   if (sd->blocks)
3661                     {
3662                        itb = (Item_Block *)(sd->blocks);
3663                        if (itb->count >= sd->max_items_per_block)
3664                          {
3665                             itb = _item_block_new(sd, EINA_TRUE);
3666                             if (!itb) return EINA_FALSE;
3667                          }
3668                     }
3669                   else
3670                     {
3671                        itb = _item_block_new(sd, EINA_TRUE);
3672                        if (!itb) return EINA_FALSE;
3673                     }
3674                   itb->items = eina_list_prepend(itb->items, it);
3675
3676                   _item_position_update(itb->items, 0);
3677                }
3678              else
3679                {
3680                   if (sd->blocks)
3681                     {
3682                        itb = (Item_Block *)(sd->blocks->last);
3683                        if (itb->count >= sd->max_items_per_block)
3684                          {
3685                             itb = _item_block_new(sd, EINA_FALSE);
3686                             if (!itb) return EINA_FALSE;
3687                          }
3688                     }
3689                   else
3690                     {
3691                        itb = _item_block_new(sd, EINA_FALSE);
3692                        if (!itb) return EINA_FALSE;
3693                     }
3694                   itb->items = eina_list_append(itb->items, it);
3695                   it->position = eina_list_count(itb->items);
3696                }
3697           }
3698      }
3699    else
3700      {
3701         Eina_List *tmp;
3702
3703         if (it->item->rel->item->queued)
3704           {
3705              /* NOTE: for a strange reason eina_list and eina_inlist
3706                 don't have the same property on sorted insertion
3707                 order, so the queue is not always ordered like the
3708                 item list.  This lead to issue where we depend on an
3709                 item that is not yet created. As a quick work around,
3710                 we reschedule the calc of the item and stop reordering
3711                 the list to prevent any nasty issue to show up here.
3712               */
3713              sd->queue = eina_list_append(sd->queue, it);
3714              sd->requeued = EINA_TRUE;
3715              it->item->queued = EINA_TRUE;
3716
3717              return EINA_FALSE;
3718           }
3719         itb = it->item->rel->item->block;
3720         if (!itb) goto newblock;
3721         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3722         if (it->item->before)
3723           {
3724              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3725              _item_position_update
3726                (eina_list_prev(tmp), it->item->rel->position);
3727           }
3728         else
3729           {
3730              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3731              _item_position_update
3732                (eina_list_next(tmp), it->item->rel->position + 1);
3733           }
3734      }
3735
3736    itb->count++;
3737    itb->changed = EINA_TRUE;
3738    it->item->block = itb;
3739    if (itb->sd->calc_job) ecore_job_del(itb->sd->calc_job);
3740    itb->sd->calc_job = ecore_job_add(_calc_job, itb->sd);
3741
3742    if (itb->count > itb->sd->max_items_per_block)
3743      {
3744         int newc;
3745         Item_Block *itb2;
3746         Elm_Gen_Item *it2;
3747         Eina_Bool done = EINA_FALSE;
3748
3749         newc = itb->count / 2;
3750
3751         if (EINA_INLIST_GET(itb)->prev)
3752           {
3753              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3754
3755              if (itbp->count + newc < sd->max_items_per_block / 2)
3756                {
3757                   /* moving items to previous block */
3758                   while ((itb->count > newc) && (itb->items))
3759                     {
3760                        it2 = eina_list_data_get(itb->items);
3761                        itb->items = eina_list_remove_list
3762                            (itb->items, itb->items);
3763                        itb->count--;
3764
3765                        itbp->items = eina_list_append(itbp->items, it2);
3766                        it2->item->block = itbp;
3767                        itbp->count++;
3768                     }
3769
3770                   done = EINA_TRUE;
3771                }
3772           }
3773
3774         if (!done && EINA_INLIST_GET(itb)->next)
3775           {
3776              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3777
3778              if (itbn->count + newc < sd->max_items_per_block / 2)
3779                {
3780                   /* moving items to next block */
3781                   while ((itb->count > newc) && (itb->items))
3782                     {
3783                        Eina_List *l;
3784
3785                        l = eina_list_last(itb->items);
3786                        it2 = eina_list_data_get(l);
3787                        itb->items = eina_list_remove_list(itb->items, l);
3788                        itb->count--;
3789
3790                        itbn->items = eina_list_prepend(itbn->items, it2);
3791                        it2->item->block = itbn;
3792                        itbn->count++;
3793                     }
3794
3795                   done = EINA_TRUE;
3796                }
3797           }
3798
3799         if (!done)
3800           {
3801              /* moving items to new block */
3802              itb2 = calloc(1, sizeof(Item_Block));
3803              if (!itb2) return EINA_FALSE;
3804              itb2->sd = sd;
3805              sd->blocks =
3806                eina_inlist_append_relative(sd->blocks, EINA_INLIST_GET(itb2),
3807                                            EINA_INLIST_GET(itb));
3808              itb2->changed = EINA_TRUE;
3809              while ((itb->count > newc) && (itb->items))
3810                {
3811                   Eina_List *l;
3812
3813                   l = eina_list_last(itb->items);
3814                   it2 = l->data;
3815                   itb->items = eina_list_remove_list(itb->items, l);
3816                   itb->count--;
3817
3818                   itb2->items = eina_list_prepend(itb2->items, it2);
3819                   it2->item->block = itb2;
3820                   itb2->count++;
3821                }
3822           }
3823      }
3824
3825    return EINA_TRUE;
3826 }
3827
3828 static int
3829 _item_process(Elm_Genlist_Smart_Data *sd,
3830               Elm_Gen_Item *it)
3831 {
3832    if (!_item_block_add(sd, it)) return 1;
3833    if (!sd->blocks)
3834      _item_block_realize(it->item->block);
3835
3836    return 0;
3837 }
3838
3839 static void
3840 _item_process_post(Elm_Genlist_Smart_Data *sd,
3841                    Elm_Gen_Item *it,
3842                    Eina_Bool qadd)
3843 {
3844    Eina_Bool show_me = EINA_FALSE;
3845
3846    if (it->item->block->changed)
3847      {
3848         show_me = _item_block_recalc
3849             (it->item->block, it->item->block->num, qadd);
3850         it->item->block->changed = 0;
3851         if (sd->pan_changed)
3852           {
3853              if (sd->calc_job) ecore_job_del(sd->calc_job);
3854              sd->calc_job = NULL;
3855              _calc_job(sd);
3856              sd->pan_changed = EINA_FALSE;
3857           }
3858      }
3859    if (show_me) it->item->block->show_me = EINA_TRUE;
3860
3861    /* when prepending, move the scroller along with the first selected
3862     * item to create the illusion that we're watching the selected
3863     * item this prevents the selected item being scrolled off the
3864     * viewport
3865     */
3866    if (sd->selected && it->item->before)
3867      {
3868         int y, h;
3869         Elm_Gen_Item *it2;
3870
3871         it2 = sd->selected->data;
3872         if (!it2->item->block) return;
3873         sd->s_iface->content_pos_get(ELM_WIDGET_DATA(sd)->obj, NULL, &y);
3874         evas_object_geometry_get(sd->pan_obj, NULL, NULL, NULL, &h);
3875         if ((it->y + it->item->block->y > y + h) ||
3876             (it->y + it->item->block->y + it->item->h < y))
3877           /* offscreen, just update */
3878           sd->s_iface->content_region_show
3879             (ELM_WIDGET_DATA(sd)->obj, it2->x + it2->item->block->x, y,
3880             it2->item->block->w, h);
3881         else
3882           sd->s_iface->content_region_show
3883             (ELM_WIDGET_DATA(sd)->obj, it->x + it->item->block->x,
3884             y + it->item->h, it->item->block->w, h);
3885      }
3886 }
3887
3888 static int
3889 _queue_process(Elm_Genlist_Smart_Data *sd)
3890 {
3891    int n;
3892    double t0, t;
3893
3894    t0 = ecore_loop_time_get();
3895    for (n = 0; (sd->queue) && (n < 128); n++)
3896      {
3897         Elm_Gen_Item *it;
3898
3899         it = eina_list_data_get(sd->queue);
3900         sd->queue = eina_list_remove_list(sd->queue, sd->queue);
3901         it->item->queued = EINA_FALSE;
3902         if (_item_process(sd, it)) continue;
3903         t = ecore_time_get();
3904         _item_process_post(sd, it, EINA_TRUE);
3905         /* same as eina_inlist_count > 1 */
3906         if (sd->blocks && sd->blocks->next)
3907           {
3908              if ((t - t0) > (ecore_animator_frametime_get())) break;
3909           }
3910      }
3911    return n;
3912 }
3913
3914 static Eina_Bool
3915 _item_idle_enterer(void *data)
3916 {
3917    Elm_Genlist_Smart_Data *sd = data;
3918
3919    if (sd->prev_viewport_w == 0) return ECORE_CALLBACK_RENEW;
3920    if (_queue_process(sd) > 0)
3921      {
3922         // wake up mainloop
3923         // Job always be alive because idle_enterer should be alive
3924         if (sd->calc_job) ecore_job_del(sd->calc_job);
3925         sd->calc_job = ecore_job_add(_calc_job, sd);
3926      }
3927    if (!sd->queue)
3928      {
3929         sd->queue_idle_enterer = NULL;
3930         return ECORE_CALLBACK_CANCEL;
3931      }
3932
3933 #if GENLIST_FX_SUPPORT
3934    _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
3935 #endif
3936    return ECORE_CALLBACK_RENEW;
3937 }
3938
3939 static void
3940 _item_queue(Elm_Genlist_Smart_Data *sd,
3941             Elm_Gen_Item *it,
3942             Eina_Compare_Cb cb)
3943 {
3944    if (it->item->queued) return;
3945
3946    it->item->queued = EINA_TRUE;
3947    if (cb && !sd->requeued)
3948      sd->queue = eina_list_sorted_insert(sd->queue, cb, it);
3949    else
3950      sd->queue = eina_list_append(sd->queue, it);
3951
3952    if (sd->queue_idle_enterer)
3953       ecore_idle_enterer_del(sd->queue_idle_enterer);
3954    sd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, sd);
3955
3956    if (sd->prev_viewport_w != 0)
3957      {
3958         while ((sd->queue) && ((!sd->blocks) || (!sd->blocks->next)))
3959           _queue_process(sd);
3960
3961         while ((sd->queue) && (sd->blocks) &&
3962                (sd->homogeneous) && (sd->mode == ELM_LIST_COMPRESS))
3963           _queue_process(sd);
3964      }
3965 }
3966
3967 /* If the application wants to know the relative item, use
3968  * elm_genlist_item_prev_get(it)*/
3969 static void
3970 _item_move_after(Elm_Gen_Item *it,
3971                  Elm_Gen_Item *after)
3972 {
3973    if (!it) return;
3974    if (!after) return;
3975    if (it == after) return;
3976
3977    GL_IT(it)->wsd->items =
3978      eina_inlist_remove(GL_IT(it)->wsd->items, EINA_INLIST_GET(it));
3979    if (it->item->block) _item_block_del(it);
3980
3981    GL_IT(it)->wsd->items = eina_inlist_append_relative
3982        (GL_IT(it)->wsd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3983    it->item->rel = after;
3984    after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
3985    it->item->before = EINA_FALSE;
3986    if (after->item->group_item) it->item->group_item = after->item->group_item;
3987    _item_queue(GL_IT(it)->wsd, it, NULL);
3988
3989    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_AFTER, it);
3990 }
3991
3992 static void
3993 _access_activate_cb(void *data __UNUSED__,
3994                     Evas_Object *part_obj __UNUSED__,
3995                     Elm_Object_Item *item)
3996 {
3997    _item_select_unselect((Elm_Gen_Item *)item, EINA_TRUE);
3998 }
3999
4000 /* If the application wants to know the relative item, use
4001  * elm_genlist_item_next_get(it)*/
4002 static void
4003 _item_move_before(Elm_Gen_Item *it,
4004                   Elm_Gen_Item *before)
4005 {
4006    if (!it) return;
4007    if (!before) return;
4008    if (it == before) return;
4009
4010    GL_IT(it)->wsd->items =
4011      eina_inlist_remove(GL_IT(it)->wsd->items, EINA_INLIST_GET(it));
4012    if (it->item->block) _item_block_del(it);
4013    GL_IT(it)->wsd->items = eina_inlist_prepend_relative
4014        (GL_IT(it)->wsd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4015    it->item->rel = before;
4016    before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
4017    it->item->before = EINA_TRUE;
4018    if (before->item->group_item)
4019      it->item->group_item = before->item->group_item;
4020    _item_queue(GL_IT(it)->wsd, it, NULL);
4021
4022    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_BEFORE, it);
4023 }
4024
4025 static void
4026 _item_mouse_up_cb(void *data,
4027                   Evas *evas __UNUSED__,
4028                   Evas_Object *obj __UNUSED__,
4029                   void *event_info)
4030 {
4031    Evas_Event_Mouse_Up *ev = event_info;
4032    Eina_Bool dragged = EINA_FALSE;
4033    Elm_Genlist_Smart_Data *sd;
4034    Elm_Gen_Item *it = data;
4035
4036    if (ev->button != 1) return;
4037    it->down = EINA_FALSE;
4038    sd = GL_IT(it)->wsd;
4039
4040    sd->mouse_down = EINA_FALSE;
4041    if (sd->multi_touched)
4042      {
4043         if ((!sd->multi) && (!it->selected) && (it->highlighted))
4044           _item_unhighlight(it);
4045         if (sd->multi_down) return;
4046         _multi_touch_gesture_eval(data);
4047         return;
4048      }
4049    if (it->long_timer)
4050      {
4051         ecore_timer_del(it->long_timer);
4052         it->long_timer = NULL;
4053      }
4054    if (it->dragging)
4055      {
4056         it->dragging = EINA_FALSE;
4057         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
4058         dragged = 1;
4059      }
4060    if (it->item->swipe_timer)
4061      {
4062         ecore_timer_del(it->item->swipe_timer);
4063         it->item->swipe_timer = NULL;
4064      }
4065    if (sd->multi_timer)
4066      {
4067         ecore_timer_del(sd->multi_timer);
4068         sd->multi_timer = NULL;
4069         sd->multi_timeout = EINA_FALSE;
4070      }
4071    sd->on_hold = EINA_FALSE;
4072    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
4073      {
4074         if (sd->swipe) _swipe_do(data);
4075         sd->longpressed = EINA_FALSE;
4076         return;
4077      }
4078    if ((sd->reorder_mode) && (sd->reorder_it))
4079      {
4080         Evas_Coord it_scrl_y = ev->canvas.y - sd->reorder_it->dy;
4081         sd->reorder_fast = 0;
4082
4083         if (sd->reorder_rel &&
4084             (sd->reorder_it->parent == sd->reorder_rel->parent))
4085           {
4086              if (it_scrl_y <= sd->reorder_rel->item->scrl_y)
4087                _item_move_before(sd->reorder_it, sd->reorder_rel);
4088              else
4089                _item_move_after(sd->reorder_it, sd->reorder_rel);
4090              evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4091           }
4092         else
4093           {
4094              if (sd->calc_job) ecore_job_del(sd->calc_job);
4095              sd->calc_job = ecore_job_add(_calc_job, sd);
4096           }
4097         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
4098         sd->reorder_it = sd->reorder_rel = NULL;
4099         sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
4100         sd->s_iface->bounce_allow_set
4101           (ELM_WIDGET_DATA(sd)->obj, sd->h_bounce, sd->v_bounce);
4102      }
4103    if (dragged)
4104      {
4105         if (it->want_unrealize && !(it->item->unrealize_disabled))
4106           {
4107              _item_unrealize(it, EINA_FALSE);
4108              if (it->item->block->want_unrealize)
4109                _item_block_unrealize(it->item->block);
4110           }
4111         return;
4112      }
4113
4114    if (!sd->longpressed)
4115      if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) ||
4116               (it->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS))
4117               _item_select_unselect(it, EINA_TRUE);
4118      else _item_select_unselect(it, !it->selected);
4119    else
4120      _item_unhighlight(it);
4121 }
4122
4123 static void
4124 _item_mouse_callbacks_add(Elm_Gen_Item *it,
4125                           Evas_Object *view)
4126 {
4127    evas_object_event_callback_add
4128      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
4129    evas_object_event_callback_add
4130      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
4131    evas_object_event_callback_add
4132      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
4133    evas_object_event_callback_add
4134      (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
4135    evas_object_event_callback_add
4136      (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
4137    evas_object_event_callback_add
4138      (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
4139 }
4140
4141 static void
4142 _item_mouse_callbacks_del(Elm_Gen_Item *it,
4143                           Evas_Object *view)
4144 {
4145    evas_object_event_callback_del_full
4146      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
4147    evas_object_event_callback_del_full
4148      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
4149    evas_object_event_callback_del_full
4150      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
4151    evas_object_event_callback_del_full
4152      (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
4153    evas_object_event_callback_del_full
4154      (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
4155    evas_object_event_callback_del_full
4156      (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
4157 }
4158
4159 static Eina_Bool
4160 _scroll_hold_timer_cb(void *data)
4161 {
4162    Elm_Genlist_Smart_Data *sd = data;
4163
4164    if (!data) return ECORE_CALLBACK_CANCEL;
4165
4166    sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
4167    sd->scr_hold_timer = NULL;
4168
4169    return ECORE_CALLBACK_CANCEL;
4170 }
4171
4172 static void
4173 _decorate_item_finished_signal_cb(void *data,
4174                                   Evas_Object *obj,
4175                                   const char *emission __UNUSED__,
4176                                   const char *source __UNUSED__)
4177 {
4178    Elm_Gen_Item *it = data;
4179    char buf[1024];
4180
4181    if (!data || !obj) return;
4182    if ((!it->realized) || (!it->item->deco_it_view)) return;
4183
4184    it->item->nocache_once = EINA_FALSE;
4185    _decorate_item_unrealize(it);
4186    if (it->item->group_item)
4187      evas_object_raise(it->item->VIEW(group_item));
4188
4189    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished",
4190             GL_IT(it)->wsd->decorate_it_type);
4191    edje_object_signal_callback_del_full
4192      (obj, buf, "elm", _decorate_item_finished_signal_cb, it);
4193 }
4194
4195 static Eina_List *
4196 _item_mode_content_unrealize(Elm_Gen_Item *it,
4197                              Evas_Object *target,
4198                              Eina_List **source,
4199                              const char *parts,
4200                              Eina_List **contents_list)
4201 {
4202    Eina_List *res = *contents_list;
4203
4204    if (it->itc->func.content_get)
4205      {
4206         const Eina_List *l;
4207         const char *key;
4208         Evas_Object *ic = NULL;
4209
4210         EINA_LIST_FOREACH(*source, l, key)
4211           {
4212              if (parts && fnmatch(parts, key, FNM_PERIOD))
4213                continue;
4214
4215              ic = edje_object_part_swallow_get(target, key);
4216              if (ic)
4217                {
4218                   res = eina_list_remove(res, ic);
4219                   edje_object_part_unswallow(target, ic);
4220                   evas_object_del(ic);
4221                }
4222           }
4223      }
4224
4225    return res;
4226 }
4227
4228 static Eina_List *
4229 _item_content_unrealize(Elm_Gen_Item *it,
4230                         Evas_Object *target,
4231                         Eina_List **source,
4232                         const char *parts)
4233 {
4234    Eina_List *res = it->content_objs;
4235
4236    if (it->itc->func.content_get)
4237      {
4238         const Eina_List *l;
4239         const char *key;
4240         Evas_Object *ic = NULL;
4241
4242         EINA_LIST_FOREACH(*source, l, key)
4243           {
4244              if (parts && fnmatch(parts, key, FNM_PERIOD))
4245                continue;
4246
4247              ic = edje_object_part_swallow_get(target, key);
4248              if (ic)
4249                {
4250                   res = eina_list_remove(res, ic);
4251                   edje_object_part_unswallow(target, ic);
4252                   // FIXME: If parent-child relationship was broken before 'ic'
4253                   // is deleted, freeze_pop will not be called. ex) elm_slider
4254                   // If layout is used instead of edje, this problme can be
4255                   // solved.
4256                   if (0 != elm_widget_scroll_freeze_get(ic))
4257                     elm_widget_scroll_freeze_pop(ic);
4258                   evas_object_del(ic);
4259                }
4260           }
4261      }
4262
4263    return res;
4264 }
4265
4266 static Eina_Bool
4267 _item_block_recalc(Item_Block *itb,
4268                    int in,
4269                    Eina_Bool qadd)
4270 {
4271    const Eina_List *l, *ll;
4272    Elm_Gen_Item *it;
4273    Evas_Coord minw = 0, minh = 0;
4274    Eina_Bool show_me = EINA_FALSE, changed = EINA_FALSE;
4275    Evas_Coord y = 0;
4276
4277    itb->num = in;
4278    EINA_LIST_FOREACH_SAFE(itb->items, l, ll, it)
4279      {
4280         show_me |= it->item->show_me;
4281         if (!itb->realized)
4282           {
4283              if (qadd)
4284                {
4285                   if (!it->item->mincalcd) changed = EINA_TRUE;
4286                   if (changed)
4287                     {
4288                        _item_realize(it, in, EINA_TRUE);
4289                        _item_unrealize(it, EINA_TRUE);
4290                     }
4291                }
4292              else
4293                {
4294                   if ((itb->sd->homogeneous) &&
4295                       (itb->sd->mode == ELM_LIST_COMPRESS))
4296                     {
4297                        if (it->group)
4298                          {
4299                             it->item->w = it->item->minw =
4300                                 GL_IT(it)->wsd->group_item_width;
4301                             it->item->h = it->item->minh =
4302                                 GL_IT(it)->wsd->group_item_height;
4303                          }
4304                        else
4305                          {
4306                             it->item->w = it->item->minw =
4307                                 GL_IT(it)->wsd->item_width;
4308                             it->item->h = it->item->minh =
4309                                 GL_IT(it)->wsd->item_height;
4310                          }
4311                     }
4312                   else
4313                     {
4314                        _item_realize(it, in, EINA_TRUE);
4315                        _item_unrealize(it, EINA_TRUE);
4316                     }
4317                }
4318           }
4319         else
4320           {
4321              if (!it->item->mincalcd) changed = EINA_TRUE;
4322              _item_realize(it, in, EINA_FALSE);
4323           }
4324         minh += it->item->minh;
4325         if (minw < it->item->minw) minw = it->item->minw;
4326         in++;
4327         it->x = 0;
4328         it->y = y;
4329 #if GENLIST_PINCH_ZOOM_SUPPORT
4330         if (IS_ROOT_PARENT_IT(it))
4331           it->item->pan_scrl_y = itb->y + it->y;
4332 #endif
4333         y += it->item->h;
4334      }
4335    if (changed) itb->sd->pan_changed = changed;
4336    itb->minw = minw;
4337    itb->minh = minh;
4338    itb->changed = EINA_FALSE;
4339    itb->position_update = EINA_FALSE;
4340
4341    return show_me;
4342 }
4343
4344 static void
4345 _update_job(void *data)
4346 {
4347    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
4348    Elm_Genlist_Smart_Data *sd = data;
4349    Item_Block *itb;
4350    Eina_List *l2;
4351    int num, num0;
4352
4353    sd->update_job = NULL;
4354    num = 0;
4355
4356    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4357    EINA_INLIST_FOREACH(sd->blocks, itb)
4358      {
4359         Evas_Coord itminw, itminh;
4360         Elm_Gen_Item *it;
4361
4362         if (!itb->updateme)
4363           {
4364              num += itb->count;
4365              if (position)
4366                _item_block_position(itb, num);
4367              continue;
4368           }
4369         num0 = num;
4370         recalc = EINA_FALSE;
4371         EINA_LIST_FOREACH(itb->items, l2, it)
4372           {
4373              if (it->item->updateme)
4374                {
4375                   itminw = it->item->minw;
4376                   itminh = it->item->minh;
4377
4378                   it->item->updateme = EINA_FALSE;
4379                   if (it->realized)
4380                     {
4381                        _item_unrealize(it, EINA_FALSE);
4382                        _item_realize(it, num, EINA_FALSE);
4383                        position = EINA_TRUE;
4384                     }
4385                   else
4386                     {
4387                        _item_realize(it, num, EINA_TRUE);
4388                        _item_unrealize(it, EINA_TRUE);
4389                     }
4390                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
4391                     recalc = EINA_TRUE;
4392                }
4393              num++;
4394           }
4395         itb->updateme = EINA_FALSE;
4396         if (recalc)
4397           {
4398              position = EINA_TRUE;
4399              itb->changed = EINA_TRUE;
4400              _item_block_recalc(itb, num0, EINA_FALSE);
4401              _item_block_position(itb, num0);
4402           }
4403      }
4404    if (position)
4405      {
4406         if (sd->calc_job) ecore_job_del(sd->calc_job);
4407         sd->calc_job = ecore_job_add(_calc_job, sd);
4408      }
4409    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4410    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4411 }
4412
4413 static void
4414 _scroll_animate_start_cb(Evas_Object *obj,
4415                          void *data __UNUSED__)
4416 {
4417 #if GENLIST_FX_SUPPORT
4418    _elm_genlist_fx_clear(obj, EINA_FALSE);
4419 #endif
4420    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
4421 }
4422
4423 static void
4424 _scroll_animate_stop_cb(Evas_Object *obj,
4425                         void *data __UNUSED__)
4426 {
4427 #if GENLIST_FX_SUPPORT
4428    _elm_genlist_fx_clear(obj, EINA_FALSE);
4429 #endif
4430    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
4431 }
4432
4433 static void
4434 _scroll_drag_start_cb(Evas_Object *obj,
4435                       void *data __UNUSED__)
4436 {
4437    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_START, NULL);
4438 }
4439
4440 static void
4441 _scroll_drag_stop_cb(Evas_Object *obj,
4442                      void *data __UNUSED__)
4443 {
4444    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_STOP, NULL);
4445 }
4446
4447 static void
4448 _edge_left_cb(Evas_Object *obj,
4449               void *data __UNUSED__)
4450 {
4451    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
4452 }
4453
4454 static void
4455 _edge_right_cb(Evas_Object *obj,
4456                void *data __UNUSED__)
4457 {
4458    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
4459 }
4460
4461 static void
4462 _edge_top_cb(Evas_Object *obj,
4463              void *data __UNUSED__)
4464 {
4465    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
4466 }
4467
4468 static void
4469 _edge_bottom_cb(Evas_Object *obj,
4470                 void *data __UNUSED__)
4471 {
4472    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
4473 }
4474
4475 static void
4476 _vbar_drag_cb(Evas_Object *obj,
4477                 void *data __UNUSED__)
4478 {
4479    evas_object_smart_callback_call(obj, SIG_VBAR_DRAG, NULL);
4480 }
4481
4482 static void
4483 _vbar_press_cb(Evas_Object *obj,
4484                 void *data __UNUSED__)
4485 {
4486    evas_object_smart_callback_call(obj, SIG_VBAR_PRESS, NULL);
4487 }
4488
4489 static void
4490 _vbar_unpress_cb(Evas_Object *obj,
4491                 void *data __UNUSED__)
4492 {
4493    evas_object_smart_callback_call(obj, SIG_VBAR_UNPRESS, NULL);
4494 }
4495
4496 static void
4497 _hbar_drag_cb(Evas_Object *obj,
4498                 void *data __UNUSED__)
4499 {
4500    evas_object_smart_callback_call(obj, SIG_HBAR_DRAG, NULL);
4501 }
4502
4503 static void
4504 _hbar_press_cb(Evas_Object *obj,
4505                 void *data __UNUSED__)
4506 {
4507    evas_object_smart_callback_call(obj, SIG_HBAR_PRESS, NULL);
4508 }
4509
4510 static void
4511 _hbar_unpress_cb(Evas_Object *obj,
4512                 void *data __UNUSED__)
4513 {
4514    evas_object_smart_callback_call(obj, SIG_HBAR_UNPRESS, NULL);
4515 }
4516
4517 static void
4518 _decorate_item_realize(Elm_Gen_Item *it)
4519 {
4520    char buf[1024];
4521    if (it->item->deco_it_view) return;
4522
4523    //evas_event_freeze(evas_object_evas_get(obj));
4524    it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
4525    edje_object_scale_set
4526      (it->item->deco_it_view, elm_widget_scale_get(WIDGET(it)) *
4527      elm_config_scale_get());
4528    evas_object_smart_member_add
4529      (it->item->deco_it_view, GL_IT(it)->wsd->pan_obj);
4530    elm_widget_sub_object_add(WIDGET(it), it->item->deco_it_view);
4531
4532    strncpy(buf, "item", sizeof(buf));
4533    if (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)
4534      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
4535
4536    if (it->item->order_num_in & 0x1)
4537      strncat(buf, "_odd", sizeof(buf) - strlen(buf));
4538    strncat(buf, "/", sizeof(buf) - strlen(buf));
4539    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
4540
4541    elm_widget_theme_object_set
4542      (WIDGET(it), it->item->deco_it_view, "genlist", buf,
4543      elm_widget_style_get(WIDGET(it)));
4544    edje_object_mirrored_set
4545      (it->item->deco_it_view, elm_widget_mirrored_get(WIDGET(it)));
4546
4547    /* signal callback add */
4548    evas_object_event_callback_add
4549      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb,
4550      it);
4551    evas_object_event_callback_add
4552      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
4553    evas_object_event_callback_add
4554      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb,
4555      it);
4556
4557    if (eina_list_count(it->item->deco_it_content_objs) != 0)
4558      ERR_ABORT("If you see this error, please notify us and we"
4559                "will fix it");
4560
4561    /* text_get, content_get, state_get */
4562    _item_text_realize
4563      (it, it->item->deco_it_view, &it->item->deco_it_texts, NULL);
4564    if (!it->item->deco_it_contents)
4565      it->item->deco_it_contents =
4566        elm_widget_stringlist_get
4567          (edje_object_data_get(it->item->deco_it_view, "contents"));
4568    it->item->deco_it_content_objs =
4569      _item_mode_content_realize
4570        (it, it->item->deco_it_view, &it->item->deco_it_contents, NULL,
4571        &it->item->deco_it_content_objs);
4572    _item_state_realize
4573      (it, it->item->deco_it_view, &it->item->deco_it_states, NULL);
4574    edje_object_part_swallow
4575      (it->item->deco_it_view,
4576      edje_object_data_get(it->item->deco_it_view, "mode_part"), VIEW(it));
4577
4578    it->want_unrealize = EINA_FALSE;
4579    //evas_event_thaw(evas_object_evas_get(obj));
4580    //evas_event_thaw_eval(evas_object_evas_get(obj));
4581 }
4582
4583 static void
4584 _decorate_item_set(Elm_Gen_Item *it)
4585 {
4586    Elm_Genlist_Smart_Data *sd;
4587    char buf[1024];
4588
4589    if (!it) return;
4590
4591    sd = GL_IT(it)->wsd;
4592
4593    sd->mode_item = it;
4594    it->item->nocache_once = EINA_TRUE;
4595
4596    if (sd->scr_hold_timer)
4597      {
4598         ecore_timer_del(sd->scr_hold_timer);
4599         sd->scr_hold_timer = NULL;
4600      }
4601    sd->s_iface->hold_set(ELM_WIDGET_DATA(sd)->obj, EINA_TRUE);
4602    sd->scr_hold_timer = ecore_timer_add(0.1, _scroll_hold_timer_cb, sd);
4603
4604    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4605    _decorate_item_realize(it);
4606    if (it->item->group_item)
4607      evas_object_raise(it->item->VIEW(group_item));
4608    _item_position
4609      (it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
4610    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4611    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
4612
4613    snprintf(buf, sizeof(buf), "elm,state,%s,active", sd->decorate_it_type);
4614    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
4615 }
4616
4617 static void
4618 _decorate_item_unset(Elm_Genlist_Smart_Data *sd)
4619 {
4620    char buf[1024], buf2[1024];
4621    Elm_Gen_Item *it;
4622
4623    if (!sd->mode_item) return;
4624
4625    it = sd->mode_item;
4626    it->item->nocache_once = EINA_TRUE;
4627
4628    snprintf(buf, sizeof(buf), "elm,state,%s,passive", sd->decorate_it_type);
4629    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished",
4630             sd->decorate_it_type);
4631    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
4632    edje_object_signal_callback_add
4633      (it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb,
4634      it);
4635    sd->mode_item = NULL;
4636 }
4637
4638 #if 0
4639 // FIXME: difference from upstream
4640 static void
4641 _mouse_down_scroller(void        *data,
4642                      Evas        *evas __UNUSED__,
4643                      Evas_Object *obj __UNUSED__,
4644                      void        *event_info __UNUSED__)
4645 {
4646    Widget_Data *wd = elm_widget_data_get(data);
4647
4648    if (!wd) return;
4649    wd->drag_started = EINA_FALSE;
4650 }
4651
4652 static void
4653 _mouse_up_scroller(void        *data,
4654                    Evas        *evas __UNUSED__,
4655                    Evas_Object *obj __UNUSED__,
4656                    void        *event_info __UNUSED__)
4657 {
4658    Widget_Data *wd = elm_widget_data_get(data);
4659
4660    if (!wd) return;
4661    wd->drag_started = EINA_FALSE;
4662 }
4663
4664 static void
4665 _mouse_move_scroller(void        *data,
4666                      Evas        *evas __UNUSED__,
4667                      Evas_Object *obj __UNUSED__,
4668                      void        *event_info)
4669 {
4670    Widget_Data *wd = elm_widget_data_get(data);
4671    Evas_Event_Mouse_Move *ev = event_info;
4672    Evas_Coord minw = 0, minh = 0, dx, dy, adx, ady;
4673
4674    if (!wd) return;
4675    if (wd->drag_started) return;
4676
4677    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
4678    dx = ev->cur.canvas.x - ev->prev.canvas.x;
4679    dy = ev->cur.canvas.y - ev->prev.canvas.y;
4680    adx = dx;
4681    ady = dy;
4682    if (adx < 0) adx = -dx;
4683    if (ady < 0) ady = -dy;
4684    if (((ady < minh) && (ady > minh / 2)) && (ady > adx))
4685      {
4686         if (dy < 0)
4687           {
4688              evas_object_smart_callback_call(data, SIG_DRAG_START_UP, NULL);
4689              wd->drag_started = EINA_TRUE;
4690           }
4691         else
4692           {
4693              evas_object_smart_callback_call(data, SIG_DRAG_START_DOWN, NULL);
4694              wd->drag_started = EINA_TRUE;
4695           }
4696      }
4697 }
4698 #endif
4699
4700 static void
4701 _elm_genlist_smart_add(Evas_Object *obj)
4702 {
4703    Evas_Coord minw, minh;
4704    Elm_Genlist_Pan_Smart_Data *pan_data;
4705
4706    EVAS_SMART_DATA_ALLOC(obj, Elm_Genlist_Smart_Data);
4707
4708    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.add(obj);
4709
4710    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
4711    evas_object_smart_member_add(priv->hit_rect, obj);
4712    elm_widget_sub_object_add(obj, priv->hit_rect);
4713
4714    /* common scroller hit rectangle setup */
4715    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
4716    evas_object_show(priv->hit_rect);
4717    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
4718
4719    elm_widget_can_focus_set(obj, EINA_TRUE);
4720    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
4721
4722    elm_layout_theme_set(obj, "genlist", "base", elm_widget_style_get(obj));
4723
4724    /* interface's add() routine issued AFTER the object's smart_add() */
4725    priv->s_iface = evas_object_smart_interface_get
4726        (obj, ELM_SCROLLABLE_IFACE_NAME);
4727
4728    priv->s_iface->objects_set
4729      (obj, ELM_WIDGET_DATA(priv)->resize_obj, priv->hit_rect);
4730
4731    priv->s_iface->bounce_allow_set
4732      (obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable);
4733    priv->v_bounce = _elm_config->thumbscroll_bounce_enable;
4734
4735    priv->s_iface->animate_start_cb_set(obj, _scroll_animate_start_cb);
4736    priv->s_iface->animate_stop_cb_set(obj, _scroll_animate_stop_cb);
4737    priv->s_iface->drag_start_cb_set(obj, _scroll_drag_start_cb);
4738    priv->s_iface->drag_stop_cb_set(obj, _scroll_drag_stop_cb);
4739    priv->s_iface->edge_left_cb_set(obj, _edge_left_cb);
4740    priv->s_iface->edge_right_cb_set(obj, _edge_right_cb);
4741    priv->s_iface->edge_top_cb_set(obj, _edge_top_cb);
4742    priv->s_iface->edge_bottom_cb_set(obj, _edge_bottom_cb);
4743    priv->s_iface->vbar_drag_cb_set(obj, _vbar_drag_cb);
4744    priv->s_iface->vbar_press_cb_set(obj, _vbar_press_cb);
4745    priv->s_iface->vbar_unpress_cb_set(obj, _vbar_unpress_cb);
4746    priv->s_iface->hbar_drag_cb_set(obj, _hbar_drag_cb);
4747    priv->s_iface->hbar_press_cb_set(obj, _hbar_press_cb);
4748    priv->s_iface->hbar_unpress_cb_set(obj, _hbar_unpress_cb);
4749
4750    priv->mode = ELM_LIST_SCROLL;
4751    priv->max_items_per_block = MAX_ITEMS_PER_BLOCK;
4752    priv->item_cache_max = priv->max_items_per_block * 2;
4753    priv->longpress_timeout = _elm_config->longpress_timeout;
4754    priv->highlight = EINA_TRUE;
4755
4756 #if GENLIST_FX_SUPPORT
4757    priv->fx_mode = EINA_FALSE;
4758    priv->rendered = EINA_FALSE;
4759    priv->fx_first_captured = EINA_FALSE;
4760    priv->fx_playing = EINA_FALSE;
4761    priv->fx_items_deleted = EINA_FALSE;
4762    priv->genlist_clearing = EINA_FALSE;
4763 #endif
4764
4765    priv->pan_obj = evas_object_smart_add
4766        (evas_object_evas_get(obj), _elm_genlist_pan_smart_class_new());
4767    pan_data = evas_object_smart_data_get(priv->pan_obj);
4768    pan_data->wsd = priv;
4769
4770 #if 0
4771    // FIXME: difference from upstream
4772    evas_object_event_callback_add(pan_obj, EVAS_CALLBACK_MOUSE_DOWN,
4773                                   _mouse_down_scroller, obj);
4774    evas_object_event_callback_add(pan_obj, EVAS_CALLBACK_MOUSE_UP,
4775                                   _mouse_up_scroller, obj);
4776    evas_object_event_callback_add(pan_obj, EVAS_CALLBACK_MOUSE_MOVE,
4777                                   _mouse_move_scroller, obj);
4778 #endif
4779
4780    priv->s_iface->extern_pan_set(obj, priv->pan_obj);
4781
4782    edje_object_size_min_calc(ELM_WIDGET_DATA(priv)->resize_obj, &minw, &minh);
4783    evas_object_size_hint_min_set(obj, minw, minh);
4784
4785    _item_cache_all_free(priv);
4786    _mirrored_set(obj, elm_widget_mirrored_get(obj));
4787
4788    elm_layout_sizing_eval(obj);
4789 }
4790
4791 static void
4792 _elm_genlist_smart_del(Evas_Object *obj)
4793 {
4794    ELM_GENLIST_DATA_GET(obj, sd);
4795
4796    elm_genlist_clear(obj);
4797    if (sd->calc_job) ecore_job_del(sd->calc_job);
4798    if (sd->update_job) ecore_job_del(sd->update_job);
4799    if (sd->queue_idle_enterer) ecore_idle_enterer_del(sd->queue_idle_enterer);
4800    if (sd->must_recalc_idler) ecore_idler_del(sd->must_recalc_idler);
4801    if (sd->multi_timer) ecore_timer_del(sd->multi_timer);
4802    if (sd->decorate_it_type) eina_stringshare_del(sd->decorate_it_type);
4803    if (sd->scr_hold_timer) ecore_timer_del(sd->scr_hold_timer);
4804
4805    evas_object_del(sd->pan_obj);
4806    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.del(obj);
4807 }
4808
4809 static void
4810 _elm_genlist_smart_move(Evas_Object *obj,
4811                         Evas_Coord x,
4812                         Evas_Coord y)
4813 {
4814    ELM_GENLIST_DATA_GET(obj, sd);
4815
4816    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.move(obj, x, y);
4817
4818    evas_object_move(sd->hit_rect, x, y);
4819 }
4820
4821 static void
4822 _elm_genlist_smart_resize(Evas_Object *obj,
4823                           Evas_Coord w,
4824                           Evas_Coord h)
4825 {
4826    ELM_GENLIST_DATA_GET(obj, sd);
4827
4828    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.resize(obj, w, h);
4829
4830    evas_object_resize(sd->hit_rect, w, h);
4831 }
4832
4833 static void
4834 _elm_genlist_smart_member_add(Evas_Object *obj,
4835                               Evas_Object *member)
4836 {
4837    ELM_GENLIST_DATA_GET(obj, sd);
4838
4839    ELM_WIDGET_CLASS(_elm_genlist_parent_sc)->base.member_add(obj, member);
4840
4841    if (sd->hit_rect)
4842      evas_object_raise(sd->hit_rect);
4843 }
4844
4845 static void
4846 _access_obj_process(Elm_Genlist_Smart_Data *sd, Eina_Bool is_access)
4847 {
4848    Item_Block *itb;
4849    Eina_Bool done = EINA_FALSE;
4850
4851    EINA_INLIST_FOREACH(sd->blocks, itb)
4852      {
4853         if (itb->realized)
4854           {
4855              Eina_List *l;
4856              Elm_Gen_Item *it;
4857
4858              done = EINA_TRUE;
4859              EINA_LIST_FOREACH(itb->items, l, it)
4860                {
4861                   if (!it->realized) continue;
4862                   if (is_access) _access_widget_item_register(it);
4863                   else
4864                     _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
4865                }
4866           }
4867         else if (done) break;
4868      }
4869 }
4870
4871 static void
4872 _elm_genlist_smart_access(Evas_Object *obj, Eina_Bool is_access)
4873 {
4874    ELM_GENLIST_CHECK(obj);
4875    ELM_GENLIST_DATA_GET(obj, sd);
4876
4877    if (is_access)
4878      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
4879      _elm_genlist_smart_focus_next;
4880    else
4881      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
4882    _access_obj_process(sd, is_access);
4883 }
4884
4885 static void
4886 _elm_genlist_smart_set_user(Elm_Genlist_Smart_Class *sc)
4887 {
4888    ELM_WIDGET_CLASS(sc)->base.add = _elm_genlist_smart_add;
4889    ELM_WIDGET_CLASS(sc)->base.del = _elm_genlist_smart_del;
4890    ELM_WIDGET_CLASS(sc)->base.move = _elm_genlist_smart_move;
4891    ELM_WIDGET_CLASS(sc)->base.resize = _elm_genlist_smart_resize;
4892    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_genlist_smart_member_add;
4893
4894    ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_genlist_smart_sub_object_add;
4895    ELM_WIDGET_CLASS(sc)->sub_object_del = _elm_genlist_smart_sub_object_del;
4896    ELM_WIDGET_CLASS(sc)->on_focus = _elm_genlist_smart_on_focus;
4897    ELM_WIDGET_CLASS(sc)->theme = _elm_genlist_smart_theme;
4898    ELM_WIDGET_CLASS(sc)->event = _elm_genlist_smart_event;
4899    ELM_WIDGET_CLASS(sc)->translate = _elm_genlist_smart_translate;
4900
4901    /* not a 'focus chain manager' */
4902    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
4903    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
4904
4905    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_genlist_smart_sizing_eval;
4906
4907    // ACCESS
4908    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
4909      ELM_WIDGET_CLASS(sc)->focus_next = _elm_genlist_smart_focus_next;
4910
4911    ELM_WIDGET_CLASS(sc)->access = _elm_genlist_smart_access;
4912 }
4913
4914 EAPI const Elm_Genlist_Smart_Class *
4915 elm_genlist_smart_class_get(void)
4916 {
4917    static Elm_Genlist_Smart_Class _sc =
4918      ELM_GENLIST_SMART_CLASS_INIT_NAME_VERSION(ELM_GENLIST_SMART_NAME);
4919    static const Elm_Genlist_Smart_Class *class = NULL;
4920    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
4921
4922    if (class)
4923      return class;
4924
4925    _elm_genlist_smart_set(&_sc);
4926    esc->callbacks = _smart_callbacks;
4927    class = &_sc;
4928
4929    return class;
4930 }
4931
4932 EAPI Evas_Object *
4933 elm_genlist_add(Evas_Object *parent)
4934 {
4935    Evas_Object *obj;
4936
4937    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
4938
4939    obj = elm_widget_add(_elm_genlist_smart_class_new(), parent);
4940    if (!obj) return NULL;
4941
4942    if (!elm_widget_sub_object_add(parent, obj))
4943      ERR("could not add %p as sub object of %p", obj, parent);
4944
4945    return obj;
4946 }
4947
4948
4949 static Evas_Object *
4950 _item_content_get_hook(Elm_Gen_Item *it,
4951                        const char *part)
4952 {
4953    Evas_Object *ret = NULL;
4954    if (it->deco_all_view)
4955      ret = edje_object_part_swallow_get(it->deco_all_view, part);
4956    else if (it->decorate_it_set)
4957      ret = edje_object_part_swallow_get(it->item->deco_it_view, part);
4958    if (!ret)
4959      ret = edje_object_part_swallow_get(VIEW(it), part);
4960    return ret;
4961 }
4962
4963 static const char *
4964 _item_text_get_hook(Elm_Gen_Item *it,
4965                     const char *part)
4966 {
4967    if (!it->itc->func.text_get) return NULL;
4968    const char *ret = NULL;
4969    if (it->deco_all_view)
4970      ret = edje_object_part_text_get(it->deco_all_view, part);
4971    else if (it->decorate_it_set)
4972      ret = edje_object_part_text_get(it->item->deco_it_view, part);
4973    if (!ret)
4974      ret = edje_object_part_text_get(VIEW(it), part);
4975    return ret;
4976 }
4977
4978 static void
4979 _item_disable_hook(Elm_Object_Item *item)
4980 {
4981    Eina_List *l;
4982    Evas_Object *obj;
4983    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
4984
4985    if (it->selected)
4986      elm_genlist_item_selected_set(item, EINA_FALSE);
4987
4988    if (it->realized)
4989      {
4990         if (elm_widget_item_disabled_get(it))
4991           {
4992              edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
4993              if (it->deco_all_view)
4994                edje_object_signal_emit
4995                  (it->deco_all_view, "elm,state,disabled", "elm");
4996           }
4997         else
4998           {
4999              edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
5000              if (it->deco_all_view)
5001                edje_object_signal_emit
5002                  (it->deco_all_view, "elm,state,enabled", "elm");
5003           }
5004         EINA_LIST_FOREACH(it->content_objs, l, obj)
5005           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(it));
5006      }
5007 }
5008
5009 static void
5010 _item_free(Elm_Gen_Item *it)
5011 {
5012    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
5013
5014 #if GENLIST_FX_SUPPORT
5015    if (sd->fx_mode) GL_IT(it)->has_proxy_it = EINA_FALSE;
5016    _elm_genlist_proxy_item_del((Elm_Object_Item *)it);
5017    if ((!sd->fx_mode) || (sd->genlist_clearing))
5018 #endif
5019      {
5020         _item_free_common(it);
5021      }
5022    _item_unrealize(it, EINA_FALSE);
5023    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
5024    free(it->item);
5025
5026    if (sd->calc_job) ecore_job_del(sd->calc_job);
5027    sd->calc_job = ecore_job_add(_calc_job, sd);
5028 }
5029
5030 #if GENLIST_FX_SUPPORT
5031 static void
5032 _item_del_pre_fx_process(Elm_Gen_Item *it)
5033 {
5034    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
5035
5036    sd->fx_items_deleted = EINA_TRUE;
5037    _elm_genlist_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
5038    if (!eina_list_data_find(sd->pending_del_items, it))
5039      sd->pending_del_items = eina_list_append(sd->pending_del_items, it);
5040
5041    _item_free_common(it);
5042
5043 }
5044 #endif
5045
5046 static Eina_Bool
5047 _item_del_pre_hook(Elm_Object_Item *item)
5048 {
5049    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5050
5051 #if GENLIST_FX_SUPPORT
5052    if ((GL_IT(it)->wsd->fx_mode) && (!GL_IT(it)->wsd->genlist_clearing))
5053      {
5054         _item_del_pre_fx_process(it);
5055         return EINA_FALSE;
5056      }
5057 #endif
5058    _item_free(it);
5059    return EINA_TRUE;
5060 }
5061
5062 static void
5063 _item_signal_emit_hook(Elm_Object_Item *it,
5064                        const char *emission,
5065                        const char *source)
5066 {
5067    edje_object_signal_emit(VIEW(it), emission, source);
5068 }
5069
5070 static Elm_Gen_Item *
5071 _elm_genlist_item_new(Elm_Genlist_Smart_Data *sd,
5072                       const Elm_Genlist_Item_Class *itc,
5073                       const void *data,
5074                       Elm_Gen_Item *parent,
5075                       Elm_Genlist_Item_Type type,
5076                       Evas_Smart_Cb func,
5077                       const void *func_data)
5078 {
5079    Elm_Gen_Item *it, *it2;
5080    int depth = 0;
5081
5082    if (!itc) return NULL;
5083
5084    it = elm_widget_item_new(ELM_WIDGET_DATA(sd)->obj, Elm_Gen_Item);
5085    if (!it) return NULL;
5086
5087    it->itc = itc;
5088    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
5089
5090    it->base.data = data;
5091    it->parent = parent;
5092    it->func.func = func;
5093    it->func.data = func_data;
5094
5095    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
5096    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
5097    elm_widget_item_disable_hook_set(it, _item_disable_hook);
5098    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
5099    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
5100
5101 #if 0 // FIXME: difference from upstream
5102    it->can_focus = EINA_TRUE;
5103 #endif
5104    //it->del_cb = (Ecore_Cb)_item_free;
5105    //it->highlight_cb = (Ecore_Cb)_item_highlight;
5106    //it->unhighlight_cb = (Ecore_Cb)_item_unhighlight;
5107    //it->sel_cb = (Ecore_Cb)_item_select;
5108    //it->unsel_cb = (Ecore_Cb)_item_unselect;
5109    //it->unrealize_cb = (Ecore_Cb)_item_unrealize_cb;
5110
5111    GL_IT(it) = ELM_NEW(Elm_Gen_Item_Type);
5112    GL_IT(it)->wsd = sd;
5113    GL_IT(it)->type = type;
5114    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
5115
5116    if (it->parent)
5117      {
5118         if (it->parent->group)
5119           GL_IT(it)->group_item = parent;
5120         else if (GL_IT(it->parent)->group_item)
5121           GL_IT(it)->group_item = GL_IT(it->parent)->group_item;
5122      }
5123    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
5124      {
5125         if (!it2->parent->group) depth += 1;
5126      }
5127    GL_IT(it)->expanded_depth = depth;
5128    sd->item_count++;
5129
5130 #if GENLIST_FX_SUPPORT
5131    it->item->num = sd->item_count;
5132    if (sd->fx_mode)
5133      {
5134         sd->fx_items_deleted = EINA_FALSE;
5135         _elm_genlist_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
5136      }
5137 #endif
5138    return it;
5139 }
5140
5141 static int
5142 _elm_genlist_item_compare(const void *data,
5143                           const void *data1)
5144 {
5145    const Elm_Gen_Item *it, *item1;
5146
5147    it = ELM_GEN_ITEM_FROM_INLIST(data);
5148    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
5149    return GL_IT(it)->wsd->item_compare_cb(it, item1);
5150 }
5151
5152 static int
5153 _elm_genlist_item_list_compare(const void *data,
5154                                const void *data1)
5155 {
5156    const Elm_Gen_Item *it = data;
5157    const Elm_Gen_Item *item1 = data1;
5158
5159    return GL_IT(it)->wsd->item_compare_cb(it, item1);
5160 }
5161
5162 EAPI unsigned int
5163 elm_genlist_items_count(const Evas_Object *obj)
5164 {
5165    ELM_GENLIST_CHECK(obj) 0;
5166    ELM_GENLIST_DATA_GET(obj, sd);
5167
5168    return sd->item_count;
5169 }
5170
5171 EAPI Elm_Object_Item *
5172 elm_genlist_item_append(Evas_Object *obj,
5173                         const Elm_Genlist_Item_Class *itc,
5174                         const void *data,
5175                         Elm_Object_Item *parent,
5176                         Elm_Genlist_Item_Type type,
5177                         Evas_Smart_Cb func,
5178                         const void *func_data)
5179 {
5180    Elm_Gen_Item *it;
5181
5182    ELM_GENLIST_CHECK(obj) NULL;
5183    ELM_GENLIST_DATA_GET(obj, sd);
5184    if (parent)
5185      ELM_WIDGET_ITEM_RETURN_IF_ONDEL(((Elm_Widget_Item *)parent),NULL);
5186
5187    it = _elm_genlist_item_new
5188        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5189    if (!it) return NULL;
5190
5191    if (!it->parent)
5192      {
5193         if (it->group)
5194           sd->group_items = eina_list_append(sd->group_items, it);
5195         sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
5196         it->item->rel = NULL;
5197      }
5198    else
5199      {
5200         Elm_Gen_Item *it2 = NULL;
5201         Eina_List *ll = eina_list_last(it->parent->item->items);
5202
5203         if (ll) it2 = ll->data;
5204         it->parent->item->items =
5205           eina_list_append(it->parent->item->items, it);
5206         if (!it2) it2 = it->parent;
5207         sd->items = eina_inlist_append_relative
5208           (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
5209         it->item->rel = it2;
5210         it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
5211      }
5212    it->item->before = EINA_FALSE;
5213    _item_queue(sd, it, NULL);
5214
5215    return (Elm_Object_Item *)it;
5216 }
5217
5218 EAPI Elm_Object_Item *
5219 elm_genlist_item_prepend(Evas_Object *obj,
5220                          const Elm_Genlist_Item_Class *itc,
5221                          const void *data,
5222                          Elm_Object_Item *parent,
5223                          Elm_Genlist_Item_Type type,
5224                          Evas_Smart_Cb func,
5225                          const void *func_data)
5226 {
5227    Elm_Gen_Item *it;
5228
5229    ELM_GENLIST_CHECK(obj) NULL;
5230    ELM_GENLIST_DATA_GET(obj, sd);
5231    it = _elm_genlist_item_new
5232        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5233    if (!it) return NULL;
5234
5235    if (!it->parent)
5236      {
5237         if (it->group)
5238           sd->group_items = eina_list_prepend(sd->group_items, it);
5239         sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
5240         it->item->rel = NULL;
5241      }
5242    else
5243      {
5244         Elm_Gen_Item *it2 = NULL;
5245         Eina_List *ll = it->parent->item->items;
5246
5247         if (ll) it2 = ll->data;
5248         it->parent->item->items =
5249           eina_list_prepend(it->parent->item->items, it);
5250         if (!it2) it2 = it->parent;
5251         sd->items = eina_inlist_prepend_relative
5252             (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
5253         it->item->rel = it2;
5254         it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
5255      }
5256    it->item->before = EINA_TRUE;
5257    _item_queue(sd, it, NULL);
5258
5259    return (Elm_Object_Item *)it;
5260 }
5261
5262 EAPI Elm_Object_Item *
5263 elm_genlist_item_insert_after(Evas_Object *obj,
5264                               const Elm_Genlist_Item_Class *itc,
5265                               const void *data,
5266                               Elm_Object_Item *parent,
5267                               Elm_Object_Item *after_it,
5268                               Elm_Genlist_Item_Type type,
5269                               Evas_Smart_Cb func,
5270                               const void *func_data)
5271 {
5272    Elm_Gen_Item *after = (Elm_Gen_Item *)after_it;
5273    Elm_Gen_Item *it;
5274
5275    ELM_GENLIST_CHECK(obj) NULL;
5276    ELM_GENLIST_ITEM_CHECK_OR_RETURN(after_it, NULL);
5277    ELM_GENLIST_DATA_GET(obj, sd);
5278
5279    /* It makes no sense to insert after in an empty list with after !=
5280     * NULL, something really bad is happening in your app. */
5281    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
5282
5283    it = _elm_genlist_item_new
5284        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5285    if (!it) return NULL;
5286
5287    if (!it->parent)
5288      {
5289         if ((it->group) && (after->group))
5290           sd->group_items = eina_list_append_relative
5291               (sd->group_items, it, after);
5292      }
5293    else
5294      {
5295         it->parent->item->items =
5296           eina_list_append_relative(it->parent->item->items, it, after);
5297      }
5298    sd->items = eina_inlist_append_relative
5299        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
5300
5301    it->item->rel = after;
5302    after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
5303    it->item->before = EINA_FALSE;
5304    _item_queue(sd, it, NULL);
5305
5306    return (Elm_Object_Item *)it;
5307 }
5308
5309 EAPI Elm_Object_Item *
5310 elm_genlist_item_insert_before(Evas_Object *obj,
5311                                const Elm_Genlist_Item_Class *itc,
5312                                const void *data,
5313                                Elm_Object_Item *parent,
5314                                Elm_Object_Item *before_it,
5315                                Elm_Genlist_Item_Type type,
5316                                Evas_Smart_Cb func,
5317                                const void *func_data)
5318 {
5319    Elm_Gen_Item *before = (Elm_Gen_Item *)before_it;
5320    Elm_Gen_Item *it;
5321
5322    ELM_GENLIST_CHECK(obj) NULL;
5323    ELM_GENLIST_ITEM_CHECK_OR_RETURN(before_it, NULL);
5324    ELM_GENLIST_DATA_GET(obj, sd);
5325
5326    /* It makes no sense to insert before in an empty list with before
5327     * != NULL, something really bad is happening in your app. */
5328    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
5329
5330    it = _elm_genlist_item_new
5331        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5332    if (!it) return NULL;
5333
5334    if (!it->parent)
5335      {
5336         if (it->group && before->group)
5337           sd->group_items =
5338             eina_list_prepend_relative(sd->group_items, it, before);
5339      }
5340    else
5341      {
5342         it->parent->item->items =
5343           eina_list_prepend_relative(it->parent->item->items, it, before);
5344      }
5345    sd->items = eina_inlist_prepend_relative
5346        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
5347
5348    it->item->rel = before;
5349    before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
5350    it->item->before = EINA_TRUE;
5351    _item_queue(sd, it, NULL);
5352
5353    return (Elm_Object_Item *)it;
5354 }
5355
5356 EAPI Elm_Object_Item *
5357 elm_genlist_item_sorted_insert(Evas_Object *obj,
5358                                const Elm_Genlist_Item_Class *itc,
5359                                const void *data,
5360                                Elm_Object_Item *parent,
5361                                Elm_Genlist_Item_Type type,
5362                                Eina_Compare_Cb comp,
5363                                Evas_Smart_Cb func,
5364                                const void *func_data)
5365 {
5366    Elm_Gen_Item *rel = NULL;
5367    Elm_Gen_Item *it;
5368
5369    ELM_GENLIST_CHECK(obj) NULL;
5370    ELM_GENLIST_DATA_GET(obj, sd);
5371
5372    it = _elm_genlist_item_new
5373        (sd, itc, data, (Elm_Gen_Item *)parent, type, func, func_data);
5374    if (!it) return NULL;
5375
5376    sd->item_compare_cb = comp;
5377
5378    if (it->parent)
5379      {
5380         Eina_List *l;
5381         int cmp_result;
5382
5383         l = eina_list_search_sorted_near_list
5384             (it->parent->item->items, _elm_genlist_item_list_compare, it,
5385             &cmp_result);
5386
5387         if (l)
5388           rel = eina_list_data_get(l);
5389         else
5390           rel = it->parent;
5391
5392         if (cmp_result >= 0)
5393           {
5394              it->parent->item->items = eina_list_prepend_relative_list
5395                  (it->parent->item->items, it, l);
5396              sd->items = eina_inlist_prepend_relative
5397                  (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
5398              it->item->before = EINA_FALSE;
5399           }
5400         else if (cmp_result < 0)
5401           {
5402              it->parent->item->items = eina_list_append_relative_list
5403                  (it->parent->item->items, it, l);
5404              sd->items = eina_inlist_append_relative
5405                  (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
5406              it->item->before = EINA_TRUE;
5407           }
5408      }
5409    else
5410      {
5411         if (!sd->state)
5412           {
5413              sd->state = eina_inlist_sorted_state_new();
5414              eina_inlist_sorted_state_init(sd->state, sd->items);
5415              sd->requeued = EINA_FALSE;
5416           }
5417
5418         if (it->group)
5419           sd->group_items = eina_list_append(sd->group_items, it);
5420
5421         sd->items = eina_inlist_sorted_state_insert
5422             (sd->items, EINA_INLIST_GET(it), _elm_genlist_item_compare,
5423             sd->state);
5424
5425         if (EINA_INLIST_GET(it)->next)
5426           {
5427              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5428              it->item->before = EINA_TRUE;
5429           }
5430         else if (EINA_INLIST_GET(it)->prev)
5431           {
5432              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5433              it->item->before = EINA_FALSE;
5434           }
5435      }
5436
5437    if (rel)
5438      {
5439         it->item->rel = rel;
5440         rel->item->rel_revs = eina_list_append(rel->item->rel_revs, it);
5441      }
5442
5443    _item_queue(sd, it, _elm_genlist_item_list_compare);
5444
5445    return (Elm_Object_Item *)it;
5446 }
5447
5448 static void
5449 _elm_genlist_fx_clear(Evas_Object *obj, Eina_Bool force)
5450 {
5451    ELM_GENLIST_DATA_GET(obj, sd);
5452
5453    Elm_Gen_FX_Item *fi;
5454    Proxy_Item *pi;
5455    Elm_Gen_Item *it;
5456
5457    if ((!force) && (!sd->fx_first_captured)) return;
5458
5459    EINA_LIST_FREE(sd->capture_before_items, pi)
5460      {
5461         if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
5462         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
5463         if (pi->proxy) evas_object_del(pi->proxy);
5464         free(pi);
5465      }
5466    EINA_LIST_FREE(sd->capture_after_items, pi)
5467      {
5468         if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
5469         if (pi->proxy) evas_object_smart_member_del(pi->proxy);
5470         if (pi->proxy) evas_object_del(pi->proxy);
5471         free(pi);
5472      }
5473
5474    EINA_LIST_FREE(sd->fx_items, fi)
5475      {
5476         if (fi->trans) elm_transit_del(fi->trans);
5477         free(fi);
5478      }
5479
5480    EINA_LIST_FREE (sd->pending_unrealized_items, it)
5481       _item_unrealize(it, EINA_FALSE);
5482
5483    EINA_LIST_FREE (sd->pending_unrealized_decorate_all_items, it)
5484       _decorate_all_item_unrealize(it);
5485
5486    EINA_LIST_FREE (sd->pending_del_items, it)
5487      {
5488         _item_free(it);
5489         _elm_widget_item_free((Elm_Widget_Item *)it);
5490      }
5491    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
5492    sd->alpha_bg = NULL;
5493    if (sd->fx_timer) ecore_timer_del(sd->fx_timer);
5494    sd->fx_timer = NULL;
5495
5496    sd->genlist_clearing = EINA_TRUE;
5497    sd->fx_playing = EINA_FALSE;
5498    sd->sorting = EINA_FALSE;
5499    sd->fx_first_captured = EINA_FALSE;
5500    sd->fx_items_deleted = EINA_FALSE;
5501 }
5502
5503 EAPI void
5504 elm_genlist_clear(Evas_Object *obj)
5505 {
5506    ELM_GENLIST_CHECK(obj);
5507    ELM_GENLIST_DATA_GET(obj, sd);
5508    Elm_Gen_Item *it;
5509
5510    if (sd->state)
5511      {
5512         eina_inlist_sorted_state_free(sd->state);
5513         sd->state = NULL;
5514      }
5515
5516 #if GENLIST_FX_SUPPORT
5517    if (sd->fx_mode)
5518      {
5519         _elm_genlist_fx_clear(obj, EINA_TRUE);
5520         sd->genlist_clearing = EINA_TRUE;
5521         sd->rendered = EINA_FALSE;
5522      }
5523 #endif
5524 #if GENLIST_PINCH_ZOOM_SUPPORT
5525    sd->pinch_zoom_h = 0;
5526    sd->realized_top_item = NULL;
5527    sd->pinch_zoom_mode = ELM_GEN_PINCH_ZOOM_NONE;
5528 #endif
5529
5530    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5531
5532    // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE
5533    // because sd->items can be modified inside elm_widget_item_del()
5534    while (sd->items)
5535      {
5536         it = EINA_INLIST_CONTAINER_GET(sd->items->last, Elm_Gen_Item);
5537         it->item->nocache_once = EINA_TRUE;
5538         elm_widget_item_del(it);
5539      }
5540    sd->items = NULL;
5541    sd->blocks = NULL;
5542    _item_cache_all_free(sd);
5543
5544    sd->pan_changed = EINA_TRUE;
5545    if (sd->selected) sd->selected = eina_list_free(sd->selected);
5546    sd->selected = NULL;
5547
5548    sd->anchor_item = NULL;
5549    if (sd->multi_timer)
5550      {
5551         ecore_timer_del(sd->multi_timer);
5552         sd->multi_timer = NULL;
5553      }
5554    if (sd->update_job)
5555      {
5556         ecore_job_del(sd->update_job);
5557         sd->update_job = NULL;
5558      }
5559    if (sd->calc_job)
5560      {
5561         ecore_job_del(sd->calc_job);
5562         sd->calc_job = NULL;
5563      }
5564    if (sd->queue_idle_enterer)
5565      {
5566         ecore_idle_enterer_del(sd->queue_idle_enterer);
5567         sd->queue_idle_enterer = NULL;
5568      }
5569    if (sd->must_recalc_idler)
5570      {
5571         ecore_idler_del(sd->must_recalc_idler);
5572         sd->must_recalc_idler = NULL;
5573      }
5574    if (sd->queue) sd->queue = eina_list_free(sd->queue);
5575    if (sd->reorder_move_animator)
5576      {
5577         ecore_animator_del(sd->reorder_move_animator);
5578         sd->reorder_move_animator = NULL;
5579      }
5580    sd->show_item = NULL;
5581    sd->reorder_old_pan_y = 0;
5582
5583    sd->pan_x = 0;
5584    sd->pan_y = 0;
5585    sd->minw = 0;
5586    sd->minh = 0;
5587
5588    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
5589    sd->alpha_bg = NULL;
5590
5591    if (sd->pan_obj)
5592      {
5593         evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
5594         evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
5595      }
5596    elm_layout_sizing_eval(ELM_WIDGET_DATA(sd)->obj);
5597    sd->s_iface->content_region_show(obj, 0, 0, 0, 0);
5598
5599 #if GENLIST_FX_SUPPORT
5600    sd->genlist_clearing = EINA_FALSE;
5601 #endif
5602    //evas_event_thaw(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5603    //evas_event_thaw_eval(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5604 }
5605
5606 EAPI void
5607 elm_genlist_multi_select_set(Evas_Object *obj,
5608                              Eina_Bool multi)
5609 {
5610    ELM_GENLIST_CHECK(obj);
5611    ELM_GENLIST_DATA_GET(obj, sd);
5612
5613    sd->multi = !!multi;
5614 }
5615
5616 EAPI Eina_Bool
5617 elm_genlist_multi_select_get(const Evas_Object *obj)
5618 {
5619    ELM_GENLIST_CHECK(obj) EINA_FALSE;
5620    ELM_GENLIST_DATA_GET(obj, sd);
5621
5622    return sd->multi;
5623 }
5624
5625 EAPI Elm_Object_Item *
5626 elm_genlist_selected_item_get(const Evas_Object *obj)
5627 {
5628    ELM_GENLIST_CHECK(obj) NULL;
5629    ELM_GENLIST_DATA_GET(obj, sd);
5630
5631    if (sd->selected)
5632      return sd->selected->data;
5633
5634    return NULL;
5635 }
5636
5637 EAPI Eina_List *
5638 elm_genlist_selected_items_get(const Evas_Object *obj)
5639 {
5640    ELM_GENLIST_CHECK(obj) NULL;
5641    ELM_GENLIST_DATA_GET(obj, sd);
5642
5643    return sd->selected;
5644 }
5645
5646 EAPI Eina_List *
5647 elm_genlist_realized_items_get(const Evas_Object *obj)
5648 {
5649    Item_Block *itb;
5650    Eina_List *list = NULL;
5651    Eina_Bool done = EINA_FALSE;
5652
5653    ELM_GENLIST_CHECK(obj) NULL;
5654    ELM_GENLIST_DATA_GET(obj, sd);
5655
5656    EINA_INLIST_FOREACH(sd->blocks, itb)
5657      {
5658         if (itb->realized)
5659           {
5660              Eina_List *l;
5661              Elm_Gen_Item *it;
5662
5663              done = EINA_TRUE;
5664              EINA_LIST_FOREACH(itb->items, l, it)
5665                {
5666                   if (it->realized) list = eina_list_append(list, it);
5667                }
5668           }
5669         else
5670           {
5671              if (done) break;
5672           }
5673      }
5674    return list;
5675 }
5676
5677 EAPI Elm_Object_Item *
5678 elm_genlist_at_xy_item_get(const Evas_Object *obj,
5679                            Evas_Coord x,
5680                            Evas_Coord y,
5681                            int *posret)
5682 {
5683    Evas_Coord ox, oy, ow, oh;
5684    Evas_Coord lasty;
5685    Item_Block *itb;
5686
5687    ELM_GENLIST_CHECK(obj) NULL;
5688    ELM_GENLIST_DATA_GET(obj, sd);
5689
5690    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
5691    lasty = oy;
5692    EINA_INLIST_FOREACH(sd->blocks, itb)
5693      {
5694         Eina_List *l;
5695         Elm_Gen_Item *it;
5696
5697         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->sd->pan_x,
5698                                  oy + itb->y - itb->sd->pan_y,
5699                                  itb->w, itb->h, x, y, 1, 1))
5700           continue;
5701         EINA_LIST_FOREACH(itb->items, l, it)
5702           {
5703              Evas_Coord itx, ity;
5704
5705              itx = ox + itb->x + it->x - itb->sd->pan_x;
5706              ity = oy + itb->y + it->y - itb->sd->pan_y;
5707              if (ELM_RECTS_INTERSECT
5708                    (itx, ity, it->item->w, it->item->h, x, y, 1, 1))
5709                {
5710                   if (posret)
5711                     {
5712                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
5713                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
5714                          *posret = 1;
5715                        else *posret = 0;
5716                     }
5717
5718                   return (Elm_Object_Item *)it;
5719                }
5720              lasty = ity + it->item->h;
5721           }
5722      }
5723    if (posret)
5724      {
5725         if (y > lasty) *posret = 1;
5726         else *posret = -1;
5727      }
5728
5729    return NULL;
5730 }
5731
5732 EAPI Elm_Object_Item *
5733 elm_genlist_first_item_get(const Evas_Object *obj)
5734 {
5735    Elm_Gen_Item *tit, *it = NULL;
5736
5737    ELM_GENLIST_CHECK(obj) NULL;
5738    ELM_GENLIST_DATA_GET(obj, sd);
5739
5740    EINA_INLIST_REVERSE_FOREACH(sd->items, tit) it = tit;
5741
5742    return (Elm_Object_Item *)it;
5743 }
5744
5745 EAPI Elm_Object_Item *
5746 elm_genlist_last_item_get(const Evas_Object *obj)
5747 {
5748    Elm_Gen_Item *it;
5749
5750    ELM_GENLIST_CHECK(obj) NULL;
5751    ELM_GENLIST_DATA_GET(obj, sd);
5752    if (!sd->items) return NULL;
5753
5754    it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
5755    return (Elm_Object_Item *)it;
5756 }
5757
5758 EAPI Elm_Object_Item *
5759 elm_genlist_item_next_get(const Elm_Object_Item *item)
5760 {
5761    Elm_Gen_Item *it;
5762
5763    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
5764
5765    it = (Elm_Gen_Item *)item;
5766    while (it)
5767      {
5768         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5769         if (it) break;
5770      }
5771
5772    return (Elm_Object_Item *)it;
5773 }
5774
5775 EAPI Elm_Object_Item *
5776 elm_genlist_item_prev_get(const Elm_Object_Item *item)
5777 {
5778    Elm_Gen_Item *it;
5779
5780    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
5781
5782    it = (Elm_Gen_Item *)item;
5783    while (it)
5784      {
5785         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5786         if (it) break;
5787      }
5788
5789    return (Elm_Object_Item *)it;
5790 }
5791
5792 EAPI Elm_Object_Item *
5793 elm_genlist_item_parent_get(const Elm_Object_Item *it)
5794 {
5795    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
5796
5797    return (Elm_Object_Item *)((Elm_Gen_Item *)it)->parent;
5798 }
5799
5800 EAPI void
5801 elm_genlist_item_subitems_clear(Elm_Object_Item *item)
5802 {
5803    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5804
5805    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5806    _item_sub_items_clear(it);
5807 }
5808
5809 EAPI void
5810 elm_genlist_item_selected_set(Elm_Object_Item *item,
5811                               Eina_Bool selected)
5812 {
5813    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5814    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5815
5816    if (elm_widget_item_disabled_get(it)) return;
5817    selected = !!selected;
5818    if (it->selected == selected) return;
5819
5820    _item_select_unselect(it, selected);
5821 }
5822
5823 EAPI Eina_Bool
5824 elm_genlist_item_selected_get(const Elm_Object_Item *it)
5825 {
5826    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5827
5828    return ((Elm_Gen_Item *)it)->selected;
5829 }
5830
5831 static Elm_Gen_Item *
5832 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
5833 {
5834    Elm_Gen_Item *it2;
5835
5836    if (it->item->expanded)
5837      {
5838         it2 = (Elm_Gen_Item *)elm_genlist_item_next_get((Elm_Object_Item *)it);
5839      }
5840    else
5841      {
5842         it2 = (Elm_Gen_Item *)elm_genlist_item_next_get((Elm_Object_Item *)it);
5843         while (it2)
5844           {
5845              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
5846              it2 = (Elm_Gen_Item *)
5847                elm_genlist_item_next_get((Elm_Object_Item *)it2);
5848           }
5849      }
5850    return it2;
5851 }
5852
5853 static Evas_Object *
5854 _tray_alpha_bg_create(const Evas_Object *obj)
5855 {
5856    Evas_Object *bg = NULL;
5857    Evas_Coord ox, oy, ow, oh;
5858
5859    ELM_GENLIST_CHECK(obj) NULL;
5860    ELM_GENLIST_DATA_GET(obj, sd);
5861
5862    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
5863    bg = evas_object_rectangle_add
5864        (evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
5865    evas_object_color_set(bg, 0, 0, 0, 0);
5866    evas_object_resize(bg, ow, oh);
5867    evas_object_move(bg, ox, oy);
5868
5869    return bg;
5870 }
5871
5872 EAPI void
5873 elm_genlist_item_expanded_set(Elm_Object_Item *item,
5874                               Eina_Bool expanded)
5875 {
5876    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5877
5878    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5879
5880    expanded = !!expanded;
5881    if (it->item->expanded == expanded) return;
5882    if (it->item->type != ELM_GENLIST_ITEM_TREE) return;
5883    it->item->expanded = expanded;
5884    GL_IT(it)->wsd->expanded_item = it;
5885    GL_IT(it)->wsd->expanded_next_item =
5886      _elm_genlist_expanded_next_item_get(it);
5887
5888    if (it->item->expanded)
5889      {
5890         if (it->realized)
5891           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
5892         evas_object_smart_callback_call(WIDGET(it), SIG_EXPANDED, it);
5893         GL_IT(it)->wsd->auto_scroll_enabled = EINA_TRUE;
5894      }
5895    else
5896      {
5897         if (it->realized)
5898           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
5899         evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACTED, it);
5900         GL_IT(it)->wsd->auto_scroll_enabled = EINA_FALSE;
5901      }
5902 }
5903
5904 EAPI Eina_Bool
5905 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
5906 {
5907    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5908
5909    return ((Elm_Gen_Item *)it)->item->expanded;
5910 }
5911
5912 EAPI int
5913 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
5914 {
5915    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, 0);
5916
5917    return ((Elm_Gen_Item *)it)->item->expanded_depth;
5918 }
5919
5920 static Eina_Bool
5921 _elm_genlist_item_coordinates_calc(Elm_Object_Item *item,
5922                                    Elm_Genlist_Item_Scrollto_Type type,
5923                                    Eina_Bool bring_in,
5924                                    Evas_Coord *x,
5925                                    Evas_Coord *y,
5926                                    Evas_Coord *w,
5927                                    Evas_Coord *h)
5928 {
5929    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5930    Evas_Coord gith = 0;
5931
5932    if (!((GL_IT(it)->wsd->homogeneous) &&
5933          (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)))
5934      {
5935         if ((it->item->queued) || (!it->item->mincalcd))
5936           {
5937              GL_IT(it)->wsd->show_item = it;
5938              GL_IT(it)->wsd->bring_in = bring_in;
5939              GL_IT(it)->wsd->scroll_to_type = type;
5940              it->item->show_me = EINA_TRUE;
5941              return EINA_FALSE;
5942           }
5943      }
5944    if (GL_IT(it)->wsd->show_item)
5945      {
5946         GL_IT(it)->wsd->show_item->item->show_me = EINA_FALSE;
5947         GL_IT(it)->wsd->show_item = NULL;
5948      }
5949
5950    evas_object_geometry_get(GL_IT(it)->wsd->pan_obj, NULL, NULL, w, h);
5951    switch (type)
5952      {
5953       case ELM_GENLIST_ITEM_SCROLLTO_IN:
5954         if ((it->item->group_item) &&
5955             (GL_IT(it)->wsd->pan_y > (it->y + it->item->block->y)))
5956           gith = it->item->group_item->item->h;
5957         *h = it->item->h;
5958         *y = it->y + it->item->block->y - gith;
5959         break;
5960
5961       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
5962         if (it->item->group_item) gith = it->item->group_item->item->h;
5963         *y = it->y + it->item->block->y - gith;
5964         break;
5965
5966       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
5967         *y = it->y + it->item->block->y - (*h / 2) + (it->item->h / 2);
5968         break;
5969
5970       default:
5971         return EINA_FALSE;
5972      }
5973
5974    *x = it->x + it->item->block->x;
5975    *w = it->item->block->w;
5976
5977    return EINA_TRUE;
5978 }
5979
5980 EAPI void
5981 elm_genlist_item_promote(Elm_Object_Item *item)
5982 {
5983    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5984    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5985    _item_move_before
5986      (it, (Elm_Gen_Item *)elm_genlist_first_item_get(WIDGET(it)));
5987 }
5988
5989 EAPI void
5990 elm_genlist_item_demote(Elm_Object_Item *item)
5991 {
5992    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
5993    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
5994    _item_move_after(it, (Elm_Gen_Item *)elm_genlist_last_item_get(WIDGET(it)));
5995 }
5996
5997 EAPI void
5998 elm_genlist_item_show(Elm_Object_Item *item,
5999                       Elm_Genlist_Item_Scrollto_Type type)
6000 {
6001    Evas_Coord x, y, w, h;
6002    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6003    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6004
6005    if (_elm_genlist_item_coordinates_calc
6006          (item, type, EINA_FALSE, &x, &y, &w, &h))
6007      GL_IT(it)->wsd->s_iface->content_region_show(WIDGET(item), x, y, w, h);
6008 }
6009
6010 EAPI void
6011 elm_genlist_item_bring_in(Elm_Object_Item *item,
6012                           Elm_Genlist_Item_Scrollto_Type type)
6013 {
6014    Evas_Coord x, y, w, h;
6015    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6016    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6017
6018    if (_elm_genlist_item_coordinates_calc
6019          (item, type, EINA_TRUE, &x, &y, &w, &h))
6020      GL_IT(it)->wsd->s_iface->region_bring_in(WIDGET(item), x, y, w, h);
6021 }
6022
6023 EAPI void
6024 elm_genlist_item_all_contents_unset(Elm_Object_Item *item,
6025                                     Eina_List **l)
6026 {
6027    Evas_Object *content;
6028
6029    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6030    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6031
6032    EINA_LIST_FREE (it->content_objs, content)
6033      {
6034         evas_object_smart_member_del(content);
6035         evas_object_hide(content);
6036         if (l) *l = eina_list_append(*l, content);
6037      }
6038 }
6039
6040 EAPI void
6041 elm_genlist_item_update(Elm_Object_Item *item)
6042 {
6043    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6044    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6045
6046    if (!it->item->block) return;
6047    it->item->mincalcd = EINA_FALSE;
6048    it->item->updateme = EINA_TRUE;
6049    it->item->block->updateme = EINA_TRUE;
6050 #if GENLIST_ENTRY_SUPPORT
6051    it->item->unrealize_disabled = EINA_FALSE;
6052 #endif
6053
6054 #if GENLIST_FX_SUPPORT
6055      _elm_genlist_fx_clear(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj, EINA_FALSE);
6056 #endif
6057
6058    if (GL_IT(it)->wsd->update_job) ecore_job_del(GL_IT(it)->wsd->update_job);
6059    GL_IT(it)->wsd->update_job = ecore_job_add(_update_job, GL_IT(it)->wsd);
6060 }
6061
6062 EAPI void
6063 elm_genlist_item_fields_update(Elm_Object_Item *item,
6064                                const char *parts,
6065                                Elm_Genlist_Item_Field_Type itf)
6066 {
6067    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6068    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6069
6070    if (!it->item->block) return;
6071
6072 #if GENLIST_ENTRY_SUPPORT
6073    it->item->unrealize_disabled = EINA_FALSE;
6074 #endif
6075    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
6076      {
6077         _item_text_realize(it, VIEW(it), &it->texts, parts);
6078      }
6079    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
6080      {
6081         it->content_objs = _item_content_unrealize(it, VIEW(it),
6082                                                    &it->contents, parts);
6083         it->content_objs = _item_content_realize(it, VIEW(it),
6084                                                  &it->contents, parts);
6085
6086         if (it->flipped)
6087           {
6088              it->item->flip_content_objs =
6089                _item_mode_content_unrealize(it, VIEW(it),
6090                                             &it->item->flip_contents, parts,
6091                                             &it->item->flip_content_objs);
6092              it->item->flip_content_objs =
6093                _item_mode_content_realize(it, VIEW(it),
6094                                           &it->item->flip_contents, parts,
6095                                           &it->item->flip_content_objs);
6096           }
6097         if (it->item->deco_it_view)
6098           {
6099              it->item->deco_it_content_objs =
6100                _item_mode_content_unrealize(it, it->item->deco_it_view,
6101                                             &it->item->deco_it_contents, parts,
6102                                             &it->item->deco_it_content_objs);
6103              it->item->deco_it_content_objs =
6104                _item_mode_content_realize(it, it->item->deco_it_view,
6105                                           &it->item->deco_it_contents, parts,
6106                                           &it->item->deco_it_content_objs);
6107           }
6108         if (GL_IT(it)->wsd->decorate_all_mode)
6109           {
6110              it->item->deco_all_content_objs =
6111                _item_mode_content_unrealize
6112                  (it, it->deco_all_view, &it->item->deco_all_contents, parts,
6113                  &it->item->deco_all_content_objs);
6114              it->item->deco_all_content_objs =
6115                _item_mode_content_realize(it, it->deco_all_view,
6116                                           &it->item->deco_all_contents, parts,
6117                                           &it->item->deco_all_content_objs);
6118           }
6119      }
6120
6121    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
6122      _item_state_realize(it, VIEW(it), &it->states, parts);
6123 }
6124
6125 EAPI void
6126 elm_genlist_item_item_class_update(Elm_Object_Item *item,
6127                                    const Elm_Genlist_Item_Class *itc)
6128 {
6129    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6130    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6131
6132    if (!it->item->block) return;
6133    EINA_SAFETY_ON_NULL_RETURN(itc);
6134    it->itc = itc;
6135    it->item->nocache_once = EINA_TRUE;
6136
6137    elm_widget_stringlist_free(it->texts);
6138    it->texts = NULL;
6139    elm_widget_stringlist_free(it->contents);
6140    it->contents = NULL;
6141    elm_widget_stringlist_free(it->states);
6142    it->states = NULL;
6143
6144    if (it->flipped)
6145      {
6146         elm_widget_stringlist_free(it->item->flip_contents);
6147         it->item->flip_contents = NULL;
6148      }
6149    if (it->item->deco_it_view)
6150      {
6151         elm_widget_stringlist_free(it->item->deco_it_texts);
6152         it->item->deco_it_texts = NULL;
6153         elm_widget_stringlist_free(it->item->deco_it_contents);
6154         it->item->deco_it_contents = NULL;
6155      }
6156    if (GL_IT(it)->wsd->decorate_all_mode)
6157      {
6158         elm_widget_stringlist_free(it->item->deco_all_texts);
6159         it->item->deco_all_texts = NULL;
6160         elm_widget_stringlist_free(it->item->deco_all_contents);
6161         it->item->deco_all_contents = NULL;
6162      }
6163
6164    elm_genlist_item_update(item);
6165 }
6166
6167 EAPI const Elm_Genlist_Item_Class *
6168 elm_genlist_item_item_class_get(const Elm_Object_Item *item)
6169 {
6170    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
6171    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6172    return it->itc;
6173 }
6174
6175 static Evas_Object *
6176 _elm_genlist_item_label_create(void *data,
6177                                Evas_Object *obj __UNUSED__,
6178                                Evas_Object *tooltip,
6179                                void *it __UNUSED__)
6180 {
6181    Evas_Object *label = elm_label_add(tooltip);
6182
6183    if (!label)
6184      return NULL;
6185
6186    elm_object_style_set(label, "tooltip");
6187    elm_object_text_set(label, data);
6188
6189    return label;
6190 }
6191
6192 static void
6193 _elm_genlist_item_label_del_cb(void *data,
6194                                Evas_Object *obj __UNUSED__,
6195                                void *event_info __UNUSED__)
6196 {
6197    eina_stringshare_del(data);
6198 }
6199
6200 EAPI void
6201 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
6202                                   const char *text)
6203 {
6204    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
6205
6206    text = eina_stringshare_add(text);
6207    elm_genlist_item_tooltip_content_cb_set
6208      (it, _elm_genlist_item_label_create, text,
6209      _elm_genlist_item_label_del_cb);
6210 }
6211
6212 EAPI void
6213 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item *item,
6214                                         Elm_Tooltip_Item_Content_Cb func,
6215                                         const void *data,
6216                                         Evas_Smart_Cb del_cb)
6217 {
6218    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6219
6220    ELM_GENLIST_ITEM_CHECK_OR_GOTO(item, error);
6221
6222    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
6223      return;
6224
6225    if (it->tooltip.del_cb)
6226      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6227
6228    it->tooltip.content_cb = func;
6229    it->tooltip.data = data;
6230    it->tooltip.del_cb = del_cb;
6231
6232    if (VIEW(it))
6233      {
6234         elm_widget_item_tooltip_content_cb_set
6235           (it, it->tooltip.content_cb, it->tooltip.data, NULL);
6236         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
6237         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
6238      }
6239
6240    return;
6241
6242 error:
6243    if (del_cb) del_cb((void *)data, NULL, NULL);
6244 }
6245
6246 EAPI void
6247 elm_genlist_item_tooltip_unset(Elm_Object_Item *item)
6248 {
6249    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6250
6251    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6252
6253    if ((VIEW(it)) && (it->tooltip.content_cb))
6254      elm_widget_item_tooltip_unset(it);
6255
6256    if (it->tooltip.del_cb)
6257      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
6258    it->tooltip.del_cb = NULL;
6259    it->tooltip.content_cb = NULL;
6260    it->tooltip.data = NULL;
6261    it->tooltip.free_size = EINA_FALSE;
6262    if (it->tooltip.style)
6263      elm_genlist_item_tooltip_style_set(item, NULL);
6264 }
6265
6266 EAPI void
6267 elm_genlist_item_tooltip_style_set(Elm_Object_Item *item,
6268                                    const char *style)
6269 {
6270    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6271
6272    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6273
6274    eina_stringshare_replace(&it->tooltip.style, style);
6275    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
6276 }
6277
6278 EAPI const char *
6279 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
6280 {
6281    return elm_object_item_tooltip_style_get(it);
6282 }
6283
6284 EAPI Eina_Bool
6285 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *item,
6286                                          Eina_Bool disable)
6287 {
6288    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6289
6290    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
6291
6292    it->tooltip.free_size = disable;
6293    if (VIEW(it)) return elm_widget_item_tooltip_window_mode_set(it, disable);
6294
6295    return EINA_TRUE;
6296 }
6297
6298 EAPI Eina_Bool
6299 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
6300 {
6301    return elm_object_tooltip_window_mode_get(VIEW(it));
6302 }
6303
6304 EAPI void
6305 elm_genlist_item_cursor_set(Elm_Object_Item *item,
6306                             const char *cursor)
6307 {
6308    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6309
6310    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6311    eina_stringshare_replace(&it->mouse_cursor, cursor);
6312    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
6313 }
6314
6315 EAPI const char *
6316 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
6317 {
6318    return elm_widget_item_cursor_get(it);
6319 }
6320
6321 EAPI void
6322 elm_genlist_item_cursor_unset(Elm_Object_Item *item)
6323 {
6324    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6325
6326    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6327
6328    if (!it->mouse_cursor) return;
6329
6330    if (VIEW(it)) elm_widget_item_cursor_unset(it);
6331
6332    eina_stringshare_del(it->mouse_cursor);
6333    it->mouse_cursor = NULL;
6334 }
6335
6336 EAPI void
6337 elm_genlist_item_cursor_style_set(Elm_Object_Item *it,
6338                                   const char *style)
6339 {
6340    elm_widget_item_cursor_style_set(it, style);
6341 }
6342
6343 EAPI const char *
6344 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
6345 {
6346    return elm_widget_item_cursor_style_get(it);
6347 }
6348
6349 EAPI void
6350 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
6351                                         Eina_Bool engine_only)
6352 {
6353    elm_widget_item_cursor_engine_only_set(it, engine_only);
6354 }
6355
6356 EAPI Eina_Bool
6357 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
6358 {
6359    return elm_widget_item_cursor_engine_only_get(it);
6360 }
6361
6362 EAPI int
6363 elm_genlist_item_index_get(const Elm_Object_Item *item)
6364 {
6365    int cnt = 0;
6366    Elm_Gen_Item *tmp;
6367    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6368
6369    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, -1);
6370
6371    EINA_INLIST_FOREACH(GL_IT(it)->wsd->items, tmp)
6372      {
6373         if (tmp == it) break;
6374         cnt++;
6375      }
6376    return cnt;
6377 }
6378
6379 EAPI void
6380 elm_genlist_mode_set(Evas_Object *obj,
6381                      Elm_List_Mode mode)
6382 {
6383    ELM_GENLIST_CHECK(obj);
6384    ELM_GENLIST_DATA_GET(obj, sd);
6385
6386    if (sd->mode == mode) return;
6387    sd->mode = mode;
6388    elm_layout_sizing_eval(obj);
6389 }
6390
6391 EAPI Elm_List_Mode
6392 elm_genlist_mode_get(const Evas_Object *obj)
6393 {
6394    ELM_GENLIST_CHECK(obj) ELM_LIST_LAST;
6395    ELM_GENLIST_DATA_GET(obj, sd);
6396
6397    return sd->mode;
6398 }
6399
6400 EAPI void
6401 elm_genlist_bounce_set(Evas_Object *obj,
6402                        Eina_Bool h_bounce,
6403                        Eina_Bool v_bounce)
6404 {
6405    ELM_GENLIST_CHECK(obj);
6406    ELM_GENLIST_DATA_GET(obj, sd);
6407
6408    sd->h_bounce = !!h_bounce;
6409    sd->v_bounce = !!v_bounce;
6410    sd->s_iface->bounce_allow_set(obj, sd->h_bounce, sd->v_bounce);
6411 }
6412
6413 EAPI void
6414 elm_genlist_bounce_get(const Evas_Object *obj,
6415                        Eina_Bool *h_bounce,
6416                        Eina_Bool *v_bounce)
6417 {
6418    ELM_GENLIST_CHECK(obj);
6419    ELM_GENLIST_DATA_GET(obj, sd);
6420
6421    if (h_bounce) *h_bounce = sd->h_bounce;
6422    if (v_bounce) *v_bounce = sd->v_bounce;
6423 }
6424
6425 EAPI void
6426 elm_genlist_homogeneous_set(Evas_Object *obj,
6427                             Eina_Bool homogeneous)
6428 {
6429    ELM_GENLIST_CHECK(obj);
6430    ELM_GENLIST_DATA_GET(obj, sd);
6431
6432    sd->homogeneous = !!homogeneous;
6433 }
6434
6435 EAPI Eina_Bool
6436 elm_genlist_homogeneous_get(const Evas_Object *obj)
6437 {
6438    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6439    ELM_GENLIST_DATA_GET(obj, sd);
6440
6441    return sd->homogeneous;
6442 }
6443
6444 EAPI void
6445 elm_genlist_block_count_set(Evas_Object *obj,
6446                             int count)
6447 {
6448    ELM_GENLIST_CHECK(obj);
6449    ELM_GENLIST_DATA_GET(obj, sd);
6450    EINA_SAFETY_ON_TRUE_RETURN(count < 1);
6451
6452    sd->max_items_per_block = count;
6453    sd->item_cache_max = sd->max_items_per_block * 2;
6454    _item_cache_all_free(sd);
6455 }
6456
6457 EAPI int
6458 elm_genlist_block_count_get(const Evas_Object *obj)
6459 {
6460    ELM_GENLIST_CHECK(obj) 0;
6461    ELM_GENLIST_DATA_GET(obj, sd);
6462
6463    return sd->max_items_per_block;
6464 }
6465
6466 EAPI void
6467 elm_genlist_longpress_timeout_set(Evas_Object *obj,
6468                                   double timeout)
6469 {
6470    ELM_GENLIST_CHECK(obj);
6471    ELM_GENLIST_DATA_GET(obj, sd);
6472
6473    sd->longpress_timeout = timeout;
6474 }
6475
6476 EAPI double
6477 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
6478 {
6479    ELM_GENLIST_CHECK(obj) 0;
6480    ELM_GENLIST_DATA_GET(obj, sd);
6481
6482    return sd->longpress_timeout;
6483 }
6484
6485 EAPI void
6486 elm_genlist_scroller_policy_set(Evas_Object *obj,
6487                                 Elm_Scroller_Policy policy_h,
6488                                 Elm_Scroller_Policy policy_v)
6489 {
6490    ELM_GENLIST_CHECK(obj);
6491    ELM_GENLIST_DATA_GET(obj, sd);
6492
6493    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
6494        (policy_v >= ELM_SCROLLER_POLICY_LAST))
6495      return;
6496
6497    sd->s_iface->policy_set(obj, policy_h, policy_v);
6498 }
6499
6500 EAPI void
6501 elm_genlist_scroller_policy_get(const Evas_Object *obj,
6502                                 Elm_Scroller_Policy *policy_h,
6503                                 Elm_Scroller_Policy *policy_v)
6504 {
6505    Elm_Scroller_Policy s_policy_h, s_policy_v;
6506
6507    ELM_GENLIST_CHECK(obj);
6508    ELM_GENLIST_DATA_GET(obj, sd);
6509
6510    sd->s_iface->policy_get(obj, &s_policy_h, &s_policy_v);
6511    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
6512    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
6513 }
6514
6515 EAPI void
6516 elm_genlist_realized_items_update(Evas_Object *obj)
6517 {
6518    Eina_List *list, *l;
6519    Elm_Object_Item *it;
6520
6521    ELM_GENLIST_CHECK(obj);
6522
6523    list = elm_genlist_realized_items_get(obj);
6524    EINA_LIST_FOREACH(list, l, it)
6525      elm_genlist_item_update(it);
6526 }
6527
6528 EAPI void
6529 elm_genlist_item_decorate_mode_set(Elm_Object_Item *item,
6530                                    const char *decorate_it_type,
6531                                    Eina_Bool decorate_it_set)
6532 {
6533    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6534    Elm_Genlist_Smart_Data *sd;
6535
6536    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6537    sd = GL_IT(it)->wsd;
6538
6539    if (elm_widget_item_disabled_get(it)) return;
6540    if (!decorate_it_type) return;
6541    if (sd->decorate_all_mode) return;
6542
6543    if ((sd->mode_item == it) &&
6544        (!strcmp(decorate_it_type, sd->decorate_it_type)) &&
6545        (decorate_it_set))
6546      return;
6547    if (!it->itc->decorate_item_style) return;
6548    it->decorate_it_set = decorate_it_set;
6549
6550    _item_unselect(it);
6551    if (((sd->decorate_it_type)
6552         && (strcmp(decorate_it_type, sd->decorate_it_type))) ||
6553        (decorate_it_set) || ((it == sd->mode_item) && (!decorate_it_set)))
6554      _decorate_item_unset(sd);
6555
6556    eina_stringshare_replace(&sd->decorate_it_type, decorate_it_type);
6557    if (decorate_it_set) _decorate_item_set(it);
6558 }
6559
6560 EAPI const char *
6561 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *item)
6562 {
6563    Elm_Gen_Item *i = (Elm_Gen_Item *)item;
6564
6565    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
6566    return GL_IT(i)->wsd->decorate_it_type;
6567 }
6568
6569 EAPI Elm_Object_Item *
6570 elm_genlist_decorated_item_get(const Evas_Object *obj)
6571 {
6572    ELM_GENLIST_CHECK(obj) NULL;
6573    ELM_GENLIST_DATA_GET(obj, sd);
6574
6575    return (Elm_Object_Item *)sd->mode_item;
6576 }
6577
6578 EAPI Eina_Bool
6579 elm_genlist_decorate_mode_get(const Evas_Object *obj)
6580 {
6581    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6582    ELM_GENLIST_DATA_GET(obj, sd);
6583
6584    return sd->decorate_all_mode;
6585 }
6586
6587 EAPI void
6588 elm_genlist_decorate_mode_set(Evas_Object *obj,
6589                               Eina_Bool decorated)
6590 {
6591    Elm_Gen_Item *it;
6592    Eina_List *list, *l;
6593
6594    ELM_GENLIST_CHECK(obj);
6595    ELM_GENLIST_DATA_GET(obj, sd);
6596
6597    decorated = !!decorated;
6598    if (sd->decorate_all_mode == decorated) return;
6599    // decorate_all_mode should be set first
6600    // because content_get func. will be called after this
6601    // and user can check whether deocrate_all_mode is enabeld.
6602    sd->decorate_all_mode = decorated;
6603
6604    list = elm_genlist_realized_items_get(obj);
6605    if (!sd->decorate_all_mode)
6606      {
6607         EINA_LIST_FOREACH(list, l, it)
6608           {
6609              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6610                _decorate_all_item_unrealize(it);
6611           }
6612         _item_cache_all_free(sd);
6613      }
6614    else
6615      {
6616         EINA_LIST_FOREACH(list, l, it)
6617           {
6618              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6619                {
6620                   if (it->itc->decorate_all_item_style)
6621                     _decorate_all_item_realize(it, EINA_TRUE);
6622                }
6623           }
6624      }
6625 #if GENLIST_FX_SUPPORT
6626      _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
6627 #endif
6628    if (sd->calc_job) ecore_job_del(sd->calc_job);
6629    sd->calc_job = ecore_job_add(_calc_job, sd);
6630 }
6631
6632 EAPI void
6633 elm_genlist_reorder_mode_set(Evas_Object *obj,
6634                              Eina_Bool reorder_mode)
6635 {
6636 #if 1 // FIXME: difference from upstream
6637    Eina_List *list, *l;
6638    Elm_Gen_Item *it;
6639 #endif
6640    ELM_GENLIST_CHECK(obj);
6641    ELM_GENLIST_DATA_GET(obj, sd);
6642
6643    if (sd->reorder_mode == !!reorder_mode) return;
6644    sd->reorder_mode = !!reorder_mode;
6645 #if 1 // FIXME: difference from upstream
6646    list = elm_genlist_realized_items_get(obj);
6647    EINA_LIST_FOREACH(list, l, it)
6648      {
6649         if (it->item->type != ELM_GENLIST_ITEM_GROUP)
6650           {
6651              if (sd->reorder_mode)
6652                edje_object_signal_emit
6653                  (VIEW(it), "elm,state,reorder,mode_set", "elm");
6654              else
6655                edje_object_signal_emit
6656                  (VIEW(it), "elm,state,reorder,mode_unset", "elm");
6657           }
6658         if (sd->decorate_all_mode)
6659           {
6660              if (sd->reorder_mode)
6661                edje_object_signal_emit
6662                   (it->deco_all_view, "elm,state,reorder,mode_set", "elm");
6663              else
6664                edje_object_signal_emit
6665                   (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
6666           }
6667      }
6668    eina_list_free(list);
6669 #endif
6670 }
6671
6672 EAPI Eina_Bool
6673 elm_genlist_reorder_mode_get(const Evas_Object *obj)
6674 {
6675    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6676    ELM_GENLIST_DATA_GET(obj, sd);
6677
6678    return sd->reorder_mode;
6679 }
6680
6681 EAPI Elm_Genlist_Item_Type
6682 elm_genlist_item_type_get(const Elm_Object_Item *item)
6683 {
6684    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6685
6686    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, ELM_GENLIST_ITEM_MAX);
6687
6688    return it->item->type;
6689 }
6690
6691 EAPI Elm_Genlist_Item_Class *
6692 elm_genlist_item_class_new(void)
6693 {
6694    Elm_Genlist_Item_Class *itc = ELM_NEW(Elm_Genlist_Item_Class);
6695    EINA_SAFETY_ON_NULL_RETURN_VAL(itc, NULL);
6696
6697    itc->version = CLASS_ALLOCATED;
6698    itc->refcount = 1;
6699    itc->delete_me = EINA_FALSE;
6700
6701    return itc;
6702 }
6703
6704 EAPI void
6705 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
6706 {
6707    if (itc && (itc->version == CLASS_ALLOCATED))
6708      {
6709         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
6710         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
6711         else
6712           {
6713              itc->version = 0;
6714              free(itc);
6715           }
6716      }
6717 }
6718
6719 EAPI void
6720 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
6721 {
6722    if (itc && (itc->version == CLASS_ALLOCATED))
6723      {
6724         itc->refcount++;
6725         if (itc->refcount == 0) itc->refcount--;
6726      }
6727 }
6728
6729 EAPI void
6730 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
6731 {
6732    if (itc && (itc->version == CLASS_ALLOCATED))
6733      {
6734         if (itc->refcount > 0) itc->refcount--;
6735         if (itc->delete_me && (!itc->refcount))
6736           elm_genlist_item_class_free(itc);
6737      }
6738 }
6739
6740 EAPI void
6741 elm_genlist_item_flip_set(Elm_Object_Item *item,
6742                           Eina_Bool flip)
6743 {
6744    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6745    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6746    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
6747
6748    flip = !!flip;
6749    if (it->flipped == flip) return;
6750
6751    it->item->unrealize_disabled = EINA_FALSE;
6752    if (flip)
6753      {
6754         _item_unselect(it);
6755         _item_unrealize(it, EINA_FALSE);
6756         it->flipped = EINA_TRUE;
6757         it->item->nocache = EINA_TRUE;
6758      }
6759    else
6760      {
6761         _item_unrealize(it, EINA_FALSE);
6762         it->flipped = EINA_FALSE;
6763         it->item->nocache = EINA_FALSE;
6764      }
6765    if (sd->calc_job) ecore_job_del(sd->calc_job);
6766    sd->calc_job = ecore_job_add(_calc_job, sd);
6767 }
6768
6769 EAPI Eina_Bool
6770 elm_genlist_item_flip_get(const Elm_Object_Item *item)
6771 {
6772    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6773
6774    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
6775
6776    return it->flipped;
6777 }
6778
6779 EAPI void
6780 elm_genlist_select_mode_set(Evas_Object *obj,
6781                             Elm_Object_Select_Mode mode)
6782 {
6783    ELM_GENLIST_CHECK(obj);
6784    ELM_GENLIST_DATA_GET(obj, sd);
6785
6786    if (mode >= ELM_OBJECT_SELECT_MODE_MAX || (sd->select_mode == mode))
6787      return;
6788
6789    sd->select_mode = mode;
6790    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
6791        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ))
6792      {
6793         Eina_List *l, *ll;
6794         Elm_Gen_Item *it;
6795         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, it)
6796           _item_unselect(it);
6797      }
6798 }
6799
6800 EAPI Elm_Object_Select_Mode
6801 elm_genlist_select_mode_get(const Evas_Object *obj)
6802 {
6803    ELM_GENLIST_CHECK(obj) ELM_OBJECT_SELECT_MODE_MAX;
6804    ELM_GENLIST_DATA_GET(obj, sd);
6805
6806    return sd->select_mode;
6807 }
6808
6809 EAPI void
6810 elm_genlist_highlight_mode_set(Evas_Object *obj,
6811                                Eina_Bool highlight)
6812 {
6813    ELM_GENLIST_CHECK(obj);
6814    ELM_GENLIST_DATA_GET(obj, sd);
6815
6816    sd->highlight = !!highlight;
6817 }
6818
6819 EAPI Eina_Bool
6820 elm_genlist_highlight_mode_get(const Evas_Object *obj)
6821 {
6822    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6823    ELM_GENLIST_DATA_GET(obj, sd);
6824
6825    return sd->highlight;
6826 }
6827
6828 EAPI void
6829 elm_genlist_item_select_mode_set(Elm_Object_Item *item,
6830                                  Elm_Object_Select_Mode mode)
6831 {
6832    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6833
6834    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
6835    if (!it) return;
6836    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
6837      return;
6838    if (it->select_mode != mode)
6839      it->select_mode = mode;
6840
6841    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
6842        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY ))
6843       _item_unselect(it);
6844
6845    if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
6846      {
6847         it->item->mincalcd = EINA_FALSE;
6848         it->item->updateme = EINA_TRUE;
6849         if (it->item->block) it->item->block->updateme = EINA_TRUE;
6850         if (GL_IT(it)->wsd->update_job)
6851           ecore_job_del(GL_IT(it)->wsd->update_job);
6852         GL_IT(it)->wsd->update_job =
6853           ecore_job_add(_update_job, GL_IT(it)->wsd);
6854
6855         // reset homogeneous item size
6856         if (GL_IT(it)->wsd->homogeneous)
6857           {
6858              if (it->group)
6859                GL_IT(it)->wsd->group_item_width =
6860                  GL_IT(it)->wsd->group_item_height = 0;
6861              else
6862                GL_IT(it)->wsd->item_width = GL_IT(it)->wsd->item_height = 0;
6863           }
6864      }
6865 }
6866
6867 EAPI Elm_Object_Select_Mode
6868 elm_genlist_item_select_mode_get(const Elm_Object_Item *item)
6869 {
6870    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6871
6872    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, ELM_OBJECT_SELECT_MODE_MAX);
6873
6874    if (!it) return ELM_OBJECT_SELECT_MODE_MAX;
6875
6876    return it->select_mode;
6877 }
6878
6879 // will be deprecated
6880 EAPI void
6881 elm_genlist_tree_effect_enabled_set(Evas_Object *obj __UNUSED__,
6882                                     Eina_Bool enabled __UNUSED__)
6883 {
6884    ELM_GENLIST_CHECK(obj);
6885 }
6886
6887 // will be deprecated
6888 EAPI Eina_Bool
6889 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj __UNUSED__)
6890 {
6891    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6892
6893    return EINA_FALSE;
6894 }
6895
6896 EAPI Elm_Object_Item *
6897 elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
6898 {
6899    Elm_Gen_Item *it = NULL;
6900    Eina_Accessor *a;
6901    void *data;
6902
6903    ELM_GENLIST_CHECK(obj) NULL;
6904    ELM_GENLIST_DATA_GET(obj, sd);
6905
6906    if (!sd->items) return NULL;
6907
6908    a = eina_inlist_accessor_new(sd->items);
6909    if (!a) return NULL;
6910    if (eina_accessor_data_get(a, nth, &data))
6911      it = ELM_GEN_ITEM_FROM_INLIST(data);
6912    eina_accessor_free(a);
6913    return (Elm_Object_Item *)it;
6914 }
6915
6916 #if GENLIST_FX_SUPPORT
6917 EAPI void
6918 elm_genlist_fx_mode_set(Evas_Object *obj, Eina_Bool mode)
6919 {
6920    ELM_GENLIST_CHECK(obj);
6921    ELM_GENLIST_DATA_GET(obj, sd);
6922
6923    sd->fx_mode = mode;
6924 }
6925
6926 EAPI Eina_Bool
6927 elm_genlist_fx_mode_get(const Evas_Object *obj)
6928 {
6929    ELM_GENLIST_CHECK(obj) EINA_FALSE;
6930    ELM_GENLIST_DATA_GET(obj, sd);
6931
6932    return sd->fx_mode;
6933 }
6934
6935 static void
6936 _elm_genlist_proxy_item_del(const Elm_Object_Item *item)
6937 {
6938    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6939    if ((!it) || (!it->item)) return;
6940
6941    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
6942    Proxy_Item *pi;
6943    Eina_List *l;
6944
6945    EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
6946       if (pi->it == it) pi->it = NULL;
6947
6948    EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
6949       if (pi->it == it) pi->it = NULL;
6950 }
6951
6952 static Proxy_Item *
6953 _elm_genlist_proxy_item_new(const Elm_Object_Item *item)
6954 {
6955    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
6956    if ((!it) || (!it->item)) return EINA_FALSE;
6957    int w, h;
6958
6959    Proxy_Item *pi = NULL;
6960    pi = calloc(1, sizeof(Proxy_Item));
6961    if (!pi) return NULL;
6962
6963    pi->proxy = evas_object_image_filled_add
6964       (evas_object_evas_get(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj));
6965    if (!pi->proxy) return EINA_FALSE;
6966    evas_object_clip_set(pi->proxy, evas_object_clip_get(GL_IT(it)->wsd->pan_obj));
6967    evas_object_smart_member_add(pi->proxy, GL_IT(it)->wsd->pan_obj);
6968    evas_object_hide(pi->proxy);
6969
6970    if ((GL_IT(it)->wsd->decorate_all_mode) && (it->deco_all_view))
6971      evas_object_image_source_set(pi->proxy, it->deco_all_view);
6972    else
6973      evas_object_image_source_set(pi->proxy, VIEW(it));
6974
6975    GL_IT(it)->has_proxy_it = EINA_TRUE;
6976    pi->it = it;
6977    pi->num = it->item->num;
6978    pi->x = it->item->scrl_x;
6979    pi->y = it->item->scrl_y;
6980    pi->w = it->item->w;
6981    pi->h = it->item->h;
6982
6983    evas_object_geometry_get(VIEW(it), NULL, NULL, &w, &h);
6984
6985    if (w <= 0 || h <= 0)
6986      {
6987         evas_object_size_hint_min_get(VIEW(it), &w, &h);
6988         evas_object_size_hint_min_set(pi->proxy, w, h);
6989      }
6990    else evas_object_resize(pi->proxy, w, h);
6991
6992    return pi;
6993 }
6994
6995 static Eina_Bool
6996 _elm_genlist_fx_capture(Evas_Object *obj, int level)
6997 {
6998    ELM_GENLIST_DATA_GET(obj, sd);
6999
7000    Item_Block *itb;
7001    Eina_List *l;
7002    Eina_Bool done = EINA_FALSE;
7003    Elm_Gen_Item *it;
7004    Proxy_Item *pi;
7005    Evas_Coord ox, oy, ow, oh;
7006
7007    if (!sd->sorting)
7008      {
7009         if ((!sd->rendered) || (sd->fx_playing)) return EINA_FALSE;
7010         if ((!level) && (sd->fx_first_captured)) return EINA_FALSE;
7011         if ((level) && (!sd->fx_first_captured)) return EINA_FALSE;
7012      }
7013    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7014
7015    if (!level)
7016      {
7017         sd->fx_first_captured = EINA_TRUE;
7018         EINA_LIST_FREE(sd->capture_before_items, pi)
7019           {
7020              if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
7021              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
7022              if (pi->proxy) evas_object_del(pi->proxy);
7023              free(pi);
7024           }
7025      }
7026    else
7027      {
7028         EINA_LIST_FREE(sd->capture_after_items, pi)
7029           {
7030              if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
7031              if (pi->proxy) evas_object_smart_member_del(pi->proxy);
7032              if (pi->proxy) evas_object_del(pi->proxy);
7033              free(pi);
7034           }
7035
7036         EINA_INLIST_FOREACH(sd->blocks, itb)
7037           {
7038              if (itb->realized)
7039                {
7040                   EINA_LIST_FOREACH(itb->items, l, it)
7041                     {
7042                        if (it->realized && it->item->scrl_y >= oy)
7043                          {
7044                             sd->realized_top_item = it;
7045                             break;
7046                          }
7047                     }
7048                }
7049              if (sd->realized_top_item) break;
7050           }
7051      }
7052
7053 #if GENLIST_PINCH_ZOOM_SUPPORT
7054    if (sd->pinch_zoom_mode)
7055      {
7056         EINA_INLIST_FOREACH(sd->blocks, itb)
7057           {
7058              EINA_LIST_FOREACH(itb->items, l, it)
7059                {
7060
7061                   if (IS_ROOT_PARENT_IT(it) && it->realized
7062                       && (GL_IT(it)->scrl_y + GL_IT(it)->h >= oy && GL_IT(it)->scrl_y <= oy + oh))
7063                     {
7064                        pi = _elm_genlist_proxy_item_new((Elm_Object_Item *)it);
7065                        if (!level) sd->capture_before_items = eina_list_append(sd->capture_before_items, pi);
7066                        else sd->capture_after_items = eina_list_append(sd->capture_after_items, pi);
7067                     }
7068                }
7069           }
7070         if ((sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT) && (level)) return EINA_TRUE;
7071         if ((sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_EXPAND) && (!level)) return EINA_TRUE;
7072      }
7073 #endif
7074
7075    EINA_INLIST_FOREACH(sd->blocks, itb)
7076      {
7077         if (itb->realized)
7078           {
7079              done = EINA_TRUE;
7080              EINA_LIST_FOREACH(itb->items, l, it)
7081                {
7082 #if GENLIST_PINCH_ZOOM_SUPPORT
7083                   if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(it))) continue;
7084 #endif
7085                   if (it->realized)
7086                     {
7087                        pi = _elm_genlist_proxy_item_new((Elm_Object_Item *)it);
7088                        if (!pi) continue;
7089                        if (!level)
7090                          sd->capture_before_items = eina_list_append(sd->capture_before_items, pi);
7091                        else
7092                          sd->capture_after_items = eina_list_append(sd->capture_after_items, pi);
7093                     }
7094                }
7095           }
7096         else if (done) break;
7097      }
7098    return EINA_TRUE;
7099 }
7100
7101 static Elm_Gen_FX_Item *
7102 _elm_genlist_fx_item_find(const Elm_Object_Item *item)
7103 {
7104    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
7105    if (!it) return EINA_FALSE;
7106
7107    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
7108    if (!sd) return NULL;
7109
7110    Elm_Gen_FX_Item *fi = NULL;
7111    Eina_List *l;
7112
7113    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7114      {
7115         if (fi->it == it) return fi;
7116      }
7117    return NULL;
7118 }
7119
7120 static Elm_Gen_FX_Item *
7121 _elm_genlist_fx_item_new(const Proxy_Item *pi)
7122 {
7123    if ((!pi) || (!pi->it)) return NULL;
7124
7125    Elm_Gen_FX_Item *fi = NULL;
7126    fi = calloc(1, sizeof(Elm_Gen_FX_Item));
7127    if (!fi) return NULL;
7128
7129    fi->it = pi->it;
7130    GL_IT(fi->it)->fi = fi;
7131    fi->proxy = pi->proxy;
7132    fi->num = pi->num;
7133    fi->from.x = fi->to.x = pi->x;
7134    fi->from.y = fi->to.y = pi->y;
7135    fi->from.w = fi->to.w = pi->w;
7136    fi->from.h = fi->to.h = pi->h;
7137    fi->update = EINA_FALSE;
7138
7139    return fi;
7140 }
7141
7142 static Elm_Object_Item *
7143 _elm_genlist_fx_item_prev_get(const Elm_Object_Item *item)
7144 {
7145    Elm_Gen_Item *it;
7146    it = (Elm_Gen_Item *)item;
7147    if (!it) return NULL;
7148    if (GL_IT(it)->wsd->pinch_zoom_mode) return NULL;
7149
7150    while (it)
7151      {
7152         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
7153         if (it) break;
7154      }
7155
7156    return (Elm_Object_Item *)it;
7157 }
7158
7159 EAPI Eina_Bool
7160 _elm_genlist_fx_items_make(Evas_Object *obj)
7161 {
7162    ELM_GENLIST_CHECK(obj) EINA_FALSE;
7163    ELM_GENLIST_DATA_GET(obj, sd);
7164
7165    Elm_Gen_FX_Item *fi;
7166    Proxy_Item *pi;
7167    Eina_List *l;
7168    Elm_Gen_Item *prev = NULL;
7169    Evas_Coord ox, oy, ow, oh, mv_dist, max_mv_dist = 0;
7170
7171    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7172
7173    EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
7174      {
7175         fi = _elm_genlist_fx_item_new(pi);
7176         if (fi) sd->fx_items = eina_list_append(sd->fx_items, fi);
7177      }
7178
7179    EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
7180      {
7181         fi = _elm_genlist_fx_item_find((Elm_Object_Item *)pi->it);
7182
7183         if (fi) // pi exists in both before and after capture items
7184           {
7185              fi->type = ELM_GEN_ITEM_FX_TYPE_SAME;
7186              fi->update = EINA_TRUE;
7187              fi->to.x = pi->x;
7188              fi->to.y = pi->y;
7189              fi->to.w = pi->w;
7190              fi->to.h = pi->h;
7191
7192              // find the max distance between before and after capture items
7193              mv_dist = abs(fi->to.y - fi->from.y);
7194              if (max_mv_dist < mv_dist) max_mv_dist = mv_dist;
7195           }
7196         else  // pi only exists in after capture items
7197           {
7198              fi = _elm_genlist_fx_item_new(pi);
7199              if (fi)
7200                {
7201                   fi->type = ELM_GEN_ITEM_FX_TYPE_ADD;
7202                   fi->update = EINA_TRUE;
7203                   sd->fx_items = eina_list_append(sd->fx_items, fi);
7204                }
7205           }
7206      }
7207
7208    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7209      {
7210         // find deleted items
7211         if (!fi->update) // pi only exists in before capture items
7212           {
7213              fi->type = ELM_GEN_ITEM_FX_TYPE_DEL;
7214              fi->update = EINA_TRUE;
7215
7216              prev = (Elm_Gen_Item *)_elm_genlist_fx_item_prev_get((Elm_Object_Item *)fi->it);
7217              if ((prev) && (GL_IT(prev)->fi))
7218                {
7219                   fi->to.y = GL_IT(prev)->fi->to.y + GL_IT(prev)->fi->to.h;
7220                }
7221           }
7222         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_ADD)
7223           {
7224              prev = (Elm_Gen_Item *)_elm_genlist_fx_item_prev_get((Elm_Object_Item *)fi->it);
7225              if ((prev) && (prev->realized) && (GL_IT(prev)->fi))
7226                {
7227                   fi->from.y = GL_IT(prev)->fi->from.y + GL_IT(prev)->fi->from.h;
7228                }
7229              else
7230                {
7231                   if (sd->realized_top_item)
7232                     {
7233
7234                        if (fi->num <= sd->realized_top_item->item->num)
7235                          fi->from.y -= max_mv_dist;
7236                        else
7237                          fi->from.y += max_mv_dist;
7238                     }
7239                }
7240           }
7241      }
7242
7243    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7244      {
7245         if ((GL_IT(fi->it)->items) && (GL_IT(fi->it)->expanded_depth == 0))
7246           {
7247 #if GENLIST_PINCH_ZOOM_SUPPORT
7248              if (sd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
7249                {
7250                   fi->from.y = oy + GL_IT(fi->it)->pan_scrl_y - sd->pinch_pan_y;
7251                }
7252 #endif
7253              if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
7254                {
7255                   if (sd->realized_top_item)
7256                     {
7257                        if (fi->num <= sd->realized_top_item->item->num)
7258                          fi->to.y = oy - fi->from.h;
7259                        else
7260                          fi->to.y = oy + oh;
7261                     }
7262                }
7263           }
7264      }
7265
7266    return EINA_TRUE;
7267 }
7268
7269 static Elm_Gen_FX_Item *
7270 _fx_cover_item_get(const Elm_Gen_FX_Item *fi)
7271 {
7272    Elm_Gen_FX_Item *cover_fi;
7273    Eina_List *l;
7274    if (!fi) return NULL;
7275
7276    Elm_Genlist_Smart_Data *sd = GL_IT(fi->it)->wsd;
7277    Evas_Coord ox, oy, ow, oh;
7278    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7279
7280    EINA_LIST_FOREACH(sd->fx_items, l, cover_fi)
7281      {
7282         if (fi == cover_fi) continue;
7283         if (sd->fx_items_deleted)
7284           {
7285              if ((cover_fi->from.y >= oy+oh || cover_fi->from.y > fi->to.y) && (cover_fi->from.y - cover_fi->to.y > 0))
7286                return cover_fi;
7287           }
7288         else
7289           {
7290              if ((cover_fi->to.y > fi->to.y) && (cover_fi->from.y - cover_fi->to.y < 0))
7291                return cover_fi;
7292           }
7293      }
7294    return NULL;
7295 }
7296
7297 static void
7298 _item_fx_op(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__, double progress __UNUSED__)
7299 {
7300    Elm_Gen_FX_Item *fi = data, *cover_it;
7301    Elm_Genlist_Smart_Data *sd = GL_IT(fi->it)->wsd;
7302    Evas_Coord fi_ox, fi_oy, cover_it_ox, cover_it_oy, ox, oy, ow, oh;
7303
7304    evas_object_show(VIEW(fi->it));
7305    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7306    evas_object_geometry_get(fi->proxy, &fi_ox, &fi_oy, NULL, NULL);
7307    evas_object_move(fi->proxy, ox, fi_oy);
7308    evas_object_show(fi->proxy);
7309 #if GENLIST_PINCH_ZOOM_SUPPORT
7310    if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(fi->it))) evas_object_raise(fi->proxy);
7311 #endif
7312
7313    if ((!sd->expanded_next_item) || (sd->expanded_next_item == fi->it)) goto raise_event_block;
7314    if (fi->type == ELM_GEN_ITEM_FX_TYPE_SAME) goto raise_event_block;
7315
7316    // find the closest item that cover current item when deleting
7317    cover_it = _fx_cover_item_get(fi);
7318    if (cover_it)
7319      {
7320         evas_object_geometry_get(cover_it->proxy, &cover_it_ox, &cover_it_oy, NULL, NULL);
7321
7322         if (sd->fx_items_deleted)
7323           {
7324              if (cover_it_oy
7325                  && (fi_oy + fi->to.h >= cover_it_oy + cover_it->to.h ) && (fi->from.y < cover_it->from.y))
7326                evas_object_hide(fi->proxy);
7327           }
7328         else if (cover_it_oy && (fi_oy >= cover_it_oy))
7329           evas_object_hide(fi->proxy);
7330         else
7331           evas_object_show(fi->proxy);
7332      }
7333
7334 raise_event_block:
7335    evas_object_raise(sd->alpha_bg);
7336
7337    return;
7338 }
7339
7340
7341 static void
7342 _item_fx_done(Elm_Transit_Effect *data, Elm_Transit *transit __UNUSED__)
7343 {
7344    Elm_Gen_FX_Item *fx_done_it = data;
7345    Elm_Genlist_Smart_Data *sd = GL_IT(fx_done_it->it)->wsd;
7346
7347    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
7348
7349    evas_object_image_source_visible_set(fx_done_it->proxy, EINA_TRUE);
7350    evas_object_lower(fx_done_it->proxy);
7351
7352    if ((sd->decorate_all_mode) && (fx_done_it->it->deco_all_view))
7353      evas_object_move(fx_done_it->it->deco_all_view, fx_done_it->to.x, fx_done_it->to.y);
7354    else
7355      evas_object_move(VIEW(fx_done_it->it), fx_done_it->to.x, fx_done_it->to.y);
7356    GL_IT(fx_done_it->it)->has_proxy_it = EINA_FALSE;
7357
7358    evas_object_clip_unset(fx_done_it->proxy);
7359 }
7360
7361 static void
7362 _item_fx_del_cb(void *data, Elm_Transit *transit __UNUSED__)
7363 {
7364    Elm_Gen_FX_Item *fx_done_it = data;
7365    Elm_Gen_Item *it = NULL;
7366    Proxy_Item *pi = NULL;
7367    Eina_List *l;
7368    Elm_Genlist_Smart_Data *sd = GL_IT(fx_done_it->it)->wsd;
7369
7370    if ((!fx_done_it) || (!fx_done_it->it) || (!sd)) return;
7371
7372    sd->fx_items = eina_list_remove(sd->fx_items, fx_done_it);
7373    GL_IT(fx_done_it->it)->fi = NULL;
7374    free(fx_done_it);
7375
7376    if (!eina_list_count(sd->fx_items))
7377      {
7378         EINA_LIST_FREE (sd->pending_unrealized_items, it)
7379           {
7380              if (GL_IT(it)) GL_IT(it)->has_proxy_it = EINA_FALSE;
7381 #if GENLIST_PINCH_ZOOM_SUPPORT
7382              if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(it))) continue;
7383 #endif
7384              _item_unrealize(it, EINA_FALSE);
7385           }
7386         EINA_LIST_FREE (sd->pending_unrealized_decorate_all_items, it)
7387           {
7388              if (GL_IT(it)) GL_IT(it)->has_proxy_it = EINA_FALSE;
7389 #if GENLIST_PINCH_ZOOM_SUPPORT
7390              if ((sd->pinch_zoom_mode) && (IS_ROOT_PARENT_IT(it))) continue;
7391 #endif
7392              _decorate_all_item_unrealize(it);
7393           }
7394
7395         EINA_LIST_FREE (sd->pending_del_items, it)
7396           {
7397              _item_free(it);
7398              _elm_widget_item_free((Elm_Widget_Item *)it);
7399           }
7400
7401         EINA_LIST_FOREACH(sd->capture_before_items, l, pi)
7402            evas_object_hide(pi->proxy);
7403         EINA_LIST_FOREACH(sd->capture_after_items, l, pi)
7404            evas_object_hide(pi->proxy);
7405
7406         sd->fx_playing = EINA_FALSE;
7407         sd->sorting = EINA_FALSE;
7408         sd->fx_first_captured = EINA_FALSE;
7409         evas_object_hide(sd->alpha_bg);
7410
7411         sd->realized_top_item = NULL;
7412         sd->pan_changed = EINA_TRUE;
7413         evas_object_smart_changed(sd->pan_obj);
7414      }
7415 }
7416
7417 static Eina_Bool
7418 _sorting_effect_animator_cb(void *data)
7419 {
7420    Elm_Genlist_Smart_Data *sd = data;
7421    Elm_Gen_FX_Item *fi;
7422    Eina_List *l;
7423
7424    Evas_Coord ox, oy, ow, oh;
7425    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7426
7427    sd->fx_timer = NULL;
7428    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7429      {
7430         if (!fi->changed)
7431           {
7432              fi->changed = EINA_TRUE;
7433              evas_object_resize(fi->proxy, ow, fi->to.h);
7434
7435              fi->trans = elm_transit_add();
7436              elm_transit_object_add(fi->trans, fi->proxy);
7437              evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
7438              elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
7439
7440              elm_transit_effect_translation_add(fi->trans, fi->to.x, fi->to.y - 30 * elm_config_scale_get(), fi->to.x, fi->to.y);
7441              elm_transit_effect_color_add(fi->trans,0, 0, 0, 0, 255,255,255,255);
7442
7443              elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
7444              elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
7445              elm_transit_duration_set(fi->trans,0.3);
7446              elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
7447              elm_transit_go(fi->trans);
7448
7449              return ECORE_CALLBACK_RENEW;
7450           }
7451      }
7452    return ECORE_CALLBACK_CANCEL;
7453 }
7454
7455 static void
7456 _elm_genlist_fx_play(Evas_Object *obj)
7457 {
7458    ELM_GENLIST_CHECK(obj);
7459    ELM_GENLIST_DATA_GET(obj, sd);
7460
7461    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
7462    Elm_Gen_FX_Item *fi;
7463    Eina_List *l;
7464
7465    if (!sd->fx_mode) return;
7466
7467    EINA_LIST_FREE(sd->fx_items, fi)
7468      {
7469         if (fi->trans) elm_transit_del(fi->trans);
7470         free(fi);
7471      }
7472    _item_cache_all_free(sd);
7473
7474    _elm_genlist_fx_items_make(obj);
7475    if (!eina_list_count(sd->fx_items) || (sd->queue))
7476      {
7477         _elm_genlist_fx_clear(obj, EINA_TRUE);
7478         return;
7479      }
7480
7481    sd->fx_playing = EINA_TRUE;
7482
7483    if (!sd->alpha_bg) sd->alpha_bg = _tray_alpha_bg_create(obj);
7484    evas_object_show(sd->alpha_bg);
7485
7486    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7487    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
7488
7489    if (sd->sorting)
7490      {
7491         EINA_LIST_FOREACH(sd->fx_items, l, fi)
7492            evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
7493         if (sd->fx_timer) ecore_timer_del(sd->fx_timer);
7494         sd->fx_timer = ecore_timer_add(0.05, _sorting_effect_animator_cb, sd);
7495         return;
7496      }
7497
7498    EINA_LIST_FOREACH(sd->fx_items, l, fi)
7499      {
7500         if (!fi->proxy) continue;
7501
7502         if ((fi->from.y <= oy) || (fi->from.y + fi->from.h >= oy + oh))
7503           {
7504              if ((sd->decorate_all_mode) && (fi->it->deco_all_view))
7505                evas_object_move(fi->it->deco_all_view, cvx, fi->to.y);
7506              else
7507                evas_object_move(VIEW(fi->it), cvx, fi->to.y);
7508           }
7509         else if ((fi->to.y <= oy) || (fi->to.y + fi->to.h >= oy + oh))
7510           {
7511              if ((sd->decorate_all_mode) && (fi->it->deco_all_view))
7512                evas_object_move(fi->it->deco_all_view, cvx, fi->from.y);
7513              else
7514                evas_object_move(VIEW(fi->it), cvx, fi->from.y);
7515           }
7516
7517         evas_object_resize(fi->proxy, ow, fi->to.h);
7518         evas_object_show(fi->proxy);
7519
7520         fi->trans = elm_transit_add();
7521         elm_transit_object_add(fi->trans, fi->proxy);
7522
7523         evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
7524         elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
7525
7526         if (fi->type == ELM_GEN_ITEM_FX_TYPE_SAME)
7527           {
7528              evas_object_raise(fi->proxy);
7529              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
7530           }
7531
7532         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_ADD)
7533           {
7534              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
7535              elm_transit_effect_color_add(fi->trans, 0, 0, 0, 0, 255, 255, 255, 255);
7536              if ((!sd->pinch_zoom_mode) && (!sd->expanded_item))
7537                elm_transit_effect_zoom_add(fi->trans, 0.8, 1.0);
7538           }
7539         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
7540           {
7541              _item_unhighlight(fi->it);
7542              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
7543              elm_transit_effect_color_add(fi->trans, 255, 255, 255, 255, 0, 0, 0, 0);
7544              if ((!sd->pinch_zoom_mode) && (!sd->expanded_item))
7545                elm_transit_effect_zoom_add(fi->trans, 1.0, 0.8);
7546           }
7547         elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
7548         elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
7549
7550         elm_transit_duration_set(fi->trans, FX_MOVE_TIME);
7551         elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
7552         elm_transit_go(fi->trans);
7553      }
7554 }
7555 #endif
7556
7557 #if GENLIST_PINCH_ZOOM_SUPPORT
7558 EAPI Eina_Bool
7559 elm_genlist_pinch_zoom_mode_set(Evas_Object *obj, Elm_Gen_Pinch_Zoom_Mode mode)
7560 {
7561    ELM_GENLIST_DATA_GET(obj, sd);
7562
7563    Item_Block *itb;
7564    Eina_List *l;
7565    Elm_Gen_Item *it;
7566    Eina_Bool done = EINA_FALSE;
7567
7568    if ((sd->queue) || (!sd->rendered) || (sd->queue_idle_enterer)) 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 }