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