Merge branch 'master' of youmin.ha@165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs...
[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    if (it->queued) return;
2740    it->queued = EINA_TRUE;
2741    wd->queue = eina_list_append(wd->queue, it);
2742    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
2743      {
2744         if (wd->queue_idler)
2745           {
2746              ecore_idler_del(wd->queue_idler);
2747              wd->queue_idler = NULL;
2748           }
2749         _queue_proecess(wd, 0);
2750      }
2751    if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_item_idler, wd);
2752 }
2753 #else
2754
2755 static int
2756 _item_idler(void *data)
2757 {
2758    Widget_Data *wd = data;
2759    int n, showme = 0;
2760    double t0, t;
2761
2762    t0 = ecore_time_get();
2763    for (n = 0; (wd->queue) && (n < 128); n++)
2764      {
2765         Elm_Genlist_Item *it;
2766
2767         it = wd->queue->data;
2768         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
2769         it->queued = EINA_FALSE;
2770         _item_block_add(wd, it);
2771         t = ecore_time_get();
2772         if (it->block->changed)
2773           {
2774              showme = _item_block_recalc(it->block, it->block->num, 1, 1);
2775              it->block->changed = 0;
2776           }
2777         if (showme) it->block->showme = 1;
2778         if (eina_inlist_count(wd->blocks) > 1)
2779           {
2780              if ((t - t0) > (ecore_animator_frametime_get())) break;
2781           }
2782      }
2783    if (n > 0)
2784      {
2785         if (wd->calc_job) ecore_job_del(wd->calc_job);
2786         wd->calc_job = ecore_job_add(_calc_job, wd);
2787      }
2788    if (!wd->queue)
2789      {
2790         wd->queue_idler = NULL;
2791         return 0;
2792      }
2793    return 1;
2794 }
2795
2796 static void
2797 _item_queue(Widget_Data *wd, Elm_Genlist_Item *it)
2798 {
2799         Item_Block *itb;
2800
2801         // Add the initial set of Items directly to the Blocks, to show the genlist
2802         // without empty screen.
2803         itb = (Item_Block *)(wd->blocks);
2804         if( (NULL == itb) || (itb->count < wd->max_items_per_block) )
2805         {
2806                 _item_block_add(wd, it);
2807         }
2808         else
2809         {
2810                 if (it->queued) return;
2811                 if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_item_idler, wd);
2812                 it->queued = EINA_TRUE;
2813                 wd->queue = eina_list_append(wd->queue, it);
2814         }
2815 }
2816
2817 #endif
2818
2819 /**
2820  * Add Group Item to the genlist
2821  *
2822  * @param obj The genlist object
2823  * @param itc The item class for the item
2824  * @param data The group item data
2825  */
2826 EAPI Elm_Genlist_GroupItem *
2827 elm_genlist_groupitem_add(Evas_Object *obj, const Elm_Genlist_Item_Class *itc,
2828                         const void *data)
2829 {
2830         Elm_Genlist_GroupItem *git;
2831         Widget_Data *wd = elm_widget_data_get(obj);
2832
2833         git = calloc(1, sizeof(Elm_Genlist_GroupItem));
2834         if (!git) return NULL;
2835         git->wd = wd;
2836         git->itc = itc;
2837         git->data = data;
2838
2839         wd->group_items = eina_inlist_append(wd->group_items, EINA_INLIST_GET(git) );
2840         return git;
2841 }
2842
2843 /**
2844  * Delete a given groupitem
2845  *
2846  * This deletes the group item from genlist and calls the genlist group item del class
2847  * callback defined in the item class, if it is set.
2848  *
2849  * @param git The group item
2850  *
2851  * @ingroup Genlist
2852  */
2853 EAPI void
2854 elm_genlist_groupitem_del(Elm_Genlist_GroupItem *git)
2855 {
2856    _groupitem_remove( git, EINA_TRUE);
2857 }
2858
2859 /**
2860  * Append item to the end of the genlist
2861  *
2862  * This appends the given item to the end of the list or the end of the
2863  * children if the parent is given.
2864  *
2865  * @param obj The genlist object
2866  * @param itc The item class for the item
2867  * @param data The item data
2868  * @param parent The parent item, or NULL if none
2869  * @param flags Item flags
2870  * @param func Convenience function called when item selected
2871  * @param func_data Data passed to @p func above.
2872  * @return A handle to the item added or NULL if not possible
2873  *
2874  * @ingroup Genlist
2875  */
2876 EAPI Elm_Genlist_Item *
2877 elm_genlist_item_append(Evas_Object *obj, const Elm_Genlist_Item_Class *itc,
2878                         const void *data, Elm_Genlist_Item *parent,
2879                         Elm_Genlist_Item_Flags flags,
2880                         Evas_Smart_Cb func, const void *func_data)
2881 {
2882    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2883    Widget_Data *wd = elm_widget_data_get(obj);
2884    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func, func_data);
2885    if (!wd) return NULL;
2886    if (!it) return NULL;
2887    if (!it->parent)
2888      {
2889         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
2890         it->rel = NULL;
2891         it->before = 0;
2892      }
2893    else
2894      {
2895         Elm_Genlist_Item *it2 = NULL;
2896         Eina_List *ll = eina_list_last(it->parent->items);
2897         if (ll) it2 = ll->data;
2898         it->parent->items = eina_list_append(it->parent->items, it);
2899         if (!it2) it2 = it->parent;
2900         wd->items =
2901           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
2902                                       EINA_INLIST_GET(it2));
2903         if( it->parent->group_item)
2904           _set_groupitem( it, it->parent->group_item );
2905         it->rel = it2;
2906         it->rel->relcount++;
2907         it->before = 0;
2908      }
2909    _item_queue(wd, it);
2910    return it;
2911 }
2912
2913 /**
2914  * Append item to the end of the genlist with Group Item
2915  *
2916  * This appends the given item to the end of the list or the end of the
2917  * children if the parent is given.
2918  *
2919  * @param obj The genlist object
2920  * @param itc The item class for the item
2921  * @param data The item data
2922  * @param parent The parent item, or NULL if none
2923  * @param flags Item flags
2924  * @param git Group Item
2925  * @param func Convenience function called when item selected
2926  * @param func_data Data passed to @p func above.
2927  * @return A handle to the item added or NULL if not possible
2928  *
2929  * @ingroup Genlist
2930  */
2931 EAPI Elm_Genlist_Item *
2932 elm_genlist_item_append_with_group(Evas_Object *obj, const Elm_Genlist_Item_Class *itc,
2933                         const void *data, Elm_Genlist_Item *parent,
2934                         Elm_Genlist_Item_Flags flags, Elm_Genlist_GroupItem *git,
2935                         Evas_Smart_Cb func, const void *func_data)
2936 {
2937     ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2938     Widget_Data *wd = elm_widget_data_get(obj);
2939     Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func, func_data);
2940     if (!wd) return NULL;
2941     if (!it) return NULL;
2942     if (!it->parent)
2943     {
2944       wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
2945       it->rel = NULL;
2946       it->before = 0;
2947     }
2948     else
2949     {
2950       Elm_Genlist_Item *it2 = NULL;
2951       Eina_List *ll = eina_list_last(it->parent->items);
2952       if (ll) it2 = ll->data;
2953       it->parent->items = eina_list_append(it->parent->items, it);
2954       if (!it2) it2 = it->parent;
2955       wd->items =
2956         eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
2957                                     EINA_INLIST_GET(it2));
2958       if( it->parent->group_item)
2959         _set_groupitem( it, it->parent->group_item );
2960       it->rel = it2;
2961       it->rel->relcount++;
2962       it->before = 0;
2963     }
2964     _set_groupitem( it, git );
2965     _item_queue(wd, it);
2966     return it;
2967 }
2968
2969 /**
2970  * Prepend item at start of the genlist
2971  *
2972  * This adds an item to the beginning of the list or beginning of the children
2973  * of the parent if given.
2974  *
2975  * @param obj The genlist object
2976  * @param itc The item class for the item
2977  * @param data The item data
2978  * @param parent The parent item, or NULL if none
2979  * @param flags Item flags
2980  * @param func Convenience function called when item selected
2981  * @param func_data Data passed to @p func above.
2982  * @return A handle to the item added or NULL if not possible
2983  *
2984  * @ingroup Genlist
2985  */
2986 EAPI Elm_Genlist_Item *
2987 elm_genlist_item_prepend(Evas_Object *obj, const Elm_Genlist_Item_Class *itc,
2988                          const void *data, Elm_Genlist_Item *parent,
2989                          Elm_Genlist_Item_Flags flags,
2990                          Evas_Smart_Cb func, const void *func_data)
2991 {
2992    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2993    Widget_Data *wd = elm_widget_data_get(obj);
2994    Elm_Genlist_Item *it = _item_new(wd, itc, data, parent, flags, func, func_data);
2995    if (!wd) return NULL;
2996    if (!it) return NULL;
2997    if (!it->parent)
2998      wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
2999    else
3000      {
3001         printf("FIXME: 12 tree not handled yet\n");
3002      }
3003    it->rel = NULL;
3004    it->before = 1;
3005    _item_queue(wd, it);
3006    return it;
3007 }
3008
3009 /**
3010  * Insert item before another in the genlist
3011  *
3012  * This inserts an item before another in the list. It will be in the same tree
3013  * level as the item it is inseted before.
3014  *
3015  * @param obj The genlist object
3016  * @param itc The item class for the item
3017  * @param data The item data
3018  * @param before The item to insert before
3019  * @param flags Item flags
3020  * @param func Convenience function called when item selected
3021  * @param func_data Data passed to @p func above.
3022  * @return A handle to the item added or NULL if not possible
3023  *
3024  * @ingroup Genlist
3025  */
3026 EAPI Elm_Genlist_Item *
3027 elm_genlist_item_insert_before(Evas_Object *obj, const Elm_Genlist_Item_Class *itc,
3028                                const void *data, Elm_Genlist_Item *before,
3029                                Elm_Genlist_Item_Flags flags,
3030                                Evas_Smart_Cb func, const void *func_data)
3031 {
3032    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3033    Widget_Data *wd = elm_widget_data_get(obj);
3034    Elm_Genlist_Item *it = _item_new(wd, itc, data, NULL, flags, func, func_data);
3035    if (!wd) return NULL;
3036    if (!it) return NULL;
3037    if (!it->parent)
3038      wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), 
3039                                               EINA_INLIST_GET(before));
3040    else
3041      {
3042         printf("FIXME: 13 tree not handled yet\n");
3043      }
3044    it->rel = before;
3045    it->rel->relcount++;
3046    it->before = 1;
3047    _item_queue(wd, it);
3048    return it;
3049 }
3050
3051 /**
3052  * Insert and item after another in the genlst
3053  *
3054  * This inserts an item after another in the list. It will be in the same tree
3055  * level as the item it is inseted after.
3056  *
3057  * @param obj The genlist object
3058  * @param itc The item class for the item
3059  * @param data The item data
3060  * @param after The item to insert after
3061  * @param flags Item flags
3062  * @param func Convenience function called when item selected
3063  * @param func_data Data passed to @p func above.
3064  * @return A handle to the item added or NULL if not possible
3065  *
3066  * @ingroup Genlist
3067  */
3068 EAPI Elm_Genlist_Item *
3069 elm_genlist_item_insert_after(Evas_Object *obj, const Elm_Genlist_Item_Class *itc,
3070                               const void *data, Elm_Genlist_Item *after,
3071                               Elm_Genlist_Item_Flags flags,
3072                               Evas_Smart_Cb func, const void *func_data)
3073 {
3074    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3075    Widget_Data *wd = elm_widget_data_get(obj);
3076    Elm_Genlist_Item *it = _item_new(wd, itc, data, NULL, flags, func, func_data);
3077    if (!wd) return NULL;
3078    if (!it) return NULL;
3079    if (!it->parent)
3080      wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), 
3081                                              EINA_INLIST_GET(after));
3082    else
3083      {
3084         printf("FIXME: 14 tree not handled yet\n");
3085      }
3086    it->rel = after;
3087    it->rel->relcount++;
3088    it->before = 0;
3089    _item_queue(wd, it);
3090    return it;
3091 }
3092
3093 /**
3094  * Moves the Genlist Item
3095  */
3096 EAPI void
3097 elm_genlist_item_move_after(Elm_Genlist_Item *it, Elm_Genlist_Item *after )
3098 {
3099   if (!it) return;
3100
3101   it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
3102   _item_block_del(it);
3103
3104   if( after)
3105     {
3106     it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it),
3107                                                  EINA_INLIST_GET(after));
3108      it->rel = after;
3109       it->rel->relcount++;
3110     }
3111   else
3112   {
3113       it->wd->items = eina_inlist_prepend(it->wd->items, EINA_INLIST_GET(it));
3114     }
3115
3116     it->before = 1;
3117    _item_queue(it->wd, it);
3118 }
3119
3120 /**
3121  * Clear the genlist
3122  *
3123  * This clears all items in the list, leaving it empty.
3124  *
3125  * @param obj The genlist object
3126  *
3127  * @ingroup Genlist
3128  */
3129 EAPI void
3130 elm_genlist_clear(Evas_Object *obj)
3131 {
3132    ELM_CHECK_WIDTYPE(obj, widtype);
3133    Widget_Data *wd = elm_widget_data_get(obj);
3134    if (!wd) return;
3135
3136    while (wd->group_items)
3137    {
3138      _groupitem_remove((Elm_Genlist_GroupItem *)wd->group_items, EINA_FALSE);
3139
3140    }
3141    while (wd->items)
3142      {
3143         Elm_Genlist_Item *it = (Elm_Genlist_Item *)(wd->items);
3144
3145         wd->items = eina_inlist_remove(wd->items, wd->items);
3146         if (it->realized) _item_unrealize(it);
3147         if (it->itc->func.del) it->itc->func.del(it->data, it->wd->obj);
3148         if (it->long_timer) ecore_timer_del(it->long_timer);
3149         free(it);
3150      }
3151    while (wd->blocks)
3152      {
3153         Item_Block *itb = (Item_Block *)(wd->blocks);
3154
3155         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
3156         if (itb->items) eina_list_free(itb->items);
3157         free(itb);
3158      }
3159    if (wd->calc_job)
3160      {
3161         ecore_job_del(wd->calc_job);
3162         wd->calc_job = NULL;
3163      }
3164    if (wd->queue_idler)
3165      {
3166         ecore_idler_del(wd->queue_idler);
3167         wd->queue_idler = NULL;
3168      }
3169    if (wd->queue)
3170      {
3171         eina_list_free(wd->queue);
3172         wd->queue = NULL;
3173      }
3174    if (wd->selected)
3175      {
3176         eina_list_free(wd->selected);
3177         wd->selected = NULL;
3178      }
3179    wd->show_item = NULL;
3180    wd->pan_x = 0;
3181    wd->pan_y = 0;
3182    wd->minw = 0;
3183    wd->minh = 0;
3184    evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
3185    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
3186    _sizing_eval(obj);
3187 }
3188
3189 /**
3190  * Enable or disable multi-select in the genlist
3191  *
3192  * This enables (EINA_TRUE) or disableds (EINA_FALSE) multi-select in the list. This allows
3193  * more than 1 item to be selected.
3194  *
3195  * @param obj The genlist object
3196  * @param multi Multi-select enable/disable
3197  *
3198  * @ingroup Genlist
3199  */
3200 EAPI void
3201 elm_genlist_multi_select_set(Evas_Object *obj, Eina_Bool multi)
3202 {
3203    ELM_CHECK_WIDTYPE(obj, widtype);
3204    Widget_Data *wd = elm_widget_data_get(obj);
3205    if (!wd) return;
3206    wd->multi = multi;
3207 }
3208
3209 /**
3210  * Gets if multi-select in genlist is enable or disable
3211  *
3212  * @param obj The genlist object
3213  * @return Multi-select enable/disable
3214  * (EINA_TRUE = enabled/EINA_FALSE = disabled)
3215  *
3216  * @ingroup Genlist
3217  */
3218 EAPI Eina_Bool
3219 elm_genlist_multi_select_get(const Evas_Object *obj)
3220 {
3221    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3222    Widget_Data *wd = elm_widget_data_get(obj);
3223    if (!wd) return EINA_FALSE;
3224    return wd->multi;
3225 }
3226
3227
3228 /**
3229  * Get the selectd item in the genlist
3230  *
3231  * This gets the selected item in the list (if multi-select is enabled only
3232  * the first item in the list is selected - which is not very useful, so see
3233  * elm_genlist_selected_items_get()for when multi-select is used).
3234  *
3235  * If no item is selected, NULL is returned.
3236  *
3237  * @param obj The genlist object
3238  * @return The selected item, or NULL if none.
3239  *
3240  * @ingroup Genlist
3241  */
3242 EAPI Elm_Genlist_Item *
3243 elm_genlist_selected_item_get(const Evas_Object *obj)
3244 {
3245    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3246    Widget_Data *wd = elm_widget_data_get(obj);
3247    if (!wd) return NULL;
3248    if (wd->selected) return wd->selected->data;
3249    return NULL;
3250 }
3251
3252 /**
3253  * Get a list of selected items in the genlist
3254  *
3255  * This retgurns a list of the selected items. This list pointer is only valid
3256  * so long as no items are selected or unselected (or unselected implicitly
3257  * by deletion). The list contains Elm_Genlist_Item pointers.
3258  *
3259  * @param obj The genlist object
3260  * @return The list of selected items, nor NULL if none are selected.
3261  *
3262  * @ingroup Genlist
3263  */
3264 EAPI const Eina_List *
3265 elm_genlist_selected_items_get(const Evas_Object *obj)
3266 {
3267    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3268    Widget_Data *wd = elm_widget_data_get(obj);
3269    if (!wd) return NULL;
3270    return wd->selected;
3271 }
3272
3273 /**
3274  * Get a list of realized items in genlist
3275  *
3276  * This returns a list of the realized items in the genlist. The list
3277  * contains Elm_Genlist_Item pointers. The list must be freed by the
3278  * caller when done with eina_list_free(). The item pointers in the list
3279  * are only vallid so long as those items are not deleted or the genlist is
3280  * not deleted.
3281  *
3282  * @param obj The genlist object
3283  * @return The list of realized items, nor NULL if none are realized.
3284  *
3285  * @ingroup Genlist
3286  */
3287 EAPI Eina_List *
3288 elm_genlist_realized_items_get(const Evas_Object *obj)
3289 {
3290    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3291    Widget_Data *wd = elm_widget_data_get(obj);
3292    Eina_List *list = NULL;
3293    Item_Block *itb;
3294    Eina_Bool done = EINA_FALSE;
3295    if (!wd) return NULL;
3296    EINA_INLIST_FOREACH(wd->blocks, itb)
3297      {
3298         if (itb->realized)
3299           {
3300              Eina_List *l;
3301              Elm_Genlist_Item *it;
3302              
3303              done = 1;
3304              EINA_LIST_FOREACH(itb->items, l, it)
3305                {
3306                   if (it->realized) list = eina_list_append(list, it);
3307                }
3308           }
3309         else
3310           {
3311              if (done) break;
3312           }
3313      }
3314    return list;
3315 }
3316
3317 /**
3318  * Get the item that is at the x, y canvas coords
3319  *
3320  * This returns the item at the given coordinates (which are canvas relative
3321  * not object-relative). If an item is at that coordinate, that item handle
3322  * is returned, and if @p posret is not NULL, the integer pointed to is set
3323  * to a value of -1, 0 or 1, depending if the coordinate is on the upper
3324  * portion of that item (-1), on the middle section (0) or on the lower part
3325  * (1). If NULL is returned as an item (no item found there), then posret
3326  * may indicate -1 or 1 based if the coordinate is above or below all items
3327  * respectively in the genlist.
3328  *
3329  * @param it The item
3330  * @param x The input x coordinate
3331  * @param y The input y coordinate
3332  * @param posret The position relative to the item returned here
3333  * @return The item at the coordinates or NULL if none
3334  *
3335  * @ingroup Genlist
3336  */
3337 EAPI Elm_Genlist_Item *
3338 elm_genlist_at_xy_item_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *posret)
3339 {
3340    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3341    Widget_Data *wd = elm_widget_data_get(obj);
3342    Evas_Coord ox, oy, ow, oh;
3343    Item_Block *itb;
3344    Evas_Coord lasty;
3345    if (!wd) return NULL;
3346    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
3347    lasty = oy;
3348    EINA_INLIST_FOREACH(wd->blocks, itb)
3349      {
3350         Eina_List *l;
3351         Elm_Genlist_Item *it;
3352
3353         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
3354                                  oy + itb->y - itb->wd->pan_y,
3355                                  itb->w, itb->h, x, y, 1, 1))
3356           continue;
3357         EINA_LIST_FOREACH(itb->items, l, it)
3358           {
3359              Evas_Coord itx, ity;
3360
3361              itx = ox + itb->x + it->x - itb->wd->pan_x;
3362              ity = oy + itb->y + it->y - itb->wd->pan_y;
3363              if (ELM_RECTS_INTERSECT(itx, ity, it->w, it->h, x, y, 1, 1))
3364                {
3365                   if (posret)
3366                     {
3367                        if (y <= (ity + (it->h / 4))) *posret = -1;
3368                        else if (y >= (ity + it->h - (it->h / 4))) *posret = 1;
3369                        else *posret = 0;
3370                     }
3371                   return it;
3372                }
3373              lasty = ity + it->h;
3374           }
3375      }
3376    if (posret)
3377      {
3378         if (y > lasty) *posret = 1;
3379         else *posret = -1;
3380      }
3381    return NULL;
3382 }
3383
3384 /**
3385  * Get the first item in the genlist
3386  *
3387  * This returns the first item in the list.
3388  *
3389  * @param obj The genlist object
3390  * @return The first item, or NULL if none
3391  *
3392  * @ingroup Genlist
3393  */
3394 EAPI Elm_Genlist_Item *
3395 elm_genlist_first_item_get(const Evas_Object *obj)
3396 {
3397    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3398    Widget_Data *wd = elm_widget_data_get(obj);
3399    if (!wd) return NULL;
3400    if (!wd->items) return NULL;
3401    Elm_Genlist_Item *it = (Elm_Genlist_Item *)(wd->items);
3402    while ((it) && (it->delete_me))
3403      it = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->next);
3404    return it;
3405 }
3406
3407 /**
3408  * Get the last item in the genlist
3409  *
3410  * This returns the last item in the list.
3411  *
3412  * @return The last item, or NULL if none
3413  *
3414  * @ingroup Genlist
3415  */
3416 EAPI Elm_Genlist_Item *
3417 elm_genlist_last_item_get(const Evas_Object *obj)
3418 {
3419    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3420    Widget_Data *wd = elm_widget_data_get(obj);
3421    if (!wd->items) return NULL;
3422    Elm_Genlist_Item *it = (Elm_Genlist_Item *)(wd->items->last);
3423    if (!wd) return NULL;
3424    while ((it) && (it->delete_me))
3425      it = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->prev);
3426    return it;
3427 }
3428
3429 /**
3430  * Get the next item in the genlist
3431  *
3432  * This returns the item after the item @p it.
3433  *
3434  * @param it The item
3435  * @return The item after @p it, or NULL if none
3436  *
3437  * @ingroup Genlist
3438  */
3439 EAPI Elm_Genlist_Item *
3440 elm_genlist_item_next_get(const Elm_Genlist_Item *it)
3441 {
3442    while (it)
3443      {
3444         it = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->next);
3445         if ((it) && (!it->delete_me)) break;
3446      }
3447    return (Elm_Genlist_Item *)it;
3448 }
3449
3450 /**
3451  * Get the previous item in the genlist
3452  *
3453  * This returns the item before the item @p it.
3454  *
3455  * @param it The item
3456  * @return The item before @p it, or NULL if none
3457  *
3458  * @ingroup Genlist
3459  */
3460 EAPI Elm_Genlist_Item *
3461 elm_genlist_item_prev_get(const Elm_Genlist_Item *it)
3462 {
3463    while (it)
3464      {
3465         it = (Elm_Genlist_Item *)(EINA_INLIST_GET(it)->prev);
3466         if ((it) && (!it->delete_me)) break;
3467      }
3468    return (Elm_Genlist_Item *)it;
3469 }
3470
3471 /**
3472  * Get the genlist object from an item
3473  *
3474  * This returns the genlist object itself that an item belongs to.
3475  *
3476  * @param it The item
3477  * @return The genlist object
3478  *
3479  * @ingroup Genlist
3480  */
3481 EAPI Evas_Object *
3482 elm_genlist_item_genlist_get(const Elm_Genlist_Item *it)
3483 {
3484    if (!it) return NULL;
3485    return it->wd->obj;
3486 }
3487
3488 /**
3489  * Get the parent item of the given item
3490  *
3491  * This returns the prent item of the item @p it given.
3492  *
3493  * @param it The item
3494  * @return The parent of the item or NULL if none
3495  *
3496  * @ingroup Genlist
3497  */
3498 EAPI Elm_Genlist_Item *
3499 elm_genlist_item_parent_get(const Elm_Genlist_Item *it)
3500 {
3501    if (!it) return NULL;
3502    return it->parent;
3503 }
3504
3505 /**
3506  * Clear all sub-items (children) of the given item
3507  *
3508  * This clears all items that are children (or their descendants) of the
3509  * given item @p it.
3510  *
3511  * @param it The item
3512  *
3513  * @ingroup Genlist
3514  */
3515 EAPI void
3516 elm_genlist_item_subitems_clear(Elm_Genlist_Item *it)
3517 {
3518    Eina_List *tl = NULL, *l;
3519    Elm_Genlist_Item *it2;
3520
3521    if (!it) return;
3522    EINA_LIST_FOREACH(it->items, l, it2)
3523      tl = eina_list_append(tl, it2);
3524    EINA_LIST_FREE(tl, it2)
3525      elm_genlist_item_del(it2);
3526 }
3527
3528 /**
3529  * Set the selected state of an item
3530  *
3531  * This sets the selected state (1 selected, 0 not selected) of the given
3532  * item @p it.
3533  *
3534  * @param it The item
3535  * @param selected The slected state
3536  *
3537  * @ingroup Genlist
3538  */
3539 EAPI void
3540 elm_genlist_item_selected_set(Elm_Genlist_Item *it, Eina_Bool selected)
3541 {
3542    Widget_Data *wd = elm_widget_data_get(it->wd->obj);
3543    if (!wd) return;
3544    if (!it) return;
3545    if (it->delete_me) return;
3546    selected = !!selected;
3547    if (it->selected == selected) return;
3548
3549    if (selected)
3550      {
3551         if (!wd->multi)
3552           {
3553              while (wd->selected)
3554                _item_unselect(wd->selected->data);
3555           }
3556         _item_hilight(it);
3557         _item_select(it);
3558      }
3559    else
3560      _item_unselect(it);
3561 }
3562
3563 /**
3564  * Get the selected state of an item
3565  *
3566  * This gets the selected state of an item (1 selected, 0 not selected).
3567  *
3568  * @param it The item
3569  * @return The selected state
3570  *
3571  * @ingroup Genlist
3572  */
3573 EAPI Eina_Bool
3574 elm_genlist_item_selected_get(const Elm_Genlist_Item *it)
3575 {
3576    if (!it) return EINA_FALSE;
3577    return it->selected;
3578 }
3579
3580 /**
3581  * Sets the expanded state of an item (if it's a parent)
3582  *
3583  * This expands or contracts a parent iterm (thus showing or hiding the
3584  * children).
3585  *
3586  * @param it The item
3587  * @param expanded The expanded state (1 expanded, 0 not expanded).
3588  *
3589  * @ingroup Genlist
3590  */
3591 EAPI void
3592 elm_genlist_item_expanded_set(Elm_Genlist_Item *it, Eina_Bool expanded)
3593 {
3594    if (!it) return;
3595    if (it->expanded == expanded) return;
3596    it->expanded = expanded;
3597    if (it->expanded)
3598      {
3599         if (it->realized)
3600           edje_object_signal_emit(it->base, "elm,state,expanded", "elm");
3601         evas_object_smart_callback_call(it->wd->obj, "expanded", it);
3602      }
3603    else
3604      {
3605         if (it->realized)
3606           edje_object_signal_emit(it->base, "elm,state,contracted", "elm");
3607         evas_object_smart_callback_call(it->wd->obj, "contracted", it);
3608      }
3609 }
3610
3611 /**
3612  * Get the expanded state of an item
3613  *
3614  * This gets the expanded state of an item
3615  *
3616  * @param it The item
3617  * @return Thre expanded state
3618  *
3619  * @ingroup Genlist
3620  */
3621 EAPI Eina_Bool
3622 elm_genlist_item_expanded_get(const Elm_Genlist_Item *it)
3623 {
3624    if (!it) return EINA_FALSE;
3625    return it->expanded;
3626 }
3627
3628 /**
3629  * Sets the disabled state of an item.
3630  *
3631  * A disabled item cannot be selected or unselected. It will also change
3632  * appearance to appear disabled. This sets the disabled state (1 disabled, 0
3633  * not disabled).
3634  *
3635  * @param it The item
3636  * @param disabled The disabled state
3637  *
3638  * @ingroup Genlist
3639  */
3640 EAPI void
3641 elm_genlist_item_disabled_set(Elm_Genlist_Item *it, Eina_Bool disabled)
3642 {
3643    if (!it) return;
3644    if (it->disabled == disabled) return;
3645    if (it->delete_me) return;
3646    it->disabled = disabled;
3647    if (it->realized)
3648      {
3649         if (it->disabled)
3650           edje_object_signal_emit(it->base, "elm,state,disabled", "elm");
3651         else
3652           edje_object_signal_emit(it->base, "elm,state,enabled", "elm");
3653      }
3654 }
3655
3656 /**
3657  * Get the disabled state of an item
3658  *
3659  * This gets the disabld state of the given item.
3660  *
3661  * @param it The item
3662  * @return The disabled state
3663  *
3664  * @ingroup Genlist
3665  */
3666 EAPI Eina_Bool
3667 elm_genlist_item_disabled_get(const Elm_Genlist_Item *it)
3668 {
3669    if (!it) return EINA_FALSE;
3670    if (it->delete_me) return EINA_FALSE;
3671    return it->disabled;
3672 }
3673
3674 /**
3675  * Sets the display only state of an item.
3676  *
3677  * A display only item cannot be selected or unselected. It is for display
3678  * only and not selecting or otherwise clicking, dragging etc. by the user,
3679  * thus finger size rules will not be applied to this item.
3680  *
3681  * @param it The item
3682  * @param display_only The display only state
3683  *
3684  * @ingroup Genlist
3685  */
3686 EAPI void
3687 elm_genlist_item_display_only_set(Elm_Genlist_Item *it, Eina_Bool display_only)
3688 {
3689    if (!it) return;
3690    if (!it->block) return;
3691    if (it->display_only == display_only) return;
3692    if (it->delete_me) return;
3693    it->display_only = display_only;
3694    it->mincalcd = EINA_FALSE;
3695    it->updateme = EINA_TRUE;
3696    it->block->updateme = EINA_TRUE;
3697    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
3698    it->wd->update_job = ecore_job_add(_update_job, it->wd);
3699 }
3700
3701 /**
3702  * Get the display only state of an item
3703  *
3704  * This gets the display only state of the given item.
3705  *
3706  * @param it The item
3707  * @return The display only state
3708  *
3709  * @ingroup Genlist
3710  */
3711 EAPI Eina_Bool
3712 elm_genlist_item_display_only_get(const Elm_Genlist_Item *it)
3713 {
3714    if (!it) return EINA_FALSE;
3715    if (it->delete_me) return EINA_FALSE;
3716    return it->display_only;
3717 }
3718
3719 /**
3720  * Show the given item
3721  *
3722  * This causes genlist to jump to the given item @p it and show it (by scrolling),
3723  * if it is not fully visible.
3724  *
3725  * @param it The item
3726  *
3727  * @ingroup Genlist
3728  */
3729 EAPI void
3730 elm_genlist_item_show(Elm_Genlist_Item *it)
3731 {
3732    if (!it) return;
3733    if (it->delete_me) return;
3734    if ((it->queued) || (!it->mincalcd))
3735      {
3736         it->wd->show_item = it;
3737         it->wd->bring_in = 1;
3738         it->showme = EINA_TRUE;
3739         return;
3740      }
3741    if (it->wd->show_item)
3742      {
3743         it->wd->show_item->showme = EINA_FALSE;
3744         it->wd->show_item = NULL;
3745      }
3746    elm_smart_scroller_child_region_show(it->wd->scr,
3747                                         it->x + it->block->x,
3748                                         it->y + it->block->y,
3749                                         it->block->w, it->h);
3750 }
3751
3752 /**
3753  * Bring in the given item
3754  *
3755  * This causes genlist to jump to the given item @p it and show it (by scrolling),
3756  * if it is not fully visible. This may use animation to do so and take a
3757  * period of time
3758  *
3759  * @param it The item
3760  *
3761  * @ingroup Genlist
3762  */
3763 EAPI void
3764 elm_genlist_item_bring_in(Elm_Genlist_Item *it)
3765 {
3766    if (!it) return;
3767    if (it->delete_me) return;
3768    if ((it->queued) || (!it->mincalcd))
3769      {
3770         it->wd->show_item = it;
3771         it->wd->bring_in = 1;
3772         it->showme = EINA_TRUE;
3773         return;
3774      }
3775    if (it->wd->show_item)
3776      {
3777         it->wd->show_item->showme = EINA_FALSE;
3778         it->wd->show_item = NULL;
3779      }
3780    elm_smart_scroller_region_bring_in(it->wd->scr,
3781                                       it->x + it->block->x,
3782                                       it->y + it->block->y,
3783                                       it->block->w, it->h);
3784 }
3785
3786 /**
3787  * Show the given item at the top
3788  *
3789  * This causes genlist to jump to the given item @p it and show it (by scrolling),
3790  * if it is not fully visible.
3791  *
3792  * @param it The item
3793  *
3794  * @ingroup Genlist
3795  */
3796 EAPI void
3797 elm_genlist_item_top_show(Elm_Genlist_Item *it)
3798 {
3799    Evas_Coord ow, oh;
3800
3801    if (!it) return;
3802    if (it->delete_me) return;
3803    if ((it->queued) || (!it->mincalcd))
3804      {
3805         it->wd->show_item = it;
3806         it->wd->bring_in = 1;
3807         it->showme = EINA_TRUE;
3808         return;
3809      }
3810    if (it->wd->show_item)
3811      {
3812         it->wd->show_item->showme = EINA_FALSE;
3813         it->wd->show_item = NULL;
3814      }
3815    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
3816    elm_smart_scroller_child_region_show(it->wd->scr,
3817                                         it->x + it->block->x,
3818                                         it->y + it->block->y,
3819                                         it->block->w, oh);
3820 }
3821
3822 /**
3823  * Bring in the given item at the top
3824  *
3825  * This causes genlist to jump to the given item @p it and show it (by scrolling),
3826  * if it is not fully visible. This may use animation to do so and take a
3827  * period of time
3828  *
3829  * @param it The item
3830  *
3831  * @ingroup Genlist
3832  */
3833 EAPI void
3834 elm_genlist_item_top_bring_in(Elm_Genlist_Item *it)
3835 {
3836    Evas_Coord ow, oh;
3837
3838    if (!it) return;
3839    if (it->delete_me) return;
3840    if ((it->queued) || (!it->mincalcd))
3841      {
3842         it->wd->show_item = it;
3843         it->wd->bring_in = 1;
3844         it->showme = EINA_TRUE;
3845         return;
3846      }
3847    if (it->wd->show_item)
3848      {
3849         it->wd->show_item->showme = EINA_FALSE;
3850         it->wd->show_item = NULL;
3851      }
3852    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
3853    elm_smart_scroller_region_bring_in(it->wd->scr,
3854                                       it->x + it->block->x,
3855                                       it->y + it->block->y,
3856                                       it->block->w, oh);
3857 }
3858
3859 /**
3860  * Show the given item at the middle
3861  *
3862  * This causes genlist to jump to the given item @p it and show it (by scrolling),
3863  * if it is not fully visible.
3864  *
3865  * @param it The item
3866  *
3867  * @ingroup Genlist
3868  */
3869 EAPI void
3870 elm_genlist_item_middle_show(Elm_Genlist_Item *it)
3871 {
3872    Evas_Coord ow, oh;
3873
3874    if (!it) return;
3875    if (it->delete_me) return;
3876    if ((it->queued) || (!it->mincalcd))
3877      {
3878         it->wd->show_item = it;
3879         it->wd->bring_in = 1;
3880         it->showme = EINA_TRUE;
3881         return;
3882      }
3883    if (it->wd->show_item)
3884      {
3885         it->wd->show_item->showme = EINA_FALSE;
3886         it->wd->show_item = NULL;
3887      }
3888    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
3889    elm_smart_scroller_child_region_show(it->wd->scr,
3890                                         it->x + it->block->x,
3891                          it->y + it->block->y - oh/2 + it->h/2,
3892                                         it->block->w, oh);
3893 }
3894
3895
3896 /**
3897  * Bring in the given item at the middle
3898  *
3899  * This causes genlist to jump to the given item @p it and show it (by scrolling),
3900  * if it is not fully visible. This may use animation to do so and take a
3901  * period of time
3902  *
3903  * @param it The item
3904  *
3905  * @ingroup Genlist
3906  */
3907 EAPI void
3908 elm_genlist_item_middle_bring_in(Elm_Genlist_Item *it)
3909 {
3910    Evas_Coord ow, oh;
3911
3912    if (!it) return;
3913    if (it->delete_me) return;
3914    if ((it->queued) || (!it->mincalcd))
3915      {
3916         it->wd->show_item = it;
3917         it->wd->bring_in = 1;
3918         it->showme = EINA_TRUE;
3919         return;
3920      }
3921    if (it->wd->show_item)
3922      {
3923         it->wd->show_item->showme = EINA_FALSE;
3924         it->wd->show_item = NULL;
3925      }
3926    evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &ow, &oh);
3927    elm_smart_scroller_region_bring_in(it->wd->scr,
3928                                       it->x + it->block->x,
3929                                       it->y + it->block->y - oh/2 + it->h/2,
3930                                       it->block->w, oh);
3931 }
3932
3933 /**
3934  * Delete a given item
3935  *
3936  * This deletes the item from genlist and calls the genlist item del class
3937  * callback defined in the item class, if it is set.
3938  *
3939  * @param it The item
3940  *
3941  * @ingroup Genlist
3942  */
3943 EAPI void
3944 elm_genlist_item_del(Elm_Genlist_Item *it)
3945 {
3946    if (!it) return;
3947    if ((it->relcount > 0) || (it->walking > 0))
3948      {
3949         elm_genlist_item_subitems_clear(it);
3950         it->delete_me = EINA_TRUE;
3951         if (it->wd->show_item == it) it->wd->show_item = NULL;
3952         if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
3953         if (it->block)
3954           {
3955              if (it->realized) _item_unrealize(it);
3956              it->block->changed = EINA_TRUE;
3957              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
3958              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
3959           }
3960         if (it->itc->func.del) it->itc->func.del(it->data, it->wd->obj);
3961         return;
3962      }
3963    _item_del(it);
3964 }
3965
3966 /**
3967  * Set the data item from the genlist item
3968  *
3969  * This set the data value passed on the elm_genlist_item_append() and
3970  * related item addition calls. This function will also call
3971  * elm_genlist_item_update() so the item will be updated to reflect the
3972  * new data.
3973  *
3974  * @param it The item
3975  * @param data The new data pointer to set
3976  *
3977  * @ingroup Genlist
3978  */
3979 EAPI void
3980 elm_genlist_item_data_set(Elm_Genlist_Item *it, const void *data)
3981 {
3982    if (!it) return;
3983    it->data = data;
3984    elm_genlist_item_update(it);
3985 }
3986
3987 /**
3988  * Get the data item from the genlist item
3989  *
3990  * This returns the data value passed on the elm_genlist_item_append() and
3991  * related item addition calls.
3992  *
3993  * @param it The item
3994  * @return The data pointer provided when created
3995  *
3996  * @ingroup Genlist
3997  */
3998 EAPI const void *
3999 elm_genlist_item_data_get(const Elm_Genlist_Item *it)
4000 {
4001    if (!it) return NULL;
4002    return it->data;
4003 }
4004
4005 /**
4006  * Get the real evas object of the genlist item
4007  *
4008  * This returns the actual evas object used for the specified genlist item.
4009  * This may be NULL as it may not be created, and ma be deleted at any time
4010  * by genlist. Do not modify this object (move, resize, show, hide etc.) as
4011  * genlist is controlling it. This function is for querying, emitting
4012  * custom signals or hooking lower level callbacks for events. Do not
4013  * delete this object under any circumstances.
4014  *
4015  * @param it The item
4016  * @return The objct pointer
4017  *
4018  * @ingroup Genlist
4019  */
4020 EAPI const Evas_Object *
4021 elm_genlist_item_object_get(const Elm_Genlist_Item *it)
4022 {
4023    if (!it) return NULL;
4024    return it->base;
4025 }
4026
4027 /**
4028  * Update the contents of an item
4029  *
4030  * This updates an item by calling all the item class functions again to get
4031  * the icons, labels and states. Use this when he original item data has
4032  * changed and the changes are desired to be reflected.
4033  *
4034  * @param it The item
4035  *
4036  * @ingroup Genlist
4037  */
4038 EAPI void
4039 elm_genlist_item_update(Elm_Genlist_Item *it)
4040 {
4041    if (!it->block) return;
4042    if (it->delete_me) return;
4043    it->mincalcd = EINA_FALSE;
4044    it->updateme = EINA_TRUE;
4045    it->block->updateme = EINA_TRUE;
4046    if (it->wd->update_job) ecore_job_del(it->wd->update_job);
4047    it->wd->update_job = ecore_job_add(_update_job, it->wd);
4048 }
4049
4050 /**
4051  * This sets the horizontal stretching mode
4052  *
4053  * This sets the mode used for sizing items horizontally. Valid modes are
4054  * ELM_LIST_LIMIT and ELM_LIST_SCROLL. The default is ELM_LIST_SCROLL. This
4055  * mode means that if items are too wide to fit, the scroller will scroll
4056  * horizontally. Otherwise items are expanded to fill the width of the
4057  * viewport of the scroller. If it is ELM_LIST_LIMIT, Items will be expanded
4058  * to the viewport width and limited to that size.
4059  *
4060  * @param obj The genlist object
4061  * @param mode The mode to use
4062  *
4063  * @ingroup Genlist
4064  */
4065 EAPI void
4066 elm_genlist_horizontal_mode_set(Evas_Object *obj, Elm_List_Mode mode)
4067 {
4068    ELM_CHECK_WIDTYPE(obj, widtype);
4069    Widget_Data *wd = elm_widget_data_get(obj);
4070    if (!wd) return;
4071    if (wd->mode == mode) return;
4072    wd->mode = mode;
4073    _sizing_eval(obj);
4074 }
4075
4076 /**
4077  * Gets the horizontal stretching mode
4078  *
4079  * @param obj The genlist object
4080  * @return The mode to use
4081  * (ELM_LIST_LIMIT, ELM_LIST_SCROLL, ELM_LIST_LIMIT)
4082  *
4083  * @ingroup Genlist
4084  */
4085 EAPI Elm_List_Mode
4086 elm_genlist_horizontal_mode_get(const Evas_Object *obj)
4087 {
4088    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
4089    Widget_Data *wd = elm_widget_data_get(obj);
4090    if (!wd) return ELM_LIST_LAST;
4091    return wd->mode;
4092 }
4093
4094 /**
4095  * Set the always select mode.
4096  *
4097  * Items will only call their selection func and callback when first becoming
4098  * selected. Any further clicks will do nothing, unless you enable always
4099  * select with elm_genlist_always_select_mode_set(). This means even if
4100  * selected, every click will make the selected callbacks be called.
4101  *
4102  * @param obj The genlist object
4103  * @param always_select The always select mode
4104  * (EINA_TRUE = on, EINA_FALSE = off)
4105  *
4106  * @ingroup Genlist
4107  */
4108 EAPI void
4109 elm_genlist_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select)
4110 {
4111    ELM_CHECK_WIDTYPE(obj, widtype);
4112    Widget_Data *wd = elm_widget_data_get(obj);
4113    if (!wd) return;
4114    wd->always_select = always_select;
4115 }
4116
4117 /**
4118  * Get the always select mode.
4119  *
4120  * @param obj The genlist object
4121  * @return The always select mode
4122  * (EINA_TRUE = on, EINA_FALSE = off)
4123  *
4124  * @ingroup Genlist
4125  */
4126 EAPI Eina_Bool
4127 elm_genlist_always_select_mode_get(const Evas_Object *obj)
4128 {
4129    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4130    Widget_Data *wd = elm_widget_data_get(obj);
4131    if (!wd) return EINA_FALSE;
4132    return wd->always_select;
4133 }
4134
4135 /**
4136  * Set no select mode
4137  *
4138  * This will turn off the ability to select items entirely and they will
4139  * neither appear selected nor call selected callback functions.
4140  *
4141  * @param obj The genlist object
4142  * @param no_select The no select mode
4143  * (EINA_TRUE = on, EINA_FALSE = off)
4144  *
4145  * @ingroup Genlist
4146  */
4147 EAPI void
4148 elm_genlist_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select)
4149 {
4150    ELM_CHECK_WIDTYPE(obj, widtype);
4151    Widget_Data *wd = elm_widget_data_get(obj);
4152    if (!wd) return;
4153    wd->no_select = no_select;
4154 }
4155
4156 /**
4157  * Gets no select mode
4158  *
4159  * @param obj The genlist object
4160  * @return The no select mode
4161  * (EINA_TRUE = on, EINA_FALSE = off)
4162  *
4163  * @ingroup Genlist
4164  */
4165 EAPI Eina_Bool
4166 elm_genlist_no_select_mode_get(const Evas_Object *obj)
4167 {
4168    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4169    Widget_Data *wd = elm_widget_data_get(obj);
4170    if (!wd) return EINA_FALSE;
4171    return wd->no_select;
4172 }
4173
4174 /**
4175  * Set compress mode
4176  *
4177  * This will enable the compress mode where items are "compressed" horizontally
4178  * to fit the genlist scrollable viewport width.
4179  *
4180  * @param obj The genlist object
4181  * @param no_select The compress mode
4182  * (EINA_TRUE = on, EINA_FALSE = off)
4183  *
4184  * @ingroup Genlist
4185  */
4186 EAPI void
4187 elm_genlist_compress_mode_set(Evas_Object *obj, Eina_Bool compress)
4188 {
4189    ELM_CHECK_WIDTYPE(obj, widtype);
4190    Widget_Data *wd = elm_widget_data_get(obj);
4191    if (!wd) return;
4192    wd->compress = compress;
4193 }
4194
4195 /**
4196  * Get the compress mode
4197  *
4198  * @param obj The genlist object
4199  * @return The compress mode
4200  * (EINA_TRUE = on, EINA_FALSE = off)
4201  *
4202  * @ingroup Genlist
4203  */
4204 EAPI Eina_Bool
4205 elm_genlist_compress_mode_get(const Evas_Object *obj)
4206 {
4207    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4208    Widget_Data *wd = elm_widget_data_get(obj);
4209    if (!wd) return EINA_FALSE;
4210    return wd->compress;
4211 }
4212
4213 /**
4214  * Set bounce mode
4215  *
4216  * This will enable or disable the scroller bounce mode for the genlist. See 
4217  * elm_scroller_bounce_set() for details
4218  *
4219  * @param obj The genlist object
4220  * @param h_bounce Allow bounce horizontally
4221  * @param v_bounce Allow bounce vertically
4222  *
4223  * @ingroup Genlist
4224  */
4225 EAPI void
4226 elm_genlist_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
4227 {
4228    ELM_CHECK_WIDTYPE(obj, widtype);
4229    Widget_Data *wd = elm_widget_data_get(obj);
4230    if (!wd) return;
4231    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
4232 }
4233
4234 /**
4235  * Get the bounce mode
4236  *
4237  * @param obj The genlist object
4238  * @param h_bounce Allow bounce horizontally
4239  * @param v_bounce Allow bounce vertically
4240  *
4241  * @ingroup Genlist
4242  */
4243 EAPI void
4244 elm_genlist_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
4245 {
4246    ELM_CHECK_WIDTYPE(obj, widtype);
4247    Widget_Data *wd = elm_widget_data_get(obj);
4248    if (!wd) return;
4249    elm_smart_scroller_bounce_allow_get(obj, h_bounce, v_bounce);
4250 }
4251
4252 /**
4253  * Set homogenous mode
4254  *
4255  * This will enable the homogeneous mode where items are of the same height and width
4256  * so that genlist may do the lazy-loading at its maximum.  This implies 'compressed' mode
4257  *
4258  * @param obj The genlist object
4259  * @param homogeneous Assume the items within the genlist are of the same height and width
4260  * (EINA_TRUE = on, EINA_FALSE = off)
4261  *
4262  * @ingroup Genlist
4263  */
4264 EAPI void
4265 elm_genlist_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
4266 {
4267    ELM_CHECK_WIDTYPE(obj, widtype);
4268    Widget_Data *wd = elm_widget_data_get(obj);
4269    if (!wd) return;
4270    if (homogeneous) elm_genlist_compress_mode_set(obj, EINA_TRUE);
4271    wd->homogeneous = homogeneous;
4272 }
4273
4274 /**
4275  * Get the homogenous mode
4276  *
4277  * @param obj The genlist object
4278  * @return Assume the items within the genlist are of the same height and width
4279  * (EINA_TRUE = on, EINA_FALSE = off)
4280  *
4281  * @ingroup Genlist
4282  */
4283 EAPI Eina_Bool
4284 elm_genlist_homogeneous_get(const Evas_Object *obj)
4285 {
4286    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4287    Widget_Data *wd = elm_widget_data_get(obj);
4288    if (!wd) return EINA_FALSE;
4289    return wd->homogeneous;
4290 }
4291
4292 /**
4293  * Set the maximum number of items within an item block
4294  *
4295  * This will configure the block count to tune to the target with particular performance matrix.
4296  *
4297  * @param obj The genlist object
4298  * @param n   Maximum number of items within an item block
4299  *
4300  * @ingroup Genlist
4301  */
4302 EAPI void
4303 elm_genlist_block_count_set(Evas_Object *obj, int n)
4304 {
4305    ELM_CHECK_WIDTYPE(obj, widtype);
4306    Widget_Data *wd = elm_widget_data_get(obj);
4307    if (!wd) return;
4308    wd->max_items_per_block = n;
4309 }
4310
4311 /**
4312  * Get the maximum number of items within an item block
4313  *
4314  * @param obj The genlist object
4315  * @return Maximum number of items within an item block
4316  *
4317  * @ingroup Genlist
4318  */
4319 EAPI int
4320 elm_genlist_block_count_get(const Evas_Object *obj)
4321 {
4322    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4323    Widget_Data *wd = elm_widget_data_get(obj);
4324    if (!wd) return 0;
4325    return wd->max_items_per_block;
4326 }
4327
4328 /**
4329  * Set the Genlist Internal scroller scrollbar policy
4330  *
4331  * This sets the Genlist Internal scrollbar visibility policy.
4332  * ELM_SMART_SCROLLER_POLICY_AUTO means the scrollbar is made visible if it
4333  * is needed, and otherwise kept hidden. ELM_SMART_SCROLLER_POLICY_ON turns
4334  * it on all the time, and ELM_SMART_SCROLLER_POLICY_OFF always keeps it off.
4335  * This applies respectively for the horizontal and vertical scrollbars.
4336  *
4337  * @param obj The Genlist object
4338  * @param policy_h Horizontal scrollbar policy
4339  * @param policy_v Vertical scrollbar policy
4340  *
4341  * @ingroup Genlist
4342  */
4343 EAPI void
4344 elm_genlist_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
4345 {
4346    ELM_CHECK_WIDTYPE(obj, widtype);
4347    Widget_Data *wd = elm_widget_data_get(obj);
4348    if (!wd)  return;
4349
4350    const Elm_Scroller_Policy map[3] =
4351        {
4352            ELM_SMART_SCROLLER_POLICY_AUTO,
4353             ELM_SMART_SCROLLER_POLICY_ON,
4354             ELM_SMART_SCROLLER_POLICY_OFF
4355        };
4356    if ((policy_h < 0) || (policy_h >= 3) || (policy_v < 0) || (policy_v >= 3))
4357      return;
4358
4359    elm_smart_scroller_policy_set(wd->scr, map[policy_h], map[policy_v]);
4360 }
4361
4362
4363 EAPI void
4364 elm_genlist_set_edit_mode(Evas_Object *obj, int emode, Elm_Genlist_Edit_Class *edit_class )
4365 {
4366     Eina_List * realized_list;
4367     Elm_Genlist_Item *it;
4368     Eina_List *l;
4369
4370     ELM_CHECK_WIDTYPE(obj, widtype);
4371     Widget_Data *wd = elm_widget_data_get(obj);
4372     if (!wd) return;
4373     if( wd->edit_mode == emode ) return;
4374
4375     wd->edit_mode = emode;
4376
4377     wd->animate_edit_controls = 1;
4378     if( wd->edit_mode == ELM_GENLIST_EDIT_MODE_NONE)
4379     {
4380       if( wd->ed ) free (wd->ed);
4381       wd->ed = NULL;
4382     }
4383     else
4384     {
4385       if( !wd->ed )
4386         wd->ed = calloc(1, sizeof(Edit_Data));
4387
4388       wd->ed->ec = edit_class;
4389
4390       if( (wd->edit_mode & ELM_GENLIST_EDIT_MODE_DELETE) && !wd->ed->del_confirm)
4391       {
4392           wd->ed->del_confirm = elm_button_add(wd->obj);
4393           elm_button_label_set(wd->ed->del_confirm, "Delete");
4394           evas_object_smart_member_add(wd->ed->del_confirm, wd->pan_smart);
4395           edje_object_scale_set( wd->ed->del_confirm, elm_widget_scale_get(wd->ed->del_confirm) *
4396                                                         _elm_config->scale);
4397           evas_object_smart_callback_add(wd->ed->del_confirm, "clicked", _delete_confirm_cb, wd );
4398       }
4399     }
4400
4401     realized_list = elm_genlist_realized_items_get(obj);
4402
4403     EINA_LIST_FOREACH(realized_list, l, it)
4404     {
4405      _edit_controls_eval(it);
4406     }
4407
4408     if (wd->calc_job) ecore_job_del(wd->calc_job);
4409     wd->calc_job = ecore_job_add(_calc_job, wd);
4410 }