elementary/genlist, gengrid - added itc version checking.
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2 #include <fnmatch.h>
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_gen_common.h"
8
9 #define MAX_ITEMS_PER_BLOCK 32
10 #define REORDER_EFFECT_TIME 0.5
11
12 #define ELM_GEN_SETUP(wd) \
13    (wd)->calc_cb = (Ecore_Cb)_calc_job; \
14    (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
15    (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
16
17 #define ELM_GEN_ITEM_SETUP(it) \
18    (it)->del_cb = (Ecore_Cb)_item_del; \
19    (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
20    (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
21    (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
22    (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
23
24 #define ELM_GENLIST_CHECK_ITC_VER(itc) \
25    do \
26      { \
27         if (!itc) \
28           { \
29              ERR("Genlist_Item_Class(itc) is NULL"); \
30              return; \
31           } \
32         if (itc->version != ELM_GENLIST_ITEM_CLASS_VERSION) \
33           { \
34              ERR("Genlist_Item_Class version mismatched! required = (%d), current  = (%d)", itc->version, ELM_GENLIST_ITEM_CLASS_VERSION); \
35              return; \
36           } \
37      } \
38    while(0)
39
40
41
42 typedef struct _Item_Block  Item_Block;
43 typedef struct _Item_Cache  Item_Cache;
44
45 struct Elm_Gen_Item_Type
46 {
47    Elm_Gen_Item                 *it;
48    Item_Block                   *block;
49    Eina_List                    *items;
50    Evas_Coord                    w, h, minw, minh;
51    Elm_Gen_Item                 *group_item;
52    Elm_Genlist_Item_Flags        flags;
53    Eina_List                    *mode_texts, *mode_contents, *mode_states, *mode_content_objs;
54    Eina_List                    *edit_texts, *edit_contents, *edit_states, *edit_content_objs;
55    Ecore_Timer                  *swipe_timer;
56    Evas_Coord                    scrl_x, scrl_y, old_scrl_y;
57
58    Elm_Gen_Item                 *rel;
59    Evas_Object                  *mode_view;
60    int                           expanded_depth;
61    int                           order_num_in;
62
63    Eina_Bool                     before : 1;
64
65    Eina_Bool                     want_realize : 1;
66    Eina_Bool                     expanded : 1;
67    Eina_Bool                     mincalcd : 1;
68    Eina_Bool                     queued : 1;
69    Eina_Bool                     showme : 1;
70    Eina_Bool                     updateme : 1;
71    Eina_Bool                     nocache : 1;
72    Eina_Bool                     stacking_even : 1;
73    Eina_Bool                     nostacking : 1;
74    Eina_Bool                     move_effect_enabled : 1;
75    Eina_Bool                     edit_mode_item_realized : 1;
76 };
77
78 struct _Item_Block
79 {
80    EINA_INLIST;
81    int          count;
82    int          num;
83    int          reorder_offset;
84    Widget_Data *wd;
85    Eina_List   *items;
86    Evas_Coord   x, y, w, h, minw, minh;
87    int          position;
88    int          item_position_stamp;
89
90    Eina_Bool    position_update : 1;
91    Eina_Bool    want_unrealize : 1;
92    Eina_Bool    realized : 1;
93    Eina_Bool    changed : 1;
94    Eina_Bool    updateme : 1;
95    Eina_Bool    showme : 1;
96    Eina_Bool    must_recalc : 1;
97 };
98
99 struct _Item_Cache
100 {
101    EINA_INLIST;
102
103    Evas_Object *base_view, *spacer;
104
105    const char  *item_style; // it->itc->item_style
106    Eina_Bool    tree : 1; // it->group
107    Eina_Bool    compress : 1; // it->wd->compress
108
109    Eina_Bool    selected : 1; // it->selected
110    Eina_Bool    disabled : 1; // it->disabled
111    Eina_Bool    expanded : 1; // it->item->expanded
112 };
113
114 static const char *widtype = NULL;
115 static void      _item_cache_zero(Widget_Data *wd);
116 static void      _del_hook(Evas_Object *obj);
117 static void      _mirrored_set(Evas_Object *obj,
118                                Eina_Bool    rtl);
119 static void      _theme_hook(Evas_Object *obj);
120 static void      _show_region_hook(void        *data,
121                                    Evas_Object *obj);
122 static void      _sizing_eval(Evas_Object *obj);
123 static void      _item_realize(Elm_Gen_Item *it,
124                                int           in,
125                                Eina_Bool     calc);
126 static void      _item_unrealize_cb(Elm_Gen_Item *it);
127 static void      _item_block_unrealize(Item_Block *itb);
128 static void      _calc_job(void *data);
129 static void      _on_focus_hook(void        *data,
130                                 Evas_Object *obj);
131 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
132 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
133 static Eina_Bool _item_single_select_up(Widget_Data *wd);
134 static Eina_Bool _item_single_select_down(Widget_Data *wd);
135 static Eina_Bool _event_hook(Evas_Object       *obj,
136                              Evas_Object       *src,
137                              Evas_Callback_Type type,
138                              void              *event_info);
139 static void      _signal_emit_hook(Evas_Object *obj,
140                                    const char  *emission,
141                                    const char  *source);
142 static Eina_Bool _deselect_all_items(Widget_Data *wd);
143 static void      _pan_calculate(Evas_Object *obj);
144 static void      _pan_max_get(Evas_Object *obj,
145                               Evas_Coord  *x,
146                               Evas_Coord  *y);
147 static void      _item_position(Elm_Gen_Item *it,
148                                 Evas_Object  *obj,
149                                 Evas_Coord    it_x,
150                                 Evas_Coord    it_y);
151 static void      _mode_item_realize(Elm_Gen_Item *it);
152 static void      _mode_item_unrealize(Elm_Gen_Item *it);
153 static void      _item_mode_set(Elm_Gen_Item *it);
154 static void      _item_mode_unset(Widget_Data *wd);
155 static void      _edit_mode_item_position(Elm_Gen_Item *it, int itx, int ity);
156 static void      _edit_mode_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on);
157 static void      _edit_mode_item_unrealize(Elm_Gen_Item *it);
158 static void      _group_items_recalc(void *data);
159 static void      _item_move_after(Elm_Gen_Item *it,
160                                   Elm_Gen_Item *after);
161 static void      _item_move_before(Elm_Gen_Item *it,
162                                    Elm_Gen_Item *before);
163 static void      _item_auto_scroll(Widget_Data *wd);
164 static void      _elm_genlist_clear(Evas_Object *obj,
165                                     Eina_Bool    standby);
166 static void      _pan_child_size_get(Evas_Object *obj,
167                                      Evas_Coord  *w,
168                                      Evas_Coord  *h);
169
170 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
171
172 static const char SIG_ACTIVATED[] = "activated";
173 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
174 static const char SIG_SELECTED[] = "selected";
175 static const char SIG_UNSELECTED[] = "unselected";
176 static const char SIG_EXPANDED[] = "expanded";
177 static const char SIG_CONTRACTED[] = "contracted";
178 static const char SIG_EXPAND_REQUEST[] = "expand,request";
179 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
180 static const char SIG_REALIZED[] = "realized";
181 static const char SIG_UNREALIZED[] = "unrealized";
182 static const char SIG_DRAG_START_UP[] = "drag,start,up";
183 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
184 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
185 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
186 static const char SIG_DRAG_STOP[] = "drag,stop";
187 static const char SIG_DRAG[] = "drag";
188 static const char SIG_LONGPRESSED[] = "longpressed";
189 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
190 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
191 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
192 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
193 static const char SIG_EDGE_TOP[] = "edge,top";
194 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
195 static const char SIG_EDGE_LEFT[] = "edge,left";
196 static const char SIG_EDGE_RIGHT[] = "edge,right";
197 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
198 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
199 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
200 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
201 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
202 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
203 static const char SIG_SWIPE[] = "swipe";
204 static const char SIG_MOVED[] = "moved";
205 static const char SIG_INDEX_UPDATE[] = "index,update";
206
207 static const Evas_Smart_Cb_Description _signals[] = {
208    {SIG_CLICKED_DOUBLE, ""},
209    {SIG_ACTIVATED, ""},
210    {SIG_SELECTED, ""},
211    {SIG_UNSELECTED, ""},
212    {SIG_EXPANDED, ""},
213    {SIG_CONTRACTED, ""},
214    {SIG_EXPAND_REQUEST, ""},
215    {SIG_CONTRACT_REQUEST, ""},
216    {SIG_REALIZED, ""},
217    {SIG_UNREALIZED, ""},
218    {SIG_DRAG_START_UP, ""},
219    {SIG_DRAG_START_DOWN, ""},
220    {SIG_DRAG_START_LEFT, ""},
221    {SIG_DRAG_START_RIGHT, ""},
222    {SIG_DRAG_STOP, ""},
223    {SIG_DRAG, ""},
224    {SIG_LONGPRESSED, ""},
225    {SIG_SCROLL_ANIM_START, ""},
226    {SIG_SCROLL_ANIM_STOP, ""},
227    {SIG_SCROLL_DRAG_START, ""},
228    {SIG_SCROLL_DRAG_STOP, ""},
229    {SIG_EDGE_TOP, ""},
230    {SIG_EDGE_BOTTOM, ""},
231    {SIG_EDGE_LEFT, ""},
232    {SIG_EDGE_RIGHT, ""},
233    {SIG_MULTI_SWIPE_LEFT, ""},
234    {SIG_MULTI_SWIPE_RIGHT, ""},
235    {SIG_MULTI_SWIPE_UP, ""},
236    {SIG_MULTI_SWIPE_DOWN, ""},
237    {SIG_MULTI_PINCH_OUT, ""},
238    {SIG_MULTI_PINCH_IN, ""},
239    {SIG_SWIPE, ""},
240    {SIG_MOVED, ""},
241    {NULL, NULL}
242 };
243
244 /* TEMPORARY */
245 #undef ELM_CHECK_WIDTYPE
246 #define ELM_CHECK_WIDTYPE(obj, widtype) \
247    if ((!obj) || (!elm_genlist_type_check((obj), __func__))) return
248 #undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
249 #define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
250    ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
251    ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
252
253 static const char *_gengrid = NULL;
254 static const char *_genlist = NULL;
255
256 /* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
257 Eina_Bool
258 elm_genlist_type_check(const Evas_Object *obj,
259                        const char        *func)
260 {
261    const char *provided, *expected = "(unknown)";
262    static int abort_on_warn = -1;
263    provided = elm_widget_type_get(obj);
264    if (!_genlist) _genlist = eina_stringshare_add("genlist");
265    if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
266    if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
267      return EINA_TRUE;
268    if ((!provided) || (!provided[0]))
269      {
270         provided = evas_object_type_get(obj);
271         if ((!provided) || (!provided[0]))
272           provided = "(unknown)";
273      }
274    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
275    if (abort_on_warn == -1)
276      {
277         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
278         else abort_on_warn = 0;
279      }
280    if (abort_on_warn == 1) abort();
281    return EINA_FALSE;
282 }
283
284 static Eina_Bool
285 _event_hook(Evas_Object       *obj,
286             Evas_Object       *src __UNUSED__,
287             Evas_Callback_Type type,
288             void              *event_info)
289 {
290    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
291    Evas_Event_Key_Down *ev = event_info;
292    Widget_Data *wd = elm_widget_data_get(obj);
293    Evas_Coord pan_max_x = 0, pan_max_y = 0;
294    if (!wd) return EINA_FALSE;
295    if (!wd->items) return EINA_FALSE;
296    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
297    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
298
299    Elm_Object_Item *it = NULL;
300    Evas_Coord x = 0;
301    Evas_Coord y = 0;
302    Evas_Coord step_x = 0;
303    Evas_Coord step_y = 0;
304    Evas_Coord v_w = 0;
305    Evas_Coord v_h = 0;
306    Evas_Coord page_x = 0;
307    Evas_Coord page_y = 0;
308
309    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
310    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
311    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
312    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
313
314    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
315      {
316         x -= step_x;
317      }
318    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
319      {
320         x += step_x;
321      }
322    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
323      {
324         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
325              (_item_multi_select_up(wd)))
326             || (_item_single_select_up(wd)))
327           {
328              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
329              return EINA_TRUE;
330           }
331         else
332           y -= step_y;
333      }
334    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
335      {
336         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
337              (_item_multi_select_down(wd)))
338             || (_item_single_select_down(wd)))
339           {
340              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
341              return EINA_TRUE;
342           }
343         else
344           y += step_y;
345      }
346    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
347      {
348         it = elm_genlist_first_item_get(obj);
349         elm_genlist_item_bring_in(it);
350         elm_genlist_item_selected_set(it, EINA_TRUE);
351         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
352         return EINA_TRUE;
353      }
354    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
355      {
356         it = elm_genlist_last_item_get(obj);
357         elm_genlist_item_bring_in(it);
358         elm_genlist_item_selected_set(it, EINA_TRUE);
359         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
360         return EINA_TRUE;
361      }
362    else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
363      {
364         if (page_y < 0)
365           y -= -(page_y * v_h) / 100;
366         else
367           y -= page_y;
368      }
369    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
370      {
371         if (page_y < 0)
372           y += -(page_y * v_h) / 100;
373         else
374           y += page_y;
375      }
376    else if (!strcmp(ev->keyname, "Escape"))
377      {
378         if (!_deselect_all_items(wd)) return EINA_FALSE;
379         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
380         return EINA_TRUE;
381      }
382    else if (((!strcmp(ev->keyname, "Return")) ||
383              (!strcmp(ev->keyname, "KP_Enter")) ||
384              (!strcmp(ev->keyname, "space")))
385             && (!wd->multi) && (wd->selected))
386      {
387         it = elm_genlist_selected_item_get(obj);
388         elm_genlist_item_expanded_set(it,
389                                       !elm_genlist_item_expanded_get(it));
390         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
391      }
392    else return EINA_FALSE;
393
394    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
395    _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
396    if (x < 0) x = 0;
397    if (x > pan_max_x) x = pan_max_x;
398    if (y < 0) y = 0;
399    if (y > pan_max_y) y = pan_max_y;
400    elm_smart_scroller_child_pos_set(wd->scr, x, y);
401    return EINA_TRUE;
402 }
403
404 static Eina_Bool
405 _deselect_all_items(Widget_Data *wd)
406 {
407    if (!wd->selected) return EINA_FALSE;
408    while (wd->selected)
409      elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
410
411    return EINA_TRUE;
412 }
413
414 static Eina_Bool
415 _item_multi_select_up(Widget_Data *wd)
416 {
417    if (!wd->selected) return EINA_FALSE;
418    if (!wd->multi) return EINA_FALSE;
419
420    Elm_Object_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
421    if (!prev) return EINA_TRUE;
422
423    if (elm_genlist_item_selected_get(prev))
424      {
425         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
426         wd->last_selected_item = prev;
427         elm_genlist_item_show(wd->last_selected_item);
428      }
429    else
430      {
431         elm_genlist_item_selected_set(prev, EINA_TRUE);
432         elm_genlist_item_show(prev);
433      }
434    return EINA_TRUE;
435 }
436
437 static Eina_Bool
438 _item_multi_select_down(Widget_Data *wd)
439 {
440    if (!wd->selected) return EINA_FALSE;
441    if (!wd->multi) return EINA_FALSE;
442
443    Elm_Object_Item *next;
444    next = elm_genlist_item_next_get(wd->last_selected_item);
445    if (!next) return EINA_TRUE;
446
447    if (elm_genlist_item_selected_get(next))
448      {
449         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
450         wd->last_selected_item = next;
451         elm_genlist_item_show(wd->last_selected_item);
452      }
453    else
454      {
455         elm_genlist_item_selected_set(next, EINA_TRUE);
456         elm_genlist_item_show(next);
457      }
458    return EINA_TRUE;
459 }
460
461 static Eina_Bool
462 _item_single_select_up(Widget_Data *wd)
463 {
464    Elm_Gen_Item *prev;
465    if (!wd->selected)
466      {
467         prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
468         while ((prev) && (prev->generation < wd->generation))
469           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
470      }
471    else prev = (Elm_Gen_Item *) elm_genlist_item_prev_get(wd->last_selected_item);
472
473    if (!prev) return EINA_FALSE;
474
475    _deselect_all_items(wd);
476
477    elm_genlist_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
478    elm_genlist_item_show((Elm_Object_Item *) prev);
479    return EINA_TRUE;
480 }
481
482 static Eina_Bool
483 _item_single_select_down(Widget_Data *wd)
484 {
485    Elm_Gen_Item *next;
486    if (!wd->selected)
487      {
488         next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
489         while ((next) && (next->generation < wd->generation))
490           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
491      }
492    else next = (Elm_Gen_Item *) elm_genlist_item_next_get(wd->last_selected_item);
493
494    if (!next) return EINA_FALSE;
495
496    _deselect_all_items(wd);
497
498    elm_genlist_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
499    elm_genlist_item_show((Elm_Object_Item *) next);
500    return EINA_TRUE;
501 }
502
503 static void
504 _on_focus_hook(void        *data __UNUSED__,
505                Evas_Object *obj)
506 {
507    Widget_Data *wd = elm_widget_data_get(obj);
508    if (!wd) return;
509    if (elm_widget_focus_get(obj))
510      {
511         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
512         evas_object_focus_set(wd->obj, EINA_TRUE);
513         if ((wd->selected) && (!wd->last_selected_item))
514           wd->last_selected_item = eina_list_data_get(wd->selected);
515      }
516    else
517      {
518         elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
519         evas_object_focus_set(wd->obj, EINA_FALSE);
520      }
521 }
522
523 static void
524 _del_hook(Evas_Object *obj)
525 {
526    Widget_Data *wd = elm_widget_data_get(obj);
527    if (!wd) return;
528    _item_cache_zero(wd);
529    if (wd->calc_job) ecore_job_del(wd->calc_job);
530    if (wd->update_job) ecore_job_del(wd->update_job);
531    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
532    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
533    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
534    if (wd->mode_type) eina_stringshare_del(wd->mode_type);
535    if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
536    free(wd);
537 }
538
539 static void
540 _del_pre_hook(Evas_Object *obj)
541 {
542    Widget_Data *wd = elm_widget_data_get(obj);
543    if (!wd) return;
544    if (wd->edit_mode) elm_genlist_edit_mode_set(wd->obj, EINA_FALSE);
545    elm_genlist_clear(obj);
546    evas_object_del(wd->pan_smart);
547    wd->pan_smart = NULL;
548 }
549
550 static void
551 _mirrored_set(Evas_Object *obj,
552               Eina_Bool    rtl)
553 {
554    Widget_Data *wd = elm_widget_data_get(obj);
555    if (!wd) return;
556    _item_cache_zero(wd);
557    elm_smart_scroller_mirrored_set(wd->scr, rtl);
558 }
559
560 static void
561 _theme_hook(Evas_Object *obj)
562 {
563    Widget_Data *wd = elm_widget_data_get(obj);
564    Item_Block *itb;
565    if (!wd) return;
566    evas_event_freeze(evas_object_evas_get(wd->obj));
567    _item_cache_zero(wd);
568    _elm_widget_mirrored_reload(obj);
569    _mirrored_set(obj, elm_widget_mirrored_get(obj));
570    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
571                                        elm_widget_style_get(obj));
572    edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
573    wd->item_width = wd->item_height = 0;
574    wd->group_item_width = wd->group_item_height = 0;
575    wd->minw = wd->minh = wd->realminw = 0;
576    EINA_INLIST_FOREACH(wd->blocks, itb)
577      {
578         Eina_List *l;
579         Elm_Gen_Item *it;
580
581         if (itb->realized) _item_block_unrealize(itb);
582         EINA_LIST_FOREACH(itb->items, l, it)
583           it->item->mincalcd = EINA_FALSE;
584
585         itb->changed = EINA_TRUE;
586      }
587    if (wd->calc_job) ecore_job_del(wd->calc_job);
588    wd->calc_job = ecore_job_add(_calc_job, wd);
589    _sizing_eval(obj);
590    evas_event_thaw(evas_object_evas_get(wd->obj));
591    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
592 }
593
594 static void
595 _show_region_hook(void        *data,
596                   Evas_Object *obj)
597 {
598    Widget_Data *wd = elm_widget_data_get(data);
599    Evas_Coord x, y, w, h;
600    if (!wd) return;
601    elm_widget_show_region_get(obj, &x, &y, &w, &h);
602    //x & y are screen coordinates, Add with pan coordinates
603    x += wd->pan_x;
604    y += wd->pan_y;
605    elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
606 }
607
608 static void
609 _translate_hook(Evas_Object *obj)
610 {
611    evas_object_smart_callback_call(obj, "language,changed", NULL);
612 }
613
614 static void
615 _sizing_eval(Evas_Object *obj)
616 {
617    Widget_Data *wd = elm_widget_data_get(obj);
618    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
619    if (!wd) return;
620    evas_object_size_hint_min_get(wd->scr, &minw, &minh);
621    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
622    minh = -1;
623    if (wd->height_for_width)
624      {
625         Evas_Coord vw, vh;
626
627         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
628         if ((vw != 0) && (vw != wd->prev_viewport_w))
629           {
630              Item_Block *itb;
631
632              wd->prev_viewport_w = vw;
633              EINA_INLIST_FOREACH(wd->blocks, itb)
634                {
635                   itb->must_recalc = EINA_TRUE;
636                }
637              if (wd->calc_job) ecore_job_del(wd->calc_job);
638              wd->calc_job = ecore_job_add(_calc_job, wd);
639           }
640      }
641    if (wd->mode == ELM_LIST_LIMIT)
642      {
643         Evas_Coord vmw, vmh;
644
645         minw = wd->realminw;
646         maxw = -1;
647         elm_smart_scroller_child_viewport_size_get(wd->scr, &vmw, &vmh);
648         edje_object_size_min_calc
649           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
650         minw = vmw + minw;
651      }
652    else
653      {
654         Evas_Coord vmw, vmh;
655
656         edje_object_size_min_calc
657           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
658         minw = vmw;
659         minh = vmh;
660      }
661    evas_object_size_hint_min_set(obj, minw, minh);
662    evas_object_size_hint_max_set(obj, maxw, maxh);
663 }
664
665 static void
666 _signal_emit_hook(Evas_Object *obj,
667                   const char  *emission,
668                   const char  *source)
669 {
670    Widget_Data *wd = elm_widget_data_get(obj);
671    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
672                            emission, source);
673 }
674
675 static void
676 _item_highlight(Elm_Gen_Item *it)
677 {
678    const char *selectraise;
679    if ((it->wd->no_select) || (it->generation < it->wd->generation) ||
680        (it->highlighted) || elm_widget_item_disabled_get(it) ||
681        (it->display_only) || (it->item->mode_view))
682      return;
683    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
684    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,selected", "elm");
685    selectraise = edje_object_data_get(VIEW(it), "selectraise");
686    if ((selectraise) && (!strcmp(selectraise, "on")))
687      {
688         if (it->edit_obj) evas_object_raise(it->edit_obj);
689         else evas_object_raise(VIEW(it));
690         if ((it->item->group_item) && (it->item->group_item->realized))
691           evas_object_raise(it->item->VIEW(group_item));
692      }
693    it->highlighted = EINA_TRUE;
694 }
695
696 static void
697 _item_unhighlight(Elm_Gen_Item *it)
698 {
699    if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
700    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
701    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,unselected", "elm");
702    if (!it->item->nostacking)
703      {
704        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
705          {
706              if (it->edit_obj) evas_object_lower(it->edit_obj);
707              else evas_object_lower(VIEW(it));
708          }
709        else
710          {
711              if (it->edit_obj) evas_object_raise(it->edit_obj);
712              else evas_object_raise(VIEW(it));
713          }
714      }
715    it->highlighted = EINA_FALSE;
716 }
717
718 static void
719 _item_block_position_update(Eina_Inlist *list, int idx)
720 {
721    Item_Block *tmp;
722
723    EINA_INLIST_FOREACH(list, tmp)
724      {
725         tmp->position = idx++;
726         tmp->position_update = EINA_TRUE;
727      }
728 }
729
730 static void
731 _item_position_update(Eina_List *list, int idx)
732 {
733    Elm_Gen_Item *it;
734    Eina_List *l;
735
736    EINA_LIST_FOREACH(list, l, it)
737      {
738         it->position = idx++;
739         it->position_update = EINA_TRUE;
740      }
741 }
742
743 static void
744 _item_block_del(Elm_Gen_Item *it)
745 {
746    Eina_Inlist *il;
747    Item_Block *itb = it->item->block;
748
749    itb->items = eina_list_remove(itb->items, it);
750    itb->count--;
751    itb->changed = EINA_TRUE;
752    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
753    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
754    if (itb->count < 1)
755      {
756         il = EINA_INLIST_GET(itb);
757         Item_Block *itbn = (Item_Block *)(il->next);
758         if (it->parent)
759           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
760         else
761           {
762              _item_block_position_update(il->next, itb->position);
763              it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
764           }
765         free(itb);
766         if (itbn) itbn->changed = EINA_TRUE;
767      }
768    else
769      {
770         if (itb->count < itb->wd->max_items_per_block/2)
771           {
772              il = EINA_INLIST_GET(itb);
773              Item_Block *itbp = (Item_Block *)(il->prev);
774              Item_Block *itbn = (Item_Block *)(il->next);
775              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
776                {
777                   Elm_Gen_Item *it2;
778
779                   EINA_LIST_FREE(itb->items, it2)
780                     {
781                        it2->item->block = itbp;
782                        itbp->items = eina_list_append(itbp->items, it2);
783                        itbp->count++;
784                        itbp->changed = EINA_TRUE;
785                     }
786                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
787                                               itb->position);
788                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
789                                                       EINA_INLIST_GET(itb));
790                   free(itb);
791                }
792              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
793                {
794                   while (itb->items)
795                     {
796                        Eina_List *last = eina_list_last(itb->items);
797                        Elm_Gen_Item *it2 = last->data;
798
799                        it2->item->block = itbn;
800                        itb->items = eina_list_remove_list(itb->items, last);
801                        itbn->items = eina_list_prepend(itbn->items, it2);
802                        itbn->count++;
803                        itbn->changed = EINA_TRUE;
804                     }
805                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
806                                               itb->position);
807                   it->wd->blocks =
808                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
809                   free(itb);
810                }
811           }
812      }
813 }
814
815 static void
816 _item_del(Elm_Gen_Item *it)
817 {
818    Evas_Object *obj = WIDGET(it);
819
820    evas_event_freeze(evas_object_evas_get(obj));
821    elm_genlist_item_subitems_clear((Elm_Object_Item *) it);
822    if (it->wd->show_item == it) it->wd->show_item = NULL;
823    if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
824    if (it->item->edit_mode_item_realized) _edit_mode_item_unrealize(it);
825    if (it->item->block) _item_block_del(it);
826    if (it->item->queued)
827      it->wd->queue = eina_list_remove(it->wd->queue, it);
828    if (it->wd->anchor_item == it)
829      {
830         it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
831         if (!it->wd->anchor_item)
832           it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
833      }
834    if (it->wd->expanded_item == it) it->wd->expanded_item = NULL;
835    if (it->parent)
836      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
837    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
838    _elm_genlist_item_del_serious(it);
839    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
840    evas_event_thaw(evas_object_evas_get(obj));
841    evas_event_thaw_eval(evas_object_evas_get(obj));
842 }
843
844 static void
845 _clear_cb(Widget_Data *wd)
846 {
847    wd->anchor_item = NULL;
848    while (wd->blocks)
849      {
850         Item_Block *itb = (Item_Block *)(wd->blocks);
851
852         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
853         if (itb->items) eina_list_free(itb->items);
854         free(itb);
855      }
856    if (wd->queue_idle_enterer)
857      {
858         ecore_idle_enterer_del(wd->queue_idle_enterer);
859         wd->queue_idle_enterer = NULL;
860      }
861    if (wd->must_recalc_idler)
862      {
863         ecore_idler_del(wd->must_recalc_idler);
864         wd->must_recalc_idler = NULL;
865      }
866    if (wd->queue) wd->queue = eina_list_free(wd->queue);
867    if (wd->reorder_move_animator)
868      {
869         ecore_animator_del(wd->reorder_move_animator);
870         wd->reorder_move_animator = NULL;
871      }
872    wd->show_item = NULL;
873    wd->reorder_old_pan_y = 0;
874 }
875
876 static void
877 _item_unselect(Elm_Gen_Item *it)
878 {
879    if ((it->generation < it->wd->generation) || (!it->selected)) return;
880    it->selected = EINA_FALSE;
881    it->wd->selected = eina_list_remove(it->wd->selected, it);
882    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
883 }
884
885 static void
886 _mouse_move(void        *data,
887             Evas        *evas __UNUSED__,
888             Evas_Object *obj,
889             void        *event_info)
890 {
891    Elm_Gen_Item *it = data;
892    Evas_Event_Mouse_Move *ev = event_info;
893    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
894    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
895
896    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
897      {
898         if (!it->wd->on_hold)
899           {
900              it->wd->on_hold = EINA_TRUE;
901              if (!it->wd->wasselected)
902                {
903                   _item_unhighlight(it);
904                   _item_unselect(it);
905                }
906           }
907      }
908    if (it->wd->multitouched)
909      {
910         it->wd->cur_x = ev->cur.canvas.x;
911         it->wd->cur_y = ev->cur.canvas.y;
912         return;
913      }
914    if ((it->dragging) && (it->down))
915      {
916         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
917         else
918           {
919              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
920              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
921              if (abs((it->wd->history[it->wd->movements].x -
922                       it->wd->history[0].x)) > 40)
923                it->wd->swipe = EINA_TRUE;
924              else
925                it->wd->movements++;
926           }
927         if (it->long_timer)
928           {
929              ecore_timer_del(it->long_timer);
930              it->long_timer = NULL;
931           }
932         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
933         return;
934      }
935    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
936      {
937         if (it->long_timer)
938           {
939              ecore_timer_del(it->long_timer);
940              it->long_timer = NULL;
941           }
942         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
943           {
944              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
945              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
946
947              if (!it->wd->reorder_start_y)
948                it->wd->reorder_start_y = it->item->block->y + it->y;
949
950              if (it_scrl_y < oy)
951                y_pos = oy;
952              else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
953                y_pos = oy + oh - it->wd->reorder_it->item->h;
954              else
955                y_pos = it_scrl_y;
956
957              if (it->edit_obj)
958                _item_position(it, it->edit_obj, it->item->scrl_x, y_pos);
959              else
960              _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
961
962              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
963              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
964           }
965         return;
966      }
967    if (!it->display_only)
968      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
969    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
970    x = ev->cur.canvas.x - x;
971    y = ev->cur.canvas.y - y;
972    dx = x - it->dx;
973    adx = dx;
974    if (adx < 0) adx = -dx;
975    dy = y - it->dy;
976    ady = dy;
977    if (ady < 0) ady = -dy;
978    minw /= 2;
979    minh /= 2;
980    if ((adx > minw) || (ady > minh))
981      {
982         it->dragging = EINA_TRUE;
983         if (it->long_timer)
984           {
985              ecore_timer_del(it->long_timer);
986              it->long_timer = NULL;
987           }
988         if (!it->wd->wasselected)
989           {
990              _item_unhighlight(it);
991              _item_unselect(it);
992           }
993         if (dy < 0)
994           {
995              if (ady > adx)
996                evas_object_smart_callback_call(WIDGET(it),
997                                                SIG_DRAG_START_UP, it);
998              else
999                {
1000                   if (dx < 0)
1001                     evas_object_smart_callback_call(WIDGET(it),
1002                                                     SIG_DRAG_START_LEFT, it);
1003                   else
1004                     evas_object_smart_callback_call(WIDGET(it),
1005                                                     SIG_DRAG_START_RIGHT, it);
1006                }
1007           }
1008         else
1009           {
1010              if (ady > adx)
1011                evas_object_smart_callback_call(WIDGET(it),
1012                                                SIG_DRAG_START_DOWN, it);
1013              else
1014                {
1015                   if (dx < 0)
1016                     evas_object_smart_callback_call(WIDGET(it),
1017                                                     SIG_DRAG_START_LEFT, it);
1018                   else
1019                     evas_object_smart_callback_call(WIDGET(it),
1020                                                     SIG_DRAG_START_RIGHT, it);
1021                }
1022           }
1023      }
1024 }
1025
1026 static Eina_Bool
1027 _long_press(void *data)
1028 {
1029    Elm_Gen_Item *it = data, *it_tmp;
1030    Eina_List *list, *l;
1031
1032    it->long_timer = NULL;
1033    if (elm_widget_item_disabled_get(it) || (it->dragging) || (it->display_only))
1034      return ECORE_CALLBACK_CANCEL;
1035    it->wd->longpressed = EINA_TRUE;
1036    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1037    if ((it->wd->reorder_mode) && (!it->group))
1038      {
1039         it->wd->reorder_it = it;
1040         it->wd->reorder_start_y = 0;
1041         if (it->edit_obj)
1042           evas_object_raise(it->edit_obj);
1043         else
1044           evas_object_raise(VIEW(it));
1045
1046         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1047         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1048
1049         list = elm_genlist_realized_items_get(it->wd->obj);
1050         EINA_LIST_FOREACH(list, l, it_tmp)
1051           {
1052              if (it != it_tmp) _item_unselect(it_tmp);
1053           }
1054         if (elm_genlist_item_expanded_get((Elm_Object_Item *) it))
1055           {
1056              elm_genlist_item_expanded_set((Elm_Object_Item *) it, EINA_FALSE);
1057              return ECORE_CALLBACK_RENEW;
1058           }
1059
1060         if (!it->wd->edit_mode)
1061           edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1062      }
1063    return ECORE_CALLBACK_CANCEL;
1064 }
1065
1066 static void
1067 _swipe(Elm_Gen_Item *it)
1068 {
1069    int i, sum = 0;
1070
1071    if (!it) return;
1072    if ((it->display_only) || elm_widget_item_disabled_get(it)) return;
1073    it->wd->swipe = EINA_FALSE;
1074    for (i = 0; i < it->wd->movements; i++)
1075      {
1076         sum += it->wd->history[i].x;
1077         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1078      }
1079
1080    sum /= it->wd->movements;
1081    if (abs(sum - it->wd->history[0].x) <= 10) return;
1082    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1083 }
1084
1085 static Eina_Bool
1086 _swipe_cancel(void *data)
1087 {
1088    Elm_Gen_Item *it = data;
1089
1090    if (!it) return ECORE_CALLBACK_CANCEL;
1091    it->wd->swipe = EINA_FALSE;
1092    it->wd->movements = 0;
1093    return ECORE_CALLBACK_RENEW;
1094 }
1095
1096 static Eina_Bool
1097 _multi_cancel(void *data)
1098 {
1099    Widget_Data *wd = data;
1100
1101    if (!wd) return ECORE_CALLBACK_CANCEL;
1102    wd->multi_timeout = EINA_TRUE;
1103    return ECORE_CALLBACK_RENEW;
1104 }
1105
1106 static void
1107 _multi_touch_gesture_eval(void *data)
1108 {
1109    Elm_Gen_Item *it = data;
1110
1111    it->wd->multitouched = EINA_FALSE;
1112    if (it->wd->multi_timer)
1113      {
1114         ecore_timer_del(it->wd->multi_timer);
1115         it->wd->multi_timer = NULL;
1116      }
1117    if (it->wd->multi_timeout)
1118      {
1119         it->wd->multi_timeout = EINA_FALSE;
1120         return;
1121      }
1122
1123    Evas_Coord minw = 0, minh = 0;
1124    Evas_Coord off_x, off_y, off_mx, off_my;
1125
1126    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1127    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1128    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1129    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1130    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1131
1132    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1133      {
1134         if ((off_x + off_mx) > (off_y + off_my))
1135           {
1136              if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1137                evas_object_smart_callback_call(WIDGET(it),
1138                                                SIG_MULTI_SWIPE_RIGHT, it);
1139              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1140                evas_object_smart_callback_call(WIDGET(it),
1141                                                SIG_MULTI_SWIPE_LEFT, it);
1142              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1143                evas_object_smart_callback_call(WIDGET(it),
1144                                                SIG_MULTI_PINCH_OUT, it);
1145              else
1146                evas_object_smart_callback_call(WIDGET(it),
1147                                                SIG_MULTI_PINCH_IN, it);
1148           }
1149         else
1150           {
1151              if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1152                evas_object_smart_callback_call(WIDGET(it),
1153                                                SIG_MULTI_SWIPE_DOWN, it);
1154              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1155                evas_object_smart_callback_call(WIDGET(it),
1156                                                SIG_MULTI_SWIPE_UP, it);
1157              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1158                evas_object_smart_callback_call(WIDGET(it),
1159                                                SIG_MULTI_PINCH_OUT, it);
1160              else
1161                evas_object_smart_callback_call(WIDGET(it),
1162                                                SIG_MULTI_PINCH_IN, it);
1163           }
1164      }
1165    it->wd->multi_timeout = EINA_FALSE;
1166 }
1167
1168 static void
1169 _multi_down(void        *data,
1170             Evas        *evas __UNUSED__,
1171             Evas_Object *obj __UNUSED__,
1172             void        *event_info)
1173 {
1174    Elm_Gen_Item *it = data;
1175    Evas_Event_Multi_Down *ev = event_info;
1176
1177    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1178    it->wd->multi_device = ev->device;
1179    it->wd->multi_down = EINA_TRUE;
1180    it->wd->multitouched = EINA_TRUE;
1181    it->wd->prev_mx = ev->canvas.x;
1182    it->wd->prev_my = ev->canvas.y;
1183    if (!it->wd->wasselected)
1184      {
1185         _item_unhighlight(it);
1186         _item_unselect(it);
1187      }
1188    it->wd->wasselected = EINA_FALSE;
1189    it->wd->longpressed = EINA_FALSE;
1190    if (it->long_timer)
1191      {
1192         ecore_timer_del(it->long_timer);
1193         it->long_timer = NULL;
1194      }
1195    if (it->dragging)
1196      {
1197         it->dragging = EINA_FALSE;
1198         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1199      }
1200    if (it->item->swipe_timer)
1201      {
1202         ecore_timer_del(it->item->swipe_timer);
1203         it->item->swipe_timer = NULL;
1204      }
1205    if (it->wd->on_hold)
1206      {
1207         it->wd->swipe = EINA_FALSE;
1208         it->wd->movements = 0;
1209         it->wd->on_hold = EINA_FALSE;
1210      }
1211 }
1212
1213 static void
1214 _multi_up(void        *data,
1215           Evas        *evas __UNUSED__,
1216           Evas_Object *obj __UNUSED__,
1217           void        *event_info)
1218 {
1219    Elm_Gen_Item *it = data;
1220    Evas_Event_Multi_Up *ev = event_info;
1221
1222    if (it->wd->multi_device != ev->device) return;
1223    it->wd->multi_device = 0;
1224    it->wd->multi_down = EINA_FALSE;
1225    if (it->wd->mouse_down) return;
1226    _multi_touch_gesture_eval(data);
1227 }
1228
1229 static void
1230 _multi_move(void        *data,
1231             Evas        *evas __UNUSED__,
1232             Evas_Object *obj __UNUSED__,
1233             void        *event_info)
1234 {
1235    Elm_Gen_Item *it = data;
1236    Evas_Event_Multi_Move *ev = event_info;
1237
1238    if (it->wd->multi_device != ev->device) return;
1239    it->wd->cur_mx = ev->cur.canvas.x;
1240    it->wd->cur_my = ev->cur.canvas.y;
1241 }
1242
1243 static void
1244 _mouse_down(void        *data,
1245             Evas        *evas __UNUSED__,
1246             Evas_Object *obj,
1247             void        *event_info)
1248 {
1249    Elm_Gen_Item *it = data;
1250    Evas_Event_Mouse_Down *ev = event_info;
1251    Evas_Coord x, y;
1252
1253    if (ev->button != 1) return;
1254    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1255      {
1256         it->wd->on_hold = EINA_TRUE;
1257      }
1258
1259    it->down = EINA_TRUE;
1260    it->dragging = EINA_FALSE;
1261    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1262    it->dx = ev->canvas.x - x;
1263    it->dy = ev->canvas.y - y;
1264    it->wd->mouse_down = EINA_TRUE;
1265    if (!it->wd->multitouched)
1266      {
1267         it->wd->prev_x = ev->canvas.x;
1268         it->wd->prev_y = ev->canvas.y;
1269         it->wd->multi_timeout = EINA_FALSE;
1270         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1271         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1272      }
1273    it->wd->longpressed = EINA_FALSE;
1274    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1275    else it->wd->on_hold = EINA_FALSE;
1276    if (it->wd->on_hold) return;
1277    it->wd->wasselected = it->selected;
1278    _item_highlight(it);
1279    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1280      if ((!elm_widget_item_disabled_get(it)) && (!it->display_only))
1281        {
1282           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1283           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1284        }
1285    if (it->long_timer) ecore_timer_del(it->long_timer);
1286    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1287    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1288    if (it->realized)
1289      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1290                                       it);
1291    else
1292      it->long_timer = NULL;
1293    it->wd->swipe = EINA_FALSE;
1294    it->wd->movements = 0;
1295 }
1296
1297 static void
1298 _mouse_up(void        *data,
1299           Evas        *evas __UNUSED__,
1300           Evas_Object *obj __UNUSED__,
1301           void        *event_info)
1302 {
1303    Elm_Gen_Item *it = data;
1304    Evas_Event_Mouse_Up *ev = event_info;
1305    Eina_Bool dragged = EINA_FALSE;
1306
1307    if (ev->button != 1) return;
1308    it->down = EINA_FALSE;
1309    it->wd->mouse_down = EINA_FALSE;
1310    if (it->wd->multitouched)
1311      {
1312         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1313         if (it->wd->multi_down) return;
1314         _multi_touch_gesture_eval(data);
1315         return;
1316      }
1317    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1318    else it->wd->on_hold = EINA_FALSE;
1319    if (it->long_timer)
1320      {
1321         ecore_timer_del(it->long_timer);
1322         it->long_timer = NULL;
1323      }
1324    if (it->dragging)
1325      {
1326         it->dragging = EINA_FALSE;
1327         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1328         dragged = 1;
1329      }
1330    if (it->item->swipe_timer)
1331      {
1332         ecore_timer_del(it->item->swipe_timer);
1333         it->item->swipe_timer = NULL;
1334      }
1335    if (it->wd->multi_timer)
1336      {
1337         ecore_timer_del(it->wd->multi_timer);
1338         it->wd->multi_timer = NULL;
1339         it->wd->multi_timeout = EINA_FALSE;
1340      }
1341    if (it->wd->on_hold)
1342      {
1343         if (it->wd->swipe) _swipe(data);
1344         it->wd->longpressed = EINA_FALSE;
1345         it->wd->on_hold = EINA_FALSE;
1346         return;
1347      }
1348    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1349      {
1350         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1351
1352         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1353           {
1354              if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1355                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1356              else
1357                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1358           }
1359         else
1360           {
1361              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1362              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1363           }
1364         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1365         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1366         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1367         elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1368      }
1369    if (it->wd->longpressed)
1370      {
1371         it->wd->longpressed = EINA_FALSE;
1372         if (!it->wd->wasselected)
1373           {
1374              _item_unhighlight(it);
1375              _item_unselect(it);
1376           }
1377         it->wd->wasselected = EINA_FALSE;
1378         return;
1379      }
1380    if (dragged)
1381      {
1382         if (it->want_unrealize)
1383           {
1384              _elm_genlist_item_unrealize(it, EINA_FALSE);
1385              if (it->item->block->want_unrealize)
1386                _item_block_unrealize(it->item->block);
1387           }
1388      }
1389    if (elm_widget_item_disabled_get(it) || (dragged) || (it->display_only))
1390      return;
1391    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1392    if (it->wd->multi)
1393      {
1394         if (!it->selected)
1395           {
1396              _item_highlight(it);
1397              it->sel_cb(it);
1398           }
1399         else
1400           {
1401              _item_unhighlight(it);
1402              _item_unselect(it);
1403           }
1404      }
1405    else
1406      {
1407         if (!it->selected)
1408           {
1409              Widget_Data *wd = it->wd;
1410              if (wd)
1411                {
1412                   while (wd->selected)
1413                     {
1414                        _item_unhighlight(wd->selected->data);
1415                        _item_unselect(wd->selected->data);
1416                     }
1417                }
1418           }
1419         else
1420           {
1421              const Eina_List *l, *l_next;
1422              Elm_Gen_Item *it2;
1423
1424              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1425                if (it2 != it)
1426                   {
1427                      _item_unhighlight(it2);
1428                      _item_unselect(it2);
1429                   }
1430              //_item_highlight(it);
1431              //_item_select(it);
1432           }
1433         _item_highlight(it);
1434         it->sel_cb(it);
1435      }
1436 }
1437
1438 static void
1439 _signal_expand_toggle(void        *data,
1440                       Evas_Object *obj __UNUSED__,
1441                       const char  *emission __UNUSED__,
1442                       const char  *source __UNUSED__)
1443 {
1444    Elm_Gen_Item *it = data;
1445
1446    if (it->item->expanded)
1447      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1448    else
1449      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1450 }
1451
1452 static void
1453 _signal_expand(void        *data,
1454                Evas_Object *obj __UNUSED__,
1455                const char  *emission __UNUSED__,
1456                const char  *source __UNUSED__)
1457 {
1458    Elm_Gen_Item *it = data;
1459
1460    if (!it->item->expanded)
1461      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1462 }
1463
1464 static void
1465 _signal_contract(void        *data,
1466                  Evas_Object *obj __UNUSED__,
1467                  const char  *emission __UNUSED__,
1468                  const char  *source __UNUSED__)
1469 {
1470    Elm_Gen_Item *it = data;
1471
1472    if (it->item->expanded)
1473      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1474 }
1475
1476 static Eina_Bool
1477 _scr_hold_timer_cb(void *data)
1478 {
1479    if (!data) return ECORE_CALLBACK_CANCEL;
1480    Widget_Data *wd = data;
1481    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1482    wd->scr_hold_timer = NULL;
1483    return ECORE_CALLBACK_CANCEL;
1484 }
1485
1486 static void
1487 _mode_finished_signal_cb(void        *data,
1488                          Evas_Object *obj,
1489                          const char  *emission __UNUSED__,
1490                          const char  *source __UNUSED__)
1491 {
1492    if (!data) return;
1493    if (!obj) return;
1494    Elm_Gen_Item *it = data;
1495    if ((it->generation < it->wd->generation) || (!it->realized) || (!it->item->mode_view)) return;
1496    char buf[1024];
1497    Evas *te = evas_object_evas_get(obj);
1498
1499    evas_event_freeze(te);
1500    it->item->nocache = EINA_FALSE;
1501    _mode_item_unrealize(it);
1502    if (it->item->group_item)
1503      evas_object_raise(it->item->VIEW(group_item));
1504    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type);
1505    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1506    evas_event_thaw(te);
1507    evas_event_thaw_eval(te);
1508 }
1509
1510 static void
1511 _item_cache_clean(Widget_Data *wd)
1512 {
1513    evas_event_freeze(evas_object_evas_get(wd->obj));
1514    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1515      {
1516         Item_Cache *itc;
1517
1518         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1519         wd->item_cache = eina_inlist_remove(wd->item_cache,
1520                                             wd->item_cache->last);
1521         wd->item_cache_count--;
1522         if (itc->spacer) evas_object_del(itc->spacer);
1523         if (itc->base_view) evas_object_del(itc->base_view);
1524         if (itc->item_style) eina_stringshare_del(itc->item_style);
1525         free(itc);
1526      }
1527    evas_event_thaw(evas_object_evas_get(wd->obj));
1528    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1529 }
1530
1531 static void
1532 _item_cache_zero(Widget_Data *wd)
1533 {
1534    int pmax = wd->item_cache_max;
1535    wd->item_cache_max = 0;
1536    _item_cache_clean(wd);
1537    wd->item_cache_max = pmax;
1538 }
1539
1540 static void
1541 _item_cache_add(Elm_Gen_Item *it)
1542 {
1543    Item_Cache *itc;
1544
1545    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1546    if (it->wd->item_cache_max <= 0)
1547      {
1548         evas_object_del(VIEW(it));
1549         VIEW(it) = NULL;
1550         evas_object_del(it->spacer);
1551         it->spacer = NULL;
1552         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1553         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1554         return;
1555      }
1556
1557    it->wd->item_cache_count++;
1558    itc = calloc(1, sizeof(Item_Cache));
1559    if (!itc)
1560      {
1561         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1562         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1563         return;
1564      }
1565    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1566                                             EINA_INLIST_GET(itc));
1567    itc->spacer = it->spacer;
1568    it->spacer = NULL;
1569    itc->base_view = VIEW(it);
1570    VIEW(it) = NULL;
1571    edje_object_signal_emit(itc->base_view, "elm,state,unselected", "elm");
1572    evas_object_hide(itc->base_view);
1573    evas_object_move(itc->base_view, -9999, -9999);
1574    itc->item_style = eina_stringshare_add(it->itc->item_style);
1575    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) itc->tree = 1;
1576    itc->compress = (it->wd->compress);
1577    itc->selected = it->selected;
1578    itc->disabled = elm_widget_item_disabled_get(it);
1579    itc->expanded = it->item->expanded;
1580    if (it->long_timer)
1581      {
1582         ecore_timer_del(it->long_timer);
1583         it->long_timer = NULL;
1584      }
1585    if (it->item->swipe_timer)
1586      {
1587         ecore_timer_del(it->item->swipe_timer);
1588         it->item->swipe_timer = NULL;
1589      }
1590    // FIXME: other callbacks?
1591    edje_object_signal_callback_del_full(itc->base_view,
1592                                         "elm,action,expand,toggle",
1593                                         "elm", _signal_expand_toggle, it);
1594    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1595                                         "elm",
1596                                         _signal_expand, it);
1597    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1598                                         "elm", _signal_contract, it);
1599    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
1600                                        _mouse_down, it);
1601    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
1602                                        _mouse_up, it);
1603    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
1604                                        _mouse_move, it);
1605    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
1606                                        _multi_down, it);
1607    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
1608                                        _multi_up, it);
1609    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
1610                                        _multi_move, it);
1611    _item_cache_clean(it->wd);
1612    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1613    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1614 }
1615
1616 static Item_Cache *
1617 _item_cache_find(Elm_Gen_Item *it)
1618 {
1619    Item_Cache *itc;
1620    Eina_Bool tree = 0;
1621
1622    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) tree = 1;
1623    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1624      {
1625         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1626           continue;
1627         if ((itc->tree == tree) &&
1628             (itc->compress == it->wd->compress) &&
1629             (!strcmp(it->itc->item_style, itc->item_style)))
1630           {
1631              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1632                                                      EINA_INLIST_GET(itc));
1633              it->wd->item_cache_count--;
1634              return itc;
1635           }
1636      }
1637    return NULL;
1638 }
1639
1640 static void
1641 _elm_genlist_item_index_update(Elm_Gen_Item *it)
1642 {
1643    if (it->position_update || it->item->block->position_update)
1644      {
1645         evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
1646         it->position_update = EINA_FALSE;
1647      }
1648 }
1649
1650 static void
1651 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1652 {
1653    if (!it->item->nostacking)
1654      {
1655         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1656           {
1657              if (it->edit_obj) evas_object_lower(it->edit_obj);
1658              else evas_object_lower(VIEW(it));
1659           }
1660         else
1661           {
1662              if (it->edit_obj) evas_object_raise(it->edit_obj);
1663              else evas_object_raise(VIEW(it));
1664           }
1665      }
1666
1667    if (it->item->order_num_in & 0x1)
1668      {
1669         edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1670         if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,odd", "elm");
1671      }
1672    else
1673      {
1674         edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1675         if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,even", "elm");
1676      }
1677 }
1678
1679 static void
1680 _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1681 {
1682    if (itc)
1683      {
1684         if (it->selected != itc->selected)
1685           {
1686              if (it->selected)
1687                edje_object_signal_emit(VIEW(it),
1688                                        "elm,state,selected", "elm");
1689
1690              if (it->edit_obj)
1691                edje_object_signal_emit(it->edit_obj,
1692                                        "elm,state,selected", "elm");
1693           }
1694         if (elm_widget_item_disabled_get(it) != itc->disabled)
1695           {
1696              if (elm_widget_item_disabled_get(it))
1697                edje_object_signal_emit(VIEW(it),
1698                                        "elm,state,disabled", "elm");
1699              if (it->edit_obj)
1700                edje_object_signal_emit(it->edit_obj,
1701                                        "elm,state,disabled", "elm");
1702           }
1703         if (it->item->expanded != itc->expanded)
1704           {
1705              if (it->item->expanded)
1706                edje_object_signal_emit(VIEW(it),
1707                                        "elm,state,expanded", "elm");
1708              if (it->edit_obj)
1709                edje_object_signal_emit(it->edit_obj,
1710                                        "elm,state,expanded", "elm");
1711           }
1712      }
1713    else
1714      {
1715         if (it->selected)
1716           {
1717              edje_object_signal_emit(VIEW(it),
1718                                      "elm,state,selected", "elm");
1719              if (it->edit_obj)
1720                edje_object_signal_emit(it->edit_obj,
1721                                        "elm,state,selected", "elm");
1722           }
1723
1724         if (elm_widget_item_disabled_get(it))
1725           {
1726              edje_object_signal_emit(VIEW(it),
1727                                      "elm,state,disabled", "elm");
1728              if (it->edit_obj)
1729                edje_object_signal_emit(it->edit_obj,
1730                                        "elm,state,disabled", "elm");
1731           }
1732         if (it->item->expanded)
1733           {
1734              edje_object_signal_emit(VIEW(it),
1735                                      "elm,state,expanded", "elm");
1736              if (it->edit_obj)
1737                edje_object_signal_emit(it->edit_obj,
1738                                        "elm,state,expanded", "elm");
1739           }
1740      }
1741 }
1742
1743 static void
1744 _item_cache_free(Item_Cache *itc)
1745 {
1746    if (itc->spacer) evas_object_del(itc->spacer);
1747    if (itc->base_view) evas_object_del(itc->base_view);
1748    if (itc->item_style) eina_stringshare_del(itc->item_style);
1749    free(itc);
1750 }
1751
1752 static void
1753 _item_text_realize(Elm_Gen_Item *it,
1754                     Evas_Object *target,
1755                     Eina_List **source,
1756                     const char *parts)
1757 {
1758    if (it->itc->func.text_get)
1759      {
1760         const Eina_List *l;
1761         const char *key;
1762
1763         *source = elm_widget_stringlist_get(edje_object_data_get(target, "texts"));
1764         EINA_LIST_FOREACH(*source, l, key)
1765           {
1766              if (parts && fnmatch(parts, key, FNM_PERIOD))
1767                continue;
1768
1769              char *s = it->itc->func.text_get
1770                 ((void *)it->base.data, WIDGET(it), key);
1771
1772              if (s)
1773                {
1774                   edje_object_part_text_set(target, key, s);
1775                   free(s);
1776                }
1777              else
1778                {
1779                   edje_object_part_text_set(target, key, "");
1780                }
1781           }
1782      }
1783 }
1784
1785 static Eina_List *
1786 _item_content_unrealize(Elm_Gen_Item *it,
1787                    Evas_Object *target,
1788                    Eina_List **source,
1789                    const char *parts)
1790 {
1791    Eina_List *res = it->content_objs;
1792
1793    if (it->itc->func.content_get)
1794      {
1795         const Eina_List *l;
1796         const char *key;
1797         Evas_Object *ic = NULL;
1798
1799         EINA_LIST_FOREACH(*source, l, key)
1800           {
1801              if (parts && fnmatch(parts, key, FNM_PERIOD))
1802                continue;
1803
1804              ic = edje_object_part_swallow_get(target, key);
1805              if (ic)
1806                {
1807                   res = eina_list_remove(res, ic);
1808                   edje_object_part_unswallow(target, ic);
1809                   evas_object_del(ic);
1810                }
1811           }
1812      }
1813
1814    return res;
1815 }
1816
1817 static Eina_List *
1818 _item_content_realize(Elm_Gen_Item *it,
1819                    Evas_Object *target,
1820                    Eina_List **source,
1821                    const char *parts)
1822 {
1823    Eina_List *res = NULL;
1824
1825    if (it->itc->func.content_get)
1826      {
1827         const Eina_List *l;
1828         const char *key;
1829         Evas_Object *ic = NULL;
1830
1831         *source = elm_widget_stringlist_get(edje_object_data_get(target, "contents"));
1832
1833         if (parts && (eina_list_count(*source) != eina_list_count(it->content_objs)))
1834           res = it->content_objs;
1835
1836         EINA_LIST_FOREACH(*source, l, key)
1837           {
1838              if (parts && fnmatch(parts, key, FNM_PERIOD))
1839                continue;
1840
1841              if (it->itc->func.content_get)
1842                ic = it->itc->func.content_get
1843                   ((void *)it->base.data, WIDGET(it), key);
1844              if (ic)
1845                {
1846                   res = eina_list_append(res, ic);
1847                   edje_object_part_swallow(target, key, ic);
1848                   evas_object_show(ic);
1849                   elm_widget_sub_object_add(WIDGET(it), ic);
1850                   if (elm_widget_item_disabled_get(it))
1851                     elm_widget_disabled_set(ic, EINA_TRUE);
1852                }
1853           }
1854      }
1855
1856    return res;
1857 }
1858
1859 static void
1860 _item_state_realize(Elm_Gen_Item *it,
1861                     Evas_Object *target,
1862                     Eina_List **source,
1863                     const char *parts)
1864 {
1865    if (it->itc->func.state_get)
1866      {
1867         const Eina_List *l;
1868         const char *key;
1869         char buf[4096];
1870
1871         *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
1872         EINA_LIST_FOREACH(*source, l, key)
1873           {
1874              if (parts && fnmatch(parts, key, FNM_PERIOD))
1875                continue;
1876
1877              Eina_Bool on = it->itc->func.state_get
1878                 ((void *)it->base.data, WIDGET(it), key);
1879
1880              if (on)
1881                {
1882                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1883                   edje_object_signal_emit(target, buf, "elm");
1884                }
1885              else
1886                {
1887                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
1888                   edje_object_signal_emit(target, buf, "elm");
1889                }
1890           }
1891      }
1892 }
1893
1894 static void
1895 _item_realize(Elm_Gen_Item *it,
1896               int               in,
1897               Eina_Bool         calc)
1898 {
1899    const char *treesize;
1900    char buf[1024];
1901    int tsize = 20;
1902    Item_Cache *itc = NULL;
1903
1904    if (it->generation < it->wd->generation) return;
1905    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
1906    if (it->realized)
1907      {
1908         if (it->item->order_num_in != in)
1909           {
1910              it->item->order_num_in = in;
1911              _elm_genlist_item_odd_even_update(it);
1912              _elm_genlist_item_state_update(it, NULL);
1913              _elm_genlist_item_index_update(it);
1914           }
1915         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1916         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1917         return;
1918      }
1919    it->item->order_num_in = in;
1920
1921    if (it->item->nocache)
1922      it->item->nocache = EINA_FALSE;
1923    else
1924      itc = _item_cache_find(it);
1925    if (itc)
1926      {
1927         VIEW(it) = itc->base_view;
1928         itc->base_view = NULL;
1929         it->spacer = itc->spacer;
1930         itc->spacer = NULL;
1931      }
1932    else
1933      {
1934         const char *stacking_even;
1935         const char *stacking;
1936
1937         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
1938         edje_object_scale_set(VIEW(it),
1939                               elm_widget_scale_get(WIDGET(it)) *
1940                               _elm_config->scale);
1941         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
1942         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
1943
1944         if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS)
1945           strncpy(buf, "tree", sizeof(buf));
1946         else strncpy(buf, "item", sizeof(buf));
1947         if (it->wd->compress)
1948           strncat(buf, "_compress", sizeof(buf) - strlen(buf));
1949
1950         strncat(buf, "/", sizeof(buf) - strlen(buf));
1951         strncat(buf, it->itc->item_style, sizeof(buf) - strlen(buf));
1952
1953         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
1954                               elm_widget_style_get(WIDGET(it)));
1955
1956         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1957         if (!stacking_even) stacking_even = "above";
1958         it->item->stacking_even = !!strcmp("above", stacking_even);
1959
1960         stacking = edje_object_data_get(VIEW(it), "stacking");
1961         if (!stacking) stacking = "yes";
1962         it->item->nostacking = !!strcmp("yes", stacking);
1963
1964         edje_object_mirrored_set(VIEW(it),
1965                                  elm_widget_mirrored_get(WIDGET(it)));
1966         it->spacer =
1967           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1968         evas_object_color_set(it->spacer, 0, 0, 0, 0);
1969         elm_widget_sub_object_add(WIDGET(it), it->spacer);
1970      }
1971
1972    _elm_genlist_item_odd_even_update(it);
1973
1974    treesize = edje_object_data_get(VIEW(it), "treesize");
1975    if (treesize) tsize = atoi(treesize);
1976    evas_object_size_hint_min_set(it->spacer,
1977                                  (it->item->expanded_depth * tsize) * _elm_config->scale, 1);
1978    edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1979    if (!calc)
1980      {
1981         edje_object_signal_callback_add(VIEW(it),
1982                                         "elm,action,expand,toggle",
1983                                         "elm", _signal_expand_toggle, it);
1984         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
1985                                         "elm", _signal_expand, it);
1986         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
1987                                         "elm", _signal_contract, it);
1988         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1989                                        _mouse_down, it);
1990         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1991                                        _mouse_up, it);
1992         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1993                                        _mouse_move, it);
1994         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
1995                                        _multi_down, it);
1996         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_UP,
1997                                        _multi_up, it);
1998         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
1999                                        _multi_move, it);
2000
2001         if ((it->wd->edit_mode) && (!it->edit_obj) &&
2002             (it->item->flags != ELM_GENLIST_ITEM_GROUP) && (it->itc->edit_item_style))
2003           _edit_mode_item_realize(it, EINA_FALSE);
2004
2005         _elm_genlist_item_state_update(it, itc);
2006         _elm_genlist_item_index_update(it);
2007      }
2008
2009    if ((calc) && (it->wd->homogeneous) &&
2010        ((it->wd->item_width) ||
2011         ((it->wd->item_width) && (it->wd->group_item_width))))
2012      {
2013         /* homogenous genlist shortcut */
2014         if (!it->item->mincalcd)
2015           {
2016              if (it->group)
2017                {
2018                   it->item->w = it->item->minw = it->wd->group_item_width;
2019                   it->item->h = it->item->minh = it->wd->group_item_height;
2020                }
2021              else
2022                {
2023                   it->item->w = it->item->minw = it->wd->item_width;
2024                   it->item->h = it->item->minh = it->wd->item_height;
2025                }
2026              it->item->mincalcd = EINA_TRUE;
2027           }
2028      }
2029    else
2030      {
2031         /* FIXME: If you see that assert, please notify us and we
2032            will clean our mess */
2033         assert(eina_list_count(it->content_objs) == 0);
2034
2035         _item_text_realize(it, VIEW(it), &it->texts, NULL);
2036         it->content_objs = _item_content_realize(it, VIEW(it), &it->contents, NULL);
2037         _item_state_realize(it, VIEW(it), &it->states, NULL);
2038
2039         if (!it->item->mincalcd)
2040           {
2041              Evas_Coord mw = -1, mh = -1;
2042
2043              if (!it->display_only)
2044                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2045              if (it->wd->height_for_width) mw = it->wd->prev_viewport_w;
2046              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
2047                                                   mh);
2048              if (!it->display_only)
2049                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2050              it->item->w = it->item->minw = mw;
2051              it->item->h = it->item->minh = mh;
2052              it->item->mincalcd = EINA_TRUE;
2053
2054              if ((!it->wd->group_item_width) && (it->group))
2055                {
2056                   it->wd->group_item_width = mw;
2057                   it->wd->group_item_height = mh;
2058                }
2059              else if ((!it->wd->item_width) && (it->item->flags == ELM_GENLIST_ITEM_NONE))
2060                {
2061                   it->wd->item_width = mw;
2062                   it->wd->item_height = mh;
2063                }
2064           }
2065         if (!calc) evas_object_show(VIEW(it));
2066      }
2067
2068    if (it->tooltip.content_cb)
2069      {
2070         elm_widget_item_tooltip_content_cb_set(it,
2071                                                it->tooltip.content_cb,
2072                                                it->tooltip.data, NULL);
2073         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
2074         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
2075      }
2076
2077    if (it->mouse_cursor)
2078      elm_widget_item_cursor_set(it, it->mouse_cursor);
2079
2080    it->realized = EINA_TRUE;
2081    it->want_unrealize = EINA_FALSE;
2082
2083    if (itc) _item_cache_free(itc);
2084    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2085    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2086    if (!calc)
2087      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
2088
2089    if ((!calc) && (it->wd->edit_mode) && (it->item->flags != ELM_GENLIST_ITEM_GROUP))
2090      {
2091         if (it->itc->edit_item_style)
2092           {
2093              if (!it->edit_obj) _edit_mode_item_realize(it, EINA_FALSE);
2094              edje_object_message_signal_process(it->edit_obj);
2095           }
2096      }
2097    edje_object_message_signal_process(VIEW(it));
2098 }
2099
2100 static void
2101 _item_unrealize_cb(Elm_Gen_Item *it)
2102 {
2103    if (it->item->nocache)
2104      {
2105         evas_object_del(VIEW(it));
2106         VIEW(it) = NULL;
2107         evas_object_del(it->spacer);
2108         it->spacer = NULL;
2109      }
2110    else
2111      {
2112         edje_object_mirrored_set(VIEW(it),
2113                                  elm_widget_mirrored_get(WIDGET(it)));
2114         edje_object_scale_set(VIEW(it),
2115                               elm_widget_scale_get(WIDGET(it))
2116                               * _elm_config->scale);
2117         _item_cache_add(it);
2118      }
2119
2120    _mode_item_unrealize(it);
2121    it->states = NULL;
2122    it->realized = EINA_FALSE;
2123    it->want_unrealize = EINA_FALSE;
2124    if (it->wd->edit_mode) _edit_mode_item_unrealize(it);
2125 }
2126
2127 static Eina_Bool
2128 _item_block_recalc(Item_Block *itb,
2129                    int         in,
2130                    Eina_Bool   qadd)
2131 {
2132    const Eina_List *l;
2133    Elm_Gen_Item *it;
2134    Evas_Coord minw = 0, minh = 0;
2135    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
2136    Evas_Coord y = 0;
2137
2138    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2139    itb->num = in;
2140    EINA_LIST_FOREACH(itb->items, l, it)
2141      {
2142         if (it->generation < it->wd->generation) continue;
2143         showme |= it->item->showme;
2144         if (!itb->realized)
2145           {
2146              if (qadd)
2147                {
2148                   if (!it->item->mincalcd) changed = EINA_TRUE;
2149                   if (changed)
2150                     {
2151                        _item_realize(it, in, EINA_TRUE);
2152                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2153                     }
2154                }
2155              else
2156                {
2157                   _item_realize(it, in, EINA_TRUE);
2158                   _elm_genlist_item_unrealize(it, EINA_TRUE);
2159                }
2160           }
2161         else
2162           _item_realize(it, in, EINA_FALSE);
2163         minh += it->item->minh;
2164         if (minw < it->item->minw) minw = it->item->minw;
2165         in++;
2166         it->x = 0;
2167         it->y = y;
2168         y += it->item->h;
2169      }
2170    itb->minw = minw;
2171    itb->minh = minh;
2172    itb->changed = EINA_FALSE;
2173    itb->position_update = EINA_FALSE;
2174    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2175    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2176    return showme;
2177 }
2178
2179 static void
2180 _item_block_realize(Item_Block *itb)
2181 {
2182    if (itb->realized) return;
2183    itb->realized = EINA_TRUE;
2184    itb->want_unrealize = EINA_FALSE;
2185 }
2186
2187 static void
2188 _item_block_unrealize(Item_Block *itb)
2189 {
2190    const Eina_List *l;
2191    Elm_Gen_Item *it;
2192    Eina_Bool dragging = EINA_FALSE;
2193
2194    if (!itb->realized) return;
2195    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2196    EINA_LIST_FOREACH(itb->items, l, it)
2197      {
2198         if (itb->must_recalc || !it->group)
2199           {
2200              if (it->dragging)
2201                {
2202                   dragging = EINA_TRUE;
2203                   it->want_unrealize = EINA_TRUE;
2204                }
2205              else
2206                _elm_genlist_item_unrealize(it, EINA_FALSE);
2207           }
2208      }
2209    if (!dragging)
2210      {
2211         itb->realized = EINA_FALSE;
2212         itb->want_unrealize = EINA_TRUE;
2213      }
2214    else
2215      itb->want_unrealize = EINA_FALSE;
2216    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2217    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2218 }
2219
2220 static int
2221 _get_space_for_reorder_item(Elm_Gen_Item *it)
2222 {
2223    Evas_Coord rox, roy, row, roh, oy, oh;
2224    Eina_Bool top = EINA_FALSE;
2225    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2226    if (!reorder_it) return 0;
2227
2228    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2229    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2230
2231    if ((it->wd->reorder_start_y < it->item->block->y) &&
2232        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2233      {
2234         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2235         if (it->item->block->count == 1)
2236           it->wd->reorder_rel = it;
2237      }
2238    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2239             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2240      {
2241         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2242      }
2243    else
2244      it->item->block->reorder_offset = 0;
2245
2246    it->item->scrl_y += it->item->block->reorder_offset;
2247
2248    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2249                               rox, roy + (roh / 2), row, 1));
2250    if (top)
2251      {
2252         it->wd->reorder_rel = it;
2253         it->item->scrl_y += it->wd->reorder_it->item->h;
2254         return it->wd->reorder_it->item->h;
2255      }
2256    else
2257      return 0;
2258 }
2259
2260 static Eina_Bool
2261 _reorder_move_animator_cb(void *data)
2262 {
2263    Elm_Gen_Item *it = data;
2264    Eina_Bool down = EINA_FALSE;
2265    double t;
2266    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2267
2268    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2269
2270    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2271    else y = dy;
2272
2273    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2274    if (diff > it->item->h) y = diff / 2;
2275
2276    if (it->item->old_scrl_y < it->item->scrl_y)
2277      {
2278         it->item->old_scrl_y += y;
2279         down = EINA_TRUE;
2280      }
2281    else if (it->item->old_scrl_y > it->item->scrl_y)
2282      {
2283         it->item->old_scrl_y -= y;
2284         down = EINA_FALSE;
2285      }
2286
2287    if (it->edit_obj)
2288      _item_position(it, it->edit_obj, it->item->scrl_x, it->item->old_scrl_y);
2289    else
2290      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2291    _group_items_recalc(it->wd);
2292
2293    if ((it->wd->reorder_pan_move) ||
2294        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2295        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2296      {
2297         it->item->old_scrl_y = it->item->scrl_y;
2298         it->item->move_effect_enabled = EINA_FALSE;
2299         it->wd->reorder_move_animator = NULL;
2300         return ECORE_CALLBACK_CANCEL;
2301      }
2302    return ECORE_CALLBACK_RENEW;
2303 }
2304
2305 static void
2306 _item_position(Elm_Gen_Item *it,
2307                Evas_Object      *view,
2308                Evas_Coord        it_x,
2309                Evas_Coord        it_y)
2310 {
2311    if (!it) return;
2312    if (!view) return;
2313
2314    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2315    evas_object_resize(view, it->item->w, it->item->h);
2316    evas_object_move(view, it_x, it_y);
2317    evas_object_show(view);
2318    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2319    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2320 }
2321
2322 static void
2323 _item_block_position(Item_Block *itb,
2324                      int         in)
2325 {
2326    const Eina_List *l;
2327    Elm_Gen_Item *it;
2328    Elm_Gen_Item *git;
2329    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2330    Eina_Bool vis = EINA_FALSE;
2331
2332    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2333    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2334    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2335                             &cvw, &cvh);
2336    EINA_LIST_FOREACH(itb->items, l, it)
2337      {
2338         if (it->generation < it->wd->generation) continue;
2339         else if (it->wd->reorder_it == it) continue;
2340         it->x = 0;
2341         it->y = y;
2342         it->item->w = itb->w;
2343         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2344         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2345
2346         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2347                                    cvx, cvy, cvw, cvh));
2348         if (!it->group)
2349           {
2350              if ((itb->realized) && (!it->realized))
2351                {
2352                   if (vis) _item_realize(it, in, EINA_FALSE);
2353                }
2354              if (it->realized)
2355                {
2356                   if (vis)
2357                     {
2358                        if (it->wd->reorder_mode)
2359                          y += _get_space_for_reorder_item(it);
2360                        git = it->item->group_item;
2361                        if (git)
2362                          {
2363                             if (git->item->scrl_y < oy)
2364                               git->item->scrl_y = oy;
2365                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2366                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2367                             git->item->want_realize = EINA_TRUE;
2368                          }
2369                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2370                          {
2371                             if (!it->item->move_effect_enabled)
2372                               {
2373                                  it->item->move_effect_enabled = EINA_TRUE;
2374                                  it->wd->reorder_move_animator =
2375                                     ecore_animator_add(
2376                                        _reorder_move_animator_cb, it);
2377                               }
2378                          }
2379                        if (!it->item->move_effect_enabled)
2380                          {
2381                             if ((it->wd->edit_mode) && (it->itc->edit_item_style))
2382                               _edit_mode_item_position(it, it->item->scrl_x,
2383                                                        it->item->scrl_y);
2384                             else
2385                               {
2386                                  if (it->item->mode_view)
2387                                    _item_position(it, it->item->mode_view,
2388                                                   it->item->scrl_x,
2389                                                   it->item->scrl_y);
2390                                  else
2391                                    _item_position(it, VIEW(it), it->item->scrl_x,
2392                                                   it->item->scrl_y);
2393                               }
2394                             it->item->old_scrl_y = it->item->scrl_y;
2395                          }
2396                     }
2397                   else
2398                     {
2399                        if (!it->dragging) _elm_genlist_item_unrealize(it, EINA_FALSE);
2400                     }
2401                }
2402              in++;
2403           }
2404         else
2405           {
2406              if (vis) it->item->want_realize = EINA_TRUE;
2407           }
2408         y += it->item->h;
2409      }
2410    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2411    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2412 }
2413
2414 static void
2415 _group_items_recalc(void *data)
2416 {
2417    Widget_Data *wd = data;
2418    Eina_List *l;
2419    Elm_Gen_Item *git;
2420
2421    evas_event_freeze(evas_object_evas_get(wd->obj));
2422    EINA_LIST_FOREACH(wd->group_items, l, git)
2423      {
2424         if (git->item->want_realize)
2425           {
2426              if (!git->realized)
2427                _item_realize(git, 0, EINA_FALSE);
2428              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2429              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2430              evas_object_show(VIEW(git));
2431              evas_object_raise(VIEW(git));
2432           }
2433         else if (!git->item->want_realize && git->realized)
2434           {
2435              if (!git->dragging)
2436                _elm_genlist_item_unrealize(git, EINA_FALSE);
2437           }
2438      }
2439    evas_event_thaw(evas_object_evas_get(wd->obj));
2440    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2441 }
2442
2443 static Eina_Bool
2444 _must_recalc_idler(void *data)
2445 {
2446    Widget_Data *wd = data;
2447    if (wd->calc_job) ecore_job_del(wd->calc_job);
2448    wd->calc_job = ecore_job_add(_calc_job, wd);
2449    wd->must_recalc_idler = NULL;
2450    return ECORE_CALLBACK_CANCEL;
2451 }
2452
2453 static void
2454 _scroll_item(Widget_Data *wd)
2455 {
2456    Elm_Gen_Item *it = NULL;
2457    Evas_Coord gith = 0;
2458    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
2459
2460    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
2461    it = wd->show_item;
2462    dx = it->x + it->item->block->x;
2463    dy = it->y + it->item->block->y;
2464    dw = it->item->block->w;
2465    dh = oh;
2466    switch (wd->scrollto_type)
2467      {
2468       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2469          if (it->item->group_item) gith = it->item->group_item->item->h;
2470          dy -= gith;
2471          break;
2472       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2473          dy += (it->item->h / 2 - oh / 2);
2474          break;
2475       case ELM_GENLIST_ITEM_SCROLLTO_IN:
2476       default:
2477          if ((wd->expanded_item) &&
2478              ((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
2479               - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
2480            {
2481               it = wd->expanded_item;
2482               if (it->item->group_item) gith = it->item->group_item->item->h;
2483               dx = it->x + it->item->block->x;
2484               dy = it->y + it->item->block->y - gith;
2485               dw = it->item->block->w;
2486            }
2487          else
2488            {
2489               if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
2490                 gith = it->item->group_item->item->h;
2491               dy -= gith;
2492               dh = it->item->h;
2493            }
2494          break;
2495      }
2496    if (wd->bring_in)
2497      elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
2498    else
2499      elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
2500
2501    it->item->showme = EINA_FALSE;
2502    wd->show_item = NULL;
2503    wd->auto_scroll_enabled = EINA_FALSE;
2504    wd->check_scroll = EINA_FALSE;
2505 }
2506
2507 static void
2508 _calc_job(void *data)
2509 {
2510    Widget_Data *wd = data;
2511    Item_Block *itb, *chb = NULL;
2512    Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw;
2513    Evas_Coord pan_w = 0, pan_h = 0;
2514    int in = 0;
2515    Eina_Bool minw_change = EINA_FALSE;
2516    Eina_Bool did_must_recalc = EINA_FALSE;
2517    if (!wd) return;
2518
2519    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2520    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2521
2522    if (wd->w != ow)
2523      wd->w = ow;
2524
2525    evas_event_freeze(evas_object_evas_get(wd->obj));
2526    EINA_INLIST_FOREACH(wd->blocks, itb)
2527      {
2528         Eina_Bool showme = EINA_FALSE;
2529
2530         itb->num = in;
2531         showme = itb->showme;
2532         itb->showme = EINA_FALSE;
2533         if (chb)
2534           {
2535              if (itb->realized) _item_block_unrealize(itb);
2536           }
2537         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2538           {
2539              if (itb->must_recalc)
2540                {
2541                   Eina_List *l;
2542                   Elm_Gen_Item *it;
2543                   EINA_LIST_FOREACH(itb->items, l, it)
2544                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2545                   itb->changed = EINA_TRUE;
2546                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2547                   if (itb->realized) _item_block_unrealize(itb);
2548                   itb->must_recalc = EINA_FALSE;
2549                }
2550              showme = _item_block_recalc(itb, in, EINA_FALSE);
2551              chb = itb;
2552           }
2553         itb->y = y;
2554         itb->x = 0;
2555         minh += itb->minh;
2556         if (minw == -1) minw = itb->minw;
2557         else if ((!itb->must_recalc) && (minw < itb->minw))
2558           {
2559              minw = itb->minw;
2560              minw_change = EINA_TRUE;
2561           }
2562         if (minw > vw)
2563           {
2564              minw = vw;
2565              minw_change = EINA_TRUE;
2566           }
2567         itb->w = minw;
2568         itb->h = itb->minh;
2569         y += itb->h;
2570         in += itb->count;
2571         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2572           wd->check_scroll = EINA_TRUE;
2573      }
2574    if (minw_change)
2575      {
2576         EINA_INLIST_FOREACH(wd->blocks, itb)
2577           {
2578              itb->minw = minw;
2579              itb->w = itb->minw;
2580           }
2581      }
2582    if ((chb) && (EINA_INLIST_GET(chb)->next))
2583      {
2584         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2585           {
2586              if (itb->realized) _item_block_unrealize(itb);
2587           }
2588      }
2589    wd->realminw = minw;
2590    if (minw < wd->w) minw = wd->w;
2591    if ((minw != wd->minw) || (minh != wd->minh))
2592      {
2593         wd->minw = minw;
2594         wd->minh = minh;
2595         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2596         _sizing_eval(wd->obj);
2597         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2598           {
2599              Elm_Gen_Item *it;
2600              Evas_Coord it_y;
2601
2602              it = wd->anchor_item;
2603              it_y = wd->anchor_y;
2604              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2605                                               it->item->block->y + it->y + it_y);
2606              wd->anchor_item = it;
2607              wd->anchor_y = it_y;
2608           }
2609      }
2610    if (did_must_recalc)
2611      {
2612         if (!wd->must_recalc_idler)
2613           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2614      }
2615    if (wd->check_scroll)
2616      {
2617         _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
2618         if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
2619           wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
2620        switch (wd->scrollto_type)
2621           {
2622            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2623               dy = wd->h;
2624               break;
2625            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2626               dy = wd->h / 2;
2627               break;
2628            case ELM_GENLIST_ITEM_SCROLLTO_IN:
2629            default:
2630               dy = 0;
2631               break;
2632           }
2633         if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
2634             (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
2635           {
2636              _scroll_item(wd);
2637           }
2638      }
2639    wd->calc_job = NULL;
2640    evas_object_smart_changed(wd->pan_smart);
2641    evas_event_thaw(evas_object_evas_get(wd->obj));
2642    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2643 }
2644
2645 static void
2646 _update_job(void *data)
2647 {
2648    Widget_Data *wd = data;
2649    Eina_List *l2;
2650    Item_Block *itb;
2651    int num, num0;
2652    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2653    if (!wd) return;
2654    wd->update_job = NULL;
2655    num = 0;
2656
2657    evas_event_freeze(evas_object_evas_get(wd->obj));
2658    EINA_INLIST_FOREACH(wd->blocks, itb)
2659      {
2660         Evas_Coord itminw, itminh;
2661         Elm_Gen_Item *it;
2662
2663         if (!itb->updateme)
2664           {
2665              num += itb->count;
2666              if (position)
2667                _item_block_position(itb, num);
2668              continue;
2669           }
2670         num0 = num;
2671         recalc = EINA_FALSE;
2672         EINA_LIST_FOREACH(itb->items, l2, it)
2673           {
2674              if (it->item->updateme)
2675                {
2676                   itminw = it->item->minw;
2677                   itminh = it->item->minh;
2678
2679                   it->item->updateme = EINA_FALSE;
2680                   if (it->realized)
2681                     {
2682                        _elm_genlist_item_unrealize(it, EINA_FALSE);
2683                        _item_realize(it, num, EINA_FALSE);
2684                        position = EINA_TRUE;
2685                     }
2686                   else
2687                     {
2688                        _item_realize(it, num, EINA_TRUE);
2689                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2690                     }
2691                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
2692                     recalc = EINA_TRUE;
2693                }
2694              num++;
2695           }
2696         itb->updateme = EINA_FALSE;
2697         if (recalc)
2698           {
2699              position = EINA_TRUE;
2700              itb->changed = EINA_TRUE;
2701              _item_block_recalc(itb, num0, EINA_FALSE);
2702              _item_block_position(itb, num0);
2703           }
2704      }
2705    if (position)
2706      {
2707         if (wd->calc_job) ecore_job_del(wd->calc_job);
2708         wd->calc_job = ecore_job_add(_calc_job, wd);
2709      }
2710    evas_event_thaw(evas_object_evas_get(wd->obj));
2711    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2712 }
2713
2714 static void
2715 _pan_set(Evas_Object *obj,
2716          Evas_Coord   x,
2717          Evas_Coord   y)
2718 {
2719    Pan *sd = evas_object_smart_data_get(obj);
2720    Item_Block *itb;
2721
2722    if (!sd) return;
2723    //   Evas_Coord ow, oh;
2724    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2725    //   ow = sd->wd->minw - ow;
2726    //   if (ow < 0) ow = 0;
2727    //   oh = sd->wd->minh - oh;
2728    //   if (oh < 0) oh = 0;
2729    //   if (x < 0) x = 0;
2730    //   if (y < 0) y = 0;
2731    //   if (x > ow) x = ow;
2732    //   if (y > oh) y = oh;
2733    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2734    sd->wd->pan_x = x;
2735    sd->wd->pan_y = y;
2736
2737    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2738      {
2739         if ((itb->y + itb->h) > y)
2740           {
2741              Elm_Gen_Item *it;
2742              Eina_List *l2;
2743
2744              EINA_LIST_FOREACH(itb->items, l2, it)
2745                {
2746                   if ((itb->y + it->y) >= y)
2747                     {
2748                        sd->wd->anchor_item = it;
2749                        sd->wd->anchor_y = -(itb->y + it->y - y);
2750                        goto done;
2751                     }
2752                }
2753           }
2754      }
2755 done:
2756    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2757 }
2758
2759 static void
2760 _pan_get(Evas_Object *obj,
2761          Evas_Coord  *x,
2762          Evas_Coord  *y)
2763 {
2764    Pan *sd = evas_object_smart_data_get(obj);
2765
2766    if (!sd) return;
2767    if (x) *x = sd->wd->pan_x;
2768    if (y) *y = sd->wd->pan_y;
2769 }
2770
2771 static void
2772 _pan_max_get(Evas_Object *obj,
2773              Evas_Coord  *x,
2774              Evas_Coord  *y)
2775 {
2776    Pan *sd = evas_object_smart_data_get(obj);
2777    Evas_Coord ow, oh;
2778
2779    if (!sd) return;
2780    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2781    ow = sd->wd->minw - ow;
2782    if (ow < 0) ow = 0;
2783    oh = sd->wd->minh - oh;
2784    if (oh < 0) oh = 0;
2785    if (x) *x = ow;
2786    if (y) *y = oh;
2787 }
2788
2789 static void
2790 _pan_min_get(Evas_Object *obj __UNUSED__,
2791              Evas_Coord  *x,
2792              Evas_Coord  *y)
2793 {
2794    if (x) *x = 0;
2795    if (y) *y = 0;
2796 }
2797
2798 static void
2799 _pan_child_size_get(Evas_Object *obj,
2800                     Evas_Coord  *w,
2801                     Evas_Coord  *h)
2802 {
2803    Pan *sd = evas_object_smart_data_get(obj);
2804
2805    if (!sd) return;
2806    if (w) *w = sd->wd->minw;
2807    if (h) *h = sd->wd->minh;
2808 }
2809
2810 static void
2811 _pan_add(Evas_Object *obj)
2812 {
2813    Pan *sd;
2814    Evas_Object_Smart_Clipped_Data *cd;
2815
2816    _pan_sc.add(obj);
2817    cd = evas_object_smart_data_get(obj);
2818    sd = ELM_NEW(Pan);
2819    if (!sd) return;
2820    sd->__clipped_data = *cd;
2821    free(cd);
2822    evas_object_smart_data_set(obj, sd);
2823 }
2824
2825 static void
2826 _pan_del(Evas_Object *obj)
2827 {
2828    Pan *sd = evas_object_smart_data_get(obj);
2829
2830    if (!sd) return;
2831    if (sd->resize_job)
2832      {
2833         ecore_job_del(sd->resize_job);
2834         sd->resize_job = NULL;
2835      }
2836    _pan_sc.del(obj);
2837 }
2838
2839 static void
2840 _pan_resize_job(void *data)
2841 {
2842    Pan *sd = data;
2843    if (!sd) return;
2844    _sizing_eval(sd->wd->obj);
2845    sd->resize_job = NULL;
2846 }
2847
2848 static void
2849 _pan_resize(Evas_Object *obj,
2850             Evas_Coord   w,
2851             Evas_Coord   h)
2852 {
2853    Pan *sd = evas_object_smart_data_get(obj);
2854    Evas_Coord ow, oh;
2855
2856    if (!sd) return;
2857    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2858    if ((ow == w) && (oh == h)) return;
2859    if ((sd->wd->height_for_width) && (ow != w))
2860      {
2861         /* fix me later */
2862         if (sd->resize_job) ecore_job_del(sd->resize_job);
2863         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
2864      }
2865    sd->wd->pan_changed = EINA_TRUE;
2866    evas_object_smart_changed(obj);
2867    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2868    sd->wd->calc_job = NULL;
2869 /* OLD
2870    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2871    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2872  */
2873 }
2874
2875 static void
2876 _pan_calculate(Evas_Object *obj)
2877 {
2878    Pan *sd = evas_object_smart_data_get(obj);
2879    Item_Block *itb;
2880    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2881    int in = 0;
2882    Elm_Gen_Item *git;
2883    Eina_List *l;
2884
2885    if (!sd) return;
2886    evas_event_freeze(evas_object_evas_get(obj));
2887
2888    if (sd->wd->pan_changed)
2889      {
2890         _calc_job(sd->wd);
2891         sd->wd->pan_changed = EINA_FALSE;
2892      }
2893
2894    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2895    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2896    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
2897      {
2898         git->item->want_realize = EINA_FALSE;
2899      }
2900    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2901      {
2902         itb->w = sd->wd->minw;
2903         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
2904                                 itb->y - sd->wd->pan_y + oy,
2905                                 itb->w, itb->h,
2906                                 cvx, cvy, cvw, cvh))
2907           {
2908              if ((!itb->realized) || (itb->changed))
2909                _item_block_realize(itb);
2910              _item_block_position(itb, in);
2911           }
2912         else
2913           {
2914              if (itb->realized) _item_block_unrealize(itb);
2915           }
2916         in += itb->count;
2917      }
2918    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
2919       _group_items_recalc(sd->wd);
2920    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
2921      {
2922         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
2923            sd->wd->reorder_pan_move = EINA_TRUE;
2924         else sd->wd->reorder_pan_move = EINA_FALSE;
2925         evas_object_raise(sd->wd->VIEW(reorder_it));
2926         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
2927         sd->wd->start_time = ecore_loop_time_get();
2928      }
2929    _item_auto_scroll(sd->wd);
2930    evas_event_thaw(evas_object_evas_get(obj));
2931    evas_event_thaw_eval(evas_object_evas_get(obj));
2932 }
2933
2934 static void
2935 _pan_move(Evas_Object *obj,
2936           Evas_Coord   x __UNUSED__,
2937           Evas_Coord   y __UNUSED__)
2938 {
2939    Pan *sd = evas_object_smart_data_get(obj);
2940
2941    if (!sd) return;
2942
2943    sd->wd->pan_changed = EINA_TRUE;
2944    evas_object_smart_changed(obj);
2945    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2946    sd->wd->calc_job = NULL;
2947 }
2948
2949 static void
2950 _hold_on(void        *data __UNUSED__,
2951          Evas_Object *obj,
2952          void        *event_info __UNUSED__)
2953 {
2954    Widget_Data *wd = elm_widget_data_get(obj);
2955    if (!wd) return;
2956    elm_smart_scroller_hold_set(wd->scr, 1);
2957 }
2958
2959 static void
2960 _hold_off(void        *data __UNUSED__,
2961           Evas_Object *obj,
2962           void        *event_info __UNUSED__)
2963 {
2964    Widget_Data *wd = elm_widget_data_get(obj);
2965    if (!wd) return;
2966    elm_smart_scroller_hold_set(wd->scr, 0);
2967 }
2968
2969 static void
2970 _freeze_on(void        *data __UNUSED__,
2971            Evas_Object *obj,
2972            void        *event_info __UNUSED__)
2973 {
2974    Widget_Data *wd = elm_widget_data_get(obj);
2975    if (!wd) return;
2976    elm_smart_scroller_freeze_set(wd->scr, 1);
2977 }
2978
2979 static void
2980 _freeze_off(void        *data __UNUSED__,
2981             Evas_Object *obj,
2982             void        *event_info __UNUSED__)
2983 {
2984    Widget_Data *wd = elm_widget_data_get(obj);
2985    if (!wd) return;
2986    elm_smart_scroller_freeze_set(wd->scr, 0);
2987 }
2988
2989 static void
2990 _scr_anim_start(void        *data,
2991                 Evas_Object *obj __UNUSED__,
2992                 void        *event_info __UNUSED__)
2993 {
2994    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
2995 }
2996
2997 static void
2998 _scr_anim_stop(void        *data,
2999                Evas_Object *obj __UNUSED__,
3000                void        *event_info __UNUSED__)
3001 {
3002    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3003 }
3004
3005 static void
3006 _scr_drag_start(void            *data,
3007                 Evas_Object     *obj __UNUSED__,
3008                 void            *event_info __UNUSED__)
3009 {
3010    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3011 }
3012
3013 static void
3014 _scr_drag_stop(void            *data,
3015                Evas_Object     *obj __UNUSED__,
3016                void            *event_info __UNUSED__)
3017 {
3018    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3019 }
3020
3021 static void
3022 _edge_left(void        *data,
3023            Evas_Object *scr __UNUSED__,
3024            void        *event_info __UNUSED__)
3025 {
3026    Evas_Object *obj = data;
3027    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3028 }
3029
3030 static void
3031 _edge_right(void        *data,
3032             Evas_Object *scr __UNUSED__,
3033             void        *event_info __UNUSED__)
3034 {
3035    Evas_Object *obj = data;
3036    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3037 }
3038
3039 static void
3040 _edge_top(void        *data,
3041           Evas_Object *scr __UNUSED__,
3042           void        *event_info __UNUSED__)
3043 {
3044    Evas_Object *obj = data;
3045    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3046 }
3047
3048 static void
3049 _edge_bottom(void        *data,
3050              Evas_Object *scr __UNUSED__,
3051              void        *event_info __UNUSED__)
3052 {
3053    Evas_Object *obj = data;
3054    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3055 }
3056
3057 static void
3058 _mode_item_realize(Elm_Gen_Item *it)
3059 {
3060    char buf[1024];
3061
3062    if ((it->item->mode_view) || (it->generation < it->wd->generation)) return;
3063
3064    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3065    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3066    edje_object_scale_set(it->item->mode_view,
3067                          elm_widget_scale_get(WIDGET(it)) *
3068                          _elm_config->scale);
3069    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
3070    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
3071
3072    strncpy(buf, "item", sizeof(buf));
3073    if (it->wd->compress)
3074      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3075
3076    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3077    strncat(buf, "/", sizeof(buf) - strlen(buf));
3078    strncat(buf, it->itc->mode_item_style, sizeof(buf) - strlen(buf));
3079
3080    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
3081                          elm_widget_style_get(WIDGET(it)));
3082    edje_object_mirrored_set(it->item->mode_view,
3083                             elm_widget_mirrored_get(WIDGET(it)));
3084
3085    /* signal callback add */
3086    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
3087                                   _mouse_down, it);
3088    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
3089                                   _mouse_up, it);
3090    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
3091                                   _mouse_move, it);
3092
3093    /* text_get, content_get, state_get */
3094    /* FIXME: If you see that assert, please notify us and we
3095       will clean our mess */
3096    assert(eina_list_count(it->item->mode_content_objs) == 0);
3097
3098    _item_text_realize(it, it->item->mode_view, &it->item->mode_texts, NULL);
3099    it->item->mode_content_objs =
3100      _item_content_realize(it, it->item->mode_view,
3101                            &it->item->mode_contents, NULL);
3102    _item_state_realize(it, it->item->mode_view, &it->item->mode_states, NULL);
3103
3104    edje_object_part_swallow(it->item->mode_view,
3105                             edje_object_data_get(it->item->mode_view, "mode_part"),
3106                             VIEW(it));
3107
3108    it->want_unrealize = EINA_FALSE;
3109    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3110    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3111 }
3112
3113 static void
3114 _mode_item_unrealize(Elm_Gen_Item *it)
3115 {
3116    Widget_Data *wd = it->wd;
3117    Evas_Object *content;
3118    if (!it->item->mode_view) return;
3119
3120    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3121    elm_widget_stringlist_free(it->item->mode_texts);
3122    it->item->mode_texts = NULL;
3123    elm_widget_stringlist_free(it->item->mode_contents);
3124    it->item->mode_contents = NULL;
3125    elm_widget_stringlist_free(it->item->mode_states);
3126
3127    EINA_LIST_FREE(it->item->mode_content_objs, content)
3128      evas_object_del(content);
3129
3130    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
3131    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3132    evas_object_del(it->item->mode_view);
3133    it->item->mode_view = NULL;
3134
3135    if (wd->mode_item == it)
3136      wd->mode_item = NULL;
3137    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3138    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3139 }
3140
3141 static void
3142 _item_mode_set(Elm_Gen_Item *it)
3143 {
3144    if (!it) return;
3145    Widget_Data *wd = it->wd;
3146    if (!wd) return;
3147    char buf[1024];
3148
3149    wd->mode_item = it;
3150    it->item->nocache = EINA_TRUE;
3151
3152    if (wd->scr_hold_timer)
3153      {
3154         ecore_timer_del(wd->scr_hold_timer);
3155         wd->scr_hold_timer = NULL;
3156      }
3157    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3158    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3159
3160    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3161    _mode_item_realize(it);
3162    if (it->item->group_item)
3163      evas_object_raise(it->item->VIEW(group_item));
3164    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
3165    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3166    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3167
3168    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
3169    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3170 }
3171
3172 static void
3173 _item_mode_unset(Widget_Data *wd)
3174 {
3175    if (!wd) return;
3176    if (!wd->mode_item) return;
3177    char buf[1024], buf2[1024];
3178    Elm_Gen_Item *it;
3179
3180    it = wd->mode_item;
3181    it->item->nocache = EINA_TRUE;
3182
3183    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type);
3184    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type);
3185
3186    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3187    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
3188
3189    wd->mode_item = NULL;
3190 }
3191
3192 static void
3193 _edit_mode_item_position(Elm_Gen_Item *it, int itx, int ity)
3194 {
3195    if ((!it) || (!it->wd->edit_mode)) return;
3196    evas_object_resize(it->edit_obj, it->item->w, it->item->h);
3197    evas_object_move(it->edit_obj, itx, ity);
3198 }
3199
3200 static void
3201 _edit_mode_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3202 {
3203    char buf[1024];
3204    const char *stacking_even;
3205    const char *stacking;
3206
3207    if ((!it) || (it->item->edit_mode_item_realized) ||
3208        (it->generation < it->wd->generation))
3209      return;
3210
3211    it->edit_obj = edje_object_add(evas_object_evas_get(WIDGET(it)));
3212    edje_object_scale_set(it->edit_obj, elm_widget_scale_get(WIDGET(it)) *
3213                          _elm_config->scale);
3214    evas_object_smart_member_add(it->edit_obj, it->wd->pan_smart);
3215    elm_widget_sub_object_add(WIDGET(it), it->edit_obj);
3216
3217    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS)
3218       strncpy(buf, "tree", sizeof(buf));
3219    else strncpy(buf, "item", sizeof(buf));
3220    if (it->wd->compress)
3221       strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3222
3223    strncat(buf, "/", sizeof(buf) - strlen(buf));
3224    strncat(buf, it->itc->edit_item_style, sizeof(buf) - strlen(buf));
3225
3226    _elm_theme_object_set(WIDGET(it),  it->edit_obj, "genlist", buf,
3227                          elm_widget_style_get(WIDGET(it)));
3228
3229    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3230    if (!stacking_even) stacking_even = "above";
3231    it->item->stacking_even = !!strcmp("above", stacking_even);
3232
3233    stacking = edje_object_data_get(VIEW(it), "stacking");
3234    if (!stacking) stacking = "yes";
3235    it->item->nostacking = !!strcmp("yes", stacking);
3236
3237    edje_object_mirrored_set(it->edit_obj,
3238                             elm_widget_mirrored_get(WIDGET(it)));
3239
3240    _elm_genlist_item_odd_even_update(it);
3241    _elm_genlist_item_state_update(it, NULL);
3242
3243    if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,edit,enabled,effect", "elm");
3244    else edje_object_signal_emit(it->edit_obj, "elm,state,edit,enabled", "elm");
3245
3246    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MOUSE_DOWN,
3247                                   _mouse_down, it);
3248    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MOUSE_UP,
3249                                   _mouse_up, it);
3250    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MOUSE_MOVE,
3251                                   _mouse_move, it);
3252    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MULTI_DOWN,
3253                                   _multi_down, it);
3254    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MULTI_UP,
3255                                   _multi_up, it);
3256    evas_object_event_callback_add(it->edit_obj, EVAS_CALLBACK_MULTI_MOVE,
3257                                   _multi_move, it);
3258
3259    _item_text_realize(it, it->edit_obj, &it->item->edit_texts, NULL);
3260    it->item->edit_content_objs =
3261      _item_content_realize(it, it->edit_obj, &it->item->edit_contents, NULL);
3262    _item_state_realize(it, it->edit_obj, &it->item->edit_states, NULL);
3263    edje_object_part_swallow(it->edit_obj, "elm.swallow.edit.content", VIEW(it));
3264
3265    _edit_mode_item_position(it, it->item->scrl_x, it->item->scrl_y);
3266    evas_object_show(it->edit_obj);
3267
3268    it->item->edit_mode_item_realized = EINA_TRUE;
3269    it->want_unrealize = EINA_FALSE;
3270 }
3271
3272 static void
3273 _edit_mode_item_unrealize(Elm_Gen_Item *it)
3274 {
3275    Evas_Object *icon;
3276    if ((!it) || (!it->item->edit_mode_item_realized)) return;
3277
3278    edje_object_part_unswallow(it->edit_obj, VIEW(it));
3279    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3280    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3281    _elm_genlist_item_odd_even_update(it);
3282    _elm_genlist_item_state_update(it, NULL);
3283
3284    evas_object_del(it->edit_obj);
3285    it->edit_obj = NULL;
3286    elm_widget_stringlist_free(it->item->edit_texts);
3287    it->item->edit_texts = NULL;
3288    elm_widget_stringlist_free(it->item->edit_contents);
3289    it->item->edit_contents = NULL;
3290    elm_widget_stringlist_free(it->item->edit_states);
3291    it->item->edit_states = NULL;
3292    EINA_LIST_FREE(it->item->edit_content_objs, icon)
3293       evas_object_del(icon);
3294    edje_object_message_signal_process(it->edit_obj);
3295
3296    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MOUSE_DOWN,
3297                                        _mouse_down, it);
3298    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MOUSE_UP,
3299                                        _mouse_up, it);
3300    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MOUSE_MOVE,
3301                                        _mouse_move, it);
3302    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MULTI_DOWN,
3303                                        _multi_down, it);
3304    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MULTI_UP,
3305                                        _multi_up, it);
3306    evas_object_event_callback_del_full(it->edit_obj, EVAS_CALLBACK_MULTI_MOVE,
3307                                        _multi_move, it);
3308    it->item->edit_mode_item_realized = EINA_FALSE;
3309 }
3310
3311 static void
3312 _item_auto_scroll(Widget_Data *wd)
3313 {
3314    if (!wd) return;
3315    Elm_Gen_Item  *tmp_item = NULL;
3316
3317    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3318      {
3319         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3320         if (!tmp_item) return;
3321         wd->show_item = tmp_item;
3322         wd->bring_in = EINA_TRUE;
3323         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3324         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3325           {
3326              wd->show_item->item->showme = EINA_TRUE;
3327              wd->auto_scroll_enabled = EINA_FALSE;
3328           }
3329         else
3330           _scroll_item(wd);
3331      }
3332 }
3333
3334 EAPI Evas_Object *
3335 elm_genlist_add(Evas_Object *parent)
3336 {
3337    Evas_Object *obj;
3338    Evas *e;
3339    Widget_Data *wd;
3340    Evas_Coord minw, minh;
3341    static Evas_Smart *smart = NULL;
3342
3343    if (!smart)
3344      {
3345         static Evas_Smart_Class sc;
3346
3347         evas_object_smart_clipped_smart_set(&_pan_sc);
3348         sc = _pan_sc;
3349         sc.name = "elm_genlist_pan";
3350         sc.version = EVAS_SMART_CLASS_VERSION;
3351         sc.add = _pan_add;
3352         sc.del = _pan_del;
3353         sc.resize = _pan_resize;
3354         sc.move = _pan_move;
3355         sc.calculate = _pan_calculate;
3356         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3357      }
3358
3359    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3360
3361    ELM_SET_WIDTYPE(widtype, "genlist");
3362    ELM_GEN_SETUP(wd);
3363    elm_widget_type_set(obj, "genlist");
3364    elm_widget_sub_object_add(parent, obj);
3365    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3366    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3367    elm_widget_data_set(obj, wd);
3368    elm_widget_del_hook_set(obj, _del_hook);
3369    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3370    elm_widget_theme_hook_set(obj, _theme_hook);
3371    elm_widget_can_focus_set(obj, EINA_TRUE);
3372    elm_widget_event_hook_set(obj, _event_hook);
3373    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3374    elm_widget_translate_hook_set(obj, _translate_hook);
3375
3376    wd->generation = 1;
3377    wd->scr = elm_smart_scroller_add(e);
3378    elm_smart_scroller_widget_set(wd->scr, obj);
3379    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3380                                        elm_widget_style_get(obj));
3381    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3382                                        _elm_config->thumbscroll_bounce_enable);
3383    elm_widget_resize_object_set(obj, wd->scr);
3384
3385    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3386    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3387    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3388    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3389    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3390    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3391    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3392    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3393
3394    wd->obj = obj;
3395    wd->mode = ELM_LIST_SCROLL;
3396    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3397    wd->item_cache_max = wd->max_items_per_block * 2;
3398    wd->longpress_timeout = _elm_config->longpress_timeout;
3399
3400    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3401    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3402    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3403    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3404
3405    wd->pan_smart = evas_object_smart_add(e, smart);
3406    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3407    wd->pan->wd = wd;
3408
3409    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3410                                      _pan_set, _pan_get, _pan_max_get,
3411                                      _pan_min_get, _pan_child_size_get);
3412
3413    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3414                              &minw, &minh);
3415    evas_object_size_hint_min_set(obj, minw, minh);
3416
3417    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3418
3419    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3420    _sizing_eval(obj);
3421    return obj;
3422 }
3423
3424 void
3425 _item_select(Elm_Gen_Item *it)
3426 {
3427    if ((it->wd->no_select) || (it->generation < it->wd->generation) || (it->mode_set)) return;
3428    if (!it->selected)
3429      {
3430         it->selected = EINA_TRUE;
3431         it->wd->selected = eina_list_append(it->wd->selected, it);
3432      }
3433    else if (!it->wd->always_select) return;
3434
3435    evas_object_ref(WIDGET(it));
3436    it->walking++;
3437    it->wd->walking++;
3438    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3439    if (it->generation == it->wd->generation)
3440      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3441    it->walking--;
3442    it->wd->walking--;
3443    evas_object_unref(WIDGET(it));
3444    if ((it->wd->clear_me) && (!it->wd->walking))
3445      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3446    else
3447      {
3448         if ((!it->walking) && (it->generation < it->wd->generation))
3449           {
3450              if (!it->relcount)
3451                {
3452                   it->del_cb(it);
3453                   elm_widget_item_free(it);
3454                }
3455           }
3456         else
3457           it->wd->last_selected_item = (Elm_Object_Item *) it;
3458      }
3459 }
3460
3461 static Evas_Object *
3462 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
3463 {
3464    return edje_object_part_swallow_get(VIEW(it), part);
3465 }
3466
3467 static void
3468 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
3469 {
3470    if (content && part)
3471      {
3472         it->content_objs = eina_list_append(it->content_objs, content);
3473         edje_object_part_swallow(VIEW(it), part, content);
3474      }
3475 }
3476
3477 static Evas_Object *
3478 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
3479 {
3480    Evas_Object *obj;
3481    obj = edje_object_part_swallow_get(VIEW(it), part);
3482    if (!obj) return NULL;
3483    it->content_objs = eina_list_remove(it->content_objs, obj);
3484    edje_object_part_unswallow(VIEW(it), obj);
3485    return obj;
3486 }
3487
3488 static const char *
3489 _item_text_hook(Elm_Gen_Item *it, const char *part)
3490 {
3491    if (!it->itc->func.text_get) return NULL;
3492    return edje_object_part_text_get(VIEW(it), part);
3493 }
3494
3495 static void
3496 _item_disable_hook(Elm_Object_Item *it)
3497 {
3498    Eina_List *l;
3499    Evas_Object *obj;
3500    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
3501
3502    if (_it->generation < _it->wd->generation) return;
3503
3504    if (_it->selected)
3505      elm_genlist_item_selected_set(it, EINA_FALSE);
3506
3507    if (_it->realized)
3508      {
3509         if (elm_widget_item_disabled_get(it))
3510           {
3511              edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
3512              if (_it->edit_obj)
3513                edje_object_signal_emit(_it->edit_obj, "elm,state,disabled", "elm");
3514           }
3515         else
3516           {
3517              edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
3518              if (_it->edit_obj)
3519                edje_object_signal_emit(_it->edit_obj, "elm,state,enabled", "elm");
3520           }
3521         EINA_LIST_FOREACH(_it->content_objs, l, obj)
3522           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
3523      }
3524 }
3525
3526 static Eina_Bool
3527 _item_del_pre_hook(Elm_Object_Item *it)
3528 {
3529    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
3530
3531    if ((_it->relcount > 0) || (_it->walking > 0))
3532      {
3533         elm_genlist_item_subitems_clear(it);
3534         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
3535         _elm_genlist_item_del_notserious(_it);
3536         if (_it->item->block)
3537           {
3538              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
3539              _it->item->block->changed = EINA_TRUE;
3540              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
3541              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
3542           }
3543         if (_it->parent)
3544           {
3545              _it->parent->item->items =
3546                 eina_list_remove(_it->parent->item->items, it);
3547              _it->parent = NULL;
3548           }
3549         return EINA_FALSE;
3550      }
3551    _item_del(_it);
3552    return EINA_TRUE;
3553 }
3554
3555 Elm_Gen_Item *
3556 _elm_genlist_item_new(Widget_Data              *wd,
3557                       const Elm_Gen_Item_Class *itc,
3558                       const void               *data,
3559                       Elm_Gen_Item             *parent,
3560                       Evas_Smart_Cb             func,
3561                       const void               *func_data)
3562 {
3563    Elm_Gen_Item *it;
3564
3565    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
3566    if (!it) return NULL;
3567    it->wd = wd;
3568    it->generation = wd->generation;
3569    it->itc = itc;
3570    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
3571    it->base.data = data;
3572    it->parent = parent;
3573    it->func.func = func;
3574    it->func.data = func_data;
3575    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
3576    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
3577    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
3578    elm_widget_item_text_get_hook_set(it, _item_text_hook);
3579    elm_widget_item_disable_hook_set(it, _item_disable_hook);
3580    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
3581    /* TEMPORARY */
3582    it->sel_cb = (Ecore_Cb)_item_select;
3583
3584    return it;
3585 }
3586
3587 static Elm_Gen_Item *
3588 _item_new(Widget_Data                  *wd,
3589           const Elm_Genlist_Item_Class *itc,
3590           const void                   *data,
3591           Elm_Gen_Item                 *parent,
3592           Elm_Genlist_Item_Flags        flags,
3593           Evas_Smart_Cb                 func,
3594           const void                   *func_data)
3595 {
3596    Elm_Gen_Item *it, *it2;
3597    int depth = 0;
3598
3599    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
3600    if (!it) return NULL;
3601    it->item = ELM_NEW(Elm_Gen_Item_Type);
3602    it->item->flags = flags;
3603    if (flags & ELM_GENLIST_ITEM_GROUP) it->group++;
3604    it->item->expanded_depth = 0;
3605    ELM_GEN_ITEM_SETUP(it);
3606    if (it->parent)
3607      {
3608         if (it->parent->group)
3609           it->item->group_item = parent;
3610         else if (it->parent->item->group_item)
3611           it->item->group_item = it->parent->item->group_item;
3612      }
3613    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
3614      {
3615         if (!it2->parent->group) depth += 1;
3616      }
3617    it->item->expanded_depth = depth;
3618    wd->item_count++;
3619    return it;
3620 }
3621
3622 static Item_Block *
3623 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
3624 {
3625    Item_Block *itb;
3626
3627    itb = calloc(1, sizeof(Item_Block));
3628    if (!itb) return NULL;
3629    itb->wd = wd;
3630    if (prepend)
3631      {
3632         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3633         _item_block_position_update(wd->blocks, 0);
3634      }
3635    else
3636      {
3637         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3638         itb->position_update = EINA_TRUE;
3639         if (wd->blocks != EINA_INLIST_GET(itb))
3640           {
3641              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3642           }
3643         else
3644           {
3645              itb->position = 0;
3646           }
3647      }
3648    return itb;
3649 }
3650
3651 static Eina_Bool
3652 _item_block_add(Widget_Data *wd,
3653                 Elm_Gen_Item *it)
3654 {
3655    Item_Block *itb = NULL;
3656
3657    if (!it->item->rel)
3658      {
3659 newblock:
3660         if (it->item->rel)
3661           {
3662              itb = calloc(1, sizeof(Item_Block));
3663              if (!itb) return EINA_FALSE;
3664              itb->wd = wd;
3665              if (!it->item->rel->item->block)
3666                {
3667                   wd->blocks =
3668                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3669                   itb->items = eina_list_append(itb->items, it);
3670                   itb->position_update = EINA_TRUE;
3671                   it->position = eina_list_count(itb->items);
3672                   it->position_update = EINA_TRUE;
3673
3674                   if (wd->blocks != EINA_INLIST_GET(itb))
3675                     {
3676                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3677                     }
3678                   else
3679                     {
3680                        itb->position = 0;
3681                     }
3682                }
3683              else
3684                {
3685                   Eina_List *tmp;
3686
3687                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3688                   if (it->item->before)
3689                     {
3690                        wd->blocks = eina_inlist_prepend_relative
3691                            (wd->blocks, EINA_INLIST_GET(itb),
3692                            EINA_INLIST_GET(it->item->rel->item->block));
3693                        itb->items =
3694                          eina_list_prepend_relative_list(itb->items, it, tmp);
3695
3696                        /* Update index from where we prepended */
3697                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3698                        _item_block_position_update(EINA_INLIST_GET(itb),
3699                                                    it->item->rel->item->block->position);
3700                     }
3701                   else
3702                     {
3703                        wd->blocks = eina_inlist_append_relative
3704                            (wd->blocks, EINA_INLIST_GET(itb),
3705                            EINA_INLIST_GET(it->item->rel->item->block));
3706                        itb->items =
3707                          eina_list_append_relative_list(itb->items, it, tmp);
3708
3709                        /* Update block index from where we appended */
3710                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3711                        _item_block_position_update(EINA_INLIST_GET(itb),
3712                                                    it->item->rel->item->block->position + 1);
3713                     }
3714                }
3715           }
3716         else
3717           {
3718              if (it->item->before)
3719                {
3720                   if (wd->blocks)
3721                     {
3722                        itb = (Item_Block *)(wd->blocks);
3723                        if (itb->count >= wd->max_items_per_block)
3724                          {
3725                             itb = _item_block_new(wd, EINA_TRUE);
3726                             if (!itb) return EINA_FALSE;
3727                          }
3728                     }
3729                   else
3730                     {
3731                        itb = _item_block_new(wd, EINA_TRUE);
3732                        if (!itb) return EINA_FALSE;
3733                     }
3734                   itb->items = eina_list_prepend(itb->items, it);
3735
3736                   _item_position_update(itb->items, 0);
3737                }
3738              else
3739                {
3740                   if (wd->blocks)
3741                     {
3742                        itb = (Item_Block *)(wd->blocks->last);
3743                        if (itb->count >= wd->max_items_per_block)
3744                          {
3745                             itb = _item_block_new(wd, EINA_FALSE);
3746                             if (!itb) return EINA_FALSE;
3747                          }
3748                     }
3749                   else
3750                     {
3751                        itb = _item_block_new(wd, EINA_FALSE);
3752                        if (!itb) return EINA_FALSE;
3753                     }
3754                   itb->items = eina_list_append(itb->items, it);
3755                   it->position = eina_list_count(itb->items);
3756                }
3757           }
3758      }
3759    else
3760      {
3761         Eina_List *tmp;
3762
3763         if (it->item->rel->item->queued)
3764           {
3765              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3766                 on sorted insertion order, so the queue is not always ordered like the item list.
3767                 This lead to issue where we depend on an item that is not yet created. As a quick
3768                 work around, we reschedule the calc of the item and stop reordering the list to
3769                 prevent any nasty issue to show up here.
3770               */
3771              wd->queue = eina_list_append(wd->queue, it);
3772              wd->requeued = EINA_TRUE;
3773              it->item->queued = EINA_TRUE;
3774              return EINA_FALSE;
3775           }
3776         itb = it->item->rel->item->block;
3777         if (!itb) goto newblock;
3778         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3779         if (it->item->before)
3780           {
3781              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3782              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3783           }
3784         else
3785           {
3786              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3787              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3788           }
3789      }
3790    itb->count++;
3791    itb->changed = EINA_TRUE;
3792    it->item->block = itb;
3793    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3794    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3795    if (it->item->rel)
3796      {
3797         it->item->rel->relcount--;
3798         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3799           {
3800              _item_del(it->item->rel);
3801              elm_widget_item_free(it->item->rel);
3802           }
3803         it->item->rel = NULL;
3804      }
3805    if (itb->count > itb->wd->max_items_per_block)
3806      {
3807         Item_Block *itb2;
3808         Elm_Gen_Item *it2;
3809         int newc;
3810         Eina_Bool done = EINA_FALSE;
3811
3812         newc = itb->count / 2;
3813
3814         if (EINA_INLIST_GET(itb)->prev)
3815           {
3816              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3817
3818              if (itbp->count + newc < wd->max_items_per_block / 2)
3819                {
3820                   /* moving items to previous block */
3821                   while ((itb->count > newc) && (itb->items))
3822                     {
3823                        it2 = eina_list_data_get(itb->items);
3824                        itb->items = eina_list_remove_list(itb->items, itb->items);
3825                        itb->count--;
3826
3827                        itbp->items = eina_list_append(itbp->items, it2);
3828                        it2->item->block = itbp;
3829                        itbp->count++;
3830                     }
3831
3832                   done = EINA_TRUE;
3833                }
3834           }
3835
3836         if (!done && EINA_INLIST_GET(itb)->next)
3837           {
3838              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3839
3840              if (itbn->count + newc < wd->max_items_per_block / 2)
3841                {
3842                   /* moving items to next block */
3843                   while ((itb->count > newc) && (itb->items))
3844                     {
3845                        Eina_List *l;
3846
3847                        l = eina_list_last(itb->items);
3848                        it2 = eina_list_data_get(l);
3849                        itb->items = eina_list_remove_list(itb->items, l);
3850                        itb->count--;
3851
3852                        itbn->items = eina_list_prepend(itbn->items, it2);
3853                        it2->item->block = itbn;
3854                        itbn->count++;
3855                     }
3856
3857                   done = EINA_TRUE;
3858                }
3859           }
3860
3861         if (!done)
3862           {
3863              /* moving items to new block */
3864              itb2 = calloc(1, sizeof(Item_Block));
3865              if (!itb2) return EINA_FALSE;
3866              itb2->wd = wd;
3867              wd->blocks =
3868                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3869                                            EINA_INLIST_GET(itb));
3870              itb2->changed = EINA_TRUE;
3871              while ((itb->count > newc) && (itb->items))
3872                {
3873                   Eina_List *l;
3874
3875                   l = eina_list_last(itb->items);
3876                   it2 = l->data;
3877                   itb->items = eina_list_remove_list(itb->items, l);
3878                   itb->count--;
3879
3880                   itb2->items = eina_list_prepend(itb2->items, it2);
3881                   it2->item->block = itb2;
3882                   itb2->count++;
3883                }
3884           }
3885      }
3886
3887    return EINA_TRUE;
3888 }
3889
3890 static int
3891 _queue_process(Widget_Data *wd)
3892 {
3893    int n;
3894    Eina_Bool showme = EINA_FALSE;
3895    double t0, t;
3896
3897    t0 = ecore_loop_time_get();
3898    //evas_event_freeze(evas_object_evas_get(wd->obj));
3899    for (n = 0; (wd->queue) && (n < 128); n++)
3900      {
3901         Elm_Gen_Item *it;
3902
3903         it = eina_list_data_get(wd->queue);
3904         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3905         it->item->queued = EINA_FALSE;
3906         if (!_item_block_add(wd, it)) continue;
3907         if (!wd->blocks)
3908           _item_block_realize(it->item->block);
3909         t = ecore_time_get();
3910         if (it->item->block->changed)
3911           {
3912              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
3913              it->item->block->changed = 0;
3914              if (wd->pan_changed)
3915                {
3916                   if (wd->calc_job) ecore_job_del(wd->calc_job);
3917                   wd->calc_job = NULL;
3918                   _calc_job(wd);
3919                   wd->pan_changed = EINA_FALSE;
3920                }
3921           }
3922         if (showme) it->item->block->showme = EINA_TRUE;
3923         /* same as eina_inlist_count > 1 */
3924         if (wd->blocks && wd->blocks->next)
3925           {
3926              if ((t - t0) > (ecore_animator_frametime_get())) break;
3927           }
3928      }
3929    //evas_event_thaw(evas_object_evas_get(wd->obj));
3930    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3931    return n;
3932 }
3933
3934 static Eina_Bool
3935 _idle_process(void *data, Eina_Bool *wakeup)
3936 {
3937    Widget_Data *wd = data;
3938
3939    //xxx
3940    //static double q_start = 0.0;
3941    //if (q_start == 0.0) q_start = ecore_time_get();
3942    //xxx
3943    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3944    if (!wd->queue)
3945      {
3946         //xxx
3947         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3948         //xxx
3949         return ECORE_CALLBACK_CANCEL;
3950      }
3951    return ECORE_CALLBACK_RENEW;
3952 }
3953
3954 static Eina_Bool
3955 _item_idle_enterer(void *data)
3956 {
3957    Widget_Data *wd = data;
3958    Eina_Bool wakeup = EINA_FALSE;
3959    Eina_Bool ok = _idle_process(data, &wakeup);
3960
3961    if (wakeup)
3962      {
3963         // wake up mainloop
3964         if (wd->calc_job) ecore_job_del(wd->calc_job);
3965         wd->calc_job = ecore_job_add(_calc_job, wd);
3966      }
3967    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3968    return ok;
3969 }
3970
3971 static void
3972 _item_queue(Widget_Data *wd,
3973             Elm_Gen_Item *it,
3974             Eina_Compare_Cb cb)
3975 {
3976    if (it->item->queued) return;
3977    it->item->queued = EINA_TRUE;
3978    if (cb && !wd->requeued)
3979      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
3980    else
3981      wd->queue = eina_list_append(wd->queue, it);
3982 // FIXME: why does a freeze then thaw here cause some genlist
3983 // elm_genlist_item_append() to be much much slower?
3984 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3985    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3986      {
3987         if (wd->queue_idle_enterer)
3988           {
3989              ecore_idle_enterer_del(wd->queue_idle_enterer);
3990              wd->queue_idle_enterer = NULL;
3991           }
3992         _queue_process(wd);
3993      }
3994 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3995 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3996    if (!wd->queue_idle_enterer)
3997      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3998 }
3999
4000 static int
4001 _elm_genlist_item_compare(const void *data, const void *data1)
4002 {
4003    const Elm_Gen_Item *it, *item1;
4004    it = ELM_GEN_ITEM_FROM_INLIST(data);
4005    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4006    return it->wd->item_compare_cb(it, item1);
4007 }
4008
4009 static int
4010 _elm_genlist_item_list_compare(const void *data, const void *data1)
4011 {
4012    const Elm_Gen_Item *it = data;
4013    const Elm_Gen_Item *item1 = data1;
4014    return it->wd->item_compare_cb(it, item1);
4015 }
4016
4017 static void
4018 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4019 {
4020    if (!it) return;
4021    if (!after) return;
4022
4023    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4024    _item_block_del(it);
4025
4026    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4027    it->item->rel = after;
4028    it->item->rel->relcount++;
4029    it->item->before = EINA_FALSE;
4030    if (after->item->group_item) it->item->group_item = after->item->group_item;
4031    _item_queue(it->wd, it, NULL);
4032
4033    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4034 }
4035
4036 static void
4037 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4038 {
4039    if (!it) return;
4040    if (!before) return;
4041
4042    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4043    _item_block_del(it);
4044    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4045    it->item->rel = before;
4046    it->item->rel->relcount++;
4047    it->item->before = EINA_TRUE;
4048    if (before->item->group_item) it->item->group_item = before->item->group_item;
4049    _item_queue(it->wd, it, NULL);
4050
4051    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4052 }
4053
4054 EAPI unsigned int
4055 elm_genlist_items_count(const Evas_Object *obj)
4056 {
4057    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4058    Widget_Data *wd = elm_widget_data_get(obj);
4059    if (!wd) return 0;
4060    return wd->item_count;
4061 }
4062
4063 EAPI Elm_Object_Item *
4064 elm_genlist_item_append(Evas_Object                  *obj,
4065                         const Elm_Genlist_Item_Class *itc,
4066                         const void                   *data,
4067                         Elm_Object_Item              *parent,
4068                         Elm_Genlist_Item_Flags        flags,
4069                         Evas_Smart_Cb                 func,
4070                         const void                   *func_data)
4071 {
4072    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4073    Widget_Data *wd = elm_widget_data_get(obj);
4074    if (!wd) return NULL;
4075    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
4076                                 func, func_data);
4077    if (!it) return NULL;
4078    if (!it->parent)
4079      {
4080         if (it->group)
4081           wd->group_items = eina_list_append(wd->group_items, it);
4082         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4083         it->item->rel = NULL;
4084      }
4085    else
4086      {
4087         Elm_Gen_Item *it2 = NULL;
4088         Eina_List *ll = eina_list_last(it->parent->item->items);
4089         if (ll) it2 = ll->data;
4090         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4091         if (!it2) it2 = it->parent;
4092         wd->items =
4093           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4094                                       EINA_INLIST_GET(it2));
4095         it->item->rel = it2;
4096         it->item->rel->relcount++;
4097      }
4098    it->item->before = EINA_FALSE;
4099    _item_queue(wd, it, NULL);
4100    return (Elm_Object_Item *) it;
4101 }
4102
4103 EAPI Elm_Object_Item *
4104 elm_genlist_item_prepend(Evas_Object                  *obj,
4105                          const Elm_Genlist_Item_Class *itc,
4106                          const void                   *data,
4107                          Elm_Object_Item              *parent,
4108                          Elm_Genlist_Item_Flags        flags,
4109                          Evas_Smart_Cb                 func,
4110                          const void                   *func_data)
4111 {
4112    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4113    Widget_Data *wd = elm_widget_data_get(obj);
4114    if (!wd) return NULL;
4115    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
4116                                 func, func_data);
4117    if (!it) return NULL;
4118    if (!it->parent)
4119      {
4120         if (it->group)
4121           wd->group_items = eina_list_prepend(wd->group_items, it);
4122         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4123         it->item->rel = NULL;
4124      }
4125    else
4126      {
4127         Elm_Gen_Item *it2 = NULL;
4128         Eina_List *ll = it->parent->item->items;
4129         if (ll) it2 = ll->data;
4130         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4131         if (!it2) it2 = it->parent;
4132         wd->items =
4133           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4134                                        EINA_INLIST_GET(it2));
4135         it->item->rel = it2;
4136         it->item->rel->relcount++;
4137      }
4138    it->item->before = EINA_TRUE;
4139    _item_queue(wd, it, NULL);
4140    return (Elm_Object_Item *) it;
4141 }
4142
4143 EAPI Elm_Object_Item *
4144 elm_genlist_item_insert_after(Evas_Object                  *obj,
4145                               const Elm_Genlist_Item_Class *itc,
4146                               const void                   *data,
4147                               Elm_Object_Item              *parent,
4148                               Elm_Object_Item              *after,
4149                               Elm_Genlist_Item_Flags        flags,
4150                               Evas_Smart_Cb                 func,
4151                               const void                   *func_data)
4152 {
4153    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4154    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4155    Widget_Data *wd = elm_widget_data_get(obj);
4156    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4157    if (!wd) return NULL;
4158    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4159    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4160
4161    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
4162                                 func, func_data);
4163    if (!it) return NULL;
4164    if (!it->parent)
4165      {
4166         if ((it->group) && (_after->group))
4167           wd->group_items = eina_list_append_relative(wd->group_items, it,
4168                                                       _after);
4169      }
4170    else
4171      {
4172         it->parent->item->items =
4173            eina_list_append_relative(it->parent->item->items, it, _after);
4174      }
4175    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4176                                            EINA_INLIST_GET(_after));
4177    it->item->rel = _after;
4178    it->item->rel->relcount++;
4179    it->item->before = EINA_FALSE;
4180    _item_queue(wd, it, NULL);
4181    return (Elm_Object_Item *) it;
4182 }
4183
4184 EAPI Elm_Object_Item *
4185 elm_genlist_item_insert_before(Evas_Object                  *obj,
4186                                const Elm_Genlist_Item_Class *itc,
4187                                const void                   *data,
4188                                Elm_Object_Item              *parent,
4189                                Elm_Object_Item              *before,
4190                                Elm_Genlist_Item_Flags        flags,
4191                                Evas_Smart_Cb                 func,
4192                                const void                   *func_data)
4193 {
4194    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4195    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4196    Widget_Data *wd = elm_widget_data_get(obj);
4197    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4198    if (!wd) return NULL;
4199    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4200    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4201
4202    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
4203                                 func, func_data);
4204    if (!it) return NULL;
4205    if (!it->parent)
4206      {
4207         if (it->group && _before->group)
4208           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4209                                                        _before);
4210      }
4211    else
4212      {
4213         it->parent->item->items =
4214            eina_list_prepend_relative(it->parent->item->items, it, _before);
4215      }
4216    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4217                                             EINA_INLIST_GET(_before));
4218    it->item->rel = _before;
4219    it->item->rel->relcount++;
4220    it->item->before = EINA_TRUE;
4221    _item_queue(wd, it, NULL);
4222    return (Elm_Object_Item *) it;
4223 }
4224
4225 EAPI Elm_Object_Item *
4226 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4227                                const Elm_Genlist_Item_Class *itc,
4228                                const void                   *data,
4229                                Elm_Object_Item              *parent,
4230                                Elm_Genlist_Item_Flags        flags,
4231                                Eina_Compare_Cb               comp,
4232                                Evas_Smart_Cb                 func,
4233                                const void                   *func_data)
4234 {
4235    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4236    Widget_Data *wd = elm_widget_data_get(obj);
4237    if (!wd) return NULL;
4238    Elm_Gen_Item *rel = NULL;
4239    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, flags,
4240                                 func, func_data);
4241    if (!it) return NULL;
4242
4243    wd->item_compare_cb = comp;
4244
4245    if (it->parent)
4246      {
4247         Eina_List *l;
4248         int cmp_result;
4249
4250         l = eina_list_search_sorted_near_list(it->parent->item->items,
4251                                               _elm_genlist_item_list_compare,
4252                                               it,
4253                                               &cmp_result);
4254         if (l)
4255           rel = eina_list_data_get(l);
4256         else
4257           rel = it->parent;
4258
4259         if (cmp_result >= 0)
4260           {
4261              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4262              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4263              it->item->before = EINA_FALSE;
4264           }
4265         else if (cmp_result < 0)
4266           {
4267              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4268              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4269              it->item->before = EINA_TRUE;
4270           }
4271      }
4272    else
4273      {
4274         if (!wd->state)
4275           {
4276              wd->state = eina_inlist_sorted_state_new();
4277              eina_inlist_sorted_state_init(wd->state, wd->items);
4278              wd->requeued = EINA_FALSE;
4279           }
4280
4281         if (it->group)
4282           wd->group_items = eina_list_append(wd->group_items, it);
4283
4284         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4285                                                     _elm_genlist_item_compare, wd->state);
4286
4287         if (EINA_INLIST_GET(it)->next)
4288           {
4289              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4290              it->item->before = EINA_TRUE;
4291           }
4292         else if (EINA_INLIST_GET(it)->prev)
4293           {
4294              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4295              it->item->before = EINA_FALSE;
4296           }
4297      }
4298
4299    if (rel)
4300      {
4301         it->item->rel = rel;
4302         it->item->rel->relcount++;
4303      }
4304
4305    _item_queue(wd, it, _elm_genlist_item_list_compare);
4306
4307    return (Elm_Object_Item *) it;
4308 }
4309
4310 static void
4311 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4312 {
4313    Eina_Inlist *next, *l;
4314
4315    ELM_CHECK_WIDTYPE(obj, widtype);
4316    Widget_Data *wd = elm_widget_data_get(obj);
4317    if (!wd) return;
4318
4319    if (!standby) wd->generation++;
4320
4321    if (wd->state)
4322      {
4323         eina_inlist_sorted_state_free(wd->state);
4324         wd->state = NULL;
4325      }
4326
4327    if (wd->walking > 0)
4328      {
4329         wd->clear_me = EINA_TRUE;
4330         return;
4331      }
4332    evas_event_freeze(evas_object_evas_get(wd->obj));
4333    for (l = wd->items, next = l ? l->next : NULL;
4334         l;
4335         l = next, next = next ? next->next : NULL)
4336      {
4337         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4338
4339         if (it->generation < wd->generation)
4340           {
4341              Elm_Gen_Item *itn = NULL;
4342
4343              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4344              if (itn) itn->walking++; /* prevent early death of subitem */
4345              it->del_cb(it);
4346              elm_widget_item_free(it);
4347              if (itn) itn->walking--;
4348           }
4349      }
4350    wd->clear_me = EINA_FALSE;
4351    wd->pan_changed = EINA_TRUE;
4352    if (wd->calc_job)
4353      {
4354         ecore_job_del(wd->calc_job);
4355         wd->calc_job = NULL;
4356      }
4357    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4358    if (wd->clear_cb) wd->clear_cb(wd);
4359    wd->pan_x = 0;
4360    wd->pan_y = 0;
4361    wd->minw = 0;
4362    wd->minh = 0;
4363    if (wd->pan_smart)
4364      {
4365         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4366         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4367      }
4368    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4369    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4370    evas_event_thaw(evas_object_evas_get(wd->obj));
4371    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4372 }
4373
4374 EAPI void
4375 elm_genlist_clear(Evas_Object *obj)
4376 {
4377    _elm_genlist_clear(obj, EINA_FALSE);
4378 }
4379
4380 EAPI void
4381 elm_genlist_multi_select_set(Evas_Object *obj,
4382                              Eina_Bool    multi)
4383 {
4384    ELM_CHECK_WIDTYPE(obj, widtype);
4385    Widget_Data *wd = elm_widget_data_get(obj);
4386    if (!wd) return;
4387    wd->multi = !!multi;
4388 }
4389
4390 EAPI Eina_Bool
4391 elm_genlist_multi_select_get(const Evas_Object *obj)
4392 {
4393    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4394    Widget_Data *wd = elm_widget_data_get(obj);
4395    if (!wd) return EINA_FALSE;
4396    return wd->multi;
4397 }
4398
4399 EAPI Elm_Object_Item *
4400 elm_genlist_selected_item_get(const Evas_Object *obj)
4401 {
4402    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4403    Widget_Data *wd = elm_widget_data_get(obj);
4404    if (!wd) return NULL;
4405    if (wd->selected) return wd->selected->data;
4406    return NULL;
4407 }
4408
4409 EAPI const Eina_List *
4410 elm_genlist_selected_items_get(const Evas_Object *obj)
4411 {
4412    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4413    Widget_Data *wd = elm_widget_data_get(obj);
4414    if (!wd) return NULL;
4415    return wd->selected;
4416 }
4417
4418 EAPI Eina_List *
4419 elm_genlist_realized_items_get(const Evas_Object *obj)
4420 {
4421    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4422    Widget_Data *wd = elm_widget_data_get(obj);
4423    Eina_List *list = NULL;
4424    Item_Block *itb;
4425    Eina_Bool done = EINA_FALSE;
4426    if (!wd) return NULL;
4427    EINA_INLIST_FOREACH(wd->blocks, itb)
4428      {
4429         if (itb->realized)
4430           {
4431              Eina_List *l;
4432              Elm_Gen_Item *it;
4433
4434              done = EINA_TRUE;
4435              EINA_LIST_FOREACH(itb->items, l, it)
4436                {
4437                   if (it->realized) list = eina_list_append(list, it);
4438                }
4439           }
4440         else
4441           {
4442              if (done) break;
4443           }
4444      }
4445    return list;
4446 }
4447
4448 EAPI Elm_Object_Item *
4449 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4450                            Evas_Coord         x,
4451                            Evas_Coord         y,
4452                            int               *posret)
4453 {
4454    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4455    Widget_Data *wd = elm_widget_data_get(obj);
4456    Evas_Coord ox, oy, ow, oh;
4457    Item_Block *itb;
4458    Evas_Coord lasty;
4459    if (!wd) return NULL;
4460    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4461    lasty = oy;
4462    EINA_INLIST_FOREACH(wd->blocks, itb)
4463      {
4464         Eina_List *l;
4465         Elm_Gen_Item *it;
4466
4467         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4468                                  oy + itb->y - itb->wd->pan_y,
4469                                  itb->w, itb->h, x, y, 1, 1))
4470           continue;
4471         EINA_LIST_FOREACH(itb->items, l, it)
4472           {
4473              Evas_Coord itx, ity;
4474
4475              itx = ox + itb->x + it->x - itb->wd->pan_x;
4476              ity = oy + itb->y + it->y - itb->wd->pan_y;
4477              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4478                {
4479                   if (posret)
4480                     {
4481                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
4482                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
4483                          *posret = 1;
4484                        else *posret = 0;
4485                     }
4486                   return (Elm_Object_Item *) it;
4487                }
4488              lasty = ity + it->item->h;
4489           }
4490      }
4491    if (posret)
4492      {
4493         if (y > lasty) *posret = 1;
4494         else *posret = -1;
4495      }
4496    return NULL;
4497 }
4498
4499 EAPI Elm_Object_Item *
4500 elm_genlist_first_item_get(const Evas_Object *obj)
4501 {
4502    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4503    Widget_Data *wd = elm_widget_data_get(obj);
4504    if (!wd) return NULL;
4505    if (!wd->items) return NULL;
4506    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4507    while ((it) && (it->generation < wd->generation))
4508      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4509    return (Elm_Object_Item *) it;
4510 }
4511
4512 EAPI Elm_Object_Item *
4513 elm_genlist_last_item_get(const Evas_Object *obj)
4514 {
4515    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4516    Widget_Data *wd = elm_widget_data_get(obj);
4517    if (!wd) return NULL;
4518    if (!wd->items) return NULL;
4519    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4520    while ((it) && (it->generation < wd->generation))
4521      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4522    return (Elm_Object_Item *) it;
4523 }
4524
4525 EAPI Elm_Object_Item *
4526 elm_genlist_item_next_get(const Elm_Object_Item *it)
4527 {
4528    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4529    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4530    while (_it)
4531      {
4532         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
4533         if ((_it) && (_it->generation == _it->wd->generation)) break;
4534      }
4535    return (Elm_Object_Item *) _it;
4536 }
4537
4538 EAPI Elm_Object_Item *
4539 elm_genlist_item_prev_get(const Elm_Object_Item *it)
4540 {
4541    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4542    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4543    while (_it)
4544      {
4545         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
4546         if ((_it) && (_it->generation == _it->wd->generation)) break;
4547      }
4548    return (Elm_Object_Item *) _it;
4549 }
4550
4551 EINA_DEPRECATED EAPI Evas_Object *
4552 elm_genlist_item_genlist_get(const Elm_Object_Item *it)
4553 {
4554    return elm_object_item_widget_get(it);
4555 }
4556
4557 EAPI Elm_Object_Item *
4558 elm_genlist_item_parent_get(const Elm_Object_Item *it)
4559 {
4560    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4561    return (Elm_Object_Item *) ((Elm_Gen_Item *) it)->parent;
4562 }
4563
4564 EAPI void
4565 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4566 {
4567    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4568    Eina_List *tl = NULL, *l;
4569    Elm_Gen_Item *_it;
4570    Elm_Object_Item *it2;
4571    _it = (Elm_Gen_Item *) it;
4572
4573    EINA_LIST_FOREACH(_it->item->items, l, it2)
4574      tl = eina_list_append(tl, it2);
4575    EINA_LIST_FREE(tl, it2)
4576      elm_object_item_del(it2);
4577 }
4578
4579 EAPI void
4580 elm_genlist_item_selected_set(Elm_Object_Item *it,
4581                               Eina_Bool selected)
4582 {
4583    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4584    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4585    Widget_Data *wd = _it->wd;
4586    if (!wd) return;
4587    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4588      return;
4589    selected = !!selected;
4590    if (_it->selected == selected) return;
4591
4592    if (selected)
4593      {
4594         if (!wd->multi)
4595           {
4596              while (wd->selected)
4597                {
4598                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4599                   _it->unsel_cb(wd->selected->data);
4600                }
4601           }
4602         _it->highlight_cb(_it);
4603         _item_select(_it);
4604         return;
4605      }
4606    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4607    _it->unsel_cb(_it);
4608 }
4609
4610 EAPI Eina_Bool
4611 elm_genlist_item_selected_get(const Elm_Object_Item *it)
4612 {
4613    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4614    return ((Elm_Gen_Item *) it)->selected;
4615 }
4616
4617 EAPI void
4618 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
4619                               Eina_Bool         expanded)
4620 {
4621    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4622    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4623    expanded = !!expanded;
4624    if (_it->item->expanded == expanded) return;
4625    _it->item->expanded = expanded;
4626    if (_it->item->expanded)
4627      {
4628         if (_it->realized)
4629           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4630         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4631         _it->wd->auto_scroll_enabled = EINA_TRUE;
4632         _it->wd->expanded_item = _it;
4633      }
4634    else
4635      {
4636         if (_it->realized)
4637           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4638         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4639         _it->wd->auto_scroll_enabled = EINA_FALSE;
4640         _it->wd->expanded_item = NULL;
4641      }
4642 }
4643
4644 EAPI Eina_Bool
4645 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4646 {
4647    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4648    return ((Elm_Gen_Item *) it)->item->expanded;
4649 }
4650
4651 EAPI int
4652 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4653 {
4654    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4655    return ((Elm_Gen_Item *) it)->item->expanded_depth;
4656 }
4657
4658 EINA_DEPRECATED EAPI void
4659 elm_genlist_item_disabled_set(Elm_Object_Item  *it,
4660                               Eina_Bool         disabled)
4661 {
4662    elm_object_item_disabled_set(it, disabled);
4663 }
4664
4665 EINA_DEPRECATED EAPI Eina_Bool
4666 elm_genlist_item_disabled_get(const Elm_Object_Item *it)
4667 {
4668    return elm_object_item_disabled_get(it);
4669 }
4670
4671 EAPI void
4672 elm_genlist_item_display_only_set(Elm_Object_Item  *it,
4673                                   Eina_Bool         display_only)
4674 {
4675    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4676    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4677    display_only = !!display_only;
4678    if (_it->display_only == display_only) return;
4679    if (_it->generation < _it->wd->generation) return;
4680    _it->display_only = display_only;
4681    _it->item->mincalcd = EINA_FALSE;
4682    _it->item->updateme = EINA_TRUE;
4683    if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
4684    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4685    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4686 }
4687
4688 EAPI Eina_Bool
4689 elm_genlist_item_display_only_get(const Elm_Object_Item *it)
4690 {
4691    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4692    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4693    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4694    return _it->display_only;
4695 }
4696
4697 EAPI void
4698 elm_genlist_item_show(Elm_Object_Item *it)
4699 {
4700    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4701    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4702    Evas_Coord gith = 0;
4703    if (_it->generation < _it->wd->generation) return;
4704    if ((_it->item->queued) || (!_it->item->mincalcd))
4705      {
4706         _it->wd->show_item = _it;
4707         _it->wd->bring_in = EINA_FALSE;
4708         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
4709         _it->item->showme = EINA_TRUE;
4710         return;
4711      }
4712    if (_it->wd->show_item)
4713      {
4714         _it->wd->show_item->item->showme = EINA_FALSE;
4715         _it->wd->show_item = NULL;
4716      }
4717    if ((_it->item->group_item) &&
4718        (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4719      gith = _it->item->group_item->item->h;
4720    elm_smart_scroller_child_region_show(_it->wd->scr,
4721                                         _it->x + _it->item->block->x,
4722                                         _it->y + _it->item->block->y - gith,
4723                                         _it->item->block->w, _it->item->h);
4724 }
4725
4726 EAPI void
4727 elm_genlist_item_promote(Elm_Object_Item *it)
4728 {
4729    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4730    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4731    if (_it->generation < _it->wd->generation) return;
4732    _item_move_before(_it,
4733                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4734 }
4735
4736 EAPI void
4737 elm_genlist_item_demote(Elm_Object_Item *it)
4738 {
4739    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4740    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4741    if (_it->generation < _it->wd->generation) return;
4742    _item_move_after(_it,
4743                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4744 }
4745
4746 EAPI void
4747 elm_genlist_item_bring_in(Elm_Object_Item *it)
4748 {
4749    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4750    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4751    Evas_Coord gith = 0;
4752    if (_it->generation < _it->wd->generation) return;
4753    if ((_it->item->queued) || (!_it->item->mincalcd))
4754      {
4755         _it->wd->show_item = _it;
4756         _it->wd->bring_in = EINA_TRUE;
4757         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
4758         _it->item->showme = EINA_TRUE;
4759         return;
4760      }
4761    if (_it->wd->show_item)
4762      {
4763         _it->wd->show_item->item->showme = EINA_FALSE;
4764         _it->wd->show_item = NULL;
4765      }
4766    if ((_it->item->group_item) &&
4767        (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4768      gith = _it->item->group_item->item->h;
4769    elm_smart_scroller_region_bring_in(_it->wd->scr,
4770                                       _it->x + _it->item->block->x,
4771                                       _it->y + _it->item->block->y - gith,
4772                                       _it->item->block->w, _it->item->h);
4773 }
4774
4775 EAPI void
4776 elm_genlist_item_top_show(Elm_Object_Item *it)
4777 {
4778    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4779    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4780    Evas_Coord ow, oh;
4781    Evas_Coord gith = 0;
4782
4783    if (_it->generation < _it->wd->generation) return;
4784    if ((_it->item->queued) || (!_it->item->mincalcd))
4785      {
4786         _it->wd->show_item = _it;
4787         _it->wd->bring_in = EINA_FALSE;
4788         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
4789         _it->item->showme = EINA_TRUE;
4790         return;
4791      }
4792    if (_it->wd->show_item)
4793      {
4794         _it->wd->show_item->item->showme = EINA_FALSE;
4795         _it->wd->show_item = NULL;
4796      }
4797    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4798    if (_it->item->group_item) gith = _it->item->group_item->item->h;
4799    elm_smart_scroller_child_region_show(_it->wd->scr,
4800                                         _it->x + _it->item->block->x,
4801                                         _it->y + _it->item->block->y - gith,
4802                                         _it->item->block->w, oh);
4803 }
4804
4805 EAPI void
4806 elm_genlist_item_top_bring_in(Elm_Object_Item *it)
4807 {
4808    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4809    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4810    Evas_Coord ow, oh;
4811    Evas_Coord gith = 0;
4812
4813    if (_it->generation < _it->wd->generation) return;
4814    if ((_it->item->queued) || (!_it->item->mincalcd))
4815      {
4816         _it->wd->show_item = _it;
4817         _it->wd->bring_in = EINA_TRUE;
4818         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
4819         _it->item->showme = EINA_TRUE;
4820         return;
4821      }
4822    if (_it->wd->show_item)
4823      {
4824         _it->wd->show_item->item->showme = EINA_FALSE;
4825         _it->wd->show_item = NULL;
4826      }
4827    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4828    if (_it->item->group_item) gith = _it->item->group_item->item->h;
4829    elm_smart_scroller_region_bring_in(_it->wd->scr,
4830                                       _it->x + _it->item->block->x,
4831                                       _it->y + _it->item->block->y - gith,
4832                                       _it->item->block->w, oh);
4833 }
4834
4835 EAPI void
4836 elm_genlist_item_middle_show(Elm_Object_Item *it)
4837 {
4838    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4839    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4840    Evas_Coord ow, oh;
4841
4842    if (_it->generation < _it->wd->generation) return;
4843    if ((_it->item->queued) || (!_it->item->mincalcd))
4844      {
4845         _it->wd->show_item = _it;
4846         _it->wd->bring_in = EINA_FALSE;
4847         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
4848         _it->item->showme = EINA_TRUE;
4849         return;
4850      }
4851    if (_it->wd->show_item)
4852      {
4853         _it->wd->show_item->item->showme = EINA_FALSE;
4854         _it->wd->show_item = NULL;
4855      }
4856    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4857    elm_smart_scroller_child_region_show(_it->wd->scr,
4858                                         _it->x + _it->item->block->x,
4859                                         _it->y + _it->item->block->y - oh / 2 +
4860                                         _it->item->h / 2, _it->item->block->w,
4861                                         oh);
4862 }
4863
4864 EAPI void
4865 elm_genlist_item_middle_bring_in(Elm_Object_Item *it)
4866 {
4867    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4868    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4869    Evas_Coord ow, oh;
4870
4871    if (_it->generation < _it->wd->generation) return;
4872    if ((_it->item->queued) || (!_it->item->mincalcd))
4873      {
4874         _it->wd->show_item = _it;
4875         _it->wd->bring_in = EINA_TRUE;
4876         _it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
4877         _it->item->showme = EINA_TRUE;
4878         return;
4879      }
4880    if (_it->wd->show_item)
4881      {
4882         _it->wd->show_item->item->showme = EINA_FALSE;
4883         _it->wd->show_item = NULL;
4884      }
4885    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, &ow, &oh);
4886    elm_smart_scroller_region_bring_in(_it->wd->scr,
4887                                       _it->x + _it->item->block->x,
4888                                       _it->y + _it->item->block->y - oh / 2 +
4889                                       _it->item->h / 2, _it->item->block->w,
4890                                       oh);
4891 }
4892
4893 EAPI void
4894 elm_genlist_item_del(Elm_Object_Item *it)
4895 {
4896    elm_object_item_del(it);
4897 }
4898
4899 EAPI void
4900 elm_genlist_item_data_set(Elm_Object_Item  *it,
4901                           const void       *data)
4902 {
4903    elm_object_item_data_set(it, (void *) data);
4904 }
4905
4906 EAPI void *
4907 elm_genlist_item_data_get(const Elm_Object_Item *it)
4908 {
4909    return elm_object_item_data_get(it);
4910 }
4911
4912 EAPI void
4913 elm_genlist_item_icons_orphan(Elm_Object_Item *it)
4914 {
4915    elm_genlist_item_contents_orphan(it);
4916 }
4917
4918 EAPI void
4919 elm_genlist_item_contents_orphan(Elm_Object_Item *it)
4920 {
4921    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4922
4923    Evas_Object *content;
4924    EINA_LIST_FREE(((Elm_Gen_Item *) it)->content_objs, content)
4925      {
4926         elm_widget_sub_object_del(WIDGET(it), content);
4927         evas_object_smart_member_del(content);
4928         evas_object_hide(content);
4929      }
4930 }
4931
4932 EINA_DEPRECATED EAPI const Evas_Object *
4933 elm_genlist_item_object_get(const Elm_Object_Item *it)
4934 {
4935    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4936    return VIEW(it);
4937 }
4938
4939 EAPI void
4940 elm_genlist_item_update(Elm_Object_Item *it)
4941 {
4942    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4943    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4944
4945    if (!_it->item->block) return;
4946    if (_it->generation < _it->wd->generation) return;
4947    _it->item->mincalcd = EINA_FALSE;
4948    _it->item->updateme = EINA_TRUE;
4949    _it->item->block->updateme = EINA_TRUE;
4950    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4951    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4952 }
4953
4954 EAPI void
4955 elm_genlist_item_fields_update(Elm_Object_Item *it,
4956                                const char *parts,
4957                                Elm_Genlist_Item_Field_Flags itf)
4958 {
4959    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4960    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4961
4962    if (!_it->item->block) return;
4963    if (_it->generation < _it->wd->generation) return;
4964
4965    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
4966      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
4967    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4968      {
4969         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
4970                                                    &_it->contents, parts);
4971         _it->content_objs = _item_content_realize(_it, VIEW(_it),
4972                                                  &_it->contents, parts);
4973      }
4974    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4975      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
4976 }
4977
4978 EAPI void
4979 elm_genlist_item_item_class_update(Elm_Object_Item *it,
4980                                    const Elm_Genlist_Item_Class *itc)
4981 {
4982    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4983    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4984
4985    if (!_it->item->block) return;
4986    EINA_SAFETY_ON_NULL_RETURN(itc);
4987    if (_it->generation < _it->wd->generation) return;
4988    _it->itc = itc;
4989    _it->item->nocache = EINA_TRUE;
4990    elm_genlist_item_update(it);
4991 }
4992
4993 EAPI const Elm_Genlist_Item_Class *
4994 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
4995 {
4996    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4997    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4998    if (_it->generation < _it->wd->generation) return NULL;
4999    return _it->itc;
5000 }
5001
5002 static Evas_Object *
5003 _elm_genlist_item_label_create(void        *data,
5004                                Evas_Object *obj __UNUSED__,
5005                                Evas_Object *tooltip,
5006                                void        *it __UNUSED__)
5007 {
5008    Evas_Object *label = elm_label_add(tooltip);
5009    if (!label)
5010      return NULL;
5011    elm_object_style_set(label, "tooltip");
5012    elm_object_text_set(label, data);
5013    return label;
5014 }
5015
5016 static void
5017 _elm_genlist_item_label_del_cb(void        *data,
5018                                Evas_Object *obj __UNUSED__,
5019                                void        *event_info __UNUSED__)
5020 {
5021    eina_stringshare_del(data);
5022 }
5023
5024 EAPI void
5025 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5026                                   const char      *text)
5027 {
5028    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5029    text = eina_stringshare_add(text);
5030    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5031                                            text,
5032                                            _elm_genlist_item_label_del_cb);
5033 }
5034
5035 EAPI void
5036 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
5037                                         Elm_Tooltip_Item_Content_Cb func,
5038                                         const void                 *data,
5039                                         Evas_Smart_Cb               del_cb)
5040 {
5041    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5042    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5043
5044    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5045      return;
5046
5047    if (_it->tooltip.del_cb)
5048      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5049
5050    _it->tooltip.content_cb = func;
5051    _it->tooltip.data = data;
5052    _it->tooltip.del_cb = del_cb;
5053
5054    if (VIEW(_it))
5055      {
5056         elm_widget_item_tooltip_content_cb_set(_it,
5057                                                _it->tooltip.content_cb,
5058                                                _it->tooltip.data, NULL);
5059         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5060         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5061      }
5062
5063    return;
5064
5065 error:
5066    if (del_cb) del_cb((void *)data, NULL, NULL);
5067 }
5068
5069 EAPI void
5070 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5071 {
5072    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5073    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5074
5075    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5076      elm_widget_item_tooltip_unset(_it);
5077
5078    if (_it->tooltip.del_cb)
5079      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5080    _it->tooltip.del_cb = NULL;
5081    _it->tooltip.content_cb = NULL;
5082    _it->tooltip.data = NULL;
5083    _it->tooltip.free_size = EINA_FALSE;
5084    if (_it->tooltip.style)
5085      elm_genlist_item_tooltip_style_set(it, NULL);
5086 }
5087
5088 EAPI void
5089 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5090                                    const char       *style)
5091 {
5092    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5093    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5094
5095    eina_stringshare_replace(&_it->tooltip.style, style);
5096    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5097 }
5098
5099 EAPI const char *
5100 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5101 {
5102    return elm_object_item_tooltip_style_get(it);
5103 }
5104
5105 EAPI Eina_Bool
5106 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5107                                          Eina_Bool disable)
5108 {
5109    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5110    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5111
5112    _it->tooltip.free_size = disable;
5113    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5114    return EINA_TRUE;
5115 }
5116
5117 EAPI Eina_Bool
5118 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5119 {
5120    return elm_object_tooltip_window_mode_get(VIEW(it));
5121 }
5122
5123 EAPI void
5124 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5125                             const char       *cursor)
5126 {
5127    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5128    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5129    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5130    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5131 }
5132
5133 EAPI const char *
5134 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5135 {
5136    return elm_widget_item_cursor_get(it);
5137 }
5138
5139 EAPI void
5140 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5141 {
5142    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5143    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5144
5145    if (!_it->mouse_cursor) return;
5146
5147    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5148
5149    eina_stringshare_del(_it->mouse_cursor);
5150    _it->mouse_cursor = NULL;
5151 }
5152
5153 EAPI void
5154 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
5155                                   const char       *style)
5156 {
5157    elm_widget_item_cursor_style_set(it, style);
5158 }
5159
5160 EAPI const char *
5161 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5162 {
5163    return elm_widget_item_cursor_style_get(it);
5164 }
5165
5166 EAPI void
5167 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5168                                         Eina_Bool        engine_only)
5169 {
5170    elm_widget_item_cursor_engine_only_set(it, engine_only);
5171 }
5172
5173 EAPI Eina_Bool
5174 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5175 {
5176    return elm_widget_item_cursor_engine_only_get(it);
5177 }
5178
5179 EAPI int
5180 elm_genlist_item_index_get(const Elm_Object_Item *it)
5181 {
5182    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5183    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5184
5185    if (_it->item->block)
5186      return _it->position + _it->item->block->position;
5187    return -1;
5188 }
5189
5190 EAPI void
5191 elm_genlist_mode_set(Evas_Object  *obj,
5192                      Elm_List_Mode mode)
5193 {
5194    ELM_CHECK_WIDTYPE(obj, widtype);
5195    Widget_Data *wd = elm_widget_data_get(obj);
5196    if (!wd) return;
5197    if (wd->mode == mode) return;
5198    wd->mode = mode;
5199    _sizing_eval(obj);
5200 }
5201
5202 EAPI void
5203 elm_genlist_horizontal_set(Evas_Object  *obj,
5204                            Elm_List_Mode mode)
5205 {
5206    elm_genlist_mode_set(obj, mode);
5207 }
5208
5209 EAPI void
5210 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
5211                                 Elm_List_Mode mode)
5212 {
5213    elm_genlist_mode_set(obj, mode);
5214 }
5215
5216 EAPI Elm_List_Mode
5217 elm_genlist_mode_get(const Evas_Object *obj)
5218 {
5219    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5220    Widget_Data *wd = elm_widget_data_get(obj);
5221    if (!wd) return ELM_LIST_LAST;
5222    return wd->mode;
5223 }
5224
5225 EINA_DEPRECATED EAPI Elm_List_Mode
5226 elm_genlist_horizontal_get(const Evas_Object *obj)
5227 {
5228    return elm_genlist_mode_get(obj);
5229 }
5230
5231 EINA_DEPRECATED EAPI Elm_List_Mode
5232 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
5233 {
5234    return elm_genlist_mode_get(obj);
5235 }
5236
5237 EAPI void
5238 elm_genlist_always_select_mode_set(Evas_Object *obj,
5239                                    Eina_Bool    always_select)
5240 {
5241    ELM_CHECK_WIDTYPE(obj, widtype);
5242    Widget_Data *wd = elm_widget_data_get(obj);
5243    if (!wd) return;
5244    wd->always_select = !!always_select;
5245 }
5246
5247 EAPI Eina_Bool
5248 elm_genlist_always_select_mode_get(const Evas_Object *obj)
5249 {
5250    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5251    Widget_Data *wd = elm_widget_data_get(obj);
5252    if (!wd) return EINA_FALSE;
5253    return wd->always_select;
5254 }
5255
5256 EAPI void
5257 elm_genlist_no_select_mode_set(Evas_Object *obj,
5258                                Eina_Bool    no_select)
5259 {
5260    ELM_CHECK_WIDTYPE(obj, widtype);
5261    Widget_Data *wd = elm_widget_data_get(obj);
5262    if (!wd) return;
5263    wd->no_select = !!no_select;
5264 }
5265
5266 EAPI Eina_Bool
5267 elm_genlist_no_select_mode_get(const Evas_Object *obj)
5268 {
5269    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5270    Widget_Data *wd = elm_widget_data_get(obj);
5271    if (!wd) return EINA_FALSE;
5272    return wd->no_select;
5273 }
5274
5275 EAPI void
5276 elm_genlist_compress_mode_set(Evas_Object *obj,
5277                               Eina_Bool    compress)
5278 {
5279    ELM_CHECK_WIDTYPE(obj, widtype);
5280    Widget_Data *wd = elm_widget_data_get(obj);
5281    if (!wd) return;
5282    wd->compress = !!compress;
5283    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
5284 }
5285
5286 EAPI Eina_Bool
5287 elm_genlist_compress_mode_get(const Evas_Object *obj)
5288 {
5289    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5290    Widget_Data *wd = elm_widget_data_get(obj);
5291    if (!wd) return EINA_FALSE;
5292    return wd->compress;
5293 }
5294
5295 EAPI void
5296 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5297                                       Eina_Bool    height_for_width)
5298 {
5299    ELM_CHECK_WIDTYPE(obj, widtype);
5300    Widget_Data *wd = elm_widget_data_get(obj);
5301    if (!wd) return;
5302    wd->height_for_width = !!height_for_width;
5303    if (wd->height_for_width)
5304      {
5305         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5306         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5307      }
5308 }
5309
5310 EAPI Eina_Bool
5311 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5312 {
5313    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5314    Widget_Data *wd = elm_widget_data_get(obj);
5315    if (!wd) return EINA_FALSE;
5316    return wd->height_for_width;
5317 }
5318
5319 EAPI void
5320 elm_genlist_bounce_set(Evas_Object *obj,
5321                        Eina_Bool    h_bounce,
5322                        Eina_Bool    v_bounce)
5323 {
5324    ELM_CHECK_WIDTYPE(obj, widtype);
5325    Widget_Data *wd = elm_widget_data_get(obj);
5326    if (!wd) return;
5327    wd->h_bounce = !!h_bounce;
5328    wd->v_bounce = !!v_bounce;
5329    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5330 }
5331
5332 EAPI void
5333 elm_genlist_bounce_get(const Evas_Object *obj,
5334                        Eina_Bool         *h_bounce,
5335                        Eina_Bool         *v_bounce)
5336 {
5337    ELM_CHECK_WIDTYPE(obj, widtype);
5338    Widget_Data *wd = elm_widget_data_get(obj);
5339    if (!wd) return;
5340    if (h_bounce) *h_bounce = wd->h_bounce;
5341    if (v_bounce) *v_bounce = wd->v_bounce;
5342 }
5343
5344 EAPI void
5345 elm_genlist_homogeneous_set(Evas_Object *obj,
5346                             Eina_Bool    homogeneous)
5347 {
5348    ELM_CHECK_WIDTYPE(obj, widtype);
5349    Widget_Data *wd = elm_widget_data_get(obj);
5350    if (!wd) return;
5351    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5352    wd->homogeneous = !!homogeneous;
5353 }
5354
5355 EAPI Eina_Bool
5356 elm_genlist_homogeneous_get(const Evas_Object *obj)
5357 {
5358    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5359    Widget_Data *wd = elm_widget_data_get(obj);
5360    if (!wd) return EINA_FALSE;
5361    return wd->homogeneous;
5362 }
5363
5364 EAPI void
5365 elm_genlist_block_count_set(Evas_Object *obj,
5366                             int          count)
5367 {
5368    ELM_CHECK_WIDTYPE(obj, widtype);
5369    Widget_Data *wd = elm_widget_data_get(obj);
5370    if (!wd) return;
5371    wd->max_items_per_block = count;
5372    wd->item_cache_max = wd->max_items_per_block * 2;
5373    _item_cache_clean(wd);
5374 }
5375
5376 EAPI int
5377 elm_genlist_block_count_get(const Evas_Object *obj)
5378 {
5379    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5380    Widget_Data *wd = elm_widget_data_get(obj);
5381    if (!wd) return 0;
5382    return wd->max_items_per_block;
5383 }
5384
5385 EAPI void
5386 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5387                                   double       timeout)
5388 {
5389    ELM_CHECK_WIDTYPE(obj, widtype);
5390    Widget_Data *wd = elm_widget_data_get(obj);
5391    if (!wd) return;
5392    wd->longpress_timeout = timeout;
5393 }
5394
5395 EAPI double
5396 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5397 {
5398    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5399    Widget_Data *wd = elm_widget_data_get(obj);
5400    if (!wd) return 0;
5401    return wd->longpress_timeout;
5402 }
5403
5404 EAPI void
5405 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5406                                 Elm_Scroller_Policy policy_h,
5407                                 Elm_Scroller_Policy policy_v)
5408 {
5409    ELM_CHECK_WIDTYPE(obj, widtype);
5410    Widget_Data *wd = elm_widget_data_get(obj);
5411    if ((!wd) || (!wd->scr)) return;
5412    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5413        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5414      return;
5415    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5416 }
5417
5418 EAPI void
5419 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5420                                 Elm_Scroller_Policy *policy_h,
5421                                 Elm_Scroller_Policy *policy_v)
5422 {
5423    ELM_CHECK_WIDTYPE(obj, widtype);
5424    Widget_Data *wd = elm_widget_data_get(obj);
5425    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5426    if ((!wd) || (!wd->scr)) return;
5427    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5428    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5429    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5430 }
5431
5432 EAPI void
5433 elm_genlist_realized_items_update(Evas_Object *obj)
5434 {
5435    ELM_CHECK_WIDTYPE(obj, widtype);
5436
5437    Eina_List *list, *l;
5438    Elm_Object_Item *it;
5439
5440    list = elm_genlist_realized_items_get(obj);
5441    EINA_LIST_FOREACH(list, l, it)
5442      elm_genlist_item_update(it);
5443 }
5444
5445 EAPI void
5446 elm_genlist_item_mode_set(Elm_Object_Item  *it,
5447                           const char       *mode_type,
5448                           Eina_Bool         mode_set)
5449 {
5450    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5451    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5452
5453    Widget_Data *wd = _it->wd;
5454    Eina_List *l;
5455    Elm_Object_Item *it2;
5456
5457    if (!wd) return;
5458    if (!mode_type) return;
5459    if ((_it->generation < _it->wd->generation) ||
5460        elm_widget_item_disabled_get(_it)) return;
5461    if (wd->edit_mode) return;
5462
5463    if ((wd->mode_item == _it) &&
5464        (!strcmp(mode_type, wd->mode_type)) &&
5465        (mode_set))
5466       return;
5467    if (!_it->itc->mode_item_style) return;
5468    _it->mode_set = mode_set;
5469
5470    if (wd->multi)
5471      {
5472         EINA_LIST_FOREACH(wd->selected, l, it2)
5473           if (((Elm_Gen_Item *) it2)->realized)
5474             elm_genlist_item_selected_set(it2, EINA_FALSE);
5475      }
5476    else
5477      {
5478         it2 = elm_genlist_selected_item_get(wd->obj);
5479         if ((it2) && (((Elm_Gen_Item *) it2)->realized))
5480           elm_genlist_item_selected_set(it2, EINA_FALSE);
5481      }
5482
5483    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5484        (mode_set) ||
5485        ((_it == wd->mode_item) && (!mode_set)))
5486      _item_mode_unset(wd);
5487
5488    eina_stringshare_replace(&wd->mode_type, mode_type);
5489    if (mode_set) _item_mode_set(_it);
5490 }
5491
5492 EAPI const char *
5493 elm_genlist_mode_item_style_get(const Evas_Object *obj)
5494 {
5495    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5496    Widget_Data *wd = elm_widget_data_get(obj);
5497    if (!wd) return NULL;
5498    return wd->mode_item->itc->mode_item_style;
5499 }
5500
5501 EAPI void
5502 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
5503 {
5504    ELM_CHECK_WIDTYPE(obj, widtype);
5505    Widget_Data *wd = elm_widget_data_get(obj);
5506    if (!wd) return;
5507    if ((style == wd->mode_item->itc->mode_item_style) ||
5508        (style && wd->mode_item->itc->mode_item_style &&
5509        (!strcmp(style, wd->mode_item->itc->mode_item_style))))
5510      return;
5511    eina_stringshare_replace((const char**)&wd->mode_item->itc->mode_item_style, style);
5512    elm_genlist_realized_items_update(obj);
5513 }
5514
5515 EAPI const char *
5516 elm_genlist_mode_type_get(const Evas_Object *obj)
5517 {
5518    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5519    Widget_Data *wd = elm_widget_data_get(obj);
5520    if (!wd) return NULL;
5521    return wd->mode_type;
5522 }
5523
5524 EAPI const Elm_Object_Item *
5525 elm_genlist_mode_item_get(const Evas_Object *obj)
5526 {
5527    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5528    Widget_Data *wd = elm_widget_data_get(obj);
5529    if (!wd) return NULL;
5530    return (Elm_Object_Item *) wd->mode_item;
5531 }
5532
5533 EAPI Eina_Bool
5534 elm_genlist_edit_mode_get(const Evas_Object *obj)
5535 {
5536    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5537    Widget_Data *wd = elm_widget_data_get(obj);
5538    if (!wd) return EINA_FALSE;
5539
5540    return wd->edit_mode;
5541 }
5542
5543 EAPI void
5544 elm_genlist_edit_mode_set(Evas_Object *obj, Eina_Bool edit_mode)
5545 {
5546    ELM_CHECK_WIDTYPE(obj, widtype);
5547    Eina_List *list, *l;
5548    Elm_Gen_Item *it;
5549
5550    Widget_Data *wd = elm_widget_data_get(obj);
5551    if (!wd) return;
5552    edit_mode = !!edit_mode;
5553    if (wd->edit_mode == edit_mode) return;
5554    wd->edit_mode = edit_mode;
5555
5556    list = elm_genlist_realized_items_get(obj);
5557    if (!wd->edit_mode)
5558      {
5559         EINA_LIST_FOREACH(list, l, it)
5560           {
5561              if (it->item->flags != ELM_GENLIST_ITEM_GROUP)
5562                _edit_mode_item_unrealize(it);
5563           }
5564         _item_cache_zero(wd);
5565      }
5566    else
5567      {
5568         EINA_LIST_FOREACH(list, l, it)
5569           {
5570              if (it->item->flags != ELM_GENLIST_ITEM_GROUP)
5571                {
5572                   if (it->selected) _item_unselect(it);
5573                   if (it->itc->edit_item_style)
5574                      _edit_mode_item_realize(it, EINA_TRUE);
5575                }
5576           }
5577      }
5578    if (wd->calc_job) ecore_job_del(wd->calc_job);
5579    wd->calc_job = ecore_job_add(_calc_job, wd);
5580 }
5581
5582 EAPI void
5583 elm_genlist_reorder_mode_set(Evas_Object *obj,
5584                              Eina_Bool    reorder_mode)
5585 {
5586    ELM_CHECK_WIDTYPE(obj, widtype);
5587    Widget_Data *wd = elm_widget_data_get(obj);
5588    if (!wd) return;
5589    wd->reorder_mode = !!reorder_mode;
5590 }
5591
5592 EAPI Eina_Bool
5593 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5594 {
5595    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5596    Widget_Data *wd = elm_widget_data_get(obj);
5597    if (!wd) return EINA_FALSE;
5598    return wd->reorder_mode;
5599 }
5600
5601 EAPI Elm_Genlist_Item_Flags
5602 elm_genlist_item_flags_get(const Elm_Object_Item *it)
5603 {
5604    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5605    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
5606    return _it->item->flags;
5607 }
5608
5609 EAPI Elm_Genlist_Item_Class *
5610 elm_genlist_item_class_new(void)
5611 {
5612    Elm_Genlist_Item_Class *itc;
5613
5614    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5615    if (!itc)
5616      return NULL;
5617    itc->version = ELM_GENLIST_ITEM_CLASS_VERSION;
5618    itc->refcount = 1;
5619    itc->delete_me = EINA_FALSE;
5620
5621    return itc;
5622 }
5623
5624 EAPI void
5625 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5626 {
5627    ELM_GENLIST_CHECK_ITC_VER(itc);
5628    if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5629    if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5630    else
5631      {
5632         itc->version = 0;
5633         free(itc);
5634      }
5635 }
5636
5637 EAPI void
5638 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5639 {
5640    ELM_GENLIST_CHECK_ITC_VER(itc);
5641
5642    itc->refcount++;
5643    if (itc->refcount == 0) itc->refcount--;
5644 }
5645
5646 EAPI void
5647 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5648 {
5649    ELM_GENLIST_CHECK_ITC_VER(itc);
5650
5651    if (itc->refcount > 0) itc->refcount--;
5652    if (itc->delete_me && (!itc->refcount))
5653      elm_genlist_item_class_free(itc);
5654 }
5655
5656 /* for gengrid as of now */
5657 void
5658 _elm_genlist_page_relative_set(Evas_Object *obj,
5659                                double       h_pagerel,
5660                                double       v_pagerel)
5661 {
5662    Evas_Coord pagesize_h;
5663    Evas_Coord pagesize_v;
5664
5665    ELM_CHECK_WIDTYPE(obj, widtype);
5666    Widget_Data *wd = elm_widget_data_get(obj);
5667    if (!wd) return;
5668
5669    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5670    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5671                                  pagesize_v);
5672 }
5673
5674 /* for gengrid as of now */
5675 void
5676 _elm_genlist_page_relative_get(const Evas_Object *obj,
5677                                double            *h_pagerel,
5678                                double            *v_pagerel)
5679 {
5680    ELM_CHECK_WIDTYPE(obj, widtype);
5681    Widget_Data *wd = elm_widget_data_get(obj);
5682    if (!wd) return;
5683
5684    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5685 }
5686
5687 /* for gengrid as of now */
5688 void
5689 _elm_genlist_page_size_set(Evas_Object *obj,
5690                            Evas_Coord   h_pagesize,
5691                            Evas_Coord   v_pagesize)
5692 {
5693    double pagerel_h;
5694    double pagerel_v;
5695
5696    ELM_CHECK_WIDTYPE(obj, widtype);
5697    Widget_Data *wd = elm_widget_data_get(obj);
5698    if (!wd) return;
5699    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5700    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5701                                  v_pagesize);
5702 }
5703
5704 /* for gengrid as of now */
5705 void
5706 _elm_genlist_current_page_get(const Evas_Object *obj,
5707                               int               *h_pagenumber,
5708                               int               *v_pagenumber)
5709 {
5710    ELM_CHECK_WIDTYPE(obj, widtype);
5711    Widget_Data *wd = elm_widget_data_get(obj);
5712    if (!wd) return;
5713    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5714 }
5715
5716 /* for gengrid as of now */
5717 void
5718 _elm_genlist_last_page_get(const Evas_Object *obj,
5719                            int               *h_pagenumber,
5720                            int               *v_pagenumber)
5721 {
5722    ELM_CHECK_WIDTYPE(obj, widtype);
5723    Widget_Data *wd = elm_widget_data_get(obj);
5724    if (!wd) return;
5725    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5726 }
5727
5728 /* for gengrid as of now */
5729 void
5730 _elm_genlist_page_show(const Evas_Object *obj,
5731                        int                h_pagenumber,
5732                        int                v_pagenumber)
5733 {
5734    ELM_CHECK_WIDTYPE(obj, widtype);
5735    Widget_Data *wd = elm_widget_data_get(obj);
5736    if (!wd) return;
5737    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5738 }
5739
5740 /* for gengrid as of now */
5741 void
5742 _elm_genlist_page_bring_in(const Evas_Object *obj,
5743                            int                h_pagenumber,
5744                            int                v_pagenumber)
5745 {
5746    ELM_CHECK_WIDTYPE(obj, widtype);
5747    Widget_Data *wd = elm_widget_data_get(obj);
5748    if (!wd) return;
5749    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5750 }
5751
5752 void
5753 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5754                             Eina_Bool     calc)
5755 {
5756    Evas_Object *content;
5757
5758    if (!it->realized) return;
5759    if (it->wd->reorder_it == it) return;
5760
5761    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5762    if (!calc)
5763      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5764    if (it->long_timer)
5765      {
5766         ecore_timer_del(it->long_timer);
5767         it->long_timer = NULL;
5768      }
5769
5770    elm_widget_stringlist_free(it->texts);
5771    it->texts = NULL;
5772    elm_widget_stringlist_free(it->contents);
5773    it->contents = NULL;
5774    elm_widget_stringlist_free(it->states);
5775    it->states = NULL;
5776
5777    EINA_LIST_FREE(it->content_objs, content)
5778      evas_object_del(content);
5779
5780    it->unrealize_cb(it);
5781
5782    it->realized = EINA_FALSE;
5783    it->want_unrealize = EINA_FALSE;
5784    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5785    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5786 }
5787
5788 void
5789 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5790 {
5791    elm_widget_item_pre_notify_del(it);
5792    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5793    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5794
5795    if (it->itc->func.del)
5796      it->itc->func.del((void *)it->base.data, WIDGET(it));
5797 }
5798
5799 void
5800 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5801 {
5802    _elm_genlist_item_del_notserious(it);
5803    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5804    if (it->tooltip.del_cb)
5805      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5806    it->wd->walking -= it->walking;
5807    if (it->long_timer) ecore_timer_del(it->long_timer);
5808    if (it->group)
5809      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5810
5811    if (it->wd->state)
5812      {
5813         eina_inlist_sorted_state_free(it->wd->state);
5814         it->wd->state = NULL;
5815      }
5816    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5817    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5818    free(it->item);
5819
5820    it->item = NULL;
5821    if (it->wd->last_selected_item == (Elm_Object_Item *) it)
5822      it->wd->last_selected_item = NULL;
5823    it->wd->item_count--;
5824 }