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