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