Merge "[C&P popup] supprot multi language"
[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                   if (mw > itb->w)
2907                     width_changed = EINA_TRUE;
2908                   else
2909                     mw = itb->w;
2910                   it->w = it->minw = mw;
2911                   it->h = it->minh = mh;
2912                   it->mincalcd = EINA_TRUE;
2913
2914                   //if ((it->minw != itminw) || (it->minh != itminh))
2915                   //if ((it->minh != itminh))
2916                   //  recalc = 1;
2917                   if ((it->minw != itminw))
2918                     width_changed = EINA_TRUE;
2919                   if ((it->minh != itminh))
2920                     height_changed = EINA_TRUE;
2921
2922                   if ((!it->wd->group_item_width) && (it->flags == ELM_GENLIST_ITEM_GROUP))
2923                     {
2924                        it->wd->group_item_width = mw;
2925                        it->wd->group_item_height = mh;
2926                     }
2927                   else if ((!it->wd->item_width) && (it->flags == ELM_GENLIST_ITEM_NONE))
2928                     {
2929                        it->wd->item_width = mw;
2930                        it->wd->item_height = mh;
2931                     }
2932                }
2933              num++;
2934           }
2935         itb->changeme = EINA_FALSE;
2936         // TODO: why this is separated.
2937         if (height_changed)
2938           {
2939              position = 1;
2940              itb->changed = EINA_TRUE;
2941              _item_block_recalc(itb, num0, 0);
2942              _item_block_position(itb, num0);
2943           }
2944         else if (width_changed)
2945           {
2946              _item_block_position(itb, num0);
2947           }
2948      }
2949    if (position)
2950      {
2951         if (wd->calc_job) ecore_job_del(wd->calc_job);
2952         wd->calc_job = ecore_job_add(_calc_job, wd);
2953      }
2954 }
2955
2956 static void
2957 _pan_set(Evas_Object *obj,
2958          Evas_Coord   x,
2959          Evas_Coord   y)
2960 {
2961    Pan *sd = evas_object_smart_data_get(obj);
2962 #ifdef ANCHOR_ITEM
2963    Item_Block *itb;
2964 #endif
2965
2966    if (!sd) return;
2967    //   Evas_Coord ow, oh;
2968    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2969    //   ow = sd->wd->minw - ow;
2970    //   if (ow < 0) ow = 0;
2971    //   oh = sd->wd->minh - oh;
2972    //   if (oh < 0) oh = 0;
2973    //   if (x < 0) x = 0;
2974    //   if (y < 0) y = 0;
2975    //   if (x > ow) x = ow;
2976    //   if (y > oh) y = oh;
2977    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2978    sd->wd->pan_x = x;
2979    sd->wd->pan_y = y;
2980
2981 #ifdef ANCHOR_ITEM
2982    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2983      {
2984         if ((itb->y + itb->h) > y)
2985           {
2986              Elm_Genlist_Item *it;
2987              Eina_List *l2;
2988
2989              EINA_LIST_FOREACH(itb->items, l2, it)
2990                {
2991                   if ((itb->y + it->y) >= y)
2992                     {
2993                        sd->wd->anchor_item = it;
2994                        sd->wd->anchor_y = -(itb->y + it->y - y);
2995                        goto done;
2996                     }
2997                }
2998           }
2999      }
3000 done:
3001 #endif
3002    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
3003 }
3004
3005 static void
3006 _pan_get(Evas_Object *obj,
3007          Evas_Coord  *x,
3008          Evas_Coord  *y)
3009 {
3010    Pan *sd = evas_object_smart_data_get(obj);
3011
3012    if (!sd) return;
3013    if (x) *x = sd->wd->pan_x;
3014    if (y) *y = sd->wd->pan_y;
3015 }
3016
3017 static void
3018 _pan_max_get(Evas_Object *obj,
3019              Evas_Coord  *x,
3020              Evas_Coord  *y)
3021 {
3022    Pan *sd = evas_object_smart_data_get(obj);
3023    Evas_Coord ow, oh;
3024
3025    if (!sd) return;
3026    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3027    ow = sd->wd->minw - ow;
3028    if (ow < 0) ow = 0;
3029    oh = sd->wd->minh - oh;
3030    if (oh < 0) oh = 0;
3031    if (x) *x = ow;
3032    if (y) *y = oh;
3033 }
3034
3035 static void
3036 _pan_min_get(Evas_Object *obj __UNUSED__,
3037              Evas_Coord  *x,
3038              Evas_Coord  *y)
3039 {
3040    if (x) *x = 0;
3041    if (y) *y = 0;
3042 }
3043
3044 static void
3045 _pan_child_size_get(Evas_Object *obj,
3046                     Evas_Coord  *w,
3047                     Evas_Coord  *h)
3048 {
3049    Pan *sd = evas_object_smart_data_get(obj);
3050
3051    if (!sd) return;
3052    if (w) *w = sd->wd->minw;
3053    if (h) *h = sd->wd->minh;
3054 }
3055
3056 static void
3057 _pan_add(Evas_Object *obj)
3058 {
3059    Pan *sd;
3060    Evas_Object_Smart_Clipped_Data *cd;
3061
3062    _pan_sc.add(obj);
3063    cd = evas_object_smart_data_get(obj);
3064    sd = ELM_NEW(Pan);
3065    if (!sd) return;
3066    sd->__clipped_data = *cd;
3067    free(cd);
3068    evas_object_smart_data_set(obj, sd);
3069 }
3070
3071 static void
3072 _pan_del(Evas_Object *obj)
3073 {
3074    Pan *sd = evas_object_smart_data_get(obj);
3075
3076    if (!sd) return;
3077    if (sd->resize_job)
3078      {
3079         ecore_job_del(sd->resize_job);
3080         sd->resize_job = NULL;
3081      }
3082    _pan_sc.del(obj);
3083 }
3084
3085 static void
3086 _pan_resize_job(void *data)
3087 {
3088    Pan *sd = data;
3089    if (!sd) return;
3090    _sizing_eval(sd->wd->obj);
3091    sd->resize_job = NULL;
3092 }
3093
3094 static void
3095 _pan_resize(Evas_Object *obj,
3096             Evas_Coord   w,
3097             Evas_Coord   h)
3098 {
3099    Pan *sd = evas_object_smart_data_get(obj);
3100    Evas_Coord ow, oh;
3101
3102    if (!sd) return;
3103    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3104    if ((ow == w) && (oh == h)) return;
3105    if ((sd->wd->height_for_width) && (ow != w))
3106      {
3107         sd->wd->pan_resize = EINA_TRUE;
3108         if (sd->resize_job) ecore_job_del(sd->resize_job);
3109         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
3110      }
3111    sd->wd->pan_changed = EINA_TRUE;
3112    evas_object_smart_changed(obj);
3113    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3114    sd->wd->calc_job = NULL;
3115 }
3116
3117 static void
3118 _pan_calculate(Evas_Object *obj)
3119 {
3120    Pan *sd = evas_object_smart_data_get(obj);
3121    Item_Block *itb;
3122    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
3123    int in = 0;
3124    Elm_Genlist_Item *git;
3125    Eina_List *l;
3126
3127    if (!sd) return;
3128    evas_event_freeze(evas_object_evas_get(obj));
3129
3130    if (sd->wd->pan_changed)
3131      {
3132         _calc_job(sd->wd);
3133         sd->wd->pan_changed = EINA_FALSE;
3134      }
3135
3136    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3137    sd->wd->prev_viewport_w = ow;
3138    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
3139    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3140      {
3141         itb->w = sd->wd->minw;
3142         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3143                                 itb->y - sd->wd->pan_y + oy,
3144                                 itb->w, itb->h,
3145                                 cvx, cvy, cvw, cvh))
3146           {
3147              if ((!itb->realized) || (itb->changed))
3148                _item_block_realize(itb);
3149              _item_block_position(itb, in);
3150           }
3151         else
3152           {
3153              if (itb->realized) _item_block_unrealize(itb);
3154           }
3155         in += itb->count;
3156      }
3157
3158    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3159      {
3160         if (sd->wd->pan_y != sd->wd->old_pan_y)
3161           sd->wd->reorder_pan_move = EINA_TRUE;
3162         else sd->wd->reorder_pan_move = EINA_FALSE;
3163         evas_object_raise(sd->wd->reorder_it->edit_obj);
3164         sd->wd->old_pan_y = sd->wd->pan_y;
3165         sd->wd->start_time = ecore_loop_time_get();
3166      }
3167
3168       if (sd->wd->effect_mode &&
3169           ((sd->wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND) ||
3170            (sd->wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT) ||
3171            (sd->wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE)))
3172         {
3173            if (!sd->wd->item_moving_effect_timer)
3174              {
3175                 if (sd->wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE)
3176                    _item_flip_effect_show(sd->wd->expand_item);
3177
3178                 evas_object_raise(sd->wd->alpha_bg);
3179                 evas_object_show(sd->wd->alpha_bg);
3180                 elm_smart_scroller_bounce_animator_disabled_set(sd->wd->scr, EINA_TRUE);
3181                 sd->wd->start_time = current_time_get();
3182                 sd->wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, sd->wd);
3183              }
3184         }
3185       else _item_auto_scroll(sd->wd);
3186    sd->wd->pan_resize = EINA_FALSE;
3187    evas_event_thaw(evas_object_evas_get(obj));
3188    evas_event_thaw_eval(evas_object_evas_get(obj));
3189 }
3190
3191 static void
3192 _pan_move(Evas_Object *obj,
3193           Evas_Coord   x __UNUSED__,
3194           Evas_Coord   y __UNUSED__)
3195 {
3196    Pan *sd = evas_object_smart_data_get(obj);
3197
3198    if (!sd) return;
3199
3200    sd->wd->pan_changed = EINA_TRUE;
3201    evas_object_smart_changed(obj);
3202    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3203    sd->wd->calc_job = NULL;
3204 }
3205
3206 static void
3207 _hold_on(void        *data __UNUSED__,
3208          Evas_Object *obj,
3209          void        *event_info __UNUSED__)
3210 {
3211    Widget_Data *wd = elm_widget_data_get(obj);
3212    if (!wd) return;
3213    elm_smart_scroller_hold_set(wd->scr, 1);
3214 }
3215
3216 static void
3217 _hold_off(void        *data __UNUSED__,
3218           Evas_Object *obj,
3219           void        *event_info __UNUSED__)
3220 {
3221    Widget_Data *wd = elm_widget_data_get(obj);
3222    if (!wd) return;
3223    elm_smart_scroller_hold_set(wd->scr, 0);
3224 }
3225
3226 static void
3227 _freeze_on(void        *data __UNUSED__,
3228            Evas_Object *obj,
3229            void        *event_info __UNUSED__)
3230 {
3231    Widget_Data *wd = elm_widget_data_get(obj);
3232    if (!wd) return;
3233    elm_smart_scroller_freeze_set(wd->scr, 1);
3234 }
3235
3236 static void
3237 _freeze_off(void        *data __UNUSED__,
3238             Evas_Object *obj,
3239             void        *event_info __UNUSED__)
3240 {
3241    Widget_Data *wd = elm_widget_data_get(obj);
3242    if (!wd) return;
3243    elm_smart_scroller_freeze_set(wd->scr, 0);
3244 }
3245
3246 static void
3247 _scr_anim_start(void        *data,
3248                 Evas_Object *obj __UNUSED__,
3249                 void        *event_info __UNUSED__)
3250 {
3251    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3252 }
3253
3254 static void
3255 _scr_anim_stop(void        *data,
3256                Evas_Object *obj __UNUSED__,
3257                void        *event_info __UNUSED__)
3258 {
3259    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3260 }
3261
3262 static void
3263 _scr_drag_start(void            *data,
3264                 Evas_Object     *obj __UNUSED__,
3265                 void            *event_info __UNUSED__)
3266 {
3267    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3268 }
3269
3270 static void
3271 _scr_drag_stop(void            *data,
3272                Evas_Object     *obj __UNUSED__,
3273                void            *event_info __UNUSED__)
3274 {
3275    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3276 }
3277
3278 static void
3279 _scroll_edge_left(void        *data,
3280                   Evas_Object *scr __UNUSED__,
3281                   void        *event_info __UNUSED__)
3282 {
3283    Evas_Object *obj = data;
3284    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_LEFT, NULL);
3285 }
3286
3287 static void
3288 _scroll_edge_right(void        *data,
3289                    Evas_Object *scr __UNUSED__,
3290                    void        *event_info __UNUSED__)
3291 {
3292    Evas_Object *obj = data;
3293    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_RIGHT, NULL);
3294 }
3295
3296 static void
3297 _scroll_edge_top(void        *data,
3298                  Evas_Object *scr __UNUSED__,
3299                  void        *event_info __UNUSED__)
3300 {
3301    Evas_Object *obj = data;
3302    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_TOP, NULL);
3303 }
3304
3305 static void
3306 _scroll_edge_bottom(void        *data,
3307                     Evas_Object *scr __UNUSED__,
3308                     void        *event_info __UNUSED__)
3309 {
3310    Evas_Object *obj = data;
3311    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_BOTTOM, NULL);
3312 }
3313
3314 static void
3315 _mode_item_realize(Elm_Genlist_Item *it)
3316 {
3317    char buf[1024];
3318
3319    if ((it->mode_view) || (it->delete_me)) return;
3320
3321    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3322    it->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3323    edje_object_scale_set(it->mode_view,
3324                          elm_widget_scale_get(WIDGET(it)) *
3325                          _elm_config->scale);
3326    evas_object_smart_member_add(it->mode_view, it->wd->pan_smart);
3327    elm_widget_sub_object_add(WIDGET(it), it->mode_view);
3328
3329    strncpy(buf, "item", sizeof(buf));
3330    if (it->wd->compress)
3331      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3332
3333    if (it->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3334    strncat(buf, "/", sizeof(buf) - strlen(buf));
3335    strncat(buf, it->itc->mode_item_style, sizeof(buf) - strlen(buf));
3336
3337    _elm_theme_object_set(WIDGET(it), it->mode_view, "genlist", buf,
3338                          elm_widget_style_get(WIDGET(it)));
3339    edje_object_mirrored_set(it->mode_view,
3340                             elm_widget_mirrored_get(WIDGET(it)));
3341
3342    /* signal callback add */
3343    evas_object_event_callback_add(it->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
3344                                   _mouse_down, it);
3345    evas_object_event_callback_add(it->mode_view, EVAS_CALLBACK_MOUSE_UP,
3346                                   _mouse_up, it);
3347    evas_object_event_callback_add(it->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
3348                                   _mouse_move, it);
3349
3350    /* label_get, icon_get, state_get */
3351    _item_label_realize(it, it->mode_view, &it->mode_labels, NULL);
3352    if (it->itc->func.icon_get)
3353      {
3354         const Eina_List *l;
3355         const char *key;
3356
3357         it->mode_icons =
3358            elm_widget_stringlist_get(edje_object_data_get(it->mode_view,
3359                                                           "icons"));
3360         EINA_LIST_FOREACH(it->mode_icons, l, key)
3361          {
3362            Evas_Object *ic = it->itc->func.icon_get
3363                 ((void *)it->base.data, WIDGET(it), l->data);
3364
3365              if (ic)
3366                {
3367                   it->mode_icon_objs = eina_list_append(it->mode_icon_objs, ic);
3368                   edje_object_part_swallow(it->mode_view, key, ic);
3369                   evas_object_show(ic);
3370                   elm_widget_sub_object_add(WIDGET(it), ic);
3371                   if (it->disabled)
3372                     elm_widget_disabled_set(ic, EINA_TRUE);
3373                }
3374           }
3375      }
3376    _item_state_realize(it, it->mode_view, &it->mode_states, NULL);
3377    edje_object_part_swallow(it->mode_view,
3378                             edje_object_data_get(it->mode_view, "mode_part"),
3379                             VIEW(it));
3380
3381    it->want_unrealize = EINA_FALSE;
3382    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3383    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3384 }
3385
3386 static void
3387 _mode_item_unrealize(Elm_Genlist_Item *it)
3388 {
3389    Widget_Data *wd = it->wd;
3390    Evas_Object *icon;
3391    if (!it->mode_view) return;
3392
3393    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3394    elm_widget_stringlist_free(it->mode_labels);
3395    it->mode_labels = NULL;
3396    elm_widget_stringlist_free(it->mode_icons);
3397    it->mode_icons = NULL;
3398    elm_widget_stringlist_free(it->mode_states);
3399
3400    EINA_LIST_FREE(it->mode_icon_objs, icon)
3401      evas_object_del(icon);
3402
3403    edje_object_part_unswallow(it->mode_view, VIEW(it));
3404    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3405    evas_object_del(it->mode_view);
3406    it->mode_view = NULL;
3407
3408    if (wd->mode_item == it)
3409      wd->mode_item = NULL;
3410    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3411    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3412 }
3413
3414 static void
3415 _item_mode_set(Elm_Genlist_Item *it)
3416 {
3417    if (!it) return;
3418    Widget_Data *wd = it->wd;
3419    if (!wd) return;
3420    char buf[1024];
3421
3422    wd->mode_item = it;
3423    it->nocache = EINA_TRUE;
3424
3425    if (wd->scr_hold_timer)
3426      {
3427         ecore_timer_del(wd->scr_hold_timer);
3428         wd->scr_hold_timer = NULL;
3429      }
3430    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3431    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3432
3433    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3434    _mode_item_realize(it);
3435    if (it->group_item)
3436      evas_object_raise(it->VIEW(group_item));
3437    _item_position(it, it->mode_view, it->scrl_x, it->scrl_y);
3438    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3439    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3440
3441    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
3442    edje_object_signal_emit(it->mode_view, buf, "elm");
3443 }
3444
3445 static void
3446 _item_mode_unset(Widget_Data *wd)
3447 {
3448    if (!wd) return;
3449    if (!wd->mode_item) return;
3450    char buf[1024], buf2[1024];
3451    Elm_Genlist_Item *it;
3452
3453    it = wd->mode_item;
3454    it->nocache = EINA_TRUE;
3455
3456    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type);
3457    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type);
3458
3459    edje_object_signal_emit(it->mode_view, buf, "elm");
3460    edje_object_signal_callback_add(it->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
3461
3462    wd->mode_item = NULL;
3463 }
3464
3465
3466 static void
3467 _item_auto_scroll(void *data)
3468 {
3469    Widget_Data *wd = data;
3470    if (!wd) return;
3471
3472    if ((wd->expand_item) && (!wd->auto_scrolled))
3473      {
3474         Elm_Genlist_Item  *it;
3475         Eina_List *l;
3476         Evas_Coord ox, oy, ow, oh;
3477         evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
3478
3479         wd->auto_scrolled = EINA_TRUE;
3480         if (wd->expand_item->scrl_y > (oh + oy) / 2)
3481           {
3482             EINA_LIST_FOREACH(wd->expand_item->items, l, it)
3483               {
3484                  elm_genlist_item_bring_in(it);
3485               }
3486           }
3487      }
3488 }
3489 EAPI Evas_Object *
3490 elm_genlist_add(Evas_Object *parent)
3491 {
3492    Evas_Object *obj;
3493    Evas *e;
3494    Widget_Data *wd;
3495    Evas_Coord minw, minh;
3496    static Evas_Smart *smart = NULL;
3497
3498    if (!smart)
3499      {
3500         static Evas_Smart_Class sc;
3501
3502         evas_object_smart_clipped_smart_set(&_pan_sc);
3503         sc = _pan_sc;
3504         sc.name = "elm_genlist_pan";
3505         sc.version = EVAS_SMART_CLASS_VERSION;
3506         sc.add = _pan_add;
3507         sc.del = _pan_del;
3508         sc.resize = _pan_resize;
3509         sc.move = _pan_move;
3510         sc.calculate = _pan_calculate;
3511         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3512      }
3513
3514    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3515
3516    ELM_SET_WIDTYPE(widtype, "genlist");
3517    elm_widget_type_set(obj, "genlist");
3518    elm_widget_sub_object_add(parent, obj);
3519    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3520    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3521    elm_widget_data_set(obj, wd);
3522    elm_widget_del_hook_set(obj, _del_hook);
3523    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3524    elm_widget_theme_hook_set(obj, _theme_hook);
3525    elm_widget_can_focus_set(obj, EINA_TRUE);
3526    elm_widget_event_hook_set(obj, _event_hook);
3527    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3528    elm_widget_translate_hook_set(obj, _translate_hook);
3529
3530    wd->scr = elm_smart_scroller_add(e);
3531    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_DOWN,
3532                                   _mouse_down_scroller, obj);
3533    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_UP,
3534                                   _mouse_up_scroller, obj);
3535    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_MOVE,
3536                                   _mouse_move_scroller, obj);
3537    elm_smart_scroller_widget_set(wd->scr, obj);
3538    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3539                                        elm_widget_style_get(obj));
3540    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3541                                        _elm_config->thumbscroll_bounce_enable);
3542    elm_widget_resize_object_set(obj, wd->scr);
3543
3544    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3545    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3546    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3547    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3548    evas_object_smart_callback_add(wd->scr, "edge,left", _scroll_edge_left, obj);
3549    evas_object_smart_callback_add(wd->scr, "edge,right", _scroll_edge_right,
3550                                   obj);
3551    evas_object_smart_callback_add(wd->scr, "edge,top", _scroll_edge_top, obj);
3552    evas_object_smart_callback_add(wd->scr, "edge,bottom", _scroll_edge_bottom,
3553                                   obj);
3554
3555    wd->obj = obj;
3556    wd->mode = ELM_LIST_SCROLL;
3557    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3558    wd->item_cache_max = wd->max_items_per_block * 2;
3559    wd->longpress_timeout = _elm_config->longpress_timeout;
3560    wd->effect_mode = _elm_config->effect_enable;
3561
3562    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3563    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3564    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3565    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3566
3567    wd->pan_smart = evas_object_smart_add(e, smart);
3568    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3569    wd->pan->wd = wd;
3570
3571    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3572                                      _pan_set, _pan_get, _pan_max_get,
3573                                      _pan_min_get, _pan_child_size_get);
3574
3575    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3576                              &minw, &minh);
3577    evas_object_size_hint_min_set(obj, minw, minh);
3578
3579    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3580    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3581    _sizing_eval(obj);
3582    return obj;
3583 }
3584
3585 static Elm_Genlist_Item *
3586 _item_new(Widget_Data                  *wd,
3587           const Elm_Genlist_Item_Class *itc,
3588           const void                   *data,
3589           Elm_Genlist_Item             *parent,
3590           Elm_Genlist_Item_Flags        flags,
3591           Evas_Smart_Cb                 func,
3592           const void                   *func_data)
3593 {
3594    Elm_Genlist_Item *it;
3595
3596    it = elm_widget_item_new(wd->obj, Elm_Genlist_Item);
3597    if (!it) return NULL;
3598    it->wd = wd;
3599    it->itc = itc;
3600    it->base.data = data;
3601    it->parent = parent;
3602    it->flags = flags;
3603    it->func.func = func;
3604    it->func.data = func_data;
3605    it->mouse_cursor = NULL;
3606    it->expanded_depth = 0;
3607    it->can_focus = EINA_TRUE;
3608    elm_widget_item_text_get_hook_set(it, _item_label_hook);
3609    elm_widget_item_del_cb_set(it, _item_del_hook);
3610
3611    if (it->parent)
3612      {
3613         if (it->parent->flags & ELM_GENLIST_ITEM_GROUP)
3614           it->group_item = parent;
3615         else if (it->parent->group_item)
3616           it->group_item = it->parent->group_item;
3617      }
3618    return it;
3619 }
3620
3621 static void
3622 _item_block_add(Widget_Data      *wd,
3623                 Elm_Genlist_Item *it)
3624 {
3625    Item_Block *itb = NULL;
3626
3627    if (!it->rel)
3628      {
3629 newblock:
3630         if (it->rel)
3631           {
3632              itb = calloc(1, sizeof(Item_Block));
3633              if (!itb) return;
3634              itb->wd = wd;
3635              if (!it->rel->block)
3636                {
3637                   wd->blocks =
3638                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3639                   itb->items = eina_list_append(itb->items, it);
3640                }
3641              else
3642                {
3643                   if (it->before)
3644                     {
3645                        wd->blocks = eina_inlist_prepend_relative
3646                            (wd->blocks, EINA_INLIST_GET(itb),
3647                            EINA_INLIST_GET(it->rel->block));
3648                        itb->items =
3649                          eina_list_prepend_relative(itb->items, it, it->rel);
3650                     }
3651                   else
3652                     {
3653                        wd->blocks = eina_inlist_append_relative
3654                            (wd->blocks, EINA_INLIST_GET(itb),
3655                            EINA_INLIST_GET(it->rel->block));
3656                        itb->items =
3657                          eina_list_append_relative(itb->items, it, it->rel);
3658                     }
3659                }
3660           }
3661         else
3662           {
3663              if (it->before)
3664                {
3665                   if (wd->blocks)
3666                     {
3667                        itb = (Item_Block *)(wd->blocks);
3668                        if (itb->count >= wd->max_items_per_block)
3669                          {
3670                             itb = calloc(1, sizeof(Item_Block));
3671                             if (!itb) return;
3672                             itb->wd = wd;
3673                             wd->blocks =
3674                               eina_inlist_prepend(wd->blocks,
3675                                                   EINA_INLIST_GET(itb));
3676                          }
3677                     }
3678                   else
3679                     {
3680                        itb = calloc(1, sizeof(Item_Block));
3681                        if (!itb) return;
3682                        itb->wd = wd;
3683                        wd->blocks =
3684                          eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3685                     }
3686                   itb->items = eina_list_prepend(itb->items, it);
3687                }
3688              else
3689                {
3690                   if (wd->blocks)
3691                     {
3692                        itb = (Item_Block *)(wd->blocks->last);
3693                        if (itb->count >= wd->max_items_per_block)
3694                          {
3695                             itb = calloc(1, sizeof(Item_Block));
3696                             if (!itb) return;
3697                             itb->wd = wd;
3698                             wd->blocks =
3699                               eina_inlist_append(wd->blocks,
3700                                                  EINA_INLIST_GET(itb));
3701                          }
3702                     }
3703                   else
3704                     {
3705                        itb = calloc(1, sizeof(Item_Block));
3706                        if (!itb) return;
3707                        itb->wd = wd;
3708                        wd->blocks =
3709                          eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3710                     }
3711                   itb->items = eina_list_append(itb->items, it);
3712                }
3713           }
3714      }
3715    else
3716      {
3717         itb = it->rel->block;
3718         if (!itb) goto newblock;
3719         if (it->before)
3720           itb->items = eina_list_prepend_relative(itb->items, it, it->rel);
3721         else
3722           itb->items = eina_list_append_relative(itb->items, it, it->rel);
3723      }
3724    itb->count++;
3725    itb->changed = EINA_TRUE;
3726    it->block = itb;
3727    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3728    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3729    if (it->rel)
3730      {
3731         it->rel->relcount--;
3732         if ((it->rel->delete_me) && (!it->rel->relcount))
3733           _item_del(it->rel);
3734         it->rel = NULL;
3735      }
3736    if (itb->count > itb->wd->max_items_per_block)
3737      {
3738         int newc;
3739         Item_Block *itb2;
3740         Elm_Genlist_Item *it2;
3741
3742         newc = itb->count / 2;
3743         itb2 = calloc(1, sizeof(Item_Block));
3744         if (!itb2) return;
3745         itb2->wd = wd;
3746         wd->blocks =
3747           eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3748                                       EINA_INLIST_GET(itb));
3749         itb2->changed = EINA_TRUE;
3750         while ((itb->count > newc) && (itb->items))
3751           {
3752              Eina_List *l;
3753
3754              l = eina_list_last(itb->items);
3755              it2 = l->data;
3756              itb->items = eina_list_remove_list(itb->items, l);
3757              itb->count--;
3758
3759              itb2->items = eina_list_prepend(itb2->items, it2);
3760              it2->block = itb2;
3761              itb2->count++;
3762           }
3763      }
3764 }
3765
3766 static int
3767 _queue_process(Widget_Data *wd)
3768 {
3769    int n;
3770    Eina_Bool showme = EINA_FALSE;
3771    double t0, t;
3772
3773    t0 = ecore_time_get();
3774    //evas_event_freeze(evas_object_evas_get(wd->obj));
3775    for (n = 0; (wd->queue) && (n < 128); n++)
3776      {
3777         Elm_Genlist_Item *it;
3778
3779         it = wd->queue->data;
3780         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3781         it->queued = EINA_FALSE;
3782         _item_block_add(wd, it);
3783         t = ecore_time_get();
3784         if (it->block->changed)
3785           {
3786              showme = _item_block_recalc(it->block, it->block->num, EINA_TRUE);
3787              it->block->changed = 0;
3788              if(wd->pan_changed)
3789                {
3790                   if (wd->calc_job) ecore_job_del(wd->calc_job);
3791                   wd->calc_job = NULL;
3792                   _calc_job(wd);
3793                   wd->pan_changed = EINA_FALSE;
3794                }
3795           }
3796         if (showme) it->block->showme = EINA_TRUE;
3797         if (eina_inlist_count(wd->blocks) > 1)
3798           {
3799              if ((t - t0) > (ecore_animator_frametime_get())) break;
3800           }
3801      }
3802    //evas_event_thaw(evas_object_evas_get(wd->obj));
3803    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3804    return n;
3805 }
3806
3807 static Eina_Bool
3808 _idle_process(void *data, Eina_Bool *wakeup)
3809 {
3810    Widget_Data *wd = data;
3811
3812    //xxx
3813    //static double q_start = 0.0;
3814    //if (q_start == 0.0) q_start = ecore_time_get();
3815    //xxx
3816    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3817    if (!wd->queue)
3818      {
3819         //xxx
3820         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3821         //xxx
3822         return ECORE_CALLBACK_CANCEL;
3823      }
3824    return ECORE_CALLBACK_RENEW;
3825 }
3826
3827 static Eina_Bool
3828 _item_idle_enterer(void *data)
3829 {
3830    Widget_Data *wd = data;
3831    Eina_Bool wakeup = EINA_FALSE;
3832    Eina_Bool ok = _idle_process(data, &wakeup);
3833
3834    if (wakeup)
3835      {
3836         // wake up mainloop
3837         if (wd->calc_job) ecore_job_del(wd->calc_job);
3838         wd->calc_job = ecore_job_add(_calc_job, wd);
3839      }
3840    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3841    return ok;
3842 }
3843
3844 static void
3845 _item_queue(Widget_Data      *wd,
3846             Elm_Genlist_Item *it)
3847 {
3848    if (it->queued) return;
3849    it->queued = EINA_TRUE;
3850    wd->queue = eina_list_append(wd->queue, it);
3851 // FIXME: why does a freeze then thaw here cause some genlist
3852 // elm_genlist_item_append() to be much much slower?
3853 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3854    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3855      {
3856         if (wd->queue_idle_enterer)
3857           {
3858              ecore_idle_enterer_del(wd->queue_idle_enterer);
3859              wd->queue_idle_enterer = NULL;
3860           }
3861         _queue_process(wd);
3862      }
3863 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3864 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3865    if (!wd->queue_idle_enterer)
3866      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3867 }
3868
3869 static void
3870 _item_move_after(Elm_Genlist_Item *it, Elm_Genlist_Item *after)
3871 {
3872    if (!it) return;
3873    if (!after) return;
3874
3875    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3876    it->wd->reorder_deleted = EINA_TRUE;
3877    _item_block_del(it);
3878
3879    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3880    it->rel = after;
3881    it->rel->relcount++;
3882    it->before = EINA_FALSE;
3883    if (after->group_item) it->group_item = after->group_item;
3884    _item_queue(it->wd, it);
3885
3886    // TODO: change this to smart callback
3887    if (it->itc->func.moved)
3888      it->itc->func.moved(WIDGET(it), it, after, EINA_TRUE);
3889 }
3890
3891 static void
3892 _item_move_before(Elm_Genlist_Item *it, Elm_Genlist_Item *before)
3893 {
3894    if (!it) return;
3895    if (!before) return;
3896
3897    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3898    it->wd->reorder_deleted = EINA_TRUE;
3899    _item_block_del(it);
3900    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3901    it->rel = before;
3902    it->rel->relcount++;
3903    it->before = EINA_TRUE;
3904    if (before->group_item) it->group_item = before->group_item;
3905    _item_queue(it->wd, it);
3906
3907    // TODO: change this to smart callback
3908    if (it->itc->func.moved)
3909      it->itc->func.moved(WIDGET(it), it, before, EINA_FALSE);
3910 }
3911
3912 EAPI Elm_Genlist_Item *
3913 elm_genlist_item_append(Evas_Object                  *obj,
3914                         const Elm_Genlist_Item_Class *itc,
3915                         const void                   *data,
3916                         Elm_Genlist_Item             *parent,
3917                         Elm_Genlist_Item_Flags        flags,
3918                         Evas_Smart_Cb                 func,
3919                         const void                   *func_data)
3920 {
3921    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3922    Widget_Data *wd = elm_widget_data_get(obj);
3923    if (!wd) return NULL;
3924    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
3925                                     func_data);
3926    if (!it) return NULL;
3927    if (!it->parent)
3928      {
3929         if (flags & ELM_GENLIST_ITEM_GROUP)
3930           wd->group_items = eina_list_append(wd->group_items, it);
3931         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3932         it->rel = NULL;
3933      }
3934    else
3935      {
3936         Elm_Genlist_Item *it2 = NULL;
3937         Eina_List *ll = eina_list_last(it->parent->items);
3938         if (ll) it2 = ll->data;
3939         it->parent->items = eina_list_append(it->parent->items, it);
3940         if (!it2) it2 = it->parent;
3941         if (it2->delete_me)
3942            it2 = elm_genlist_item_prev_get(it2);
3943         wd->items =
3944           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3945                                       EINA_INLIST_GET(it2));
3946         it->rel = it2;
3947         it->rel->relcount++;
3948      }
3949    it->before = EINA_FALSE;
3950    _item_queue(wd, it);
3951    return it;
3952 }
3953
3954 EAPI Elm_Genlist_Item *
3955 elm_genlist_item_prepend(Evas_Object                  *obj,
3956                          const Elm_Genlist_Item_Class *itc,
3957                          const void                   *data,
3958                          Elm_Genlist_Item             *parent,
3959                          Elm_Genlist_Item_Flags        flags,
3960                          Evas_Smart_Cb                 func,
3961                          const void                   *func_data)
3962 {
3963    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3964    Widget_Data *wd = elm_widget_data_get(obj);
3965    if (!wd) return NULL;
3966    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
3967                                     func_data);
3968
3969    if (!it) return NULL;
3970    if (!it->parent)
3971      {
3972         if (flags & ELM_GENLIST_ITEM_GROUP)
3973           wd->group_items = eina_list_prepend(wd->group_items, it);
3974         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3975         it->rel = NULL;
3976      }
3977    else
3978      {
3979         Elm_Genlist_Item *it2 = NULL;
3980         Eina_List *ll = it->parent->items;
3981         if (ll) it2 = ll->data;
3982         it->parent->items = eina_list_prepend(it->parent->items, it);
3983         if (!it2) it2 = it->parent;
3984         if (it2->delete_me)
3985            it2 = elm_genlist_item_next_get(it2);
3986         wd->items =
3987           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3988                                        EINA_INLIST_GET(it2));
3989         it->rel = it2;
3990         it->rel->relcount++;
3991      }
3992    it->before = EINA_TRUE;
3993    _item_queue(wd, it);
3994    return it;
3995 }
3996
3997 EAPI Elm_Genlist_Item *
3998 elm_genlist_item_insert_after(Evas_Object                  *obj,
3999                               const Elm_Genlist_Item_Class *itc,
4000                               const void                   *data,
4001                               Elm_Genlist_Item             *parent,
4002                               Elm_Genlist_Item             *after,
4003                               Elm_Genlist_Item_Flags        flags,
4004                               Evas_Smart_Cb                 func,
4005                               const void                   *func_data)
4006 {
4007    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4008    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
4009    Widget_Data *wd = elm_widget_data_get(obj);
4010    if (!wd) return NULL;
4011    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4012    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
4013                                     func_data);
4014    if (!it) return NULL;
4015
4016    if (!it->parent)
4017      {
4018         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
4019             (after->flags & ELM_GENLIST_ITEM_GROUP))
4020           wd->group_items = eina_list_append_relative(wd->group_items, it,
4021                                                       after);
4022      }
4023    else
4024      {
4025         it->parent->items = eina_list_append_relative(it->parent->items, it,
4026                                                       after);
4027      }
4028    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4029                                            EINA_INLIST_GET(after));
4030    it->rel = after;
4031    it->rel->relcount++;
4032    it->before = EINA_FALSE;
4033    _item_queue(wd, it);
4034    return it;
4035 }
4036
4037 EAPI Elm_Genlist_Item *
4038 elm_genlist_item_insert_before(Evas_Object                  *obj,
4039                                const Elm_Genlist_Item_Class *itc,
4040                                const void                   *data,
4041                                Elm_Genlist_Item             *parent,
4042                                Elm_Genlist_Item             *before,
4043                                Elm_Genlist_Item_Flags        flags,
4044                                Evas_Smart_Cb                 func,
4045                                const void                   *func_data)
4046 {
4047    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4048    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
4049    Widget_Data *wd = elm_widget_data_get(obj);
4050    if (!wd) return NULL;
4051    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4052    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
4053                                     func_data);
4054    if (!it) return NULL;
4055
4056    if (!it->parent)
4057      {
4058         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
4059             (before->flags & ELM_GENLIST_ITEM_GROUP))
4060           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4061                                                        before);
4062      }
4063    else
4064      {
4065         it->parent->items = eina_list_prepend_relative(it->parent->items, it,
4066                                                        before);
4067      }
4068    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4069                                             EINA_INLIST_GET(before));
4070    it->rel = before;
4071    it->rel->relcount++;
4072    it->before = EINA_TRUE;
4073    _item_queue(wd, it);
4074    return it;
4075 }
4076
4077 EAPI void
4078 elm_genlist_clear(Evas_Object *obj)
4079 {
4080    ELM_CHECK_WIDTYPE(obj, widtype);
4081    Widget_Data *wd = elm_widget_data_get(obj);
4082    if (!wd) return;
4083    if (wd->walking > 0)
4084      {
4085         Elm_Genlist_Item *it;
4086
4087         wd->clear_me = EINA_TRUE;
4088         EINA_INLIST_FOREACH(wd->items, it)
4089           {
4090              it->delete_me = EINA_TRUE;
4091           }
4092         return;
4093      }
4094    evas_event_freeze(evas_object_evas_get(wd->obj));
4095    while (wd->items)
4096      {
4097         Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
4098         it->nocache = EINA_TRUE;
4099         it->highlighted = EINA_FALSE;
4100 #ifdef ANCHOR_ITEM
4101         if (wd->anchor_item == it)
4102           {
4103              wd->anchor_item = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4104              if (!wd->anchor_item)
4105                wd->anchor_item =
4106                  ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4107           }
4108 #endif
4109         wd->items = eina_inlist_remove(wd->items, wd->items);
4110         if (it->flags & ELM_GENLIST_ITEM_GROUP)
4111           it->wd->group_items = eina_list_remove(it->wd->group_items, it);
4112         elm_widget_item_pre_notify_del(it);
4113         if (it->realized) _item_unrealize(it, EINA_FALSE);
4114         if (((wd->clear_me) || (!it->delete_me)) && (it->itc->func.del))
4115           it->itc->func.del((void *)it->base.data, WIDGET(it));
4116         if (it->long_timer) ecore_timer_del(it->long_timer);
4117         if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
4118         elm_widget_item_del(it);
4119      }
4120    wd->clear_me = EINA_FALSE;
4121    wd->anchor_item = NULL;
4122    while (wd->blocks)
4123      {
4124         Item_Block *itb = (Item_Block *)(wd->blocks);
4125
4126         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
4127         if (itb->items) eina_list_free(itb->items);
4128         free(itb);
4129      }
4130    wd->pan_changed = EINA_TRUE;
4131    if (wd->calc_job)
4132      {
4133         ecore_job_del(wd->calc_job);
4134         wd->calc_job = NULL;
4135      }
4136    if (wd->queue_idle_enterer)
4137      {
4138         ecore_idle_enterer_del(wd->queue_idle_enterer);
4139         wd->queue_idle_enterer = NULL;
4140      }
4141    if (wd->must_recalc_idler)
4142      {
4143         ecore_idler_del(wd->must_recalc_idler);
4144         wd->must_recalc_idler = NULL;
4145      }
4146    if (wd->queue)
4147      {
4148         eina_list_free(wd->queue);
4149         wd->queue = NULL;
4150      }
4151    if (wd->selected)
4152      {
4153         eina_list_free(wd->selected);
4154         wd->selected = NULL;
4155      }
4156    if (wd->reorder_move_animator)
4157      {
4158         ecore_animator_del(wd->reorder_move_animator);
4159         wd->reorder_move_animator = NULL;
4160      }
4161    wd->show_item = NULL;
4162    wd->pan_x = 0;
4163    wd->pan_y = 0;
4164    wd->old_pan_y = 0;
4165    wd->minw = 0;
4166    wd->minh = 0;
4167
4168    if (wd->alpha_bg)
4169       evas_object_del(wd->alpha_bg);
4170    wd->alpha_bg = NULL;
4171
4172    if (wd->pan_smart)
4173      {
4174         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4175         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4176      }
4177    _sizing_eval(obj);
4178    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4179    evas_event_thaw(evas_object_evas_get(wd->obj));
4180    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4181 }
4182
4183 EAPI void
4184 elm_genlist_multi_select_set(Evas_Object *obj,
4185                              Eina_Bool    multi)
4186 {
4187    ELM_CHECK_WIDTYPE(obj, widtype);
4188    Widget_Data *wd = elm_widget_data_get(obj);
4189    if (!wd) return;
4190    wd->multi = multi;
4191 }
4192
4193 EAPI Eina_Bool
4194 elm_genlist_multi_select_get(const Evas_Object *obj)
4195 {
4196    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4197    Widget_Data *wd = elm_widget_data_get(obj);
4198    if (!wd) return EINA_FALSE;
4199    return wd->multi;
4200 }
4201
4202 EAPI Elm_Genlist_Item *
4203 elm_genlist_selected_item_get(const Evas_Object *obj)
4204 {
4205    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4206    Widget_Data *wd = elm_widget_data_get(obj);
4207    if (!wd) return NULL;
4208    if (wd->selected) return wd->selected->data;
4209    return NULL;
4210 }
4211
4212 EAPI const Eina_List *
4213 elm_genlist_selected_items_get(const Evas_Object *obj)
4214 {
4215    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4216    Widget_Data *wd = elm_widget_data_get(obj);
4217    if (!wd) return NULL;
4218    return wd->selected;
4219 }
4220
4221 EAPI Eina_List *
4222 elm_genlist_realized_items_get(const Evas_Object *obj)
4223 {
4224    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4225    Widget_Data *wd = elm_widget_data_get(obj);
4226    Eina_List *list = NULL;
4227    Item_Block *itb;
4228    Eina_Bool done = EINA_FALSE;
4229    if (!wd) return NULL;
4230    EINA_INLIST_FOREACH(wd->blocks, itb)
4231      {
4232         if (itb->realized)
4233           {
4234              Eina_List *l;
4235              Elm_Genlist_Item *it;
4236
4237              done = 1;
4238              EINA_LIST_FOREACH(itb->items, l, it)
4239                {
4240                   if (it->realized) list = eina_list_append(list, it);
4241                }
4242           }
4243         else
4244           {
4245              if (done) break;
4246           }
4247      }
4248    return list;
4249 }
4250
4251 EAPI Elm_Genlist_Item *
4252 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4253                            Evas_Coord         x,
4254                            Evas_Coord         y,
4255                            int               *posret)
4256 {
4257    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4258    Widget_Data *wd = elm_widget_data_get(obj);
4259    Evas_Coord ox, oy, ow, oh;
4260    Item_Block *itb;
4261    Evas_Coord lasty;
4262    if (!wd) return NULL;
4263    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4264    lasty = oy;
4265    EINA_INLIST_FOREACH(wd->blocks, itb)
4266      {
4267         Eina_List *l;
4268         Elm_Genlist_Item *it;
4269
4270         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4271                                  oy + itb->y - itb->wd->pan_y,
4272                                  itb->w, itb->h, x, y, 1, 1))
4273           continue;
4274         EINA_LIST_FOREACH(itb->items, l, it)
4275           {
4276              Evas_Coord itx, ity;
4277
4278              itx = ox + itb->x + it->x - itb->wd->pan_x;
4279              ity = oy + itb->y + it->y - itb->wd->pan_y;
4280              if (ELM_RECTS_INTERSECT(itx, ity, it->w, it->h, x, y, 1, 1))
4281                {
4282                   if (posret)
4283                     {
4284                        if (y <= (ity + (it->h / 4))) *posret = -1;
4285                        else if (y >= (ity + it->h - (it->h / 4)))
4286                          *posret = 1;
4287                        else *posret = 0;
4288                     }
4289                   return it;
4290                }
4291              lasty = ity + it->h;
4292           }
4293      }
4294    if (posret)
4295      {
4296         if (y > lasty) *posret = 1;
4297         else *posret = -1;
4298      }
4299    return NULL;
4300 }
4301
4302 EAPI Elm_Genlist_Item *
4303 elm_genlist_first_item_get(const Evas_Object *obj)
4304 {
4305    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4306    Widget_Data *wd = elm_widget_data_get(obj);
4307    if (!wd) return NULL;
4308    if (!wd->items) return NULL;
4309    Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
4310    while ((it) && (it->delete_me))
4311      it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4312    return it;
4313 }
4314
4315 EAPI Elm_Genlist_Item *
4316 elm_genlist_last_item_get(const Evas_Object *obj)
4317 {
4318    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4319    Widget_Data *wd = elm_widget_data_get(obj);
4320    if (!wd) return NULL;
4321    if (!wd->items) return NULL;
4322    Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items->last);
4323    while ((it) && (it->delete_me))
4324      it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4325    return it;
4326 }
4327
4328 EAPI Elm_Genlist_Item *
4329 elm_genlist_item_next_get(const Elm_Genlist_Item *it)
4330 {
4331    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4332    while (it)
4333      {
4334         it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4335         if ((it) && (!it->delete_me)) break;
4336      }
4337    return (Elm_Genlist_Item *)it;
4338 }
4339
4340 EAPI Elm_Genlist_Item *
4341 elm_genlist_item_prev_get(const Elm_Genlist_Item *it)
4342 {
4343    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4344    while (it)
4345      {
4346         it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4347         if ((it) && (!it->delete_me)) break;
4348      }
4349    return (Elm_Genlist_Item *)it;
4350 }
4351
4352 EAPI Evas_Object *
4353 elm_genlist_item_genlist_get(const Elm_Genlist_Item *it)
4354 {
4355    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4356    return WIDGET(it);
4357 }
4358
4359 EAPI Elm_Genlist_Item *
4360 elm_genlist_item_parent_get(const Elm_Genlist_Item *it)
4361 {
4362    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4363    return it->parent;
4364 }
4365
4366 EAPI void
4367 elm_genlist_item_subitems_clear(Elm_Genlist_Item *it)
4368 {
4369    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4370    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4371    if (!wd) return;
4372    Elm_Genlist_Item *it2, *it3;
4373    Evas_Coord y, h;
4374
4375    if (!wd->effect_mode || !wd->move_effect_mode)
4376       _item_subitems_clear(it);
4377    else
4378      {
4379         if ((!wd->item_moving_effect_timer) && (it->flags != ELM_GENLIST_ITEM_GROUP) &&
4380              wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE)
4381           {
4382              wd->expand_item = it;
4383              _item_flip_effect_show(it);
4384              evas_object_geometry_get(VIEW(it), NULL, &y, NULL, &h);
4385              wd->expand_item_end = y + h;
4386
4387              it2= it;
4388              do {
4389                   it2 = elm_genlist_item_next_get(it2);
4390                   if (!it2) break;
4391              } while (it2->expanded_depth > it->expanded_depth);
4392              if (it2)
4393                {
4394                   int diff;
4395                   Evas_Coord vy, vh;
4396                   evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), NULL, &vy, NULL, &vh);
4397                   diff = it2->old_scrl_y - (vy + vh);
4398                   if (diff > 0)
4399                     {
4400                        it3 = it2;
4401                        while (it3)
4402                          {
4403                             it3->old_scrl_y = it3->old_scrl_y - diff;
4404                             it3 = elm_genlist_item_next_get(it3);
4405                          }
4406                     }
4407
4408                   wd->expand_item_gap = wd->expand_item_end - it2->old_scrl_y;
4409                }
4410              else
4411                 wd->expand_item_gap = 0;
4412
4413              evas_object_raise(wd->alpha_bg);
4414              evas_object_show(wd->alpha_bg);
4415
4416              wd->start_time = current_time_get();
4417              wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, wd);
4418           }
4419         else
4420            _item_subitems_clear(it);
4421      }
4422 }
4423
4424 EAPI void
4425 elm_genlist_item_selected_set(Elm_Genlist_Item *it,
4426                               Eina_Bool         selected)
4427 {
4428    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4429    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4430    if (!wd) return;
4431    if ((it->delete_me) || (it->disabled)) return;
4432    selected = !!selected;
4433    if (it->selected == selected) return;
4434
4435    if (selected)
4436      {
4437         if (!wd->multi)
4438           {
4439              while (wd->selected)
4440                _item_unselect(wd->selected->data);
4441           }
4442         _item_highlight(it);
4443         _item_select(it);
4444      }
4445    else
4446      _item_unselect(it);
4447 }
4448
4449 EAPI Eina_Bool
4450 elm_genlist_item_selected_get(const Elm_Genlist_Item *it)
4451 {
4452    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4453    return it->selected;
4454 }
4455
4456 EAPI void
4457 elm_genlist_item_expanded_set(Elm_Genlist_Item *it,
4458                               Eina_Bool         expanded)
4459 {
4460    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4461    if (it->flags != ELM_GENLIST_ITEM_SUBITEMS) return;
4462    if (it->expanded == expanded) return;
4463    it->expanded = expanded;
4464    it->wd->expand_item = it;
4465
4466    if (it->wd->effect_mode && !it->wd->alpha_bg)
4467       it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(it));
4468
4469    if (it->expanded)
4470      {
4471         it->wd->auto_scrolled = EINA_FALSE;
4472         it->wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND;
4473         if (it->realized)
4474           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
4475         evas_object_smart_callback_call(WIDGET(it), "expanded", it);
4476      }
4477    else
4478      {
4479         it->wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT;
4480         if (it->realized)
4481           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
4482         evas_object_smart_callback_call(WIDGET(it), "contracted", it);
4483      }
4484 }
4485
4486 EAPI Eina_Bool
4487 elm_genlist_item_expanded_get(const Elm_Genlist_Item *it)
4488 {
4489    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4490    return it->expanded;
4491 }
4492
4493 EAPI int
4494 elm_genlist_item_expanded_depth_get(const Elm_Genlist_Item *it)
4495 {
4496    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
4497    return it->expanded_depth;
4498 }
4499
4500 EAPI void
4501 elm_genlist_item_disabled_set(Elm_Genlist_Item *it,
4502                               Eina_Bool         disabled)
4503 {
4504    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4505    Eina_List *l;
4506    Evas_Object *obj;
4507    if (it->disabled == disabled) return;
4508    if (it->delete_me) return;
4509    it->disabled = !!disabled;
4510    if (it->selected)
4511      elm_genlist_item_selected_set(it, EINA_FALSE);
4512    if (it->realized)
4513      {
4514         if (it->disabled)
4515           {
4516              edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
4517              if (it->edit_obj)
4518                edje_object_signal_emit(it->edit_obj, "elm,state,disabled", "elm");
4519           }
4520         else
4521           {
4522              edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
4523              if (it->edit_obj)
4524                edje_object_signal_emit(it->edit_obj, "elm,state,enabled", "elm");
4525           }
4526         EINA_LIST_FOREACH(it->icon_objs, l, obj)
4527            elm_widget_disabled_set(obj, disabled);
4528      }
4529 }
4530
4531 EAPI Eina_Bool
4532 elm_genlist_item_disabled_get(const Elm_Genlist_Item *it)
4533 {
4534    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4535    if (it->delete_me) return EINA_FALSE;
4536    return it->disabled;
4537 }
4538
4539 EAPI void
4540 elm_genlist_item_display_only_set(Elm_Genlist_Item *it,
4541                                   Eina_Bool         display_only)
4542 {
4543    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4544    if (it->display_only == display_only) return;
4545    if (it->delete_me) return;
4546    it->display_only = display_only;
4547    it->mincalcd = EINA_FALSE;
4548    it->updateme = EINA_TRUE;
4549    if (it->block) it->block->updateme = EINA_TRUE;
4550    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4551    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4552 }
4553
4554 EAPI Eina_Bool
4555 elm_genlist_item_display_only_get(const Elm_Genlist_Item *it)
4556 {
4557    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4558    if (it->delete_me) return EINA_FALSE;
4559    return it->display_only;
4560 }
4561
4562 EAPI void
4563 elm_genlist_item_show(Elm_Genlist_Item *it)
4564 {
4565    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4566    if (it->delete_me) return;
4567    if ((it->queued) || (!it->mincalcd))
4568      {
4569         it->wd->show_item = it;
4570         it->wd->bring_in = EINA_TRUE;
4571         it->showme = EINA_TRUE;
4572         return;
4573      }
4574    if (it->wd->show_item)
4575      {
4576         it->wd->show_item->showme = EINA_FALSE;
4577         it->wd->show_item = NULL;
4578      }
4579    elm_smart_scroller_child_region_show(it->wd->scr,
4580                                         it->x + it->block->x,
4581                                         it->y + it->block->y,
4582                                         it->block->w, it->h);
4583 }
4584
4585 EAPI void
4586 elm_genlist_item_bring_in(Elm_Genlist_Item *it)
4587 {
4588    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4589    if (it->delete_me) return;
4590    if ((it->queued) || (!it->mincalcd))
4591      {
4592         it->wd->show_item = it;
4593         it->wd->bring_in = EINA_TRUE;
4594         it->showme = EINA_TRUE;
4595         return;
4596      }
4597    if (it->wd->show_item)
4598      {
4599         it->wd->show_item->showme = EINA_FALSE;
4600         it->wd->show_item = NULL;
4601      }
4602    elm_smart_scroller_region_bring_in(it->wd->scr,
4603                                       it->x + it->block->x,
4604                                       it->y + it->block->y,
4605                                       it->block->w, it->h);
4606 }
4607
4608 EAPI void
4609 elm_genlist_item_top_show(Elm_Genlist_Item *it)
4610 {
4611    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4612    Evas_Coord ow, oh;
4613
4614    if (it->delete_me) return;
4615    if ((it->queued) || (!it->mincalcd))
4616      {
4617         it->wd->show_item = it;
4618         it->wd->bring_in = EINA_TRUE;
4619         it->showme = EINA_TRUE;
4620         return;
4621      }
4622    if (it->wd->show_item)
4623      {
4624         it->wd->show_item->showme = EINA_FALSE;
4625         it->wd->show_item = NULL;
4626      }
4627    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4628    elm_smart_scroller_child_region_show(it->wd->scr,
4629                                         it->x + it->block->x,
4630                                         it->y + it->block->y,
4631                                         it->block->w, oh);
4632 }
4633
4634 EAPI void
4635 elm_genlist_item_top_bring_in(Elm_Genlist_Item *it)
4636 {
4637    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4638    Evas_Coord ow, oh;
4639
4640    if (it->delete_me) return;
4641    if ((it->queued) || (!it->mincalcd))
4642      {
4643         it->wd->show_item = it;
4644         it->wd->bring_in = EINA_TRUE;
4645         it->showme = EINA_TRUE;
4646         return;
4647      }
4648    if (it->wd->show_item)
4649      {
4650         it->wd->show_item->showme = EINA_FALSE;
4651         it->wd->show_item = NULL;
4652      }
4653    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4654    elm_smart_scroller_region_bring_in(it->wd->scr,
4655                                       it->x + it->block->x,
4656                                       it->y + it->block->y,
4657                                       it->block->w, oh);
4658 }
4659
4660 EAPI void
4661 elm_genlist_item_middle_show(Elm_Genlist_Item *it)
4662 {
4663    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4664    Evas_Coord ow, oh;
4665
4666    if (it->delete_me) return;
4667    if ((it->queued) || (!it->mincalcd))
4668      {
4669         it->wd->show_item = it;
4670         it->wd->bring_in = EINA_TRUE;
4671         it->showme = EINA_TRUE;
4672         return;
4673      }
4674    if (it->wd->show_item)
4675      {
4676         it->wd->show_item->showme = EINA_FALSE;
4677         it->wd->show_item = NULL;
4678      }
4679    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4680    elm_smart_scroller_child_region_show(it->wd->scr,
4681                                         it->x + it->block->x,
4682                                         it->y + it->block->y - oh / 2 +
4683                                         it->h / 2, it->block->w, oh);
4684 }
4685
4686 EAPI void
4687 elm_genlist_item_middle_bring_in(Elm_Genlist_Item *it)
4688 {
4689    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4690    Evas_Coord ow, oh;
4691
4692    if (it->delete_me) return;
4693    if ((it->queued) || (!it->mincalcd))
4694      {
4695         it->wd->show_item = it;
4696         it->wd->bring_in = EINA_TRUE;
4697         it->showme = EINA_TRUE;
4698         return;
4699      }
4700    if (it->wd->show_item)
4701      {
4702         it->wd->show_item->showme = EINA_FALSE;
4703         it->wd->show_item = NULL;
4704      }
4705    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4706    elm_smart_scroller_region_bring_in(it->wd->scr,
4707                                       it->x + it->block->x,
4708                                       it->y + it->block->y - oh / 2 + it->h / 2,
4709                                       it->block->w, oh);
4710 }
4711
4712 EAPI void
4713 elm_genlist_item_del(Elm_Genlist_Item *it)
4714 {
4715    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4716    if ((it->relcount > 0) || (it->walking > 0))
4717      {
4718         elm_widget_item_pre_notify_del(it);
4719         elm_genlist_item_subitems_clear(it);
4720         it->delete_me = EINA_TRUE;
4721         if (it->wd->show_item == it) it->wd->show_item = NULL;
4722         if (it->selected)
4723           it->wd->selected = eina_list_remove(it->wd->selected,
4724                                               it);
4725         if (it->block)
4726           {
4727              if (it->realized) _item_unrealize(it, EINA_FALSE);
4728              it->block->changed = EINA_TRUE;
4729              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
4730              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
4731           }
4732         if (it->itc->func.del)
4733           it->itc->func.del((void *)it->base.data, WIDGET(it));
4734         return;
4735      }
4736    _item_del(it);
4737 }
4738
4739 EAPI void
4740 elm_genlist_item_data_set(Elm_Genlist_Item *it,
4741                           const void       *data)
4742 {
4743    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4744    elm_widget_item_data_set(it, data);
4745 }
4746
4747 EAPI void *
4748 elm_genlist_item_data_get(const Elm_Genlist_Item *it)
4749 {
4750    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4751    return elm_widget_item_data_get(it);
4752 }
4753
4754 EAPI void
4755 elm_genlist_item_icons_orphan(Elm_Genlist_Item *it)
4756 {
4757    Evas_Object *icon;
4758    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4759    EINA_LIST_FREE(it->icon_objs, icon)
4760      {
4761         elm_widget_sub_object_del(WIDGET(it), icon);
4762         evas_object_smart_member_del(icon);
4763         evas_object_hide(icon);
4764      }
4765 }
4766
4767 EAPI const Evas_Object *
4768 elm_genlist_item_object_get(const Elm_Genlist_Item *it)
4769 {
4770    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4771    return VIEW(it);
4772 }
4773
4774 EAPI void
4775 elm_genlist_item_update(Elm_Genlist_Item *it)
4776 {
4777    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4778    if (!it->block) return;
4779    if (it->delete_me) return;
4780    it->mincalcd = EINA_FALSE;
4781    it->updateme = EINA_TRUE;
4782    it->block->updateme = EINA_TRUE;
4783    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4784    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4785    it->defer_unrealize = EINA_FALSE;
4786 }
4787
4788 EAPI void
4789 elm_genlist_item_fields_update(Elm_Genlist_Item *it,
4790                                const char *parts,
4791                                Elm_Genlist_Item_Field_Flags itf)
4792 {
4793    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4794    if (!it->block) return;
4795    if (it->delete_me) return;
4796
4797    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4798      _item_label_realize(it, VIEW(it), &it->labels, parts);
4799    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_ICON))
4800      {
4801         it->icon_objs = _item_icon_unrealize(it, VIEW(it),
4802                                              &it->icons, parts);
4803         it->icon_objs = _item_icon_realize(it, VIEW(it),
4804                                            &it->icons, parts);
4805
4806         if (it->renamed)
4807           {
4808              it->icon_objs = _item_mode_icon_unrealize(it, VIEW(it),
4809                                                        &it->icons, parts, &it->icon_objs);
4810              it->icon_objs = _item_mode_icon_realize(it, VIEW(it),
4811                                                      &it->icons, parts, &it->icon_objs, "renames");
4812           }
4813
4814         if (it->mode_view)
4815           {
4816              it->mode_icon_objs = _item_mode_icon_unrealize(it, it->mode_view,
4817                                                             &it->mode_icons, parts, &it->mode_icon_objs);
4818              it->mode_icon_objs = _item_mode_icon_realize(it, it->mode_view,
4819                                                           &it->mode_icons, parts, &it->mode_icon_objs, "icons");
4820           }
4821
4822         if (it->wd->edit_mode)
4823           {
4824              it->edit_icon_objs = _item_mode_icon_unrealize(it, it->edit_obj,
4825                                                             &it->icons, parts, &it->edit_icon_objs);
4826              it->edit_icon_objs = _item_mode_icon_realize(it, it->edit_obj,
4827                                                      &it->icons, parts, &it->edit_icon_objs, "edit_icons");
4828           }
4829      }
4830    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4831      _item_state_realize(it, VIEW(it), &it->states, parts);
4832 }
4833
4834 EAPI void
4835 elm_genlist_item_item_class_update(Elm_Genlist_Item             *it,
4836                                    const Elm_Genlist_Item_Class *itc)
4837 {
4838    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4839    if (!it->block) return;
4840    EINA_SAFETY_ON_NULL_RETURN(itc);
4841    if (it->delete_me) return;
4842    it->itc = itc;
4843    it->nocache = EINA_TRUE;
4844    elm_genlist_item_update(it);
4845 }
4846
4847 EAPI const Elm_Genlist_Item_Class *
4848 elm_genlist_item_item_class_get(const Elm_Genlist_Item *it)
4849 {
4850    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4851    if (it->delete_me) return NULL;
4852    return it->itc;
4853 }
4854 static Evas_Object *
4855 _elm_genlist_item_label_create(void        *data,
4856                                Evas_Object *obj __UNUSED__,
4857                                Evas_Object *tooltip,
4858                                void        *item __UNUSED__)
4859 {
4860    Evas_Object *label = elm_label_add(tooltip);
4861    if (!label)
4862      return NULL;
4863    elm_object_style_set(label, "tooltip");
4864    elm_object_text_set(label, data);
4865    return label;
4866 }
4867
4868 static void
4869 _elm_genlist_item_label_del_cb(void        *data,
4870                                Evas_Object *obj __UNUSED__,
4871                                void        *event_info __UNUSED__)
4872 {
4873    eina_stringshare_del(data);
4874 }
4875
4876 EAPI void
4877 elm_genlist_item_tooltip_text_set(Elm_Genlist_Item *item,
4878                                   const char       *text)
4879 {
4880    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4881    text = eina_stringshare_add(text);
4882    elm_genlist_item_tooltip_content_cb_set(item, _elm_genlist_item_label_create,
4883                                            text,
4884                                            _elm_genlist_item_label_del_cb);
4885 }
4886
4887 EAPI void
4888 elm_genlist_item_tooltip_content_cb_set(Elm_Genlist_Item           *item,
4889                                         Elm_Tooltip_Item_Content_Cb func,
4890                                         const void                 *data,
4891                                         Evas_Smart_Cb               del_cb)
4892 {
4893    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
4894
4895    if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
4896      return;
4897
4898    if (item->tooltip.del_cb)
4899      item->tooltip.del_cb((void *)item->tooltip.data,
4900                           item->base.widget, item);
4901
4902    item->tooltip.content_cb = func;
4903    item->tooltip.data = data;
4904    item->tooltip.del_cb = del_cb;
4905
4906    if (VIEW(item))
4907      {
4908         elm_widget_item_tooltip_content_cb_set(item,
4909                                                item->tooltip.content_cb,
4910                                                item->tooltip.data, NULL);
4911         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
4912      }
4913
4914    return;
4915
4916 error:
4917    if (del_cb) del_cb((void *)data, NULL, NULL);
4918 }
4919
4920 EAPI void
4921 elm_genlist_item_tooltip_unset(Elm_Genlist_Item *item)
4922 {
4923    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4924    if ((item->base.view) && (item->tooltip.content_cb))
4925      elm_widget_item_tooltip_unset(item);
4926
4927    if (item->tooltip.del_cb)
4928      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
4929    item->tooltip.del_cb = NULL;
4930    item->tooltip.content_cb = NULL;
4931    item->tooltip.data = NULL;
4932    if (item->tooltip.style)
4933      elm_genlist_item_tooltip_style_set(item, NULL);
4934 }
4935
4936 EAPI void
4937 elm_genlist_item_tooltip_style_set(Elm_Genlist_Item *item,
4938                                    const char       *style)
4939 {
4940    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4941    eina_stringshare_replace(&item->tooltip.style, style);
4942    if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
4943 }
4944
4945 EAPI const char *
4946 elm_genlist_item_tooltip_style_get(const Elm_Genlist_Item *item)
4947 {
4948    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
4949    return item->tooltip.style;
4950 }
4951
4952 EAPI Eina_Bool
4953 elm_genlist_item_tooltip_size_restrict_disable(Elm_Genlist_Item *item, Eina_Bool disable)
4954 {
4955    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
4956    return elm_widget_item_tooltip_size_restrict_disable(item, disable);
4957 }
4958
4959 EAPI Eina_Bool
4960 elm_genlist_item_tooltip_size_restrict_disabled_get(const Elm_Genlist_Item *item)
4961 {
4962    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
4963    return elm_widget_item_tooltip_size_restrict_disabled_get(item);
4964 }
4965
4966 EAPI void
4967 elm_genlist_item_cursor_set(Elm_Genlist_Item *item,
4968                             const char       *cursor)
4969 {
4970    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4971    eina_stringshare_replace(&item->mouse_cursor, cursor);
4972    if (item->base.view) elm_widget_item_cursor_set(item, cursor);
4973 }
4974
4975 EAPI const char *
4976 elm_genlist_item_cursor_get(const Elm_Genlist_Item *item)
4977 {
4978    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
4979    return elm_widget_item_cursor_get(item);
4980 }
4981
4982 EAPI void
4983 elm_genlist_item_cursor_unset(Elm_Genlist_Item *item)
4984 {
4985    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4986    if (!item->mouse_cursor)
4987      return;
4988
4989    if (VIEW(item))
4990      elm_widget_item_cursor_unset(item);
4991
4992    eina_stringshare_del(item->mouse_cursor);
4993    item->mouse_cursor = NULL;
4994 }
4995
4996 EAPI void
4997 elm_genlist_item_cursor_style_set(Elm_Genlist_Item *item,
4998                                   const char       *style)
4999 {
5000    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5001    elm_widget_item_cursor_style_set(item, style);
5002 }
5003
5004 EAPI const char *
5005 elm_genlist_item_cursor_style_get(const Elm_Genlist_Item *item)
5006 {
5007    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
5008    return elm_widget_item_cursor_style_get(item);
5009 }
5010
5011 EAPI void
5012 elm_genlist_item_cursor_engine_only_set(Elm_Genlist_Item *item,
5013                                         Eina_Bool         engine_only)
5014 {
5015    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5016    elm_widget_item_cursor_engine_only_set(item, engine_only);
5017 }
5018
5019 EAPI Eina_Bool
5020 elm_genlist_item_cursor_engine_only_get(const Elm_Genlist_Item *item)
5021 {
5022    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5023    return elm_widget_item_cursor_engine_only_get(item);
5024 }
5025
5026 EAPI void
5027 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
5028                                 Elm_List_Mode mode)
5029 {
5030    ELM_CHECK_WIDTYPE(obj, widtype);
5031    Widget_Data *wd = elm_widget_data_get(obj);
5032    if (!wd) return;
5033    if (wd->mode == mode) return;
5034    wd->mode = mode;
5035    _sizing_eval(obj);
5036 }
5037
5038 EAPI Elm_List_Mode
5039 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
5040 {
5041    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5042    Widget_Data *wd = elm_widget_data_get(obj);
5043    if (!wd) return ELM_LIST_LAST;
5044    return wd->mode;
5045 }
5046
5047 EAPI void
5048 elm_genlist_always_select_mode_set(Evas_Object *obj,
5049                                    Eina_Bool    always_select)
5050 {
5051    ELM_CHECK_WIDTYPE(obj, widtype);
5052    Widget_Data *wd = elm_widget_data_get(obj);
5053    if (!wd) return;
5054    wd->always_select = always_select;
5055 }
5056
5057 EAPI Eina_Bool
5058 elm_genlist_always_select_mode_get(const Evas_Object *obj)
5059 {
5060    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5061    Widget_Data *wd = elm_widget_data_get(obj);
5062    if (!wd) return EINA_FALSE;
5063    return wd->always_select;
5064 }
5065
5066 EAPI void
5067 elm_genlist_no_select_mode_set(Evas_Object *obj,
5068                                Eina_Bool    no_select)
5069 {
5070    ELM_CHECK_WIDTYPE(obj, widtype);
5071    Widget_Data *wd = elm_widget_data_get(obj);
5072    if (!wd) return;
5073    wd->no_select = no_select;
5074 }
5075
5076 EAPI Eina_Bool
5077 elm_genlist_no_select_mode_get(const Evas_Object *obj)
5078 {
5079    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5080    Widget_Data *wd = elm_widget_data_get(obj);
5081    if (!wd) return EINA_FALSE;
5082    return wd->no_select;
5083 }
5084
5085 EAPI void
5086 elm_genlist_compress_mode_set(Evas_Object *obj,
5087                               Eina_Bool    compress)
5088 {
5089    ELM_CHECK_WIDTYPE(obj, widtype);
5090    Widget_Data *wd = elm_widget_data_get(obj);
5091    if (!wd) return;
5092    wd->compress = compress;
5093 }
5094
5095 EAPI Eina_Bool
5096 elm_genlist_compress_mode_get(const Evas_Object *obj)
5097 {
5098    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5099    Widget_Data *wd = elm_widget_data_get(obj);
5100    if (!wd) return EINA_FALSE;
5101    return wd->compress;
5102 }
5103
5104 EAPI void
5105 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5106                                       Eina_Bool    height_for_width)
5107 {
5108    ELM_CHECK_WIDTYPE(obj, widtype);
5109    Widget_Data *wd = elm_widget_data_get(obj);
5110    if (!wd) return;
5111    wd->height_for_width = !!height_for_width;
5112    if (wd->height_for_width)
5113      {
5114         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5115         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5116      }
5117 }
5118
5119 EAPI Eina_Bool
5120 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5121 {
5122    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5123    Widget_Data *wd = elm_widget_data_get(obj);
5124    if (!wd) return EINA_FALSE;
5125    return wd->height_for_width;
5126 }
5127
5128 EAPI void
5129 elm_genlist_bounce_set(Evas_Object *obj,
5130                        Eina_Bool    h_bounce,
5131                        Eina_Bool    v_bounce)
5132 {
5133    ELM_CHECK_WIDTYPE(obj, widtype);
5134    Widget_Data *wd = elm_widget_data_get(obj);
5135    if (!wd) return;
5136    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
5137 }
5138
5139 EAPI void
5140 elm_genlist_bounce_get(const Evas_Object *obj,
5141                        Eina_Bool         *h_bounce,
5142                        Eina_Bool         *v_bounce)
5143 {
5144    ELM_CHECK_WIDTYPE(obj, widtype);
5145    Widget_Data *wd = elm_widget_data_get(obj);
5146    if (!wd) return;
5147    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
5148 }
5149
5150 EAPI void
5151 elm_genlist_homogeneous_set(Evas_Object *obj,
5152                             Eina_Bool    homogeneous)
5153 {
5154    ELM_CHECK_WIDTYPE(obj, widtype);
5155    Widget_Data *wd = elm_widget_data_get(obj);
5156    if (!wd) return;
5157    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5158    wd->homogeneous = homogeneous;
5159 }
5160
5161 EAPI Eina_Bool
5162 elm_genlist_homogeneous_get(const Evas_Object *obj)
5163 {
5164    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5165    Widget_Data *wd = elm_widget_data_get(obj);
5166    if (!wd) return EINA_FALSE;
5167    return wd->homogeneous;
5168 }
5169
5170 EAPI void
5171 elm_genlist_block_count_set(Evas_Object *obj,
5172                             int          n)
5173 {
5174    ELM_CHECK_WIDTYPE(obj, widtype);
5175    Widget_Data *wd = elm_widget_data_get(obj);
5176    if (!wd) return;
5177    wd->max_items_per_block = n;
5178    wd->item_cache_max = wd->max_items_per_block * 2;
5179    _item_cache_clean(wd);
5180 }
5181
5182 EAPI int
5183 elm_genlist_block_count_get(const Evas_Object *obj)
5184 {
5185    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5186    Widget_Data *wd = elm_widget_data_get(obj);
5187    if (!wd) return 0;
5188    return wd->max_items_per_block;
5189 }
5190
5191 EAPI void
5192 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5193                                   double       timeout)
5194 {
5195    ELM_CHECK_WIDTYPE(obj, widtype);
5196    Widget_Data *wd = elm_widget_data_get(obj);
5197    if (!wd) return;
5198    wd->longpress_timeout = timeout;
5199 }
5200
5201 EAPI double
5202 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5203 {
5204    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5205    Widget_Data *wd = elm_widget_data_get(obj);
5206    if (!wd) return 0;
5207    return wd->longpress_timeout;
5208 }
5209
5210 EAPI void
5211 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5212                                 Elm_Scroller_Policy policy_h,
5213                                 Elm_Scroller_Policy policy_v)
5214 {
5215    ELM_CHECK_WIDTYPE(obj, widtype);
5216    Widget_Data *wd = elm_widget_data_get(obj);
5217    if ((!wd) || (!wd->scr)) return;
5218    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5219        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5220      return;
5221    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5222 }
5223
5224 EAPI void
5225 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5226                                 Elm_Scroller_Policy *policy_h,
5227                                 Elm_Scroller_Policy *policy_v)
5228 {
5229    ELM_CHECK_WIDTYPE(obj, widtype);
5230    Widget_Data *wd = elm_widget_data_get(obj);
5231    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5232    if ((!wd) || (!wd->scr)) return;
5233    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5234    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5235    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5236 }
5237
5238 EAPI void
5239 elm_genlist_realized_items_update(Evas_Object *obj)
5240 {
5241    ELM_CHECK_WIDTYPE(obj, widtype);
5242
5243    Eina_List *list, *l;
5244    Elm_Genlist_Item *it;
5245
5246    list = elm_genlist_realized_items_get(obj);
5247    EINA_LIST_FOREACH(list, l, it)
5248      elm_genlist_item_update(it);
5249 }
5250
5251 EAPI void
5252 elm_genlist_item_mode_set(Elm_Genlist_Item *it,
5253                           const char       *mode_type,
5254                           Eina_Bool         mode_set)
5255 {
5256    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
5257    Widget_Data *wd = it->wd;
5258    Eina_List *l;
5259    Elm_Genlist_Item *it2;
5260
5261    if (!wd) return;
5262    if (!mode_type) return;
5263    if ((it->delete_me) || (it->disabled)) return;
5264    if (wd->edit_mode) return;
5265
5266    if ((wd->mode_item == it) &&
5267        (!strcmp(mode_type, wd->mode_type)) &&
5268        (mode_set))
5269       return;
5270    if (!it->itc->mode_item_style) return;
5271
5272    if (wd->multi)
5273      {
5274         EINA_LIST_FOREACH(wd->selected, l, it2)
5275           if (it2->realized)
5276             elm_genlist_item_selected_set(it2, EINA_FALSE);
5277      }
5278    else
5279      {
5280         it2 = elm_genlist_selected_item_get(wd->obj);
5281         if ((it2) && (it2->realized))
5282           elm_genlist_item_selected_set(it2, EINA_FALSE);
5283      }
5284
5285    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5286        (mode_set) ||
5287        ((it == wd->mode_item) && (!mode_set)))
5288      _item_mode_unset(wd);
5289
5290    eina_stringshare_replace(&wd->mode_type, mode_type);
5291    if (mode_set) _item_mode_set(it);
5292 }
5293
5294 EAPI const char *
5295 elm_genlist_mode_item_style_get(const Evas_Object *obj)
5296 {
5297    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5298    Widget_Data *wd = elm_widget_data_get(obj);
5299    if (!wd) return NULL;
5300    return wd->mode_item->itc->mode_item_style;
5301 }
5302
5303 EAPI void
5304 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
5305 {
5306    ELM_CHECK_WIDTYPE(obj, widtype);
5307    Widget_Data *wd = elm_widget_data_get(obj);
5308    if (!wd) return;
5309    if ((style == wd->mode_item->itc->mode_item_style) ||
5310        (style && wd->mode_item->itc->mode_item_style &&
5311        (!strcmp(style, wd->mode_item->itc->mode_item_style))))
5312      return;
5313    eina_stringshare_replace(&wd->mode_item->itc->mode_item_style, style);
5314    elm_genlist_realized_items_update(obj);
5315 }
5316
5317 EAPI const char *
5318 elm_genlist_mode_get(const Evas_Object *obj)
5319 {
5320    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5321    Widget_Data *wd = elm_widget_data_get(obj);
5322    if (!wd) return NULL;
5323    return wd->mode_type;
5324 }
5325
5326 EAPI const Elm_Genlist_Item *
5327 elm_genlist_mode_item_get(const Evas_Object *obj)
5328 {
5329    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5330    Widget_Data *wd = elm_widget_data_get(obj);
5331    if (!wd) return NULL;
5332    return wd->mode_item;
5333 }
5334
5335 EAPI void
5336 elm_genlist_reorder_mode_set(Evas_Object *obj,
5337                              Eina_Bool    reorder_mode)
5338 {
5339    ELM_CHECK_WIDTYPE(obj, widtype);
5340    Widget_Data *wd = elm_widget_data_get(obj);
5341    if (!wd) return;
5342    wd->reorder_mode = reorder_mode;
5343 }
5344
5345 EAPI Eina_Bool
5346 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5347 {
5348    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5349    Widget_Data *wd = elm_widget_data_get(obj);
5350    if (!wd) return EINA_FALSE;
5351    return wd->reorder_mode;
5352 }
5353
5354 EAPI void
5355 elm_genlist_item_move_after(Elm_Genlist_Item *it __UNUSED__, Elm_Genlist_Item *after __UNUSED__)
5356 {
5357    return;
5358 }
5359
5360 EAPI void
5361 elm_genlist_item_move_before(Elm_Genlist_Item *it __UNUSED__, Elm_Genlist_Item *before __UNUSED__)
5362 {
5363    return;
5364 }
5365
5366 EAPI void
5367 elm_genlist_effect_set(const Evas_Object *obj, Eina_Bool emode)
5368 {
5369    ELM_CHECK_WIDTYPE(obj, widtype);
5370    Widget_Data *wd = elm_widget_data_get(obj);
5371    if (!wd) return;
5372    wd->effect_mode = emode;
5373    //   wd->point_rect = evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5374    //   evas_object_resize(wd->point_rect, 10, 25);
5375    //   evas_object_color_set(wd->point_rect, 255, 0, 0, 130);
5376    //   evas_object_show(wd->point_rect);
5377    //   evas_object_hide(wd->point_rect);
5378 }
5379
5380 static Evas_Object*
5381 _create_tray_alpha_bg(const Evas_Object *obj)
5382 {
5383    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5384    Widget_Data *wd = elm_widget_data_get(obj);
5385    if (!wd) return NULL;
5386
5387    Evas_Object *bg = NULL;
5388    Evas_Coord ox, oy, ow, oh;
5389
5390    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5391    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5392    evas_object_color_set(bg,0,0,0,0);
5393    evas_object_resize(bg , ow, oh);
5394    evas_object_move(bg , ox, oy);
5395    evas_object_show(bg);
5396    evas_object_hide(bg);
5397    return bg ;
5398 }
5399
5400 static unsigned int
5401 current_time_get()
5402 {
5403    struct timeval timev;
5404
5405    gettimeofday(&timev, NULL);
5406    return ((timev.tv_sec * 1000) + ((timev.tv_usec) / 1000));
5407 }
5408
5409 // added for item moving animation.
5410 static Eina_Bool
5411 _item_moving_effect_timer_cb(void *data)
5412 {
5413    Widget_Data *wd = data;
5414    if (!wd) return EINA_FALSE;
5415    Item_Block *itb;
5416    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
5417    Elm_Genlist_Item *it = NULL, *it2;
5418    const Eina_List *l;
5419    double time = 0.5, t;
5420    int y, dy;
5421    Eina_Bool check, end = EINA_FALSE, vis = EINA_TRUE;
5422    int in = 0;
5423
5424    t = ((0.0 > (t = current_time_get() - wd->start_time)) ? 0.0 : t) / 1000;
5425
5426    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5427    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
5428    if (t > time) end = EINA_TRUE;
5429
5430    // Below while statement is needed, when the genlist is resized.
5431    it2 = wd->expand_item;
5432    while (it2 && vis)
5433      {
5434         evas_object_move(VIEW(it2), it2->scrl_x, it2->scrl_y);
5435         vis = (ELM_RECTS_INTERSECT(it2->scrl_x, it2->scrl_y, it2->w, it2->h,
5436                                    cvx, cvy, cvw, cvh));
5437         it2 = elm_genlist_item_prev_get(it2);
5438      }
5439    it2 = elm_genlist_item_next_get(wd->expand_item);
5440    while (it2)
5441      {
5442         if (wd->expand_item->expanded_depth >= it2->expanded_depth) break;
5443         it2 = elm_genlist_item_next_get(it2);
5444      }
5445    dy = 0;
5446    if (it2)
5447      {
5448         if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5449           dy = ((it2->scrl_y > cvy + cvh) ? cvy + cvh : it2->scrl_y) - it2->old_scrl_y;
5450         else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5451           dy = wd->expand_item_gap;
5452
5453         if (t <= time)
5454           {
5455              y = ((1 - (1 - (t / time)) * (1 - (t /time))) * dy);
5456           }
5457         else
5458           {
5459              end = EINA_TRUE;
5460              y = dy;
5461           }
5462
5463         check = EINA_FALSE;
5464         EINA_INLIST_FOREACH(wd->blocks, itb)
5465           {
5466              itb->w = wd->minw;
5467              if (ELM_RECTS_INTERSECT(itb->x - wd->pan_x + ox,
5468                                      itb->y - wd->pan_y + oy,
5469                                      itb->w, itb->h,
5470                                      cvx, cvy, cvw, cvh))
5471                {
5472                   EINA_LIST_FOREACH(itb->items, l, it)
5473                     {
5474                        if (it == it2) check = EINA_TRUE;
5475                        if (!check) continue;
5476
5477                        if (!it->old_scrl_y)
5478                          it->old_scrl_y  = it->scrl_y;
5479                        if (it->old_scrl_y + y < oy + oh)
5480                          {
5481                             if (!it->realized) _item_realize(it, in, 0);
5482                          }
5483                        if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE && it->old_scrl_y + y < it->scrl_y)
5484                          it->old_scrl_y = it->scrl_y - y;
5485                        in++;
5486
5487                        if (wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE ||
5488                            (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE && it->old_scrl_y + y >= it->scrl_y))
5489                          {
5490                             if (wd->edit_mode) _effect_item_controls(it, it->scrl_x, it->old_scrl_y + y);
5491                             else
5492                               {
5493                                  evas_object_resize(VIEW(it), it->w, it->h);
5494                                  evas_object_move(VIEW(it), it->scrl_x, it->old_scrl_y + y);
5495                                  evas_object_show(VIEW(it));
5496                                  evas_object_raise(VIEW(it));
5497                               }
5498
5499                             if (it->group_item) evas_object_raise(it->group_item->base.view);
5500                          }
5501                     }
5502                }
5503           }
5504
5505         if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5506           {
5507              it = elm_genlist_item_prev_get(it2);
5508              while (it)
5509                {
5510                   if (it->expanded_depth <= it2->expanded_depth) break;
5511                   if ((it->scrl_y < it2->old_scrl_y + y) && (it->expanded_depth > it2->expanded_depth))
5512                     {
5513                        if (!it->effect_done)
5514                          {
5515                             edje_object_signal_emit(VIEW(it), "flip_item", "");
5516                             evas_object_show(VIEW(it));
5517                             it->effect_done = EINA_TRUE;
5518                          }
5519                     }
5520                   it = elm_genlist_item_prev_get(it);
5521                }
5522           }
5523         else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5524           {
5525              it = elm_genlist_item_prev_get(it2);
5526              while (it)
5527                {
5528                   if ((it->scrl_y > it2->old_scrl_y + y) && (it->expanded_depth > it2->expanded_depth))
5529                     {
5530                        if (!it->effect_done)
5531                          {
5532                             edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
5533                             it->effect_done = EINA_TRUE;
5534                          }
5535                     }
5536                   else
5537                     break;
5538                   it = elm_genlist_item_prev_get(it);
5539                }
5540           }
5541      }
5542    else
5543      {
5544         int expand_num = 0;
5545         int expand_order = 0;
5546         if (wd->expand_item) it = elm_genlist_item_next_get(wd->expand_item);
5547         while (it)
5548           {
5549              expand_num++;
5550              it = elm_genlist_item_next_get(it);
5551           }
5552         if (wd->expand_item) it = elm_genlist_item_next_get(wd->expand_item);
5553         while (it)
5554           {
5555              expand_order++;
5556              if (wd->expand_item->expanded_depth >= it->expanded_depth) break;
5557              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5558                {
5559                   if (!it->effect_done)
5560                     {
5561                        if (t >= (((expand_order - 1) * time) / expand_num))
5562                          {
5563                             edje_object_signal_emit(VIEW(it), "flip_item", "");
5564                             evas_object_show(VIEW(it));
5565                             it->effect_done = EINA_TRUE;
5566                          }
5567                     }
5568                }
5569              it = elm_genlist_item_next_get(it);
5570           }
5571      }
5572
5573    if (end)
5574      {
5575         if (wd->item_moving_effect_timer)
5576           {
5577              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5578                 _item_subitems_clear(wd->expand_item);
5579              EINA_INLIST_FOREACH(wd->blocks, itb)
5580                {
5581                   EINA_LIST_FOREACH(itb->items, l, it)
5582                     {
5583                        it->effect_done = EINA_TRUE;
5584                        it->old_scrl_y = it->scrl_y;
5585                     }
5586                }
5587           }
5588         wd->item_moving_effect_timer = NULL;
5589
5590         _item_auto_scroll(wd);
5591         evas_object_lower(wd->alpha_bg);
5592         evas_object_hide(wd->alpha_bg);
5593         elm_smart_scroller_bounce_animator_disabled_set(wd->scr, EINA_FALSE);
5594         wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_NONE;
5595
5596         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
5597         evas_object_smart_callback_call(wd->obj, "effect_done", NULL);
5598         evas_object_smart_changed(wd->pan_smart);
5599         return ECORE_CALLBACK_CANCEL;
5600      }
5601    return ECORE_CALLBACK_RENEW;
5602 }
5603
5604 static void
5605 _emit_contract(Elm_Genlist_Item *it)
5606 {
5607    Elm_Genlist_Item *it2;
5608    Eina_List *l;
5609
5610    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
5611    it->effect_done = EINA_FALSE;
5612
5613    EINA_LIST_FOREACH(it->items, l, it2)
5614       if (it2)
5615          _emit_contract(it2);
5616 }
5617
5618 // added for item moving animation.
5619 static int
5620 _item_flip_effect_show(Elm_Genlist_Item *it)
5621 {
5622    Elm_Genlist_Item *it2;
5623    Eina_List *l;
5624    Widget_Data *wd = it->wd;
5625
5626    EINA_LIST_FOREACH(it->items, l, it2)
5627      {
5628         if (it2->parent && it == it2->parent)
5629           {
5630              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5631                edje_object_signal_emit(it2->base.view, "elm,state,hide", "");
5632              else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5633                _emit_contract(it2);
5634           }
5635      }
5636
5637    return ECORE_CALLBACK_CANCEL;
5638 }
5639
5640 /*
5641 static void
5642 _elm_genlist_pinch_zoom_execute(Evas_Object *obj, Eina_Bool emode)
5643 {
5644    printf("!!! NOW FIXING \n");
5645 }
5646 */
5647
5648 /**
5649  * Set pinch zoom mode
5650  *
5651  * @param obj The genlist object
5652  * @param emode
5653  * (EINA_TRUE = pinch contract (zoom in), EINA_FALSE = pinch expand (zoom out)
5654  *
5655  * @ingroup Genlist
5656  */
5657 EAPI void
5658 elm_genlist_pinch_zoom_mode_set(Evas_Object *obj __UNUSED__, Eina_Bool emode __UNUSED__)
5659 {
5660    printf("!!! NOW FIXING \n");
5661 }
5662
5663 /**
5664  * Get pinch zoom mode
5665  *
5666  * @param obj The genlist object
5667  * @return The pinch mode
5668  * (EINA_TRUE = pinch contract (zoom in), EINA_FALSE = pinch expand (zoom out)
5669  *
5670  * @ingroup Genlist
5671  */
5672 EAPI Eina_Bool
5673 elm_genlist_pinch_zoom_mode_get(const Evas_Object *obj __UNUSED__)
5674 {
5675    printf("!!! NOW FIXING \n");
5676    return EINA_FALSE;
5677 }
5678
5679 EAPI void
5680 elm_genlist_pinch_zoom_set(Evas_Object *obj __UNUSED__, Eina_Bool emode __UNUSED__)
5681 {
5682    printf("!!! NOW FIXING \n");
5683 }
5684
5685
5686 ////////////////////////////////////////////////////////////////////////
5687 //  EDIT  MODE
5688 ////////////////////////////////////////////////////////////////////////
5689
5690 static void
5691 _effect_item_controls(Elm_Genlist_Item *it, int itx, int ity)
5692 {
5693    if (!it->wd->edit_mode) return;
5694    evas_object_resize(it->edit_obj,it->w, it->h);
5695    evas_object_move(it->edit_obj, itx, ity);
5696 }
5697
5698 static void
5699 _effect_item_realize(Elm_Genlist_Item *it, Eina_Bool effect_on)
5700 {
5701    if ((it->effect_item_realized) || (it->delete_me)) return;
5702    char buf[1024];
5703
5704    if (it->mode_view)
5705      _mode_finished_signal_cb(it, (Evas_Object *)elm_genlist_item_object_get(it), NULL, NULL);
5706
5707    it->edit_obj = edje_object_add(evas_object_evas_get(WIDGET(it)));
5708    edje_object_scale_set(it->edit_obj, elm_widget_scale_get(WIDGET(it)) *
5709                          _elm_config->scale);
5710    evas_object_smart_member_add(it->edit_obj, it->wd->pan_smart);
5711    elm_widget_sub_object_add(WIDGET(it), it->edit_obj);
5712
5713    if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) strncpy(buf, "tree", sizeof(buf));
5714    else strncpy(buf, "item", sizeof(buf));
5715    if (it->wd->compress) strncat(buf, "_compress", sizeof(buf) - strlen(buf));
5716
5717    strncat(buf, "/", sizeof(buf) - strlen(buf));
5718
5719    if (it->itc->edit_item_style && strcmp(it->itc->edit_item_style, "default"))
5720      {
5721         strncat(buf, it->itc->edit_item_style, sizeof(buf) - strlen(buf));
5722         _elm_theme_object_set(WIDGET(it), it->edit_obj, "genlist", buf, elm_widget_style_get(WIDGET(it)));
5723      }
5724    else
5725      {
5726         _elm_theme_object_set(WIDGET(it), it->edit_obj, "genlist", "item/edit_default", elm_widget_style_get(WIDGET(it)));
5727      }
5728
5729    if (it->wd->reorder_mode)
5730      {
5731         if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,reorder_enabled_effect", "elm");
5732         else edje_object_signal_emit(it->edit_obj, "elm,state,reorder_enabled", "elm");
5733      }
5734    if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,emode_enabled_effect", "elm");
5735    else edje_object_signal_emit(it->edit_obj, "elm,state,emode_enabled", "elm");
5736
5737    if (it->disabled) edje_object_signal_emit(it->edit_obj, "elm,state,disabled", "elm");
5738    else edje_object_signal_emit(it->edit_obj, "elm,state,enabled", "elm");
5739
5740
5741    if ((it->wd->edit_mode))
5742      {
5743         if (it->itc->func.icon_get)
5744           {
5745              const Eina_List *l;
5746              const char *key;
5747
5748              if (it->renamed) edje_object_signal_emit(it->edit_obj, "elm,state,rename,enabled", "elm");
5749              it->icons = elm_widget_stringlist_get(edje_object_data_get(it->edit_obj, "edit_icons"));
5750              EINA_LIST_FOREACH(it->icons, l, key)
5751                {
5752                   Evas_Object *ic = it->itc->func.icon_get
5753                      ((void *)it->base.data, WIDGET(it), l->data);
5754
5755                   if (ic)
5756                     {
5757                        it->edit_icon_objs = eina_list_append(it->edit_icon_objs, ic);
5758                        edje_object_part_swallow(it->edit_obj, key, ic);
5759                        evas_object_show(ic);
5760                        elm_widget_sub_object_add(WIDGET(it), ic);
5761                        if (it->disabled)
5762                          elm_widget_disabled_set(ic, EINA_TRUE);
5763                     }
5764                }
5765           }
5766      }
5767    edje_object_part_swallow(it->edit_obj, "original_edc", VIEW(it));
5768    _effect_item_controls(it,it->scrl_x, it->scrl_y);
5769    evas_object_show(it->edit_obj);
5770
5771    it->effect_item_realized = EINA_TRUE;
5772    it->want_unrealize = EINA_FALSE;
5773 }
5774
5775 static void
5776 _effect_item_unrealize(Elm_Genlist_Item *it)
5777 {
5778    Evas_Object *icon;
5779
5780    if (!it->effect_item_realized) return;
5781    if (it->wd->reorder_it && it->wd->reorder_it == it) return;
5782
5783    edje_object_signal_emit(it->edit_obj, "elm,state,reorder_disable_effect", "elm");
5784    edje_object_signal_emit(it->edit_obj, "elm,state,sel,disable", "elm");
5785    edje_object_message_signal_process(it->edit_obj);
5786    edje_object_part_unswallow(it->edit_obj, VIEW(it));
5787    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
5788    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
5789    //   evas_object_smart_callback_call(it->edit_obj, "unrealized", it);
5790    //   _item_cache_add(it);
5791    evas_object_del(it->edit_obj);
5792    it->edit_obj = NULL;
5793    EINA_LIST_FREE(it->edit_icon_objs, icon)
5794       evas_object_del(icon);
5795
5796 //   edje_object_signal_emit(it->edit_obj, "elm,state,edit_end,disable", "elm");
5797    it->effect_item_realized = EINA_FALSE;
5798 }
5799
5800 /**
5801  * Get Genlist edit mode
5802  *
5803  * @param obj The genlist object
5804  * @return The edit mode status
5805  * (EINA_TRUE = edit mode, EINA_FALSE = normal mode
5806  *
5807  * @ingroup Genlist
5808  */
5809 EAPI Eina_Bool
5810 elm_genlist_edit_mode_get(const Evas_Object *obj)
5811 {
5812    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5813    Widget_Data *wd = elm_widget_data_get(obj);
5814    if (!wd) return EINA_FALSE;
5815
5816    if (wd->edit_mode) return EINA_TRUE;
5817    else return EINA_FALSE;
5818 }
5819
5820 /**
5821  * Set Genlist edit mode
5822  *
5823  * This sets Genlist edit mode.
5824  *
5825  * @param obj The Genlist object
5826  * @param emode ELM_GENLIST_EDIT_MODE_{NONE & REORDER & INSERT & DELETE & SELECT & SELECT_ALL}
5827  * @param edit_class Genlist edit class (Elm_Genlist_Edit_Class structure)
5828  *
5829  * @ingroup Genlist
5830  */
5831 EAPI void
5832 elm_genlist_edit_mode_set(Evas_Object *obj, Eina_Bool edit_mode)
5833 {
5834    ELM_CHECK_WIDTYPE(obj, widtype);
5835
5836    Item_Block *itb;
5837    Eina_List *l;
5838    Elm_Genlist_Item *it;
5839
5840    Widget_Data *wd = elm_widget_data_get(obj);
5841    if (!wd) return;
5842    if (wd->edit_mode == edit_mode) return;
5843
5844    wd->edit_mode = edit_mode;
5845    if (!wd->edit_mode)
5846      {
5847         EINA_INLIST_FOREACH(wd->blocks, itb)
5848           {
5849              if (itb->realized)
5850                {
5851                   EINA_LIST_FOREACH(itb->items, l, it)
5852                     {
5853                        if (it->flags != ELM_GENLIST_ITEM_GROUP && it->realized)
5854                          {
5855                             _effect_item_unrealize(it);
5856                          }
5857                     }
5858                }
5859           }
5860         _item_cache_zero(wd);
5861      }
5862    else
5863      {
5864
5865         EINA_INLIST_FOREACH(wd->blocks, itb)
5866           {
5867              if (itb->realized)
5868                {
5869                   EINA_LIST_FOREACH(itb->items, l, it)
5870                     {
5871                        if (it->flags != ELM_GENLIST_ITEM_GROUP && it->realized)
5872                          {
5873                             if(it->selected) _item_unselect(it);
5874                             if (it->itc->edit_item_style) _effect_item_realize(it, EINA_TRUE);
5875                          }
5876                     }
5877                 }
5878            }
5879       }
5880
5881    if (wd->calc_job) ecore_job_del(wd->calc_job);
5882    wd->calc_job = ecore_job_add(_calc_job, wd);
5883 }
5884
5885 /**
5886  * Set a given item's rename mode
5887  *
5888  * This renames the item's label from genlist
5889  *
5890  * @param it The item
5891  * @param renamed set if emode is EINA_TRUE, unset if emode is EINA_FALSE
5892  *
5893  * @ingroup Genlist
5894  */
5895 EAPI void
5896 elm_genlist_item_rename_mode_set(Elm_Genlist_Item *it, Eina_Bool renamed)
5897 {
5898    if (!it) return;
5899
5900    if (renamed)
5901      {
5902         _item_unrealize(it, EINA_FALSE);
5903         it->renamed = EINA_TRUE;
5904         it->wd->rename_it = it;
5905         it->nocache = EINA_TRUE;
5906         if (it->selected)  _item_unselect(it);
5907
5908         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5909         it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
5910      }
5911    else
5912      {
5913         if (it->renamed)
5914           {
5915              it->renamed = EINA_FALSE;
5916              it->nocache = EINA_TRUE;
5917              it->wd->rename_it = NULL;
5918              _item_cache_zero(it->wd);
5919              elm_genlist_item_update(it);
5920           }
5921      }
5922 }
5923
5924 EAPI Eina_Bool
5925 elm_genlist_item_rename_mode_get(Elm_Genlist_Item *item)
5926 {
5927    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5928    return item->renamed;
5929 }
5930
5931 EAPI void
5932 elm_genlist_item_no_select_mode_set(Elm_Genlist_Item *it,
5933                                     Eina_Bool    no_select)
5934 {
5935    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
5936    it->no_select = no_select;
5937 }
5938
5939 EAPI Eina_Bool
5940 elm_genlist_item_no_select_mode_get(const Elm_Genlist_Item *it)
5941 {
5942    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
5943    return it->no_select;
5944 }