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