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