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