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