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