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