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