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