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