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