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