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