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