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