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