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