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