Elementary: Use !! to Eina_Bool substitution in EAPIs.
[framework/uifw/elementary.git] / src / lib / elm_gengrid.c
1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
3 #include "elm_priv.h"
4
5 /**
6  * @defgroup Gengrid Gengrid
7  *
8  * This widget aims to position objects in a grid layout while
9  * actually building only the visible ones, using the same idea as
10  * genlist: the user define a class for each item, specifying
11  * functions that will be called at object creation and deletion.
12  *
13  * A item in the Gengrid can have 0 or more text labels (they can be
14  * regular text or textblock - that's up to the style to determine), 0
15  * or more icons (which are simply objects swallowed into the Gengrid
16  * item) and 0 or more boolean states that can be used for check,
17  * radio or other indicators by the edje theme style.  A item may be
18  * one of several styles (Elementary provides 1 by default -
19  * "default", but this can be extended by system or application custom
20  * themes/overlays/extensions).
21  *
22  * In order to implement the ability to add and delete items on the
23  * fly, Gengrid implements a class/callback system where the
24  * application provides a structure with information about that type
25  * of item (Gengrid may contain multiple different items with
26  * different classes, states and styles). Gengrid will call the
27  * functions in this struct (methods) when an item is "realized" (that
28  * is created dynamically while scrolling). All objects will simply be
29  * deleted when no longer needed with evas_object_del(). The
30  * Elm_GenGrid_Item_Class structure contains the following members:
31  *
32  * item_style - This is a constant string and simply defines the name
33  * of the item style. It must be specified and the default should be
34  * "default".
35  *
36  * func.label_get - This function is called when an actual item object
37  * is created. The data parameter is the one passed to
38  * elm_gengrid_item_append() and related item creation functions. The
39  * obj parameter is the Gengrid object and the part parameter is the
40  * string name of the text part in the edje design that is listed as
41  * one of the possible labels that can be set. This function must
42  * return a strdup'()ed string as the caller will free() it when done.
43  *
44  * func.icon_get - This function is called when an actual item object
45  * is created. The data parameter is the one passed to
46  * elm_gengrid_item_append() and related item creation functions. The
47  * obj parameter is the Gengrid object and the part parameter is the
48  * string name of the icon part in the edje design that is listed as
49  * one of the possible icons that can be set. This must return NULL
50  * for no object or a valid object. The object will be deleted by
51  * Gengrid on shutdown or when the item is unrealized.
52  *
53  * func.state_get - This function is called when an actual item object
54  * is created. The data parameter is the one passed to
55  * elm_gengrid_item_append() and related item creation functions. The
56  * obj parameter is the Gengrid object and the part parameter is the
57  * string name of th state part in the edje design that is listed as
58  * one of the possible states that can be set. Return 0 for false and
59  * 1 for true. Gengrid will emit a signal to the edje object with
60  * "elm,state,XXX,active" "elm" when true (the default is false),
61  * where XXX is the name of the part.
62  *
63  * func.del - This is called when elm_gengrid_item_del() is called on
64  * an item or elm_gengrid_clear() is called on the Gengrid. This is
65  * intended for use when actual Gengrid items are deleted, so any
66  * backing data attached to the item (e.g. its data parameter on
67  * creation) can be deleted.
68  *
69  * If the application wants multiple items to be able to be selected,
70  * elm_gengrid_multi_select_set() can enable this. If the Gengrid is
71  * single-selection only (the default), then
72  * elm_gengrid_select_item_get() will return the selected item, if
73  * any, or NULL if none is selected. If the Gengrid is multi-select
74  * then elm_gengrid_selected_items_get() will return a list (that is
75  * only valid as long as no items are modified (added, deleted,
76  * selected or unselected).
77  *
78  * If an item changes (state of boolean changes, label or icons
79  * change), then use elm_gengrid_item_update() to have Gengrid update
80  * the item with the new state. Gengrid will re-realize the item thus
81  * call the functions in the _Elm_Gengrid_Item_Class for that item.
82  *
83  * To programmatically (un)select an item use
84  * elm_gengrid_item_selected_set().  To get its selected state use
85  * elm_gengrid_item_selected_get(). To make an item disabled (unable to
86  * be selected and appear differently) use
87  * elm_gengrid_item_disabled_set() to set this and
88  * elm_gengrid_item_disabled_get() to get the disabled state.
89  *
90  * Cells will only call their selection func and callback when first
91  * becoming selected. Any further clicks will do nothing, unless you
92  * enable always select with
93  * elm_gengrid_always_select_mode_set(). This means event if selected,
94  * every click will make the selected callbacks be called.
95  * elm_gengrid_no_select_mode_set() will turn off the ability to
96  * select items entirely and they will neither appear selected nor
97  * call selected callback function.
98  *
99  * Remember that you can create new styles and add your own theme
100  * augmentation per application with elm_theme_extension_add(). If you
101  * absolutely must have a specific style that overrides any theme the
102  * user or system sets up you can use elm_theme_overlay_add() to add
103  * such a file.
104  *
105  * Signals that you can add callbacks for are:
106  *
107  * "clicked,double" - The user has double-clicked or pressed enter on
108  *                    an item. The event_infoparameter is the Gengrid item
109  *                    that was double-clicked.
110  * "selected" - The user has made an item selected. The event_info
111  *              parameter is the Gengrid item that was selected.
112  * "unselected" - The user has made an item unselected. The event_info
113  *                parameter is the Gengrid item that was unselected.
114  * "realized" - This is called when the item in the Gengrid is created
115  *              as a real evas object. event_info is the Gengrid item that was
116  *              created. The object may be deleted at any time, so it is up to
117  *              the caller to not use the object pointer from
118  *              elm_gengrid_item_object_get() in a way where it may point to
119  *              freed objects.
120  * "unrealized" - This is called when the real evas object for this item
121  *                is deleted. event_info is the Gengrid item that was created.
122  * "changed" - Called when an item is added, removed, resized or moved
123  *             and when gengrid is resized or horizontal property changes.
124  * "drag,start,up" - Called when the item in the Gengrid has been
125  *                   dragged (not scrolled) up.
126  * "drag,start,down" - Called when the item in the Gengrid has been
127  *                     dragged (not scrolled) down.
128  * "drag,start,left" - Called when the item in the Gengrid has been
129  *                     dragged (not scrolled) left.
130  * "drag,start,right" - Called when the item in the Gengrid has been
131  *                      dragged (not scrolled) right.
132  * "drag,stop" - Called when the item in the Gengrid has stopped being
133  *               dragged.
134  * "drag" - Called when the item in the Gengrid is being dragged.
135  * "scroll" - called when the content has been scrolled (moved).
136  * "scroll,drag,start" - called when dragging the content has started.
137  * "scroll,drag,stop" - called when dragging the content has stopped.
138  *
139  * --
140  * TODO:
141  * Handle non-homogeneous objects too.
142  */
143
144  typedef struct _Widget_Data Widget_Data;
145  typedef struct _Pan         Pan;
146
147 #define PRELOAD 1
148
149  struct _Elm_Gengrid_Item
150 {
151    Elm_Widget_Item               base;
152    EINA_INLIST;
153    Evas_Object                  *spacer;
154    const Elm_Gengrid_Item_Class *gic;
155    Ecore_Timer                  *long_timer;
156    Widget_Data                  *wd;
157    Eina_List                    *labels, *icons, *states, *icon_objs;
158    struct
159      {
160         Evas_Smart_Cb func;
161         const void   *data;
162      } func;
163
164    Evas_Coord x, y, dx, dy;
165    int        relcount;
166    int        walking;
167
168    struct
169      {
170         const void                 *data;
171         Elm_Tooltip_Item_Content_Cb content_cb;
172         Evas_Smart_Cb               del_cb;
173         const char                 *style;
174      } tooltip;
175
176    const char *mouse_cursor;
177
178    Eina_Bool   want_unrealize : 1;
179    Eina_Bool   realized : 1;
180    Eina_Bool   dragging : 1;
181    Eina_Bool   down : 1;
182    Eina_Bool   delete_me : 1;
183    Eina_Bool   display_only : 1;
184    Eina_Bool   disabled : 1;
185    Eina_Bool   selected : 1;
186    Eina_Bool   hilighted : 1;
187 };
188
189 struct _Widget_Data
190 {
191    Evas_Object      *self, *scr;
192    Evas_Object      *pan_smart;
193    Pan              *pan;
194    Eina_Inlist      *items;
195    Ecore_Job        *calc_job;
196    Eina_List        *selected;
197    Elm_Gengrid_Item *last_selected_item;
198    double            align_x, align_y;
199
200    Evas_Coord        pan_x, pan_y;
201    Evas_Coord        item_width, item_height; /* Each item size */
202    Evas_Coord        minw, minh; /* Total obj size */
203    unsigned int      nmax;
204    long              count;
205    int               walking;
206
207    Eina_Bool         horizontal : 1;
208    Eina_Bool         on_hold : 1;
209    Eina_Bool         longpressed : 1;
210    Eina_Bool         multi : 1;
211    Eina_Bool         no_select : 1;
212    Eina_Bool         wasselected : 1;
213    Eina_Bool         always_select : 1;
214    Eina_Bool         clear_me : 1;
215 };
216
217 #define ELM_GENGRID_ITEM_FROM_INLIST(item) \
218    ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Gengrid_Item) : NULL)
219
220 struct _Pan
221 {
222    Evas_Object_Smart_Clipped_Data __clipped_data;
223    Widget_Data                   *wd;
224 };
225
226 static const char *widtype = NULL;
227 static void      _item_hilight(Elm_Gengrid_Item *item);
228 static void      _item_unrealize(Elm_Gengrid_Item *item);
229 static void      _item_select(Elm_Gengrid_Item *item);
230 static void      _item_unselect(Elm_Gengrid_Item *item);
231 static void      _calc_job(void *data);
232 static void      _on_focus_hook(void        *data,
233                                 Evas_Object *obj);
234 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
235 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
236 static Eina_Bool _item_multi_select_left(Widget_Data *wd);
237 static Eina_Bool _item_multi_select_right(Widget_Data *wd);
238 static Eina_Bool _item_single_select_up(Widget_Data *wd);
239 static Eina_Bool _item_single_select_down(Widget_Data *wd);
240 static Eina_Bool _item_single_select_left(Widget_Data *wd);
241 static Eina_Bool _item_single_select_right(Widget_Data *wd);
242 static Eina_Bool _event_hook(Evas_Object       *obj,
243                              Evas_Object       *src,
244                              Evas_Callback_Type type,
245                              void              *event_info);
246 static Eina_Bool _deselect_all_items(Widget_Data *wd);
247
248 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
249 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
250
251 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
252 static const char SIG_SELECTED[] = "selected";
253 static const char SIG_UNSELECTED[] = "unselected";
254 static const char SIG_REALIZED[] = "realized";
255 static const char SIG_UNREALIZED[] = "unrealized";
256 static const char SIG_CHANGED[] = "changed";
257 static const char SIG_DRAG_START_UP[] = "drag,start,up";
258 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
259 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
260 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
261 static const char SIG_DRAG_STOP[] = "drag,stop";
262 static const char SIG_DRAG[] = "drag";
263 static const char SIG_SCROLL[] = "scroll";
264 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
265 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
266
267 static const Evas_Smart_Cb_Description _signals[] = {
268        {SIG_CLICKED_DOUBLE, ""},
269        {SIG_SELECTED, ""},
270        {SIG_UNSELECTED, ""},
271        {SIG_REALIZED, ""},
272        {SIG_UNREALIZED, ""},
273        {SIG_CHANGED, ""},
274        {SIG_DRAG_START_UP, ""},
275        {SIG_DRAG_START_DOWN, ""},
276        {SIG_DRAG_START_LEFT, ""},
277        {SIG_DRAG_START_RIGHT, ""},
278        {SIG_DRAG_STOP, ""},
279        {SIG_DRAG, ""},
280        {SIG_SCROLL, ""},
281        {SIG_SCROLL_DRAG_START, ""},
282        {SIG_SCROLL_DRAG_STOP, ""},
283        {NULL, NULL}
284 };
285
286
287
288 static Eina_Bool
289 _event_hook(Evas_Object       *obj,
290             Evas_Object *src   __UNUSED__,
291             Evas_Callback_Type type,
292             void              *event_info)
293 {
294    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
295    Evas_Event_Key_Down *ev = event_info;
296    Widget_Data *wd = elm_widget_data_get(obj);
297    if (!wd) return EINA_FALSE;
298    if (!wd->items) return EINA_FALSE;
299    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
300    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
301
302    Elm_Gengrid_Item *item = NULL;
303    Evas_Coord x = 0;
304    Evas_Coord y = 0;
305    Evas_Coord step_x = 0;
306    Evas_Coord step_y = 0;
307    Evas_Coord v_w = 0;
308    Evas_Coord v_h = 0;
309    Evas_Coord page_x = 0;
310    Evas_Coord page_y = 0;
311
312    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
313    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
314    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
315    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
316
317    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
318      {
319         if ((wd->horizontal) &&
320             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
321               (_item_multi_select_up(wd)))
322              || (_item_single_select_up(wd))))
323           {
324              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
325              return EINA_TRUE;
326           }
327         else if ((!wd->horizontal) &&
328                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
329                    (_item_multi_select_left(wd)))
330                   || (_item_single_select_left(wd))))
331           {
332              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
333              return EINA_TRUE;
334           }
335         else
336           x -= step_x;
337      }
338    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
339      {
340         if ((wd->horizontal) &&
341             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
342               (_item_multi_select_down(wd)))
343              || (_item_single_select_down(wd))))
344           {
345              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
346              return EINA_TRUE;
347           }
348         else if ((!wd->horizontal) &&
349                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
350                    (_item_multi_select_right(wd)))
351                   || (_item_single_select_right(wd))))
352           {
353              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
354              return EINA_TRUE;
355           }
356         else
357           x += step_x;
358      }
359    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
360      {
361         if ((wd->horizontal) &&
362             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
363               (_item_multi_select_left(wd)))
364              || (_item_single_select_left(wd))))
365           {
366              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
367              return EINA_TRUE;
368           }
369         else if ((!wd->horizontal) &&
370                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
371                    (_item_multi_select_up(wd)))
372                   || (_item_single_select_up(wd))))
373           {
374              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
375              return EINA_TRUE;
376           }
377         else
378           y -= step_y;
379      }
380    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
381      {
382         if ((wd->horizontal) &&
383             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
384               (_item_multi_select_right(wd)))
385              || (_item_single_select_right(wd))))
386           {
387              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
388              return EINA_TRUE;
389           }
390         else if ((!wd->horizontal) &&
391                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
392                    (_item_multi_select_down(wd)))
393                   || (_item_single_select_down(wd))))
394           {
395              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
396              return EINA_TRUE;
397           }
398         else
399           y += step_y;
400      }
401    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
402      {
403         item = elm_gengrid_first_item_get(obj);
404         elm_gengrid_item_bring_in(item);
405         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
406         return EINA_TRUE;
407      }
408    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
409      {
410         item = elm_gengrid_last_item_get(obj);
411         elm_gengrid_item_bring_in(item);
412         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
413         return EINA_TRUE;
414      }
415    else if ((!strcmp(ev->keyname, "Prior")) ||
416             (!strcmp(ev->keyname, "KP_Prior")))
417      {
418         if (wd->horizontal)
419           {
420              if (page_x < 0)
421                x -= -(page_x * v_w) / 100;
422              else
423                x -= page_x;
424           }
425         else
426           {
427              if (page_y < 0)
428                y -= -(page_y * v_h) / 100;
429              else
430                y -= page_y;
431           }
432      }
433    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
434      {
435         if (wd->horizontal)
436           {
437              if (page_x < 0)
438                x += -(page_x * v_w) / 100;
439              else
440                x += page_x;
441           }
442         else
443           {
444              if (page_y < 0)
445                y += -(page_y * v_h) / 100;
446              else
447                y += page_y;
448           }
449      }
450    else if (!strcmp(ev->keyname, "Escape"))
451      {
452         if (!_deselect_all_items(wd)) return EINA_FALSE;
453         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
454         return EINA_TRUE;
455      }
456    else if ((!strcmp(ev->keyname, "Return")) ||
457             (!strcmp(ev->keyname, "KP_Enter")) ||
458             (!strcmp(ev->keyname, "space")))
459      {
460         item = elm_gengrid_selected_item_get(obj);
461         evas_object_smart_callback_call(item->wd->self, SIG_CLICKED_DOUBLE, item);
462         evas_object_smart_callback_call(item->wd->self, "clicked", item); // will be removed
463      }
464    else return EINA_FALSE;
465
466    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
467    elm_smart_scroller_child_pos_set(wd->scr, x, y);
468    return EINA_TRUE;
469 }
470
471 static Eina_Bool
472 _deselect_all_items(Widget_Data *wd)
473 {
474    if (!wd->selected) return EINA_FALSE;
475    while(wd->selected)
476      elm_gengrid_item_selected_set(wd->selected->data, EINA_FALSE);
477
478    return EINA_TRUE;
479 }
480
481 static Eina_Bool
482 _item_multi_select_left(Widget_Data *wd)
483 {
484    if (!wd->selected) return EINA_FALSE;
485
486    Elm_Gengrid_Item *prev = elm_gengrid_item_prev_get(wd->last_selected_item);
487    if (!prev) return EINA_TRUE;
488    if (elm_gengrid_item_selected_get(prev))
489      {
490         elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
491         wd->last_selected_item = prev;
492         elm_gengrid_item_show(wd->last_selected_item);
493      }
494    else
495      {
496         elm_gengrid_item_selected_set(prev, EINA_TRUE);
497         elm_gengrid_item_show(prev);
498      }
499
500    return EINA_TRUE;
501 }
502
503 static Eina_Bool
504 _item_multi_select_right(Widget_Data *wd)
505 {
506    if (!wd->selected) return EINA_FALSE;
507
508    Elm_Gengrid_Item *next = elm_gengrid_item_next_get(wd->last_selected_item);
509    if (!next) return EINA_TRUE;
510    if (elm_gengrid_item_selected_get(next))
511      {
512         elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
513         wd->last_selected_item = next;
514         elm_gengrid_item_show(wd->last_selected_item);
515      }
516    else
517      {
518         elm_gengrid_item_selected_set(next, EINA_TRUE);
519         elm_gengrid_item_show(next);
520      }
521
522    return EINA_TRUE;
523 }
524
525 static Eina_Bool
526 _item_multi_select_up(Widget_Data *wd)
527 {
528    unsigned int i;
529    Eina_Bool r = EINA_TRUE;
530
531    if (!wd->selected) return EINA_FALSE;
532
533    for (i = 0; (r) && (i < wd->nmax); i++)
534      r &= _item_multi_select_left(wd);
535
536    return r;
537 }
538
539 static Eina_Bool
540 _item_multi_select_down(Widget_Data *wd)
541 {
542    unsigned int i;
543    Eina_Bool r = EINA_TRUE;
544
545    if (!wd->selected) return EINA_FALSE;
546
547    for (i = 0; (r) && (i < wd->nmax); i++)
548      r &= _item_multi_select_right(wd);
549
550    return r;
551 }
552
553 static Eina_Bool
554 _item_single_select_up(Widget_Data *wd)
555 {
556    unsigned int i;
557
558    Elm_Gengrid_Item *prev;
559
560    if (!wd->selected)
561      {
562         prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
563         while ((prev) && (prev->delete_me))
564           prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
565         elm_gengrid_item_selected_set(prev, EINA_TRUE);
566         elm_gengrid_item_show(prev);
567         return EINA_TRUE;
568      }
569    else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
570
571    if (!prev) return EINA_FALSE;
572
573    for (i = 1; i < wd->nmax; i++)
574      {
575         Elm_Gengrid_Item *tmp = elm_gengrid_item_prev_get(prev);
576         if (!tmp) return EINA_FALSE;
577         prev = tmp;
578      }
579
580    _deselect_all_items(wd);
581
582    elm_gengrid_item_selected_set(prev, EINA_TRUE);
583    elm_gengrid_item_show(prev);
584    return EINA_TRUE;
585 }
586
587 static Eina_Bool
588 _item_single_select_down(Widget_Data *wd)
589 {
590    unsigned int i;
591
592    Elm_Gengrid_Item *next;
593
594    if (!wd->selected)
595      {
596         next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
597         while ((next) && (next->delete_me))
598           next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
599         elm_gengrid_item_selected_set(next, EINA_TRUE);
600         elm_gengrid_item_show(next);
601         return EINA_TRUE;
602      }
603    else next = elm_gengrid_item_next_get(wd->last_selected_item);
604
605    if (!next) return EINA_FALSE;
606
607    for (i = 1; i < wd->nmax; i++)
608      {
609         Elm_Gengrid_Item *tmp = elm_gengrid_item_next_get(next);
610         if (!tmp) return EINA_FALSE;
611         next = tmp;
612      }
613
614    _deselect_all_items(wd);
615
616    elm_gengrid_item_selected_set(next, EINA_TRUE);
617    elm_gengrid_item_show(next);
618    return EINA_TRUE;
619 }
620
621 static Eina_Bool
622 _item_single_select_left(Widget_Data *wd)
623 {
624    Elm_Gengrid_Item *prev;
625    if (!wd->selected)
626      {
627         prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
628         while ((prev) && (prev->delete_me))
629           prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
630      }
631    else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
632
633    if (!prev) return EINA_FALSE;
634
635    _deselect_all_items(wd);
636
637    elm_gengrid_item_selected_set(prev, EINA_TRUE);
638    elm_gengrid_item_show(prev);
639    return EINA_TRUE;
640 }
641
642 static Eina_Bool
643 _item_single_select_right(Widget_Data *wd)
644 {
645    Elm_Gengrid_Item *next;
646    if (!wd->selected)
647      {
648         next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
649         while ((next) && (next->delete_me))
650           next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
651      }
652    else next = elm_gengrid_item_next_get(wd->last_selected_item);
653
654    if (!next) return EINA_FALSE;
655
656    _deselect_all_items(wd);
657
658    elm_gengrid_item_selected_set(next, EINA_TRUE);
659    elm_gengrid_item_show(next);
660    return EINA_TRUE;
661 }
662
663 static void
664 _on_focus_hook(void *data   __UNUSED__,
665                Evas_Object *obj)
666 {
667    Widget_Data *wd = elm_widget_data_get(obj);
668    if (!wd) return;
669    if (elm_widget_focus_get(obj))
670      {
671         edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
672         evas_object_focus_set(wd->self, EINA_TRUE);
673         if ((wd->selected) && (!wd->last_selected_item))
674           wd->last_selected_item = eina_list_data_get(wd->selected);
675      }
676    else
677      {
678         edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
679         evas_object_focus_set(wd->self, EINA_FALSE);
680      }
681 }
682
683 static void
684 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
685 {
686    Widget_Data *wd = elm_widget_data_get(obj);
687    Elm_Gengrid_Item *item;
688    if (!wd) return;
689    elm_smart_scroller_mirrored_set(wd->scr, rtl);
690    if (!wd->items) return;
691    item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
692
693    while (item)
694      {
695         edje_object_mirrored_set(item->base.view, rtl);
696         elm_gengrid_item_update(item);
697         item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
698      }
699 }
700
701 static void
702 _theme_hook(Evas_Object *obj)
703 {
704    Widget_Data *wd = elm_widget_data_get(obj);
705    if (!wd) return;
706    _elm_widget_mirrored_reload(obj);
707    _mirrored_set(obj, elm_widget_mirrored_get(obj));
708    elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
709                                        elm_widget_style_get(obj));
710 }
711
712 static void
713 _del_pre_hook(Evas_Object *obj)
714 {
715    Widget_Data *wd = elm_widget_data_get(obj);
716    if (!wd) return;
717    elm_gengrid_clear(obj);
718    evas_object_del(wd->pan_smart);
719    wd->pan_smart = NULL;
720 }
721
722 static void
723 _del_hook(Evas_Object *obj)
724 {
725    Widget_Data *wd = elm_widget_data_get(obj);
726    free(wd);
727 }
728
729 static void
730 _signal_emit_hook(Evas_Object *obj,
731                   const char  *emission,
732                   const char  *source)
733 {
734    Widget_Data *wd = elm_widget_data_get(obj);
735    if (!wd) return;
736    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
737                            emission, source);
738 }
739
740 static void
741 _mouse_move(void        *data,
742             Evas *evas   __UNUSED__,
743             Evas_Object *obj,
744             void        *event_info)
745 {
746    Elm_Gengrid_Item *item = data;
747    Evas_Event_Mouse_Move *ev = event_info;
748    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
749
750    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
751      {
752         if (!item->wd->on_hold)
753           {
754              item->wd->on_hold = EINA_TRUE;
755              if (!item->wd->wasselected)
756                _item_unselect(item);
757           }
758      }
759    if ((item->dragging) && (item->down))
760      {
761         if (item->long_timer)
762           {
763              ecore_timer_del(item->long_timer);
764              item->long_timer = NULL;
765           }
766         evas_object_smart_callback_call(item->wd->self, SIG_DRAG, item);
767         return;
768      }
769    if ((!item->down) || (item->wd->longpressed))
770      {
771         if (item->long_timer)
772           {
773              ecore_timer_del(item->long_timer);
774              item->long_timer = NULL;
775           }
776         return;
777      }
778    if (!item->display_only)
779      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
780    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
781    x = ev->cur.canvas.x - x;
782    y = ev->cur.canvas.y - y;
783    dx = x - item->dx;
784    adx = dx;
785    if (adx < 0) adx = -dx;
786    dy = y - item->dy;
787    ady = dy;
788    if (ady < 0) ady = -dy;
789    minw /= 2;
790    minh /= 2;
791    if ((adx > minw) || (ady > minh))
792      {
793         const char *left_drag, *right_drag;
794         if (!elm_widget_mirrored_get(item->wd->self))
795           {
796              left_drag = SIG_DRAG_START_LEFT;
797              right_drag = SIG_DRAG_START_RIGHT;
798           }
799         else
800           {
801              left_drag = SIG_DRAG_START_RIGHT;
802              right_drag = SIG_DRAG_START_LEFT;
803           }
804
805         item->dragging = 1;
806         if (item->long_timer)
807           {
808              ecore_timer_del(item->long_timer);
809              item->long_timer = NULL;
810           }
811         if (!item->wd->wasselected)
812           _item_unselect(item);
813         if (dy < 0)
814           {
815              if (ady > adx)
816                evas_object_smart_callback_call(item->wd->self, SIG_DRAG_START_UP,
817                                                item);
818              else
819                {
820                   if (dx < 0)
821                     evas_object_smart_callback_call(item->wd->self,
822                                                     left_drag, item);
823                }
824           }
825         else
826           {
827              if (ady > adx)
828                evas_object_smart_callback_call(item->wd->self,
829                                                SIG_DRAG_START_DOWN, item);
830              else
831                {
832                   if (dx < 0)
833                     evas_object_smart_callback_call(item->wd->self,
834                                                     left_drag, item);
835                   else
836                     evas_object_smart_callback_call(item->wd->self,
837                                                     right_drag, item);
838                }
839           }
840      }
841 }
842
843 static Eina_Bool
844 _long_press(void *data)
845 {
846    Elm_Gengrid_Item *item = data;
847
848    item->long_timer = NULL;
849    if ((item->disabled) || (item->dragging)) return ECORE_CALLBACK_CANCEL;
850    item->wd->longpressed = EINA_TRUE;
851    evas_object_smart_callback_call(item->wd->self, "longpressed", item);
852    return ECORE_CALLBACK_CANCEL;
853 }
854
855 static void
856 _mouse_down(void        *data,
857             Evas *evas   __UNUSED__,
858             Evas_Object *obj,
859             void        *event_info)
860 {
861    Elm_Gengrid_Item *item = data;
862    Evas_Event_Mouse_Down *ev = event_info;
863    Evas_Coord x, y;
864
865    if (ev->button != 1) return;
866    item->down = 1;
867    item->dragging = 0;
868    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
869    item->dx = ev->canvas.x - x;
870    item->dy = ev->canvas.y - y;
871    item->wd->longpressed = EINA_FALSE;
872    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) item->wd->on_hold = EINA_TRUE;
873    else item->wd->on_hold = EINA_FALSE;
874    item->wd->wasselected = item->selected;
875    _item_hilight(item);
876    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
877      {
878         evas_object_smart_callback_call(item->wd->self, SIG_CLICKED_DOUBLE, item);
879         evas_object_smart_callback_call(item->wd->self, "clicked", item); // will be removed
880      }
881    if (item->long_timer) ecore_timer_del(item->long_timer);
882    if (item->realized)
883      item->long_timer = ecore_timer_add(_elm_config->longpress_timeout,
884                                         _long_press, item);
885    else
886      item->long_timer = NULL;
887 }
888
889 static void
890 _mouse_up(void            *data,
891           Evas *evas       __UNUSED__,
892           Evas_Object *obj __UNUSED__,
893           void            *event_info)
894 {
895    Elm_Gengrid_Item *item = data;
896    Evas_Event_Mouse_Up *ev = event_info;
897    Eina_Bool dragged = EINA_FALSE;
898
899    if (ev->button != 1) return;
900    item->down = EINA_FALSE;
901    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) item->wd->on_hold = EINA_TRUE;
902    else item->wd->on_hold = EINA_FALSE;
903    if (item->long_timer)
904      {
905         ecore_timer_del(item->long_timer);
906         item->long_timer = NULL;
907      }
908    if (item->dragging)
909      {
910         item->dragging = EINA_FALSE;
911         evas_object_smart_callback_call(item->wd->self, SIG_DRAG_STOP, item);
912         dragged = EINA_TRUE;
913      }
914    if (item->wd->on_hold)
915      {
916         item->wd->longpressed = EINA_FALSE;
917         item->wd->on_hold = EINA_FALSE;
918         return;
919      }
920    if (item->wd->longpressed)
921      {
922         item->wd->longpressed = EINA_FALSE;
923         if (!item->wd->wasselected) _item_unselect(item);
924         item->wd->wasselected = EINA_FALSE;
925         return;
926      }
927    if (dragged)
928      {
929         if (item->want_unrealize) _item_unrealize(item);
930      }
931    if ((item->disabled) || (dragged)) return;
932    if (item->wd->multi)
933      {
934         if (!item->selected)
935           {
936              _item_hilight(item);
937              _item_select(item);
938           }
939         else _item_unselect(item);
940      }
941    else
942      {
943         if (!item->selected)
944           {
945              while (item->wd->selected)
946                _item_unselect(item->wd->selected->data);
947           }
948         else
949           {
950              const Eina_List *l, *l_next;
951              Elm_Gengrid_Item *item2;
952
953              EINA_LIST_FOREACH_SAFE(item->wd->selected, l, l_next, item2)
954                 if (item2 != item) _item_unselect(item2);
955           }
956         _item_hilight(item);
957         _item_select(item);
958      }
959 }
960
961 static void
962 _item_hilight(Elm_Gengrid_Item *item)
963 {
964    if ((item->wd->no_select) || (item->delete_me) || (item->hilighted)) return;
965    edje_object_signal_emit(item->base.view, "elm,state,selected", "elm");
966    item->hilighted = EINA_TRUE;
967 }
968
969 static void
970 _item_realize(Elm_Gengrid_Item *item)
971 {
972    char buf[1024];
973    char style[1024];
974
975    if ((item->realized) || (item->delete_me)) return;
976    item->base.view = edje_object_add(evas_object_evas_get(item->wd->self));
977    edje_object_scale_set(item->base.view, elm_widget_scale_get(item->wd->self) *
978                          _elm_config->scale);
979    edje_object_mirrored_set(item->base.view, elm_widget_mirrored_get(item->base.widget));
980    evas_object_smart_member_add(item->base.view, item->wd->pan_smart);
981    elm_widget_sub_object_add(item->wd->self, item->base.view);
982    snprintf(style, sizeof(style), "item/%s",
983             item->gic->item_style ? item->gic->item_style : "default");
984    _elm_theme_object_set(item->wd->self, item->base.view, "gengrid", style,
985                          elm_widget_style_get(item->wd->self));
986    item->spacer =
987       evas_object_rectangle_add(evas_object_evas_get(item->wd->self));
988    evas_object_color_set(item->spacer, 0, 0, 0, 0);
989    elm_widget_sub_object_add(item->wd->self, item->spacer);
990    evas_object_size_hint_min_set(item->spacer, 2 * _elm_config->scale, 1);
991    edje_object_part_swallow(item->base.view, "elm.swallow.pad", item->spacer);
992
993    if (item->gic->func.label_get)
994      {
995         const Eina_List *l;
996         const char *key;
997
998         item->labels =
999            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
1000                                                           "labels"));
1001         EINA_LIST_FOREACH(item->labels, l, key)
1002           {
1003              char *s = item->gic->func.label_get
1004                 ((void *)item->base.data, item->wd->self, l->data);
1005              if (s)
1006                {
1007                   edje_object_part_text_set(item->base.view, l->data, s);
1008                   free(s);
1009                }
1010           }
1011      }
1012
1013    if (item->gic->func.icon_get)
1014      {
1015         const Eina_List *l;
1016         const char *key;
1017
1018         item->icons =
1019            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
1020                                                           "icons"));
1021         EINA_LIST_FOREACH(item->icons, l, key)
1022           {
1023              Evas_Object *ic = item->gic->func.icon_get
1024                 ((void *)item->base.data, item->wd->self, l->data);
1025              if (ic)
1026                {
1027                   item->icon_objs = eina_list_append(item->icon_objs, ic);
1028                   edje_object_part_swallow(item->base.view, key, ic);
1029                   evas_object_show(ic);
1030                   elm_widget_sub_object_add(item->wd->self, ic);
1031                }
1032           }
1033      }
1034
1035    if (item->gic->func.state_get)
1036      {
1037         const Eina_List *l;
1038         const char *key;
1039
1040         item->states =
1041            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
1042                                                           "states"));
1043         EINA_LIST_FOREACH(item->states, l, key)
1044           {
1045              Eina_Bool on = item->gic->func.state_get
1046                 ((void *)item->base.data, item->wd->self, l->data);
1047              if (on)
1048                {
1049                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1050                   edje_object_signal_emit(item->base.view, buf, "elm");
1051                }
1052           }
1053      }
1054
1055    if ((!item->wd->item_width) && (!item->wd->item_height))
1056      {
1057         edje_object_size_min_restricted_calc(item->base.view,
1058                                              &item->wd->item_width,
1059                                              &item->wd->item_height,
1060                                              item->wd->item_width,
1061                                              item->wd->item_height);
1062         elm_coords_finger_size_adjust(1, &item->wd->item_width,
1063                                       1, &item->wd->item_height);
1064      }
1065
1066    evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_DOWN,
1067                                   _mouse_down, item);
1068    evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_UP,
1069                                   _mouse_up, item);
1070    evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_MOVE,
1071                                   _mouse_move, item);
1072
1073    if (item->selected)
1074      edje_object_signal_emit(item->base.view, "elm,state,selected", "elm");
1075    if (item->disabled)
1076      edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
1077
1078    evas_object_show(item->base.view);
1079
1080    if (item->tooltip.content_cb)
1081      {
1082         elm_widget_item_tooltip_content_cb_set(item,
1083                                                item->tooltip.content_cb,
1084                                                item->tooltip.data, NULL);
1085         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
1086      }
1087
1088    if (item->mouse_cursor)
1089      elm_widget_item_cursor_set(item, item->mouse_cursor);
1090
1091    item->realized = EINA_TRUE;
1092    item->want_unrealize = EINA_FALSE;
1093 }
1094
1095 static void
1096 _item_unrealize(Elm_Gengrid_Item *item)
1097 {
1098    Evas_Object *icon;
1099
1100    if (!item->realized) return;
1101    if (item->long_timer)
1102      {
1103         ecore_timer_del(item->long_timer);
1104         item->long_timer = NULL;
1105      }
1106    evas_object_del(item->base.view);
1107    item->base.view = NULL;
1108    evas_object_del(item->spacer);
1109    item->spacer = NULL;
1110    elm_widget_stringlist_free(item->labels);
1111    item->labels = NULL;
1112    elm_widget_stringlist_free(item->icons);
1113    item->icons = NULL;
1114    elm_widget_stringlist_free(item->states);
1115    item->states = NULL;
1116
1117    EINA_LIST_FREE(item->icon_objs, icon)
1118       evas_object_del(icon);
1119
1120    item->realized = EINA_FALSE;
1121    item->want_unrealize = EINA_FALSE;
1122 }
1123
1124 static void
1125 _item_place(Elm_Gengrid_Item *item,
1126             Evas_Coord        cx,
1127             Evas_Coord        cy)
1128 {
1129    Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh;
1130    Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
1131    item->x = cx;
1132    item->y = cy;
1133    evas_object_geometry_get(item->wd->pan_smart, &ox, &oy, &vw, &vh);
1134
1135    /* Preload rows/columns at each side of the Gengrid */
1136    cvx = ox - PRELOAD * item->wd->item_width;
1137    cvy = oy - PRELOAD * item->wd->item_height;
1138    cvw = vw + 2 * PRELOAD * item->wd->item_width;
1139    cvh = vh + 2 * PRELOAD * item->wd->item_height;
1140
1141    alignh = 0;
1142    alignw = 0;
1143
1144    if (item->wd->horizontal)
1145      {
1146         int columns, items_visible = 0, items_row;
1147
1148         if (item->wd->item_height > 0)
1149           items_visible = vh / item->wd->item_height;
1150         if (items_visible < 1)
1151           items_visible = 1;
1152
1153         columns = item->wd->count / items_visible;
1154         if (item->wd->count % items_visible)
1155           columns++;
1156
1157         tcw = item->wd->item_width * columns;
1158         alignw = (vw - tcw) * item->wd->align_x;
1159
1160         items_row = items_visible;
1161         if (items_row > item->wd->count)
1162           items_row = item->wd->count;
1163         tch = items_row * item->wd->item_height;
1164         alignh = (vh - tch) * item->wd->align_y;
1165      }
1166    else
1167      {
1168         int rows, items_visible = 0, items_col;
1169
1170         if (item->wd->item_width > 0)
1171           items_visible = vw / item->wd->item_width;
1172         if (items_visible < 1)
1173           items_visible = 1;
1174
1175         rows = item->wd->count / items_visible;
1176         if (item->wd->count % items_visible)
1177           rows++;
1178
1179         tch = item->wd->item_height * rows;
1180         alignh = (vh - tch) * item->wd->align_y;
1181
1182         items_col = items_visible;
1183         if (items_col > item->wd->count)
1184           items_col = item->wd->count;
1185         tcw = items_col * item->wd->item_width;
1186         alignw = (vw - tcw) * item->wd->align_x;
1187      }
1188
1189    x = cx * item->wd->item_width - item->wd->pan_x + ox + alignw;
1190    if (elm_widget_mirrored_get(item->wd->self))
1191      {  /* Switch items side and componsate for pan_x when in RTL mode */
1192         Evas_Coord ww;
1193         evas_object_geometry_get(item->wd->self, NULL, NULL, &ww, NULL);
1194         x = ww - x - item->wd->item_width - item->wd->pan_x - item->wd->pan_x;
1195      }
1196
1197    y = cy * item->wd->item_height - item->wd->pan_y + oy + alignh;
1198
1199    Eina_Bool was_realized = item->realized;
1200    if (ELM_RECTS_INTERSECT(x, y, item->wd->item_width, item->wd->item_height,
1201                            cvx, cvy, cvw, cvh))
1202      {
1203         _item_realize(item);
1204         if (!was_realized)
1205           evas_object_smart_callback_call(item->wd->self, SIG_REALIZED, item);
1206         evas_object_move(item->base.view, x, y);
1207         evas_object_resize(item->base.view, item->wd->item_width,
1208                            item->wd->item_height);
1209      }
1210    else
1211      {
1212         _item_unrealize(item);
1213         if (was_realized)
1214           evas_object_smart_callback_call(item->wd->self, SIG_UNREALIZED, item);
1215      }
1216 }
1217
1218 static Elm_Gengrid_Item *
1219 _item_create(Widget_Data                  *wd,
1220              const Elm_Gengrid_Item_Class *gic,
1221              const void                   *data,
1222              Evas_Smart_Cb                 func,
1223              const void                   *func_data)
1224 {
1225    Elm_Gengrid_Item *item;
1226
1227    item = elm_widget_item_new(wd->self, Elm_Gengrid_Item);
1228    if (!item) return NULL;
1229    wd->count++;
1230    item->wd = wd;
1231    item->gic = gic;
1232    item->base.data = data;
1233    item->func.func = func;
1234    item->func.data = func_data;
1235    item->mouse_cursor = NULL;
1236    return item;
1237 }
1238
1239 static void
1240 _item_del(Elm_Gengrid_Item *item)
1241 {
1242    elm_widget_item_pre_notify_del(item);
1243    if (item->selected)
1244      item->wd->selected = eina_list_remove(item->wd->selected, item);
1245    if (item->realized) _item_unrealize(item);
1246    if ((!item->delete_me) && (item->gic->func.del))
1247      item->gic->func.del((void *)item->base.data, item->wd->self);
1248    item->delete_me = EINA_TRUE;
1249    item->wd->items = eina_inlist_remove(item->wd->items, EINA_INLIST_GET(item));
1250    if (item->long_timer) ecore_timer_del(item->long_timer);
1251    if (item->tooltip.del_cb)
1252      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
1253    item->wd->walking -= item->walking;
1254    item->wd->count--;
1255    if (item->wd->calc_job) ecore_job_del(item->wd->calc_job);
1256    item->wd->calc_job = ecore_job_add(_calc_job, item->wd);
1257    elm_widget_item_del(item);
1258 }
1259
1260 static void
1261 _item_select(Elm_Gengrid_Item *item)
1262 {
1263    if ((item->wd->no_select) || (item->delete_me)) return;
1264    if (item->selected)
1265      {
1266         if (item->wd->always_select) goto call;
1267         return;
1268      }
1269    item->selected = EINA_TRUE;
1270    item->wd->selected = eina_list_append(item->wd->selected, item);
1271 call:
1272    item->walking++;
1273    item->wd->walking++;
1274    if (item->func.func)
1275      item->func.func((void *)item->func.data, item->wd->self, item);
1276    if (!item->delete_me)
1277      evas_object_smart_callback_call(item->wd->self, SIG_SELECTED, item);
1278    item->walking--;
1279    item->wd->walking--;
1280    if ((item->wd->clear_me) && (!item->wd->walking))
1281      elm_gengrid_clear(item->base.widget);
1282    else
1283      {
1284         if ((!item->walking) && (item->delete_me))
1285           if (!item->relcount) _item_del(item);
1286      }
1287    item->wd->last_selected_item = item;
1288 }
1289
1290 static void
1291 _item_unselect(Elm_Gengrid_Item *item)
1292 {
1293    if ((item->delete_me) || (!item->hilighted)) return;
1294    edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
1295    item->hilighted = EINA_FALSE;
1296    if (item->selected)
1297      {
1298         item->selected = EINA_FALSE;
1299         item->wd->selected = eina_list_remove(item->wd->selected, item);
1300         evas_object_smart_callback_call(item->wd->self, SIG_UNSELECTED, item);
1301      }
1302 }
1303
1304 static void
1305 _calc_job(void *data)
1306 {
1307    Widget_Data *wd = data;
1308    Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
1309    int count;
1310
1311    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &cvw, &cvh);
1312    if ((cvw != 0) || (cvh != 0))
1313      {
1314         if ((wd->horizontal) && (wd->item_height > 0))
1315           nmax = cvh / wd->item_height;
1316         else if (wd->item_width > 0)
1317           nmax = cvw / wd->item_width;
1318
1319         if (nmax < 1)
1320           nmax = 1;
1321
1322         count = wd->count;
1323         if (wd->horizontal)
1324           {
1325              minw = ceil(count / (float)nmax) * wd->item_width;
1326              minh = nmax * wd->item_height;
1327           }
1328         else
1329           {
1330              minw = nmax * wd->item_width;
1331              minh = ceil(count / (float)nmax) * wd->item_height;
1332           }
1333
1334         if ((minw != wd->minw) || (minh != wd->minh))
1335           {
1336              wd->minh = minh;
1337              wd->minw = minw;
1338              evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
1339           }
1340
1341         wd->nmax = nmax;
1342         wd->calc_job = NULL;
1343         evas_object_smart_changed(wd->pan_smart);
1344      }
1345 }
1346
1347 static void
1348 _pan_add(Evas_Object *obj)
1349 {
1350    Pan *sd;
1351    Evas_Object_Smart_Clipped_Data *cd;
1352
1353    _pan_sc.add(obj);
1354    cd = evas_object_smart_data_get(obj);
1355    sd = ELM_NEW(Pan);
1356    if (!sd) return;
1357    sd->__clipped_data = *cd;
1358    free(cd);
1359    evas_object_smart_data_set(obj, sd);
1360 }
1361
1362 static void
1363 _pan_del(Evas_Object *obj)
1364 {
1365    Pan *sd = evas_object_smart_data_get(obj);
1366
1367    if (!sd) return;
1368    _pan_sc.del(obj);
1369 }
1370
1371 static void
1372 _pan_set(Evas_Object *obj,
1373          Evas_Coord   x,
1374          Evas_Coord   y)
1375 {
1376    Pan *sd = evas_object_smart_data_get(obj);
1377    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
1378    sd->wd->pan_x = x;
1379    sd->wd->pan_y = y;
1380    evas_object_smart_changed(obj);
1381 }
1382
1383 static void
1384 _pan_get(Evas_Object *obj,
1385          Evas_Coord  *x,
1386          Evas_Coord  *y)
1387 {
1388    Pan *sd = evas_object_smart_data_get(obj);
1389    if (x) *x = sd->wd->pan_x;
1390    if (y) *y = sd->wd->pan_y;
1391 }
1392
1393 static void
1394 _pan_child_size_get(Evas_Object *obj,
1395                     Evas_Coord  *w,
1396                     Evas_Coord  *h)
1397 {
1398    Pan *sd = evas_object_smart_data_get(obj);
1399    if (w) *w = sd->wd->minw;
1400    if (h) *h = sd->wd->minh;
1401 }
1402
1403 static void
1404 _pan_max_get(Evas_Object *obj,
1405              Evas_Coord  *x,
1406              Evas_Coord  *y)
1407 {
1408    Pan *sd = evas_object_smart_data_get(obj);
1409    Evas_Coord ow, oh;
1410
1411    if (!sd) return;
1412    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1413    if (x)
1414      *x = (ow < sd->wd->minw) ? sd->wd->minw - ow : 0;
1415    if (y)
1416      *y = (oh < sd->wd->minh) ? sd->wd->minh - oh : 0;
1417 }
1418
1419 static void
1420 _pan_min_get(Evas_Object *obj,
1421              Evas_Coord  *x,
1422              Evas_Coord  *y)
1423 {
1424    Pan *sd = evas_object_smart_data_get(obj);
1425    Evas_Coord mx, my;
1426
1427    if (!sd) return;
1428    _pan_max_get(obj, &mx, &my);
1429    if (x)
1430      *x = -mx * sd->wd->align_x;
1431    if (y)
1432      *y = -my * sd->wd->align_y;
1433 }
1434
1435 static void
1436 _pan_resize(Evas_Object *obj,
1437             Evas_Coord   w,
1438             Evas_Coord   h)
1439 {
1440    Pan *sd = evas_object_smart_data_get(obj);
1441    Evas_Coord ow, oh;
1442
1443    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1444    if ((ow == w) && (oh == h)) return;
1445    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1446    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1447 }
1448
1449 static void
1450 _pan_calculate(Evas_Object *obj)
1451 {
1452    Pan *sd = evas_object_smart_data_get(obj);
1453    Evas_Coord cx = 0, cy = 0;
1454    Elm_Gengrid_Item *item;
1455
1456    if (!sd) return;
1457    if (!sd->wd->nmax) return;
1458
1459    EINA_INLIST_FOREACH(sd->wd->items, item)
1460      {
1461         _item_place(item, cx, cy);
1462         if (sd->wd->horizontal)
1463           {
1464              cy = (cy + 1) % sd->wd->nmax;
1465              if (!cy) cx++;
1466           }
1467         else
1468           {
1469              cx = (cx + 1) % sd->wd->nmax;
1470              if (!cx) cy++;
1471           }
1472      }
1473    evas_object_smart_callback_call(sd->wd->self, SIG_CHANGED, NULL);
1474 }
1475
1476 static void
1477 _pan_move(Evas_Object *obj,
1478           Evas_Coord x __UNUSED__,
1479           Evas_Coord y __UNUSED__)
1480 {
1481    Pan *sd = evas_object_smart_data_get(obj);
1482    if (!sd) return;
1483    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1484    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1485 }
1486
1487 static void
1488 _hold_on(void *data       __UNUSED__,
1489          Evas_Object     *obj,
1490          void *event_info __UNUSED__)
1491 {
1492    Widget_Data *wd = elm_widget_data_get(obj);
1493    if (!wd) return;
1494    elm_smart_scroller_hold_set(wd->scr, 1);
1495 }
1496
1497 static void
1498 _hold_off(void *data       __UNUSED__,
1499           Evas_Object     *obj,
1500           void *event_info __UNUSED__)
1501 {
1502    Widget_Data *wd = elm_widget_data_get(obj);
1503    if (!wd) return;
1504    elm_smart_scroller_hold_set(wd->scr, 0);
1505 }
1506
1507 static void
1508 _freeze_on(void *data       __UNUSED__,
1509            Evas_Object     *obj,
1510            void *event_info __UNUSED__)
1511 {
1512    Widget_Data *wd = elm_widget_data_get(obj);
1513    if (!wd) return;
1514    elm_smart_scroller_freeze_set(wd->scr, 1);
1515 }
1516
1517 static void
1518 _freeze_off(void *data       __UNUSED__,
1519             Evas_Object     *obj,
1520             void *event_info __UNUSED__)
1521 {
1522    Widget_Data *wd = elm_widget_data_get(obj);
1523    if (!wd) return;
1524    elm_smart_scroller_freeze_set(wd->scr, 0);
1525 }
1526
1527 static void
1528 _scr_drag_start(void            *data,
1529                 Evas_Object *obj __UNUSED__,
1530                 void *event_info __UNUSED__)
1531 {
1532    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
1533 }
1534
1535 static void
1536 _scr_drag_stop(void            *data,
1537                Evas_Object *obj __UNUSED__,
1538                void *event_info __UNUSED__)
1539 {
1540    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
1541 }
1542
1543 static void
1544 _scr_scroll(void            *data,
1545             Evas_Object *obj __UNUSED__,
1546             void *event_info __UNUSED__)
1547 {
1548    evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
1549 }
1550
1551 /**
1552  * Add a new Gengrid object.
1553  *
1554  * @param parent The parent object.
1555  * @return  The new object or NULL if it cannot be created.
1556  *
1557  * @see elm_gengrid_item_size_set()
1558  * @see elm_gengrid_horizontal_set()
1559  * @see elm_gengrid_item_append()
1560  * @see elm_gengrid_item_del()
1561  * @see elm_gengrid_clear()
1562  *
1563  * @ingroup Gengrid
1564  */
1565 EAPI Evas_Object *
1566 elm_gengrid_add(Evas_Object *parent)
1567 {
1568    Evas_Object *obj;
1569    Evas *e;
1570    Widget_Data *wd;
1571    static Evas_Smart *smart = NULL;
1572    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1573
1574    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1575
1576    ELM_SET_WIDTYPE(widtype, "gengrid");
1577    elm_widget_type_set(obj, "gengrid");
1578    elm_widget_sub_object_add(parent, obj);
1579    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1580    elm_widget_data_set(obj, wd);
1581    elm_widget_del_hook_set(obj, _del_hook);
1582    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1583    elm_widget_theme_hook_set(obj, _theme_hook);
1584    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1585    elm_widget_can_focus_set(obj, EINA_TRUE);
1586    elm_widget_event_hook_set(obj, _event_hook);
1587
1588    wd->scr = elm_smart_scroller_add(e);
1589    elm_smart_scroller_widget_set(wd->scr, obj);
1590    elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
1591                                        "default");
1592    elm_widget_resize_object_set(obj, wd->scr);
1593
1594    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
1595    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
1596    evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
1597
1598    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
1599
1600    wd->self = obj;
1601    wd->align_x = 0.5;
1602    wd->align_y = 0.5;
1603    wd->no_select = EINA_FALSE;
1604
1605    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1606    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1607    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1608    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1609
1610    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1611
1612    if (!smart)
1613      {
1614         static Evas_Smart_Class sc;
1615
1616         evas_object_smart_clipped_smart_set(&_pan_sc);
1617         sc = _pan_sc;
1618         sc.name = "elm_gengrid_pan";
1619         sc.version = EVAS_SMART_CLASS_VERSION;
1620         sc.add = _pan_add;
1621         sc.del = _pan_del;
1622         sc.resize = _pan_resize;
1623         sc.move = _pan_move;
1624         sc.calculate = _pan_calculate;
1625         smart = evas_smart_class_new(&sc);
1626      }
1627    if (smart)
1628      {
1629         wd->pan_smart = evas_object_smart_add(e, smart);
1630         wd->pan = evas_object_smart_data_get(wd->pan_smart);
1631         wd->pan->wd = wd;
1632      }
1633
1634    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
1635                                      _pan_set, _pan_get, _pan_max_get,
1636                                      _pan_min_get, _pan_child_size_get);
1637
1638    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1639    return obj;
1640 }
1641
1642 /**
1643  * Set the size for the item of the Gengrid.
1644  *
1645  * @param obj The Gengrid object.
1646  * @param w The item's width.
1647  * @param h The item's height;
1648  *
1649  * @see elm_gengrid_item_size_get()
1650  *
1651  * @ingroup Gengrid
1652  */
1653 EAPI void
1654 elm_gengrid_item_size_set(Evas_Object *obj,
1655                           Evas_Coord   w,
1656                           Evas_Coord   h)
1657 {
1658    ELM_CHECK_WIDTYPE(obj, widtype);
1659    Widget_Data *wd = elm_widget_data_get(obj);
1660    if (!wd) return;
1661    if ((wd->item_width == w) && (wd->item_height == h)) return;
1662    wd->item_width = w;
1663    wd->item_height = h;
1664    if (wd->calc_job) ecore_job_del(wd->calc_job);
1665    wd->calc_job = ecore_job_add(_calc_job, wd);
1666 }
1667
1668 /**
1669  * Get the size of the item of the Gengrid.
1670  *
1671  * @param obj The Gengrid object.
1672  * @param w Pointer to the item's width.
1673  * @param h Pointer to the item's height.
1674  *
1675  * @see elm_gengrid_item_size_get()
1676  *
1677  * @ingroup Gengrid
1678  */
1679 EAPI void
1680 elm_gengrid_item_size_get(const Evas_Object *obj,
1681                           Evas_Coord        *w,
1682                           Evas_Coord        *h)
1683 {
1684    ELM_CHECK_WIDTYPE(obj, widtype);
1685    Widget_Data *wd = elm_widget_data_get(obj);
1686    if (!wd) return;
1687    if (w) *w = wd->item_width;
1688    if (h) *h = wd->item_height;
1689 }
1690
1691 /**
1692  * Set item's alignment within the scroller.
1693  *
1694  * @param obj The Gengrid object.
1695  * @param align_x The x alignment (0 <= x <= 1).
1696  * @param align_y The y alignment (0 <= y <= 1).
1697  *
1698  * @see elm_gengrid_align_get()
1699  *
1700  * @ingroup Gengrid
1701  */
1702 EAPI void
1703 elm_gengrid_align_set(Evas_Object *obj,
1704                       double       align_x,
1705                       double       align_y)
1706 {
1707    ELM_CHECK_WIDTYPE(obj, widtype);
1708    Widget_Data *wd = elm_widget_data_get(obj);
1709
1710    if (align_x > 1.0)
1711      align_x = 1.0;
1712    else if (align_x < 0.0)
1713      align_x = 0.0;
1714    wd->align_x = align_x;
1715
1716    if (align_y > 1.0)
1717      align_y = 1.0;
1718    else if (align_y < 0.0)
1719      align_y = 0.0;
1720    wd->align_y = align_y;
1721 }
1722
1723 /**
1724  * Get the alignenment set for the Gengrid object.
1725  *
1726  * @param obj The Gengrid object.
1727  * @param align_x Pointer to x alignenment.
1728  * @param align_y Pointer to y alignenment.
1729  *
1730  * @see elm_gengrid_align_set()
1731  *
1732  * @ingroup Gengrid
1733  */
1734 EAPI void
1735 elm_gengrid_align_get(const Evas_Object *obj,
1736                       double            *align_x,
1737                       double            *align_y)
1738 {
1739    ELM_CHECK_WIDTYPE(obj, widtype);
1740    Widget_Data *wd = elm_widget_data_get(obj);
1741    if (align_x) *align_x = wd->align_x;
1742    if (align_y) *align_y = wd->align_y;
1743 }
1744
1745 /**
1746  * Add item to the end of the Gengrid.
1747  *
1748  * @param obj The Gengrid object.
1749  * @param gic The item class for the item.
1750  * @param data The item data.
1751  * @param func Convenience function called when item is selected.
1752  * @param func_data Data passed to @p func above.
1753  * @return A handle to the item added or NULL if not possible.
1754  *
1755  * @see elm_gengrid_item_prepend()
1756  * @see elm_gengrid_item_insert_before()
1757  * @see elm_gengrid_item_insert_after()
1758  * @see elm_gengrid_item_del()
1759  *
1760  * @ingroup Gengrid
1761  */
1762 EAPI Elm_Gengrid_Item *
1763 elm_gengrid_item_append(Evas_Object                  *obj,
1764                         const Elm_Gengrid_Item_Class *gic,
1765                         const void                   *data,
1766                         Evas_Smart_Cb                 func,
1767                         const void                   *func_data)
1768 {
1769    Elm_Gengrid_Item *item;
1770    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1771    Widget_Data *wd = elm_widget_data_get(obj);
1772    if (!wd) return NULL;
1773
1774    item = _item_create(wd, gic, data, func, func_data);
1775    if (!item) return NULL;
1776    wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(item));
1777
1778    if (wd->calc_job) ecore_job_del(wd->calc_job);
1779    wd->calc_job = ecore_job_add(_calc_job, wd);
1780
1781    return item;
1782 }
1783
1784 /**
1785  * Add item at start of the Gengrid.
1786  *
1787  * This adds an item to the beginning of the grid.
1788  *
1789  * @param obj The Gengrid object.
1790  * @param gic The item class for the item.
1791  * @param data The item data.
1792  * @param func Convenience function called when item is selected.
1793  * @param func_data Data passed to @p func above.
1794  * @return A handle to the item added or NULL if not possible.
1795  *
1796  * @see elm_gengrid_item_append()
1797  * @see elm_gengrid_item_insert_before()
1798  * @see elm_gengrid_item_insert_after()
1799  * @see elm_gengrid_item_del()
1800  *
1801  * @ingroup Gengrid
1802  */
1803 EAPI Elm_Gengrid_Item *
1804 elm_gengrid_item_prepend(Evas_Object                  *obj,
1805                          const Elm_Gengrid_Item_Class *gic,
1806                          const void                   *data,
1807                          Evas_Smart_Cb                 func,
1808                          const void                   *func_data)
1809 {
1810    Elm_Gengrid_Item *item;
1811    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1812    Widget_Data *wd = elm_widget_data_get(obj);
1813    if (!wd) return NULL;
1814
1815    item = _item_create(wd, gic, data, func, func_data);
1816    if (!item) return NULL;
1817    wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(item));
1818
1819    if (wd->calc_job) ecore_job_del(wd->calc_job);
1820    wd->calc_job = ecore_job_add(_calc_job, wd);
1821
1822    return item;
1823 }
1824
1825 /**
1826  * Insert and item before another in the Gengrid.
1827  *
1828  * This inserts an item before another in the grid.
1829  *
1830  * @param obj The Gengrid object.
1831  * @param gic The item class for the item.
1832  * @param data The item data.
1833  * @param relative The item to which insert before.
1834  * @param func Convenience function called when item is selected.
1835  * @param func_data Data passed to @p func above.
1836  * @return A handle to the item added or NULL if not possible.
1837  *
1838  * @see elm_gengrid_item_append()
1839  * @see elm_gengrid_item_prepend()
1840  * @see elm_gengrid_item_insert_after()
1841  * @see elm_gengrid_item_del()
1842  *
1843  * @ingroup Gengrid
1844  */
1845 EAPI Elm_Gengrid_Item *
1846 elm_gengrid_item_insert_before(Evas_Object                  *obj,
1847                                const Elm_Gengrid_Item_Class *gic,
1848                                const void                   *data,
1849                                Elm_Gengrid_Item             *relative,
1850                                Evas_Smart_Cb                 func,
1851                                const void                   *func_data)
1852 {
1853    Elm_Gengrid_Item *item;
1854    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1855    EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
1856    Widget_Data *wd = elm_widget_data_get(obj);
1857    if (!wd) return NULL;
1858
1859    item = _item_create(wd, gic, data, func, func_data);
1860    if (!item) return NULL;
1861    wd->items = eina_inlist_prepend_relative
1862       (wd->items, EINA_INLIST_GET(item), EINA_INLIST_GET(relative));
1863
1864    if (wd->calc_job) ecore_job_del(wd->calc_job);
1865    wd->calc_job = ecore_job_add(_calc_job, wd);
1866
1867    return item;
1868 }
1869
1870 /**
1871  * Insert and item after another in the Gengrid.
1872  *
1873  * This inserts an item after another in the grid.
1874  *
1875  * @param obj The Gengrid object.
1876  * @param gic The item class for the item.
1877  * @param data The item data.
1878  * @param relative The item to which insert after.
1879  * @param func Convenience function called when item is selected.
1880  * @param func_data Data passed to @p func above.
1881  * @return A handle to the item added or NULL if not possible.
1882  *
1883  * @see elm_gengrid_item_append()
1884  * @see elm_gengrid_item_prepend()
1885  * @see elm_gengrid_item_insert_before()
1886  * @see elm_gengrid_item_del()
1887  *
1888  * @ingroup Gengrid
1889  */
1890 EAPI Elm_Gengrid_Item *
1891 elm_gengrid_item_insert_after(Evas_Object                  *obj,
1892                               const Elm_Gengrid_Item_Class *gic,
1893                               const void                   *data,
1894                               Elm_Gengrid_Item             *relative,
1895                               Evas_Smart_Cb                 func,
1896                               const void                   *func_data)
1897 {
1898    Elm_Gengrid_Item *item;
1899    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1900    EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
1901    Widget_Data *wd = elm_widget_data_get(obj);
1902    if (!wd) return NULL;
1903
1904    item = _item_create(wd, gic, data, func, func_data);
1905    if (!item) return NULL;
1906    wd->items = eina_inlist_append_relative
1907       (wd->items, EINA_INLIST_GET(item), EINA_INLIST_GET(relative));
1908
1909    if (wd->calc_job) ecore_job_del(wd->calc_job);
1910    wd->calc_job = ecore_job_add(_calc_job, wd);
1911
1912    return item;
1913 }
1914
1915 /**
1916  * Remove an item from the Gengrid.
1917  *
1918  * @param item The item to be removed.
1919  * @return @c EINA_TRUE on success or @c EINA_FALSE otherwise.
1920  *
1921  * @see elm_gengrid_clear() to remove all items of the Gengrid.
1922  *
1923  * @ingroup Gengrid
1924  */
1925 EAPI void
1926 elm_gengrid_item_del(Elm_Gengrid_Item *item)
1927 {
1928    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1929    if ((item->relcount > 0) || (item->walking > 0))
1930      {
1931         item->delete_me = EINA_TRUE;
1932         elm_widget_item_pre_notify_del(item);
1933         if (item->selected)
1934           item->wd->selected = eina_list_remove(item->wd->selected, item);
1935         if (item->gic->func.del)
1936           item->gic->func.del((void *)item->base.data, item->wd->self);
1937         return;
1938      }
1939
1940    _item_del(item);
1941 }
1942
1943 /**
1944  * Set for what direction the Gengrid will expand.
1945  *
1946  * @param obj The Gengrid object.
1947  * @param setting If @c EINA_TRUE the Gengrid will expand horizontally
1948  * or vertically if @c EINA_FALSE.
1949  *
1950  * @ingroup Gengrid
1951  */
1952 EAPI void
1953 elm_gengrid_horizontal_set(Evas_Object *obj,
1954                            Eina_Bool    setting)
1955 {
1956    ELM_CHECK_WIDTYPE(obj, widtype);
1957    Widget_Data *wd = elm_widget_data_get(obj);
1958    if (!wd) return;
1959    if (setting == wd->horizontal) return;
1960    wd->horizontal = setting;
1961
1962    /* Update the items to conform to the new layout */
1963    if (wd->calc_job) ecore_job_del(wd->calc_job);
1964    wd->calc_job = ecore_job_add(_calc_job, wd);
1965 }
1966
1967 /**
1968  * Get for what direction the Gengrid is expanded.
1969  *
1970  * @param obj The Gengrid object.
1971  * @return If the Gengrid is expanded horizontally return @c EINA_TRUE
1972  * else @c EINA_FALSE.
1973  *
1974  * @ingroup Gengrid
1975  */
1976 EAPI Eina_Bool
1977 elm_gengrid_horizontal_get(const Evas_Object *obj)
1978 {
1979    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1980    Widget_Data *wd = elm_widget_data_get(obj);
1981    if (!wd) return EINA_FALSE;
1982    return wd->horizontal;
1983 }
1984
1985 /**
1986  * Clear the Gengrid
1987  *
1988  * This clears all items in the Gengrid, leaving it empty.
1989  *
1990  * @param obj The Gengrid object.
1991  *
1992  * @see elm_gengrid_item_del() to remove just one item.
1993  *
1994  * @ingroup Gengrid
1995  */
1996 EAPI void
1997 elm_gengrid_clear(Evas_Object *obj)
1998 {
1999    ELM_CHECK_WIDTYPE(obj, widtype);
2000    Widget_Data *wd = elm_widget_data_get(obj);
2001    if (!wd) return;
2002
2003    if (wd->calc_job)
2004      {
2005         ecore_job_del(wd->calc_job);
2006         wd->calc_job = NULL;
2007      }
2008
2009    if (wd->walking > 0)
2010      {
2011         Elm_Gengrid_Item *item;
2012         wd->clear_me = 1;
2013         EINA_INLIST_FOREACH(wd->items, item)
2014            item->delete_me = 1;
2015         return;
2016      }
2017    wd->clear_me = 0;
2018    while (wd->items)
2019      {
2020         Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
2021
2022         wd->items = eina_inlist_remove(wd->items, wd->items);
2023         elm_widget_item_pre_notify_del(item);
2024         if (item->realized) _item_unrealize(item);
2025         if (item->gic->func.del)
2026           item->gic->func.del((void *)item->base.data, wd->self);
2027         if (item->long_timer) ecore_timer_del(item->long_timer);
2028         elm_widget_item_del(item);
2029      }
2030
2031    if (wd->selected)
2032      {
2033         eina_list_free(wd->selected);
2034         wd->selected = NULL;
2035      }
2036
2037    wd->pan_x = 0;
2038    wd->pan_y = 0;
2039    wd->minw = 0;
2040    wd->minh = 0;
2041    wd->count = 0;
2042    evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
2043    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2044 }
2045
2046 /**
2047  * Get the real evas object of the Gengrid item
2048  *
2049  * This returns the actual evas object used for the specified Gengrid
2050  * item.  This may be NULL as it may not be created, and may be
2051  * deleted at any time by Gengrid. Do not modify this object (move,
2052  * resize, show, hide etc.) as Gengrid is controlling it. This
2053  * function is for querying, emitting custom signals or hooking lower
2054  * level callbacks for events. Do not delete this object under any
2055  * circumstances.
2056  *
2057  * @param item The Gengrid item.
2058  * @return the evas object associated to this item.
2059  *
2060  * @see elm_gengrid_item_data_get()
2061  *
2062  * @ingroup Gengrid
2063  */
2064 EAPI const Evas_Object *
2065 elm_gengrid_item_object_get(const Elm_Gengrid_Item *item)
2066 {
2067    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2068    return item->base.view;
2069 }
2070
2071 /**
2072  * Update the contents of an item
2073  *
2074  * This updates an item by calling all the item class functions again
2075  * to get the icons, labels and states. Use this when the original
2076  * item data has changed and the changes are desired to be reflected.
2077  *
2078  * @param item The item
2079  *
2080  * @ingroup Gengrid
2081  */
2082 EAPI void
2083 elm_gengrid_item_update(Elm_Gengrid_Item *item)
2084 {
2085    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2086    if (!item->realized) return;
2087    if (item->want_unrealize) return;
2088    _item_unrealize(item);
2089    _item_realize(item);
2090    _item_place(item, item->x, item->y);
2091 }
2092
2093 /**
2094  * Returns the data associated to an item
2095  *
2096  * This returns the data value passed on the elm_gengrid_item_append()
2097  * and related item addition calls.
2098  *
2099  * @param item The Gengrid item.
2100  * @return the data associated to this item.
2101  *
2102  * @see elm_gengrid_item_append()
2103  * @see elm_gengrid_item_object_get()
2104  *
2105  * @ingroup Gengrid
2106  */
2107 EAPI void *
2108 elm_gengrid_item_data_get(const Elm_Gengrid_Item *item)
2109 {
2110    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2111    return elm_widget_item_data_get(item);
2112 }
2113
2114 /**
2115  * Set the datan item from the gengrid item
2116  *
2117  * This set the data value passed on the elm_gengrid_item_append() and
2118  * related item addition calls. This function will also call
2119  * elm_gengrid_item_update() so the item will be updated to reflect
2120  * the new data.
2121  *
2122  * @param item The item
2123  * @param data The new data pointer to set
2124  *
2125  * @ingroup Gengrid
2126  */
2127 EAPI void
2128 elm_gengrid_item_data_set(Elm_Gengrid_Item *item,
2129                           const void       *data)
2130 {
2131    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2132    elm_widget_item_data_set(item, data);
2133    elm_gengrid_item_update(item);
2134 }
2135
2136 /**
2137  * Get the item's coordinates.
2138  *
2139  * This returns the logical position of the item whithin the Gengrid.
2140  *
2141  * @param item The Gengrid item.
2142  * @param x The x-axis coordinate pointer.
2143  * @param y The y-axis coordinate pointer.
2144  *
2145  * @ingroup Gengrid
2146  */
2147 EAPI void
2148 elm_gengrid_item_pos_get(const Elm_Gengrid_Item *item,
2149                          unsigned int           *x,
2150                          unsigned int           *y)
2151 {
2152    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2153    if (x) *x = item->x;
2154    if (y) *y = item->y;
2155 }
2156
2157 /**
2158  * Enable or disable multi-select in the Gengrid.
2159  *
2160  * This enables (EINA_TRUE) or disables (EINA_FALSE) multi-select in
2161  * the Gengrid.  This allows more than 1 item to be selected.
2162  *
2163  * @param obj The Gengrid object.
2164  * @param multi Multi-select enabled/disabled
2165  *
2166  * @ingroup Gengrid
2167  */
2168 EAPI void
2169 elm_gengrid_multi_select_set(Evas_Object *obj,
2170                              Eina_Bool    multi)
2171 {
2172    ELM_CHECK_WIDTYPE(obj, widtype);
2173    Widget_Data *wd = elm_widget_data_get(obj);
2174    if (!wd) return;
2175    wd->multi = multi;
2176 }
2177
2178 /**
2179  * Get if multi-select in Gengrid is enabled or disabled
2180  *
2181  * @param obj The Gengrid object
2182  * @return Multi-select enable/disable
2183  * (EINA_TRUE = enabled / EINA_FALSE = disabled)
2184  *
2185  * @ingroup Gengrid
2186  */
2187 EAPI Eina_Bool
2188 elm_gengrid_multi_select_get(const Evas_Object *obj)
2189 {
2190    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2191    Widget_Data *wd = elm_widget_data_get(obj);
2192    if (!wd) return EINA_FALSE;
2193    return wd->multi;
2194 }
2195
2196 /**
2197  * Get the selected item in the Gengrid
2198  *
2199  * This gets the selected item in the Gengrid (if multi-select is
2200  * enabled only the first item in the list is selected - which is not
2201  * very useful, so see elm_gengrid_selected_items_get() for when
2202  * multi-select is used).
2203  *
2204  * If no item is selected, NULL is returned.
2205  *
2206  * @param obj The Gengrid object.
2207  * @return The selected item, or NULL if none.
2208  *
2209  * @ingroup Gengrid
2210  */
2211 EAPI Elm_Gengrid_Item *
2212 elm_gengrid_selected_item_get(const Evas_Object *obj)
2213 {
2214    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2215    Widget_Data *wd = elm_widget_data_get(obj);
2216    if (!wd) return NULL;
2217    if (wd->selected) return wd->selected->data;
2218    return NULL;
2219 }
2220
2221 /**
2222  * Get a list of selected items in the Gengrid.
2223  *
2224  * This returns a list of the selected items. This list pointer is
2225  * only valid so long as no items are selected or unselected (or
2226  * unselected implictly by deletion). The list contains
2227  * Elm_Gengrid_Item pointers.
2228  *
2229  * @param obj The Gengrid object.
2230  * @return The list of selected items, or NULL if none are selected.
2231  *
2232  * @ingroup Gengrid
2233  */
2234 EAPI const Eina_List *
2235 elm_gengrid_selected_items_get(const Evas_Object *obj)
2236 {
2237    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2238    Widget_Data *wd = elm_widget_data_get(obj);
2239    if (!wd) return NULL;
2240    return wd->selected;
2241 }
2242
2243 /**
2244  * Set the selected state of an item.
2245  *
2246  * This sets the selected state of an item. If multi-select is not
2247  * enabled and selected is EINA_TRUE, previously selected items are
2248  * unselected.
2249  *
2250  * @param item The item
2251  * @param selected The selected state.
2252  *
2253  * @ingroup Gengrid
2254  */
2255 EAPI void
2256 elm_gengrid_item_selected_set(Elm_Gengrid_Item *item,
2257                               Eina_Bool         selected)
2258 {
2259    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2260    Widget_Data *wd = item->wd;
2261    if (!wd) return;
2262    if (item->delete_me) return;
2263    selected = !!selected;
2264    if (item->selected == selected) return;
2265
2266    if (selected)
2267      {
2268         if (!wd->multi)
2269           {
2270              while (wd->selected)
2271                _item_unselect(wd->selected->data);
2272           }
2273         _item_hilight(item);
2274         _item_select(item);
2275      }
2276    else
2277      _item_unselect(item);
2278 }
2279
2280 /**
2281  * Get the selected state of an item.
2282  *
2283  * This gets the selected state of an item (1 selected, 0 not selected).
2284  *
2285  * @param item The item
2286  * @return The selected state
2287  *
2288  * @ingroup Gengrid
2289  */
2290 EAPI Eina_Bool
2291 elm_gengrid_item_selected_get(const Elm_Gengrid_Item *item)
2292 {
2293    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2294    return item->selected;
2295 }
2296
2297 /**
2298  * Sets the disabled state of an item.
2299  *
2300  * A disabled item cannot be selected or unselected. It will also
2301  * change appearance to disabled. This sets the disabled state (1
2302  * disabled, 0 not disabled).
2303  *
2304  * @param item The item
2305  * @param disabled The disabled state
2306  *
2307  * @ingroup Gengrid
2308  */
2309 EAPI void
2310 elm_gengrid_item_disabled_set(Elm_Gengrid_Item *item,
2311                               Eina_Bool         disabled)
2312 {
2313    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2314    if (item->disabled == disabled) return;
2315    if (item->delete_me) return;
2316    item->disabled = !!disabled;
2317    if (item->realized)
2318      {
2319         if (item->disabled)
2320           edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
2321         else
2322           edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm");
2323      }
2324 }
2325
2326 /**
2327  * Get the disabled state of an item.
2328  *
2329  * This gets the disabled state of the given item.
2330  *
2331  * @param item The item
2332  * @return The disabled state
2333  *
2334  * @ingroup Gengrid
2335  */
2336 EAPI Eina_Bool
2337 elm_gengrid_item_disabled_get(const Elm_Gengrid_Item *item)
2338 {
2339    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2340    if (item->delete_me) return EINA_FALSE;
2341    return item->disabled;
2342 }
2343
2344 static Evas_Object *
2345 _elm_gengrid_item_label_create(void        *data,
2346                                Evas_Object *obj,
2347                                void *item   __UNUSED__)
2348 {
2349    Evas_Object *label = elm_label_add(obj);
2350    if (!label)
2351      return NULL;
2352    elm_object_style_set(label, "tooltip");
2353    elm_label_label_set(label, data);
2354    return label;
2355 }
2356
2357 static void
2358 _elm_gengrid_item_label_del_cb(void            *data,
2359                                Evas_Object *obj __UNUSED__,
2360                                void *event_info __UNUSED__)
2361 {
2362    eina_stringshare_del(data);
2363 }
2364
2365 /**
2366  * Set the text to be shown in the gengrid item.
2367  *
2368  * @param item Target item
2369  * @param text The text to set in the content
2370  *
2371  * Setup the text as tooltip to object. The item can have only one
2372  * tooltip, so any previous tooltip data is removed.
2373  *
2374  * @ingroup Gengrid
2375  */
2376 EAPI void
2377 elm_gengrid_item_tooltip_text_set(Elm_Gengrid_Item *item,
2378                                   const char       *text)
2379 {
2380    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2381    text = eina_stringshare_add(text);
2382    elm_gengrid_item_tooltip_content_cb_set(item, _elm_gengrid_item_label_create,
2383                                            text,
2384                                            _elm_gengrid_item_label_del_cb);
2385 }
2386
2387 /**
2388  * Set the content to be shown in the tooltip item
2389  *
2390  * Setup the tooltip to item. The item can have only one tooltip, so
2391  * any previous tooltip data is removed. @p func(with @p data) will be
2392  * called every time that need show the tooltip and it should return a
2393  * valid Evas_Object. This object is then managed fully by tooltip
2394  * system and is deleted when the tooltip is gone.
2395  *
2396  * @param item the gengrid item being attached a tooltip.
2397  * @param func the function used to create the tooltip contents.
2398  * @param data what to provide to @a func as callback data/context.
2399  * @param del_cb called when data is not needed anymore, either when
2400  *        another callback replaces @func, the tooltip is unset with
2401  *        elm_gengrid_item_tooltip_unset() or the owner @an item
2402  *        dies. This callback receives as the first parameter the
2403  *        given @a data, and @c event_info is the item.
2404  *
2405  * @ingroup Gengrid
2406  */
2407 EAPI void
2408 elm_gengrid_item_tooltip_content_cb_set(Elm_Gengrid_Item           *item,
2409                                         Elm_Tooltip_Item_Content_Cb func,
2410                                         const void                 *data,
2411                                         Evas_Smart_Cb               del_cb)
2412 {
2413    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
2414
2415    if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
2416      return;
2417
2418    if (item->tooltip.del_cb)
2419      item->tooltip.del_cb((void *)item->tooltip.data,
2420                           item->base.widget, item);
2421    item->tooltip.content_cb = func;
2422    item->tooltip.data = data;
2423    item->tooltip.del_cb = del_cb;
2424    if (item->base.view)
2425      {
2426         elm_widget_item_tooltip_content_cb_set(item,
2427                                                item->tooltip.content_cb,
2428                                                item->tooltip.data, NULL);
2429         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
2430      }
2431
2432    return;
2433
2434 error:
2435    if (del_cb) del_cb((void *)data, NULL, NULL);
2436 }
2437
2438 /**
2439  * Unset tooltip from item
2440  *
2441  * @param item gengrid item to remove previously set tooltip.
2442  *
2443  * Remove tooltip from item. The callback provided as del_cb to
2444  * elm_gengrid_item_tooltip_content_cb_set() will be called to notify
2445  * it is not used anymore.
2446  *
2447  * @see elm_gengrid_item_tooltip_content_cb_set()
2448  *
2449  * @ingroup Gengrid
2450  */
2451 EAPI void
2452 elm_gengrid_item_tooltip_unset(Elm_Gengrid_Item *item)
2453 {
2454    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2455    if ((item->base.view) && (item->tooltip.content_cb))
2456      elm_widget_item_tooltip_unset(item);
2457
2458    if (item->tooltip.del_cb)
2459      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
2460    item->tooltip.del_cb = NULL;
2461    item->tooltip.content_cb = NULL;
2462    item->tooltip.data = NULL;
2463    if (item->tooltip.style)
2464      elm_gengrid_item_tooltip_style_set(item, NULL);
2465 }
2466
2467 /**
2468  * Sets a different style for this item tooltip.
2469  *
2470  * @note before you set a style you should define a tooltip with
2471  *       elm_gengrid_item_tooltip_content_cb_set() or
2472  *       elm_gengrid_item_tooltip_text_set()
2473  *
2474  * @param item gengrid item with tooltip already set.
2475  * @param style the theme style to use (default, transparent, ...)
2476  *
2477  * @ingroup Gengrid
2478  */
2479 EAPI void
2480 elm_gengrid_item_tooltip_style_set(Elm_Gengrid_Item *item,
2481                                    const char       *style)
2482 {
2483    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2484    eina_stringshare_replace(&item->tooltip.style, style);
2485    if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
2486 }
2487
2488 /**
2489  * Get the style for this item tooltip.
2490  *
2491  * @param item gengrid item with tooltip already set.
2492  * @return style the theme style in use, defaults to "default". If the
2493  *         object does not have a tooltip set, then NULL is returned.
2494  *
2495  * @ingroup Gengrid
2496  */
2497 EAPI const char *
2498 elm_gengrid_item_tooltip_style_get(const Elm_Gengrid_Item *item)
2499 {
2500    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2501    return item->tooltip.style;
2502 }
2503
2504 /**
2505  * Set the cursor to be shown when mouse is over the gengrid item
2506  *
2507  * @param item Target item
2508  * @param cursor the cursor name to be used.
2509  *
2510  * @see elm_object_cursor_set()
2511  * @ingroup Gengrid
2512  */
2513 EAPI void
2514 elm_gengrid_item_cursor_set(Elm_Gengrid_Item *item,
2515                             const char       *cursor)
2516 {
2517    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2518    eina_stringshare_replace(&item->mouse_cursor, cursor);
2519    if (item->base.view) elm_widget_item_cursor_set(item, cursor);
2520 }
2521
2522 /**
2523  * Get the cursor to be shown when mouse is over the gengrid item
2524  *
2525  * @param item gengrid item with cursor already set.
2526  * @return the cursor name.
2527  *
2528  * @ingroup Gengrid
2529  */
2530 EAPI const char *
2531 elm_gengrid_item_cursor_get(const Elm_Gengrid_Item *item)
2532 {
2533    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2534    return elm_widget_item_cursor_get(item);
2535 }
2536
2537 /**
2538  * Unset the cursor to be shown when mouse is over the gengrid item
2539  *
2540  * @param item Target item
2541  *
2542  * @see elm_object_cursor_unset()
2543  * @ingroup Gengrid
2544  */
2545 EAPI void
2546 elm_gengrid_item_cursor_unset(Elm_Gengrid_Item *item)
2547 {
2548    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2549    if (!item->mouse_cursor)
2550      return;
2551
2552    if (item->base.view)
2553      elm_widget_item_cursor_unset(item);
2554
2555    eina_stringshare_del(item->mouse_cursor);
2556    item->mouse_cursor = NULL;
2557 }
2558
2559 /**
2560  * Sets a different style for this item cursor.
2561  *
2562  * @note before you set a style you should define a cursor with
2563  *       elm_gengrid_item_cursor_set()
2564  *
2565  * @param item gengrid item with cursor already set.
2566  * @param style the theme style to use (default, transparent, ...)
2567  *
2568  * @ingroup Gengrid
2569  */
2570 EAPI void
2571 elm_gengrid_item_cursor_style_set(Elm_Gengrid_Item *item,
2572                                   const char       *style)
2573 {
2574    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2575    elm_widget_item_cursor_style_set(item, style);
2576 }
2577
2578 /**
2579  * Get the style for this item cursor.
2580  *
2581  * @param item gengrid item with cursor already set.
2582  * @return style the theme style in use, defaults to "default". If the
2583  *         object does not have a cursor set, then NULL is returned.
2584  *
2585  * @ingroup Gengrid
2586  */
2587 EAPI const char *
2588 elm_gengrid_item_cursor_style_get(const Elm_Gengrid_Item *item)
2589 {
2590    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2591    return elm_widget_item_cursor_style_get(item);
2592 }
2593
2594 /**
2595  * Set if the cursor set should be searched on the theme or should use
2596  * the provided by the engine, only.
2597  *
2598  * @note before you set if should look on theme you should define a
2599  * cursor with elm_object_cursor_set(). By default it will only look
2600  * for cursors provided by the engine.
2601  *
2602  * @param item widget item with cursor already set.
2603  * @param engine_only boolean to define it cursors should be looked
2604  * only between the provided by the engine or searched on widget's
2605  * theme as well.
2606  *
2607  * @ingroup Gengrid
2608  */
2609 EAPI void
2610 elm_gengrid_item_cursor_engine_only_set(Elm_Gengrid_Item *item,
2611                                         Eina_Bool         engine_only)
2612 {
2613    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2614    elm_widget_item_cursor_engine_only_set(item, engine_only);
2615 }
2616
2617 /**
2618  * Get the cursor engine only usage for this item cursor.
2619  *
2620  * @param item widget item with cursor already set.
2621  * @return engine_only boolean to define it cursors should be looked
2622  * only between the provided by the engine or searched on widget's
2623  * theme as well. If the object does not have a cursor set, then
2624  * EINA_FALSE is returned.
2625  *
2626  * @ingroup Gengrid
2627  */
2628 EAPI Eina_Bool
2629 elm_gengrid_item_cursor_engine_only_get(const Elm_Gengrid_Item *item)
2630 {
2631    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2632    return elm_widget_item_cursor_engine_only_get(item);
2633 }
2634
2635 /**
2636  * Set the always select mode.
2637  *
2638  * Cells will only call their selection func and callback when first
2639  * becoming selected. Any further clicks will do nothing, unless you
2640  * enable always select with
2641  * elm_gengrid_always_select_mode_set(). This means even if selected,
2642  * every click will make the selected callbacks be called.
2643  *
2644  * @param obj The Gengrid object
2645  * @param always_select The always select mode (EINA_TRUE = on,
2646  * EINA_FALSE = off)
2647  *
2648  * @ingroup Gengrid
2649  */
2650 EAPI void
2651 elm_gengrid_always_select_mode_set(Evas_Object *obj,
2652                                    Eina_Bool    always_select)
2653 {
2654    ELM_CHECK_WIDTYPE(obj, widtype);
2655    Widget_Data *wd = elm_widget_data_get(obj);
2656    if (!wd) return;
2657    wd->always_select = always_select;
2658 }
2659
2660 /**
2661  * Get the always select mode.
2662  *
2663  * @param obj The Gengrid object.
2664  * @return The always select mode (EINA_TRUE = on, EINA_FALSE = off)
2665  *
2666  * @ingroup Gengrid
2667  */
2668 EAPI Eina_Bool
2669 elm_gengrid_always_select_mode_get(const Evas_Object *obj)
2670 {
2671    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2672    Widget_Data *wd = elm_widget_data_get(obj);
2673    if (!wd) return EINA_FALSE;
2674    return wd->always_select;
2675 }
2676
2677 /**
2678  * Set no select mode.
2679  *
2680  * This will turn off the ability to select items entirely and they
2681  * will neither appear selected nor call selected callback functions.
2682  *
2683  * @param obj The Gengrid object
2684  * @param no_select The no select mode (EINA_TRUE = on, EINA_FALSE = off)
2685  *
2686  * @ingroup Gengrid
2687  */
2688 EAPI void
2689 elm_gengrid_no_select_mode_set(Evas_Object *obj,
2690                                Eina_Bool    no_select)
2691 {
2692    ELM_CHECK_WIDTYPE(obj, widtype);
2693    Widget_Data *wd = elm_widget_data_get(obj);
2694    if (!wd) return;
2695    wd->no_select = no_select;
2696 }
2697
2698 /**
2699  * Gets no select mode.
2700  *
2701  * @param obj The Gengrid object
2702  * @return The no select mode (EINA_TRUE = on, EINA_FALSE = off)
2703  *
2704  * @ingroup Gengrid
2705  */
2706 EAPI Eina_Bool
2707 elm_gengrid_no_select_mode_get(const Evas_Object *obj)
2708 {
2709    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2710    Widget_Data *wd = elm_widget_data_get(obj);
2711    if (!wd) return EINA_FALSE;
2712    return wd->no_select;
2713 }
2714
2715 /**
2716  * Set bounce mode.
2717  *
2718  * This will enable or disable the scroller bounce mode for the
2719  * Gengrid. See elm_scroller_bounce_set() for details.
2720  *
2721  * @param obj The Gengrid object
2722  * @param h_bounce Allow bounce horizontally
2723  * @param v_bounce Allow bounce vertically
2724  *
2725  * @ingroup Gengrid
2726  */
2727 EAPI void
2728 elm_gengrid_bounce_set(Evas_Object *obj,
2729                        Eina_Bool    h_bounce,
2730                        Eina_Bool    v_bounce)
2731 {
2732    ELM_CHECK_WIDTYPE(obj, widtype);
2733    Widget_Data *wd = elm_widget_data_get(obj);
2734    if (!wd) return;
2735    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
2736 }
2737
2738 /**
2739  * Get the bounce mode
2740  *
2741  * @param obj The Gengrid object
2742  * @param h_bounce Allow bounce horizontally
2743  * @param v_bounce Allow bounce vertically
2744  *
2745  * @ingroup Gengrid
2746  */
2747 EAPI void
2748 elm_gengrid_bounce_get(const Evas_Object *obj,
2749                        Eina_Bool         *h_bounce,
2750                        Eina_Bool         *v_bounce)
2751 {
2752    ELM_CHECK_WIDTYPE(obj, widtype);
2753    Widget_Data *wd = elm_widget_data_get(obj);
2754    if (!wd) return;
2755    elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
2756 }
2757
2758 /**
2759  * Get all items in the Gengrid.
2760  *
2761  * This returns a list of the Gengrid items. The list contains
2762  * Elm_Gengrid_Item pointers.
2763  *
2764  * @param obj The Gengrid object.
2765  * @return The list of items, or NULL if none.
2766  *
2767  * @ingroup Gengrid
2768  */
2769
2770 /**
2771  * Set gengrid scroll page size relative to viewport size.
2772  *
2773  * The gengrid scroller is capable of limiting scrolling by the user
2774  * to "pages" That is to jump by and only show a "whole page" at a
2775  * time as if the continuous area of the scroller content is split
2776  * into page sized pieces.  This sets the size of a page relative to
2777  * the viewport of the scroller. 1.0 is "1 viewport" is size
2778  * (horizontally or vertically). 0.0 turns it off in that axis. This
2779  * is mutually exclusive with page size (see
2780  * elm_gengrid_page_size_set() for more information). Likewise 0.5 is
2781  * "half a viewport". Sane usable valus are normally between 0.0 and
2782  * 1.0 including 1.0. If you only want 1 axis to be page "limited",
2783  * use 0.0 for the other axis.
2784  *
2785  * @param obj The gengrid object
2786  * @param h_pagerel The horizontal page relative size
2787  * @param v_pagerel The vertical page relative size
2788  *
2789  * @ingroup Gengrid
2790  */
2791 EAPI void
2792 elm_gengrid_page_relative_set(Evas_Object *obj,
2793                               double       h_pagerel,
2794                               double       v_pagerel)
2795 {
2796    Evas_Coord pagesize_h;
2797    Evas_Coord pagesize_v;
2798
2799    ELM_CHECK_WIDTYPE(obj, widtype);
2800    Widget_Data *wd = elm_widget_data_get(obj);
2801    if (!wd) return;
2802
2803    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
2804    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
2805                                  pagesize_v);
2806 }
2807
2808 /*
2809  * Get gengrid scroll page size relative to viewport size.
2810  *
2811  * The gengrid scroller is capable of limiting scrolling by the user
2812  * to "pages" That is to jump by and only show a "whole page" at a
2813  * time as if the continuous area of the scroller content is split
2814  * into page sized pieces.  This sets the size of a page relative to
2815  * the viewport of the scroller. 1.0 is "1 viewport" is size
2816  * (horizontally or vertically). 0.0 turns it off in that axis. This
2817  * is mutually exclusive with page size (see
2818  * elm_gengrid_page_size_set() for more information). Likewise 0.5 is
2819  * "half a viewport". Sane usable valus are normally between 0.0 and
2820  * 1.0 including 1.0. If you only want 1 axis to be page "limited",
2821  * use 0.0 for the other axis.
2822  *
2823  * @param obj The gengrid object
2824  * @param h_pagerel The horizontal page relative size
2825  * @param v_pagerel The vertical page relative size
2826  *
2827  @ingroup Gengrid
2828  */
2829 EAPI void
2830 elm_gengrid_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel)
2831 {
2832    ELM_CHECK_WIDTYPE(obj, widtype);
2833    Widget_Data *wd = elm_widget_data_get(obj);
2834    if (!wd) return;
2835
2836    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
2837 }
2838
2839 /**
2840  * Set gengrid scroll page size.
2841  *
2842  * See also elm_gengrid_page_relative_set(). This, instead of a page
2843  * size being relative to the viewport, sets it to an absolute fixed
2844  * value, with 0 turning it off for that axis.
2845  *
2846  * @param obj The gengrid object
2847  * @param h_pagesize The horizontal page size
2848  * @param v_pagesize The vertical page size
2849  *
2850  * @ingroup Gengrid
2851  */
2852 EAPI void
2853 elm_gengrid_page_size_set(Evas_Object *obj,
2854                           Evas_Coord   h_pagesize,
2855                           Evas_Coord   v_pagesize)
2856 {
2857    double pagerel_h;
2858    double pagerel_v;
2859
2860    ELM_CHECK_WIDTYPE(obj, widtype);
2861    Widget_Data *wd = elm_widget_data_get(obj);
2862    if (!wd) return;
2863    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
2864    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
2865                                  v_pagesize);
2866 }
2867
2868 /**
2869  * Get the first item in the gengrid
2870  *
2871  * This returns the first item in the list.
2872  *
2873  * @param obj The gengrid object
2874  * @return The first item, or NULL if none
2875  *
2876  * @ingroup Gengrid
2877  */
2878 EAPI Elm_Gengrid_Item *
2879 elm_gengrid_first_item_get(const Evas_Object *obj)
2880 {
2881    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2882    Widget_Data *wd = elm_widget_data_get(obj);
2883    if (!wd) return NULL;
2884    if (!wd->items) return NULL;
2885    Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
2886    while ((item) && (item->delete_me))
2887      item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
2888    return item;
2889 }
2890
2891 /**
2892  * Get the last item in the gengrid
2893  *
2894  * This returns the last item in the list.
2895  *
2896  * @return The last item, or NULL if none
2897  *
2898  * @ingroup Gengrid
2899  */
2900 EAPI Elm_Gengrid_Item *
2901 elm_gengrid_last_item_get(const Evas_Object *obj)
2902 {
2903    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2904    Widget_Data *wd = elm_widget_data_get(obj);
2905    if (!wd) return NULL;
2906    if (!wd->items) return NULL;
2907    Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
2908    while ((item) && (item->delete_me))
2909      item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
2910    return item;
2911 }
2912
2913 /**
2914  * Get the next item in the gengrid
2915  *
2916  * This returns the item after the item @p item.
2917  *
2918  * @param item The item
2919  * @return The item after @p item, or NULL if none
2920  *
2921  * @ingroup Gengrid
2922  */
2923 EAPI Elm_Gengrid_Item *
2924 elm_gengrid_item_next_get(const Elm_Gengrid_Item *item)
2925 {
2926    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2927    while (item)
2928      {
2929         item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
2930         if ((item) && (!item->delete_me)) break;
2931      }
2932    return (Elm_Gengrid_Item *)item;
2933 }
2934
2935 /**
2936  * Get the previous item in the gengrid
2937  *
2938  * This returns the item before the item @p item.
2939  *
2940  * @param item The item
2941  * @return The item before @p item, or NULL if none
2942  *
2943  * @ingroup Gengrid
2944  */
2945 EAPI Elm_Gengrid_Item *
2946 elm_gengrid_item_prev_get(const Elm_Gengrid_Item *item)
2947 {
2948    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2949    while (item)
2950      {
2951         item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
2952         if ((item) && (!item->delete_me)) break;
2953      }
2954    return (Elm_Gengrid_Item *)item;
2955 }
2956
2957 /**
2958  * Get the gengrid object from an item
2959  *
2960  * This returns the gengrid object itself that an item belongs to.
2961  *
2962  * @param item The item
2963  * @return The gengrid object
2964  *
2965  * @ingroup Gengrid
2966  */
2967 EAPI Evas_Object *
2968 elm_gengrid_item_gengrid_get(const Elm_Gengrid_Item *item)
2969 {
2970    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2971    return item->base.widget;
2972 }
2973
2974 /**
2975  * Show the given item
2976  *
2977  * This causes gengrid to jump to the given item @p item and show it
2978  * (by scrolling), if it is not fully visible.
2979  *
2980  * @param item The item
2981  *
2982  * @ingroup Gengrid
2983  */
2984 EAPI void
2985 elm_gengrid_item_show(Elm_Gengrid_Item *item)
2986 {
2987    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2988    Widget_Data *wd = elm_widget_data_get(item->wd->self);
2989    Evas_Coord minx = 0, miny = 0;
2990
2991    if (!wd) return;
2992    if ((!item) || (item->delete_me)) return;
2993    _pan_min_get(wd->pan_smart, &minx, &miny);
2994
2995    elm_smart_scroller_child_region_show(item->wd->scr,
2996                                         item->x * wd->item_width + minx,
2997                                         item->y * wd->item_height + miny,
2998                                         item->wd->item_width,
2999                                         item->wd->item_height);
3000 }
3001
3002 /**
3003  * Bring in the given item
3004  *
3005  * This causes gengrig to jump to the given item @p item and show it
3006  * (by scrolling), if it is not fully visible. This may use animation
3007  * to do so and take a period of time
3008  *
3009  * @param item The item
3010  *
3011  * @ingroup Gengrid
3012  */
3013 EAPI void
3014 elm_gengrid_item_bring_in(Elm_Gengrid_Item *item)
3015 {
3016    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
3017    if (item->delete_me) return;
3018
3019    Evas_Coord minx = 0, miny = 0;
3020    Widget_Data *wd = elm_widget_data_get(item->wd->self);
3021    if (!wd) return;
3022    _pan_min_get(wd->pan_smart, &minx, &miny);
3023
3024    elm_smart_scroller_region_bring_in(item->wd->scr,
3025                                       item->x * wd->item_width + minx,
3026                                       item->y * wd->item_height + miny,
3027                                       item->wd->item_width,
3028                                       item->wd->item_height);
3029 }