elm genlist/gengrid: Applied genlist/gengrid icons -> contents changes
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_gen.h"
8
9 #define SWIPE_MOVES         12
10 #define MAX_ITEMS_PER_BLOCK 32
11 #define REORDER_EFFECT_TIME 0.5
12
13 #define ELM_GEN_SETUP(wd) \
14    (wd)->calc_cb = (Ecore_Cb)_calc_job; \
15    (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
16    (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
17
18
19 #define ELM_GEN_ITEM_SETUP(it) \
20    (it)->del_cb = (Ecore_Cb)_item_del; \
21    (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
22    (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
23    (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
24    (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
25
26 typedef struct _Item_Block  Item_Block;
27 typedef struct _Item_Cache  Item_Cache;
28
29 struct Elm_Gen_Item_Type
30 {
31    Elm_Gen_Item                 *it;
32    Item_Block                   *block;
33    Eina_List                    *items;
34    Evas_Coord                    w, h, minw, minh;
35    Elm_Gen_Item                 *group_item;
36    Elm_Genlist_Item_Flags        flags;
37    Eina_List                    *mode_labels, *mode_contents, *mode_states, *mode_content_objs;
38    Ecore_Timer                  *swipe_timer;
39    Evas_Coord                    scrl_x, scrl_y, old_scrl_y;
40
41    Elm_Gen_Item                 *rel;
42    Evas_Object                  *mode_view;
43    int                           expanded_depth;
44    int                           order_num_in;
45
46    Eina_Bool                     before : 1;
47
48    Eina_Bool                     want_realize : 1;
49    Eina_Bool                     expanded : 1;
50    Eina_Bool                     mincalcd : 1;
51    Eina_Bool                     queued : 1;
52    Eina_Bool                     showme : 1;
53    Eina_Bool                     updateme : 1;
54    Eina_Bool                     nocache : 1;
55    Eina_Bool                     stacking_even : 1;
56    Eina_Bool                     nostacking : 1;
57    Eina_Bool                     move_effect_enabled : 1;
58 };
59
60 struct _Widget_Data
61 {
62    Eina_Inlist_Sorted_State *state;
63    Evas_Object      *obj; /* the genlist object */
64    Evas_Object      *scr; /* a smart scroller object which is used internally in genlist */
65    Evas_Object      *pan_smart; /* "elm_genlist_pan" evas smart object. this is an extern pan of smart scroller(scr). */
66    Eina_List        *selected;
67    Eina_List        *group_items; /* list of groups index items */
68    Eina_Inlist      *items; /* inlist of all items */
69    Elm_Gen_Item     *reorder_it; /* item currently being repositioned */
70    Elm_Gen_Item     *last_selected_item;
71    Pan              *pan; /* pan_smart object's smart data */
72    Ecore_Job        *calc_job;
73    int               walking;
74    int               item_width, item_height;
75    int               group_item_width, group_item_height;
76    int               minw, minh;
77    long              count;
78    Evas_Coord        pan_x, pan_y;
79    Eina_Bool         reorder_mode : 1;
80    Eina_Bool         on_hold : 1;
81    Eina_Bool         multi : 1;
82    Eina_Bool         no_select : 1;
83    Eina_Bool         wasselected : 1;
84    Eina_Bool         always_select : 1;
85    Eina_Bool         clear_me : 1;
86    Eina_Bool         h_bounce : 1;
87    Eina_Bool         v_bounce : 1;
88    Ecore_Cb          del_cb, calc_cb, sizing_cb;
89    Ecore_Cb          clear_cb;
90    ////////////////////////////////////
91    Eina_Inlist      *blocks; /* inlist of all blocks. a block consists of a certain number of items. maximum number of items in a block is 'max_items_per_block'. */
92    Evas_Coord        reorder_old_pan_y, w, h, realminw, prev_viewport_w;
93    Ecore_Job        *update_job;
94    Ecore_Idle_Enterer *queue_idle_enterer;
95    Ecore_Idler        *must_recalc_idler;
96    Eina_List        *queue;
97    Elm_Gen_Item *show_item, *anchor_item, *mode_item, *reorder_rel, *expanded_item;
98    Eina_Inlist      *item_cache; /* an inlist of edje object it cache. */
99    Evas_Coord        anchor_y;
100    Evas_Coord        reorder_start_y; /* reorder it's initial y coordinate in the pan. */
101    Elm_List_Mode     mode;
102    Ecore_Timer      *multi_timer, *scr_hold_timer;
103    Ecore_Animator   *reorder_move_animator;
104    const char       *mode_type;
105    const char       *mode_item_style;
106    unsigned int      start_time;
107    Evas_Coord        prev_x, prev_y, prev_mx, prev_my;
108    Evas_Coord        cur_x, cur_y, cur_mx, cur_my;
109    Eina_Bool         mouse_down : 1;
110    Eina_Bool         multi_down : 1;
111    Eina_Bool         multi_timeout : 1;
112    Eina_Bool         multitouched : 1;
113    Eina_Bool         longpressed : 1;
114    Eina_Bool         bring_in : 1;
115    Eina_Bool         compress : 1;
116    Eina_Bool         height_for_width : 1;
117    Eina_Bool         homogeneous : 1;
118    Eina_Bool         swipe : 1;
119    Eina_Bool         reorder_pan_move : 1;
120    Eina_Bool         auto_scroll_enabled : 1;
121    Eina_Bool         pan_resized : 1;
122    struct
123    {
124       Evas_Coord x, y;
125    } history[SWIPE_MOVES];
126    int               multi_device;
127    int               item_cache_count;
128    int               item_cache_max; /* maximum number of cached items */
129    int               movements;
130    int               max_items_per_block; /* maximum number of items per block */
131    double            longpress_timeout; /* longpress timeout. this value comes from _elm_config by default. this can be changed by elm_genlist_longpress_timeout_set() */
132 };
133
134 struct _Item_Block
135 {
136    EINA_INLIST;
137    int          count;
138    int          num;
139    int          reorder_offset;
140    Widget_Data *wd;
141    Eina_List   *items;
142    Evas_Coord   x, y, w, h, minw, minh;
143    Eina_Bool    want_unrealize : 1;
144    Eina_Bool    realized : 1;
145    Eina_Bool    changed : 1;
146    Eina_Bool    updateme : 1;
147    Eina_Bool    showme : 1;
148    Eina_Bool    must_recalc : 1;
149 };
150
151 struct _Item_Cache
152 {
153    EINA_INLIST;
154
155    Evas_Object *base_view, *spacer;
156
157    const char  *item_style; // it->itc->item_style
158    Eina_Bool    tree : 1; // it->group
159    Eina_Bool    compress : 1; // it->wd->compress
160
161    Eina_Bool    selected : 1; // it->selected
162    Eina_Bool    disabled : 1; // it->disabled
163    Eina_Bool    expanded : 1; // it->item->expanded
164 };
165
166 static const char *widtype = NULL;
167 static void      _item_cache_zero(Widget_Data *wd);
168 static void      _del_hook(Evas_Object *obj);
169 static void      _mirrored_set(Evas_Object *obj,
170                                Eina_Bool    rtl);
171 static void      _theme_hook(Evas_Object *obj);
172 static void      _show_region_hook(void        *data,
173                                    Evas_Object *obj);
174 static void      _sizing_eval(Evas_Object *obj);
175 static void      _item_realize(Elm_Gen_Item *it,
176                                int               in,
177                                Eina_Bool         calc);
178 static void      _item_unrealize_cb(Elm_Gen_Item *it);
179 static void      _item_block_unrealize(Item_Block *itb);
180 static void      _calc_job(void *data);
181 static void      _on_focus_hook(void        *data,
182                                 Evas_Object *obj);
183 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
184 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
185 static Eina_Bool _item_single_select_up(Widget_Data *wd);
186 static Eina_Bool _item_single_select_down(Widget_Data *wd);
187 static Eina_Bool _event_hook(Evas_Object       *obj,
188                              Evas_Object       *src,
189                              Evas_Callback_Type type,
190                              void              *event_info);
191 static void      _signal_emit_hook(Evas_Object *obj,
192                                    const char *emission,
193                                    const char *source);
194 static Eina_Bool _deselect_all_items(Widget_Data *wd);
195 static void      _pan_calculate(Evas_Object *obj);
196 static void      _pan_max_get(Evas_Object *obj,
197                               Evas_Coord  *x,
198                               Evas_Coord  *y);
199 static void      _item_position(Elm_Gen_Item *it,
200                                 Evas_Object      *obj,
201                                 Evas_Coord        it_x,
202                                 Evas_Coord        it_y);
203 static void      _mode_item_realize(Elm_Gen_Item *it);
204 static void      _mode_item_unrealize(Elm_Gen_Item *it);
205 static void      _item_mode_set(Elm_Gen_Item *it);
206 static void      _item_mode_unset(Widget_Data *wd);
207 static void      _group_items_recalc(void *data);
208 static void      _item_move_after(Elm_Gen_Item *it,
209                                   Elm_Gen_Item *after);
210 static void      _item_move_before(Elm_Gen_Item *it,
211                                    Elm_Gen_Item *before);
212 static void      _item_auto_scroll(Widget_Data *wd);
213
214 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
215
216 static const char SIG_ACTIVATED[] = "activated";
217 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
218 static const char SIG_SELECTED[] = "selected";
219 static const char SIG_UNSELECTED[] = "unselected";
220 static const char SIG_EXPANDED[] = "expanded";
221 static const char SIG_CONTRACTED[] = "contracted";
222 static const char SIG_EXPAND_REQUEST[] = "expand,request";
223 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
224 static const char SIG_REALIZED[] = "realized";
225 static const char SIG_UNREALIZED[] = "unrealized";
226 static const char SIG_DRAG_START_UP[] = "drag,start,up";
227 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
228 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
229 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
230 static const char SIG_DRAG_STOP[] = "drag,stop";
231 static const char SIG_DRAG[] = "drag";
232 static const char SIG_LONGPRESSED[] = "longpressed";
233 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
234 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
235 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
236 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
237 static const char SIG_SCROLL_EDGE_TOP[] = "scroll,edge,top"; // TODO : remove this
238 static const char SIG_SCROLL_EDGE_BOTTOM[] = "scroll,edge,bottom"; // TODO : remove this
239 static const char SIG_SCROLL_EDGE_LEFT[] = "scroll,edge,left"; // TODO : remove this
240 static const char SIG_SCROLL_EDGE_RIGHT[] = "scroll,edge,right"; // TODO : remove this
241 static const char SIG_EDGE_TOP[] = "edge,top";
242 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
243 static const char SIG_EDGE_LEFT[] = "edge,left";
244 static const char SIG_EDGE_RIGHT[] = "edge,right";
245 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
246 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
247 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
248 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
249 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
250 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
251 static const char SIG_SWIPE[] = "swipe";
252 static const char SIG_MOVED[] = "moved";
253
254 static const Evas_Smart_Cb_Description _signals[] = {
255    {SIG_CLICKED_DOUBLE, ""},
256    {SIG_ACTIVATED, ""},
257    {SIG_SELECTED, ""},
258    {SIG_UNSELECTED, ""},
259    {SIG_EXPANDED, ""},
260    {SIG_CONTRACTED, ""},
261    {SIG_EXPAND_REQUEST, ""},
262    {SIG_CONTRACT_REQUEST, ""},
263    {SIG_REALIZED, ""},
264    {SIG_UNREALIZED, ""},
265    {SIG_DRAG_START_UP, ""},
266    {SIG_DRAG_START_DOWN, ""},
267    {SIG_DRAG_START_LEFT, ""},
268    {SIG_DRAG_START_RIGHT, ""},
269    {SIG_DRAG_STOP, ""},
270    {SIG_DRAG, ""},
271    {SIG_LONGPRESSED, ""},
272    {SIG_SCROLL_ANIM_START, ""},
273    {SIG_SCROLL_ANIM_STOP, ""},
274    {SIG_SCROLL_DRAG_START, ""},
275    {SIG_SCROLL_DRAG_STOP, ""},
276    {SIG_SCROLL_EDGE_TOP, ""},
277    {SIG_SCROLL_EDGE_BOTTOM, ""},
278    {SIG_SCROLL_EDGE_LEFT, ""},
279    {SIG_SCROLL_EDGE_RIGHT, ""},
280    {SIG_EDGE_TOP, ""},
281    {SIG_EDGE_BOTTOM, ""},
282    {SIG_EDGE_LEFT, ""},
283    {SIG_EDGE_RIGHT, ""},
284    {SIG_MULTI_SWIPE_LEFT, ""},
285    {SIG_MULTI_SWIPE_RIGHT, ""},
286    {SIG_MULTI_SWIPE_UP, ""},
287    {SIG_MULTI_SWIPE_DOWN, ""},
288    {SIG_MULTI_PINCH_OUT, ""},
289    {SIG_MULTI_PINCH_IN, ""},
290    {SIG_SWIPE, ""},
291    {SIG_MOVED, ""},
292    {NULL, NULL}
293 };
294
295 static Eina_Compare_Cb _elm_genlist_item_compare_cb;
296 static Eina_Compare_Cb _elm_genlist_item_compare_data_cb;
297
298 static Eina_Bool
299 _event_hook(Evas_Object       *obj,
300             Evas_Object       *src __UNUSED__,
301             Evas_Callback_Type type,
302             void              *event_info)
303 {
304    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
305    Evas_Event_Key_Down *ev = event_info;
306    Widget_Data *wd = elm_widget_data_get(obj);
307    Evas_Coord pan_max_x = 0, pan_max_y = 0;
308    if (!wd) return EINA_FALSE;
309    if (!wd->items) return EINA_FALSE;
310    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
311    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
312
313    Elm_Gen_Item *it = NULL;
314    Evas_Coord x = 0;
315    Evas_Coord y = 0;
316    Evas_Coord step_x = 0;
317    Evas_Coord step_y = 0;
318    Evas_Coord v_w = 0;
319    Evas_Coord v_h = 0;
320    Evas_Coord page_x = 0;
321    Evas_Coord page_y = 0;
322
323    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
324    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
325    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
326    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
327
328    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
329      {
330         x -= step_x;
331      }
332    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
333      {
334         x += step_x;
335      }
336    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
337      {
338         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
339              (_item_multi_select_up(wd)))
340             || (_item_single_select_up(wd)))
341           {
342              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
343              return EINA_TRUE;
344           }
345         else
346           y -= step_y;
347      }
348    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
349      {
350         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
351              (_item_multi_select_down(wd)))
352             || (_item_single_select_down(wd)))
353           {
354              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
355              return EINA_TRUE;
356           }
357         else
358           y += step_y;
359      }
360    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
361      {
362         it = elm_gen_first_item_get(obj);
363         elm_genlist_item_bring_in(it);
364         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
365         return EINA_TRUE;
366      }
367    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
368      {
369         it = elm_gen_last_item_get(obj);
370         elm_genlist_item_bring_in(it);
371         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
372         return EINA_TRUE;
373      }
374    else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
375      {
376         if (page_y < 0)
377           y -= -(page_y * v_h) / 100;
378         else
379           y -= page_y;
380      }
381    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
382      {
383         if (page_y < 0)
384           y += -(page_y * v_h) / 100;
385         else
386           y += page_y;
387      }
388    else if (!strcmp(ev->keyname, "Escape"))
389      {
390         if (!_deselect_all_items(wd)) return EINA_FALSE;
391         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
392         return EINA_TRUE;
393      }
394    else if (((!strcmp(ev->keyname, "Return")) ||
395             (!strcmp(ev->keyname, "KP_Enter")) ||
396             (!strcmp(ev->keyname, "space")))
397            && (!wd->multi) && (wd->selected))
398      {
399         it = elm_genlist_selected_item_get(obj);
400         elm_genlist_item_expanded_set(it,
401                                       !elm_genlist_item_expanded_get(it));
402         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
403      }
404    else return EINA_FALSE;
405
406    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
407    _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
408    if (x < 0) x = 0;
409    if (x > pan_max_x) x = pan_max_x;
410    if (y < 0) y = 0;
411    if (y > pan_max_y) y = pan_max_y;
412    elm_smart_scroller_child_pos_set(wd->scr, x, y);
413    return EINA_TRUE;
414 }
415
416 static Eina_Bool
417 _deselect_all_items(Widget_Data *wd)
418 {
419    if (!wd->selected) return EINA_FALSE;
420    while (wd->selected)
421      elm_gen_item_selected_set(wd->selected->data, EINA_FALSE);
422
423    return EINA_TRUE;
424 }
425
426 static Eina_Bool
427 _item_multi_select_up(Widget_Data *wd)
428 {
429    if (!wd->selected) return EINA_FALSE;
430    if (!wd->multi) return EINA_FALSE;
431
432    Elm_Gen_Item *prev = elm_gen_item_prev_get(wd->last_selected_item);
433    if (!prev) return EINA_TRUE;
434
435    if (elm_gen_item_selected_get(prev))
436      {
437         elm_gen_item_selected_set(wd->last_selected_item, EINA_FALSE);
438         wd->last_selected_item = prev;
439         elm_genlist_item_show(wd->last_selected_item);
440      }
441    else
442      {
443         elm_gen_item_selected_set(prev, EINA_TRUE);
444         elm_genlist_item_show(prev);
445      }
446    return EINA_TRUE;
447 }
448
449 static Eina_Bool
450 _item_multi_select_down(Widget_Data *wd)
451 {
452    if (!wd->selected) return EINA_FALSE;
453    if (!wd->multi) return EINA_FALSE;
454
455    Elm_Gen_Item *next = elm_gen_item_next_get(wd->last_selected_item);
456    if (!next) return EINA_TRUE;
457
458    if (elm_gen_item_selected_get(next))
459      {
460         elm_gen_item_selected_set(wd->last_selected_item, EINA_FALSE);
461         wd->last_selected_item = next;
462         elm_genlist_item_show(wd->last_selected_item);
463      }
464    else
465      {
466         elm_gen_item_selected_set(next, EINA_TRUE);
467         elm_genlist_item_show(next);
468      }
469    return EINA_TRUE;
470 }
471
472 static Eina_Bool
473 _item_single_select_up(Widget_Data *wd)
474 {
475    Elm_Gen_Item *prev;
476    if (!wd->selected)
477      {
478         prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
479         while ((prev) && (prev->delete_me))
480           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
481      }
482    else prev = elm_gen_item_prev_get(wd->last_selected_item);
483
484    if (!prev) return EINA_FALSE;
485
486    _deselect_all_items(wd);
487
488    elm_gen_item_selected_set(prev, EINA_TRUE);
489    elm_genlist_item_show(prev);
490    return EINA_TRUE;
491 }
492
493 static Eina_Bool
494 _item_single_select_down(Widget_Data *wd)
495 {
496    Elm_Gen_Item *next;
497    if (!wd->selected)
498      {
499         next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
500         while ((next) && (next->delete_me))
501           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
502      }
503    else next = elm_gen_item_next_get(wd->last_selected_item);
504
505    if (!next) return EINA_FALSE;
506
507    _deselect_all_items(wd);
508
509    elm_gen_item_selected_set(next, EINA_TRUE);
510    elm_genlist_item_show(next);
511    return EINA_TRUE;
512 }
513
514 static void
515 _on_focus_hook(void        *data __UNUSED__,
516                Evas_Object *obj)
517 {
518    Widget_Data *wd = elm_widget_data_get(obj);
519    if (!wd) return;
520    if (elm_widget_focus_get(obj))
521      {
522         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
523         evas_object_focus_set(wd->obj, EINA_TRUE);
524         if ((wd->selected) && (!wd->last_selected_item))
525           wd->last_selected_item = eina_list_data_get(wd->selected);
526      }
527    else
528      {
529         elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
530         evas_object_focus_set(wd->obj, EINA_FALSE);
531      }
532 }
533
534 static void
535 _del_hook(Evas_Object *obj)
536 {
537    Widget_Data *wd = elm_widget_data_get(obj);
538    if (!wd) return;
539    _item_cache_zero(wd);
540    if (wd->calc_job) ecore_job_del(wd->calc_job);
541    if (wd->update_job) ecore_job_del(wd->update_job);
542    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
543    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
544    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
545    if (wd->mode_type) eina_stringshare_del(wd->mode_type);
546    if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
547    free(wd);
548 }
549
550 static void
551 _del_pre_hook(Evas_Object *obj)
552 {
553    Widget_Data *wd = elm_widget_data_get(obj);
554    if (!wd) return;
555    elm_gen_clear(obj);
556    evas_object_del(wd->pan_smart);
557    wd->pan_smart = NULL;
558 }
559
560 static void
561 _mirrored_set(Evas_Object *obj,
562               Eina_Bool    rtl)
563 {
564    Widget_Data *wd = elm_widget_data_get(obj);
565    if (!wd) return;
566    _item_cache_zero(wd);
567    elm_smart_scroller_mirrored_set(wd->scr, rtl);
568 }
569
570 static void
571 _theme_hook(Evas_Object *obj)
572 {
573    Widget_Data *wd = elm_widget_data_get(obj);
574    Item_Block *itb;
575    if (!wd) return;
576    evas_event_freeze(evas_object_evas_get(wd->obj));
577    _item_cache_zero(wd);
578    _elm_widget_mirrored_reload(obj);
579    _mirrored_set(obj, elm_widget_mirrored_get(obj));
580    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
581                                        elm_widget_style_get(obj));
582    edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
583    wd->item_width = wd->item_height = 0;
584    wd->group_item_width = wd->group_item_height = 0;
585    wd->minw = wd->minh = wd->realminw = 0;
586    EINA_INLIST_FOREACH(wd->blocks, itb)
587      {
588         Eina_List *l;
589         Elm_Gen_Item *it;
590
591         if (itb->realized) _item_block_unrealize(itb);
592         EINA_LIST_FOREACH(itb->items, l, it)
593           it->item->mincalcd = EINA_FALSE;
594
595         itb->changed = EINA_TRUE;
596      }
597    if (wd->calc_job) ecore_job_del(wd->calc_job);
598    wd->calc_job = ecore_job_add(_calc_job, wd);
599    _sizing_eval(obj);
600    evas_event_thaw(evas_object_evas_get(wd->obj));
601    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
602 }
603
604 static void
605 _show_region_hook(void        *data,
606                   Evas_Object *obj)
607 {
608    Widget_Data *wd = elm_widget_data_get(data);
609    Evas_Coord x, y, w, h;
610    if (!wd) return;
611    elm_widget_show_region_get(obj, &x, &y, &w, &h);
612    //x & y are screen coordinates, Add with pan coordinates
613    x += wd->pan_x;
614    y += wd->pan_y;
615    elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
616 }
617
618 static void
619 _translate_hook(Evas_Object *obj)
620 {
621    evas_object_smart_callback_call(obj, "language,changed", NULL);
622 }
623
624 static void
625 _sizing_eval(Evas_Object *obj)
626 {
627    Widget_Data *wd = elm_widget_data_get(obj);
628    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
629    if (!wd) return;
630    evas_object_size_hint_min_get(wd->scr, &minw, &minh);
631    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
632    minh = -1;
633    if (wd->height_for_width)
634      {
635         Evas_Coord vw, vh;
636
637         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
638         if ((vw != 0) && (vw != wd->prev_viewport_w))
639           {
640              Item_Block *itb;
641
642              wd->prev_viewport_w = vw;
643              EINA_INLIST_FOREACH(wd->blocks, itb)
644                {
645                   itb->must_recalc = 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           }
650      }
651    if (wd->mode == ELM_LIST_LIMIT)
652      {
653         Evas_Coord vmw, vmh, vw, vh;
654
655         minw = wd->realminw;
656         maxw = -1;
657         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
658         if ((minw > 0) && (vw < minw)) vw = minw;
659         else if ((maxw > 0) && (vw > maxw))
660           vw = maxw;
661         edje_object_size_min_calc
662           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
663         minw = vmw + minw;
664      }
665    else
666      {
667         Evas_Coord vmw, vmh;
668
669         edje_object_size_min_calc
670           (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
671         minw = vmw;
672         minh = vmh;
673      }
674    evas_object_size_hint_min_set(obj, minw, minh);
675    evas_object_size_hint_max_set(obj, maxw, maxh);
676 }
677
678 static void
679 _signal_emit_hook(Evas_Object *obj,
680                   const char  *emission,
681                   const char  *source)
682 {
683    Widget_Data *wd = elm_widget_data_get(obj);
684    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
685                            emission, source);
686 }
687
688 static void
689 _item_highlight(Elm_Gen_Item *it)
690 {
691    const char *selectraise;
692    if ((it->wd->no_select) || (it->delete_me) || (it->highlighted) ||
693        (it->disabled) || (it->display_only) || (it->item->mode_view))
694      return;
695    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
696    selectraise = edje_object_data_get(VIEW(it), "selectraise");
697    if ((selectraise) && (!strcmp(selectraise, "on")))
698      {
699         evas_object_raise(VIEW(it));
700         if ((it->item->group_item) && (it->item->group_item->realized))
701           evas_object_raise(it->item->VIEW(group_item));
702      }
703    it->highlighted = EINA_TRUE;
704 }
705
706 static void
707 _item_unhighlight(Elm_Gen_Item *it)
708 {
709    if ((it->delete_me) || (!it->highlighted)) return;
710    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
711    if (!it->item->nostacking)
712      {
713        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even) evas_object_lower(VIEW(it));
714        else evas_object_raise(VIEW(it));
715      }
716    it->highlighted = EINA_FALSE;
717 }
718
719 static void
720 _item_block_del(Elm_Gen_Item *it)
721 {
722    Eina_Inlist *il;
723    Item_Block *itb = it->item->block;
724
725    itb->items = eina_list_remove(itb->items, it);
726    itb->count--;
727    itb->changed = EINA_TRUE;
728    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
729    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
730    if (itb->count < 1)
731      {
732         il = EINA_INLIST_GET(itb);
733         Item_Block *itbn = (Item_Block *)(il->next);
734         if (it->parent)
735           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
736         else
737           it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
738         free(itb);
739         if (itbn) itbn->changed = EINA_TRUE;
740      }
741    else
742      {
743         if (itb->count < itb->wd->max_items_per_block/2)
744           {
745              il = EINA_INLIST_GET(itb);
746              Item_Block *itbp = (Item_Block *)(il->prev);
747              Item_Block *itbn = (Item_Block *)(il->next);
748              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
749                {
750                   Elm_Gen_Item *it2;
751
752                   EINA_LIST_FREE(itb->items, it2)
753                     {
754                        it2->item->block = itbp;
755                        itbp->items = eina_list_append(itbp->items, it2);
756                        itbp->count++;
757                        itbp->changed = EINA_TRUE;
758                     }
759                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
760                                                       EINA_INLIST_GET(itb));
761                   free(itb);
762                }
763              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
764                {
765                   while (itb->items)
766                     {
767                        Eina_List *last = eina_list_last(itb->items);
768                        Elm_Gen_Item *it2 = last->data;
769
770                        it2->item->block = itbn;
771                        itb->items = eina_list_remove_list(itb->items, last);
772                        itbn->items = eina_list_prepend(itbn->items, it2);
773                        itbn->count++;
774                        itbn->changed = EINA_TRUE;
775                     }
776                   it->wd->blocks =
777                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
778                   free(itb);
779                }
780           }
781      }
782 }
783
784 static void
785 _item_del(Elm_Gen_Item *it)
786 {
787    Evas_Object *obj = WIDGET(it);
788
789    evas_event_freeze(evas_object_evas_get(obj));
790    elm_genlist_item_subitems_clear(it);
791    if (it->wd->show_item == it) it->wd->show_item = NULL;
792    if (it->realized) elm_gen_item_unrealize(it, EINA_FALSE);
793    if (it->item->block) _item_block_del(it);
794    if (it->item->queued)
795      it->wd->queue = eina_list_remove(it->wd->queue, it);
796    if (it->wd->anchor_item == it)
797      {
798         it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
799         if (!it->wd->anchor_item)
800           it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
801      }
802    if (it->parent)
803      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
804    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
805    elm_gen_item_del_serious(it);
806    evas_event_thaw(evas_object_evas_get(obj));
807    evas_event_thaw_eval(evas_object_evas_get(obj));
808 }
809
810 static void
811 _clear_cb(Widget_Data *wd)
812 {
813    wd->anchor_item = NULL;
814    while (wd->blocks)
815      {
816         Item_Block *itb = (Item_Block *)(wd->blocks);
817
818         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
819         if (itb->items) eina_list_free(itb->items);
820         free(itb);
821      }
822    if (wd->queue_idle_enterer)
823      {
824         ecore_idle_enterer_del(wd->queue_idle_enterer);
825         wd->queue_idle_enterer = NULL;
826      }
827    if (wd->must_recalc_idler)
828      {
829         ecore_idler_del(wd->must_recalc_idler);
830         wd->must_recalc_idler = NULL;
831      }
832    if (wd->queue) wd->queue = eina_list_free(wd->queue);
833    if (wd->reorder_move_animator)
834      {
835         ecore_animator_del(wd->reorder_move_animator);
836         wd->reorder_move_animator = NULL;
837      }
838    wd->show_item = NULL;
839    wd->reorder_old_pan_y = 0;
840 }
841
842 static void
843 _item_unselect(Elm_Gen_Item *it)
844 {
845    if ((it->delete_me) || (!it->selected)) return;
846    it->selected = EINA_FALSE;
847    it->wd->selected = eina_list_remove(it->wd->selected, it);
848    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
849 }
850
851 static void
852 _mouse_move(void        *data,
853             Evas        *evas __UNUSED__,
854             Evas_Object *obj,
855             void        *event_info)
856 {
857    Elm_Gen_Item *it = data;
858    Evas_Event_Mouse_Move *ev = event_info;
859    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
860    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
861
862    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
863      {
864         if (!it->wd->on_hold)
865           {
866              it->wd->on_hold = EINA_TRUE;
867              if (!it->wd->wasselected)
868                {
869                   _item_unhighlight(it);
870                   _item_unselect(it);
871                }
872           }
873      }
874    if (it->wd->multitouched)
875      {
876         it->wd->cur_x = ev->cur.canvas.x;
877         it->wd->cur_y = ev->cur.canvas.y;
878         return;
879      }
880    if ((it->dragging) && (it->down))
881      {
882         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
883         else
884           {
885              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
886              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
887              if (abs((it->wd->history[it->wd->movements].x -
888                       it->wd->history[0].x)) > 40)
889                it->wd->swipe = EINA_TRUE;
890              else
891                it->wd->movements++;
892           }
893         if (it->long_timer)
894           {
895              ecore_timer_del(it->long_timer);
896              it->long_timer = NULL;
897           }
898         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
899         return;
900      }
901    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
902      {
903         if (it->long_timer)
904           {
905              ecore_timer_del(it->long_timer);
906              it->long_timer = NULL;
907           }
908         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
909           {
910              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
911              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
912
913              if (!it->wd->reorder_start_y)
914                it->wd->reorder_start_y = it->item->block->y + it->y;
915
916              if (it_scrl_y < oy)
917                y_pos = oy;
918              else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
919                y_pos = oy + oh - it->wd->reorder_it->item->h;
920              else
921                y_pos = it_scrl_y;
922
923              _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
924
925              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
926              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
927           }
928         return;
929      }
930    if (!it->display_only)
931      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
932    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
933    x = ev->cur.canvas.x - x;
934    y = ev->cur.canvas.y - y;
935    dx = x - it->dx;
936    adx = dx;
937    if (adx < 0) adx = -dx;
938    dy = y - it->dy;
939    ady = dy;
940    if (ady < 0) ady = -dy;
941    minw /= 2;
942    minh /= 2;
943    if ((adx > minw) || (ady > minh))
944      {
945         it->dragging = EINA_TRUE;
946         if (it->long_timer)
947           {
948              ecore_timer_del(it->long_timer);
949              it->long_timer = NULL;
950           }
951         if (!it->wd->wasselected)
952           {
953              _item_unhighlight(it);
954              _item_unselect(it);
955           }
956         if (dy < 0)
957           {
958              if (ady > adx)
959                evas_object_smart_callback_call(WIDGET(it),
960                                                SIG_DRAG_START_UP, it);
961              else
962                {
963                   if (dx < 0)
964                     evas_object_smart_callback_call(WIDGET(it),
965                                                     SIG_DRAG_START_LEFT, it);
966                   else
967                     evas_object_smart_callback_call(WIDGET(it),
968                                                     SIG_DRAG_START_RIGHT, it);
969                }
970           }
971         else
972           {
973              if (ady > adx)
974                evas_object_smart_callback_call(WIDGET(it),
975                                                SIG_DRAG_START_DOWN, it);
976              else
977                {
978                   if (dx < 0)
979                     evas_object_smart_callback_call(WIDGET(it),
980                                                     SIG_DRAG_START_LEFT, it);
981                   else
982                     evas_object_smart_callback_call(WIDGET(it),
983                                                     SIG_DRAG_START_RIGHT, it);
984                }
985           }
986      }
987 }
988
989 static Eina_Bool
990 _long_press(void *data)
991 {
992    Elm_Gen_Item *it = data, *it_tmp;
993    Eina_List *list, *l;
994
995    it->long_timer = NULL;
996    if ((it->disabled) || (it->dragging) || (it->display_only))
997      return ECORE_CALLBACK_CANCEL;
998    it->wd->longpressed = EINA_TRUE;
999    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1000    if ((it->wd->reorder_mode) && (it->item->flags != ELM_GENLIST_ITEM_GROUP))
1001      {
1002         it->wd->reorder_it = it;
1003         it->wd->reorder_start_y = 0;
1004
1005         evas_object_raise(VIEW(it));
1006         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1007         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1008
1009         list = elm_genlist_realized_items_get(it->wd->obj);
1010         EINA_LIST_FOREACH(list, l, it_tmp)
1011           {
1012              if (it != it_tmp) _item_unselect(it_tmp);
1013           }
1014         if (elm_genlist_item_expanded_get(it))
1015           {
1016              elm_genlist_item_expanded_set(it, EINA_FALSE);
1017              return ECORE_CALLBACK_RENEW;
1018           }
1019         edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1020      }
1021    return ECORE_CALLBACK_CANCEL;
1022 }
1023
1024 static void
1025 _swipe(Elm_Gen_Item *it)
1026 {
1027    int i, sum = 0;
1028
1029    if (!it) return;
1030    if ((it->display_only) || (it->disabled)) return;
1031    it->wd->swipe = EINA_FALSE;
1032    for (i = 0; i < it->wd->movements; i++)
1033      {
1034         sum += it->wd->history[i].x;
1035         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1036      }
1037
1038    sum /= it->wd->movements;
1039    if (abs(sum - it->wd->history[0].x) <= 10) return;
1040    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1041 }
1042
1043 static Eina_Bool
1044 _swipe_cancel(void *data)
1045 {
1046    Elm_Gen_Item *it = data;
1047
1048    if (!it) return ECORE_CALLBACK_CANCEL;
1049    it->wd->swipe = EINA_FALSE;
1050    it->wd->movements = 0;
1051    return ECORE_CALLBACK_RENEW;
1052 }
1053
1054 static Eina_Bool
1055 _multi_cancel(void *data)
1056 {
1057    Widget_Data *wd = data;
1058
1059    if (!wd) return ECORE_CALLBACK_CANCEL;
1060    wd->multi_timeout = EINA_TRUE;
1061    return ECORE_CALLBACK_RENEW;
1062 }
1063
1064 static void
1065 _multi_touch_gesture_eval(void *data)
1066 {
1067    Elm_Gen_Item *it = data;
1068
1069    it->wd->multitouched = EINA_FALSE;
1070    if (it->wd->multi_timer)
1071      {
1072         ecore_timer_del(it->wd->multi_timer);
1073         it->wd->multi_timer = NULL;
1074      }
1075    if (it->wd->multi_timeout)
1076      {
1077         it->wd->multi_timeout = EINA_FALSE;
1078         return;
1079      }
1080
1081    Evas_Coord minw = 0, minh = 0;
1082    Evas_Coord off_x, off_y, off_mx, off_my;
1083
1084    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1085    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1086    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1087    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1088    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1089
1090    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1091      {
1092         if ((off_x + off_mx) > (off_y + off_my))
1093           {
1094              if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1095                evas_object_smart_callback_call(WIDGET(it),
1096                                                SIG_MULTI_SWIPE_RIGHT, it);
1097              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1098                evas_object_smart_callback_call(WIDGET(it),
1099                                                SIG_MULTI_SWIPE_LEFT, it);
1100              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1101                evas_object_smart_callback_call(WIDGET(it),
1102                                                SIG_MULTI_PINCH_OUT, it);
1103              else
1104                evas_object_smart_callback_call(WIDGET(it),
1105                                                SIG_MULTI_PINCH_IN, it);
1106           }
1107         else
1108           {
1109              if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1110                evas_object_smart_callback_call(WIDGET(it),
1111                                                SIG_MULTI_SWIPE_DOWN, it);
1112              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1113                evas_object_smart_callback_call(WIDGET(it),
1114                                                SIG_MULTI_SWIPE_UP, it);
1115              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1116                evas_object_smart_callback_call(WIDGET(it),
1117                                                SIG_MULTI_PINCH_OUT, it);
1118              else
1119                evas_object_smart_callback_call(WIDGET(it),
1120                                                SIG_MULTI_PINCH_IN, it);
1121           }
1122      }
1123    it->wd->multi_timeout = EINA_FALSE;
1124 }
1125
1126 static void
1127 _multi_down(void        *data,
1128             Evas        *evas __UNUSED__,
1129             Evas_Object *obj __UNUSED__,
1130             void        *event_info)
1131 {
1132    Elm_Gen_Item *it = data;
1133    Evas_Event_Multi_Down *ev = event_info;
1134
1135    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1136    it->wd->multi_device = ev->device;
1137    it->wd->multi_down = EINA_TRUE;
1138    it->wd->multitouched = EINA_TRUE;
1139    it->wd->prev_mx = ev->canvas.x;
1140    it->wd->prev_my = ev->canvas.y;
1141    if (!it->wd->wasselected)
1142      {
1143         _item_unhighlight(it);
1144         _item_unselect(it);
1145      }
1146    it->wd->wasselected = EINA_FALSE;
1147    it->wd->longpressed = EINA_FALSE;
1148    if (it->long_timer)
1149      {
1150         ecore_timer_del(it->long_timer);
1151         it->long_timer = NULL;
1152      }
1153    if (it->dragging)
1154      {
1155         it->dragging = EINA_FALSE;
1156         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1157      }
1158    if (it->item->swipe_timer)
1159      {
1160         ecore_timer_del(it->item->swipe_timer);
1161         it->item->swipe_timer = NULL;
1162      }
1163    if (it->wd->on_hold)
1164      {
1165         it->wd->swipe = EINA_FALSE;
1166         it->wd->movements = 0;
1167         it->wd->on_hold = EINA_FALSE;
1168      }
1169 }
1170
1171 static void
1172 _multi_up(void        *data,
1173           Evas        *evas __UNUSED__,
1174           Evas_Object *obj __UNUSED__,
1175           void        *event_info)
1176 {
1177    Elm_Gen_Item *it = data;
1178    Evas_Event_Multi_Up *ev = event_info;
1179
1180    if (it->wd->multi_device != ev->device) return;
1181    it->wd->multi_device = 0;
1182    it->wd->multi_down = EINA_FALSE;
1183    if (it->wd->mouse_down) return;
1184    _multi_touch_gesture_eval(data);
1185 }
1186
1187 static void
1188 _multi_move(void        *data,
1189             Evas        *evas __UNUSED__,
1190             Evas_Object *obj __UNUSED__,
1191             void        *event_info)
1192 {
1193    Elm_Gen_Item *it = data;
1194    Evas_Event_Multi_Move *ev = event_info;
1195
1196    if (it->wd->multi_device != ev->device) return;
1197    it->wd->cur_mx = ev->cur.canvas.x;
1198    it->wd->cur_my = ev->cur.canvas.y;
1199 }
1200
1201 static void
1202 _mouse_down(void        *data,
1203             Evas        *evas __UNUSED__,
1204             Evas_Object *obj,
1205             void        *event_info)
1206 {
1207    Elm_Gen_Item *it = data;
1208    Evas_Event_Mouse_Down *ev = event_info;
1209    Evas_Coord x, y;
1210
1211    if (ev->button != 1) return;
1212    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1213      {
1214         it->wd->on_hold = EINA_TRUE;
1215      }
1216
1217    it->down = EINA_TRUE;
1218    it->dragging = EINA_FALSE;
1219    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1220    it->dx = ev->canvas.x - x;
1221    it->dy = ev->canvas.y - y;
1222    it->wd->mouse_down = EINA_TRUE;
1223    if (!it->wd->multitouched)
1224      {
1225         it->wd->prev_x = ev->canvas.x;
1226         it->wd->prev_y = ev->canvas.y;
1227         it->wd->multi_timeout = EINA_FALSE;
1228         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1229         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1230      }
1231    it->wd->longpressed = EINA_FALSE;
1232    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1233    else it->wd->on_hold = EINA_FALSE;
1234    if (it->wd->on_hold) return;
1235    it->wd->wasselected = it->selected;
1236    _item_highlight(it);
1237    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1238      if ((!it->disabled) && (!it->display_only))
1239        {
1240           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1241           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1242        }
1243    if (it->long_timer) ecore_timer_del(it->long_timer);
1244    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1245    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1246    if (it->realized)
1247      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1248                                       it);
1249    else
1250      it->long_timer = NULL;
1251    it->wd->swipe = EINA_FALSE;
1252    it->wd->movements = 0;
1253 }
1254
1255 static void
1256 _mouse_up(void        *data,
1257           Evas        *evas __UNUSED__,
1258           Evas_Object *obj __UNUSED__,
1259           void        *event_info)
1260 {
1261    Elm_Gen_Item *it = data;
1262    Evas_Event_Mouse_Up *ev = event_info;
1263    Eina_Bool dragged = EINA_FALSE;
1264
1265    if (ev->button != 1) return;
1266    it->down = EINA_FALSE;
1267    it->wd->mouse_down = EINA_FALSE;
1268    if (it->wd->multitouched)
1269      {
1270         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1271         if (it->wd->multi_down) return;
1272         _multi_touch_gesture_eval(data);
1273         return;
1274      }
1275    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1276    else it->wd->on_hold = EINA_FALSE;
1277    if (it->long_timer)
1278      {
1279         ecore_timer_del(it->long_timer);
1280         it->long_timer = NULL;
1281      }
1282    if (it->dragging)
1283      {
1284         it->dragging = EINA_FALSE;
1285         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1286         dragged = 1;
1287      }
1288    if (it->item->swipe_timer)
1289      {
1290         ecore_timer_del(it->item->swipe_timer);
1291         it->item->swipe_timer = NULL;
1292      }
1293    if (it->wd->multi_timer)
1294      {
1295         ecore_timer_del(it->wd->multi_timer);
1296         it->wd->multi_timer = NULL;
1297         it->wd->multi_timeout = EINA_FALSE;
1298      }
1299    if (it->wd->on_hold)
1300      {
1301         if (it->wd->swipe) _swipe(data);
1302         it->wd->longpressed = EINA_FALSE;
1303         it->wd->on_hold = EINA_FALSE;
1304         return;
1305      }
1306    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1307      {
1308         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1309
1310         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1311           {
1312              if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1313                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1314              else
1315                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1316           }
1317         else
1318           {
1319              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1320              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1321           }
1322         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1323         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1324         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1325         elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1326      }
1327    if (it->wd->longpressed)
1328      {
1329         it->wd->longpressed = EINA_FALSE;
1330         if (!it->wd->wasselected)
1331           {
1332              _item_unhighlight(it);
1333              _item_unselect(it);
1334           }
1335         it->wd->wasselected = EINA_FALSE;
1336         return;
1337      }
1338    if (dragged)
1339      {
1340         if (it->want_unrealize)
1341           {
1342              elm_gen_item_unrealize(it, EINA_FALSE);
1343              if (it->item->block->want_unrealize)
1344                _item_block_unrealize(it->item->block);
1345           }
1346      }
1347    if ((it->disabled) || (dragged) || (it->display_only)) return;
1348    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1349    if (it->wd->multi)
1350      {
1351         if (!it->selected)
1352           {
1353              _item_highlight(it);
1354              it->sel_cb(it);
1355           }
1356         else
1357           {
1358              _item_unhighlight(it);
1359              _item_unselect(it);
1360           }
1361      }
1362    else
1363      {
1364         if (!it->selected)
1365           {
1366              Widget_Data *wd = it->wd;
1367              if (wd)
1368                {
1369                   while (wd->selected)
1370                     {
1371                        _item_unhighlight(wd->selected->data);
1372                        _item_unselect(wd->selected->data);
1373                     }
1374                }
1375           }
1376         else
1377           {
1378              const Eina_List *l, *l_next;
1379              Elm_Gen_Item *it2;
1380
1381              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1382                 if (it2 != it)
1383                   {
1384                      _item_unhighlight(it2);
1385                      _item_unselect(it2);
1386                   }
1387              //_item_highlight(it);
1388              //_item_select(it);
1389           }
1390         _item_highlight(it);
1391         it->sel_cb(it);
1392      }
1393 }
1394
1395 static void
1396 _signal_expand_toggle(void        *data,
1397                       Evas_Object *obj __UNUSED__,
1398                       const char  *emission __UNUSED__,
1399                       const char  *source __UNUSED__)
1400 {
1401    Elm_Gen_Item *it = data;
1402
1403    if (it->item->expanded)
1404      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1405    else
1406      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1407 }
1408
1409 static void
1410 _signal_expand(void        *data,
1411                Evas_Object *obj __UNUSED__,
1412                const char  *emission __UNUSED__,
1413                const char  *source __UNUSED__)
1414 {
1415    Elm_Gen_Item *it = data;
1416
1417    if (!it->item->expanded)
1418      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1419 }
1420
1421 static void
1422 _signal_contract(void        *data,
1423                  Evas_Object *obj __UNUSED__,
1424                  const char  *emission __UNUSED__,
1425                  const char  *source __UNUSED__)
1426 {
1427    Elm_Gen_Item *it = data;
1428
1429    if (it->item->expanded)
1430      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1431 }
1432
1433 static Eina_Bool
1434 _scr_hold_timer_cb(void *data)
1435 {
1436    if (!data) return ECORE_CALLBACK_CANCEL;
1437    Widget_Data *wd = data;
1438    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1439    wd->scr_hold_timer = NULL;
1440    return ECORE_CALLBACK_CANCEL;
1441 }
1442
1443 static void
1444 _mode_finished_signal_cb(void        *data,
1445                          Evas_Object *obj,
1446                          const char  *emission __UNUSED__,
1447                          const char  *source __UNUSED__)
1448 {
1449    if (!data) return;
1450    if (!obj) return;
1451    Elm_Gen_Item *it = data;
1452    if ((it->delete_me) || (!it->realized) || (!it->item->mode_view)) return;
1453    char buf[1024];
1454    Evas *te = evas_object_evas_get(obj);
1455
1456    evas_event_freeze(te);
1457    it->item->nocache = EINA_FALSE;
1458    _mode_item_unrealize(it);
1459    if (it->item->group_item)
1460      evas_object_raise(it->item->VIEW(group_item));
1461    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type);
1462    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1463    evas_event_thaw(te);
1464    evas_event_thaw_eval(te);
1465 }
1466
1467 static void
1468 _item_cache_clean(Widget_Data *wd)
1469 {
1470    evas_event_freeze(evas_object_evas_get(wd->obj));
1471    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1472      {
1473         Item_Cache *itc;
1474
1475         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1476         wd->item_cache = eina_inlist_remove(wd->item_cache,
1477                                             wd->item_cache->last);
1478         wd->item_cache_count--;
1479         if (itc->spacer) evas_object_del(itc->spacer);
1480         if (itc->base_view) evas_object_del(itc->base_view);
1481         if (itc->item_style) eina_stringshare_del(itc->item_style);
1482         free(itc);
1483      }
1484    evas_event_thaw(evas_object_evas_get(wd->obj));
1485    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1486 }
1487
1488 static void
1489 _item_cache_zero(Widget_Data *wd)
1490 {
1491    int pmax = wd->item_cache_max;
1492    wd->item_cache_max = 0;
1493    _item_cache_clean(wd);
1494    wd->item_cache_max = pmax;
1495 }
1496
1497 static void
1498 _item_cache_add(Elm_Gen_Item *it)
1499 {
1500    Item_Cache *itc;
1501
1502    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1503    if (it->wd->item_cache_max <= 0)
1504      {
1505         evas_object_del(VIEW(it));
1506         VIEW(it) = NULL;
1507         evas_object_del(it->spacer);
1508         it->spacer = NULL;
1509         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1510         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1511         return;
1512      }
1513
1514    it->wd->item_cache_count++;
1515    itc = calloc(1, sizeof(Item_Cache));
1516    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1517                                             EINA_INLIST_GET(itc));
1518    itc->spacer = it->spacer;
1519    it->spacer = NULL;
1520    itc->base_view = VIEW(it);
1521    VIEW(it) = NULL;
1522    evas_object_hide(itc->base_view);
1523    evas_object_move(itc->base_view, -9999, -9999);
1524    itc->item_style = eina_stringshare_add(it->itc->item_style);
1525    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) itc->tree = 1;
1526    itc->compress = (it->wd->compress);
1527    itc->selected = it->selected;
1528    itc->disabled = it->disabled;
1529    itc->expanded = it->item->expanded;
1530    if (it->long_timer)
1531      {
1532         ecore_timer_del(it->long_timer);
1533         it->long_timer = NULL;
1534      }
1535    if (it->item->swipe_timer)
1536      {
1537         ecore_timer_del(it->item->swipe_timer);
1538         it->item->swipe_timer = NULL;
1539      }
1540    // FIXME: other callbacks?
1541    edje_object_signal_callback_del_full(itc->base_view,
1542                                         "elm,action,expand,toggle",
1543                                         "elm", _signal_expand_toggle, it);
1544    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1545                                         "elm",
1546                                         _signal_expand, it);
1547    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1548                                         "elm", _signal_contract, it);
1549    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_DOWN,
1550                                        _mouse_down, it);
1551    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_UP,
1552                                        _mouse_up, it);
1553    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MOUSE_MOVE,
1554                                        _mouse_move, it);
1555    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_DOWN,
1556                                        _multi_down, it);
1557    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_UP,
1558                                        _multi_up, it);
1559    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
1560                                        _multi_move, it);
1561    _item_cache_clean(it->wd);
1562    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1563    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1564 }
1565
1566 static Item_Cache *
1567 _item_cache_find(Elm_Gen_Item *it)
1568 {
1569    Item_Cache *itc;
1570    Eina_Bool tree = 0;
1571
1572    if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS) tree = 1;
1573    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1574      {
1575         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1576           continue;
1577         if ((itc->tree == tree) &&
1578             (itc->compress == it->wd->compress) &&
1579             (!strcmp(it->itc->item_style, itc->item_style)))
1580           {
1581              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1582                                                      EINA_INLIST_GET(itc));
1583              it->wd->item_cache_count--;
1584              return itc;
1585           }
1586      }
1587    return NULL;
1588 }
1589
1590 static void
1591 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1592 {
1593    if (!it->item->nostacking)
1594      {
1595         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1596           evas_object_lower(VIEW(it));
1597         else
1598           evas_object_raise(VIEW(it));
1599      }
1600
1601    if (it->item->order_num_in & 0x1)
1602      edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1603    else
1604      edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1605 }
1606
1607 static void
1608 _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1609 {
1610    if (itc)
1611      {
1612         if (it->selected != itc->selected)
1613           {
1614              if (it->selected)
1615                edje_object_signal_emit(VIEW(it),
1616                                        "elm,state,selected", "elm");
1617           }
1618         if (it->disabled != itc->disabled)
1619           {
1620              if (it->disabled)
1621                edje_object_signal_emit(VIEW(it),
1622                                        "elm,state,disabled", "elm");
1623           }
1624         if (it->item->expanded != itc->expanded)
1625           {
1626              if (it->item->expanded)
1627                edje_object_signal_emit(VIEW(it),
1628                                        "elm,state,expanded", "elm");
1629           }
1630      }
1631    else
1632      {
1633         if (it->selected)
1634           edje_object_signal_emit(VIEW(it),
1635                                   "elm,state,selected", "elm");
1636         if (it->disabled)
1637           edje_object_signal_emit(VIEW(it),
1638                                   "elm,state,disabled", "elm");
1639         if (it->item->expanded)
1640           edje_object_signal_emit(VIEW(it),
1641                                   "elm,state,expanded", "elm");
1642      }
1643 }
1644
1645 static void
1646 _item_cache_free(Item_Cache *itc)
1647 {
1648    if (itc->spacer) evas_object_del(itc->spacer);
1649    if (itc->base_view) evas_object_del(itc->base_view);
1650    if (itc->item_style) eina_stringshare_del(itc->item_style);
1651    free(itc);
1652 }
1653
1654 static void
1655 _item_del_hook(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1656 {
1657    Elm_Gen_Item *it = event_info;
1658    if (!it) return;
1659    if (it->wd->last_selected_item == it)
1660      it->wd->last_selected_item = NULL;
1661 }
1662
1663 static void
1664 _item_label_realize(Elm_Gen_Item *it,
1665                     Evas_Object *target,
1666                     Eina_List **source)
1667 {
1668    if (it->itc->func.label_get)
1669      {
1670         const Eina_List *l;
1671         const char *key;
1672
1673         *source = elm_widget_stringlist_get(edje_object_data_get(target, "labels"));
1674         EINA_LIST_FOREACH(*source, l, key)
1675           {
1676              char *s = it->itc->func.label_get
1677                 ((void *)it->base.data, WIDGET(it), key);
1678
1679              if (s)
1680                {
1681                   edje_object_part_text_set(target, key, s);
1682                   free(s);
1683                }
1684              else
1685                {
1686                   edje_object_part_text_set(target, key, "");
1687                }
1688           }
1689      }
1690 }
1691
1692 static Eina_List *
1693 _item_content_realize(Elm_Gen_Item *it,
1694                    Evas_Object *target,
1695                    Eina_List **source)
1696 {
1697    Eina_List *res = NULL;
1698
1699    if (it->itc->func.content_get)
1700      {
1701         const Eina_List *l;
1702         const char *key;
1703         Evas_Object *ic = NULL;
1704
1705         *source = elm_widget_stringlist_get(edje_object_data_get(target, "contents"));
1706         EINA_LIST_FOREACH(*source, l, key)
1707           {
1708              if (it->itc->func.content_get)
1709                ic = it->itc->func.content_get
1710                   ((void *)it->base.data, WIDGET(it), key);
1711              if (ic)
1712                {
1713                   res = eina_list_append(res, ic);
1714                   edje_object_part_swallow(target, key, ic);
1715                   evas_object_show(ic);
1716                   elm_widget_sub_object_add(WIDGET(it), ic);
1717                   if (it->disabled)
1718                     elm_widget_disabled_set(ic, EINA_TRUE);
1719                }
1720           }
1721      }
1722
1723    return res;
1724 }
1725
1726 static void
1727 _item_state_realize(Elm_Gen_Item *it,
1728                     Evas_Object *target,
1729                     Eina_List **source)
1730 {
1731    if (it->itc->func.state_get)
1732      {
1733         const Eina_List *l;
1734         const char *key;
1735         char buf[4096];
1736
1737         *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
1738         EINA_LIST_FOREACH(*source, l, key)
1739           {
1740              Eina_Bool on = it->itc->func.state_get
1741                 ((void *)it->base.data, WIDGET(it), key);
1742
1743              if (on)
1744                {
1745                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1746                   edje_object_signal_emit(target, buf, "elm");
1747                }
1748              else
1749                {
1750                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
1751                   edje_object_signal_emit(target, buf, "elm");
1752                }
1753           }
1754      }
1755 }
1756
1757 static void
1758 _item_realize(Elm_Gen_Item *it,
1759               int               in,
1760               Eina_Bool         calc)
1761 {
1762    Elm_Gen_Item *it2;
1763    const char *treesize;
1764    char buf[1024];
1765    int depth, tsize = 20;
1766    Item_Cache *itc = NULL;
1767
1768    if (it->delete_me) return;
1769    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
1770    if (it->realized)
1771      {
1772         if (it->item->order_num_in != in)
1773           {
1774              it->item->order_num_in = in;
1775              _elm_genlist_item_odd_even_update(it);
1776              _elm_genlist_item_state_update(it, NULL);
1777           }
1778         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1779         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1780         return;
1781      }
1782    it->item->order_num_in = in;
1783
1784    if (it->item->nocache)
1785      it->item->nocache = EINA_FALSE;
1786    else
1787      itc = _item_cache_find(it);
1788    if (itc)
1789      {
1790         VIEW(it) = itc->base_view;
1791         itc->base_view = NULL;
1792         it->spacer = itc->spacer;
1793         itc->spacer = NULL;
1794      }
1795    else
1796      {
1797         const char *stacking_even;
1798         const char *stacking;
1799
1800         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
1801         edje_object_scale_set(VIEW(it),
1802                               elm_widget_scale_get(WIDGET(it)) *
1803                               _elm_config->scale);
1804         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
1805         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
1806
1807         if (it->item->flags & ELM_GENLIST_ITEM_SUBITEMS)
1808           strncpy(buf, "tree", sizeof(buf));
1809         else strncpy(buf, "item", sizeof(buf));
1810         if (it->wd->compress)
1811           strncat(buf, "_compress", sizeof(buf) - strlen(buf));
1812
1813         strncat(buf, "/", sizeof(buf) - strlen(buf));
1814         strncat(buf, it->itc->item_style, sizeof(buf) - strlen(buf));
1815
1816         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
1817                               elm_widget_style_get(WIDGET(it)));
1818
1819         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1820         if (!stacking_even) stacking_even = "above";
1821         it->item->stacking_even = !!strcmp("above", stacking_even);
1822
1823         stacking = edje_object_data_get(VIEW(it), "stacking");
1824         if (!stacking) stacking = "yes";
1825         it->item->nostacking = !!strcmp("yes", stacking);
1826
1827         edje_object_mirrored_set(VIEW(it),
1828                                  elm_widget_mirrored_get(WIDGET(it)));
1829         it->spacer =
1830           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1831         evas_object_color_set(it->spacer, 0, 0, 0, 0);
1832         elm_widget_sub_object_add(WIDGET(it), it->spacer);
1833      }
1834
1835    _elm_genlist_item_odd_even_update(it);
1836
1837    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
1838      {
1839         if (it2->parent->item->flags != ELM_GENLIST_ITEM_GROUP) depth += 1;
1840      }
1841    it->item->expanded_depth = depth;
1842    treesize = edje_object_data_get(VIEW(it), "treesize");
1843    if (treesize) tsize = atoi(treesize);
1844    evas_object_size_hint_min_set(it->spacer,
1845                                  (depth * tsize) * _elm_config->scale, 1);
1846    edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1847    if (!calc)
1848      {
1849         edje_object_signal_callback_add(VIEW(it),
1850                                         "elm,action,expand,toggle",
1851                                         "elm", _signal_expand_toggle, it);
1852         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
1853                                         "elm", _signal_expand, it);
1854         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
1855                                         "elm", _signal_contract, it);
1856         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1857                                        _mouse_down, it);
1858         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1859                                        _mouse_up, it);
1860         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1861                                        _mouse_move, it);
1862         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_DOWN,
1863                                        _multi_down, it);
1864         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_UP,
1865                                        _multi_up, it);
1866         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MULTI_MOVE,
1867                                        _multi_move, it);
1868
1869         _elm_genlist_item_state_update(it, itc);
1870      }
1871
1872    if ((calc) && (it->wd->homogeneous) &&
1873        ((it->wd->item_width) ||
1874         ((it->wd->item_width) && (it->wd->group_item_width))))
1875      {
1876         /* homogenous genlist shortcut */
1877         if (!it->item->mincalcd)
1878           {
1879              if (it->item->flags & ELM_GENLIST_ITEM_GROUP)
1880                {
1881                   it->item->w = it->item->minw = it->wd->group_item_width;
1882                   it->item->h = it->item->minh = it->wd->group_item_height;
1883                }
1884              else
1885                {
1886                   it->item->w = it->item->minw = it->wd->item_width;
1887                   it->item->h = it->item->minh = it->wd->item_height;
1888                }
1889              it->item->mincalcd = EINA_TRUE;
1890           }
1891      }
1892    else
1893      {
1894         /* FIXME: If you see that assert, please notify us and we
1895            will clean our mess */
1896         assert(eina_list_count(it->content_objs) == 0);
1897
1898         _item_label_realize(it, VIEW(it), &it->labels);
1899         it->content_objs = _item_content_realize(it, VIEW(it), &it->contents);
1900         _item_state_realize(it, VIEW(it), &it->states);
1901
1902         if (!it->item->mincalcd)
1903           {
1904              Evas_Coord mw = -1, mh = -1;
1905
1906              if (!it->display_only)
1907                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1908              if (it->wd->height_for_width) mw = it->wd->prev_viewport_w;
1909              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
1910                                                   mh);
1911              if (!it->display_only)
1912                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1913              it->item->w = it->item->minw = mw;
1914              it->item->h = it->item->minh = mh;
1915              it->item->mincalcd = EINA_TRUE;
1916
1917              if ((!it->wd->group_item_width) && (it->item->flags == ELM_GENLIST_ITEM_GROUP))
1918                {
1919                   it->wd->group_item_width = mw;
1920                   it->wd->group_item_height = mh;
1921                }
1922              else if ((!it->wd->item_width) && (it->item->flags == ELM_GENLIST_ITEM_NONE))
1923                {
1924                   it->wd->item_width = mw;
1925                   it->wd->item_height = mh;
1926                }
1927           }
1928         if (!calc) evas_object_show(VIEW(it));
1929      }
1930
1931    if (it->tooltip.content_cb)
1932      {
1933         elm_widget_item_tooltip_content_cb_set(it,
1934                                                it->tooltip.content_cb,
1935                                                it->tooltip.data, NULL);
1936         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
1937         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
1938      }
1939
1940    if (it->mouse_cursor)
1941      elm_widget_item_cursor_set(it, it->mouse_cursor);
1942
1943    it->realized = EINA_TRUE;
1944    it->want_unrealize = EINA_FALSE;
1945
1946    if (itc) _item_cache_free(itc);
1947    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
1948    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1949    if (!calc)
1950      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1951    edje_object_message_signal_process(VIEW(it));
1952 }
1953
1954 static void
1955 _item_unrealize_cb(Elm_Gen_Item *it)
1956 {
1957    if (it->item->nocache)
1958      {
1959         evas_object_del(VIEW(it));
1960         VIEW(it) = NULL;
1961         evas_object_del(it->spacer);
1962         it->spacer = NULL;
1963      }
1964    else
1965      {
1966         edje_object_mirrored_set(VIEW(it),
1967                                  elm_widget_mirrored_get(WIDGET(it)));
1968         edje_object_scale_set(VIEW(it),
1969                               elm_widget_scale_get(WIDGET(it))
1970                               * _elm_config->scale);
1971         _item_cache_add(it);
1972      }
1973
1974    _mode_item_unrealize(it);
1975    it->states = NULL;
1976    it->realized = EINA_FALSE;
1977    it->want_unrealize = EINA_FALSE;
1978 }
1979
1980 static Eina_Bool
1981 _item_block_recalc(Item_Block *itb,
1982                    int         in,
1983                    Eina_Bool   qadd)
1984 {
1985    const Eina_List *l;
1986    Elm_Gen_Item *it;
1987    Evas_Coord minw = 0, minh = 0;
1988    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
1989    Evas_Coord y = 0;
1990
1991    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
1992    itb->num = in;
1993    EINA_LIST_FOREACH(itb->items, l, it)
1994      {
1995         if (it->delete_me) continue;
1996         showme |= it->item->showme;
1997         if (!itb->realized)
1998           {
1999              if (qadd)
2000                {
2001                   if (!it->item->mincalcd) changed = EINA_TRUE;
2002                   if (changed)
2003                     {
2004                        _item_realize(it, in, EINA_TRUE);
2005                        elm_gen_item_unrealize(it, EINA_TRUE);
2006                     }
2007                }
2008              else
2009                {
2010                   _item_realize(it, in, EINA_TRUE);
2011                   elm_gen_item_unrealize(it, EINA_TRUE);
2012                }
2013           }
2014         else
2015           _item_realize(it, in, EINA_FALSE);
2016         minh += it->item->minh;
2017         if (minw < it->item->minw) minw = it->item->minw;
2018         in++;
2019         it->x = 0;
2020         it->y = y;
2021         y += it->item->h;
2022      }
2023    itb->minw = minw;
2024    itb->minh = minh;
2025    itb->changed = EINA_FALSE;
2026    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2027    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2028    return showme;
2029 }
2030
2031 static void
2032 _item_block_realize(Item_Block *itb)
2033 {
2034    if (itb->realized) return;
2035    itb->realized = EINA_TRUE;
2036    itb->want_unrealize = EINA_FALSE;
2037 }
2038
2039 static void
2040 _item_block_unrealize(Item_Block *itb)
2041 {
2042    const Eina_List *l;
2043    Elm_Gen_Item *it;
2044    Eina_Bool dragging = EINA_FALSE;
2045
2046    if (!itb->realized) return;
2047    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2048    EINA_LIST_FOREACH(itb->items, l, it)
2049      {
2050         if (it->item->flags != ELM_GENLIST_ITEM_GROUP)
2051           {
2052              if (it->dragging)
2053                {
2054                   dragging = EINA_TRUE;
2055                   it->want_unrealize = EINA_TRUE;
2056                }
2057              else
2058                elm_gen_item_unrealize(it, EINA_FALSE);
2059           }
2060      }
2061    if (!dragging)
2062      {
2063         itb->realized = EINA_FALSE;
2064         itb->want_unrealize = EINA_TRUE;
2065      }
2066    else
2067      itb->want_unrealize = EINA_FALSE;
2068    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2069    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2070 }
2071
2072 static int
2073 _get_space_for_reorder_item(Elm_Gen_Item *it)
2074 {
2075    Evas_Coord rox, roy, row, roh, oy, oh;
2076    Eina_Bool top = EINA_FALSE;
2077    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2078    if (!reorder_it) return 0;
2079
2080    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2081    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2082
2083    if ((it->wd->reorder_start_y < it->item->block->y) &&
2084        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2085      {
2086         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2087         if (it->item->block->count == 1)
2088           it->wd->reorder_rel = it;
2089      }
2090    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2091             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2092      {
2093         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2094      }
2095    else
2096      it->item->block->reorder_offset = 0;
2097
2098    it->item->scrl_y += it->item->block->reorder_offset;
2099
2100    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2101                               rox, roy + (roh / 2), row, 1));
2102    if (top)
2103      {
2104         it->wd->reorder_rel = it;
2105         it->item->scrl_y += it->wd->reorder_it->item->h;
2106         return it->wd->reorder_it->item->h;
2107      }
2108    else
2109      return 0;
2110 }
2111
2112 static Eina_Bool
2113 _reorder_move_animator_cb(void *data)
2114 {
2115    Elm_Gen_Item *it = data;
2116    Eina_Bool down = EINA_FALSE;
2117    double t;
2118    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2119
2120    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2121
2122    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2123    else y = dy;
2124
2125    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2126    if (diff > it->item->h) y = diff / 2;
2127
2128    if (it->item->old_scrl_y < it->item->scrl_y)
2129      {
2130         it->item->old_scrl_y += y;
2131         down = EINA_TRUE;
2132      }
2133    else if (it->item->old_scrl_y > it->item->scrl_y)
2134      {
2135         it->item->old_scrl_y -= y;
2136         down = EINA_FALSE;
2137      }
2138    _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2139    _group_items_recalc(it->wd);
2140
2141    if ((it->wd->reorder_pan_move) ||
2142        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2143        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2144      {
2145         it->item->old_scrl_y = it->item->scrl_y;
2146         it->item->move_effect_enabled = EINA_FALSE;
2147         it->wd->reorder_move_animator = NULL;
2148         return ECORE_CALLBACK_CANCEL;
2149      }
2150    return ECORE_CALLBACK_RENEW;
2151 }
2152
2153 static void
2154 _item_position(Elm_Gen_Item *it,
2155                Evas_Object      *view,
2156                Evas_Coord        it_x,
2157                Evas_Coord        it_y)
2158 {
2159    if (!it) return;
2160    if (!view) return;
2161
2162    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2163    evas_object_resize(view, it->item->w, it->item->h);
2164    evas_object_move(view, it_x, it_y);
2165    evas_object_show(view);
2166    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2167    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2168 }
2169
2170 static void
2171 _item_block_position(Item_Block *itb,
2172                      int         in)
2173 {
2174    const Eina_List *l;
2175    Elm_Gen_Item *it;
2176    Elm_Gen_Item *git;
2177    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2178    int vis;
2179
2180    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2181    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2182    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2183                             &cvw, &cvh);
2184    EINA_LIST_FOREACH(itb->items, l, it)
2185      {
2186         if (it->delete_me) continue;
2187         else if (it->wd->reorder_it == it) continue;
2188         it->x = 0;
2189         it->y = y;
2190         it->item->w = itb->w;
2191         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2192         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2193
2194         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2195                                    cvx, cvy, cvw, cvh));
2196         if (it->item->flags != ELM_GENLIST_ITEM_GROUP)
2197           {
2198              if ((itb->realized) && (!it->realized))
2199                {
2200                   if (vis) _item_realize(it, in, EINA_FALSE);
2201                }
2202              if (it->realized)
2203                {
2204                   if (vis)
2205                     {
2206                        if (it->wd->reorder_mode)
2207                          y += _get_space_for_reorder_item(it);
2208                        git = it->item->group_item;
2209                        if (git)
2210                          {
2211                             if (git->item->scrl_y < oy)
2212                               git->item->scrl_y = oy;
2213                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2214                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2215                             git->item->want_realize = EINA_TRUE;
2216                          }
2217                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2218                          {
2219                             if (!it->item->move_effect_enabled)
2220                               {
2221                                  it->item->move_effect_enabled = EINA_TRUE;
2222                                  it->wd->reorder_move_animator =
2223                                     ecore_animator_add(
2224                                        _reorder_move_animator_cb, it);
2225                               }
2226                          }
2227                        if (!it->item->move_effect_enabled)
2228                          {
2229                             if (it->item->mode_view)
2230                                _item_position(it, it->item->mode_view, it->item->scrl_x,
2231                                               it->item->scrl_y);
2232                             else
2233                                _item_position(it, VIEW(it), it->item->scrl_x,
2234                                               it->item->scrl_y);
2235                             it->item->old_scrl_y = it->item->scrl_y;
2236                          }
2237                     }
2238                   else
2239                     {
2240                        if (!it->dragging) elm_gen_item_unrealize(it, EINA_FALSE);
2241                     }
2242                }
2243              in++;
2244           }
2245         else
2246           {
2247              if (vis) it->item->want_realize = EINA_TRUE;
2248           }
2249         y += it->item->h;
2250      }
2251    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2252    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2253 }
2254
2255 static void
2256 _group_items_recalc(void *data)
2257 {
2258    Widget_Data *wd = data;
2259    Eina_List *l;
2260    Elm_Gen_Item *git;
2261
2262    evas_event_freeze(evas_object_evas_get(wd->obj));
2263    EINA_LIST_FOREACH(wd->group_items, l, git)
2264      {
2265         if (git->item->want_realize)
2266           {
2267              if (!git->realized)
2268                _item_realize(git, 0, EINA_FALSE);
2269              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2270              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2271              evas_object_show(VIEW(git));
2272              evas_object_raise(VIEW(git));
2273           }
2274         else if (!git->item->want_realize && git->realized)
2275           {
2276              if (!git->dragging)
2277                elm_gen_item_unrealize(git, EINA_FALSE);
2278           }
2279      }
2280    evas_event_thaw(evas_object_evas_get(wd->obj));
2281    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2282 }
2283
2284 static Eina_Bool
2285 _must_recalc_idler(void *data)
2286 {
2287    Widget_Data *wd = data;
2288    if (wd->calc_job) ecore_job_del(wd->calc_job);
2289    wd->calc_job = ecore_job_add(_calc_job, wd);
2290    wd->must_recalc_idler = NULL;
2291    return ECORE_CALLBACK_CANCEL;
2292 }
2293
2294 static void
2295 _calc_job(void *data)
2296 {
2297    Widget_Data *wd = data;
2298    Item_Block *itb, *chb = NULL;
2299    Evas_Coord minw = -1, minh = 0, y = 0, ow;
2300    int in = 0;
2301    Eina_Bool minw_change = EINA_FALSE;
2302    Eina_Bool did_must_recalc = EINA_FALSE;
2303    if (!wd) return;
2304
2305    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2306    if (wd->w != ow)
2307      wd->w = ow;
2308
2309    evas_event_freeze(evas_object_evas_get(wd->obj));
2310    EINA_INLIST_FOREACH(wd->blocks, itb)
2311      {
2312         Eina_Bool showme = EINA_FALSE;
2313
2314         itb->num = in;
2315         showme = itb->showme;
2316         itb->showme = EINA_FALSE;
2317         if (chb)
2318           {
2319              if (itb->realized) _item_block_unrealize(itb);
2320           }
2321         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2322           {
2323              if (itb->must_recalc)
2324                {
2325                   Eina_List *l;
2326                   Elm_Gen_Item *it;
2327                   EINA_LIST_FOREACH(itb->items, l, it)
2328                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2329                   itb->changed = EINA_TRUE;
2330                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2331                   itb->must_recalc = EINA_FALSE;
2332                }
2333              if (itb->realized) _item_block_unrealize(itb);
2334              showme = _item_block_recalc(itb, in, EINA_FALSE);
2335              chb = itb;
2336           }
2337         itb->y = y;
2338         itb->x = 0;
2339         minh += itb->minh;
2340         if (minw == -1) minw = itb->minw;
2341         else if ((!itb->must_recalc) && (minw < itb->minw))
2342           {
2343              minw = itb->minw;
2344              minw_change = EINA_TRUE;
2345           }
2346         itb->w = minw;
2347         itb->h = itb->minh;
2348         y += itb->h;
2349         in += itb->count;
2350         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2351           {
2352              wd->show_item->item->showme = EINA_FALSE;
2353              if (wd->bring_in)
2354                elm_smart_scroller_region_bring_in(wd->scr,
2355                                                   wd->show_item->x +
2356                                                   wd->show_item->item->block->x,
2357                                                   wd->show_item->y +
2358                                                   wd->show_item->item->block->y,
2359                                                   wd->show_item->item->block->w,
2360                                                   wd->show_item->item->h);
2361              else
2362                elm_smart_scroller_child_region_show(wd->scr,
2363                                                     wd->show_item->x +
2364                                                     wd->show_item->item->block->x,
2365                                                     wd->show_item->y +
2366                                                     wd->show_item->item->block->y,
2367                                                     wd->show_item->item->block->w,
2368                                                     wd->show_item->item->h);
2369              wd->show_item = NULL;
2370           }
2371      }
2372    if (minw_change)
2373      {
2374         EINA_INLIST_FOREACH(wd->blocks, itb)
2375           {
2376              itb->minw = minw;
2377              itb->w = itb->minw;
2378           }
2379      }
2380    if ((chb) && (EINA_INLIST_GET(chb)->next))
2381      {
2382         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2383           {
2384              if (itb->realized) _item_block_unrealize(itb);
2385           }
2386      }
2387    wd->realminw = minw;
2388    if (minw < wd->w) minw = wd->w;
2389    if ((minw != wd->minw) || (minh != wd->minh))
2390      {
2391         wd->minw = minw;
2392         wd->minh = minh;
2393         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2394         _sizing_eval(wd->obj);
2395         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2396           {
2397              Elm_Gen_Item *it;
2398              Evas_Coord it_y;
2399
2400              it = wd->anchor_item;
2401              it_y = wd->anchor_y;
2402              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2403                                               it->item->block->y + it->y + it_y);
2404              wd->anchor_item = it;
2405              wd->anchor_y = it_y;
2406           }
2407      }
2408    if (did_must_recalc)
2409      {
2410         if (!wd->must_recalc_idler)
2411           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2412      }
2413    wd->calc_job = NULL;
2414    evas_object_smart_changed(wd->pan_smart);
2415    evas_event_thaw(evas_object_evas_get(wd->obj));
2416    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2417 }
2418
2419 static void
2420 _update_job(void *data)
2421 {
2422    Widget_Data *wd = data;
2423    Eina_List *l2;
2424    Item_Block *itb;
2425    int num, num0;
2426    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2427    if (!wd) return;
2428    wd->update_job = NULL;
2429    num = 0;
2430
2431    evas_event_freeze(evas_object_evas_get(wd->obj));
2432    EINA_INLIST_FOREACH(wd->blocks, itb)
2433      {
2434         Evas_Coord itminw, itminh;
2435         Elm_Gen_Item *it;
2436
2437         if (!itb->updateme)
2438           {
2439              num += itb->count;
2440              if (position)
2441                _item_block_position(itb, num);
2442              continue;
2443           }
2444         num0 = num;
2445         recalc = EINA_FALSE;
2446         EINA_LIST_FOREACH(itb->items, l2, it)
2447           {
2448              if (it->item->updateme)
2449                {
2450                   itminw = it->item->minw;
2451                   itminh = it->item->minh;
2452
2453                   it->item->updateme = EINA_FALSE;
2454                   if (it->realized)
2455                     {
2456                        elm_gen_item_unrealize(it, EINA_FALSE);
2457                        _item_realize(it, num, EINA_FALSE);
2458                        position = EINA_TRUE;
2459                     }
2460                   else
2461                     {
2462                        _item_realize(it, num, EINA_TRUE);
2463                        elm_gen_item_unrealize(it, EINA_TRUE);
2464                     }
2465                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
2466                     recalc = EINA_TRUE;
2467                }
2468              num++;
2469           }
2470         itb->updateme = EINA_FALSE;
2471         if (recalc)
2472           {
2473              position = EINA_TRUE;
2474              itb->changed = EINA_TRUE;
2475              _item_block_recalc(itb, num0, EINA_FALSE);
2476              _item_block_position(itb, num0);
2477           }
2478      }
2479    if (position)
2480      {
2481         if (wd->calc_job) ecore_job_del(wd->calc_job);
2482         wd->calc_job = ecore_job_add(_calc_job, wd);
2483      }
2484    evas_event_thaw(evas_object_evas_get(wd->obj));
2485    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2486 }
2487
2488 static void
2489 _pan_set(Evas_Object *obj,
2490          Evas_Coord   x,
2491          Evas_Coord   y)
2492 {
2493    Pan *sd = evas_object_smart_data_get(obj);
2494    Item_Block *itb;
2495
2496    if (!sd) return;
2497    //   Evas_Coord ow, oh;
2498    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2499    //   ow = sd->wd->minw - ow;
2500    //   if (ow < 0) ow = 0;
2501    //   oh = sd->wd->minh - oh;
2502    //   if (oh < 0) oh = 0;
2503    //   if (x < 0) x = 0;
2504    //   if (y < 0) y = 0;
2505    //   if (x > ow) x = ow;
2506    //   if (y > oh) y = oh;
2507    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2508    sd->wd->pan_x = x;
2509    sd->wd->pan_y = y;
2510
2511    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2512      {
2513         if ((itb->y + itb->h) > y)
2514           {
2515              Elm_Gen_Item *it;
2516              Eina_List *l2;
2517
2518              EINA_LIST_FOREACH(itb->items, l2, it)
2519                {
2520                   if ((itb->y + it->y) >= y)
2521                     {
2522                        sd->wd->anchor_item = it;
2523                        sd->wd->anchor_y = -(itb->y + it->y - y);
2524                        goto done;
2525                     }
2526                }
2527           }
2528      }
2529 done:
2530    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2531 }
2532
2533 static void
2534 _pan_get(Evas_Object *obj,
2535          Evas_Coord  *x,
2536          Evas_Coord  *y)
2537 {
2538    Pan *sd = evas_object_smart_data_get(obj);
2539
2540    if (!sd) return;
2541    if (x) *x = sd->wd->pan_x;
2542    if (y) *y = sd->wd->pan_y;
2543 }
2544
2545 static void
2546 _pan_max_get(Evas_Object *obj,
2547              Evas_Coord  *x,
2548              Evas_Coord  *y)
2549 {
2550    Pan *sd = evas_object_smart_data_get(obj);
2551    Evas_Coord ow, oh;
2552
2553    if (!sd) return;
2554    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2555    ow = sd->wd->minw - ow;
2556    if (ow < 0) ow = 0;
2557    oh = sd->wd->minh - oh;
2558    if (oh < 0) oh = 0;
2559    if (x) *x = ow;
2560    if (y) *y = oh;
2561 }
2562
2563 static void
2564 _pan_min_get(Evas_Object *obj __UNUSED__,
2565              Evas_Coord  *x,
2566              Evas_Coord  *y)
2567 {
2568    if (x) *x = 0;
2569    if (y) *y = 0;
2570 }
2571
2572 static void
2573 _pan_child_size_get(Evas_Object *obj,
2574                     Evas_Coord  *w,
2575                     Evas_Coord  *h)
2576 {
2577    Pan *sd = evas_object_smart_data_get(obj);
2578
2579    if (!sd) return;
2580    if (w) *w = sd->wd->minw;
2581    if (h) *h = sd->wd->minh;
2582 }
2583
2584 static void
2585 _pan_add(Evas_Object *obj)
2586 {
2587    Pan *sd;
2588    Evas_Object_Smart_Clipped_Data *cd;
2589
2590    _pan_sc.add(obj);
2591    cd = evas_object_smart_data_get(obj);
2592    sd = ELM_NEW(Pan);
2593    if (!sd) return;
2594    sd->__clipped_data = *cd;
2595    free(cd);
2596    evas_object_smart_data_set(obj, sd);
2597 }
2598
2599 static void
2600 _pan_del(Evas_Object *obj)
2601 {
2602    Pan *sd = evas_object_smart_data_get(obj);
2603
2604    if (!sd) return;
2605    if (sd->resize_job)
2606      {
2607         ecore_job_del(sd->resize_job);
2608         sd->resize_job = NULL;
2609      }
2610    _pan_sc.del(obj);
2611 }
2612
2613 static void
2614 _pan_resize_job(void *data)
2615 {
2616    Pan *sd = data;
2617    if (!sd) return;
2618    _sizing_eval(sd->wd->obj);
2619    sd->resize_job = NULL;
2620 }
2621
2622 static void
2623 _pan_resize(Evas_Object *obj,
2624             Evas_Coord   w,
2625             Evas_Coord   h)
2626 {
2627    Pan *sd = evas_object_smart_data_get(obj);
2628    Evas_Coord ow, oh;
2629
2630    if (!sd) return;
2631    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2632    if ((ow == w) && (oh == h)) return;
2633    if ((sd->wd->height_for_width) && (ow != w))
2634      {
2635         /* fix me later */
2636         if (sd->resize_job) ecore_job_del(sd->resize_job);
2637         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
2638      }
2639    sd->wd->pan_resized = EINA_TRUE;
2640    evas_object_smart_changed(obj);
2641    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2642    sd->wd->calc_job = NULL;
2643 /* OLD
2644    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2645    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2646  */
2647 }
2648
2649 static void
2650 _pan_calculate(Evas_Object *obj)
2651 {
2652    Pan *sd = evas_object_smart_data_get(obj);
2653    Item_Block *itb;
2654    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2655    int in = 0;
2656    Elm_Gen_Item *git;
2657    Eina_List *l;
2658
2659    if (!sd) return;
2660    evas_event_freeze(evas_object_evas_get(obj));
2661
2662    if (sd->wd->pan_resized)
2663      {
2664         _calc_job(sd->wd);
2665         sd->wd->pan_resized = EINA_FALSE;
2666      }
2667
2668    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2669    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2670    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
2671      {
2672         git->item->want_realize = EINA_FALSE;
2673      }
2674    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2675      {
2676         itb->w = sd->wd->minw;
2677         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
2678                                 itb->y - sd->wd->pan_y + oy,
2679                                 itb->w, itb->h,
2680                                 cvx, cvy, cvw, cvh))
2681           {
2682              if ((!itb->realized) || (itb->changed))
2683                _item_block_realize(itb);
2684              _item_block_position(itb, in);
2685           }
2686         else
2687           {
2688              if (itb->realized) _item_block_unrealize(itb);
2689           }
2690         in += itb->count;
2691      }
2692    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
2693       _group_items_recalc(sd->wd);
2694    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
2695      {
2696         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
2697            sd->wd->reorder_pan_move = EINA_TRUE;
2698         else sd->wd->reorder_pan_move = EINA_FALSE;
2699         evas_object_raise(sd->wd->VIEW(reorder_it));
2700         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
2701         sd->wd->start_time = ecore_loop_time_get();
2702      }
2703    _item_auto_scroll(sd->wd);
2704    evas_event_thaw(evas_object_evas_get(obj));
2705    evas_event_thaw_eval(evas_object_evas_get(obj));
2706 }
2707
2708 static void
2709 _pan_move(Evas_Object *obj,
2710           Evas_Coord   x __UNUSED__,
2711           Evas_Coord   y __UNUSED__)
2712 {
2713    Pan *sd = evas_object_smart_data_get(obj);
2714
2715    if (!sd) return;
2716    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2717    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2718 }
2719
2720 static void
2721 _hold_on(void        *data __UNUSED__,
2722          Evas_Object *obj,
2723          void        *event_info __UNUSED__)
2724 {
2725    Widget_Data *wd = elm_widget_data_get(obj);
2726    if (!wd) return;
2727    elm_smart_scroller_hold_set(wd->scr, 1);
2728 }
2729
2730 static void
2731 _hold_off(void        *data __UNUSED__,
2732           Evas_Object *obj,
2733           void        *event_info __UNUSED__)
2734 {
2735    Widget_Data *wd = elm_widget_data_get(obj);
2736    if (!wd) return;
2737    elm_smart_scroller_hold_set(wd->scr, 0);
2738 }
2739
2740 static void
2741 _freeze_on(void        *data __UNUSED__,
2742            Evas_Object *obj,
2743            void        *event_info __UNUSED__)
2744 {
2745    Widget_Data *wd = elm_widget_data_get(obj);
2746    if (!wd) return;
2747    elm_smart_scroller_freeze_set(wd->scr, 1);
2748 }
2749
2750 static void
2751 _freeze_off(void        *data __UNUSED__,
2752             Evas_Object *obj,
2753             void        *event_info __UNUSED__)
2754 {
2755    Widget_Data *wd = elm_widget_data_get(obj);
2756    if (!wd) return;
2757    elm_smart_scroller_freeze_set(wd->scr, 0);
2758 }
2759
2760 static void
2761 _scr_anim_start(void        *data,
2762                 Evas_Object *obj __UNUSED__,
2763                 void        *event_info __UNUSED__)
2764 {
2765    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
2766 }
2767
2768 static void
2769 _scr_anim_stop(void        *data,
2770                Evas_Object *obj __UNUSED__,
2771                void        *event_info __UNUSED__)
2772 {
2773    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
2774 }
2775
2776 static void
2777 _scr_drag_start(void            *data,
2778                 Evas_Object     *obj __UNUSED__,
2779                 void            *event_info __UNUSED__)
2780 {
2781    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
2782 }
2783
2784 static void
2785 _scr_drag_stop(void            *data,
2786                Evas_Object     *obj __UNUSED__,
2787                void            *event_info __UNUSED__)
2788 {
2789    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
2790 }
2791
2792 static void
2793 _edge_left(void        *data,
2794            Evas_Object *scr __UNUSED__,
2795            void        *event_info __UNUSED__)
2796 {
2797    Evas_Object *obj = data;
2798    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_LEFT, NULL);
2799    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
2800 }
2801
2802 static void
2803 _edge_right(void        *data,
2804             Evas_Object *scr __UNUSED__,
2805             void        *event_info __UNUSED__)
2806 {
2807    Evas_Object *obj = data;
2808    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_RIGHT, NULL);
2809    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
2810 }
2811
2812 static void
2813 _edge_top(void        *data,
2814           Evas_Object *scr __UNUSED__,
2815           void        *event_info __UNUSED__)
2816 {
2817    Evas_Object *obj = data;
2818    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_TOP, NULL);
2819    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
2820 }
2821
2822 static void
2823 _edge_bottom(void        *data,
2824              Evas_Object *scr __UNUSED__,
2825              void        *event_info __UNUSED__)
2826 {
2827    Evas_Object *obj = data;
2828    evas_object_smart_callback_call(obj, SIG_SCROLL_EDGE_BOTTOM, NULL);
2829    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
2830 }
2831
2832 static void
2833 _mode_item_realize(Elm_Gen_Item *it)
2834 {
2835    char buf[1024];
2836
2837    if ((it->item->mode_view) || (it->delete_me)) return;
2838
2839    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2840    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
2841    edje_object_scale_set(it->item->mode_view,
2842                          elm_widget_scale_get(WIDGET(it)) *
2843                          _elm_config->scale);
2844    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
2845    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
2846
2847    strncpy(buf, "item", sizeof(buf));
2848    if (it->wd->compress)
2849      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
2850
2851    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
2852    strncat(buf, "/", sizeof(buf) - strlen(buf));
2853    strncat(buf, it->wd->mode_item_style, sizeof(buf) - strlen(buf));
2854
2855    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
2856                          elm_widget_style_get(WIDGET(it)));
2857    edje_object_mirrored_set(it->item->mode_view,
2858                             elm_widget_mirrored_get(WIDGET(it)));
2859
2860    /* signal callback add */
2861    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
2862                                   _mouse_down, it);
2863    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
2864                                   _mouse_up, it);
2865    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
2866                                   _mouse_move, it);
2867
2868    /* label_get, content_get, state_get */
2869    /* FIXME: If you see that assert, please notify us and we
2870       will clean our mess */
2871    assert(eina_list_count(it->item->mode_content_objs) == 0);
2872
2873    _item_label_realize(it, it->item->mode_view, &it->item->mode_labels);
2874    it->item->mode_content_objs = _item_content_realize(it,
2875                                            it->item->mode_view,
2876                                            &it->item->mode_contents);
2877    _item_state_realize(it, it->item->mode_view, &it->item->mode_states);
2878
2879    edje_object_part_swallow(it->item->mode_view,
2880                             edje_object_data_get(it->item->mode_view, "mode_part"),
2881                             VIEW(it));
2882
2883    it->want_unrealize = EINA_FALSE;
2884    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2885    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2886 }
2887
2888 static void
2889 _mode_item_unrealize(Elm_Gen_Item *it)
2890 {
2891    Widget_Data *wd = it->wd;
2892    Evas_Object *content;
2893    if (!it->item->mode_view) return;
2894
2895    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2896    elm_widget_stringlist_free(it->item->mode_labels);
2897    it->item->mode_labels = NULL;
2898    elm_widget_stringlist_free(it->item->mode_contents);
2899    it->item->mode_contents = NULL;
2900    elm_widget_stringlist_free(it->item->mode_states);
2901
2902    EINA_LIST_FREE(it->item->mode_content_objs, content)
2903      evas_object_del(content);
2904
2905    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
2906    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
2907    evas_object_del(it->item->mode_view);
2908    it->item->mode_view = NULL;
2909
2910    if (wd->mode_item == it)
2911      wd->mode_item = NULL;
2912    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2913    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2914 }
2915
2916 static void
2917 _item_mode_set(Elm_Gen_Item *it)
2918 {
2919    if (!it) return;
2920    Widget_Data *wd = it->wd;
2921    if (!wd) return;
2922    char buf[1024];
2923
2924    wd->mode_item = it;
2925    it->item->nocache = EINA_TRUE;
2926
2927    if (wd->scr_hold_timer)
2928      {
2929         ecore_timer_del(wd->scr_hold_timer);
2930         wd->scr_hold_timer = NULL;
2931      }
2932    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
2933    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
2934
2935    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2936    _mode_item_realize(it);
2937    if (it->item->group_item)
2938      evas_object_raise(it->item->VIEW(group_item));
2939    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
2940    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2941    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2942
2943    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
2944    edje_object_signal_emit(it->item->mode_view, buf, "elm");
2945 }
2946
2947 static void
2948 _item_mode_unset(Widget_Data *wd)
2949 {
2950    if (!wd) return;
2951    if (!wd->mode_item) return;
2952    char buf[1024], buf2[1024];
2953    Elm_Gen_Item *it;
2954
2955    it = wd->mode_item;
2956    it->item->nocache = EINA_TRUE;
2957
2958    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type);
2959    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type);
2960
2961    edje_object_signal_emit(it->item->mode_view, buf, "elm");
2962    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
2963
2964    wd->mode_item = NULL;
2965 }
2966
2967 static void
2968 _item_auto_scroll(Widget_Data *wd)
2969 {
2970    if (!wd) return;
2971    Elm_Gen_Item  *it;
2972    Eina_List *l;
2973    Evas_Coord ox, oy, ow, oh;
2974
2975    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
2976      {
2977         evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
2978         if (wd->expanded_item->item->scrl_y > (oh + oy) / 2)
2979           {
2980              EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
2981                 elm_genlist_item_bring_in(it);
2982           }
2983         wd->auto_scroll_enabled = EINA_FALSE;
2984      }
2985 }
2986
2987 EAPI Evas_Object *
2988 elm_genlist_add(Evas_Object *parent)
2989 {
2990    Evas_Object *obj;
2991    Evas *e;
2992    Widget_Data *wd;
2993    Evas_Coord minw, minh;
2994    static Evas_Smart *smart = NULL;
2995
2996    if (!smart)
2997      {
2998         static Evas_Smart_Class sc;
2999
3000         evas_object_smart_clipped_smart_set(&_pan_sc);
3001         sc = _pan_sc;
3002         sc.name = "elm_genlist_pan";
3003         sc.version = EVAS_SMART_CLASS_VERSION;
3004         sc.add = _pan_add;
3005         sc.del = _pan_del;
3006         sc.resize = _pan_resize;
3007         sc.move = _pan_move;
3008         sc.calculate = _pan_calculate;
3009         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3010      }
3011
3012    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3013
3014    ELM_SET_WIDTYPE(widtype, "genlist");
3015    ELM_GEN_SETUP(wd);
3016    elm_widget_type_set(obj, "genlist");
3017    elm_widget_sub_object_add(parent, obj);
3018    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3019    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3020    elm_widget_data_set(obj, wd);
3021    elm_widget_del_hook_set(obj, _del_hook);
3022    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3023    elm_widget_theme_hook_set(obj, _theme_hook);
3024    elm_widget_can_focus_set(obj, EINA_TRUE);
3025    elm_widget_event_hook_set(obj, _event_hook);
3026    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3027    elm_widget_translate_hook_set(obj, _translate_hook);
3028
3029    wd->scr = elm_smart_scroller_add(e);
3030    elm_smart_scroller_widget_set(wd->scr, obj);
3031    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3032                                        elm_widget_style_get(obj));
3033    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3034                                        _elm_config->thumbscroll_bounce_enable);
3035    elm_widget_resize_object_set(obj, wd->scr);
3036
3037    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3038    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3039    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3040    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3041    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3042    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3043    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3044    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3045
3046    wd->obj = obj;
3047    wd->mode = ELM_LIST_SCROLL;
3048    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3049    wd->item_cache_max = wd->max_items_per_block * 2;
3050    wd->longpress_timeout = _elm_config->longpress_timeout;
3051
3052    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3053    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3054    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3055    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3056
3057    wd->pan_smart = evas_object_smart_add(e, smart);
3058    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3059    wd->pan->wd = wd;
3060
3061    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3062                                      _pan_set, _pan_get, _pan_max_get,
3063                                      _pan_min_get, _pan_child_size_get);
3064
3065    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3066                              &minw, &minh);
3067    evas_object_size_hint_min_set(obj, minw, minh);
3068
3069    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3070
3071    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3072    _sizing_eval(obj);
3073    return obj;
3074 }
3075
3076 static Elm_Gen_Item *
3077 _item_new(Widget_Data                  *wd,
3078           const Elm_Genlist_Item_Class *itc,
3079           const void                   *data,
3080           Elm_Gen_Item                 *parent,
3081           Elm_Genlist_Item_Flags        flags,
3082           Evas_Smart_Cb                 func,
3083           const void                   *func_data)
3084 {
3085    Elm_Gen_Item *it;
3086
3087    it = elm_gen_item_new(wd, itc, data, parent, func, func_data);
3088    if (!it) return NULL;
3089    it->item = ELM_NEW(Elm_Gen_Item_Type);
3090    it->item->flags = flags;
3091    if (flags & ELM_GENLIST_ITEM_GROUP) it->group++;
3092    it->item->expanded_depth = 0;
3093    elm_widget_item_del_cb_set(it, _item_del_hook);
3094    ELM_GEN_ITEM_SETUP(it);
3095    if (it->parent)
3096      {
3097         if (it->parent->group)
3098           it->item->group_item = parent;
3099         else if (it->parent->item->group_item)
3100           it->item->group_item = it->parent->item->group_item;
3101      }
3102    return it;
3103 }
3104
3105 static void
3106 _item_block_add(Widget_Data      *wd,
3107                 Elm_Gen_Item *it)
3108 {
3109    Item_Block *itb = NULL;
3110
3111    if (!it->item->rel)
3112      {
3113 newblock:
3114         if (it->item->rel)
3115           {
3116              itb = calloc(1, sizeof(Item_Block));
3117              if (!itb) return;
3118              itb->wd = wd;
3119              if (!it->item->rel->item->block)
3120                {
3121                   wd->blocks =
3122                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3123                   itb->items = eina_list_append(itb->items, it);
3124                }
3125              else
3126                {
3127                   if (it->item->before)
3128                     {
3129                        wd->blocks = eina_inlist_prepend_relative
3130                            (wd->blocks, EINA_INLIST_GET(itb),
3131                            EINA_INLIST_GET(it->item->rel->item->block));
3132                        itb->items =
3133                          eina_list_prepend_relative(itb->items, it, it->item->rel);
3134                     }
3135                   else
3136                     {
3137                        wd->blocks = eina_inlist_append_relative
3138                            (wd->blocks, EINA_INLIST_GET(itb),
3139                            EINA_INLIST_GET(it->item->rel->item->block));
3140                        itb->items =
3141                          eina_list_append_relative(itb->items, it, it->item->rel);
3142                     }
3143                }
3144           }
3145         else
3146           {
3147              if (it->item->before)
3148                {
3149                   if (wd->blocks)
3150                     {
3151                        itb = (Item_Block *)(wd->blocks);
3152                        if (itb->count >= wd->max_items_per_block)
3153                          {
3154                             itb = calloc(1, sizeof(Item_Block));
3155                             if (!itb) return;
3156                             itb->wd = wd;
3157                             wd->blocks =
3158                               eina_inlist_prepend(wd->blocks,
3159                                                   EINA_INLIST_GET(itb));
3160                          }
3161                     }
3162                   else
3163                     {
3164                        itb = calloc(1, sizeof(Item_Block));
3165                        if (!itb) return;
3166                        itb->wd = wd;
3167                        wd->blocks =
3168                          eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3169                     }
3170                   itb->items = eina_list_prepend(itb->items, it);
3171                }
3172              else
3173                {
3174                   if (wd->blocks)
3175                     {
3176                        itb = (Item_Block *)(wd->blocks->last);
3177                        if (itb->count >= wd->max_items_per_block)
3178                          {
3179                             itb = calloc(1, sizeof(Item_Block));
3180                             if (!itb) return;
3181                             itb->wd = wd;
3182                             wd->blocks =
3183                               eina_inlist_append(wd->blocks,
3184                                                  EINA_INLIST_GET(itb));
3185                          }
3186                     }
3187                   else
3188                     {
3189                        itb = calloc(1, sizeof(Item_Block));
3190                        if (!itb) return;
3191                        itb->wd = wd;
3192                        wd->blocks =
3193                          eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3194                     }
3195                   itb->items = eina_list_append(itb->items, it);
3196                }
3197           }
3198      }
3199    else
3200      {
3201         itb = it->item->rel->item->block;
3202         if (!itb) goto newblock;
3203         if (it->item->before)
3204           itb->items = eina_list_prepend_relative(itb->items, it, it->item->rel);
3205         else
3206           itb->items = eina_list_append_relative(itb->items, it, it->item->rel);
3207      }
3208    itb->count++;
3209    itb->changed = EINA_TRUE;
3210    it->item->block = itb;
3211    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3212    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3213    if (it->item->rel)
3214      {
3215         it->item->rel->relcount--;
3216         if ((it->item->rel->delete_me) && (!it->item->rel->relcount))
3217           _item_del(it->item->rel);
3218         it->item->rel = NULL;
3219      }
3220    if (itb->count > itb->wd->max_items_per_block)
3221      {
3222         int newc;
3223         Item_Block *itb2;
3224         Elm_Gen_Item *it2;
3225
3226         newc = itb->count / 2;
3227         itb2 = calloc(1, sizeof(Item_Block));
3228         if (!itb2) return;
3229         itb2->wd = wd;
3230         wd->blocks =
3231           eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3232                                       EINA_INLIST_GET(itb));
3233         itb2->changed = EINA_TRUE;
3234         while ((itb->count > newc) && (itb->items))
3235           {
3236              Eina_List *l;
3237
3238              l = eina_list_last(itb->items);
3239              it2 = l->data;
3240              itb->items = eina_list_remove_list(itb->items, l);
3241              itb->count--;
3242
3243              itb2->items = eina_list_prepend(itb2->items, it2);
3244              it2->item->block = itb2;
3245              itb2->count++;
3246           }
3247      }
3248 }
3249
3250 static int
3251 _queue_process(Widget_Data *wd)
3252 {
3253    int n;
3254    Eina_Bool showme = EINA_FALSE;
3255    double t0, t;
3256
3257    t0 = ecore_time_get();
3258    //evas_event_freeze(evas_object_evas_get(wd->obj));
3259    for (n = 0; (wd->queue) && (n < 128); n++)
3260      {
3261         Elm_Gen_Item *it;
3262
3263         it = wd->queue->data;
3264         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
3265         it->item->queued = EINA_FALSE;
3266         _item_block_add(wd, it);
3267         t = ecore_time_get();
3268         if (it->item->block->changed)
3269           {
3270              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
3271              it->item->block->changed = 0;
3272           }
3273         if (showme) it->item->block->showme = EINA_TRUE;
3274         if (eina_inlist_count(wd->blocks) > 1)
3275           {
3276              if ((t - t0) > (ecore_animator_frametime_get())) break;
3277           }
3278      }
3279    //evas_event_thaw(evas_object_evas_get(wd->obj));
3280    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3281    return n;
3282 }
3283
3284 static Eina_Bool
3285 _idle_process(void *data, Eina_Bool *wakeup)
3286 {
3287    Widget_Data *wd = data;
3288
3289    //xxx
3290    //static double q_start = 0.0;
3291    //if (q_start == 0.0) q_start = ecore_time_get();
3292    //xxx
3293    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
3294    if (!wd->queue)
3295      {
3296         //xxx
3297         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
3298         //xxx
3299         return ECORE_CALLBACK_CANCEL;
3300      }
3301    return ECORE_CALLBACK_RENEW;
3302 }
3303
3304 static Eina_Bool
3305 _item_idle_enterer(void *data)
3306 {
3307    Widget_Data *wd = data;
3308    Eina_Bool wakeup = EINA_FALSE;
3309    Eina_Bool ok = _idle_process(data, &wakeup);
3310
3311    if (wakeup)
3312      {
3313         // wake up mainloop
3314         if (wd->calc_job) ecore_job_del(wd->calc_job);
3315         wd->calc_job = ecore_job_add(_calc_job, wd);
3316      }
3317    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
3318    return ok;
3319 }
3320
3321 static void
3322 _item_queue(Widget_Data      *wd,
3323             Elm_Gen_Item *it)
3324 {
3325    if (it->item->queued) return;
3326    it->item->queued = EINA_TRUE;
3327    wd->queue = eina_list_append(wd->queue, it);
3328 // FIXME: why does a freeze then thaw here cause some genlist
3329 // elm_genlist_item_append() to be much much slower?
3330 //   evas_event_freeze(evas_object_evas_get(wd->obj));
3331    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
3332      {
3333         if (wd->queue_idle_enterer)
3334           {
3335              ecore_idle_enterer_del(wd->queue_idle_enterer);
3336              wd->queue_idle_enterer = NULL;
3337           }
3338         _queue_process(wd);
3339      }
3340 //   evas_event_thaw(evas_object_evas_get(wd->obj));
3341 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
3342    if (!wd->queue_idle_enterer)
3343      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
3344 }
3345
3346 static int
3347 _elm_genlist_item_compare_data(const void *data, const void *data1)
3348 {
3349    const Elm_Gen_Item *it = data;
3350    const Elm_Gen_Item *item1 = data1;
3351
3352    return _elm_genlist_item_compare_data_cb(it->base.data, item1->base.data);
3353 }
3354
3355 static int
3356 _elm_genlist_item_compare(const void *data, const void *data1)
3357 {
3358    const Elm_Gen_Item *it, *item1;
3359    it = ELM_GEN_ITEM_FROM_INLIST(data);
3360    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
3361    return _elm_genlist_item_compare_cb(it, item1);
3362 }
3363
3364 static int
3365 _elm_genlist_item_list_compare(const void *data, const void *data1)
3366 {
3367    const Elm_Gen_Item *it = data;
3368    const Elm_Gen_Item *item1 = data1;
3369    return _elm_genlist_item_compare_cb(it, item1);
3370 }
3371
3372 static void
3373 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
3374 {
3375    if (!it) return;
3376    if (!after) return;
3377
3378    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3379    _item_block_del(it);
3380
3381    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
3382    it->item->rel = after;
3383    it->item->rel->relcount++;
3384    it->item->before = EINA_FALSE;
3385    if (after->item->group_item) it->item->group_item = after->item->group_item;
3386    _item_queue(it->wd, it);
3387
3388    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3389 }
3390
3391 static void
3392 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
3393 {
3394    if (!it) return;
3395    if (!before) return;
3396
3397    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3398    _item_block_del(it);
3399    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
3400    it->item->rel = before;
3401    it->item->rel->relcount++;
3402    it->item->before = EINA_TRUE;
3403    if (before->item->group_item) it->item->group_item = before->item->group_item;
3404    _item_queue(it->wd, it);
3405
3406    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
3407 }
3408
3409 EAPI Elm_Gen_Item *
3410 elm_genlist_item_append(Evas_Object                  *obj,
3411                         const Elm_Genlist_Item_Class *itc,
3412                         const void                   *data,
3413                         Elm_Gen_Item             *parent,
3414                         Elm_Genlist_Item_Flags        flags,
3415                         Evas_Smart_Cb                 func,
3416                         const void                   *func_data)
3417 {
3418    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3419    Widget_Data *wd = elm_widget_data_get(obj);
3420    if (!wd) return NULL;
3421    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3422                                     func_data);
3423    if (!it) return NULL;
3424    if (!it->parent)
3425      {
3426         if (flags & ELM_GENLIST_ITEM_GROUP)
3427           wd->group_items = eina_list_append(wd->group_items, it);
3428         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
3429         it->item->rel = NULL;
3430      }
3431    else
3432      {
3433         Elm_Gen_Item *it2 = NULL;
3434         Eina_List *ll = eina_list_last(it->parent->item->items);
3435         if (ll) it2 = ll->data;
3436         it->parent->item->items = eina_list_append(it->parent->item->items, it);
3437         if (!it2) it2 = it->parent;
3438         wd->items =
3439           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3440                                       EINA_INLIST_GET(it2));
3441         it->item->rel = it2;
3442         it->item->rel->relcount++;
3443      }
3444    it->item->before = EINA_FALSE;
3445    _item_queue(wd, it);
3446    return it;
3447 }
3448
3449 EAPI Elm_Gen_Item *
3450 elm_genlist_item_prepend(Evas_Object                  *obj,
3451                          const Elm_Genlist_Item_Class *itc,
3452                          const void                   *data,
3453                          Elm_Gen_Item             *parent,
3454                          Elm_Genlist_Item_Flags        flags,
3455                          Evas_Smart_Cb                 func,
3456                          const void                   *func_data)
3457 {
3458    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3459    Widget_Data *wd = elm_widget_data_get(obj);
3460    if (!wd) return NULL;
3461    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3462                                     func_data);
3463    if (!it) return NULL;
3464    if (!it->parent)
3465      {
3466         if (flags & ELM_GENLIST_ITEM_GROUP)
3467           wd->group_items = eina_list_prepend(wd->group_items, it);
3468         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
3469         it->item->rel = NULL;
3470      }
3471    else
3472      {
3473         Elm_Gen_Item *it2 = NULL;
3474         Eina_List *ll = it->parent->item->items;
3475         if (ll) it2 = ll->data;
3476         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
3477         if (!it2) it2 = it->parent;
3478         wd->items =
3479           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3480                                        EINA_INLIST_GET(it2));
3481         it->item->rel = it2;
3482         it->item->rel->relcount++;
3483      }
3484    it->item->before = EINA_TRUE;
3485    _item_queue(wd, it);
3486    return it;
3487 }
3488
3489 EAPI Elm_Gen_Item *
3490 elm_genlist_item_insert_after(Evas_Object                  *obj,
3491                               const Elm_Genlist_Item_Class *itc,
3492                               const void                   *data,
3493                               Elm_Gen_Item             *parent,
3494                               Elm_Gen_Item             *after,
3495                               Elm_Genlist_Item_Flags        flags,
3496                               Evas_Smart_Cb                 func,
3497                               const void                   *func_data)
3498 {
3499    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3500    EINA_SAFETY_ON_NULL_RETURN_VAL(after, NULL);
3501    Widget_Data *wd = elm_widget_data_get(obj);
3502    if (!wd) return NULL;
3503    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3504                                     func_data);
3505    if (!it) return NULL;
3506    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
3507    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3508
3509    if (!it->parent)
3510      {
3511         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
3512             (after->item->flags & ELM_GENLIST_ITEM_GROUP))
3513           wd->group_items = eina_list_append_relative(wd->group_items, it,
3514                                                       after);
3515      }
3516    else
3517      {
3518         it->parent->item->items = eina_list_append_relative(it->parent->item->items, it,
3519                                                       after);
3520      }
3521    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
3522                                            EINA_INLIST_GET(after));
3523    it->item->rel = after;
3524    it->item->rel->relcount++;
3525    it->item->before = EINA_FALSE;
3526    _item_queue(wd, it);
3527    return it;
3528 }
3529
3530 EAPI Elm_Gen_Item *
3531 elm_genlist_item_insert_before(Evas_Object                  *obj,
3532                                const Elm_Genlist_Item_Class *itc,
3533                                const void                   *data,
3534                                Elm_Gen_Item             *parent,
3535                                Elm_Gen_Item             *before,
3536                                Elm_Genlist_Item_Flags        flags,
3537                                Evas_Smart_Cb                 func,
3538                                const void                   *func_data)
3539 {
3540    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3541    EINA_SAFETY_ON_NULL_RETURN_VAL(before, NULL);
3542    Widget_Data *wd = elm_widget_data_get(obj);
3543    if (!wd) return NULL;
3544    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3545                                     func_data);
3546    if (!it) return NULL;
3547    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
3548    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
3549
3550    if (!it->parent)
3551      {
3552         if ((flags & ELM_GENLIST_ITEM_GROUP) &&
3553             (before->item->flags & ELM_GENLIST_ITEM_GROUP))
3554           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
3555                                                        before);
3556      }
3557    else
3558      {
3559         it->parent->item->items = eina_list_prepend_relative(it->parent->item->items, it,
3560                                                        before);
3561      }
3562    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
3563                                             EINA_INLIST_GET(before));
3564    it->item->rel = before;
3565    it->item->rel->relcount++;
3566    it->item->before = EINA_TRUE;
3567    _item_queue(wd, it);
3568    return it;
3569 }
3570
3571 EAPI Elm_Gen_Item *
3572 elm_genlist_item_direct_sorted_insert(Evas_Object                  *obj,
3573                                       const Elm_Genlist_Item_Class *itc,
3574                                       const void                   *data,
3575                                       Elm_Gen_Item             *parent,
3576                                       Elm_Genlist_Item_Flags        flags,
3577                                       Eina_Compare_Cb               comp,
3578                                       Evas_Smart_Cb                 func,
3579                                       const void                   *func_data)
3580 {
3581    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3582    Widget_Data *wd = elm_widget_data_get(obj);
3583    if (!wd) return NULL;
3584    Elm_Gen_Item *rel = NULL;
3585    Elm_Gen_Item *it = _item_new(wd, itc, data, parent, flags, func,
3586                                     func_data);
3587    if (!it) return NULL;
3588
3589    _elm_genlist_item_compare_cb = comp;
3590
3591    if (it->parent)
3592      {
3593         Eina_List *l;
3594         int cmp_result;
3595
3596         l = eina_list_search_sorted_near_list(it->parent->item->items,
3597                                               _elm_genlist_item_list_compare, it,
3598                                               &cmp_result);
3599         if (l)
3600           rel = eina_list_data_get(l);
3601         else
3602           rel = it->parent;
3603
3604         if (cmp_result >= 0)
3605           {
3606              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
3607              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3608              it->item->before = EINA_FALSE;
3609           }
3610         else if (cmp_result < 0)
3611           {
3612              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
3613              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
3614              it->item->before = EINA_TRUE;
3615           }
3616      }
3617    else
3618      {
3619         if (!wd->state)
3620           {
3621              wd->state = eina_inlist_sorted_state_new();
3622           }
3623
3624         if (flags & ELM_GENLIST_ITEM_GROUP)
3625           wd->group_items = eina_list_append(wd->group_items, it);
3626
3627         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
3628                                                     _elm_genlist_item_compare, wd->state);
3629
3630         if (EINA_INLIST_GET(it)->next)
3631           {
3632              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3633              it->item->before = EINA_TRUE;
3634           }
3635         else if (EINA_INLIST_GET(it)->prev)
3636           {
3637              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
3638              it->item->before = EINA_FALSE;
3639           }
3640      }
3641
3642    if (rel)
3643      {
3644         it->item->rel = rel;
3645         it->item->rel->relcount++;
3646      }
3647
3648    _item_queue(wd, it);
3649
3650    return it;
3651 }
3652
3653 EAPI Elm_Gen_Item *
3654 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
3655                                const Elm_Genlist_Item_Class *itc,
3656                                const void                   *data,
3657                                Elm_Gen_Item             *parent,
3658                                Elm_Genlist_Item_Flags        flags,
3659                                Eina_Compare_Cb               comp,
3660                                Evas_Smart_Cb                 func,
3661                                const void                   *func_data)
3662 {
3663    _elm_genlist_item_compare_data_cb = comp;
3664
3665    return elm_genlist_item_direct_sorted_insert(obj, itc, data, parent, flags,
3666                                                 _elm_genlist_item_compare_data, func, func_data);
3667 }
3668
3669 EAPI void
3670 elm_genlist_clear(Evas_Object *obj)
3671 {
3672    elm_gen_clear(obj);
3673 }
3674
3675 EAPI void
3676 elm_genlist_multi_select_set(Evas_Object *obj,
3677                              Eina_Bool    multi)
3678 {
3679    ELM_CHECK_WIDTYPE(obj, widtype);
3680    Widget_Data *wd = elm_widget_data_get(obj);
3681    if (!wd) return;
3682    wd->multi = multi;
3683 }
3684
3685 EAPI Eina_Bool
3686 elm_genlist_multi_select_get(const Evas_Object *obj)
3687 {
3688    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3689    Widget_Data *wd = elm_widget_data_get(obj);
3690    if (!wd) return EINA_FALSE;
3691    return wd->multi;
3692 }
3693
3694 EAPI Elm_Gen_Item *
3695 elm_genlist_selected_item_get(const Evas_Object *obj)
3696 {
3697    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3698    Widget_Data *wd = elm_widget_data_get(obj);
3699    if (!wd) return NULL;
3700    if (wd->selected) return wd->selected->data;
3701    return NULL;
3702 }
3703
3704 EAPI const Eina_List *
3705 elm_genlist_selected_items_get(const Evas_Object *obj)
3706 {
3707    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3708    Widget_Data *wd = elm_widget_data_get(obj);
3709    if (!wd) return NULL;
3710    return wd->selected;
3711 }
3712
3713 EAPI Eina_List *
3714 elm_genlist_realized_items_get(const Evas_Object *obj)
3715 {
3716    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3717    Widget_Data *wd = elm_widget_data_get(obj);
3718    Eina_List *list = NULL;
3719    Item_Block *itb;
3720    Eina_Bool done = EINA_FALSE;
3721    if (!wd) return NULL;
3722    EINA_INLIST_FOREACH(wd->blocks, itb)
3723      {
3724         if (itb->realized)
3725           {
3726              Eina_List *l;
3727              Elm_Gen_Item *it;
3728
3729              done = 1;
3730              EINA_LIST_FOREACH(itb->items, l, it)
3731                {
3732                   if (it->realized) list = eina_list_append(list, it);
3733                }
3734           }
3735         else
3736           {
3737              if (done) break;
3738           }
3739      }
3740    return list;
3741 }
3742
3743 EAPI Elm_Gen_Item *
3744 elm_genlist_at_xy_item_get(const Evas_Object *obj,
3745                            Evas_Coord         x,
3746                            Evas_Coord         y,
3747                            int               *posret)
3748 {
3749    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3750    Widget_Data *wd = elm_widget_data_get(obj);
3751    Evas_Coord ox, oy, ow, oh;
3752    Item_Block *itb;
3753    Evas_Coord lasty;
3754    if (!wd) return NULL;
3755    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
3756    lasty = oy;
3757    EINA_INLIST_FOREACH(wd->blocks, itb)
3758      {
3759         Eina_List *l;
3760         Elm_Gen_Item *it;
3761
3762         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
3763                                  oy + itb->y - itb->wd->pan_y,
3764                                  itb->w, itb->h, x, y, 1, 1))
3765           continue;
3766         EINA_LIST_FOREACH(itb->items, l, it)
3767           {
3768              Evas_Coord itx, ity;
3769
3770              itx = ox + itb->x + it->x - itb->wd->pan_x;
3771              ity = oy + itb->y + it->y - itb->wd->pan_y;
3772              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
3773                {
3774                   if (posret)
3775                     {
3776                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
3777                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
3778                          *posret = 1;
3779                        else *posret = 0;
3780                     }
3781                   return it;
3782                }
3783              lasty = ity + it->item->h;
3784           }
3785      }
3786    if (posret)
3787      {
3788         if (y > lasty) *posret = 1;
3789         else *posret = -1;
3790      }
3791    return NULL;
3792 }
3793
3794 EAPI Elm_Gen_Item *
3795 elm_genlist_first_item_get(const Evas_Object *obj)
3796 {
3797    return elm_gen_first_item_get(obj);
3798 }
3799
3800 EAPI Elm_Gen_Item *
3801 elm_genlist_last_item_get(const Evas_Object *obj)
3802 {
3803    return elm_gen_last_item_get(obj);
3804 }
3805
3806 EAPI Elm_Gen_Item *
3807 elm_genlist_item_next_get(const Elm_Gen_Item *it)
3808 {
3809    return elm_gen_item_next_get(it);
3810 }
3811
3812 EAPI Elm_Gen_Item *
3813 elm_genlist_item_prev_get(const Elm_Gen_Item *it)
3814 {
3815    return elm_gen_item_prev_get(it);
3816 }
3817
3818 EAPI Evas_Object *
3819 elm_genlist_item_genlist_get(const Elm_Gen_Item *it)
3820 {
3821    return elm_gen_item_widget_get(it);
3822 }
3823
3824 EAPI Elm_Gen_Item *
3825 elm_genlist_item_parent_get(const Elm_Gen_Item *it)
3826 {
3827    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
3828    return it->parent;
3829 }
3830
3831 EAPI void
3832 elm_genlist_item_subitems_clear(Elm_Gen_Item *it)
3833 {
3834    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
3835    Eina_List *tl = NULL, *l;
3836    Elm_Gen_Item *it2;
3837
3838    EINA_LIST_FOREACH(it->item->items, l, it2)
3839      tl = eina_list_append(tl, it2);
3840    EINA_LIST_FREE(tl, it2)
3841      elm_genlist_item_del(it2);
3842 }
3843
3844 EAPI void
3845 elm_genlist_item_selected_set(Elm_Gen_Item *it,
3846                               Eina_Bool         selected)
3847 {
3848    elm_gen_item_selected_set(it, selected);
3849 }
3850
3851 EAPI Eina_Bool
3852 elm_genlist_item_selected_get(const Elm_Gen_Item *it)
3853 {
3854    return elm_gen_item_selected_get(it);
3855 }
3856
3857 EAPI void
3858 elm_genlist_item_expanded_set(Elm_Gen_Item *it,
3859                               Eina_Bool         expanded)
3860 {
3861    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
3862    if (it->item->expanded == expanded) return;
3863    it->item->expanded = expanded;
3864    it->wd->expanded_item = it;
3865    if (it->item->expanded)
3866      {
3867         if (it->realized)
3868           edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
3869         evas_object_smart_callback_call(WIDGET(it), SIG_EXPANDED, it);
3870         it->wd->auto_scroll_enabled = EINA_TRUE;
3871      }
3872    else
3873      {
3874         if (it->realized)
3875           edje_object_signal_emit(VIEW(it), "elm,state,contracted", "elm");
3876         evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACTED, it);
3877         it->wd->auto_scroll_enabled = EINA_FALSE;
3878      }
3879 }
3880
3881 EAPI Eina_Bool
3882 elm_genlist_item_expanded_get(const Elm_Gen_Item *it)
3883 {
3884    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
3885    return it->item->expanded;
3886 }
3887
3888 EAPI int
3889 elm_genlist_item_expanded_depth_get(const Elm_Gen_Item *it)
3890 {
3891    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, 0);
3892    return it->item->expanded_depth;
3893 }
3894
3895 EAPI void
3896 elm_genlist_item_disabled_set(Elm_Gen_Item *it,
3897                               Eina_Bool         disabled)
3898 {
3899    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
3900    Eina_List *l;
3901    Evas_Object *obj;
3902    if (it->disabled == disabled) return;
3903    if (it->delete_me) return;
3904    it->disabled = !!disabled;
3905    if (it->selected)
3906      elm_gen_item_selected_set(it, EINA_FALSE);
3907    if (it->realized)
3908      {
3909         if (it->disabled)
3910           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
3911         else
3912           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
3913         EINA_LIST_FOREACH(it->content_objs, l, obj)
3914           elm_widget_disabled_set(obj, disabled);
3915      }
3916 }
3917
3918 EAPI Eina_Bool
3919 elm_genlist_item_disabled_get(const Elm_Gen_Item *it)
3920 {
3921    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
3922    if (it->delete_me) return EINA_FALSE;
3923    return it->disabled;
3924 }
3925
3926 EAPI void
3927 elm_genlist_item_display_only_set(Elm_Gen_Item *it,
3928                                   Eina_Bool         display_only)
3929 {
3930    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
3931    if (it->display_only == display_only) return;
3932    if (it->delete_me) return;
3933    it->display_only = display_only;
3934    it->item->mincalcd = EINA_FALSE;
3935    it->item->updateme = EINA_TRUE;
3936    if (it->item->block) it->item->block->updateme = EINA_TRUE;
3937    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
3938    it->wd->update_job = ecore_job_add(_update_job, it->wd);
3939 }
3940
3941 EAPI Eina_Bool
3942 elm_genlist_item_display_only_get(const Elm_Gen_Item *it)
3943 {
3944    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
3945    if (it->delete_me) return EINA_FALSE;
3946    return it->display_only;
3947 }
3948
3949 EAPI void
3950 elm_genlist_item_show(Elm_Gen_Item *it)
3951 {
3952    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
3953    Evas_Coord gith = 0;
3954    if (it->delete_me) return;
3955    if ((it->item->queued) || (!it->item->mincalcd))
3956      {
3957         it->wd->show_item = it;
3958         it->wd->bring_in = EINA_TRUE;
3959         it->item->showme = EINA_TRUE;
3960         return;
3961      }
3962    if (it->wd->show_item)
3963      {
3964         it->wd->show_item->item->showme = EINA_FALSE;
3965         it->wd->show_item = NULL;
3966      }
3967    if ((it->item->group_item) && (it->wd->pan_y > (it->y + it->item->block->y)))
3968      gith = it->item->group_item->item->h;
3969    elm_smart_scroller_child_region_show(it->wd->scr,
3970                                         it->x + it->item->block->x,
3971                                         it->y + it->item->block->y - gith,
3972                                         it->item->block->w, it->item->h);
3973 }
3974
3975 EAPI void
3976 elm_genlist_item_bring_in(Elm_Gen_Item *it)
3977 {
3978    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
3979    Evas_Coord gith = 0;
3980    if (it->delete_me) return;
3981    if ((it->item->queued) || (!it->item->mincalcd))
3982      {
3983         it->wd->show_item = it;
3984         it->wd->bring_in = EINA_TRUE;
3985         it->item->showme = EINA_TRUE;
3986         return;
3987      }
3988    if (it->wd->show_item)
3989      {
3990         it->wd->show_item->item->showme = EINA_FALSE;
3991         it->wd->show_item = NULL;
3992      }
3993    if ((it->item->group_item) && (it->wd->pan_y > (it->y + it->item->block->y)))
3994      gith = it->item->group_item->item->h;
3995    elm_smart_scroller_region_bring_in(it->wd->scr,
3996                                       it->x + it->item->block->x,
3997                                       it->y + it->item->block->y - gith,
3998                                       it->item->block->w, it->item->h);
3999 }
4000
4001 EAPI void
4002 elm_genlist_item_top_show(Elm_Gen_Item *it)
4003 {
4004    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4005    Evas_Coord ow, oh;
4006    Evas_Coord gith = 0;
4007
4008    if (it->delete_me) return;
4009    if ((it->item->queued) || (!it->item->mincalcd))
4010      {
4011         it->wd->show_item = it;
4012         it->wd->bring_in = EINA_TRUE;
4013         it->item->showme = EINA_TRUE;
4014         return;
4015      }
4016    if (it->wd->show_item)
4017      {
4018         it->wd->show_item->item->showme = EINA_FALSE;
4019         it->wd->show_item = NULL;
4020      }
4021    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4022    if (it->item->group_item) gith = it->item->group_item->item->h;
4023    elm_smart_scroller_child_region_show(it->wd->scr,
4024                                         it->x + it->item->block->x,
4025                                         it->y + it->item->block->y - gith,
4026                                         it->item->block->w, oh);
4027 }
4028
4029 EAPI void
4030 elm_genlist_item_top_bring_in(Elm_Gen_Item *it)
4031 {
4032    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4033    Evas_Coord ow, oh;
4034    Evas_Coord gith = 0;
4035
4036    if (it->delete_me) return;
4037    if ((it->item->queued) || (!it->item->mincalcd))
4038      {
4039         it->wd->show_item = it;
4040         it->wd->bring_in = EINA_TRUE;
4041         it->item->showme = EINA_TRUE;
4042         return;
4043      }
4044    if (it->wd->show_item)
4045      {
4046         it->wd->show_item->item->showme = EINA_FALSE;
4047         it->wd->show_item = NULL;
4048      }
4049    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4050    if (it->item->group_item) gith = it->item->group_item->item->h;
4051    elm_smart_scroller_region_bring_in(it->wd->scr,
4052                                       it->x + it->item->block->x,
4053                                       it->y + it->item->block->y - gith,
4054                                       it->item->block->w, oh);
4055 }
4056
4057 EAPI void
4058 elm_genlist_item_middle_show(Elm_Gen_Item *it)
4059 {
4060    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4061    Evas_Coord ow, oh;
4062
4063    if (it->delete_me) return;
4064    if ((it->item->queued) || (!it->item->mincalcd))
4065      {
4066         it->wd->show_item = it;
4067         it->wd->bring_in = EINA_TRUE;
4068         it->item->showme = EINA_TRUE;
4069         return;
4070      }
4071    if (it->wd->show_item)
4072      {
4073         it->wd->show_item->item->showme = EINA_FALSE;
4074         it->wd->show_item = NULL;
4075      }
4076    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4077    elm_smart_scroller_child_region_show(it->wd->scr,
4078                                         it->x + it->item->block->x,
4079                                         it->y + it->item->block->y - oh / 2 +
4080                                         it->item->h / 2, it->item->block->w, oh);
4081 }
4082
4083 EAPI void
4084 elm_genlist_item_middle_bring_in(Elm_Gen_Item *it)
4085 {
4086    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4087    Evas_Coord ow, oh;
4088
4089    if (it->delete_me) return;
4090    if ((it->item->queued) || (!it->item->mincalcd))
4091      {
4092         it->wd->show_item = it;
4093         it->wd->bring_in = EINA_TRUE;
4094         it->item->showme = EINA_TRUE;
4095         return;
4096      }
4097    if (it->wd->show_item)
4098      {
4099         it->wd->show_item->item->showme = EINA_FALSE;
4100         it->wd->show_item = NULL;
4101      }
4102    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
4103    elm_smart_scroller_region_bring_in(it->wd->scr,
4104                                       it->x + it->item->block->x,
4105                                       it->y + it->item->block->y - oh / 2 + it->item->h / 2,
4106                                       it->item->block->w, oh);
4107 }
4108
4109 EAPI void
4110 elm_genlist_item_del(Elm_Gen_Item *it)
4111 {
4112    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4113    if ((it->relcount > 0) || (it->walking > 0))
4114      {
4115         elm_genlist_item_subitems_clear(it);
4116         if (it->wd->show_item == it) it->wd->show_item = NULL;
4117         elm_gen_item_del_notserious(it);
4118         if (it->item->block)
4119           {
4120              if (it->realized) elm_gen_item_unrealize(it, EINA_FALSE);
4121              it->item->block->changed = EINA_TRUE;
4122              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
4123              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
4124           }
4125         return;
4126      }
4127    _item_del(it);
4128 }
4129
4130 EAPI void
4131 elm_genlist_item_data_set(Elm_Gen_Item *it,
4132                           const void       *data)
4133 {
4134    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4135    elm_widget_item_data_set(it, data);
4136 }
4137
4138 EAPI void *
4139 elm_genlist_item_data_get(const Elm_Gen_Item *it)
4140 {
4141    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4142    return elm_widget_item_data_get(it);
4143 }
4144
4145 EAPI void
4146 elm_genlist_item_icons_orphan(Elm_Gen_Item *it)
4147 {
4148    elm_genlist_item_contents_orphan(it);
4149 }
4150
4151 EAPI void
4152 elm_genlist_item_contents_orphan(Elm_Gen_Item *it)
4153 {
4154    Evas_Object *content;
4155    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4156    EINA_LIST_FREE(it->content_objs, content)
4157      {
4158         elm_widget_sub_object_del(WIDGET(it), content);
4159         evas_object_smart_member_del(content);
4160         evas_object_hide(content);
4161      }
4162 }
4163
4164 EAPI const Evas_Object *
4165 elm_genlist_item_object_get(const Elm_Gen_Item *it)
4166 {
4167    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4168    return VIEW(it);
4169 }
4170
4171 EAPI void
4172 elm_genlist_item_update(Elm_Gen_Item *it)
4173 {
4174    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4175    if (!it->item->block) return;
4176    if (it->delete_me) return;
4177    it->item->mincalcd = EINA_FALSE;
4178    it->item->updateme = EINA_TRUE;
4179    it->item->block->updateme = EINA_TRUE;
4180    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4181    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4182 }
4183
4184 EAPI void
4185 elm_genlist_item_item_class_update(Elm_Gen_Item             *it,
4186                                    const Elm_Genlist_Item_Class *itc)
4187 {
4188    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4189    if (!it->item->block) return;
4190    EINA_SAFETY_ON_NULL_RETURN(itc);
4191    if (it->delete_me) return;
4192    it->itc = itc;
4193    it->item->nocache = EINA_TRUE;
4194    elm_genlist_item_update(it);
4195 }
4196
4197 EAPI const Elm_Genlist_Item_Class *
4198 elm_genlist_item_item_class_get(const Elm_Gen_Item *it)
4199 {
4200    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4201    if (it->delete_me) return NULL;
4202    return it->itc;
4203 }
4204
4205 static Evas_Object *
4206 _elm_genlist_item_label_create(void        *data,
4207                                Evas_Object *obj __UNUSED__,
4208                                Evas_Object *tooltip,
4209                                void        *it __UNUSED__)
4210 {
4211    Evas_Object *label = elm_label_add(tooltip);
4212    if (!label)
4213      return NULL;
4214    elm_object_style_set(label, "tooltip");
4215    elm_object_text_set(label, data);
4216    return label;
4217 }
4218
4219 static void
4220 _elm_genlist_item_label_del_cb(void        *data,
4221                                Evas_Object *obj __UNUSED__,
4222                                void        *event_info __UNUSED__)
4223 {
4224    eina_stringshare_del(data);
4225 }
4226
4227 EAPI void
4228 elm_genlist_item_tooltip_text_set(Elm_Gen_Item *it,
4229                                   const char       *text)
4230 {
4231    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4232    text = eina_stringshare_add(text);
4233    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
4234                                            text,
4235                                            _elm_genlist_item_label_del_cb);
4236 }
4237
4238 EAPI void
4239 elm_genlist_item_tooltip_content_cb_set(Elm_Gen_Item           *it,
4240                                         Elm_Tooltip_Item_Content_Cb func,
4241                                         const void                 *data,
4242                                         Evas_Smart_Cb               del_cb)
4243 {
4244    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, error);
4245
4246    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
4247      return;
4248
4249    if (it->tooltip.del_cb)
4250      it->tooltip.del_cb((void *)it->tooltip.data,
4251                           WIDGET(it), it);
4252
4253    it->tooltip.content_cb = func;
4254    it->tooltip.data = data;
4255    it->tooltip.del_cb = del_cb;
4256
4257    if (VIEW(it))
4258      {
4259         elm_widget_item_tooltip_content_cb_set(it,
4260                                                it->tooltip.content_cb,
4261                                                it->tooltip.data, NULL);
4262         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
4263         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
4264      }
4265
4266    return;
4267
4268 error:
4269    if (del_cb) del_cb((void *)data, NULL, NULL);
4270 }
4271
4272 EAPI void
4273 elm_genlist_item_tooltip_unset(Elm_Gen_Item *it)
4274 {
4275    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4276    if ((VIEW(it)) && (it->tooltip.content_cb))
4277      elm_widget_item_tooltip_unset(it);
4278
4279    if (it->tooltip.del_cb)
4280      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
4281    it->tooltip.del_cb = NULL;
4282    it->tooltip.content_cb = NULL;
4283    it->tooltip.data = NULL;
4284    it->tooltip.free_size = EINA_FALSE;
4285    if (it->tooltip.style)
4286      elm_genlist_item_tooltip_style_set(it, NULL);
4287 }
4288
4289 EAPI void
4290 elm_genlist_item_tooltip_style_set(Elm_Gen_Item *it,
4291                                    const char       *style)
4292 {
4293    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4294    eina_stringshare_replace(&it->tooltip.style, style);
4295    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
4296 }
4297
4298 EAPI const char *
4299 elm_genlist_item_tooltip_style_get(const Elm_Gen_Item *it)
4300 {
4301    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4302    return it->tooltip.style;
4303 }
4304
4305 EAPI Eina_Bool
4306 elm_genlist_item_tooltip_size_restrict_disable(Elm_Gen_Item *it, Eina_Bool disable)
4307 {
4308    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4309    it->tooltip.free_size = disable;
4310    if (VIEW(it)) return elm_widget_item_tooltip_size_restrict_disable(it, disable);
4311    return EINA_TRUE;
4312 }
4313
4314 EAPI Eina_Bool
4315 elm_genlist_item_tooltip_size_restrict_disabled_get(const Elm_Gen_Item *it)
4316 {
4317    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4318    return it->tooltip.free_size;
4319 }
4320
4321 EAPI void
4322 elm_genlist_item_cursor_set(Elm_Gen_Item *it,
4323                             const char       *cursor)
4324 {
4325    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4326    eina_stringshare_replace(&it->mouse_cursor, cursor);
4327    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
4328 }
4329
4330 EAPI const char *
4331 elm_genlist_item_cursor_get(const Elm_Gen_Item *it)
4332 {
4333    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4334    return elm_widget_item_cursor_get(it);
4335 }
4336
4337 EAPI void
4338 elm_genlist_item_cursor_unset(Elm_Gen_Item *it)
4339 {
4340    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4341    if (!it->mouse_cursor)
4342      return;
4343
4344    if (VIEW(it))
4345      elm_widget_item_cursor_unset(it);
4346
4347    eina_stringshare_del(it->mouse_cursor);
4348    it->mouse_cursor = NULL;
4349 }
4350
4351 EAPI void
4352 elm_genlist_item_cursor_style_set(Elm_Gen_Item *it,
4353                                   const char       *style)
4354 {
4355    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4356    elm_widget_item_cursor_style_set(it, style);
4357 }
4358
4359 EAPI const char *
4360 elm_genlist_item_cursor_style_get(const Elm_Gen_Item *it)
4361 {
4362    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
4363    return elm_widget_item_cursor_style_get(it);
4364 }
4365
4366 EAPI void
4367 elm_genlist_item_cursor_engine_only_set(Elm_Gen_Item *it,
4368                                         Eina_Bool         engine_only)
4369 {
4370    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4371    elm_widget_item_cursor_engine_only_set(it, engine_only);
4372 }
4373
4374 EAPI Eina_Bool
4375 elm_genlist_item_cursor_engine_only_get(const Elm_Gen_Item *it)
4376 {
4377    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
4378    return elm_widget_item_cursor_engine_only_get(it);
4379 }
4380
4381 EAPI void
4382 elm_genlist_horizontal_set(Evas_Object  *obj,
4383                                 Elm_List_Mode mode)
4384 {
4385    ELM_CHECK_WIDTYPE(obj, widtype);
4386    Widget_Data *wd = elm_widget_data_get(obj);
4387    if (!wd) return;
4388    if (wd->mode == mode) return;
4389    wd->mode = mode;
4390    _sizing_eval(obj);
4391 }
4392
4393 EAPI void
4394 elm_genlist_horizontal_mode_set(Evas_Object  *obj,
4395                                 Elm_List_Mode mode)
4396 {
4397    elm_genlist_horizontal_set(obj, mode);
4398 }
4399
4400 EAPI Elm_List_Mode
4401 elm_genlist_horizontal_get(const Evas_Object *obj)
4402 {
4403    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4404    Widget_Data *wd = elm_widget_data_get(obj);
4405    if (!wd) return ELM_LIST_LAST;
4406    return wd->mode;
4407 }
4408
4409 EAPI Elm_List_Mode
4410 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
4411 {
4412    return elm_genlist_horizontal_get(obj);
4413 }
4414
4415 EAPI void
4416 elm_genlist_always_select_mode_set(Evas_Object *obj,
4417                                    Eina_Bool    always_select)
4418 {
4419    elm_gen_always_select_mode_set(obj, always_select);
4420 }
4421
4422 EAPI Eina_Bool
4423 elm_genlist_always_select_mode_get(const Evas_Object *obj)
4424 {
4425    return elm_gen_always_select_mode_get(obj);
4426 }
4427
4428 EAPI void
4429 elm_genlist_no_select_mode_set(Evas_Object *obj,
4430                                Eina_Bool    no_select)
4431 {
4432    elm_gen_no_select_mode_set(obj, no_select);
4433 }
4434
4435 EAPI Eina_Bool
4436 elm_genlist_no_select_mode_get(const Evas_Object *obj)
4437 {
4438    return elm_gen_no_select_mode_get(obj);
4439 }
4440
4441 EAPI void
4442 elm_genlist_compress_mode_set(Evas_Object *obj,
4443                               Eina_Bool    compress)
4444 {
4445    ELM_CHECK_WIDTYPE(obj, widtype);
4446    Widget_Data *wd = elm_widget_data_get(obj);
4447    if (!wd) return;
4448    wd->compress = compress;
4449    if (!compress) elm_genlist_homogeneous_set(obj, EINA_FALSE);
4450 }
4451
4452 EAPI Eina_Bool
4453 elm_genlist_compress_mode_get(const Evas_Object *obj)
4454 {
4455    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4456    Widget_Data *wd = elm_widget_data_get(obj);
4457    if (!wd) return EINA_FALSE;
4458    return wd->compress;
4459 }
4460
4461 EAPI void
4462 elm_genlist_height_for_width_mode_set(Evas_Object *obj,
4463                                       Eina_Bool    height_for_width)
4464 {
4465    ELM_CHECK_WIDTYPE(obj, widtype);
4466    Widget_Data *wd = elm_widget_data_get(obj);
4467    if (!wd) return;
4468    wd->height_for_width = !!height_for_width;
4469    if (wd->height_for_width)
4470      {
4471         elm_genlist_homogeneous_set(obj, EINA_FALSE);
4472         elm_genlist_compress_mode_set(obj, EINA_TRUE);
4473      }
4474 }
4475
4476 EAPI Eina_Bool
4477 elm_genlist_height_for_width_mode_get(const Evas_Object *obj)
4478 {
4479    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4480    Widget_Data *wd = elm_widget_data_get(obj);
4481    if (!wd) return EINA_FALSE;
4482    return wd->height_for_width;
4483 }
4484
4485 EAPI void
4486 elm_genlist_bounce_set(Evas_Object *obj,
4487                        Eina_Bool    h_bounce,
4488                        Eina_Bool    v_bounce)
4489 {
4490    elm_gen_bounce_set(obj, h_bounce, v_bounce);
4491 }
4492
4493 EAPI void
4494 elm_genlist_bounce_get(const Evas_Object *obj,
4495                        Eina_Bool         *h_bounce,
4496                        Eina_Bool         *v_bounce)
4497 {
4498    elm_gen_bounce_get(obj, h_bounce, v_bounce);
4499 }
4500
4501 EAPI void
4502 elm_genlist_homogeneous_set(Evas_Object *obj,
4503                             Eina_Bool    homogeneous)
4504 {
4505    ELM_CHECK_WIDTYPE(obj, widtype);
4506    Widget_Data *wd = elm_widget_data_get(obj);
4507    if (!wd) return;
4508    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
4509    wd->homogeneous = homogeneous;
4510 }
4511
4512 EAPI Eina_Bool
4513 elm_genlist_homogeneous_get(const Evas_Object *obj)
4514 {
4515    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4516    Widget_Data *wd = elm_widget_data_get(obj);
4517    if (!wd) return EINA_FALSE;
4518    return wd->homogeneous;
4519 }
4520
4521 EAPI void
4522 elm_genlist_block_count_set(Evas_Object *obj,
4523                             int          n)
4524 {
4525    ELM_CHECK_WIDTYPE(obj, widtype);
4526    Widget_Data *wd = elm_widget_data_get(obj);
4527    if (!wd) return;
4528    wd->max_items_per_block = n;
4529    wd->item_cache_max = wd->max_items_per_block * 2;
4530    _item_cache_clean(wd);
4531 }
4532
4533 EAPI int
4534 elm_genlist_block_count_get(const Evas_Object *obj)
4535 {
4536    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4537    Widget_Data *wd = elm_widget_data_get(obj);
4538    if (!wd) return 0;
4539    return wd->max_items_per_block;
4540 }
4541
4542 EAPI void
4543 elm_genlist_longpress_timeout_set(Evas_Object *obj,
4544                                   double       timeout)
4545 {
4546    ELM_CHECK_WIDTYPE(obj, widtype);
4547    Widget_Data *wd = elm_widget_data_get(obj);
4548    if (!wd) return;
4549    wd->longpress_timeout = timeout;
4550 }
4551
4552 EAPI double
4553 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
4554 {
4555    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4556    Widget_Data *wd = elm_widget_data_get(obj);
4557    if (!wd) return 0;
4558    return wd->longpress_timeout;
4559 }
4560
4561 EAPI void
4562 elm_genlist_scroller_policy_set(Evas_Object        *obj,
4563                                 Elm_Scroller_Policy policy_h,
4564                                 Elm_Scroller_Policy policy_v)
4565 {
4566    ELM_CHECK_WIDTYPE(obj, widtype);
4567    Widget_Data *wd = elm_widget_data_get(obj);
4568    if ((!wd) || (!wd->scr)) return;
4569    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
4570        (policy_v >= ELM_SCROLLER_POLICY_LAST))
4571      return;
4572    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
4573 }
4574
4575 EAPI void
4576 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
4577                                 Elm_Scroller_Policy *policy_h,
4578                                 Elm_Scroller_Policy *policy_v)
4579 {
4580    ELM_CHECK_WIDTYPE(obj, widtype);
4581    Widget_Data *wd = elm_widget_data_get(obj);
4582    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
4583    if ((!wd) || (!wd->scr)) return;
4584    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
4585    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
4586    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
4587 }
4588
4589 EAPI void
4590 elm_genlist_realized_items_update(Evas_Object *obj)
4591 {
4592    ELM_CHECK_WIDTYPE(obj, widtype);
4593
4594    Eina_List *list, *l;
4595    Elm_Gen_Item *it;
4596
4597    list = elm_genlist_realized_items_get(obj);
4598    EINA_LIST_FOREACH(list, l, it)
4599      elm_genlist_item_update(it);
4600 }
4601
4602 EAPI void
4603 elm_genlist_item_mode_set(Elm_Gen_Item *it,
4604                           const char       *mode_type,
4605                           Eina_Bool         mode_set)
4606 {
4607    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
4608    Widget_Data *wd = it->wd;
4609    Eina_List *l;
4610    Elm_Gen_Item *it2;
4611
4612    if (!wd) return;
4613    if (!mode_type) return;
4614    if ((it->delete_me) || (it->disabled)) return;
4615
4616    if ((wd->mode_item == it) &&
4617        (!strcmp(mode_type, wd->mode_type)) &&
4618        (mode_set))
4619       return;
4620    if (!wd->mode_item_style) return;
4621    it->mode_set = mode_set;
4622
4623    if (wd->multi)
4624      {
4625         EINA_LIST_FOREACH(wd->selected, l, it2)
4626           if (it2->realized)
4627             elm_gen_item_selected_set(it2, EINA_FALSE);
4628      }
4629    else
4630      {
4631         it2 = elm_genlist_selected_item_get(wd->obj);
4632         if ((it2) && (it2->realized))
4633           elm_gen_item_selected_set(it2, EINA_FALSE);
4634      }
4635
4636    if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) ||
4637        (mode_set) ||
4638        ((it == wd->mode_item) && (!mode_set)))
4639      _item_mode_unset(wd);
4640
4641    eina_stringshare_replace(&wd->mode_type, mode_type);
4642    if (mode_set) _item_mode_set(it);
4643 }
4644
4645
4646 EAPI const char *
4647 elm_genlist_mode_item_style_get(const Evas_Object *obj)
4648 {
4649    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4650    Widget_Data *wd = elm_widget_data_get(obj);
4651    if (!wd) return NULL;
4652    return wd->mode_item_style;
4653 }
4654
4655 EAPI void
4656 elm_genlist_mode_item_style_set(Evas_Object *obj, const char *style)
4657 {
4658    ELM_CHECK_WIDTYPE(obj, widtype);
4659    Widget_Data *wd = elm_widget_data_get(obj);
4660    if (!wd) return;
4661    if ((style == wd->mode_item_style) || (style && wd->mode_item_style &&
4662        (!strcmp(style, wd->mode_item_style))))
4663      return;
4664    eina_stringshare_replace(&wd->mode_item_style, style);
4665    elm_genlist_realized_items_update(obj);
4666 }
4667
4668 EAPI const char *
4669 elm_genlist_mode_get(const Evas_Object *obj)
4670 {
4671    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4672    Widget_Data *wd = elm_widget_data_get(obj);
4673    if (!wd) return NULL;
4674    return wd->mode_type;
4675 }
4676
4677 EAPI const Elm_Gen_Item *
4678 elm_genlist_mode_item_get(const Evas_Object *obj)
4679 {
4680    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4681    Widget_Data *wd = elm_widget_data_get(obj);
4682    if (!wd) return NULL;
4683    return wd->mode_item;
4684 }
4685
4686 EAPI void
4687 elm_genlist_reorder_mode_set(Evas_Object *obj,
4688                              Eina_Bool    reorder_mode)
4689 {
4690    ELM_CHECK_WIDTYPE(obj, widtype);
4691    Widget_Data *wd = elm_widget_data_get(obj);
4692    if (!wd) return;
4693    wd->reorder_mode = reorder_mode;
4694 }
4695
4696 EAPI Eina_Bool
4697 elm_genlist_reorder_mode_get(const Evas_Object *obj)
4698 {
4699    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4700    Widget_Data *wd = elm_widget_data_get(obj);
4701    if (!wd) return EINA_FALSE;
4702    return wd->reorder_mode;
4703 }