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