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