Merge "[Copy&Paste popup] popup is hidden by only caller entry"
[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->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
858    if (it->realized) _item_unrealize(it, EINA_FALSE);
859    if (it->effect_item_realized) _effect_item_unrealize(it);
860    if (it->block) _item_block_del(it);
861    if ((!it->delete_me) && (it->itc->func.del))
862      it->itc->func.del((void *)it->base.data, WIDGET(it));
863    it->delete_me = EINA_TRUE;
864    if (it->queued)
865      it->wd->queue = eina_list_remove(it->wd->queue, it);
866 #ifdef ANCHOR_ITEM
867    if (it->wd->anchor_item == it)
868      {
869         it->wd->anchor_item = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
870         if (!it->wd->anchor_item)
871           it->wd->anchor_item = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
872      }
873 #endif
874    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
875    if (it->parent)
876      it->parent->items = eina_list_remove(it->parent->items, it);
877    if (it->flags & ELM_GENLIST_ITEM_GROUP)
878      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
879    if (it->long_timer) ecore_timer_del(it->long_timer);
880    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
881
882    if (it->tooltip.del_cb)
883      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
884
885    evas_event_thaw(evas_object_evas_get(tob));
886    evas_event_thaw_eval(evas_object_evas_get(tob));
887
888    elm_widget_item_del(it);
889 }
890
891 static void
892 _item_select(Elm_Genlist_Item *it)
893 {
894    Eina_List *l;
895    Evas_Object *obj;
896    Evas_Object *parent = WIDGET(it);
897
898    if ((it->wd->no_select) || (it->no_select) ||
899        (it->delete_me) || (it->mode_view)) return;
900    if (it->selected)
901      {
902         if (it->wd->always_select) goto call;
903         return;
904      }
905    it->selected = EINA_TRUE;
906    it->wd->selected = eina_list_append(it->wd->selected, it);
907 call:
908    evas_object_ref(parent);
909    it->walking++;
910    it->wd->walking++;
911    if (it->wd->last_selected_item && (it != it->wd->last_selected_item))
912      {
913         EINA_LIST_FOREACH(it->wd->last_selected_item->icon_objs, l, obj)
914           {
915              elm_widget_focused_object_clear(obj);
916              elm_widget_tree_unfocusable_set(obj, EINA_TRUE);
917           }
918         it->wd->last_selected_item->can_focus = EINA_FALSE;
919      }
920    if (it->func.func) it->func.func((void *)it->func.data, parent, it);
921    if (!it->delete_me)
922      evas_object_smart_callback_call(parent, SIG_SELECTED, it);
923    it->walking--;
924    it->wd->walking--;
925    if ((it->wd->clear_me) && (!it->wd->walking))
926      {
927         elm_genlist_clear(parent);
928         goto end;
929      }
930    else
931      {
932         if ((!it->walking) && (it->delete_me))
933           {
934              if (!it->relcount) _item_del(it);
935              goto end;
936           }
937      }
938    if (it && it->wd) it->wd->last_selected_item = it; // TODO: Remove 'if'?
939 end:
940    evas_object_unref(parent);
941 }
942
943 static void
944 _item_unselect(Elm_Genlist_Item *it)
945 {
946    const char *stacking, *selectraise;
947
948    if ((it->delete_me) || ((!it->highlighted) && (!it->selected))) return;
949    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
950    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,unselected", "elm");
951    stacking = edje_object_data_get(VIEW(it), "stacking");
952    selectraise = edje_object_data_get(VIEW(it), "selectraise");
953    if ((selectraise) && (!strcmp(selectraise, "on")))
954      {
955         if ((stacking) && (!strcmp(stacking, "below")))
956           evas_object_lower(VIEW(it));
957      }
958    it->highlighted = EINA_FALSE;
959    if (it->selected)
960      {
961         it->selected = EINA_FALSE;
962         it->wd->selected = eina_list_remove(it->wd->selected, it);
963         evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
964      }
965 }
966
967 static void
968 _mouse_move(void        *data,
969             Evas        *evas __UNUSED__,
970             Evas_Object *obj,
971             void        *event_info)
972 {
973    Elm_Genlist_Item *it = data;
974    Evas_Event_Mouse_Move *ev = event_info;
975    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
976    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
977
978    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
979      {
980         if (!it->wd->on_hold)
981           {
982              it->wd->on_hold = EINA_TRUE;
983              if ((!it->wd->wasselected) && (!it->renamed))
984                _item_unselect(it);
985           }
986      }
987    if (it->wd->multitouched)
988      {
989         it->wd->cur_x = ev->cur.canvas.x;
990         it->wd->cur_y = ev->cur.canvas.y;
991         return;
992      }
993    if ((it->dragging) && (it->down))
994      {
995         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
996         else
997           {
998              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
999              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
1000              if (abs((it->wd->history[it->wd->movements].x -
1001                       it->wd->history[0].x)) > 40)
1002                it->wd->swipe = EINA_TRUE;
1003              else
1004                it->wd->movements++;
1005           }
1006         if (it->long_timer)
1007           {
1008              ecore_timer_del(it->long_timer);
1009              it->long_timer = NULL;
1010           }
1011         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
1012         return;
1013      }
1014    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
1015      {
1016         if (it->long_timer)
1017           {
1018              ecore_timer_del(it->long_timer);
1019              it->long_timer = NULL;
1020           }
1021         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1022           {
1023              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
1024              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
1025
1026              if (!it->wd->reorder_start_y)
1027                it->wd->reorder_start_y = it->block->y + it->y;
1028
1029              if (it_scrl_y < oy)
1030                y_pos = oy;
1031              else if (it_scrl_y + it->wd->reorder_it->h > oy + oh)
1032                y_pos = oy + oh - it->wd->reorder_it->h;
1033              else
1034                y_pos = it_scrl_y;
1035
1036              if (it->edit_obj)
1037                _item_position(it, it->edit_obj, it->scrl_x, y_pos);
1038              else
1039                _item_position(it, VIEW(it), it->scrl_x, y_pos);
1040
1041              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1042              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1043           }
1044         return;
1045      }
1046    if (!it->display_only)
1047      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1048    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1049    x = ev->cur.canvas.x - x;
1050    y = ev->cur.canvas.y - y;
1051    dx = x - it->dx;
1052    adx = dx;
1053    if (adx < 0) adx = -dx;
1054    dy = y - it->dy;
1055    ady = dy;
1056    if (ady < 0) ady = -dy;
1057    minw /= 2;
1058    minh /= 2;
1059    if ((adx > minw) || (ady > minh))
1060      {
1061         it->dragging = EINA_TRUE;
1062         if (it->long_timer)
1063           {
1064              ecore_timer_del(it->long_timer);
1065              it->long_timer = NULL;
1066           }
1067         if ((!it->wd->wasselected) && (!it->renamed))
1068           _item_unselect(it);
1069         if (dy < 0)
1070           {
1071              if ((ady > adx) && (!it->wd->drag_started))
1072                evas_object_smart_callback_call(WIDGET(it),
1073                                                SIG_DRAG_START_UP, it);
1074              else
1075                {
1076                   if (dx < 0)
1077                     evas_object_smart_callback_call(WIDGET(it),
1078                                                     SIG_DRAG_START_LEFT, it);
1079                   else
1080                     evas_object_smart_callback_call(WIDGET(it),
1081                                                     SIG_DRAG_START_RIGHT, it);
1082                }
1083           }
1084         else
1085           {
1086              if ((ady > adx) && (!it->wd->drag_started))
1087                evas_object_smart_callback_call(WIDGET(it),
1088                                                SIG_DRAG_START_DOWN, it);
1089              else
1090                {
1091                   if (dx < 0)
1092                     evas_object_smart_callback_call(WIDGET(it),
1093                                                     SIG_DRAG_START_LEFT, it);
1094                   else
1095                     evas_object_smart_callback_call(WIDGET(it),
1096                                                     SIG_DRAG_START_RIGHT, it);
1097                }
1098           }
1099      }
1100 }
1101
1102 static Eina_Bool
1103 _long_press(void *data)
1104 {
1105    Elm_Genlist_Item *it = data, *it_tmp;
1106    Eina_List *list, *l;
1107
1108    it->long_timer = NULL;
1109    if ((it->disabled) || (it->dragging) || (it->display_only) || (it->wd->rename_it))
1110      return ECORE_CALLBACK_CANCEL;
1111    it->wd->longpressed = EINA_TRUE;
1112    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1113    if ((it->wd->reorder_mode) && (it->flags != ELM_GENLIST_ITEM_GROUP))
1114      {
1115         it->wd->reorder_it = it;
1116         it->wd->reorder_start_y = 0;
1117         if (it->edit_obj)
1118           evas_object_raise(it->edit_obj);
1119         else
1120           evas_object_raise(VIEW(it));
1121
1122         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1123         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1124
1125         list = elm_genlist_realized_items_get(it->wd->obj);
1126         EINA_LIST_FOREACH(list, l, it_tmp)
1127           {
1128              if (it != it_tmp) _item_unselect(it_tmp);
1129           }
1130         if (it->items)
1131           {
1132              EINA_LIST_FOREACH(it->items, l, it_tmp)
1133                {
1134                   if (elm_genlist_item_expanded_get(it_tmp))
1135                     {
1136                        elm_genlist_item_expanded_set(it_tmp, EINA_FALSE);
1137                        return ECORE_CALLBACK_RENEW;
1138                     }
1139                }
1140           }
1141         if (elm_genlist_item_expanded_get(it))
1142           {
1143              elm_genlist_item_expanded_set(it, EINA_FALSE);
1144              return ECORE_CALLBACK_RENEW;
1145           }
1146         if (it->edit_obj)
1147           edje_object_signal_emit(it->edit_obj, "elm,action,item,reorder_start", "elm");
1148         else
1149           edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1150      }
1151    return ECORE_CALLBACK_CANCEL;
1152 }
1153
1154 static void
1155 _swipe(Elm_Genlist_Item *it)
1156 {
1157    int i, sum = 0;
1158
1159    if (!it) return;
1160    if ((it->display_only) || (it->disabled)) return;
1161    it->wd->swipe = EINA_FALSE;
1162    for (i = 0; i < it->wd->movements; i++)
1163      {
1164         sum += it->wd->history[i].x;
1165         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1166      }
1167
1168    sum /= it->wd->movements;
1169    if (abs(sum - it->wd->history[0].x) <= 10) return;
1170    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1171 }
1172
1173 static Eina_Bool
1174 _swipe_cancel(void *data)
1175 {
1176    Elm_Genlist_Item *it = data;
1177
1178    if (!it) return ECORE_CALLBACK_CANCEL;
1179    it->wd->swipe = EINA_FALSE;
1180    it->wd->movements = 0;
1181    return ECORE_CALLBACK_RENEW;
1182 }
1183
1184 static Eina_Bool
1185 _multi_cancel(void *data)
1186 {
1187    Widget_Data *wd = data;
1188
1189    if (!wd) return ECORE_CALLBACK_CANCEL;
1190    wd->multi_timeout = EINA_TRUE;
1191    return ECORE_CALLBACK_RENEW;
1192 }
1193
1194 static void
1195 _multi_touch_gesture_eval(void *data)
1196 {
1197    Elm_Genlist_Item *it = data;
1198
1199    it->wd->multitouched = EINA_FALSE;
1200    if (it->wd->multi_timer)
1201      {
1202         ecore_timer_del(it->wd->multi_timer);
1203         it->wd->multi_timer = NULL;
1204      }
1205    if (it->wd->multi_timeout)
1206      {
1207         it->wd->multi_timeout = EINA_FALSE;
1208         return;
1209      }
1210
1211    Evas_Coord minw = 0, minh = 0;
1212    Evas_Coord off_x, off_y, off_mx, off_my;
1213
1214    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1215    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1216    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1217    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1218    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1219
1220    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1221      {
1222         if ((off_x + off_mx) > (off_y + off_my))
1223           {
1224              if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1225                evas_object_smart_callback_call(WIDGET(it),
1226                                                SIG_MULTI_SWIPE_RIGHT, it);
1227              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1228                evas_object_smart_callback_call(WIDGET(it),
1229                                                SIG_MULTI_SWIPE_LEFT, it);
1230              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1231                evas_object_smart_callback_call(WIDGET(it),
1232                                                SIG_MULTI_PINCH_OUT, it);
1233              else
1234                evas_object_smart_callback_call(WIDGET(it),
1235                                                SIG_MULTI_PINCH_IN, it);
1236           }
1237         else
1238           {
1239              if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1240                evas_object_smart_callback_call(WIDGET(it),
1241                                                SIG_MULTI_SWIPE_DOWN, it);
1242              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1243                evas_object_smart_callback_call(WIDGET(it),
1244                                                SIG_MULTI_SWIPE_UP, it);
1245              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1246                evas_object_smart_callback_call(WIDGET(it),
1247                                                SIG_MULTI_PINCH_OUT, it);
1248              else
1249                evas_object_smart_callback_call(WIDGET(it),
1250                                                SIG_MULTI_PINCH_IN, it);
1251           }
1252      }
1253    it->wd->multi_timeout = EINA_FALSE;
1254 }
1255
1256 static void
1257 _multi_down(void        *data,
1258             Evas        *evas __UNUSED__,
1259             Evas_Object *obj __UNUSED__,
1260             void        *event_info)
1261 {
1262    Elm_Genlist_Item *it = data;
1263    Evas_Event_Multi_Down *ev = event_info;
1264
1265    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1266    it->wd->multi_device = ev->device;
1267    it->wd->multi_down = EINA_TRUE;
1268    it->wd->multitouched = EINA_TRUE;
1269    it->wd->prev_mx = ev->canvas.x;
1270    it->wd->prev_my = ev->canvas.y;
1271    if (!it->wd->wasselected) _item_unselect(it);
1272    it->wd->wasselected = EINA_FALSE;
1273    it->wd->longpressed = EINA_FALSE;
1274    if (it->long_timer)
1275      {
1276         ecore_timer_del(it->long_timer);
1277         it->long_timer = NULL;
1278      }
1279    if (it->dragging)
1280      {
1281         it->dragging = EINA_FALSE;
1282         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1283      }
1284    if (it->swipe_timer)
1285      {
1286         ecore_timer_del(it->swipe_timer);
1287         it->swipe_timer = NULL;
1288      }
1289    if (it->wd->on_hold)
1290      {
1291         it->wd->swipe = EINA_FALSE;
1292         it->wd->movements = 0;
1293         it->wd->on_hold = EINA_FALSE;
1294      }
1295 }
1296
1297 static void
1298 _multi_up(void        *data,
1299           Evas        *evas __UNUSED__,
1300           Evas_Object *obj __UNUSED__,
1301           void        *event_info)
1302 {
1303    Elm_Genlist_Item *it = data;
1304    Evas_Event_Multi_Up *ev = event_info;
1305
1306    if (it->wd->multi_device != ev->device) return;
1307    it->wd->multi_device = 0;
1308    it->wd->multi_down = EINA_FALSE;
1309    if (it->wd->mouse_down) return;
1310    _multi_touch_gesture_eval(data);
1311 }
1312
1313 static void
1314 _multi_move(void        *data,
1315             Evas        *evas __UNUSED__,
1316             Evas_Object *obj __UNUSED__,
1317             void        *event_info)
1318 {
1319    Elm_Genlist_Item *it = data;
1320    Evas_Event_Multi_Move *ev = event_info;
1321
1322    if (it->wd->multi_device != ev->device) return;
1323    it->wd->cur_mx = ev->cur.canvas.x;
1324    it->wd->cur_my = ev->cur.canvas.y;
1325 }
1326
1327 static void
1328 _mouse_down(void        *data,
1329             Evas        *evas __UNUSED__,
1330             Evas_Object *obj,
1331             void        *event_info)
1332 {
1333    Elm_Genlist_Item *it = data;
1334    Evas_Event_Mouse_Down *ev = event_info;
1335    Evas_Coord x, y;
1336    Eina_List *l;
1337    Evas_Object *iobj;
1338
1339    if (ev->button != 1) return;
1340    if (!it->can_focus)
1341      {
1342         EINA_LIST_FOREACH(it->icon_objs, l, iobj)
1343           {
1344              elm_widget_tree_unfocusable_set(iobj, EINA_FALSE);
1345           }
1346         it->can_focus = EINA_TRUE;
1347      }
1348    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1349      {
1350         it->wd->on_hold = EINA_TRUE;
1351      }
1352    it->down = EINA_TRUE;
1353    it->dragging = EINA_FALSE;
1354    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1355    it->dx = ev->canvas.x - x;
1356    it->dy = ev->canvas.y - y;
1357    it->wd->mouse_down = EINA_TRUE;
1358    if (!it->wd->multitouched)
1359      {
1360         it->wd->prev_x = ev->canvas.x;
1361         it->wd->prev_y = ev->canvas.y;
1362         it->wd->multi_timeout = EINA_FALSE;
1363         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1364         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1365      }
1366    it->wd->longpressed = EINA_FALSE;
1367    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1368    else it->wd->on_hold = EINA_FALSE;
1369    if (it->wd->on_hold) return;
1370    it->wd->wasselected = it->selected;
1371    _item_highlight(it);
1372    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1373      if ((!it->disabled) && (!it->display_only))
1374        {
1375           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1376           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1377        }
1378    if (it->long_timer) ecore_timer_del(it->long_timer);
1379    if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
1380    it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1381    if (it->realized)
1382      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1383                                       it);
1384    else
1385      it->long_timer = NULL;
1386    it->wd->swipe = EINA_FALSE;
1387    it->wd->movements = 0;
1388 }
1389
1390 static void
1391 _mouse_up(void        *data,
1392           Evas        *evas __UNUSED__,
1393           Evas_Object *obj __UNUSED__,
1394           void        *event_info)
1395 {
1396    Elm_Genlist_Item *it = data;
1397    Evas_Event_Mouse_Up *ev = event_info;
1398    Eina_Bool dragged = EINA_FALSE;
1399
1400    if (ev->button != 1) return;
1401    it->down = EINA_FALSE;
1402    it->wd->mouse_down = EINA_FALSE;
1403    if (it->wd->multitouched)
1404      {
1405         // in single selection modes, some multi touching can make multi highlighted items.
1406         // if a item not selected and highlighted, it should be unhighlighted.
1407         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unselect(it);
1408         if (it->wd->multi_down) return;
1409         _multi_touch_gesture_eval(data);
1410         return;
1411      }
1412    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1413    else it->wd->on_hold = EINA_FALSE;
1414    if (it->long_timer)
1415      {
1416         ecore_timer_del(it->long_timer);
1417         it->long_timer = NULL;
1418      }
1419    if (it->dragging)
1420      {
1421         it->dragging = EINA_FALSE;
1422         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1423         dragged = 1;
1424      }
1425    if (it->swipe_timer)
1426      {
1427         ecore_timer_del(it->swipe_timer);
1428         it->swipe_timer = NULL;
1429      }
1430    if (it->wd->multi_timer)
1431      {
1432         ecore_timer_del(it->wd->multi_timer);
1433         it->wd->multi_timer = NULL;
1434         it->wd->multi_timeout = EINA_FALSE;
1435      }
1436    if (it->wd->on_hold)
1437      {
1438         if (it->wd->swipe) _swipe(data);
1439         it->wd->longpressed = EINA_FALSE;
1440         it->wd->on_hold = EINA_FALSE;
1441         return;
1442      }
1443    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1444      {
1445         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1446
1447         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1448           {
1449              if (it_scrl_y <= it->wd->reorder_rel->scrl_y)
1450                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1451              else
1452                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1453           }
1454         else
1455           {
1456              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1457              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1458           }
1459         it->wd->reorder_deleted = EINA_FALSE;
1460         edje_object_signal_emit(it->edit_obj, "elm,action,item,reorder_end", "elm");
1461         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1462         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1463         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_TRUE);
1464
1465      }
1466    if (it->wd->longpressed)
1467      {
1468         it->wd->longpressed = EINA_FALSE;
1469         if ((!it->wd->wasselected) && (!it->renamed))
1470           _item_unselect(it);
1471         it->wd->wasselected = EINA_FALSE;
1472         return;
1473      }
1474    if (dragged)
1475      {
1476         if (it->want_unrealize)
1477           {
1478              _item_unrealize(it, EINA_FALSE);
1479              if (it->block->want_unrealize)
1480                _item_block_unrealize(it->block);
1481           }
1482      }
1483    if ((it->disabled) || (dragged) || (it->display_only)) return;
1484    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1485    if (it->wd->multi)
1486      {
1487         if (!it->selected)
1488           {
1489              _item_highlight(it);
1490              _item_select(it);
1491           }
1492         else _item_unselect(it);
1493      }
1494    else
1495      {
1496         if (!it->selected)
1497           {
1498              Widget_Data *wd = it->wd;
1499              if (wd)
1500                {
1501                   while (wd->selected) _item_unselect(wd->selected->data);
1502                }
1503           }
1504         else
1505           {
1506              const Eina_List *l, *l_next;
1507              Elm_Genlist_Item *it2;
1508
1509              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1510                if (it2 != it) _item_unselect(it2);
1511              //_item_highlight(it);
1512              //_item_select(it);
1513           }
1514         _item_highlight(it);
1515         _item_select(it);
1516      }
1517 }
1518
1519 static void
1520 _mouse_down_scroller(void        *data,
1521                      Evas        *evas __UNUSED__,
1522                      Evas_Object *obj __UNUSED__,
1523                      void        *event_info __UNUSED__)
1524 {
1525    Widget_Data *wd = elm_widget_data_get(data);
1526
1527    if (!wd) return;
1528    wd->drag_started = EINA_FALSE;
1529 }
1530
1531 static void
1532 _mouse_up_scroller(void        *data,
1533                    Evas        *evas __UNUSED__,
1534                    Evas_Object *obj __UNUSED__,
1535                    void        *event_info __UNUSED__)
1536 {
1537    Widget_Data *wd = elm_widget_data_get(data);
1538
1539    if (!wd) return;
1540    wd->drag_started = EINA_FALSE;
1541 }
1542
1543 static void
1544 _mouse_move_scroller(void        *data,
1545                      Evas        *evas __UNUSED__,
1546                      Evas_Object *obj __UNUSED__,
1547                      void        *event_info)
1548 {
1549    Widget_Data *wd = elm_widget_data_get(data);
1550    Evas_Event_Mouse_Move *ev = event_info;
1551    Evas_Coord minw = 0, minh = 0, dx, dy, adx, ady;
1552
1553    if (!wd) return;
1554    if (wd->drag_started) return;
1555
1556    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1557    dx = ev->cur.canvas.x - ev->prev.canvas.x;
1558    dy = ev->cur.canvas.y - ev->prev.canvas.y;
1559    adx = dx;
1560    ady = dy;
1561    if (adx < 0) adx = -dx;
1562    if (ady < 0) ady = -dy;
1563    if (((ady < minh) && (ady > minh / 2)) && (ady > adx))
1564      {
1565         if (dy < 0)
1566           {
1567              evas_object_smart_callback_call(data, SIG_DRAG_START_UP, NULL);
1568              wd->drag_started = EINA_TRUE;
1569           }
1570         else
1571           {
1572              evas_object_smart_callback_call(data, SIG_DRAG_START_DOWN, NULL);
1573              wd->drag_started = EINA_TRUE;
1574           }
1575      }
1576 }
1577
1578 static void
1579 _signal_expand_toggle(void        *data,
1580                       Evas_Object *obj __UNUSED__,
1581                       const char  *emission __UNUSED__,
1582                       const char  *source __UNUSED__)
1583 {
1584    Elm_Genlist_Item *it = data;
1585
1586    if (it->expanded)
1587      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1588    else
1589      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1590 }
1591
1592 static void
1593 _signal_expand(void        *data,
1594                Evas_Object *obj __UNUSED__,
1595                const char  *emission __UNUSED__,
1596                const char  *source __UNUSED__)
1597 {
1598    Elm_Genlist_Item *it = data;
1599
1600    if (!it->expanded)
1601      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1602 }
1603
1604 static void
1605 _signal_contract(void        *data,
1606                  Evas_Object *obj __UNUSED__,
1607                  const char  *emission __UNUSED__,
1608                  const char  *source __UNUSED__)
1609 {
1610    Elm_Genlist_Item *it = data;
1611
1612    if (it->expanded)
1613      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1614 }
1615
1616 static Eina_Bool
1617 _scr_hold_timer_cb(void *data)
1618 {
1619    if (!data) return ECORE_CALLBACK_CANCEL;
1620    Widget_Data *wd = data;
1621    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1622    wd->scr_hold_timer = NULL;
1623    return ECORE_CALLBACK_CANCEL;
1624 }
1625
1626 static void
1627 _mode_finished_signal_cb(void        *data,
1628                          Evas_Object *obj,
1629                          const char  *emission __UNUSED__,
1630                          const char  *source __UNUSED__)
1631 {
1632    if (!data) return;
1633    if (!obj) return;
1634    Elm_Genlist_Item *it = data;
1635    if ((it->delete_me) || (!it->realized) || (!it->mode_view)) return;
1636    char buf[1024];
1637    Evas *te = evas_object_evas_get(obj);
1638
1639    evas_event_freeze(te);
1640    it->nocache = EINA_FALSE;
1641    _mode_item_unrealize(it);
1642    if (it->group_item)
1643      evas_object_raise(it->VIEW(group_item));
1644    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type);
1645    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1646    evas_event_thaw(te);
1647    evas_event_thaw_eval(te);
1648 }
1649
1650 static void
1651 _item_cache_clean(Widget_Data *wd)
1652 {
1653    evas_event_freeze(evas_object_evas_get(wd->obj));
1654    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1655      {
1656         Item_Cache *itc;
1657
1658         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1659         wd->item_cache = eina_inlist_remove(wd->item_cache,
1660                                             wd->item_cache->last);
1661         wd->item_cache_count--;
1662         if (itc->spacer) evas_object_del(itc->spacer);
1663         if (itc->base_view) evas_object_del(itc->base_view);
1664         if (itc->item_style) eina_stringshare_del(itc->item_style);
1665         free(itc);
1666      }
1667    evas_event_thaw(evas_object_evas_get(wd->obj));
1668    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1669 }
1670
1671 static void
1672 _item_cache_zero(Widget_Data *wd)
1673 {
1674    int pmax = wd->item_cache_max;
1675    wd->item_cache_max = 0;
1676    _item_cache_clean(wd);
1677    wd->item_cache_max = pmax;
1678 }
1679
1680 static void
1681 _item_cache_add(Elm_Genlist_Item *it)
1682 {
1683    Item_Cache *itc;
1684
1685    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1686    if (it->wd->item_cache_max <= 0)
1687      {
1688         evas_object_del(VIEW(it));
1689         VIEW(it) = NULL;
1690         evas_object_del(it->spacer);
1691         it->spacer = NULL;
1692         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1693         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1694         return;
1695      }
1696
1697    it->wd->item_cache_count++;
1698    itc = calloc(1, sizeof(Item_Cache));
1699    if (!itc)
1700      {
1701         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1702         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1703         return;
1704      }
1705    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1706                                             EINA_INLIST_GET(itc));
1707    itc->spacer = it->spacer;
1708    it->spacer = NULL;
1709    itc->base_view = VIEW(it);
1710    VIEW(it) = NULL;
1711    evas_object_hide(itc->base_view);
1712    evas_object_move(itc->base_view, -9999, -9999);
1713    itc->item_style = eina_stringshare_add(it->itc->item_style);
1714    if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) itc->tree = 1;
1715    itc->compress = (it->wd->compress);
1716    itc->odd = (it->order_num_in & 0x1);
1717    itc->selected = it->selected;
1718    itc->disabled = it->disabled;
1719    itc->expanded = it->expanded;
1720    if (it->long_timer)
1721      {
1722         ecore_timer_del(it->long_timer);
1723         it->long_timer = NULL;
1724      }
1725    if (it->swipe_timer)
1726      {
1727         ecore_timer_del(it->swipe_timer);
1728         it->swipe_timer = NULL;
1729      }
1730    // FIXME: other callbacks?
1731    edje_object_signal_callback_del_full(itc->base_view,
1732                                         "elm,action,expand,toggle",
1733                                         "elm", _signal_expand_toggle, it);
1734    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1735                                         "elm",
1736                                         _signal_expand, it);
1737    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1738                                         "elm", _signal_contract, it);
1739    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
1740                                        _mouse_down, it);
1741    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
1742                                        _mouse_up, it);
1743    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
1744                                        _mouse_move, it);
1745    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
1746                                        _multi_down, it);
1747    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
1748                                        _multi_up, it);
1749    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
1750                                        _multi_move, it);
1751    _item_cache_clean(it->wd);
1752    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1753    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1754 }
1755
1756 static Item_Cache *
1757 _item_cache_find(Elm_Genlist_Item *it)
1758 {
1759    Item_Cache *itc;
1760    Eina_Bool tree = 0, odd;
1761
1762    if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) tree = 1;
1763    odd = (it->order_num_in & 0x1);
1764    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1765      {
1766         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1767           continue;
1768         if ((itc->tree == tree) &&
1769             (itc->odd == odd) &&
1770             (itc->compress == it->wd->compress) &&
1771             (!strcmp(it->itc->item_style, itc->item_style)))
1772           {
1773              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1774                                                      EINA_INLIST_GET(itc));
1775              it->wd->item_cache_count--;
1776              return itc;
1777           }
1778      }
1779    return NULL;
1780 }
1781
1782 static void
1783 _item_cache_free(Item_Cache *itc)
1784 {
1785    if (itc->spacer) evas_object_del(itc->spacer);
1786    if (itc->base_view) evas_object_del(itc->base_view);
1787    if (itc->item_style) eina_stringshare_del(itc->item_style);
1788    free(itc);
1789 }
1790
1791 static const char *
1792 _item_label_hook(Elm_Genlist_Item *it, const char *part)
1793 {
1794    if (!it->itc->func.label_get) return NULL;
1795    return edje_object_part_text_get(VIEW(it), part);
1796 }
1797
1798 static void
1799 _icon_focused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1800 {
1801    Elm_Genlist_Item *it = data;
1802    if (it) it->defer_unrealize = EINA_TRUE;
1803 }
1804
1805 static void
1806 _icon_unfocused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1807 {
1808    Elm_Genlist_Item *it = data;
1809    if (it) it->defer_unrealize = EINA_FALSE;
1810 }
1811
1812 static void
1813 _item_del_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1814 {
1815    Elm_Genlist_Item *it = event_info;
1816    if (!it) return;
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    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
3980                                     func_data);
3981    if (!it) return NULL;
3982    if (!it->parent)
3983      {
3984         if (flags & ELM_GENLIST_ITEM_GROUP)
3985           wd->group_items = eina_list_append(wd->group_items, it);
3986         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3987         it->rel = NULL;
3988      }
3989    else
3990      {
3991         Elm_Genlist_Item *it2 = NULL;
3992         Eina_List *ll = eina_list_last(it->parent->items);
3993         if (ll) it2 = ll->data;
3994         it->parent->items = eina_list_append(it->parent->items, it);
3995         if (!it2) it2 = it->parent;
3996         if (it2->delete_me)
3997            it2 = elm_genlist_item_prev_get(it2);
3998         wd->items =
3999           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4000                                       EINA_INLIST_GET(it2));
4001         it->rel = it2;
4002         it->rel->relcount++;
4003      }
4004    it->before = EINA_FALSE;
4005    _item_queue(wd, it);
4006    return it;
4007 }
4008
4009 EAPI Elm_Genlist_Item *
4010 elm_genlist_item_prepend(Evas_Object                  *obj,
4011                          const Elm_Genlist_Item_Class *itc,
4012                          const void                   *data,
4013                          Elm_Genlist_Item             *parent,
4014                          Elm_Genlist_Item_Flags        flags,
4015                          Evas_Smart_Cb                 func,
4016                          const void                   *func_data)
4017 {
4018    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4019    Widget_Data *wd = elm_widget_data_get(obj);
4020    if (!wd) return NULL;
4021    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
4022                                     func_data);
4023
4024    if (!it) return NULL;
4025    if (!it->parent)
4026      {
4027         if (flags & ELM_GENLIST_ITEM_GROUP)
4028           wd->group_items = eina_list_prepend(wd->group_items, it);
4029         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4030         it->rel = NULL;
4031      }
4032    else
4033      {
4034         Elm_Genlist_Item *it2 = NULL;
4035         Eina_List *ll = it->parent->items;
4036         if (ll) it2 = ll->data;
4037         it->parent->items = eina_list_prepend(it->parent->items, it);
4038         if (!it2) it2 = it->parent;
4039         if (it2->delete_me)
4040            it2 = elm_genlist_item_next_get(it2);
4041         wd->items =
4042           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4043                                        EINA_INLIST_GET(it2));
4044         it->rel = it2;
4045         it->rel->relcount++;
4046      }
4047    it->before = EINA_TRUE;
4048    _item_queue(wd, it);
4049    return it;
4050 }
4051
4052 EAPI Elm_Genlist_Item *
4053 elm_genlist_item_insert_after(Evas_Object                  *obj,
4054                               const Elm_Genlist_Item_Class *itc,
4055                               const void                   *data,
4056                               Elm_Genlist_Item             *parent,
4057                               Elm_Genlist_Item             *after,
4058                               Elm_Genlist_Item_Flags        flags,
4059                               Evas_Smart_Cb                 func,
4060                               const void                   *func_data)
4061 {
4062    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4063    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
4064    Widget_Data *wd = elm_widget_data_get(obj);
4065    if (!wd) return NULL;
4066    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4067    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
4068                                     func_data);
4069    if (!it) return NULL;
4070
4071    if (!it->parent)
4072      {
4073         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
4074             (after->flags & ELM_GENLIST_ITEM_GROUP))
4075           wd->group_items = eina_list_append_relative(wd->group_items, it,
4076                                                       after);
4077      }
4078    else
4079      {
4080         it->parent->items = eina_list_append_relative(it->parent->items, it,
4081                                                       after);
4082      }
4083    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4084                                            EINA_INLIST_GET(after));
4085    it->rel = after;
4086    it->rel->relcount++;
4087    it->before = EINA_FALSE;
4088    _item_queue(wd, it);
4089    return it;
4090 }
4091
4092 EAPI Elm_Genlist_Item *
4093 elm_genlist_item_insert_before(Evas_Object                  *obj,
4094                                const Elm_Genlist_Item_Class *itc,
4095                                const void                   *data,
4096                                Elm_Genlist_Item             *parent,
4097                                Elm_Genlist_Item             *before,
4098                                Elm_Genlist_Item_Flags        flags,
4099                                Evas_Smart_Cb                 func,
4100                                const void                   *func_data)
4101 {
4102    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4103    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
4104    Widget_Data *wd = elm_widget_data_get(obj);
4105    if (!wd) return NULL;
4106    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4107    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func,
4108                                     func_data);
4109    if (!it) return NULL;
4110
4111    if (!it->parent)
4112      {
4113         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
4114             (before->flags & ELM_GENLIST_ITEM_GROUP))
4115           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4116                                                        before);
4117      }
4118    else
4119      {
4120         it->parent->items = eina_list_prepend_relative(it->parent->items, it,
4121                                                        before);
4122      }
4123    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4124                                             EINA_INLIST_GET(before));
4125    it->rel = before;
4126    it->rel->relcount++;
4127    it->before = EINA_TRUE;
4128    _item_queue(wd, it);
4129    return it;
4130 }
4131
4132 EAPI void
4133 elm_genlist_clear(Evas_Object *obj)
4134 {
4135    ELM_CHECK_WIDTYPE(obj, widtype);
4136    Widget_Data *wd = elm_widget_data_get(obj);
4137    if (!wd) return;
4138    if (wd->walking > 0)
4139      {
4140         Elm_Genlist_Item *it;
4141
4142         wd->clear_me = EINA_TRUE;
4143         EINA_INLIST_FOREACH(wd->items, it)
4144           {
4145              it->delete_me = EINA_TRUE;
4146           }
4147         return;
4148      }
4149    evas_event_freeze(evas_object_evas_get(wd->obj));
4150    while (wd->items)
4151      {
4152         Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
4153         it->nocache = EINA_TRUE;
4154         it->highlighted = EINA_FALSE;
4155 #ifdef ANCHOR_ITEM
4156         if (wd->anchor_item == it)
4157           {
4158              wd->anchor_item = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4159              if (!wd->anchor_item)
4160                wd->anchor_item =
4161                  ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4162           }
4163 #endif
4164         wd->items = eina_inlist_remove(wd->items, wd->items);
4165         if (it->flags & ELM_GENLIST_ITEM_GROUP)
4166           it->wd->group_items = eina_list_remove(it->wd->group_items, it);
4167         elm_widget_item_pre_notify_del(it);
4168         if (it->realized) _item_unrealize(it, EINA_FALSE);
4169         if (((wd->clear_me) || (!it->delete_me)) && (it->itc->func.del))
4170           it->itc->func.del((void *)it->base.data, WIDGET(it));
4171         if (it->long_timer) ecore_timer_del(it->long_timer);
4172         if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
4173         elm_widget_item_del(it);
4174      }
4175    wd->clear_me = EINA_FALSE;
4176    wd->anchor_item = NULL;
4177    while (wd->blocks)
4178      {
4179         Item_Block *itb = (Item_Block *)(wd->blocks);
4180
4181         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
4182         if (itb->items) eina_list_free(itb->items);
4183         free(itb);
4184      }
4185    wd->pan_changed = EINA_TRUE;
4186    if (wd->calc_job)
4187      {
4188         ecore_job_del(wd->calc_job);
4189         wd->calc_job = NULL;
4190      }
4191    if (wd->queue_idle_enterer)
4192      {
4193         ecore_idle_enterer_del(wd->queue_idle_enterer);
4194         wd->queue_idle_enterer = NULL;
4195      }
4196    if (wd->must_recalc_idler)
4197      {
4198         ecore_idler_del(wd->must_recalc_idler);
4199         wd->must_recalc_idler = NULL;
4200      }
4201    if (wd->queue)
4202      {
4203         eina_list_free(wd->queue);
4204         wd->queue = NULL;
4205      }
4206    if (wd->selected)
4207      {
4208         eina_list_free(wd->selected);
4209         wd->selected = NULL;
4210      }
4211    if (wd->reorder_move_animator)
4212      {
4213         ecore_animator_del(wd->reorder_move_animator);
4214         wd->reorder_move_animator = NULL;
4215      }
4216    wd->show_item = NULL;
4217    wd->pan_x = 0;
4218    wd->pan_y = 0;
4219    wd->old_pan_y = 0;
4220    wd->minw = 0;
4221    wd->minh = 0;
4222
4223    if (wd->alpha_bg)
4224       evas_object_del(wd->alpha_bg);
4225    wd->alpha_bg = NULL;
4226
4227    if (wd->pan_smart)
4228      {
4229         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4230         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4231      }
4232    _sizing_eval(obj);
4233    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4234    evas_event_thaw(evas_object_evas_get(wd->obj));
4235    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4236 }
4237
4238 EAPI void
4239 elm_genlist_multi_select_set(Evas_Object *obj,
4240                              Eina_Bool    multi)
4241 {
4242    ELM_CHECK_WIDTYPE(obj, widtype);
4243    Widget_Data *wd = elm_widget_data_get(obj);
4244    if (!wd) return;
4245    wd->multi = multi;
4246 }
4247
4248 EAPI Eina_Bool
4249 elm_genlist_multi_select_get(const Evas_Object *obj)
4250 {
4251    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4252    Widget_Data *wd = elm_widget_data_get(obj);
4253    if (!wd) return EINA_FALSE;
4254    return wd->multi;
4255 }
4256
4257 EAPI Elm_Genlist_Item *
4258 elm_genlist_selected_item_get(const Evas_Object *obj)
4259 {
4260    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4261    Widget_Data *wd = elm_widget_data_get(obj);
4262    if (!wd) return NULL;
4263    if (wd->selected) return wd->selected->data;
4264    return NULL;
4265 }
4266
4267 EAPI const Eina_List *
4268 elm_genlist_selected_items_get(const Evas_Object *obj)
4269 {
4270    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4271    Widget_Data *wd = elm_widget_data_get(obj);
4272    if (!wd) return NULL;
4273    return wd->selected;
4274 }
4275
4276 EAPI Eina_List *
4277 elm_genlist_realized_items_get(const Evas_Object *obj)
4278 {
4279    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4280    Widget_Data *wd = elm_widget_data_get(obj);
4281    Eina_List *list = NULL;
4282    Item_Block *itb;
4283    Eina_Bool done = EINA_FALSE;
4284    if (!wd) return NULL;
4285    EINA_INLIST_FOREACH(wd->blocks, itb)
4286      {
4287         if (itb->realized)
4288           {
4289              Eina_List *l;
4290              Elm_Genlist_Item *it;
4291
4292              done = 1;
4293              EINA_LIST_FOREACH(itb->items, l, it)
4294                {
4295                   if (it->realized) list = eina_list_append(list, it);
4296                }
4297           }
4298         else
4299           {
4300              if (done) break;
4301           }
4302      }
4303    return list;
4304 }
4305
4306 EAPI Elm_Genlist_Item *
4307 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4308                            Evas_Coord         x,
4309                            Evas_Coord         y,
4310                            int               *posret)
4311 {
4312    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4313    Widget_Data *wd = elm_widget_data_get(obj);
4314    Evas_Coord ox, oy, ow, oh;
4315    Item_Block *itb;
4316    Evas_Coord lasty;
4317    if (!wd) return NULL;
4318    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4319    lasty = oy;
4320    EINA_INLIST_FOREACH(wd->blocks, itb)
4321      {
4322         Eina_List *l;
4323         Elm_Genlist_Item *it;
4324
4325         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4326                                  oy + itb->y - itb->wd->pan_y,
4327                                  itb->w, itb->h, x, y, 1, 1))
4328           continue;
4329         EINA_LIST_FOREACH(itb->items, l, it)
4330           {
4331              Evas_Coord itx, ity;
4332
4333              itx = ox + itb->x + it->x - itb->wd->pan_x;
4334              ity = oy + itb->y + it->y - itb->wd->pan_y;
4335              if (ELM_RECTS_INTERSECT(itx, ity, it->w, it->h, x, y, 1, 1))
4336                {
4337                   if (posret)
4338                     {
4339                        if (y <= (ity + (it->h / 4))) *posret = -1;
4340                        else if (y >= (ity + it->h - (it->h / 4)))
4341                          *posret = 1;
4342                        else *posret = 0;
4343                     }
4344                   return it;
4345                }
4346              lasty = ity + it->h;
4347           }
4348      }
4349    if (posret)
4350      {
4351         if (y > lasty) *posret = 1;
4352         else *posret = -1;
4353      }
4354    return NULL;
4355 }
4356
4357 EAPI Elm_Genlist_Item *
4358 elm_genlist_first_item_get(const Evas_Object *obj)
4359 {
4360    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4361    Widget_Data *wd = elm_widget_data_get(obj);
4362    if (!wd) return NULL;
4363    if (!wd->items) return NULL;
4364    Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
4365    while ((it) && (it->delete_me))
4366      it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4367    return it;
4368 }
4369
4370 EAPI Elm_Genlist_Item *
4371 elm_genlist_last_item_get(const Evas_Object *obj)
4372 {
4373    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4374    Widget_Data *wd = elm_widget_data_get(obj);
4375    if (!wd) return NULL;
4376    if (!wd->items) return NULL;
4377    Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items->last);
4378    while ((it) && (it->delete_me))
4379      it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4380    return it;
4381 }
4382
4383 EAPI Elm_Genlist_Item *
4384 elm_genlist_item_next_get(const Elm_Genlist_Item *it)
4385 {
4386    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4387    while (it)
4388      {
4389         it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4390         if ((it) && (!it->delete_me)) break;
4391      }
4392    return (Elm_Genlist_Item *)it;
4393 }
4394
4395 EAPI Elm_Genlist_Item *
4396 elm_genlist_item_prev_get(const Elm_Genlist_Item *it)
4397 {
4398    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4399    while (it)
4400      {
4401         it = ELM_GENLIST_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4402         if ((it) && (!it->delete_me)) break;
4403      }
4404    return (Elm_Genlist_Item *)it;
4405 }
4406
4407 EAPI Evas_Object *
4408 elm_genlist_item_genlist_get(const Elm_Genlist_Item *it)
4409 {
4410    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4411    return WIDGET(it);
4412 }
4413
4414 EAPI Elm_Genlist_Item *
4415 elm_genlist_item_parent_get(const Elm_Genlist_Item *it)
4416 {
4417    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4418    return it->parent;
4419 }
4420
4421 EAPI void
4422 elm_genlist_item_subitems_clear(Elm_Genlist_Item *it)
4423 {
4424    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4425    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4426    if (!wd) return;
4427    Elm_Genlist_Item *it2, *it3;
4428    Evas_Coord y, h;
4429
4430    if (!wd->effect_mode || !wd->move_effect_mode)
4431       _item_subitems_clear(it);
4432    else
4433      {
4434         if ((!wd->item_moving_effect_timer) && (it->flags != ELM_GENLIST_ITEM_GROUP) &&
4435              wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE)
4436           {
4437              wd->expand_item = it;
4438              _item_flip_effect_show(it);
4439              evas_object_geometry_get(VIEW(it), NULL, &y, NULL, &h);
4440              wd->expand_item_end = y + h;
4441
4442              it2= it;
4443              do {
4444                   it2 = elm_genlist_item_next_get(it2);
4445                   if (!it2) break;
4446              } while (it2->expanded_depth > it->expanded_depth);
4447              if (it2)
4448                {
4449                   int diff;
4450                   Evas_Coord vy, vh;
4451                   evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), NULL, &vy, NULL, &vh);
4452                   diff = it2->old_scrl_y - (vy + vh);
4453                   if (diff > 0)
4454                     {
4455                        it3 = it2;
4456                        while (it3)
4457                          {
4458                             it3->old_scrl_y = it3->old_scrl_y - diff;
4459                             it3 = elm_genlist_item_next_get(it3);
4460                          }
4461                     }
4462
4463                   wd->expand_item_gap = wd->expand_item_end - it2->old_scrl_y;
4464                }
4465              else
4466                 wd->expand_item_gap = 0;
4467
4468              evas_object_raise(wd->alpha_bg);
4469              evas_object_show(wd->alpha_bg);
4470
4471              wd->start_time = current_time_get();
4472              wd->item_moving_effect_timer = ecore_animator_add(_item_moving_effect_timer_cb, wd);
4473           }
4474         else
4475            _item_subitems_clear(it);
4476      }
4477 }
4478
4479 EAPI void
4480 elm_genlist_item_selected_set(Elm_Genlist_Item *it,
4481                               Eina_Bool         selected)
4482 {
4483    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4484    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4485    if (!wd) return;
4486    if ((it->delete_me) || (it->disabled)) return;
4487    selected = !!selected;
4488    if (it->selected == selected) return;
4489
4490    if (selected)
4491      {
4492         if (!wd->multi)
4493           {
4494              while (wd->selected)
4495                _item_unselect(wd->selected->data);
4496           }
4497         _item_highlight(it);
4498         _item_select(it);
4499      }
4500    else
4501      _item_unselect(it);
4502 }
4503
4504 EAPI Eina_Bool
4505 elm_genlist_item_selected_get(const Elm_Genlist_Item *it)
4506 {
4507    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4508    return it->selected;
4509 }
4510
4511 EAPI void
4512 elm_genlist_item_expanded_set(Elm_Genlist_Item *it,
4513                               Eina_Bool         expanded)
4514 {
4515    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4516    if (it->flags != ELM_GENLIST_ITEM_SUBITEMS) return;
4517    if (it->expanded == expanded) return;
4518    it->expanded = expanded;
4519    it->wd->expand_item = it;
4520
4521    if (it->wd->effect_mode && !it->wd->alpha_bg)
4522       it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(it));
4523
4524    if (it->expanded)
4525      {
4526         it->wd->auto_scrolled = EINA_FALSE;
4527         it->wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND;
4528         if (it->realized)
4529           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
4530         evas_object_smart_callback_call(WIDGET(it), "expanded", it);
4531      }
4532    else
4533      {
4534         it->wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT;
4535         if (it->realized)
4536           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
4537         evas_object_smart_callback_call(WIDGET(it), "contracted", it);
4538      }
4539 }
4540
4541 EAPI Eina_Bool
4542 elm_genlist_item_expanded_get(const Elm_Genlist_Item *it)
4543 {
4544    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4545    return it->expanded;
4546 }
4547
4548 EAPI int
4549 elm_genlist_item_expanded_depth_get(const Elm_Genlist_Item *it)
4550 {
4551    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
4552    return it->expanded_depth;
4553 }
4554
4555 EAPI void
4556 elm_genlist_item_disabled_set(Elm_Genlist_Item *it,
4557                               Eina_Bool         disabled)
4558 {
4559    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4560    Eina_List *l;
4561    Evas_Object *obj;
4562    if (it->disabled == disabled) return;
4563    if (it->delete_me) return;
4564    it->disabled = !!disabled;
4565    if (it->selected)
4566      elm_genlist_item_selected_set(it, EINA_FALSE);
4567    if (it->realized)
4568      {
4569         if (it->disabled)
4570           {
4571              edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
4572              if (it->edit_obj)
4573                edje_object_signal_emit(it->edit_obj, "elm,state,disabled", "elm");
4574           }
4575         else
4576           {
4577              edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
4578              if (it->edit_obj)
4579                edje_object_signal_emit(it->edit_obj, "elm,state,enabled", "elm");
4580           }
4581         EINA_LIST_FOREACH(it->icon_objs, l, obj)
4582            elm_widget_disabled_set(obj, disabled);
4583      }
4584 }
4585
4586 EAPI Eina_Bool
4587 elm_genlist_item_disabled_get(const Elm_Genlist_Item *it)
4588 {
4589    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4590    if (it->delete_me) return EINA_FALSE;
4591    return it->disabled;
4592 }
4593
4594 EAPI void
4595 elm_genlist_item_display_only_set(Elm_Genlist_Item *it,
4596                                   Eina_Bool         display_only)
4597 {
4598    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4599    if (it->display_only == display_only) return;
4600    if (it->delete_me) return;
4601    it->display_only = display_only;
4602    it->mincalcd = EINA_FALSE;
4603    it->updateme = EINA_TRUE;
4604    if (it->block) it->block->updateme = EINA_TRUE;
4605    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4606    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4607 }
4608
4609 EAPI Eina_Bool
4610 elm_genlist_item_display_only_get(const Elm_Genlist_Item *it)
4611 {
4612    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4613    if (it->delete_me) return EINA_FALSE;
4614    return it->display_only;
4615 }
4616
4617 EAPI void
4618 elm_genlist_item_show(Elm_Genlist_Item *it)
4619 {
4620    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4621    Evas_Coord gith = 0;
4622    if (it->delete_me) return;
4623    if ((it->queued) || (!it->mincalcd))
4624      {
4625         it->wd->show_item = it;
4626         it->wd->bring_in = EINA_TRUE;
4627         it->showme = EINA_TRUE;
4628         return;
4629      }
4630    if (it->wd->show_item)
4631      {
4632         it->wd->show_item->showme = EINA_FALSE;
4633         it->wd->show_item = NULL;
4634      }
4635    if ((it->group_item) && (it->wd->pan_y > (it->y + it->block->y)))
4636      gith = it->group_item->h;
4637    elm_smart_scroller_child_region_show(it->wd->scr,
4638                                         it->x + it->block->x,
4639                                         it->y + it->block->y - gith,
4640                                         it->block->w, it->h);
4641 }
4642
4643 EAPI void
4644 elm_genlist_item_bring_in(Elm_Genlist_Item *it)
4645 {
4646    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4647    Evas_Coord gith = 0;
4648    if (it->delete_me) return;
4649    if ((it->queued) || (!it->mincalcd))
4650      {
4651         it->wd->show_item = it;
4652         it->wd->bring_in = EINA_TRUE;
4653         it->showme = EINA_TRUE;
4654         return;
4655      }
4656    if (it->wd->show_item)
4657      {
4658         it->wd->show_item->showme = EINA_FALSE;
4659         it->wd->show_item = NULL;
4660      }
4661    if ((it->group_item) && (it->wd->pan_y > (it->y + it->block->y)))
4662      gith = it->group_item->h;
4663    elm_smart_scroller_region_bring_in(it->wd->scr,
4664                                       it->x + it->block->x,
4665                                       it->y + it->block->y - gith,
4666                                       it->block->w, it->h);
4667 }
4668
4669 EAPI void
4670 elm_genlist_item_top_show(Elm_Genlist_Item *it)
4671 {
4672    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4673    Evas_Coord ow, oh;
4674    Evas_Coord gith = 0;
4675
4676    if (it->delete_me) return;
4677    if ((it->queued) || (!it->mincalcd))
4678      {
4679         it->wd->show_item = it;
4680         it->wd->bring_in = EINA_TRUE;
4681         it->showme = EINA_TRUE;
4682         return;
4683      }
4684    if (it->wd->show_item)
4685      {
4686         it->wd->show_item->showme = EINA_FALSE;
4687         it->wd->show_item = NULL;
4688      }
4689    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4690    if (it->group_item) gith = it->group_item->h;
4691    elm_smart_scroller_child_region_show(it->wd->scr,
4692                                         it->x + it->block->x,
4693                                         it->y + it->block->y - gith,
4694                                         it->block->w, oh);
4695 }
4696
4697 EAPI void
4698 elm_genlist_item_top_bring_in(Elm_Genlist_Item *it)
4699 {
4700    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4701    Evas_Coord ow, oh;
4702    Evas_Coord gith = 0;
4703
4704    if (it->delete_me) return;
4705    if ((it->queued) || (!it->mincalcd))
4706      {
4707         it->wd->show_item = it;
4708         it->wd->bring_in = EINA_TRUE;
4709         it->showme = EINA_TRUE;
4710         return;
4711      }
4712    if (it->wd->show_item)
4713      {
4714         it->wd->show_item->showme = EINA_FALSE;
4715         it->wd->show_item = NULL;
4716      }
4717    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4718    if (it->group_item) gith = it->group_item->h;
4719    elm_smart_scroller_region_bring_in(it->wd->scr,
4720                                       it->x + it->block->x,
4721                                       it->y + it->block->y - gith,
4722                                       it->block->w, oh);
4723 }
4724
4725 EAPI void
4726 elm_genlist_item_middle_show(Elm_Genlist_Item *it)
4727 {
4728    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4729    Evas_Coord ow, oh;
4730
4731    if (it->delete_me) return;
4732    if ((it->queued) || (!it->mincalcd))
4733      {
4734         it->wd->show_item = it;
4735         it->wd->bring_in = EINA_TRUE;
4736         it->showme = EINA_TRUE;
4737         return;
4738      }
4739    if (it->wd->show_item)
4740      {
4741         it->wd->show_item->showme = EINA_FALSE;
4742         it->wd->show_item = NULL;
4743      }
4744    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4745    elm_smart_scroller_child_region_show(it->wd->scr,
4746                                         it->x + it->block->x,
4747                                         it->y + it->block->y - oh / 2 +
4748                                         it->h / 2, it->block->w, oh);
4749 }
4750
4751 EAPI void
4752 elm_genlist_item_middle_bring_in(Elm_Genlist_Item *it)
4753 {
4754    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4755    Evas_Coord ow, oh;
4756
4757    if (it->delete_me) return;
4758    if ((it->queued) || (!it->mincalcd))
4759      {
4760         it->wd->show_item = it;
4761         it->wd->bring_in = EINA_TRUE;
4762         it->showme = EINA_TRUE;
4763         return;
4764      }
4765    if (it->wd->show_item)
4766      {
4767         it->wd->show_item->showme = EINA_FALSE;
4768         it->wd->show_item = NULL;
4769      }
4770    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4771    elm_smart_scroller_region_bring_in(it->wd->scr,
4772                                       it->x + it->block->x,
4773                                       it->y + it->block->y - oh / 2 + it->h / 2,
4774                                       it->block->w, oh);
4775 }
4776
4777 EAPI void
4778 elm_genlist_item_del(Elm_Genlist_Item *it)
4779 {
4780    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4781    if ((it->relcount > 0) || (it->walking > 0))
4782      {
4783         elm_widget_item_pre_notify_del(it);
4784         elm_genlist_item_subitems_clear(it);
4785         it->delete_me = EINA_TRUE;
4786         if (it->wd->show_item == it) it->wd->show_item = NULL;
4787         if (it->selected)
4788           it->wd->selected = eina_list_remove(it->wd->selected,
4789                                               it);
4790         if (it->block)
4791           {
4792              if (it->realized) _item_unrealize(it, EINA_FALSE);
4793              it->block->changed = EINA_TRUE;
4794              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
4795              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
4796           }
4797         if (it->itc->func.del)
4798           it->itc->func.del((void *)it->base.data, WIDGET(it));
4799         return;
4800      }
4801    _item_del(it);
4802 }
4803
4804 EAPI void
4805 elm_genlist_item_data_set(Elm_Genlist_Item *it,
4806                           const void       *data)
4807 {
4808    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4809    elm_widget_item_data_set(it, data);
4810 }
4811
4812 EAPI void *
4813 elm_genlist_item_data_get(const Elm_Genlist_Item *it)
4814 {
4815    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4816    return elm_widget_item_data_get(it);
4817 }
4818
4819 EAPI void
4820 elm_genlist_item_icons_orphan(Elm_Genlist_Item *it)
4821 {
4822    Evas_Object *icon;
4823    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4824    EINA_LIST_FREE(it->icon_objs, icon)
4825      {
4826         elm_widget_sub_object_del(WIDGET(it), icon);
4827         evas_object_smart_member_del(icon);
4828         evas_object_hide(icon);
4829      }
4830 }
4831
4832 EAPI const Evas_Object *
4833 elm_genlist_item_object_get(const Elm_Genlist_Item *it)
4834 {
4835    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4836    return VIEW(it);
4837 }
4838
4839 EAPI void
4840 elm_genlist_item_update(Elm_Genlist_Item *it)
4841 {
4842    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4843    if (!it->block) return;
4844    if (it->delete_me) return;
4845    it->mincalcd = EINA_FALSE;
4846    it->updateme = EINA_TRUE;
4847    it->block->updateme = EINA_TRUE;
4848    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4849    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4850    it->defer_unrealize = EINA_FALSE;
4851 }
4852
4853 EAPI void
4854 elm_genlist_item_fields_update(Elm_Genlist_Item *it,
4855                                const char *parts,
4856                                Elm_Genlist_Item_Field_Flags itf)
4857 {
4858    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4859    if (!it->block) return;
4860    if (it->delete_me) return;
4861
4862    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_LABEL))
4863      _item_label_realize(it, VIEW(it), &it->labels, parts);
4864    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_ICON))
4865      {
4866         it->icon_objs = _item_icon_unrealize(it, VIEW(it),
4867                                              &it->icons, parts);
4868         it->icon_objs = _item_icon_realize(it, VIEW(it),
4869                                            &it->icons, parts);
4870
4871         if (it->renamed)
4872           {
4873              it->icon_objs = _item_mode_icon_unrealize(it, VIEW(it),
4874                                                        &it->icons, parts, &it->icon_objs);
4875              it->icon_objs = _item_mode_icon_realize(it, VIEW(it),
4876                                                      &it->icons, parts, &it->icon_objs, "renames");
4877           }
4878
4879         if (it->mode_view)
4880           {
4881              it->mode_icon_objs = _item_mode_icon_unrealize(it, it->mode_view,
4882                                                             &it->mode_icons, parts, &it->mode_icon_objs);
4883              it->mode_icon_objs = _item_mode_icon_realize(it, it->mode_view,
4884                                                           &it->mode_icons, parts, &it->mode_icon_objs, "icons");
4885           }
4886
4887         if (it->wd->edit_mode)
4888           {
4889              it->edit_icon_objs = _item_mode_icon_unrealize(it, it->edit_obj,
4890                                                             &it->icons, parts, &it->edit_icon_objs);
4891              it->edit_icon_objs = _item_mode_icon_realize(it, it->edit_obj,
4892                                                      &it->icons, parts, &it->edit_icon_objs, "edit_icons");
4893           }
4894      }
4895    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4896      _item_state_realize(it, VIEW(it), &it->states, parts);
4897 }
4898
4899 EAPI void
4900 elm_genlist_item_item_class_update(Elm_Genlist_Item             *it,
4901                                    const Elm_Genlist_Item_Class *itc)
4902 {
4903    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4904    if (!it->block) return;
4905    EINA_SAFETY_ON_NULL_RETURN(itc);
4906    if (it->delete_me) return;
4907    it->itc = itc;
4908    it->nocache = EINA_TRUE;
4909    elm_genlist_item_update(it);
4910 }
4911
4912 EAPI const Elm_Genlist_Item_Class *
4913 elm_genlist_item_item_class_get(const Elm_Genlist_Item *it)
4914 {
4915    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4916    if (it->delete_me) return NULL;
4917    return it->itc;
4918 }
4919 static Evas_Object *
4920 _elm_genlist_item_label_create(void        *data,
4921                                Evas_Object *obj __UNUSED__,
4922                                Evas_Object *tooltip,
4923                                void        *item __UNUSED__)
4924 {
4925    Evas_Object *label = elm_label_add(tooltip);
4926    if (!label)
4927      return NULL;
4928    elm_object_style_set(label, "tooltip");
4929    elm_object_text_set(label, data);
4930    return label;
4931 }
4932
4933 static void
4934 _elm_genlist_item_label_del_cb(void        *data,
4935                                Evas_Object *obj __UNUSED__,
4936                                void        *event_info __UNUSED__)
4937 {
4938    eina_stringshare_del(data);
4939 }
4940
4941 EAPI void
4942 elm_genlist_item_tooltip_text_set(Elm_Genlist_Item *item,
4943                                   const char       *text)
4944 {
4945    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4946    text = eina_stringshare_add(text);
4947    elm_genlist_item_tooltip_content_cb_set(item, _elm_genlist_item_label_create,
4948                                            text,
4949                                            _elm_genlist_item_label_del_cb);
4950 }
4951
4952 EAPI void
4953 elm_genlist_item_tooltip_content_cb_set(Elm_Genlist_Item           *item,
4954                                         Elm_Tooltip_Item_Content_Cb func,
4955                                         const void                 *data,
4956                                         Evas_Smart_Cb               del_cb)
4957 {
4958    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
4959
4960    if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
4961      return;
4962
4963    if (item->tooltip.del_cb)
4964      item->tooltip.del_cb((void *)item->tooltip.data,
4965                           item->base.widget, item);
4966
4967    item->tooltip.content_cb = func;
4968    item->tooltip.data = data;
4969    item->tooltip.del_cb = del_cb;
4970
4971    if (VIEW(item))
4972      {
4973         elm_widget_item_tooltip_content_cb_set(item,
4974                                                item->tooltip.content_cb,
4975                                                item->tooltip.data, NULL);
4976         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
4977      }
4978
4979    return;
4980
4981 error:
4982    if (del_cb) del_cb((void *)data, NULL, NULL);
4983 }
4984
4985 EAPI void
4986 elm_genlist_item_tooltip_unset(Elm_Genlist_Item *item)
4987 {
4988    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
4989    if ((item->base.view) && (item->tooltip.content_cb))
4990      elm_widget_item_tooltip_unset(item);
4991
4992    if (item->tooltip.del_cb)
4993      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
4994    item->tooltip.del_cb = NULL;
4995    item->tooltip.content_cb = NULL;
4996    item->tooltip.data = NULL;
4997    if (item->tooltip.style)
4998      elm_genlist_item_tooltip_style_set(item, NULL);
4999 }
5000
5001 EAPI void
5002 elm_genlist_item_tooltip_style_set(Elm_Genlist_Item *item,
5003                                    const char       *style)
5004 {
5005    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5006    eina_stringshare_replace(&item->tooltip.style, style);
5007    if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
5008 }
5009
5010 EAPI const char *
5011 elm_genlist_item_tooltip_style_get(const Elm_Genlist_Item *item)
5012 {
5013    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
5014    return item->tooltip.style;
5015 }
5016
5017 EAPI Eina_Bool
5018 elm_genlist_item_tooltip_size_restrict_disable(Elm_Genlist_Item *item, Eina_Bool disable)
5019 {
5020    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5021    return elm_widget_item_tooltip_size_restrict_disable(item, disable);
5022 }
5023
5024 EAPI Eina_Bool
5025 elm_genlist_item_tooltip_size_restrict_disabled_get(const Elm_Genlist_Item *item)
5026 {
5027    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5028    return elm_widget_item_tooltip_size_restrict_disabled_get(item);
5029 }
5030
5031 EAPI void
5032 elm_genlist_item_cursor_set(Elm_Genlist_Item *item,
5033                             const char       *cursor)
5034 {
5035    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5036    eina_stringshare_replace(&item->mouse_cursor, cursor);
5037    if (item->base.view) elm_widget_item_cursor_set(item, cursor);
5038 }
5039
5040 EAPI const char *
5041 elm_genlist_item_cursor_get(const Elm_Genlist_Item *item)
5042 {
5043    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
5044    return elm_widget_item_cursor_get(item);
5045 }
5046
5047 EAPI void
5048 elm_genlist_item_cursor_unset(Elm_Genlist_Item *item)
5049 {
5050    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5051    if (!item->mouse_cursor)
5052      return;
5053
5054    if (VIEW(item))
5055      elm_widget_item_cursor_unset(item);
5056
5057    eina_stringshare_del(item->mouse_cursor);
5058    item->mouse_cursor = NULL;
5059 }
5060
5061 EAPI void
5062 elm_genlist_item_cursor_style_set(Elm_Genlist_Item *item,
5063                                   const char       *style)
5064 {
5065    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5066    elm_widget_item_cursor_style_set(item, style);
5067 }
5068
5069 EAPI const char *
5070 elm_genlist_item_cursor_style_get(const Elm_Genlist_Item *item)
5071 {
5072    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
5073    return elm_widget_item_cursor_style_get(item);
5074 }
5075
5076 EAPI void
5077 elm_genlist_item_cursor_engine_only_set(Elm_Genlist_Item *item,
5078                                         Eina_Bool         engine_only)
5079 {
5080    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
5081    elm_widget_item_cursor_engine_only_set(item, engine_only);
5082 }
5083
5084 EAPI Eina_Bool
5085 elm_genlist_item_cursor_engine_only_get(const Elm_Genlist_Item *item)
5086 {
5087    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5088    return elm_widget_item_cursor_engine_only_get(item);
5089 }
5090
5091 EAPI void
5092 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
5093                                 Elm_List_Mode mode)
5094 {
5095    ELM_CHECK_WIDTYPE(obj, widtype);
5096    Widget_Data *wd = elm_widget_data_get(obj);
5097    if (!wd) return;
5098    if (wd->mode == mode) return;
5099    wd->mode = mode;
5100    _sizing_eval(obj);
5101 }
5102
5103 EAPI Elm_List_Mode
5104 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
5105 {
5106    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5107    Widget_Data *wd = elm_widget_data_get(obj);
5108    if (!wd) return ELM_LIST_LAST;
5109    return wd->mode;
5110 }
5111
5112 EAPI void
5113 elm_genlist_always_select_mode_set(Evas_Object *obj,
5114                                    Eina_Bool    always_select)
5115 {
5116    ELM_CHECK_WIDTYPE(obj, widtype);
5117    Widget_Data *wd = elm_widget_data_get(obj);
5118    if (!wd) return;
5119    wd->always_select = always_select;
5120 }
5121
5122 EAPI Eina_Bool
5123 elm_genlist_always_select_mode_get(const Evas_Object *obj)
5124 {
5125    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5126    Widget_Data *wd = elm_widget_data_get(obj);
5127    if (!wd) return EINA_FALSE;
5128    return wd->always_select;
5129 }
5130
5131 EAPI void
5132 elm_genlist_no_select_mode_set(Evas_Object *obj,
5133                                Eina_Bool    no_select)
5134 {
5135    ELM_CHECK_WIDTYPE(obj, widtype);
5136    Widget_Data *wd = elm_widget_data_get(obj);
5137    if (!wd) return;
5138    wd->no_select = no_select;
5139 }
5140
5141 EAPI Eina_Bool
5142 elm_genlist_no_select_mode_get(const Evas_Object *obj)
5143 {
5144    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5145    Widget_Data *wd = elm_widget_data_get(obj);
5146    if (!wd) return EINA_FALSE;
5147    return wd->no_select;
5148 }
5149
5150 EAPI void
5151 elm_genlist_compress_mode_set(Evas_Object *obj,
5152                               Eina_Bool    compress)
5153 {
5154    ELM_CHECK_WIDTYPE(obj, widtype);
5155    Widget_Data *wd = elm_widget_data_get(obj);
5156    if (!wd) return;
5157    wd->compress = compress;
5158 }
5159
5160 EAPI Eina_Bool
5161 elm_genlist_compress_mode_get(const Evas_Object *obj)
5162 {
5163    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5164    Widget_Data *wd = elm_widget_data_get(obj);
5165    if (!wd) return EINA_FALSE;
5166    return wd->compress;
5167 }
5168
5169 EAPI void
5170 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
5171                                       Eina_Bool    height_for_width)
5172 {
5173    ELM_CHECK_WIDTYPE(obj, widtype);
5174    Widget_Data *wd = elm_widget_data_get(obj);
5175    if (!wd) return;
5176    wd->height_for_width = !!height_for_width;
5177    if (wd->height_for_width)
5178      {
5179         elm_genlist_homogeneous_set(obj, EINA_FALSE);
5180         elm_genlist_compress_mode_set(obj, EINA_TRUE);
5181      }
5182 }
5183
5184 EAPI Eina_Bool
5185 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
5186 {
5187    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5188    Widget_Data *wd = elm_widget_data_get(obj);
5189    if (!wd) return EINA_FALSE;
5190    return wd->height_for_width;
5191 }
5192
5193 EAPI void
5194 elm_genlist_bounce_set(Evas_Object *obj,
5195                        Eina_Bool    h_bounce,
5196                        Eina_Bool    v_bounce)
5197 {
5198    ELM_CHECK_WIDTYPE(obj, widtype);
5199    Widget_Data *wd = elm_widget_data_get(obj);
5200    if (!wd) return;
5201    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
5202 }
5203
5204 EAPI void
5205 elm_genlist_bounce_get(const Evas_Object *obj,
5206                        Eina_Bool         *h_bounce,
5207                        Eina_Bool         *v_bounce)
5208 {
5209    ELM_CHECK_WIDTYPE(obj, widtype);
5210    Widget_Data *wd = elm_widget_data_get(obj);
5211    if (!wd) return;
5212    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
5213 }
5214
5215 EAPI void
5216 elm_genlist_homogeneous_set(Evas_Object *obj,
5217                             Eina_Bool    homogeneous)
5218 {
5219    ELM_CHECK_WIDTYPE(obj, widtype);
5220    Widget_Data *wd = elm_widget_data_get(obj);
5221    if (!wd) return;
5222    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
5223    wd->homogeneous = homogeneous;
5224 }
5225
5226 EAPI Eina_Bool
5227 elm_genlist_homogeneous_get(const Evas_Object *obj)
5228 {
5229    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5230    Widget_Data *wd = elm_widget_data_get(obj);
5231    if (!wd) return EINA_FALSE;
5232    return wd->homogeneous;
5233 }
5234
5235 EAPI void
5236 elm_genlist_block_count_set(Evas_Object *obj,
5237                             int          n)
5238 {
5239    ELM_CHECK_WIDTYPE(obj, widtype);
5240    Widget_Data *wd = elm_widget_data_get(obj);
5241    if (!wd) return;
5242    wd->max_items_per_block = n;
5243    wd->item_cache_max = wd->max_items_per_block * 2;
5244    _item_cache_clean(wd);
5245 }
5246
5247 EAPI int
5248 elm_genlist_block_count_get(const Evas_Object *obj)
5249 {
5250    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5251    Widget_Data *wd = elm_widget_data_get(obj);
5252    if (!wd) return 0;
5253    return wd->max_items_per_block;
5254 }
5255
5256 EAPI void
5257 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5258                                   double       timeout)
5259 {
5260    ELM_CHECK_WIDTYPE(obj, widtype);
5261    Widget_Data *wd = elm_widget_data_get(obj);
5262    if (!wd) return;
5263    wd->longpress_timeout = timeout;
5264 }
5265
5266 EAPI double
5267 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5268 {
5269    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5270    Widget_Data *wd = elm_widget_data_get(obj);
5271    if (!wd) return 0;
5272    return wd->longpress_timeout;
5273 }
5274
5275 EAPI void
5276 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5277                                 Elm_Scroller_Policy policy_h,
5278                                 Elm_Scroller_Policy policy_v)
5279 {
5280    ELM_CHECK_WIDTYPE(obj, widtype);
5281    Widget_Data *wd = elm_widget_data_get(obj);
5282    if ((!wd) || (!wd->scr)) return;
5283    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5284        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5285      return;
5286    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5287 }
5288
5289 EAPI void
5290 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5291                                 Elm_Scroller_Policy *policy_h,
5292                                 Elm_Scroller_Policy *policy_v)
5293 {
5294    ELM_CHECK_WIDTYPE(obj, widtype);
5295    Widget_Data *wd = elm_widget_data_get(obj);
5296    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5297    if ((!wd) || (!wd->scr)) return;
5298    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5299    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5300    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5301 }
5302
5303 EAPI void
5304 elm_genlist_realized_items_update(Evas_Object *obj)
5305 {
5306    ELM_CHECK_WIDTYPE(obj, widtype);
5307
5308    Eina_List *list, *l;
5309    Elm_Genlist_Item *it;
5310
5311    list = elm_genlist_realized_items_get(obj);
5312    EINA_LIST_FOREACH(list, l, it)
5313      elm_genlist_item_update(it);
5314 }
5315
5316 EAPI void
5317 elm_genlist_item_mode_set(Elm_Genlist_Item *it,
5318                           const char       *mode_type,
5319                           Eina_Bool         mode_set)
5320 {
5321    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
5322    Widget_Data *wd = it->wd;
5323    Eina_List *l;
5324    Elm_Genlist_Item *it2;
5325
5326    if (!wd) return;
5327    if (!mode_type) return;
5328    if ((it->delete_me) || (it->disabled)) return;
5329    if (wd->edit_mode) return;
5330
5331    if ((wd->mode_item == it) &&
5332        (!strcmp(mode_type, wd->mode_type)) &&
5333        (mode_set))
5334       return;
5335    if (!it->itc->mode_item_style) return;
5336
5337    if (wd->multi)
5338      {
5339         EINA_LIST_FOREACH(wd->selected, l, it2)
5340           if (it2->realized)
5341             elm_genlist_item_selected_set(it2, EINA_FALSE);
5342      }
5343    else
5344      {
5345         it2 = elm_genlist_selected_item_get(wd->obj);
5346         if ((it2) && (it2->realized))
5347           elm_genlist_item_selected_set(it2, EINA_FALSE);
5348      }
5349
5350    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
5351        (mode_set) ||
5352        ((it == wd->mode_item) && (!mode_set)))
5353      _item_mode_unset(wd);
5354
5355    eina_stringshare_replace(&wd->mode_type, mode_type);
5356    if (mode_set) _item_mode_set(it);
5357 }
5358
5359 EAPI const char *
5360 elm_genlist_mode_get(const Evas_Object *obj)
5361 {
5362    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5363    Widget_Data *wd = elm_widget_data_get(obj);
5364    if (!wd) return NULL;
5365    return wd->mode_type;
5366 }
5367
5368 EAPI const Elm_Genlist_Item *
5369 elm_genlist_mode_item_get(const Evas_Object *obj)
5370 {
5371    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5372    Widget_Data *wd = elm_widget_data_get(obj);
5373    if (!wd) return NULL;
5374    return wd->mode_item;
5375 }
5376
5377 EAPI void
5378 elm_genlist_reorder_mode_set(Evas_Object *obj,
5379                              Eina_Bool    reorder_mode)
5380 {
5381    ELM_CHECK_WIDTYPE(obj, widtype);
5382    Widget_Data *wd = elm_widget_data_get(obj);
5383    if (!wd) return;
5384    wd->reorder_mode = reorder_mode;
5385 }
5386
5387 EAPI Eina_Bool
5388 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5389 {
5390    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5391    Widget_Data *wd = elm_widget_data_get(obj);
5392    if (!wd) return EINA_FALSE;
5393    return wd->reorder_mode;
5394 }
5395
5396 EAPI void
5397 elm_genlist_item_move_after(Elm_Genlist_Item *it __UNUSED__, Elm_Genlist_Item *after __UNUSED__)
5398 {
5399    return;
5400 }
5401
5402 EAPI void
5403 elm_genlist_item_move_before(Elm_Genlist_Item *it __UNUSED__, Elm_Genlist_Item *before __UNUSED__)
5404 {
5405    return;
5406 }
5407
5408 EAPI void
5409 elm_genlist_effect_set(const Evas_Object *obj, Eina_Bool emode)
5410 {
5411    ELM_CHECK_WIDTYPE(obj, widtype);
5412    Widget_Data *wd = elm_widget_data_get(obj);
5413    if (!wd) return;
5414    wd->effect_mode = emode;
5415    //   wd->point_rect = evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5416    //   evas_object_resize(wd->point_rect, 10, 25);
5417    //   evas_object_color_set(wd->point_rect, 255, 0, 0, 130);
5418    //   evas_object_show(wd->point_rect);
5419    //   evas_object_hide(wd->point_rect);
5420 }
5421
5422 static Evas_Object*
5423 _create_tray_alpha_bg(const Evas_Object *obj)
5424 {
5425    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5426    Widget_Data *wd = elm_widget_data_get(obj);
5427    if (!wd) return NULL;
5428
5429    Evas_Object *bg = NULL;
5430    Evas_Coord ox, oy, ow, oh;
5431
5432    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5433    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5434    evas_object_color_set(bg,0,0,0,0);
5435    evas_object_resize(bg , ow, oh);
5436    evas_object_move(bg , ox, oy);
5437    evas_object_show(bg);
5438    evas_object_hide(bg);
5439    return bg ;
5440 }
5441
5442 static unsigned int
5443 current_time_get()
5444 {
5445    struct timeval timev;
5446
5447    gettimeofday(&timev, NULL);
5448    return ((timev.tv_sec * 1000) + ((timev.tv_usec) / 1000));
5449 }
5450
5451 // added for item moving animation.
5452 static Eina_Bool
5453 _item_moving_effect_timer_cb(void *data)
5454 {
5455    Widget_Data *wd = data;
5456    if (!wd) return EINA_FALSE;
5457    Item_Block *itb;
5458    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
5459    Elm_Genlist_Item *it = NULL, *it2;
5460    const Eina_List *l;
5461    double time = 0.5, t;
5462    int y, dy;
5463    Eina_Bool check, end = EINA_FALSE, vis = EINA_TRUE;
5464    int in = 0;
5465
5466    t = ((0.0 > (t = current_time_get() - wd->start_time)) ? 0.0 : t) / 1000;
5467
5468    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5469    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
5470    if (t > time) end = EINA_TRUE;
5471
5472    // Below while statement is needed, when the genlist is resized.
5473    it2 = wd->expand_item;
5474    while (it2 && vis)
5475      {
5476         evas_object_move(VIEW(it2), it2->scrl_x, it2->scrl_y);
5477         vis = (ELM_RECTS_INTERSECT(it2->scrl_x, it2->scrl_y, it2->w, it2->h,
5478                                    cvx, cvy, cvw, cvh));
5479         it2 = elm_genlist_item_prev_get(it2);
5480      }
5481    it2 = elm_genlist_item_next_get(wd->expand_item);
5482    while (it2)
5483      {
5484         if (wd->expand_item->expanded_depth >= it2->expanded_depth) break;
5485         it2 = elm_genlist_item_next_get(it2);
5486      }
5487    dy = 0;
5488    if (it2)
5489      {
5490         if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5491           dy = ((it2->scrl_y > cvy + cvh) ? cvy + cvh : it2->scrl_y) - it2->old_scrl_y;
5492         else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5493           dy = wd->expand_item_gap;
5494
5495         if (t <= time)
5496           {
5497              y = ((1 - (1 - (t / time)) * (1 - (t /time))) * dy);
5498           }
5499         else
5500           {
5501              end = EINA_TRUE;
5502              y = dy;
5503           }
5504
5505         check = EINA_FALSE;
5506         EINA_INLIST_FOREACH(wd->blocks, itb)
5507           {
5508              itb->w = wd->minw;
5509              if (ELM_RECTS_INTERSECT(itb->x - wd->pan_x + ox,
5510                                      itb->y - wd->pan_y + oy,
5511                                      itb->w, itb->h,
5512                                      cvx, cvy, cvw, cvh))
5513                {
5514                   EINA_LIST_FOREACH(itb->items, l, it)
5515                     {
5516                        if (it == it2) check = EINA_TRUE;
5517                        if (!check) continue;
5518
5519                        if (!it->old_scrl_y)
5520                          it->old_scrl_y  = it->scrl_y;
5521                        if (it->old_scrl_y + y < oy + oh)
5522                          {
5523                             if (!it->realized) _item_realize(it, in, 0);
5524                          }
5525                        if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE && it->old_scrl_y + y < it->scrl_y)
5526                          it->old_scrl_y = it->scrl_y - y;
5527                        in++;
5528
5529                        if (wd->move_effect_mode != ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE ||
5530                            (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE && it->old_scrl_y + y >= it->scrl_y))
5531                          {
5532                             if (wd->edit_mode) _effect_item_controls(it, it->scrl_x, it->old_scrl_y + y);
5533                             else
5534                               {
5535                                  evas_object_resize(VIEW(it), it->w, it->h);
5536                                  evas_object_move(VIEW(it), it->scrl_x, it->old_scrl_y + y);
5537                                  evas_object_show(VIEW(it));
5538                                  evas_object_raise(VIEW(it));
5539                               }
5540
5541                             if (it->group_item) evas_object_raise(it->group_item->base.view);
5542                          }
5543                     }
5544                }
5545           }
5546
5547         if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5548           {
5549              it = elm_genlist_item_prev_get(it2);
5550              while (it)
5551                {
5552                   if (it->expanded_depth <= it2->expanded_depth) break;
5553                   if ((it->scrl_y < it2->old_scrl_y + y) && (it->expanded_depth > it2->expanded_depth))
5554                     {
5555                        if (!it->effect_done)
5556                          {
5557                             edje_object_signal_emit(VIEW(it), "flip_item", "");
5558                             evas_object_show(VIEW(it));
5559                             it->effect_done = EINA_TRUE;
5560                          }
5561                     }
5562                   it = elm_genlist_item_prev_get(it);
5563                }
5564           }
5565         else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5566           {
5567              it = elm_genlist_item_prev_get(it2);
5568              while (it)
5569                {
5570                   if ((it->scrl_y > it2->old_scrl_y + y) && (it->expanded_depth > it2->expanded_depth))
5571                     {
5572                        if (!it->effect_done)
5573                          {
5574                             edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
5575                             it->effect_done = EINA_TRUE;
5576                          }
5577                     }
5578                   else
5579                     break;
5580                   it = elm_genlist_item_prev_get(it);
5581                }
5582           }
5583      }
5584    else
5585      {
5586         int expand_num = 0;
5587         int expand_order = 0;
5588         if (wd->expand_item) it = elm_genlist_item_next_get(wd->expand_item);
5589         while (it)
5590           {
5591              expand_num++;
5592              it = elm_genlist_item_next_get(it);
5593           }
5594         if (wd->expand_item) it = elm_genlist_item_next_get(wd->expand_item);
5595         while (it)
5596           {
5597              expand_order++;
5598              if (wd->expand_item->expanded_depth >= it->expanded_depth) break;
5599              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5600                {
5601                   if (!it->effect_done)
5602                     {
5603                        if (t >= (((expand_order - 1) * time) / expand_num))
5604                          {
5605                             edje_object_signal_emit(VIEW(it), "flip_item", "");
5606                             evas_object_show(VIEW(it));
5607                             it->effect_done = EINA_TRUE;
5608                          }
5609                     }
5610                }
5611              it = elm_genlist_item_next_get(it);
5612           }
5613      }
5614
5615    if (end)
5616      {
5617         if (wd->item_moving_effect_timer)
5618           {
5619              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5620                 _item_subitems_clear(wd->expand_item);
5621              EINA_INLIST_FOREACH(wd->blocks, itb)
5622                {
5623                   EINA_LIST_FOREACH(itb->items, l, it)
5624                     {
5625                        it->effect_done = EINA_TRUE;
5626                        it->old_scrl_y = it->scrl_y;
5627                     }
5628                }
5629           }
5630         wd->item_moving_effect_timer = NULL;
5631
5632         _item_auto_scroll(wd);
5633         evas_object_lower(wd->alpha_bg);
5634         evas_object_hide(wd->alpha_bg);
5635         elm_smart_scroller_bounce_animator_disabled_set(wd->scr, EINA_FALSE);
5636         wd->move_effect_mode = ELM_GENLIST_ITEM_MOVE_EFFECT_NONE;
5637
5638         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
5639         evas_object_smart_callback_call(wd->obj, "effect_done", NULL);
5640         evas_object_smart_changed(wd->pan_smart);
5641         return ECORE_CALLBACK_CANCEL;
5642      }
5643    return ECORE_CALLBACK_RENEW;
5644 }
5645
5646 static void
5647 _emit_contract(Elm_Genlist_Item *it)
5648 {
5649    Elm_Genlist_Item *it2;
5650    Eina_List *l;
5651
5652    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
5653    it->effect_done = EINA_FALSE;
5654
5655    EINA_LIST_FOREACH(it->items, l, it2)
5656       if (it2)
5657          _emit_contract(it2);
5658 }
5659
5660 // added for item moving animation.
5661 static int
5662 _item_flip_effect_show(Elm_Genlist_Item *it)
5663 {
5664    Elm_Genlist_Item *it2;
5665    Eina_List *l;
5666    Widget_Data *wd = it->wd;
5667
5668    EINA_LIST_FOREACH(it->items, l, it2)
5669      {
5670         if (it2->parent && it == it2->parent)
5671           {
5672              if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_EXPAND)
5673                edje_object_signal_emit(it2->base.view, "elm,state,hide", "");
5674              else if (wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_CONTRACT)
5675                _emit_contract(it2);
5676           }
5677      }
5678
5679    return ECORE_CALLBACK_CANCEL;
5680 }
5681
5682 /*
5683 static void
5684 _elm_genlist_pinch_zoom_execute(Evas_Object *obj, Eina_Bool emode)
5685 {
5686    printf("!!! NOW FIXING \n");
5687 }
5688 */
5689
5690 /**
5691  * Set pinch zoom mode
5692  *
5693  * @param obj The genlist object
5694  * @param emode
5695  * (EINA_TRUE = pinch contract (zoom in), EINA_FALSE = pinch expand (zoom out)
5696  *
5697  * @ingroup Genlist
5698  */
5699 EAPI void
5700 elm_genlist_pinch_zoom_mode_set(Evas_Object *obj __UNUSED__, Eina_Bool emode __UNUSED__)
5701 {
5702    printf("!!! NOW FIXING \n");
5703 }
5704
5705 /**
5706  * Get pinch zoom mode
5707  *
5708  * @param obj The genlist object
5709  * @return The pinch mode
5710  * (EINA_TRUE = pinch contract (zoom in), EINA_FALSE = pinch expand (zoom out)
5711  *
5712  * @ingroup Genlist
5713  */
5714 EAPI Eina_Bool
5715 elm_genlist_pinch_zoom_mode_get(const Evas_Object *obj __UNUSED__)
5716 {
5717    printf("!!! NOW FIXING \n");
5718    return EINA_FALSE;
5719 }
5720
5721 EAPI void
5722 elm_genlist_pinch_zoom_set(Evas_Object *obj __UNUSED__, Eina_Bool emode __UNUSED__)
5723 {
5724    printf("!!! NOW FIXING \n");
5725 }
5726
5727
5728 ////////////////////////////////////////////////////////////////////////
5729 //  EDIT  MODE
5730 ////////////////////////////////////////////////////////////////////////
5731
5732 static void
5733 _effect_item_controls(Elm_Genlist_Item *it, int itx, int ity)
5734 {
5735    if (!it->wd->edit_mode) return;
5736    evas_object_resize(it->edit_obj,it->w, it->h);
5737    evas_object_move(it->edit_obj, itx, ity);
5738 }
5739
5740 static void
5741 _effect_item_realize(Elm_Genlist_Item *it, Eina_Bool effect_on)
5742 {
5743    if ((it->effect_item_realized) || (it->delete_me)) return;
5744    char buf[1024];
5745
5746    if (it->mode_view)
5747      _mode_finished_signal_cb(it, (Evas_Object *)elm_genlist_item_object_get(it), NULL, NULL);
5748
5749    it->edit_obj = edje_object_add(evas_object_evas_get(WIDGET(it)));
5750    edje_object_scale_set(it->edit_obj, elm_widget_scale_get(WIDGET(it)) *
5751                          _elm_config->scale);
5752    evas_object_smart_member_add(it->edit_obj, it->wd->pan_smart);
5753    elm_widget_sub_object_add(WIDGET(it), it->edit_obj);
5754
5755    if (it->flags & ELM_GENLIST_ITEM_SUBITEMS) strncpy(buf, "tree", sizeof(buf));
5756    else strncpy(buf, "item", sizeof(buf));
5757    if (it->wd->compress) strncat(buf, "_compress", sizeof(buf) - strlen(buf));
5758
5759    strncat(buf, "/", sizeof(buf) - strlen(buf));
5760
5761    if (it->itc->edit_item_style && strcmp(it->itc->edit_item_style, "default"))
5762      {
5763         strncat(buf, it->itc->edit_item_style, sizeof(buf) - strlen(buf));
5764         _elm_theme_object_set(WIDGET(it), it->edit_obj, "genlist", buf, elm_widget_style_get(WIDGET(it)));
5765      }
5766    else
5767      {
5768         _elm_theme_object_set(WIDGET(it), it->edit_obj, "genlist", "item/edit_default", elm_widget_style_get(WIDGET(it)));
5769      }
5770
5771    if (it->wd->reorder_mode)
5772      {
5773         if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,reorder_enabled_effect", "elm");
5774         else edje_object_signal_emit(it->edit_obj, "elm,state,reorder_enabled", "elm");
5775      }
5776    if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,emode_enabled_effect", "elm");
5777    else edje_object_signal_emit(it->edit_obj, "elm,state,emode_enabled", "elm");
5778
5779    if (it->disabled) edje_object_signal_emit(it->edit_obj, "elm,state,disabled", "elm");
5780    else edje_object_signal_emit(it->edit_obj, "elm,state,enabled", "elm");
5781
5782
5783    if ((it->wd->edit_mode))
5784      {
5785         if (it->itc->func.icon_get)
5786           {
5787              const Eina_List *l;
5788              const char *key;
5789
5790              if (it->renamed) edje_object_signal_emit(it->edit_obj, "elm,state,rename,enabled", "elm");
5791              it->icons = elm_widget_stringlist_get(edje_object_data_get(it->edit_obj, "edit_icons"));
5792              EINA_LIST_FOREACH(it->icons, l, key)
5793                {
5794                   Evas_Object *ic = it->itc->func.icon_get
5795                      ((void *)it->base.data, WIDGET(it), l->data);
5796
5797                   if (ic)
5798                     {
5799                        it->edit_icon_objs = eina_list_append(it->edit_icon_objs, ic);
5800                        edje_object_part_swallow(it->edit_obj, key, ic);
5801                        evas_object_show(ic);
5802                        elm_widget_sub_object_add(WIDGET(it), ic);
5803                        if (it->disabled)
5804                          elm_widget_disabled_set(ic, EINA_TRUE);
5805                     }
5806                }
5807           }
5808      }
5809    edje_object_part_swallow(it->edit_obj, "original_edc", VIEW(it));
5810    _effect_item_controls(it,it->scrl_x, it->scrl_y);
5811    evas_object_show(it->edit_obj);
5812
5813    it->effect_item_realized = EINA_TRUE;
5814    it->want_unrealize = EINA_FALSE;
5815 }
5816
5817 static void
5818 _effect_item_unrealize(Elm_Genlist_Item *it)
5819 {
5820    Evas_Object *icon;
5821
5822    if (!it->effect_item_realized) return;
5823    if (it->wd->reorder_it && it->wd->reorder_it == it) return;
5824
5825    edje_object_signal_emit(it->edit_obj, "elm,state,reorder_disable_effect", "elm");
5826    edje_object_signal_emit(it->edit_obj, "elm,state,sel,disable", "elm");
5827    edje_object_message_signal_process(it->edit_obj);
5828    edje_object_part_unswallow(it->edit_obj, VIEW(it));
5829    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
5830    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
5831    //   evas_object_smart_callback_call(it->edit_obj, "unrealized", it);
5832    //   _item_cache_add(it);
5833    evas_object_del(it->edit_obj);
5834    it->edit_obj = NULL;
5835    EINA_LIST_FREE(it->edit_icon_objs, icon)
5836       evas_object_del(icon);
5837
5838 //   edje_object_signal_emit(it->edit_obj, "elm,state,edit_end,disable", "elm");
5839    it->effect_item_realized = EINA_FALSE;
5840 }
5841
5842 /**
5843  * Get Genlist edit mode
5844  *
5845  * @param obj The genlist object
5846  * @return The edit mode status
5847  * (EINA_TRUE = edit mode, EINA_FALSE = normal mode
5848  *
5849  * @ingroup Genlist
5850  */
5851 EAPI Eina_Bool
5852 elm_genlist_edit_mode_get(const Evas_Object *obj)
5853 {
5854    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5855    Widget_Data *wd = elm_widget_data_get(obj);
5856    if (!wd) return EINA_FALSE;
5857
5858    if (wd->edit_mode) return EINA_TRUE;
5859    else return EINA_FALSE;
5860 }
5861
5862 /**
5863  * Set Genlist edit mode
5864  *
5865  * This sets Genlist edit mode.
5866  *
5867  * @param obj The Genlist object
5868  * @param emode ELM_GENLIST_EDIT_MODE_{NONE & REORDER & INSERT & DELETE & SELECT & SELECT_ALL}
5869  * @param edit_class Genlist edit class (Elm_Genlist_Edit_Class structure)
5870  *
5871  * @ingroup Genlist
5872  */
5873 EAPI void
5874 elm_genlist_edit_mode_set(Evas_Object *obj, Eina_Bool edit_mode)
5875 {
5876    ELM_CHECK_WIDTYPE(obj, widtype);
5877
5878    Item_Block *itb;
5879    Eina_List *l;
5880    Elm_Genlist_Item *it;
5881
5882    Widget_Data *wd = elm_widget_data_get(obj);
5883    if (!wd) return;
5884    if (wd->edit_mode == edit_mode) return;
5885
5886    wd->edit_mode = edit_mode;
5887    if (!wd->edit_mode)
5888      {
5889         EINA_INLIST_FOREACH(wd->blocks, itb)
5890           {
5891              if (itb->realized)
5892                {
5893                   EINA_LIST_FOREACH(itb->items, l, it)
5894                     {
5895                        if (it->flags != ELM_GENLIST_ITEM_GROUP && it->realized)
5896                          {
5897                             _effect_item_unrealize(it);
5898                          }
5899                     }
5900                }
5901           }
5902         _item_cache_zero(wd);
5903      }
5904    else
5905      {
5906
5907         EINA_INLIST_FOREACH(wd->blocks, itb)
5908           {
5909              if (itb->realized)
5910                {
5911                   EINA_LIST_FOREACH(itb->items, l, it)
5912                     {
5913                        if (it->flags != ELM_GENLIST_ITEM_GROUP && it->realized)
5914                          {
5915                             if(it->selected) _item_unselect(it);
5916                             if (it->itc->edit_item_style) _effect_item_realize(it, EINA_TRUE);
5917                          }
5918                     }
5919                 }
5920            }
5921       }
5922
5923    if (wd->calc_job) ecore_job_del(wd->calc_job);
5924    wd->calc_job = ecore_job_add(_calc_job, wd);
5925 }
5926
5927 /**
5928  * Set a given item's rename mode
5929  *
5930  * This renames the item's label from genlist
5931  *
5932  * @param it The item
5933  * @param renamed set if emode is EINA_TRUE, unset if emode is EINA_FALSE
5934  *
5935  * @ingroup Genlist
5936  */
5937 EAPI void
5938 elm_genlist_item_rename_mode_set(Elm_Genlist_Item *it, Eina_Bool renamed)
5939 {
5940    if (!it) return;
5941
5942    if (renamed)
5943      {
5944         _item_unrealize(it, EINA_FALSE);
5945         it->renamed = EINA_TRUE;
5946         it->wd->rename_it = it;
5947         it->nocache = EINA_TRUE;
5948         if (it->selected)  _item_unselect(it);
5949
5950         if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5951         it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
5952      }
5953    else
5954      {
5955         if (it->renamed)
5956           {
5957              it->renamed = EINA_FALSE;
5958              it->nocache = EINA_TRUE;
5959              it->wd->rename_it = NULL;
5960              _item_cache_zero(it->wd);
5961              elm_genlist_item_update(it);
5962           }
5963      }
5964 }
5965
5966 EAPI Eina_Bool
5967 elm_genlist_item_rename_mode_get(Elm_Genlist_Item *item)
5968 {
5969    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
5970    return item->renamed;
5971 }
5972
5973 EAPI void
5974 elm_genlist_item_no_select_mode_set(Elm_Genlist_Item *it,
5975                                     Eina_Bool    no_select)
5976 {
5977    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
5978    it->no_select = no_select;
5979 }
5980
5981 EAPI Eina_Bool
5982 elm_genlist_item_no_select_mode_get(const Elm_Genlist_Item *it)
5983 {
5984    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
5985    return it->no_select;
5986 }