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