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