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