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