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