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