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