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