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