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