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