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