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