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