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