[genlist] prevent on_focus_hook at zero items
[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->items) && (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              if(wd->pan_changed)
3747                {
3748                   if (wd->calc_job) ecore_job_del(wd->calc_job);
3749                   wd->calc_job = NULL;
3750                   _calc_job(wd);
3751                   wd->pan_changed = EINA_FALSE;
3752                }
3753           }
3754         if (showme) it->block->showme = EINA_TRUE;
3755         if (eina_inlist_count(wd->blocks) > 1)
3756           {
3757              if ((t - t0) > (ecore_animator_frametime_get())) break;
3758           }
3759      }
3760    //evas_event_thaw(evas_object_evas_get(wd->obj));
3761    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3762    return n;
3763 }
3764
3765 static Eina_Bool
3766 _idle_process(void *data, Eina_Bool *wakeup)
3767 {
3768    Widget_Data *wd = data;
3769
3770    //xxx
3771    //static double q_start = 0.0;
3772    //if (q_start == 0.0) q_start = ecore_time_get();
3773    //xxx
3774    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3775    if (!wd->queue)
3776      {
3777         //xxx
3778         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3779         //xxx
3780         return ECORE_CALLBACK_CANCEL;
3781      }
3782    return ECORE_CALLBACK_RENEW;
3783 }
3784
3785 static Eina_Bool
3786 _item_idle_enterer(void *data)
3787 {
3788    Widget_Data *wd = data;
3789    Eina_Bool wakeup = EINA_FALSE;
3790    Eina_Bool ok = _idle_process(data, &wakeup);
3791
3792    if (wakeup)
3793      {
3794         // wake up mainloop
3795         if (wd->calc_job) ecore_job_del(wd->calc_job);
3796         wd->calc_job = ecore_job_add(_calc_job, wd);
3797      }
3798    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3799    return ok;
3800 }
3801
3802 static void
3803 _item_queue(Widget_Data      *wd,
3804             Elm_Genlist_Item *it)
3805 {
3806    if (it->queued) return;
3807    it->queued = EINA_TRUE;
3808    wd->queue = eina_list_append(wd->queue, it);
3809 // FIXME: why does a freeze then thaw here cause some genlist
3810 // elm_genlist_item_append() to be much much slower?
3811 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3812    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3813      {
3814         if (wd->queue_idle_enterer)
3815           {
3816              ecore_idle_enterer_del(wd->queue_idle_enterer);
3817              wd->queue_idle_enterer = NULL;
3818           }
3819         _queue_process(wd);
3820      }
3821 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3822 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3823    if (!wd->queue_idle_enterer)
3824      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3825 }
3826
3827 static void
3828 _item_move_after(Elm_Genlist_Item *it, Elm_Genlist_Item *after)
3829 {
3830    if (!it) return;
3831    if (!after) return;
3832
3833    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3834    it->wd->reorder_deleted = EINA_TRUE;
3835    _item_block_del(it);
3836
3837    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3838    it->rel = after;
3839    it->rel->relcount++;
3840    it->before = EINA_FALSE;
3841    if (after->group_item) it->group_item = after->group_item;
3842    _item_queue(it->wd, it);
3843
3844    // TODO: change this to smart callback
3845    if (it->itc->func.moved)
3846      it->itc->func.moved(it->base.widget, it, after, EINA_TRUE);
3847 }
3848
3849 static void
3850 _item_move_before(Elm_Genlist_Item *it, Elm_Genlist_Item *before)
3851 {
3852    if (!it) return;
3853    if (!before) return;
3854
3855    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3856    it->wd->reorder_deleted = EINA_TRUE;
3857    _item_block_del(it);
3858    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3859    it->rel = before;
3860    it->rel->relcount++;
3861    it->before = EINA_TRUE;
3862    if (before->group_item) it->group_item = before->group_item;
3863    _item_queue(it->wd, it);
3864
3865    // TODO: change this to smart callback
3866    if (it->itc->func.moved)
3867      it->itc->func.moved(it->base.widget, it, before, EINA_FALSE);
3868 }
3869
3870 EAPI Elm_Genlist_Item *
3871 elm_genlist_item_append(Evas_Object                  *obj,
3872                         const Elm_Genlist_Item_Class *itc,
3873                         const void                   *data,
3874                         Elm_Genlist_Item             *parent,
3875                         Elm_Genlist_Item_Flags        flags,
3876                         Evas_Smart_Cb                 func,
3877                         const void                   *func_data)
3878 {
3879    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3880    Widget_Data *wd = elm_widget_data_get(obj);
3881    if (!wd) return NULL;
3882    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
3883                                     func_data);
3884    if (!it) return NULL;
3885    if (!it->parent)
3886      {
3887         if (flags & ELM_GENLIST_ITEM_GROUP)
3888           wd->group_items = eina_list_append(wd->group_items, it);
3889         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3890         it->rel = NULL;
3891      }
3892    else
3893      {
3894         Elm_Genlist_Item *it2 = NULL;
3895         Eina_List *ll = eina_list_last(it->parent->items);
3896         if (ll) it2 = ll->data;
3897         it->parent->items = eina_list_append(it->parent->items, it);
3898         if (!it2) it2 = it->parent;
3899         if (it2->delete_me)
3900            it2 = elm_genlist_item_prev_get(it2);
3901         wd->items =
3902           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3903                                       EINA_INLIST_GET(it2));
3904         it->rel = it2;
3905         it->rel->relcount++;
3906      }
3907    it->before = EINA_FALSE;
3908    _item_queue(wd, it);
3909    return it;
3910 }
3911
3912 EAPI Elm_Genlist_Item *
3913 elm_genlist_item_prepend(Evas_Object                  *obj,
3914                          const Elm_Genlist_Item_Class *itc,
3915                          const void                   *data,
3916                          Elm_Genlist_Item             *parent,
3917                          Elm_Genlist_Item_Flags        flags,
3918                          Evas_Smart_Cb                 func,
3919                          const void                   *func_data)
3920 {
3921    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3922    Widget_Data *wd = elm_widget_data_get(obj);
3923    if (!wd) return NULL;
3924    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
3925                                     func_data);
3926
3927    if (!it) return NULL;
3928    if (!it->parent)
3929      {
3930         if (flags & ELM_GENLIST_ITEM_GROUP)
3931           wd->group_items = eina_list_prepend(wd->group_items, it);
3932         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3933         it->rel = NULL;
3934      }
3935    else
3936      {
3937         Elm_Genlist_Item *it2 = NULL;
3938         Eina_List *ll = it->parent->items;
3939         if (ll) it2 = ll->data;
3940         it->parent->items = eina_list_prepend(it->parent->items, it);
3941         if (!it2) it2 = it->parent;
3942         if (it2->delete_me)
3943            it2 = elm_genlist_item_next_get(it2);
3944         wd->items =
3945           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3946                                        EINA_INLIST_GET(it2));
3947         it->rel = it2;
3948         it->rel->relcount++;
3949      }
3950    it->before = EINA_TRUE;
3951    _item_queue(wd, it);
3952    return it;
3953 }
3954
3955 EAPI Elm_Genlist_Item *
3956 elm_genlist_item_insert_after(Evas_Object                  *obj,
3957                               const Elm_Genlist_Item_Class *itc,
3958                               const void                   *data,
3959                               Elm_Genlist_Item             *parent,
3960                               Elm_Genlist_Item             *after,
3961                               Elm_Genlist_Item_Flags        flags,
3962                               Evas_Smart_Cb                 func,
3963                               const void                   *func_data)
3964 {
3965    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3966    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
3967    Widget_Data *wd = elm_widget_data_get(obj);
3968    if (!wd) return NULL;
3969    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
3970                                     func_data);
3971    if (!it) return NULL;
3972    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
3973    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3974
3975    if (!it->parent)
3976      {
3977         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
3978             (after->flags & ELM_GENLIST_ITEM_GROUP))
3979           wd->group_items = eina_list_append_relative(wd->group_items, it,
3980                                                       after);
3981      }
3982    else
3983      {
3984         it->parent->items = eina_list_append_relative(it->parent->items, it,
3985                                                       after);
3986      }
3987    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3988                                            EINA_INLIST_GET(after));
3989    it->rel = after;
3990    it->rel->relcount++;
3991    it->before = EINA_FALSE;
3992    _item_queue(wd, it);
3993    return it;
3994 }
3995
3996 EAPI Elm_Genlist_Item *
3997 elm_genlist_item_insert_before(Evas_Object                  *obj,
3998                                const Elm_Genlist_Item_Class *itc,
3999                                const void                   *data,
4000                                Elm_Genlist_Item             *parent,
4001                                Elm_Genlist_Item             *before,
4002                                Elm_Genlist_Item_Flags        flags,
4003                                Evas_Smart_Cb                 func,
4004                                const void                   *func_data)
4005 {
4006    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4007    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
4008    Widget_Data *wd = elm_widget_data_get(obj);
4009    if (!wd) return NULL;
4010    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
4011                                     func_data);
4012    if (!it) return NULL;
4013    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4014    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4015
4016    if (!it->parent)
4017      {
4018         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
4019             (before->flags & ELM_GENLIST_ITEM_GROUP))
4020           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4021                                                        before);
4022      }
4023    else
4024      {
4025         it->parent->items = eina_list_prepend_relative(it->parent->items, it,
4026                                                        before);
4027      }
4028    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4029                                             EINA_INLIST_GET(before));
4030    it->rel = before;
4031    it->rel->relcount++;
4032    it->before = EINA_TRUE;
4033    _item_queue(wd, it);
4034    return it;
4035 }
4036
4037 EAPI void
4038 elm_genlist_clear(Evas_Object *obj)
4039 {
4040    ELM_CHECK_WIDTYPE(obj, widtype);
4041    Widget_Data *wd = elm_widget_data_get(obj);
4042    if (!wd) return;
4043    if (wd->walking > 0)
4044      {
4045         Elm_Genlist_Item *it;
4046
4047         wd->clear_me = EINA_TRUE;
4048         EINA_INLIST_FOREACH(wd->items, it)
4049           {
4050              it->delete_me = EINA_TRUE;
4051           }
4052         return;
4053      }
4054    evas_event_freeze(evas_object_evas_get(wd->obj));
4055    while (wd->items)
4056      {
4057         Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
4058         it->nocache = EINA_TRUE;
4059         it->highlighted = EINA_FALSE;
4060 #ifdef ANCHOR_ITEM
4061         if (wd->anchor_item == it)
4062           {
4063              wd->anchor_item = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4064              if (!wd->anchor_item)
4065                wd->anchor_item =
4066                  ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4067           }
4068 #endif
4069         wd->items = eina_inlist_remove(wd->items, wd->items);
4070         if (it->flags & ELM_GENLIST_ITEM_GROUP)
4071           it->wd->group_items = eina_list_remove(it->wd->group_items, it);
4072         elm_widget_item_pre_notify_del(it);
4073         if (it->realized) _item_unrealize(it, EINA_FALSE);
4074         if (((wd->clear_me) || (!it->delete_me)) && (it->itc->func.del))
4075           it->itc->func.del((void *)it->base.data, it->base.widget);
4076         if (it->long_timer) ecore_timer_del(it->long_timer);
4077         if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
4078         elm_widget_item_del(it);
4079      }
4080    wd->clear_me = EINA_FALSE;
4081    wd->anchor_item = NULL;
4082    while (wd->blocks)
4083      {
4084         Item_Block *itb = (Item_Block *)(wd->blocks);
4085
4086         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
4087         if (itb->items) eina_list_free(itb->items);
4088         free(itb);
4089      }
4090    wd->pan_changed = EINA_TRUE;
4091    if (wd->calc_job)
4092      {
4093         ecore_job_del(wd->calc_job);
4094         wd->calc_job = NULL;
4095      }
4096    if (wd->queue_idle_enterer)
4097      {
4098         ecore_idle_enterer_del(wd->queue_idle_enterer);
4099         wd->queue_idle_enterer = NULL;
4100      }
4101    if (wd->must_recalc_idler)
4102      {
4103         ecore_idler_del(wd->must_recalc_idler);
4104         wd->must_recalc_idler = NULL;
4105      }
4106    if (wd->queue)
4107      {
4108         eina_list_free(wd->queue);
4109         wd->queue = NULL;
4110      }
4111    if (wd->selected)
4112      {
4113         eina_list_free(wd->selected);
4114         wd->selected = NULL;
4115      }
4116    if (wd->reorder_move_animator)
4117      {
4118         ecore_animator_del(wd->reorder_move_animator);
4119         wd->reorder_move_animator = NULL;
4120      }
4121    wd->show_item = NULL;
4122    wd->pan_x = 0;
4123    wd->pan_y = 0;
4124    wd->old_pan_y = 0;
4125    wd->minw = 0;
4126    wd->minh = 0;
4127
4128    if (wd->alpha_bg)
4129       evas_object_del(wd->alpha_bg);
4130    wd->alpha_bg = NULL;
4131
4132    if (wd->pan_smart)
4133      {
4134         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4135         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4136      }
4137    _sizing_eval(obj);
4138    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4139    evas_event_thaw(evas_object_evas_get(wd->obj));
4140    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4141 }
4142
4143 EAPI void
4144 elm_genlist_multi_select_set(Evas_Object *obj,
4145                              Eina_Bool    multi)
4146 {
4147    ELM_CHECK_WIDTYPE(obj, widtype);
4148    Widget_Data *wd = elm_widget_data_get(obj);
4149    if (!wd) return;
4150    wd->multi = multi;
4151 }
4152
4153 EAPI Eina_Bool
4154 elm_genlist_multi_select_get(const Evas_Object *obj)
4155 {
4156    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4157    Widget_Data *wd = elm_widget_data_get(obj);
4158    if (!wd) return EINA_FALSE;
4159    return wd->multi;
4160 }
4161
4162 EAPI Elm_Genlist_Item *
4163 elm_genlist_selected_item_get(const Evas_Object *obj)
4164 {
4165    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4166    Widget_Data *wd = elm_widget_data_get(obj);
4167    if (!wd) return NULL;
4168    if (wd->selected) return wd->selected->data;
4169    return NULL;
4170 }
4171
4172 EAPI const Eina_List *
4173 elm_genlist_selected_items_get(const Evas_Object *obj)
4174 {
4175    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4176    Widget_Data *wd = elm_widget_data_get(obj);
4177    if (!wd) return NULL;
4178    return wd->selected;
4179 }
4180
4181 EAPI Eina_List *
4182 elm_genlist_realized_items_get(const Evas_Object *obj)
4183 {
4184    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4185    Widget_Data *wd = elm_widget_data_get(obj);
4186    Eina_List *list = NULL;
4187    Item_Block *itb;
4188    Eina_Bool done = EINA_FALSE;
4189    if (!wd) return NULL;
4190    EINA_INLIST_FOREACH(wd->blocks, itb)
4191      {
4192         if (itb->realized)
4193           {
4194              Eina_List *l;
4195              Elm_Genlist_Item *it;
4196
4197              done = 1;
4198              EINA_LIST_FOREACH(itb->items, l, it)
4199                {
4200                   if (it->realized) list = eina_list_append(list, it);
4201                }
4202           }
4203         else
4204           {
4205              if (done) break;
4206           }
4207      }
4208    return list;
4209 }
4210
4211 EAPI Elm_Genlist_Item *
4212 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4213                            Evas_Coord         x,
4214                            Evas_Coord         y,
4215                            int               *posret)
4216 {
4217    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4218    Widget_Data *wd = elm_widget_data_get(obj);
4219    Evas_Coord ox, oy, ow, oh;
4220    Item_Block *itb;
4221    Evas_Coord lasty;
4222    if (!wd) return NULL;
4223    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4224    lasty = oy;
4225    EINA_INLIST_FOREACH(wd->blocks, itb)
4226      {
4227         Eina_List *l;
4228         Elm_Genlist_Item *it;
4229
4230         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4231                                  oy + itb->y - itb->wd->pan_y,
4232                                  itb->w, itb->h, x, y, 1, 1))
4233           continue;
4234         EINA_LIST_FOREACH(itb->items, l, it)
4235           {
4236              Evas_Coord itx, ity;
4237
4238              itx = ox + itb->x + it->x - itb->wd->pan_x;
4239              ity = oy + itb->y + it->y - itb->wd->pan_y;
4240              if (ELM_RECTS_INTERSECT(itx, ity, it->w, it->h, x, y, 1, 1))
4241                {
4242                   if (posret)
4243                     {
4244                        if (y <= (ity + (it->h / 4))) *posret = -1;
4245                        else if (y >= (ity + it->h - (it->h / 4)))
4246                          *posret = 1;
4247                        else *posret = 0;
4248                     }
4249                   return it;
4250                }
4251              lasty = ity + it->h;
4252           }
4253      }
4254    if (posret)
4255      {
4256         if (y > lasty) *posret = 1;
4257         else *posret = -1;
4258      }
4259    return NULL;
4260 }
4261
4262 EAPI Elm_Genlist_Item *
4263 elm_genlist_first_item_get(const Evas_Object *obj)
4264 {
4265    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4266    Widget_Data *wd = elm_widget_data_get(obj);
4267    if (!wd) return NULL;
4268    if (!wd->items) return NULL;
4269    Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
4270    while ((it) && (it->delete_me))
4271      it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4272    return it;
4273 }
4274
4275 EAPI Elm_Genlist_Item *
4276 elm_genlist_last_item_get(const Evas_Object *obj)
4277 {
4278    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4279    Widget_Data *wd = elm_widget_data_get(obj);
4280    if (!wd) return NULL;
4281    if (!wd->items) return NULL;
4282    Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items->last);
4283    while ((it) && (it->delete_me))
4284      it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4285    return it;
4286 }
4287
4288 EAPI Elm_Genlist_Item *
4289 elm_genlist_item_next_get(const Elm_Genlist_Item *it)
4290 {
4291    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4292    while (it)
4293      {
4294         it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4295         if ((it) && (!it->delete_me)) break;
4296      }
4297    return (Elm_Genlist_Item *)it;
4298 }
4299
4300 EAPI Elm_Genlist_Item *
4301 elm_genlist_item_prev_get(const Elm_Genlist_Item *it)
4302 {
4303    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4304    while (it)
4305      {
4306         it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4307         if ((it) && (!it->delete_me)) break;
4308      }
4309    return (Elm_Genlist_Item *)it;
4310 }
4311
4312 EAPI Evas_Object *
4313 elm_genlist_item_genlist_get(const Elm_Genlist_Item *it)
4314 {
4315    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4316    return it->base.widget;
4317 }
4318
4319 EAPI Elm_Genlist_Item *
4320 elm_genlist_item_parent_get(const Elm_Genlist_Item *it)
4321 {
4322    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4323    return it->parent;
4324 }
4325
4326 EAPI void
4327 elm_genlist_item_subitems_clear(Elm_Genlist_Item *it)
4328 {
4329    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4330    Elm_Genlist_Item *it2;
4331    Evas_Coord y, h;
4332
4333    if (!it->wd->effect_mode || !it->wd->move_effect_mode)
4334       _item_subitems_clear(it);
4335    else
4336      {
4337         if ((!it->wd->item_moving_effect_timer) && (it->flags != ELM_GENLIST_ITEM_GROUP) &&
4338              it->wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE    )
4339           {
4340              it->wd->expand_item = it;
4341              _item_flip_effect_show(it);
4342              evas_object_geometry_get(it->base.view, NULL, &y, NULL, &h);
4343              it->wd->expand_item_end = y + h;
4344
4345               it2= it;
4346              do {
4347                   it2 = elm_genlist_item_next_get(it2);
4348                   if (!it2) break;
4349              } while (it2->expanded_depth > it->expanded_depth);
4350              if (it2)
4351                 it->wd->expand_item_gap = it->wd->expand_item_end - it2->old_scrl_y;
4352              else
4353                 it->wd->expand_item_gap = 0;
4354
4355              evas_object_raise(it->wd->alpha_bg);
4356              evas_object_show(it->wd->alpha_bg);
4357
4358              it->wd->start_time = current_time_get();
4359              it->wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, it->wd);
4360           }
4361         else
4362            _item_subitems_clear(it);
4363      }
4364 }
4365
4366 EAPI void
4367 elm_genlist_item_selected_set(Elm_Genlist_Item *it,
4368                               Eina_Bool         selected)
4369 {
4370    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4371    Widget_Data *wd = elm_widget_data_get(it->base.widget);
4372    if (!wd) return;
4373    if ((it->delete_me) || (it->disabled)) return;
4374    selected = !!selected;
4375    if (it->selected == selected) return;
4376
4377    if (selected)
4378      {
4379         if (!wd->multi)
4380           {
4381              while (wd->selected)
4382                _item_unselect(wd->selected->data);
4383           }
4384         _item_highlight(it);
4385         _item_select(it);
4386      }
4387    else
4388      _item_unselect(it);
4389 }
4390
4391 EAPI Eina_Bool
4392 elm_genlist_item_selected_get(const Elm_Genlist_Item *it)
4393 {
4394    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4395    return it->selected;
4396 }
4397
4398 EAPI void
4399 elm_genlist_item_expanded_set(Elm_Genlist_Item *it,
4400                               Eina_Bool         expanded)
4401 {
4402    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4403    if (it->flags != ELM_GENLIST_ITEM_SUBITEMS) return;
4404    if (it->expanded == expanded) return;
4405    it->expanded = expanded;
4406    it->wd->expand_item = it;
4407
4408    if (it->wd->effect_mode && !it->wd->alpha_bg)
4409       it->wd->alpha_bg = _create_tray_alpha_bg(it->base.widget);
4410
4411    if (it->expanded)
4412      {
4413         it->wd->auto_scrolled = EINA_FALSE;
4414         it->wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND;
4415         if (it->realized)
4416           edje_object_signal_emit(it->base.view, "elm,state,expanded", "elm");
4417         evas_object_smart_callback_call(it->base.widget, "expanded", it);
4418      }
4419    else
4420      {
4421         it->wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT;
4422         if (it->realized)
4423           edje_object_signal_emit(it->base.view, "elm,state,contracted", "elm");
4424         evas_object_smart_callback_call(it->base.widget, "contracted", it);
4425      }
4426 }
4427
4428 EAPI Eina_Bool
4429 elm_genlist_item_expanded_get(const Elm_Genlist_Item *it)
4430 {
4431    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4432    return it->expanded;
4433 }
4434
4435 EAPI int
4436 elm_genlist_item_expanded_depth_get(const Elm_Genlist_Item *it)
4437 {
4438    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
4439    return it->expanded_depth;
4440 }
4441
4442 EAPI void
4443 elm_genlist_item_disabled_set(Elm_Genlist_Item *it,
4444                               Eina_Bool         disabled)
4445 {
4446    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4447    Eina_List *l;
4448    Evas_Object *obj;
4449    if (it->disabled == disabled) return;
4450    if (it->delete_me) return;
4451    it->disabled = !!disabled;
4452    if (it->selected)
4453      elm_genlist_item_selected_set(it, EINA_FALSE);
4454    if (it->realized)
4455      {
4456         if (it->disabled)
4457           {
4458              edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
4459              if (it->edit_obj)
4460                edje_object_signal_emit(it->edit_obj, "elm,state,disabled", "elm");
4461           }
4462         else
4463           {
4464              edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
4465              if (it->edit_obj)
4466                edje_object_signal_emit(it->edit_obj, "elm,state,enabled", "elm");
4467           }
4468         EINA_LIST_FOREACH(it->icon_objs, l, obj)
4469            elm_widget_disabled_set(obj, disabled);
4470      }
4471 }
4472
4473 EAPI Eina_Bool
4474 elm_genlist_item_disabled_get(const Elm_Genlist_Item *it)
4475 {
4476    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4477    if (it->delete_me) return EINA_FALSE;
4478    return it->disabled;
4479 }
4480
4481 EAPI void
4482 elm_genlist_item_display_only_set(Elm_Genlist_Item *it,
4483                                   Eina_Bool         display_only)
4484 {
4485    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4486    if (it->display_only == display_only) return;
4487    if (it->delete_me) return;
4488    it->display_only = display_only;
4489    it->mincalcd = EINA_FALSE;
4490    it->updateme = EINA_TRUE;
4491    if (it->block) it->block->updateme = EINA_TRUE;
4492    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4493    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4494 }
4495
4496 EAPI Eina_Bool
4497 elm_genlist_item_display_only_get(const Elm_Genlist_Item *it)
4498 {
4499    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4500    if (it->delete_me) return EINA_FALSE;
4501    return it->display_only;
4502 }
4503
4504 EAPI void
4505 elm_genlist_item_show(Elm_Genlist_Item *it)
4506 {
4507    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4508    Evas_Coord gith = 0;
4509    if (it->delete_me) return;
4510    if ((it->queued) || (!it->mincalcd))
4511      {
4512         it->wd->show_item = it;
4513         it->wd->bring_in = EINA_TRUE;
4514         it->showme = EINA_TRUE;
4515         return;
4516      }
4517    if (it->wd->show_item)
4518      {
4519         it->wd->show_item->showme = EINA_FALSE;
4520         it->wd->show_item = NULL;
4521      }
4522    if ((it->group_item) && (it->wd->pan_y > (it->y + it->block->y)))
4523      gith = it->group_item->h;
4524    elm_smart_scroller_child_region_show(it->wd->scr,
4525                                         it->x + it->block->x,
4526                                         it->y + it->block->y - gith,
4527                                         it->block->w, it->h);
4528 }
4529
4530 EAPI void
4531 elm_genlist_item_bring_in(Elm_Genlist_Item *it)
4532 {
4533    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4534    Evas_Coord gith = 0;
4535    if (it->delete_me) return;
4536    if ((it->queued) || (!it->mincalcd))
4537      {
4538         it->wd->show_item = it;
4539         it->wd->bring_in = EINA_TRUE;
4540         it->showme = EINA_TRUE;
4541         return;
4542      }
4543    if (it->wd->show_item)
4544      {
4545         it->wd->show_item->showme = EINA_FALSE;
4546         it->wd->show_item = NULL;
4547      }
4548    if ((it->group_item) && (it->wd->pan_y > (it->y + it->block->y)))
4549      gith = it->group_item->h;
4550    elm_smart_scroller_region_bring_in(it->wd->scr,
4551                                       it->x + it->block->x,
4552                                       it->y + it->block->y - gith,
4553                                       it->block->w, it->h);
4554 }
4555
4556 EAPI void
4557 elm_genlist_item_top_show(Elm_Genlist_Item *it)
4558 {
4559    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4560    Evas_Coord ow, oh;
4561    Evas_Coord gith = 0;
4562
4563    if (it->delete_me) return;
4564    if ((it->queued) || (!it->mincalcd))
4565      {
4566         it->wd->show_item = it;
4567         it->wd->bring_in = EINA_TRUE;
4568         it->showme = EINA_TRUE;
4569         return;
4570      }
4571    if (it->wd->show_item)
4572      {
4573         it->wd->show_item->showme = EINA_FALSE;
4574         it->wd->show_item = NULL;
4575      }
4576    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4577    if (it->group_item) gith = it->group_item->h;
4578    elm_smart_scroller_child_region_show(it->wd->scr,
4579                                         it->x + it->block->x,
4580                                         it->y + it->block->y - gith,
4581                                         it->block->w, oh);
4582 }
4583
4584 EAPI void
4585 elm_genlist_item_top_bring_in(Elm_Genlist_Item *it)
4586 {
4587    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4588    Evas_Coord ow, oh;
4589    Evas_Coord gith = 0;
4590
4591    if (it->delete_me) return;
4592    if ((it->queued) || (!it->mincalcd))
4593      {
4594         it->wd->show_item = it;
4595         it->wd->bring_in = EINA_TRUE;
4596         it->showme = EINA_TRUE;
4597         return;
4598      }
4599    if (it->wd->show_item)
4600      {
4601         it->wd->show_item->showme = EINA_FALSE;
4602         it->wd->show_item = NULL;
4603      }
4604    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4605    if (it->group_item) gith = it->group_item->h;
4606    elm_smart_scroller_region_bring_in(it->wd->scr,
4607                                       it->x + it->block->x,
4608                                       it->y + it->block->y - gith,
4609                                       it->block->w, oh);
4610 }
4611
4612 EAPI void
4613 elm_genlist_item_middle_show(Elm_Genlist_Item *it)
4614 {
4615    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4616    Evas_Coord ow, oh;
4617
4618    if (it->delete_me) return;
4619    if ((it->queued) || (!it->mincalcd))
4620      {
4621         it->wd->show_item = it;
4622         it->wd->bring_in = EINA_TRUE;
4623         it->showme = EINA_TRUE;
4624         return;
4625      }
4626    if (it->wd->show_item)
4627      {
4628         it->wd->show_item->showme = EINA_FALSE;
4629         it->wd->show_item = NULL;
4630      }
4631    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4632    elm_smart_scroller_child_region_show(it->wd->scr,
4633                                         it->x + it->block->x,
4634                                         it->y + it->block->y - oh / 2 +
4635                                         it->h / 2, it->block->w, oh);
4636 }
4637
4638 EAPI void
4639 elm_genlist_item_middle_bring_in(Elm_Genlist_Item *it)
4640 {
4641    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4642    Evas_Coord ow, oh;
4643
4644    if (it->delete_me) return;
4645    if ((it->queued) || (!it->mincalcd))
4646      {
4647         it->wd->show_item = it;
4648         it->wd->bring_in = EINA_TRUE;
4649         it->showme = EINA_TRUE;
4650         return;
4651      }
4652    if (it->wd->show_item)
4653      {
4654         it->wd->show_item->showme = EINA_FALSE;
4655         it->wd->show_item = NULL;
4656      }
4657    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4658    elm_smart_scroller_region_bring_in(it->wd->scr,
4659                                       it->x + it->block->x,
4660                                       it->y + it->block->y - oh / 2 + it->h / 2,
4661                                       it->block->w, oh);
4662 }
4663
4664 EAPI void
4665 elm_genlist_item_del(Elm_Genlist_Item *it)
4666 {
4667    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4668    if ((it->relcount > 0) || (it->walking > 0))
4669      {
4670         elm_widget_item_pre_notify_del(it);
4671         elm_genlist_item_subitems_clear(it);
4672         it->delete_me = EINA_TRUE;
4673         if (it->wd->show_item == it) it->wd->show_item = NULL;
4674         if (it->selected)
4675           it->wd->selected = eina_list_remove(it->wd->selected,
4676                                               it);
4677         if (it->block)
4678           {
4679              if (it->realized) _item_unrealize(it, EINA_FALSE);
4680              it->block->changed = EINA_TRUE;
4681              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
4682              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
4683           }
4684         if (it->itc->func.del)
4685           it->itc->func.del((void *)it->base.data, it->base.widget);
4686         return;
4687      }
4688    _item_del(it);
4689 }
4690
4691 EAPI void
4692 elm_genlist_item_data_set(Elm_Genlist_Item *it,
4693                           const void       *data)
4694 {
4695    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4696    elm_widget_item_data_set(it, data);
4697    elm_genlist_item_update(it);
4698 }
4699
4700 EAPI void *
4701 elm_genlist_item_data_get(const Elm_Genlist_Item *it)
4702 {
4703    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4704    return elm_widget_item_data_get(it);
4705 }
4706
4707 EAPI void
4708 elm_genlist_item_icons_orphan(Elm_Genlist_Item *it)
4709 {
4710    Evas_Object *icon;
4711    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4712    EINA_LIST_FREE(it->icon_objs, icon)
4713      {
4714         elm_widget_sub_object_del(it->base.widget, icon);
4715         evas_object_smart_member_del(icon);
4716         evas_object_hide(icon);
4717      }
4718 }
4719
4720 EAPI const Evas_Object *
4721 elm_genlist_item_object_get(const Elm_Genlist_Item *it)
4722 {
4723    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4724    return it->base.view;
4725 }
4726
4727 EAPI void
4728 elm_genlist_item_update(Elm_Genlist_Item *it)
4729 {
4730    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4731    if (!it->block) return;
4732    if (it->delete_me) return;
4733    it->mincalcd = EINA_FALSE;
4734    it->updateme = EINA_TRUE;
4735    it->block->updateme = EINA_TRUE;
4736    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4737    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4738    it->defer_unrealize = EINA_FALSE;
4739 }
4740
4741 EAPI void
4742 elm_genlist_item_fields_update(Elm_Genlist_Item *it,
4743                                const char *parts,
4744                                Elm_Genlist_Item_Field_Flags itf)
4745 {
4746    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4747    if (!it->block) return;
4748    if (it->delete_me) return;
4749
4750    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4751      _item_label_realize(it, it->base.view, &it->labels, parts);
4752    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_ICON))
4753      {
4754         it->icon_objs = _item_icon_unrealize(it, it->base.view,
4755                                              &it->icons, parts);
4756         it->icon_objs = _item_icon_realize(it, it->base.view,
4757                                            &it->icons, parts);
4758      }
4759    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4760      _item_state_realize(it, it->base.view, &it->states, parts);
4761 }
4762
4763 EAPI void
4764 elm_genlist_item_item_class_update(Elm_Genlist_Item             *it,
4765                                    const Elm_Genlist_Item_Class *itc)
4766 {
4767    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4768    if (!it->block) return;
4769    EINA_SAFETY_ON_NULL_RETURN(itc);
4770    if (it->delete_me) return;
4771    it->itc = itc;
4772    it->nocache = EINA_TRUE;
4773    elm_genlist_item_update(it);
4774 }
4775
4776 EAPI const Elm_Genlist_Item_Class *
4777 elm_genlist_item_item_class_get(const Elm_Genlist_Item *it)
4778 {
4779    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4780    if (it->delete_me) return NULL;
4781    return it->itc;
4782 }
4783 static Evas_Object *
4784 _elm_genlist_item_label_create(void        *data,
4785                                Evas_Object *obj,
4786                                void        *item __UNUSED__)
4787 {
4788    Evas_Object *label = elm_label_add(obj);
4789    if (!label)
4790      return NULL;
4791    elm_object_style_set(label, "tooltip");
4792    elm_object_text_set(label, data);
4793    return label;
4794 }
4795
4796 static void
4797 _elm_genlist_item_label_del_cb(void        *data,
4798                                Evas_Object *obj __UNUSED__,
4799                                void        *event_info __UNUSED__)
4800 {
4801    eina_stringshare_del(data);
4802 }
4803
4804 EAPI void
4805 elm_genlist_item_tooltip_text_set(Elm_Genlist_Item *item,
4806                                   const char       *text)
4807 {
4808    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4809    text = eina_stringshare_add(text);
4810    elm_genlist_item_tooltip_content_cb_set(item, _elm_genlist_item_label_create,
4811                                            text,
4812                                            _elm_genlist_item_label_del_cb);
4813 }
4814
4815 EAPI void
4816 elm_genlist_item_tooltip_content_cb_set(Elm_Genlist_Item           *item,
4817                                         Elm_Tooltip_Item_Content_Cb func,
4818                                         const void                 *data,
4819                                         Evas_Smart_Cb               del_cb)
4820 {
4821    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
4822
4823    if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
4824      return;
4825
4826    if (item->tooltip.del_cb)
4827      item->tooltip.del_cb((void *)item->tooltip.data,
4828                           item->base.widget, item);
4829
4830    item->tooltip.content_cb = func;
4831    item->tooltip.data = data;
4832    item->tooltip.del_cb = del_cb;
4833
4834    if (item->base.view)
4835      {
4836         elm_widget_item_tooltip_content_cb_set(item,
4837                                                item->tooltip.content_cb,
4838                                                item->tooltip.data, NULL);
4839         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
4840      }
4841
4842    return;
4843
4844 error:
4845    if (del_cb) del_cb((void *)data, NULL, NULL);
4846 }
4847
4848 EAPI void
4849 elm_genlist_item_tooltip_unset(Elm_Genlist_Item *item)
4850 {
4851    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4852    if ((item->base.view) && (item->tooltip.content_cb))
4853      elm_widget_item_tooltip_unset(item);
4854
4855    if (item->tooltip.del_cb)
4856      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
4857    item->tooltip.del_cb = NULL;
4858    item->tooltip.content_cb = NULL;
4859    item->tooltip.data = NULL;
4860    if (item->tooltip.style)
4861      elm_genlist_item_tooltip_style_set(item, NULL);
4862 }
4863
4864 EAPI void
4865 elm_genlist_item_tooltip_style_set(Elm_Genlist_Item *item,
4866                                    const char       *style)
4867 {
4868    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4869    eina_stringshare_replace(&item->tooltip.style, style);
4870    if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
4871 }
4872
4873 EAPI const char *
4874 elm_genlist_item_tooltip_style_get(const Elm_Genlist_Item *item)
4875 {
4876    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
4877    return item->tooltip.style;
4878 }
4879
4880 EAPI void
4881 elm_genlist_item_cursor_set(Elm_Genlist_Item *item,
4882                             const char       *cursor)
4883 {
4884    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4885    eina_stringshare_replace(&item->mouse_cursor, cursor);
4886    if (item->base.view) elm_widget_item_cursor_set(item, cursor);
4887 }
4888
4889 EAPI const char *
4890 elm_genlist_item_cursor_get(const Elm_Genlist_Item *item)
4891 {
4892    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
4893    return elm_widget_item_cursor_get(item);
4894 }
4895
4896 EAPI void
4897 elm_genlist_item_cursor_unset(Elm_Genlist_Item *item)
4898 {
4899    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4900    if (!item->mouse_cursor)
4901      return;
4902
4903    if (item->base.view)
4904      elm_widget_item_cursor_unset(item);
4905
4906    eina_stringshare_del(item->mouse_cursor);
4907    item->mouse_cursor = NULL;
4908 }
4909
4910 EAPI void
4911 elm_genlist_item_cursor_style_set(Elm_Genlist_Item *item,
4912                                   const char       *style)
4913 {
4914    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4915    elm_widget_item_cursor_style_set(item, style);
4916 }
4917
4918 EAPI const char *
4919 elm_genlist_item_cursor_style_get(const Elm_Genlist_Item *item)
4920 {
4921    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
4922    return elm_widget_item_cursor_style_get(item);
4923 }
4924
4925 EAPI void
4926 elm_genlist_item_cursor_engine_only_set(Elm_Genlist_Item *item,
4927                                         Eina_Bool         engine_only)
4928 {
4929    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4930    elm_widget_item_cursor_engine_only_set(item, engine_only);
4931 }
4932
4933 EAPI Eina_Bool
4934 elm_genlist_item_cursor_engine_only_get(const Elm_Genlist_Item *item)
4935 {
4936    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
4937    return elm_widget_item_cursor_engine_only_get(item);
4938 }
4939
4940 EAPI void
4941 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4942                                 Elm_List_Mode mode)
4943 {
4944    ELM_CHECK_WIDTYPE(obj, widtype);
4945    Widget_Data *wd = elm_widget_data_get(obj);
4946    if (!wd) return;
4947    if (wd->mode == mode) return;
4948    wd->mode = mode;
4949    _sizing_eval(obj);
4950 }
4951
4952 EAPI Elm_List_Mode
4953 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
4954 {
4955    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4956    Widget_Data *wd = elm_widget_data_get(obj);
4957    if (!wd) return ELM_LIST_LAST;
4958    return wd->mode;
4959 }
4960
4961 EAPI void
4962 elm_genlist_always_select_mode_set(Evas_Object *obj,
4963                                    Eina_Bool    always_select)
4964 {
4965    ELM_CHECK_WIDTYPE(obj, widtype);
4966    Widget_Data *wd = elm_widget_data_get(obj);
4967    if (!wd) return;
4968    wd->always_select = always_select;
4969 }
4970
4971 EAPI Eina_Bool
4972 elm_genlist_always_select_mode_get(const Evas_Object *obj)
4973 {
4974    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4975    Widget_Data *wd = elm_widget_data_get(obj);
4976    if (!wd) return EINA_FALSE;
4977    return wd->always_select;
4978 }
4979
4980 EAPI void
4981 elm_genlist_no_select_mode_set(Evas_Object *obj,
4982                                Eina_Bool    no_select)
4983 {
4984    ELM_CHECK_WIDTYPE(obj, widtype);
4985    Widget_Data *wd = elm_widget_data_get(obj);
4986    if (!wd) return;
4987    wd->no_select = no_select;
4988 }
4989
4990 EAPI Eina_Bool
4991 elm_genlist_no_select_mode_get(const Evas_Object *obj)
4992 {
4993    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4994    Widget_Data *wd = elm_widget_data_get(obj);
4995    if (!wd) return EINA_FALSE;
4996    return wd->no_select;
4997 }
4998
4999 EAPI void
5000 elm_genlist_compress_mode_set(Evas_Object *obj,
5001                               Eina_Bool    compress)
5002 {
5003    ELM_CHECK_WIDTYPE(obj, widtype);
5004    Widget_Data *wd = elm_widget_data_get(obj);
5005    if (!wd) return;
5006    wd->compress = compress;
5007 }
5008
5009 EAPI Eina_Bool
5010 elm_genlist_compress_mode_get(const Evas_Object *obj)
5011 {
5012    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5013    Widget_Data *wd = elm_widget_data_get(obj);
5014    if (!wd) return EINA_FALSE;
5015    return wd->compress;
5016 }
5017
5018 EAPI void
5019 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5020                                       Eina_Bool    height_for_width)
5021 {
5022    ELM_CHECK_WIDTYPE(obj, widtype);
5023    Widget_Data *wd = elm_widget_data_get(obj);
5024    if (!wd) return;
5025    wd->height_for_width = !!height_for_width;
5026    if (wd->height_for_width)
5027      {
5028         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5029         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5030      }
5031 }
5032
5033 EAPI Eina_Bool
5034 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5035 {
5036    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5037    Widget_Data *wd = elm_widget_data_get(obj);
5038    if (!wd) return EINA_FALSE;
5039    return wd->height_for_width;
5040 }
5041
5042 EAPI void
5043 elm_genlist_bounce_set(Evas_Object *obj,
5044                        Eina_Bool    h_bounce,
5045                        Eina_Bool    v_bounce)
5046 {
5047    ELM_CHECK_WIDTYPE(obj, widtype);
5048    Widget_Data *wd = elm_widget_data_get(obj);
5049    if (!wd) return;
5050    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
5051 }
5052
5053 EAPI void
5054 elm_genlist_bounce_get(const Evas_Object *obj,
5055                        Eina_Bool         *h_bounce,
5056                        Eina_Bool         *v_bounce)
5057 {
5058    ELM_CHECK_WIDTYPE(obj, widtype);
5059    Widget_Data *wd = elm_widget_data_get(obj);
5060    if (!wd) return;
5061    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
5062 }
5063
5064 EAPI void
5065 elm_genlist_homogeneous_set(Evas_Object *obj,
5066                             Eina_Bool    homogeneous)
5067 {
5068    ELM_CHECK_WIDTYPE(obj, widtype);
5069    Widget_Data *wd = elm_widget_data_get(obj);
5070    if (!wd) return;
5071    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5072    wd->homogeneous = homogeneous;
5073 }
5074
5075 EAPI Eina_Bool
5076 elm_genlist_homogeneous_get(const Evas_Object *obj)
5077 {
5078    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5079    Widget_Data *wd = elm_widget_data_get(obj);
5080    if (!wd) return EINA_FALSE;
5081    return wd->homogeneous;
5082 }
5083
5084 EAPI void
5085 elm_genlist_block_count_set(Evas_Object *obj,
5086                             int          n)
5087 {
5088    ELM_CHECK_WIDTYPE(obj, widtype);
5089    Widget_Data *wd = elm_widget_data_get(obj);
5090    if (!wd) return;
5091    wd->max_items_per_block = n;
5092    wd->item_cache_max = wd->max_items_per_block * 2;
5093    _item_cache_clean(wd);
5094 }
5095
5096 EAPI int
5097 elm_genlist_block_count_get(const Evas_Object *obj)
5098 {
5099    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5100    Widget_Data *wd = elm_widget_data_get(obj);
5101    if (!wd) return 0;
5102    return wd->max_items_per_block;
5103 }
5104
5105 EAPI void
5106 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5107                                   double       timeout)
5108 {
5109    ELM_CHECK_WIDTYPE(obj, widtype);
5110    Widget_Data *wd = elm_widget_data_get(obj);
5111    if (!wd) return;
5112    wd->longpress_timeout = timeout;
5113 }
5114
5115 EAPI double
5116 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5117 {
5118    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5119    Widget_Data *wd = elm_widget_data_get(obj);
5120    if (!wd) return 0;
5121    return wd->longpress_timeout;
5122 }
5123
5124 EAPI void
5125 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5126                                 Elm_Scroller_Policy policy_h,
5127                                 Elm_Scroller_Policy policy_v)
5128 {
5129    ELM_CHECK_WIDTYPE(obj, widtype);
5130    Widget_Data *wd = elm_widget_data_get(obj);
5131    if ((!wd) || (!wd->scr)) return;
5132    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5133        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5134      return;
5135    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5136 }
5137
5138 EAPI void
5139 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5140                                 Elm_Scroller_Policy *policy_h,
5141                                 Elm_Scroller_Policy *policy_v)
5142 {
5143    ELM_CHECK_WIDTYPE(obj, widtype);
5144    Widget_Data *wd = elm_widget_data_get(obj);
5145    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5146    if ((!wd) || (!wd->scr)) return;
5147    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5148    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5149    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5150 }
5151
5152 EAPI void
5153 elm_genlist_realized_items_update(Evas_Object *obj)
5154 {
5155    ELM_CHECK_WIDTYPE(obj, widtype);
5156
5157    Eina_List *list, *l;
5158    Elm_Genlist_Item *it;
5159
5160    list = elm_genlist_realized_items_get(obj);
5161    EINA_LIST_FOREACH(list, l, it)
5162      elm_genlist_item_update(it);
5163 }
5164
5165 EAPI void
5166 elm_genlist_item_mode_set(Elm_Genlist_Item *it,
5167                           const char       *mode_type,
5168                           Eina_Bool         mode_set)
5169 {
5170    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
5171    Widget_Data *wd = it->wd;
5172    Eina_List *l;
5173    Elm_Genlist_Item *it2;
5174
5175    if (!wd) return;
5176    if (!mode_type) return;
5177    if ((it->delete_me) || (it->disabled)) return;
5178    if (wd->edit_mode) return;
5179
5180    if ((wd->mode_item == it) &&
5181        (!strcmp(mode_type, wd->mode_type)) &&
5182        (mode_set))
5183       return;
5184    if (!it->itc->mode_item_style) return;
5185
5186    if (wd->multi)
5187      {
5188         EINA_LIST_FOREACH(wd->selected, l, it2)
5189           if (it2->realized)
5190             elm_genlist_item_selected_set(it2, EINA_FALSE);
5191      }
5192    else
5193      {
5194         it2 = elm_genlist_selected_item_get(wd->obj);
5195         if ((it2) && (it2->realized))
5196           elm_genlist_item_selected_set(it2, EINA_FALSE);
5197      }
5198
5199    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5200        (mode_set) ||
5201        ((it == wd->mode_item) && (!mode_set)))
5202      _item_mode_unset(wd);
5203
5204    eina_stringshare_replace(&wd->mode_type, mode_type);
5205    if (mode_set) _item_mode_set(it);
5206 }
5207
5208 EAPI const char *
5209 elm_genlist_mode_get(const Evas_Object *obj)
5210 {
5211    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5212    Widget_Data *wd = elm_widget_data_get(obj);
5213    if (!wd) return NULL;
5214    return wd->mode_type;
5215 }
5216
5217 EAPI const Elm_Genlist_Item *
5218 elm_genlist_mode_item_get(const Evas_Object *obj)
5219 {
5220    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5221    Widget_Data *wd = elm_widget_data_get(obj);
5222    if (!wd) return NULL;
5223    return wd->mode_item;
5224 }
5225
5226 EAPI void
5227 elm_genlist_reorder_mode_set(Evas_Object *obj,
5228                              Eina_Bool    reorder_mode)
5229 {
5230    ELM_CHECK_WIDTYPE(obj, widtype);
5231    Widget_Data *wd = elm_widget_data_get(obj);
5232    if (!wd) return;
5233    wd->reorder_mode = reorder_mode;
5234 }
5235
5236 EAPI Eina_Bool
5237 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5238 {
5239    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5240    Widget_Data *wd = elm_widget_data_get(obj);
5241    if (!wd) return EINA_FALSE;
5242    return wd->reorder_mode;
5243 }
5244
5245 EAPI void
5246 elm_genlist_item_move_after(Elm_Genlist_Item *it __UNUSED__, Elm_Genlist_Item *after __UNUSED__)
5247 {
5248    return;
5249 }
5250
5251 EAPI void
5252 elm_genlist_item_move_before(Elm_Genlist_Item *it __UNUSED__, Elm_Genlist_Item *before __UNUSED__)
5253 {
5254    return;
5255 }
5256
5257 EAPI void
5258 elm_genlist_effect_set(const Evas_Object *obj, Eina_Bool emode)
5259 {
5260    ELM_CHECK_WIDTYPE(obj, widtype);
5261    Widget_Data *wd = elm_widget_data_get(obj);
5262    if (!wd) return;
5263    wd->effect_mode = emode;
5264    //   wd->point_rect = evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5265    //   evas_object_resize(wd->point_rect, 10, 25);
5266    //   evas_object_color_set(wd->point_rect, 255, 0, 0, 130);
5267    //   evas_object_show(wd->point_rect);
5268    //   evas_object_hide(wd->point_rect);
5269 }
5270
5271 static Evas_Object*
5272 _create_tray_alpha_bg(const Evas_Object *obj)
5273 {
5274    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5275    Widget_Data *wd = elm_widget_data_get(obj);
5276    if (!wd) return NULL;
5277
5278    Evas_Object *bg = NULL;
5279    Evas_Coord ox, oy, ow, oh;
5280
5281    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5282    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5283    evas_object_color_set(bg,0,0,0,0);
5284    evas_object_resize(bg , ow, oh);
5285    evas_object_move(bg , ox, oy);
5286    evas_object_show(bg);
5287    evas_object_hide(bg);
5288    return bg ;
5289 }
5290
5291 static unsigned int
5292 current_time_get()
5293 {
5294    struct timeval timev;
5295
5296    gettimeofday(&timev, NULL);
5297    return ((timev.tv_sec * 1000) + ((timev.tv_usec) / 1000));
5298 }
5299
5300 // added for item moving animation.
5301 static Eina_Bool
5302 _item_moving_effect_timer_cb(void *data)
5303 {
5304    Widget_Data *wd = data;
5305    if (!wd) return EINA_FALSE;
5306    Item_Block *itb;
5307    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
5308    Elm_Genlist_Item *it = NULL, *it2;
5309    const Eina_List *l;
5310    double time = 0.3, t;
5311    int y, dy;
5312    Eina_Bool check, end = EINA_FALSE;
5313    int in = 0;
5314
5315    t = ((0.0 > (t = current_time_get() - wd->start_time)) ? 0.0 : t) / 1000;
5316
5317    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5318    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
5319    if (t > time) end = EINA_TRUE;
5320
5321    it2 = elm_genlist_item_next_get(wd->expand_item);
5322    while (it2)
5323      {
5324         if (wd->expand_item->expanded_depth >= it2->expanded_depth) break;
5325         it2 = elm_genlist_item_next_get(it2);
5326      }
5327    dy = 0;
5328    if (it2)
5329      {
5330         if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5331           dy = it2->scrl_y - it2->old_scrl_y;
5332         else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5333           dy = wd->expand_item_gap;
5334
5335         if (t <= time)
5336           {
5337              y = ((1 - (1 - (t / time)) * (1 - (t /time))) * dy);
5338           }
5339         else
5340           {
5341              end = EINA_TRUE;
5342              y = dy;
5343           }
5344
5345         check = EINA_FALSE;
5346         EINA_INLIST_FOREACH(wd->blocks, itb)
5347           {
5348              itb->w = wd->minw;
5349              if (ELM_RECTS_INTERSECT(itb->x - wd->pan_x + ox,
5350                                      itb->y - wd->pan_y + oy,
5351                                      itb->w, itb->h,
5352                                      cvx, cvy, cvw, cvh))
5353                {
5354                   EINA_LIST_FOREACH(itb->items, l, it)
5355                     {
5356                        if (it == it2) check = EINA_TRUE;
5357                        if (!check) continue;
5358
5359                        if (!it->old_scrl_y)
5360                          it->old_scrl_y  = it->scrl_y;
5361                        if (it->old_scrl_y + y < oy + oh)
5362                          {
5363                             if (!it->realized) _item_realize(it, in, 0);
5364                          }
5365                        if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE && it->old_scrl_y + y < it->scrl_y)
5366                          it->old_scrl_y = it->scrl_y - y;
5367                        in++;
5368
5369                        if (wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE ||
5370                            (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE && it->old_scrl_y + y >= it->scrl_y))
5371                          {
5372                             if (wd->edit_mode) _effect_item_controls(it, it->scrl_x, it->old_scrl_y + y);
5373                             else
5374                               {
5375                                  evas_object_resize(it->base.view, it->w, it->h);
5376                                  evas_object_move(it->base.view, it->scrl_x, it->old_scrl_y + y);
5377                                  evas_object_show(it->base.view);
5378                                  evas_object_raise(it->base.view);
5379                               }
5380
5381                             if (it->group_item) evas_object_raise(it->group_item->base.view);
5382                          }
5383                     }
5384                }
5385           }
5386
5387         if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5388           {
5389              it = elm_genlist_item_prev_get(it2);
5390              while (it)
5391                {
5392                   if (it->expanded_depth <= it2->expanded_depth) break;
5393                   if ((it->scrl_y < it2->old_scrl_y + y) && (it->expanded_depth > it2->expanded_depth))
5394                     {
5395                        if (!it->effect_done)
5396                          {
5397                             edje_object_signal_emit(it->base.view, "flip_item", "");
5398                             evas_object_show(it->base.view);
5399                             it->effect_done = EINA_TRUE;
5400                          }
5401                     }
5402                   it = elm_genlist_item_prev_get(it);
5403                }
5404           }
5405         else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5406           {
5407              it = elm_genlist_item_prev_get(it2);
5408              while (it)
5409                {
5410                   if ((it->scrl_y > it2->old_scrl_y + y) && (it->expanded_depth > it2->expanded_depth))
5411                     {
5412                        if (!it->effect_done)
5413                          {
5414                             edje_object_signal_emit(it->base.view, "elm,state,hide", "");
5415                             it->effect_done = EINA_TRUE;
5416                          }
5417                     }
5418                   else
5419                     break;
5420                   it = elm_genlist_item_prev_get(it);
5421                }
5422           }
5423      }
5424    else
5425      {
5426         int expand_num = 0;
5427         int expand_order = 0;
5428         if (wd->expand_item) it = elm_genlist_item_next_get(wd->expand_item);
5429         while (it)
5430           {
5431              expand_num++;
5432              it = elm_genlist_item_next_get(it);
5433           }
5434         if (wd->expand_item) it = elm_genlist_item_next_get(wd->expand_item);
5435         while (it)
5436           {
5437              expand_order++;
5438              if (wd->expand_item->expanded_depth >= it->expanded_depth) break;
5439              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5440                {
5441                   if (!it->effect_done)
5442                     {
5443                        if (t >= (((expand_order - 1) * time) / expand_num))
5444                          {
5445                             edje_object_signal_emit(it->base.view, "flip_item", "");
5446                             evas_object_show(it->base.view);
5447                             it->effect_done = EINA_TRUE;
5448                          }
5449                     }
5450                }
5451              it = elm_genlist_item_next_get(it);
5452           }
5453      }
5454
5455    if (end)
5456      {
5457         if (wd->item_moving_effect_timer)
5458           {
5459              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5460                 _item_subitems_clear(wd->expand_item);
5461              EINA_INLIST_FOREACH(wd->blocks, itb)
5462                {
5463                   EINA_LIST_FOREACH(itb->items, l, it)
5464                     {
5465                        it->effect_done = EINA_TRUE;
5466                        it->old_scrl_y = it->scrl_y;
5467                     }
5468                }
5469           }
5470         wd->item_moving_effect_timer = NULL;
5471
5472         _item_auto_scroll(wd);
5473         evas_object_lower(wd->alpha_bg);
5474         evas_object_hide(wd->alpha_bg);
5475         elm_smart_scroller_bounce_animator_disabled_set(wd->scr, EINA_FALSE);
5476         wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_NONE;
5477
5478         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
5479         evas_object_smart_callback_call(wd->obj, "effect_done", NULL);
5480         evas_object_smart_changed(wd->pan_smart);
5481         return ECORE_CALLBACK_CANCEL;
5482      }
5483    return ECORE_CALLBACK_RENEW;
5484 }
5485
5486 static void
5487 _emit_contract(Elm_Genlist_Item *it)
5488 {
5489    Elm_Genlist_Item *it2;
5490    Eina_List *l;
5491
5492    //   printf("%p is emited contract\n", it);
5493    edje_object_signal_emit(it->base.view, "elm,state,contract_flip", "");
5494    it->effect_done = EINA_FALSE;
5495
5496    EINA_LIST_FOREACH(it->items, l, it2)
5497       if (it2)
5498          _emit_contract(it2);
5499 }
5500
5501 // added for item moving animation.
5502 static int
5503 _item_flip_effect_show(Elm_Genlist_Item *it)
5504 {
5505    Elm_Genlist_Item *it2;
5506    Eina_List *l;
5507    Widget_Data *wd = it->wd;
5508    Eina_Bool check = EINA_FALSE;
5509
5510    it2 = elm_genlist_item_next_get(it);
5511    while (it2)
5512      {
5513         if (it2->expanded_depth <= it->expanded_depth) check = EINA_TRUE;
5514         it2 = elm_genlist_item_next_get(it2);
5515      }
5516    EINA_LIST_FOREACH(it->items, l, it2)
5517      {
5518         if (it2->parent && it == it2->parent)
5519           {
5520              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5521                edje_object_signal_emit(it2->base.view, "elm,state,hide", "");
5522              else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5523                _emit_contract(it2);
5524           }
5525      }
5526
5527    return ECORE_CALLBACK_CANCEL;
5528 }
5529
5530 /*
5531 static void
5532 _elm_genlist_pinch_zoom_execute(Evas_Object *obj, Eina_Bool emode)
5533 {
5534    printf("!!! NOW FIXING \n");
5535 }
5536 */
5537
5538 /**
5539  * Set pinch zoom mode
5540  *
5541  * @param obj The genlist object
5542  * @param emode
5543  * (EINA_TRUE = pinch contract (zoom in), EINA_FALSE = pinch expand (zoom out)
5544  *
5545  * @ingroup Genlist
5546  */
5547 EAPI void
5548 elm_genlist_pinch_zoom_mode_set(Evas_Object *obj __UNUSED__, Eina_Bool emode __UNUSED__)
5549 {
5550    printf("!!! NOW FIXING \n");
5551 }
5552
5553 /**
5554  * Get pinch zoom mode
5555  *
5556  * @param obj The genlist object
5557  * @return The pinch mode
5558  * (EINA_TRUE = pinch contract (zoom in), EINA_FALSE = pinch expand (zoom out)
5559  *
5560  * @ingroup Genlist
5561  */
5562 EAPI Eina_Bool
5563 elm_genlist_pinch_zoom_mode_get(const Evas_Object *obj __UNUSED__)
5564 {
5565    printf("!!! NOW FIXING \n");
5566    return EINA_FALSE;
5567 }
5568
5569 EAPI void
5570 elm_genlist_pinch_zoom_set(Evas_Object *obj __UNUSED__, Eina_Bool emode __UNUSED__)
5571 {
5572    printf("!!! NOW FIXING \n");
5573 }
5574
5575
5576 ////////////////////////////////////////////////////////////////////////
5577 //  EDIT  MODE
5578 ////////////////////////////////////////////////////////////////////////
5579
5580 static void
5581 _effect_item_controls(Elm_Genlist_Item *it, int itx, int ity)
5582 {
5583    if (!it->wd->edit_mode) return;
5584    evas_object_resize(it->edit_obj,it->w, it->h);
5585    evas_object_move(it->edit_obj, itx, ity);
5586 }
5587
5588 static void
5589 _effect_item_realize(Elm_Genlist_Item *it, Eina_Bool effect_on)
5590 {
5591    if ((it->effect_item_realized) || (it->delete_me)) return;
5592    char buf[1024];
5593
5594    if (it->mode_view)
5595      _mode_finished_signal_cb(it, (Evas_Object *)elm_genlist_item_object_get(it), NULL, NULL);
5596
5597    it->edit_obj = edje_object_add(evas_object_evas_get(it->base.widget));
5598    edje_object_scale_set(it->edit_obj, elm_widget_scale_get(it->base.widget) *
5599                          _elm_config->scale);
5600    evas_object_smart_member_add(it->edit_obj, it->wd->pan_smart);
5601    elm_widget_sub_object_add(it->base.widget, it->edit_obj);
5602
5603    if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) strncpy(buf, "tree", sizeof(buf));
5604    else strncpy(buf, "item", sizeof(buf));
5605    if (it->wd->compress) strncat(buf, "_compress", sizeof(buf) - strlen(buf));
5606
5607    strncat(buf, "/", sizeof(buf) - strlen(buf));
5608
5609    if (it->itc->edit_item_style && strcmp(it->itc->edit_item_style, "default"))
5610      {
5611         strncat(buf, it->itc->edit_item_style, sizeof(buf) - strlen(buf));
5612         _elm_theme_object_set(it->base.widget, it->edit_obj, "genlist", buf, elm_widget_style_get(it->base.widget));
5613      }
5614    else
5615      {
5616         _elm_theme_object_set(it->base.widget, it->edit_obj, "genlist", "item/edit_default", elm_widget_style_get(it->base.widget));
5617      }
5618
5619    if (it->wd->reorder_mode)
5620      {
5621         if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,reorder_enabled_effect", "elm");
5622         else edje_object_signal_emit(it->edit_obj, "elm,state,reorder_enabled", "elm");
5623      }
5624    if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,emode_enabled_effect", "elm");
5625    else edje_object_signal_emit(it->edit_obj, "elm,state,emode_enabled", "elm");
5626
5627    if (it->disabled) edje_object_signal_emit(it->edit_obj, "elm,state,disabled", "elm");
5628    else edje_object_signal_emit(it->edit_obj, "elm,state,enabled", "elm");
5629
5630
5631    if ((it->wd->edit_mode))
5632      {
5633         if (it->itc->func.icon_get)
5634           {
5635              const Eina_List *l;
5636              const char *key;
5637
5638              if (it->renamed) edje_object_signal_emit(it->edit_obj, "elm,state,rename,enabled", "elm");
5639              it->icons = elm_widget_stringlist_get(edje_object_data_get(it->edit_obj, "edit_icons"));
5640              EINA_LIST_FOREACH(it->icons, l, key)
5641                {
5642                   Evas_Object *ic = it->itc->func.icon_get
5643                      ((void *)it->base.data, it->base.widget, l->data);
5644
5645                   if (ic)
5646                     {
5647                        it->edit_icon_objs = eina_list_append(it->edit_icon_objs, ic);
5648                        edje_object_part_swallow(it->edit_obj, key, ic);
5649                        evas_object_show(ic);
5650                        elm_widget_sub_object_add(it->base.widget, ic);
5651                        if (it->disabled)
5652                          elm_widget_disabled_set(ic, EINA_TRUE);
5653                     }
5654                }
5655           }
5656      }
5657    edje_object_part_swallow(it->edit_obj, "original_edc", it->base.view);
5658    _effect_item_controls(it,it->scrl_x, it->scrl_y);
5659    evas_object_show(it->edit_obj);
5660
5661    it->effect_item_realized = EINA_TRUE;
5662    it->want_unrealize = EINA_FALSE;
5663 }
5664
5665 static void
5666 _effect_item_unrealize(Elm_Genlist_Item *it)
5667 {
5668    Evas_Object *icon;
5669
5670    if (!it->effect_item_realized) return;
5671    if (it->wd->reorder_it && it->wd->reorder_it == it) return;
5672
5673    edje_object_signal_emit(it->edit_obj, "elm,state,reorder_disable_effect", "elm");
5674    edje_object_signal_emit(it->edit_obj, "elm,state,sel,disable", "elm");
5675    edje_object_message_signal_process(it->edit_obj);
5676    edje_object_part_unswallow(it->edit_obj, it->base.view);
5677    evas_object_smart_member_add(it->base.view, it->wd->pan_smart);
5678    elm_widget_sub_object_add(it->base.widget, it->base.view);
5679    //   evas_object_smart_callback_call(it->edit_obj, "unrealized", it);
5680    //   _item_cache_add(it);
5681    evas_object_del(it->edit_obj);
5682    it->edit_obj = NULL;
5683    EINA_LIST_FREE(it->edit_icon_objs, icon)
5684       evas_object_del(icon);
5685
5686 //   edje_object_signal_emit(it->edit_obj, "elm,state,edit_end,disable", "elm");
5687    it->effect_item_realized = EINA_FALSE;
5688 }
5689
5690 /**
5691  * Get Genlist edit mode
5692  *
5693  * @param obj The genlist object
5694  * @return The edit mode status
5695  * (EINA_TRUE = edit mode, EINA_FALSE = normal mode
5696  *
5697  * @ingroup Genlist
5698  */
5699 EAPI Eina_Bool
5700 elm_genlist_edit_mode_get(const Evas_Object *obj)
5701 {
5702    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5703    Widget_Data *wd = elm_widget_data_get(obj);
5704    if (!wd) return EINA_FALSE;
5705
5706    if (wd->edit_mode) return EINA_TRUE;
5707    else return EINA_FALSE;
5708 }
5709
5710 /**
5711  * Set Genlist edit mode
5712  *
5713  * This sets Genlist edit mode.
5714  *
5715  * @param obj The Genlist object
5716  * @param emode ELM_GENLIST_EDIT_MODE_{NONE & REORDER & INSERT & DELETE & SELECT & SELECT_ALL}
5717  * @param edit_class Genlist edit class (Elm_Genlist_Edit_Class structure)
5718  *
5719  * @ingroup Genlist
5720  */
5721 EAPI void
5722 elm_genlist_edit_mode_set(Evas_Object *obj, Eina_Bool edit_mode)
5723 {
5724    ELM_CHECK_WIDTYPE(obj, widtype);
5725
5726    Item_Block *itb;
5727    Eina_List *l;
5728    Elm_Genlist_Item *it;
5729
5730    Widget_Data *wd = elm_widget_data_get(obj);
5731    if (!wd) return;
5732    if (wd->edit_mode == edit_mode) return;
5733
5734    wd->edit_mode = edit_mode;
5735    if (!wd->edit_mode)
5736      {
5737         EINA_INLIST_FOREACH(wd->blocks, itb)
5738           {
5739              if (itb->realized)
5740                {
5741                   EINA_LIST_FOREACH(itb->items, l, it)
5742                     {
5743                        if (it->flags != ELM_GENLIST_ITEM_GROUP && it->realized)
5744                          {
5745                             _effect_item_unrealize(it);
5746                          }
5747                     }
5748                }
5749           }
5750         _item_cache_zero(wd);
5751      }
5752    else
5753      {
5754
5755         EINA_INLIST_FOREACH(wd->blocks, itb)
5756           {
5757              if (itb->realized)
5758                {
5759                   EINA_LIST_FOREACH(itb->items, l, it)
5760                     {
5761                        if (it->flags != ELM_GENLIST_ITEM_GROUP && it->realized)
5762                          {
5763                             if(it->selected) _item_unselect(it);
5764                             if (it->itc->edit_item_style) _effect_item_realize(it, EINA_TRUE);
5765                          }
5766                     }
5767                 }
5768            }
5769       }
5770
5771    if (wd->calc_job) ecore_job_del(wd->calc_job);
5772    wd->calc_job = ecore_job_add(_calc_job, wd);
5773 }
5774
5775 /**
5776  * Set a given item's rename mode
5777  *
5778  * This renames the item's label from genlist
5779  *
5780  * @param it The item
5781  * @param renamed set if emode is EINA_TRUE, unset if emode is EINA_FALSE
5782  *
5783  * @ingroup Genlist
5784  */
5785 EAPI void
5786 elm_genlist_item_rename_mode_set(Elm_Genlist_Item *it, Eina_Bool renamed)
5787 {
5788    if (!it) return;
5789
5790    if (renamed)
5791      {
5792         _item_unrealize(it, EINA_FALSE);
5793         it->renamed = EINA_TRUE;
5794         it->nocache = EINA_TRUE;
5795         if (it->selected)  _item_unselect(it);
5796
5797         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5798         it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
5799      }
5800    else
5801      {
5802         if (it->renamed)
5803           {
5804              it->renamed = EINA_FALSE;
5805              it->nocache = EINA_TRUE;
5806              _item_cache_zero(it->wd);
5807              elm_genlist_item_update(it);
5808           }
5809      }
5810 }
5811
5812 EAPI Eina_Bool
5813 elm_genlist_item_rename_mode_get(Elm_Genlist_Item *item)
5814 {
5815    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5816    return item->renamed;
5817 }