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