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