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