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