elm list/gengrid: Fixed typo in internal functions and variables. hilight -> highlight.
[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  * TODO:
7  * Handle non-homogeneous objects too.
8  */
9
10  typedef struct _Widget_Data Widget_Data;
11  typedef struct _Pan         Pan;
12
13 #define PRELOAD 1
14 #define REORDER_EFFECT_TIME 0.5
15
16  struct _Elm_Gengrid_Item
17 {
18    Elm_Widget_Item               base;
19    EINA_INLIST;
20    Evas_Object                  *spacer;
21    const Elm_Gengrid_Item_Class *gic;
22    Ecore_Timer                  *long_timer;
23    Ecore_Animator               *item_moving_effect_timer;
24    Widget_Data                  *wd;
25    Eina_List                    *labels, *icons, *states, *icon_objs;
26    struct
27      {
28         Evas_Smart_Cb func;
29         const void   *data;
30      } func;
31
32    Evas_Coord   x, y, dx, dy, ox, oy, tx, ty, rx, ry;
33    unsigned int moving_effect_start_time;
34    int          relcount;
35    int          walking;
36
37    struct
38      {
39         const void                 *data;
40         Elm_Tooltip_Item_Content_Cb content_cb;
41         Evas_Smart_Cb               del_cb;
42         const char                 *style;
43         Eina_Bool                   free_size : 1;
44      } tooltip;
45
46    const char *mouse_cursor;
47
48    Eina_Bool   want_unrealize : 1;
49    Eina_Bool   realized : 1;
50    Eina_Bool   dragging : 1;
51    Eina_Bool   down : 1;
52    Eina_Bool   delete_me : 1;
53    Eina_Bool   display_only : 1;
54    Eina_Bool   disabled : 1;
55    Eina_Bool   selected : 1;
56    Eina_Bool   highlighted : 1;
57    Eina_Bool   moving : 1;
58 };
59
60 struct _Widget_Data
61 {
62    Evas_Object      *self, *scr;
63    Evas_Object      *pan_smart;
64    Pan              *pan;
65    Eina_Inlist      *items;
66    Ecore_Job        *calc_job;
67    Eina_List        *selected;
68    Elm_Gengrid_Item *last_selected_item, *reorder_item;
69    double            align_x, align_y;
70
71    Evas_Coord        pan_x, pan_y, old_pan_x, old_pan_y;
72    Evas_Coord        item_width, item_height; /* Each item size */
73    Evas_Coord        minw, minh; /* Total obj size */
74    Evas_Coord        reorder_item_x, reorder_item_y;
75    unsigned int      nmax;
76    long              count;
77    int               walking;
78
79    Eina_Bool         horizontal : 1;
80    Eina_Bool         on_hold : 1;
81    Eina_Bool         longpressed : 1;
82    Eina_Bool         multi : 1;
83    Eina_Bool         no_select : 1;
84    Eina_Bool         wasselected : 1;
85    Eina_Bool         always_select : 1;
86    Eina_Bool         clear_me : 1;
87    Eina_Bool         h_bounce : 1;
88    Eina_Bool         v_bounce : 1;
89    Eina_Bool         reorder_mode : 1;
90    Eina_Bool         reorder_item_changed : 1;
91    Eina_Bool         move_effect_enabled : 1;
92 };
93
94 #define ELM_GENGRID_ITEM_FROM_INLIST(item) \
95    ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Gengrid_Item) : NULL)
96
97 struct _Pan
98 {
99    Evas_Object_Smart_Clipped_Data __clipped_data;
100    Widget_Data                   *wd;
101 };
102
103 static const char *widtype = NULL;
104 static void      _item_highlight(Elm_Gengrid_Item *item);
105 static void      _item_unrealize(Elm_Gengrid_Item *item);
106 static void      _item_select(Elm_Gengrid_Item *item);
107 static void      _item_unselect(Elm_Gengrid_Item *item);
108 static void      _calc_job(void *data);
109 static void      _on_focus_hook(void        *data,
110                                 Evas_Object *obj);
111 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
112 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
113 static Eina_Bool _item_multi_select_left(Widget_Data *wd);
114 static Eina_Bool _item_multi_select_right(Widget_Data *wd);
115 static Eina_Bool _item_single_select_up(Widget_Data *wd);
116 static Eina_Bool _item_single_select_down(Widget_Data *wd);
117 static Eina_Bool _item_single_select_left(Widget_Data *wd);
118 static Eina_Bool _item_single_select_right(Widget_Data *wd);
119 static Eina_Bool _event_hook(Evas_Object       *obj,
120                              Evas_Object       *src,
121                              Evas_Callback_Type type,
122                              void              *event_info);
123 static Eina_Bool _deselect_all_items(Widget_Data *wd);
124
125 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
126 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
127
128 static const char SIG_ACTIVATED[] = "activated";
129 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
130 static const char SIG_SELECTED[] = "selected";
131 static const char SIG_UNSELECTED[] = "unselected";
132 static const char SIG_REALIZED[] = "realized";
133 static const char SIG_UNREALIZED[] = "unrealized";
134 static const char SIG_CHANGED[] = "changed";
135 static const char SIG_DRAG_START_UP[] = "drag,start,up";
136 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
137 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
138 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
139 static const char SIG_DRAG_STOP[] = "drag,stop";
140 static const char SIG_DRAG[] = "drag";
141 static const char SIG_SCROLL[] = "scroll";
142 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
143 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
144 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
145 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
146 static const char SIG_MOVED[] = "moved";
147
148 static const Evas_Smart_Cb_Description _signals[] = {
149    {SIG_ACTIVATED, ""},
150    {SIG_CLICKED_DOUBLE, ""},
151    {SIG_SELECTED, ""},
152    {SIG_UNSELECTED, ""},
153    {SIG_REALIZED, ""},
154    {SIG_UNREALIZED, ""},
155    {SIG_CHANGED, ""},
156    {SIG_DRAG_START_UP, ""},
157    {SIG_DRAG_START_DOWN, ""},
158    {SIG_DRAG_START_LEFT, ""},
159    {SIG_DRAG_START_RIGHT, ""},
160    {SIG_DRAG_STOP, ""},
161    {SIG_DRAG, ""},
162    {SIG_SCROLL, ""},
163    {SIG_SCROLL_ANIM_START, ""},
164    {SIG_SCROLL_ANIM_STOP, ""},
165    {SIG_SCROLL_DRAG_START, ""},
166    {SIG_SCROLL_DRAG_STOP, ""},
167    {SIG_MOVED, ""},
168    {NULL, NULL}
169 };
170
171 static Eina_Compare_Cb _elm_gengrid_item_compare_cb;
172 static Eina_Compare_Cb _elm_gengrid_item_compare_data_cb;
173
174 static Eina_Bool
175 _event_hook(Evas_Object       *obj,
176             Evas_Object *src   __UNUSED__,
177             Evas_Callback_Type type,
178             void              *event_info)
179 {
180    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
181    Evas_Event_Key_Down *ev = event_info;
182    Widget_Data *wd = elm_widget_data_get(obj);
183    if (!wd) return EINA_FALSE;
184    if (!wd->items) return EINA_FALSE;
185    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
186    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
187
188    Elm_Gengrid_Item *item = NULL;
189    Evas_Coord x = 0;
190    Evas_Coord y = 0;
191    Evas_Coord step_x = 0;
192    Evas_Coord step_y = 0;
193    Evas_Coord v_w = 0;
194    Evas_Coord v_h = 0;
195    Evas_Coord page_x = 0;
196    Evas_Coord page_y = 0;
197
198    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
199    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
200    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
201    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
202
203    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
204      {
205         if ((wd->horizontal) &&
206             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
207               (_item_multi_select_up(wd)))
208              || (_item_single_select_up(wd))))
209           {
210              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
211              return EINA_TRUE;
212           }
213         else if ((!wd->horizontal) &&
214                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
215                    (_item_multi_select_left(wd)))
216                   || (_item_single_select_left(wd))))
217           {
218              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
219              return EINA_TRUE;
220           }
221         else
222           x -= step_x;
223      }
224    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
225      {
226         if ((wd->horizontal) &&
227             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
228               (_item_multi_select_down(wd)))
229              || (_item_single_select_down(wd))))
230           {
231              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
232              return EINA_TRUE;
233           }
234         else if ((!wd->horizontal) &&
235                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
236                    (_item_multi_select_right(wd)))
237                   || (_item_single_select_right(wd))))
238           {
239              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
240              return EINA_TRUE;
241           }
242         else
243           x += step_x;
244      }
245    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
246      {
247         if ((wd->horizontal) &&
248             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
249               (_item_multi_select_left(wd)))
250              || (_item_single_select_left(wd))))
251           {
252              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
253              return EINA_TRUE;
254           }
255         else if ((!wd->horizontal) &&
256                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
257                    (_item_multi_select_up(wd)))
258                   || (_item_single_select_up(wd))))
259           {
260              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
261              return EINA_TRUE;
262           }
263         else
264           y -= step_y;
265      }
266    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
267      {
268         if ((wd->horizontal) &&
269             (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
270               (_item_multi_select_right(wd)))
271              || (_item_single_select_right(wd))))
272           {
273              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
274              return EINA_TRUE;
275           }
276         else if ((!wd->horizontal) &&
277                  (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
278                    (_item_multi_select_down(wd)))
279                   || (_item_single_select_down(wd))))
280           {
281              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
282              return EINA_TRUE;
283           }
284         else
285           y += step_y;
286      }
287    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
288      {
289         item = elm_gengrid_first_item_get(obj);
290         elm_gengrid_item_bring_in(item);
291         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
292         return EINA_TRUE;
293      }
294    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
295      {
296         item = elm_gengrid_last_item_get(obj);
297         elm_gengrid_item_bring_in(item);
298         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
299         return EINA_TRUE;
300      }
301    else if ((!strcmp(ev->keyname, "Prior")) ||
302             (!strcmp(ev->keyname, "KP_Prior")))
303      {
304         if (wd->horizontal)
305           {
306              if (page_x < 0)
307                x -= -(page_x * v_w) / 100;
308              else
309                x -= page_x;
310           }
311         else
312           {
313              if (page_y < 0)
314                y -= -(page_y * v_h) / 100;
315              else
316                y -= page_y;
317           }
318      }
319    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
320      {
321         if (wd->horizontal)
322           {
323              if (page_x < 0)
324                x += -(page_x * v_w) / 100;
325              else
326                x += page_x;
327           }
328         else
329           {
330              if (page_y < 0)
331                y += -(page_y * v_h) / 100;
332              else
333                y += page_y;
334           }
335      }
336    else if (!strcmp(ev->keyname, "Escape"))
337      {
338         if (!_deselect_all_items(wd)) return EINA_FALSE;
339         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
340         return EINA_TRUE;
341      }
342    else if ((!strcmp(ev->keyname, "Return")) ||
343             (!strcmp(ev->keyname, "KP_Enter")) ||
344             (!strcmp(ev->keyname, "space")))
345      {
346         item = elm_gengrid_selected_item_get(obj);
347         evas_object_smart_callback_call(item->wd->self, SIG_ACTIVATED, item);
348      }
349    else return EINA_FALSE;
350
351    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
352    elm_smart_scroller_child_pos_set(wd->scr, x, y);
353    return EINA_TRUE;
354 }
355
356 static Eina_Bool
357 _deselect_all_items(Widget_Data *wd)
358 {
359    if (!wd->selected) return EINA_FALSE;
360    while(wd->selected)
361      elm_gengrid_item_selected_set(wd->selected->data, EINA_FALSE);
362
363    return EINA_TRUE;
364 }
365
366 static Eina_Bool
367 _item_multi_select_left(Widget_Data *wd)
368 {
369    if (!wd->selected) return EINA_FALSE;
370
371    Elm_Gengrid_Item *prev = elm_gengrid_item_prev_get(wd->last_selected_item);
372    if (!prev) return EINA_TRUE;
373    if (elm_gengrid_item_selected_get(prev))
374      {
375         elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
376         wd->last_selected_item = prev;
377         elm_gengrid_item_show(wd->last_selected_item);
378      }
379    else
380      {
381         elm_gengrid_item_selected_set(prev, EINA_TRUE);
382         elm_gengrid_item_show(prev);
383      }
384
385    return EINA_TRUE;
386 }
387
388 static Eina_Bool
389 _item_multi_select_right(Widget_Data *wd)
390 {
391    if (!wd->selected) return EINA_FALSE;
392
393    Elm_Gengrid_Item *next = elm_gengrid_item_next_get(wd->last_selected_item);
394    if (!next) return EINA_TRUE;
395    if (elm_gengrid_item_selected_get(next))
396      {
397         elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
398         wd->last_selected_item = next;
399         elm_gengrid_item_show(wd->last_selected_item);
400      }
401    else
402      {
403         elm_gengrid_item_selected_set(next, EINA_TRUE);
404         elm_gengrid_item_show(next);
405      }
406
407    return EINA_TRUE;
408 }
409
410 static Eina_Bool
411 _item_multi_select_up(Widget_Data *wd)
412 {
413    unsigned int i;
414    Eina_Bool r = EINA_TRUE;
415
416    if (!wd->selected) return EINA_FALSE;
417
418    for (i = 0; (r) && (i < wd->nmax); i++)
419      r &= _item_multi_select_left(wd);
420
421    return r;
422 }
423
424 static Eina_Bool
425 _item_multi_select_down(Widget_Data *wd)
426 {
427    unsigned int i;
428    Eina_Bool r = EINA_TRUE;
429
430    if (!wd->selected) return EINA_FALSE;
431
432    for (i = 0; (r) && (i < wd->nmax); i++)
433      r &= _item_multi_select_right(wd);
434
435    return r;
436 }
437
438 static Eina_Bool
439 _item_single_select_up(Widget_Data *wd)
440 {
441    unsigned int i;
442
443    Elm_Gengrid_Item *prev;
444
445    if (!wd->selected)
446      {
447         prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
448         while ((prev) && (prev->delete_me))
449           prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
450         elm_gengrid_item_selected_set(prev, EINA_TRUE);
451         elm_gengrid_item_show(prev);
452         return EINA_TRUE;
453      }
454    else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
455
456    if (!prev) return EINA_FALSE;
457
458    for (i = 1; i < wd->nmax; i++)
459      {
460         Elm_Gengrid_Item *tmp = elm_gengrid_item_prev_get(prev);
461         if (!tmp) return EINA_FALSE;
462         prev = tmp;
463      }
464
465    _deselect_all_items(wd);
466
467    elm_gengrid_item_selected_set(prev, EINA_TRUE);
468    elm_gengrid_item_show(prev);
469    return EINA_TRUE;
470 }
471
472 static Eina_Bool
473 _item_single_select_down(Widget_Data *wd)
474 {
475    unsigned int i;
476
477    Elm_Gengrid_Item *next;
478
479    if (!wd->selected)
480      {
481         next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
482         while ((next) && (next->delete_me))
483           next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
484         elm_gengrid_item_selected_set(next, EINA_TRUE);
485         elm_gengrid_item_show(next);
486         return EINA_TRUE;
487      }
488    else next = elm_gengrid_item_next_get(wd->last_selected_item);
489
490    if (!next) return EINA_FALSE;
491
492    for (i = 1; i < wd->nmax; i++)
493      {
494         Elm_Gengrid_Item *tmp = elm_gengrid_item_next_get(next);
495         if (!tmp) return EINA_FALSE;
496         next = tmp;
497      }
498
499    _deselect_all_items(wd);
500
501    elm_gengrid_item_selected_set(next, EINA_TRUE);
502    elm_gengrid_item_show(next);
503    return EINA_TRUE;
504 }
505
506 static Eina_Bool
507 _item_single_select_left(Widget_Data *wd)
508 {
509    Elm_Gengrid_Item *prev;
510    if (!wd->selected)
511      {
512         prev = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
513         while ((prev) && (prev->delete_me))
514           prev = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
515      }
516    else prev = elm_gengrid_item_prev_get(wd->last_selected_item);
517
518    if (!prev) return EINA_FALSE;
519
520    _deselect_all_items(wd);
521
522    elm_gengrid_item_selected_set(prev, EINA_TRUE);
523    elm_gengrid_item_show(prev);
524    return EINA_TRUE;
525 }
526
527 static Eina_Bool
528 _item_single_select_right(Widget_Data *wd)
529 {
530    Elm_Gengrid_Item *next;
531    if (!wd->selected)
532      {
533         next = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
534         while ((next) && (next->delete_me))
535           next = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
536      }
537    else next = elm_gengrid_item_next_get(wd->last_selected_item);
538
539    if (!next) return EINA_FALSE;
540
541    _deselect_all_items(wd);
542
543    elm_gengrid_item_selected_set(next, EINA_TRUE);
544    elm_gengrid_item_show(next);
545    return EINA_TRUE;
546 }
547
548 static void
549 _on_focus_hook(void *data   __UNUSED__,
550                Evas_Object *obj)
551 {
552    Widget_Data *wd = elm_widget_data_get(obj);
553    if (!wd) return;
554    if (elm_widget_focus_get(obj))
555      {
556         edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
557         evas_object_focus_set(wd->self, EINA_TRUE);
558         if ((wd->selected) && (!wd->last_selected_item))
559           wd->last_selected_item = eina_list_data_get(wd->selected);
560      }
561    else
562      {
563         edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
564         evas_object_focus_set(wd->self, EINA_FALSE);
565      }
566 }
567
568 static void
569 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
570 {
571    Widget_Data *wd = elm_widget_data_get(obj);
572    Elm_Gengrid_Item *item;
573    if (!wd) return;
574    elm_smart_scroller_mirrored_set(wd->scr, rtl);
575    if (!wd->items) return;
576    item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
577
578    while (item)
579      {
580         edje_object_mirrored_set(item->base.view, rtl);
581         elm_gengrid_item_update(item);
582         item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
583      }
584 }
585
586 static void
587 _theme_hook(Evas_Object *obj)
588 {
589    Widget_Data *wd = elm_widget_data_get(obj);
590    if (!wd) return;
591    _elm_widget_mirrored_reload(obj);
592    _mirrored_set(obj, elm_widget_mirrored_get(obj));
593    elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
594                                        elm_widget_style_get(obj));
595 }
596
597 static void
598 _del_pre_hook(Evas_Object *obj)
599 {
600    Widget_Data *wd = elm_widget_data_get(obj);
601    if (!wd) return;
602    elm_gengrid_clear(obj);
603    evas_object_del(wd->pan_smart);
604    wd->pan_smart = NULL;
605 }
606
607 static void
608 _del_hook(Evas_Object *obj)
609 {
610    Widget_Data *wd = elm_widget_data_get(obj);
611    free(wd);
612 }
613
614 static void
615 _signal_emit_hook(Evas_Object *obj,
616                   const char  *emission,
617                   const char  *source)
618 {
619    Widget_Data *wd = elm_widget_data_get(obj);
620    if (!wd) return;
621    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
622                            emission, source);
623 }
624
625 static void
626 _mouse_move(void        *data,
627             Evas *evas   __UNUSED__,
628             Evas_Object *obj,
629             void        *event_info)
630 {
631    Elm_Gengrid_Item *item = data;
632    Evas_Event_Mouse_Move *ev = event_info;
633    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
634    Evas_Coord ox, oy, ow, oh, it_scrl_x, it_scrl_y;
635
636    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
637      {
638         if (!item->wd->on_hold)
639           {
640              item->wd->on_hold = EINA_TRUE;
641              if (!item->wd->wasselected)
642                _item_unselect(item);
643           }
644      }
645    if ((item->dragging) && (item->down))
646      {
647         if (item->long_timer)
648           {
649              ecore_timer_del(item->long_timer);
650              item->long_timer = NULL;
651           }
652         evas_object_smart_callback_call(item->wd->self, SIG_DRAG, item);
653         return;
654      }
655    if ((!item->down) || (item->wd->longpressed))
656      {
657         if (item->long_timer)
658           {
659              ecore_timer_del(item->long_timer);
660              item->long_timer = NULL;
661           }
662         if ((item->wd->reorder_mode) && (item->wd->reorder_item))
663           {
664              evas_object_geometry_get(item->wd->pan_smart, &ox, &oy, &ow, &oh);
665
666              it_scrl_x = ev->cur.canvas.x - item->wd->reorder_item->dx;
667              it_scrl_y = ev->cur.canvas.y - item->wd->reorder_item->dy;
668
669              if (it_scrl_x < ox) item->wd->reorder_item_x = ox;
670              else if (it_scrl_x + item->wd->item_width > ox + ow)
671                item->wd->reorder_item_x = ox + ow - item->wd->item_width;
672              else item->wd->reorder_item_x = it_scrl_x;
673
674              if (it_scrl_y < oy) item->wd->reorder_item_y = oy;
675              else if (it_scrl_y + item->wd->item_height > oy + oh)
676                item->wd->reorder_item_y = oy + oh - item->wd->item_height;
677              else item->wd->reorder_item_y = it_scrl_y;
678
679              if (item->wd->calc_job) ecore_job_del(item->wd->calc_job);
680              item->wd->calc_job = ecore_job_add(_calc_job, item->wd);
681           }
682         return;
683      }
684    if (!item->display_only)
685      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
686    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
687    x = ev->cur.canvas.x - x;
688    y = ev->cur.canvas.y - y;
689    dx = x - item->dx;
690    adx = dx;
691    if (adx < 0) adx = -dx;
692    dy = y - item->dy;
693    ady = dy;
694    if (ady < 0) ady = -dy;
695    minw /= 2;
696    minh /= 2;
697    if ((adx > minw) || (ady > minh))
698      {
699         const char *left_drag, *right_drag;
700         if (!elm_widget_mirrored_get(item->wd->self))
701           {
702              left_drag = SIG_DRAG_START_LEFT;
703              right_drag = SIG_DRAG_START_RIGHT;
704           }
705         else
706           {
707              left_drag = SIG_DRAG_START_RIGHT;
708              right_drag = SIG_DRAG_START_LEFT;
709           }
710
711         item->dragging = 1;
712         if (item->long_timer)
713           {
714              ecore_timer_del(item->long_timer);
715              item->long_timer = NULL;
716           }
717         if (!item->wd->wasselected)
718           _item_unselect(item);
719         if (dy < 0)
720           {
721              if (ady > adx)
722                evas_object_smart_callback_call(item->wd->self, SIG_DRAG_START_UP,
723                                                item);
724              else
725                {
726                   if (dx < 0)
727                     evas_object_smart_callback_call(item->wd->self,
728                                                     left_drag, item);
729                }
730           }
731         else
732           {
733              if (ady > adx)
734                evas_object_smart_callback_call(item->wd->self,
735                                                SIG_DRAG_START_DOWN, item);
736              else
737                {
738                   if (dx < 0)
739                     evas_object_smart_callback_call(item->wd->self,
740                                                     left_drag, item);
741                   else
742                     evas_object_smart_callback_call(item->wd->self,
743                                                     right_drag, item);
744                }
745           }
746      }
747 }
748
749 static Eina_Bool
750 _long_press(void *data)
751 {
752    Elm_Gengrid_Item *item = data;
753
754    item->long_timer = NULL;
755    if ((item->disabled) || (item->dragging)) return ECORE_CALLBACK_CANCEL;
756    item->wd->longpressed = EINA_TRUE;
757    evas_object_smart_callback_call(item->wd->self, "longpressed", item);
758    if (item->wd->reorder_mode)
759      {
760         item->wd->reorder_item = item;
761         evas_object_raise(item->base.view);
762         elm_smart_scroller_hold_set(item->wd->scr, EINA_TRUE);
763         elm_smart_scroller_bounce_allow_set(item->wd->scr, EINA_FALSE, EINA_FALSE);
764         edje_object_signal_emit(item->base.view, "elm,state,reorder,enabled", "elm");
765      }
766    return ECORE_CALLBACK_CANCEL;
767 }
768
769 static void
770 _mouse_down(void        *data,
771             Evas *evas   __UNUSED__,
772             Evas_Object *obj,
773             void        *event_info)
774 {
775    Elm_Gengrid_Item *item = data;
776    Evas_Event_Mouse_Down *ev = event_info;
777    Evas_Coord x, y;
778
779    if (ev->button != 1) return;
780    item->down = 1;
781    item->dragging = 0;
782    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
783    item->dx = ev->canvas.x - x;
784    item->dy = ev->canvas.y - y;
785    item->wd->longpressed = EINA_FALSE;
786    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) item->wd->on_hold = EINA_TRUE;
787    else item->wd->on_hold = EINA_FALSE;
788    item->wd->wasselected = item->selected;
789    _item_highlight(item);
790    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
791      {
792         evas_object_smart_callback_call(item->wd->self, SIG_CLICKED_DOUBLE, item);
793         evas_object_smart_callback_call(item->wd->self, SIG_ACTIVATED, item);
794      }
795    if (item->long_timer) ecore_timer_del(item->long_timer);
796    if (item->realized)
797      item->long_timer = ecore_timer_add(_elm_config->longpress_timeout,
798                                         _long_press, item);
799    else
800      item->long_timer = NULL;
801 }
802
803 static void
804 _mouse_up(void            *data,
805           Evas *evas       __UNUSED__,
806           Evas_Object *obj __UNUSED__,
807           void            *event_info)
808 {
809    Elm_Gengrid_Item *item = data;
810    Evas_Event_Mouse_Up *ev = event_info;
811    Eina_Bool dragged = EINA_FALSE;
812
813    if (ev->button != 1) return;
814    item->down = EINA_FALSE;
815    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) item->wd->on_hold = EINA_TRUE;
816    else item->wd->on_hold = EINA_FALSE;
817    if (item->long_timer)
818      {
819         ecore_timer_del(item->long_timer);
820         item->long_timer = NULL;
821      }
822    if (item->dragging)
823      {
824         item->dragging = EINA_FALSE;
825         evas_object_smart_callback_call(item->wd->self, SIG_DRAG_STOP, item);
826         dragged = EINA_TRUE;
827      }
828    if (item->wd->on_hold)
829      {
830         item->wd->longpressed = EINA_FALSE;
831         item->wd->on_hold = EINA_FALSE;
832         return;
833      }
834    if ((item->wd->reorder_mode) && (item->wd->reorder_item))
835      {
836         if (item->wd->calc_job) ecore_job_del(item->wd->calc_job);
837           item->wd->calc_job = ecore_job_add(_calc_job, item->wd);
838
839         evas_object_smart_callback_call(item->wd->self, SIG_MOVED, item->wd->reorder_item);
840         item->wd->reorder_item = NULL;
841         elm_smart_scroller_hold_set(item->wd->scr, EINA_FALSE);
842         elm_smart_scroller_bounce_allow_set(item->wd->scr, item->wd->h_bounce, item->wd->v_bounce);
843         edje_object_signal_emit(item->base.view, "elm,state,reorder,disabled", "elm");
844      }
845    if (item->wd->longpressed)
846      {
847         item->wd->longpressed = EINA_FALSE;
848         if (!item->wd->wasselected) _item_unselect(item);
849         item->wd->wasselected = EINA_FALSE;
850         return;
851      }
852    if (dragged)
853      {
854         if (item->want_unrealize) _item_unrealize(item);
855      }
856    if ((item->disabled) || (dragged)) return;
857    if (item->wd->multi)
858      {
859         if (!item->selected)
860           {
861              _item_highlight(item);
862              _item_select(item);
863           }
864         else _item_unselect(item);
865      }
866    else
867      {
868         if (!item->selected)
869           {
870              while (item->wd->selected)
871                _item_unselect(item->wd->selected->data);
872           }
873         else
874           {
875              const Eina_List *l, *l_next;
876              Elm_Gengrid_Item *item2;
877
878              EINA_LIST_FOREACH_SAFE(item->wd->selected, l, l_next, item2)
879                 if (item2 != item) _item_unselect(item2);
880           }
881         _item_highlight(item);
882         _item_select(item);
883      }
884 }
885
886 static void
887 _item_highlight(Elm_Gengrid_Item *item)
888 {
889    if ((item->wd->no_select) || (item->delete_me) || (item->highlighted)) return;
890    edje_object_signal_emit(item->base.view, "elm,state,selected", "elm");
891    item->highlighted = EINA_TRUE;
892 }
893
894 static void
895 _item_realize(Elm_Gengrid_Item *item)
896 {
897    char buf[1024];
898    char style[1024];
899
900    if ((item->realized) || (item->delete_me)) return;
901    item->base.view = edje_object_add(evas_object_evas_get(item->wd->self));
902    edje_object_scale_set(item->base.view, elm_widget_scale_get(item->wd->self) *
903                          _elm_config->scale);
904    edje_object_mirrored_set(item->base.view, elm_widget_mirrored_get(item->base.widget));
905    evas_object_smart_member_add(item->base.view, item->wd->pan_smart);
906    elm_widget_sub_object_add(item->wd->self, item->base.view);
907    snprintf(style, sizeof(style), "item/%s",
908             item->gic->item_style ? item->gic->item_style : "default");
909    _elm_theme_object_set(item->wd->self, item->base.view, "gengrid", style,
910                          elm_widget_style_get(item->wd->self));
911    item->spacer =
912       evas_object_rectangle_add(evas_object_evas_get(item->wd->self));
913    evas_object_color_set(item->spacer, 0, 0, 0, 0);
914    elm_widget_sub_object_add(item->wd->self, item->spacer);
915    evas_object_size_hint_min_set(item->spacer, 2 * _elm_config->scale, 1);
916    edje_object_part_swallow(item->base.view, "elm.swallow.pad", item->spacer);
917
918    if (item->gic->func.label_get)
919      {
920         const Eina_List *l;
921         const char *key;
922
923         item->labels =
924            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
925                                                           "labels"));
926         EINA_LIST_FOREACH(item->labels, l, key)
927           {
928              char *s = item->gic->func.label_get
929                 ((void *)item->base.data, item->wd->self, l->data);
930              if (s)
931                {
932                   edje_object_part_text_set(item->base.view, l->data, s);
933                   free(s);
934                }
935           }
936      }
937
938    if (item->gic->func.icon_get)
939      {
940         const Eina_List *l;
941         const char *key;
942
943         item->icons =
944            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
945                                                           "icons"));
946         EINA_LIST_FOREACH(item->icons, l, key)
947           {
948              Evas_Object *ic = item->gic->func.icon_get
949                 ((void *)item->base.data, item->wd->self, l->data);
950              if (ic)
951                {
952                   item->icon_objs = eina_list_append(item->icon_objs, ic);
953                   edje_object_part_swallow(item->base.view, key, ic);
954                   evas_object_show(ic);
955                   elm_widget_sub_object_add(item->wd->self, ic);
956                }
957           }
958      }
959
960    if (item->gic->func.state_get)
961      {
962         const Eina_List *l;
963         const char *key;
964
965         item->states =
966            elm_widget_stringlist_get(edje_object_data_get(item->base.view,
967                                                           "states"));
968         EINA_LIST_FOREACH(item->states, l, key)
969           {
970              Eina_Bool on = item->gic->func.state_get
971                 ((void *)item->base.data, item->wd->self, l->data);
972              if (on)
973                {
974                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
975                   edje_object_signal_emit(item->base.view, buf, "elm");
976                }
977           }
978      }
979
980    if ((!item->wd->item_width) && (!item->wd->item_height))
981      {
982         edje_object_size_min_restricted_calc(item->base.view,
983                                              &item->wd->item_width,
984                                              &item->wd->item_height,
985                                              item->wd->item_width,
986                                              item->wd->item_height);
987         elm_coords_finger_size_adjust(1, &item->wd->item_width,
988                                       1, &item->wd->item_height);
989      }
990
991    evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_DOWN,
992                                   _mouse_down, item);
993    evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_UP,
994                                   _mouse_up, item);
995    evas_object_event_callback_add(item->base.view, EVAS_CALLBACK_MOUSE_MOVE,
996                                   _mouse_move, item);
997
998    if (item->selected)
999      edje_object_signal_emit(item->base.view, "elm,state,selected", "elm");
1000    if (item->disabled)
1001      edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
1002
1003    evas_object_show(item->base.view);
1004
1005    if (item->tooltip.content_cb)
1006      {
1007         elm_widget_item_tooltip_content_cb_set(item,
1008                                                item->tooltip.content_cb,
1009                                                item->tooltip.data, NULL);
1010         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
1011         elm_widget_item_tooltip_size_restrict_disable(item, item->tooltip.free_size);
1012      }
1013
1014    if (item->mouse_cursor)
1015      elm_widget_item_cursor_set(item, item->mouse_cursor);
1016
1017    item->realized = EINA_TRUE;
1018    item->want_unrealize = EINA_FALSE;
1019 }
1020
1021 static void
1022 _item_unrealize(Elm_Gengrid_Item *item)
1023 {
1024    Evas_Object *icon;
1025
1026    if (!item->realized) return;
1027    if (item->long_timer)
1028      {
1029         ecore_timer_del(item->long_timer);
1030         item->long_timer = NULL;
1031      }
1032    evas_object_del(item->base.view);
1033    item->base.view = NULL;
1034    evas_object_del(item->spacer);
1035    item->spacer = NULL;
1036    elm_widget_stringlist_free(item->labels);
1037    item->labels = NULL;
1038    elm_widget_stringlist_free(item->icons);
1039    item->icons = NULL;
1040    elm_widget_stringlist_free(item->states);
1041    item->states = NULL;
1042
1043    EINA_LIST_FREE(item->icon_objs, icon)
1044       evas_object_del(icon);
1045
1046    item->realized = EINA_FALSE;
1047    item->want_unrealize = EINA_FALSE;
1048 }
1049
1050 static Eina_Bool
1051 _reorder_item_moving_effect_timer_cb(void *data)
1052 {
1053    Elm_Gengrid_Item *item = data;
1054    double time, t;
1055    Evas_Coord dx, dy;
1056
1057    time = REORDER_EFFECT_TIME;
1058    t = ((0.0 > (t = ecore_loop_time_get()-item->moving_effect_start_time)) ? 0.0 : t);
1059    dx = ((item->tx - item->ox) / 10) * _elm_config->scale;
1060    dy = ((item->ty - item->oy) / 10) * _elm_config->scale;
1061
1062    if (t <= time)
1063      {
1064         item->rx += (1 * sin((t / time) * (M_PI / 2)) * dx);
1065         item->ry += (1 * sin((t / time) * (M_PI / 2)) * dy);
1066      }
1067    else
1068      {
1069         item->rx += dx;
1070         item->ry += dy;
1071      }
1072
1073    if ((((dx > 0) && (item->rx >= item->tx)) || ((dx <= 0) && (item->rx <= item->tx))) &&
1074        (((dy > 0) && (item->ry >= item->ty)) || ((dy <= 0) && (item->ry <= item->ty))))
1075      {
1076         evas_object_move(item->base.view, item->tx, item->ty);
1077         evas_object_resize(item->base.view, item->wd->item_width, item->wd->item_height);
1078         item->moving = EINA_FALSE;
1079         item->item_moving_effect_timer = NULL;
1080         return ECORE_CALLBACK_CANCEL;
1081      }
1082
1083    evas_object_move(item->base.view, item->rx, item->ry);
1084    evas_object_resize(item->base.view, item->wd->item_width, item->wd->item_height);
1085
1086    return ECORE_CALLBACK_RENEW;
1087 }
1088
1089 static void
1090 _item_place(Elm_Gengrid_Item *item,
1091             Evas_Coord        cx,
1092             Evas_Coord        cy)
1093 {
1094    Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh;
1095    Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
1096    Eina_Bool reorder_item_move_forward = EINA_FALSE;
1097    item->x = cx;
1098    item->y = cy;
1099    evas_object_geometry_get(item->wd->pan_smart, &ox, &oy, &vw, &vh);
1100
1101    /* Preload rows/columns at each side of the Gengrid */
1102    cvx = ox - PRELOAD * item->wd->item_width;
1103    cvy = oy - PRELOAD * item->wd->item_height;
1104    cvw = vw + 2 * PRELOAD * item->wd->item_width;
1105    cvh = vh + 2 * PRELOAD * item->wd->item_height;
1106
1107    alignh = 0;
1108    alignw = 0;
1109
1110    if (item->wd->horizontal)
1111      {
1112         int columns, items_visible = 0, items_row;
1113
1114         if (item->wd->item_height > 0)
1115           items_visible = vh / item->wd->item_height;
1116         if (items_visible < 1)
1117           items_visible = 1;
1118
1119         columns = item->wd->count / items_visible;
1120         if (item->wd->count % items_visible)
1121           columns++;
1122
1123         tcw = item->wd->item_width * columns;
1124         alignw = (vw - tcw) * item->wd->align_x;
1125
1126         items_row = items_visible;
1127         if (items_row > item->wd->count)
1128           items_row = item->wd->count;
1129         tch = items_row * item->wd->item_height;
1130         alignh = (vh - tch) * item->wd->align_y;
1131      }
1132    else
1133      {
1134         int rows, items_visible = 0, items_col;
1135
1136         if (item->wd->item_width > 0)
1137           items_visible = vw / item->wd->item_width;
1138         if (items_visible < 1)
1139           items_visible = 1;
1140
1141         rows = item->wd->count / items_visible;
1142         if (item->wd->count % items_visible)
1143           rows++;
1144
1145         tch = item->wd->item_height * rows;
1146         alignh = (vh - tch) * item->wd->align_y;
1147
1148         items_col = items_visible;
1149         if (items_col > item->wd->count)
1150           items_col = item->wd->count;
1151         tcw = items_col * item->wd->item_width;
1152         alignw = (vw - tcw) * item->wd->align_x;
1153      }
1154
1155    x = cx * item->wd->item_width - item->wd->pan_x + ox + alignw;
1156    if (elm_widget_mirrored_get(item->wd->self))
1157      {  /* Switch items side and componsate for pan_x when in RTL mode */
1158         Evas_Coord ww;
1159         evas_object_geometry_get(item->wd->self, NULL, NULL, &ww, NULL);
1160         x = ww - x - item->wd->item_width - item->wd->pan_x - item->wd->pan_x;
1161      }
1162
1163    y = cy * item->wd->item_height - item->wd->pan_y + oy + alignh;
1164
1165    Eina_Bool was_realized = item->realized;
1166    if (ELM_RECTS_INTERSECT(x, y, item->wd->item_width, item->wd->item_height,
1167                            cvx, cvy, cvw, cvh))
1168      {
1169         _item_realize(item);
1170         if (!was_realized)
1171           evas_object_smart_callback_call(item->wd->self, SIG_REALIZED, item);
1172         if ((item->wd->reorder_mode) && (item->wd->reorder_item))
1173           {
1174              if (item->moving) return;
1175
1176              if (!item->wd->move_effect_enabled)
1177                {
1178                   item->ox = x;
1179                   item->oy = y;
1180                }
1181              if (item->wd->reorder_item == item)
1182                {
1183                   evas_object_move(item->base.view,
1184                                    item->wd->reorder_item_x, item->wd->reorder_item_y);
1185                   evas_object_resize(item->base.view,
1186                                      item->wd->item_width, item->wd->item_height);
1187                   return;
1188                }
1189              else
1190                {
1191                   if (item->wd->move_effect_enabled)
1192                     {
1193                        if ((item->ox != x) || (item->oy != y))
1194                          {
1195                             if (((item->wd->old_pan_x == item->wd->pan_x) && (item->wd->old_pan_y == item->wd->pan_y)) ||
1196                                 ((item->wd->old_pan_x != item->wd->pan_x) && !(item->ox - item->wd->pan_x + item->wd->old_pan_x == x)) ||
1197                                 ((item->wd->old_pan_y != item->wd->pan_y) && !(item->oy - item->wd->pan_y + item->wd->old_pan_y == y)))
1198                               {
1199                                  item->tx = x;
1200                                  item->ty = y;
1201                                  item->rx = item->ox;
1202                                  item->ry = item->oy;
1203                                  item->moving = EINA_TRUE;
1204                                  item->moving_effect_start_time = ecore_loop_time_get();
1205                                  item->item_moving_effect_timer = ecore_animator_add(_reorder_item_moving_effect_timer_cb, item);
1206                                  return;
1207                               }
1208                          }
1209                     }
1210
1211                   if (ELM_RECTS_INTERSECT(item->wd->reorder_item_x, item->wd->reorder_item_y,
1212                                           item->wd->item_width, item->wd->item_height,
1213                                           x+(item->wd->item_width/2), y+(item->wd->item_height/2),
1214                                           1, 1))
1215                     {
1216                        if (item->wd->horizontal)
1217                          {
1218                             if ((item->wd->nmax * item->wd->reorder_item->x + item->wd->reorder_item->y) >
1219                                 (item->wd->nmax * item->x + item->y))
1220                               reorder_item_move_forward = EINA_TRUE;
1221                          }
1222                        else
1223                          {
1224                             if ((item->wd->nmax * item->wd->reorder_item->y + item->wd->reorder_item->x) >
1225                                 (item->wd->nmax * item->y + item->x))
1226                               reorder_item_move_forward = EINA_TRUE;
1227                          }
1228
1229                        item->wd->items = eina_inlist_remove(item->wd->items,
1230                                                             EINA_INLIST_GET(item->wd->reorder_item));
1231                        if (reorder_item_move_forward)
1232                          item->wd->items = eina_inlist_prepend_relative(item->wd->items,
1233                                                                         EINA_INLIST_GET(item->wd->reorder_item),
1234                                                                         EINA_INLIST_GET(item));
1235                        else
1236                          item->wd->items = eina_inlist_append_relative(item->wd->items,
1237                                                                        EINA_INLIST_GET(item->wd->reorder_item),
1238                                                                        EINA_INLIST_GET(item));
1239
1240                        item->wd->reorder_item_changed = EINA_TRUE;
1241                        item->wd->move_effect_enabled = EINA_TRUE;
1242                        if (item->wd->calc_job) ecore_job_del(item->wd->calc_job);
1243                          item->wd->calc_job = ecore_job_add(_calc_job, item->wd);
1244
1245                        return;
1246                     }
1247                }
1248           }
1249         evas_object_move(item->base.view, x, y);
1250         evas_object_resize(item->base.view, item->wd->item_width,
1251                            item->wd->item_height);
1252      }
1253    else
1254      {
1255         _item_unrealize(item);
1256         if (was_realized)
1257           evas_object_smart_callback_call(item->wd->self, SIG_UNREALIZED, item);
1258      }
1259 }
1260
1261 static const char *
1262 _item_label_hook(Elm_Gengrid_Item *it, const char *part)
1263 {
1264    if (!it->gic->func.label_get) return NULL;
1265    return edje_object_part_text_get(it->base.view, part);
1266 }
1267
1268 static Elm_Gengrid_Item *
1269 _item_create(Widget_Data                  *wd,
1270              const Elm_Gengrid_Item_Class *gic,
1271              const void                   *data,
1272              Evas_Smart_Cb                 func,
1273              const void                   *func_data)
1274 {
1275    Elm_Gengrid_Item *item;
1276
1277    item = elm_widget_item_new(wd->self, Elm_Gengrid_Item);
1278    if (!item) return NULL;
1279    wd->count++;
1280    item->wd = wd;
1281    item->gic = gic;
1282    item->base.data = data;
1283    item->func.func = func;
1284    item->func.data = func_data;
1285    item->mouse_cursor = NULL;
1286    elm_widget_item_text_get_hook_set(item, _item_label_hook);
1287    return item;
1288 }
1289
1290 static void
1291 _item_del(Elm_Gengrid_Item *item)
1292 {
1293    elm_widget_item_pre_notify_del(item);
1294    if (item->selected)
1295      item->wd->selected = eina_list_remove(item->wd->selected, item);
1296    if (item->realized) _item_unrealize(item);
1297    if ((!item->delete_me) && (item->gic->func.del))
1298      item->gic->func.del((void *)item->base.data, item->wd->self);
1299    item->delete_me = EINA_TRUE;
1300    item->wd->items = eina_inlist_remove(item->wd->items, EINA_INLIST_GET(item));
1301    if (item->long_timer) ecore_timer_del(item->long_timer);
1302    if (item->tooltip.del_cb)
1303      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
1304    item->wd->walking -= item->walking;
1305    item->wd->count--;
1306    if (item->wd->calc_job) ecore_job_del(item->wd->calc_job);
1307    item->wd->calc_job = ecore_job_add(_calc_job, item->wd);
1308    elm_widget_item_del(item);
1309 }
1310
1311 static void
1312 _item_select(Elm_Gengrid_Item *item)
1313 {
1314    if ((item->wd->no_select) || (item->delete_me)) return;
1315    if (item->selected)
1316      {
1317         if (item->wd->always_select) goto call;
1318         return;
1319      }
1320    item->selected = EINA_TRUE;
1321    item->wd->selected = eina_list_append(item->wd->selected, item);
1322 call:
1323    item->walking++;
1324    item->wd->walking++;
1325    if (item->func.func)
1326      item->func.func((void *)item->func.data, item->wd->self, item);
1327    if (!item->delete_me)
1328      evas_object_smart_callback_call(item->wd->self, SIG_SELECTED, item);
1329    item->walking--;
1330    item->wd->walking--;
1331    item->wd->last_selected_item = item;
1332    if ((item->wd->clear_me) && (!item->wd->walking))
1333      elm_gengrid_clear(item->base.widget);
1334    else
1335      {
1336         if ((!item->walking) && (item->delete_me))
1337           if (!item->relcount) _item_del(item);
1338      }
1339 }
1340
1341 static void
1342 _item_unselect(Elm_Gengrid_Item *item)
1343 {
1344    if ((item->delete_me) || (!item->highlighted)) return;
1345    edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
1346    item->highlighted = EINA_FALSE;
1347    if (item->selected)
1348      {
1349         item->selected = EINA_FALSE;
1350         item->wd->selected = eina_list_remove(item->wd->selected, item);
1351         evas_object_smart_callback_call(item->wd->self, SIG_UNSELECTED, item);
1352      }
1353 }
1354
1355 static void
1356 _calc_job(void *data)
1357 {
1358    Widget_Data *wd = data;
1359    Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
1360    int count;
1361
1362    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &cvw, &cvh);
1363    if ((cvw != 0) || (cvh != 0))
1364      {
1365         if ((wd->horizontal) && (wd->item_height > 0))
1366           nmax = cvh / wd->item_height;
1367         else if (wd->item_width > 0)
1368           nmax = cvw / wd->item_width;
1369
1370         if (nmax < 1)
1371           nmax = 1;
1372
1373         count = wd->count;
1374         if (wd->horizontal)
1375           {
1376              minw = ceil(count / (float)nmax) * wd->item_width;
1377              minh = nmax * wd->item_height;
1378           }
1379         else
1380           {
1381              minw = nmax * wd->item_width;
1382              minh = ceil(count / (float)nmax) * wd->item_height;
1383           }
1384
1385         if ((minw != wd->minw) || (minh != wd->minh))
1386           {
1387              wd->minh = minh;
1388              wd->minw = minw;
1389              evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
1390           }
1391
1392         wd->nmax = nmax;
1393         evas_object_smart_changed(wd->pan_smart);
1394      }
1395    wd->calc_job = NULL;
1396 }
1397
1398 static void
1399 _pan_add(Evas_Object *obj)
1400 {
1401    Pan *sd;
1402    Evas_Object_Smart_Clipped_Data *cd;
1403
1404    _pan_sc.add(obj);
1405    cd = evas_object_smart_data_get(obj);
1406    sd = ELM_NEW(Pan);
1407    if (!sd) return;
1408    sd->__clipped_data = *cd;
1409    free(cd);
1410    evas_object_smart_data_set(obj, sd);
1411 }
1412
1413 static void
1414 _pan_del(Evas_Object *obj)
1415 {
1416    Pan *sd = evas_object_smart_data_get(obj);
1417
1418    if (!sd) return;
1419    _pan_sc.del(obj);
1420 }
1421
1422 static void
1423 _pan_set(Evas_Object *obj,
1424          Evas_Coord   x,
1425          Evas_Coord   y)
1426 {
1427    Pan *sd = evas_object_smart_data_get(obj);
1428    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
1429    sd->wd->pan_x = x;
1430    sd->wd->pan_y = y;
1431    evas_object_smart_changed(obj);
1432 }
1433
1434 static void
1435 _pan_get(Evas_Object *obj,
1436          Evas_Coord  *x,
1437          Evas_Coord  *y)
1438 {
1439    Pan *sd = evas_object_smart_data_get(obj);
1440    if (x) *x = sd->wd->pan_x;
1441    if (y) *y = sd->wd->pan_y;
1442 }
1443
1444 static void
1445 _pan_child_size_get(Evas_Object *obj,
1446                     Evas_Coord  *w,
1447                     Evas_Coord  *h)
1448 {
1449    Pan *sd = evas_object_smart_data_get(obj);
1450    if (w) *w = sd->wd->minw;
1451    if (h) *h = sd->wd->minh;
1452 }
1453
1454 static void
1455 _pan_max_get(Evas_Object *obj,
1456              Evas_Coord  *x,
1457              Evas_Coord  *y)
1458 {
1459    Pan *sd = evas_object_smart_data_get(obj);
1460    Evas_Coord ow, oh;
1461
1462    if (!sd) return;
1463    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1464    if (x)
1465      *x = (ow < sd->wd->minw) ? sd->wd->minw - ow : 0;
1466    if (y)
1467      *y = (oh < sd->wd->minh) ? sd->wd->minh - oh : 0;
1468 }
1469
1470 static void
1471 _pan_min_get(Evas_Object *obj,
1472              Evas_Coord  *x,
1473              Evas_Coord  *y)
1474 {
1475    Pan *sd = evas_object_smart_data_get(obj);
1476    Evas_Coord mx, my;
1477
1478    if (!sd) return;
1479    _pan_max_get(obj, &mx, &my);
1480    if (x)
1481      *x = -mx * sd->wd->align_x;
1482    if (y)
1483      *y = -my * sd->wd->align_y;
1484 }
1485
1486 static void
1487 _pan_resize(Evas_Object *obj,
1488             Evas_Coord   w,
1489             Evas_Coord   h)
1490 {
1491    Pan *sd = evas_object_smart_data_get(obj);
1492    Evas_Coord ow, oh;
1493
1494    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1495    if ((ow == w) && (oh == h)) return;
1496    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1497    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1498 }
1499
1500 static void
1501 _pan_calculate(Evas_Object *obj)
1502 {
1503    Pan *sd = evas_object_smart_data_get(obj);
1504    Evas_Coord cx = 0, cy = 0;
1505    Elm_Gengrid_Item *item;
1506
1507    if (!sd) return;
1508    if (!sd->wd->nmax) return;
1509
1510    sd->wd->reorder_item_changed = EINA_FALSE;
1511
1512    EINA_INLIST_FOREACH(sd->wd->items, item)
1513      {
1514         _item_place(item, cx, cy);
1515         if (sd->wd->reorder_item_changed) return;
1516         if (sd->wd->horizontal)
1517           {
1518              cy = (cy + 1) % sd->wd->nmax;
1519              if (!cy) cx++;
1520           }
1521         else
1522           {
1523              cx = (cx + 1) % sd->wd->nmax;
1524              if (!cx) cy++;
1525           }
1526      }
1527
1528    if ((sd->wd->reorder_mode) && (sd->wd->reorder_item))
1529      {
1530         if (!sd->wd->reorder_item_changed)
1531           {
1532              sd->wd->old_pan_x = sd->wd->pan_x;
1533              sd->wd->old_pan_y = sd->wd->pan_y;
1534           }
1535         sd->wd->move_effect_enabled = EINA_FALSE;
1536      }
1537    evas_object_smart_callback_call(sd->wd->self, SIG_CHANGED, NULL);
1538 }
1539
1540 static void
1541 _pan_move(Evas_Object *obj,
1542           Evas_Coord x __UNUSED__,
1543           Evas_Coord y __UNUSED__)
1544 {
1545    Pan *sd = evas_object_smart_data_get(obj);
1546    if (!sd) return;
1547    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1548    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1549 }
1550
1551 static void
1552 _hold_on(void *data       __UNUSED__,
1553          Evas_Object     *obj,
1554          void *event_info __UNUSED__)
1555 {
1556    Widget_Data *wd = elm_widget_data_get(obj);
1557    if (!wd) return;
1558    elm_smart_scroller_hold_set(wd->scr, 1);
1559 }
1560
1561 static void
1562 _hold_off(void *data       __UNUSED__,
1563           Evas_Object     *obj,
1564           void *event_info __UNUSED__)
1565 {
1566    Widget_Data *wd = elm_widget_data_get(obj);
1567    if (!wd) return;
1568    elm_smart_scroller_hold_set(wd->scr, 0);
1569 }
1570
1571 static void
1572 _freeze_on(void *data       __UNUSED__,
1573            Evas_Object     *obj,
1574            void *event_info __UNUSED__)
1575 {
1576    Widget_Data *wd = elm_widget_data_get(obj);
1577    if (!wd) return;
1578    elm_smart_scroller_freeze_set(wd->scr, 1);
1579 }
1580
1581 static void
1582 _freeze_off(void *data       __UNUSED__,
1583             Evas_Object     *obj,
1584             void *event_info __UNUSED__)
1585 {
1586    Widget_Data *wd = elm_widget_data_get(obj);
1587    if (!wd) return;
1588    elm_smart_scroller_freeze_set(wd->scr, 0);
1589 }
1590
1591 static void
1592 _scr_anim_start(void        *data,
1593                 Evas_Object *obj __UNUSED__,
1594                 void        *event_info __UNUSED__)
1595 {
1596    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
1597 }
1598
1599 static void
1600 _scr_anim_stop(void        *data,
1601                 Evas_Object *obj __UNUSED__,
1602                 void        *event_info __UNUSED__)
1603 {
1604    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
1605 }
1606
1607 static void
1608 _scr_drag_start(void            *data,
1609                 Evas_Object *obj __UNUSED__,
1610                 void *event_info __UNUSED__)
1611 {
1612    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
1613 }
1614
1615 static void
1616 _scr_drag_stop(void            *data,
1617                Evas_Object *obj __UNUSED__,
1618                void *event_info __UNUSED__)
1619 {
1620    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
1621 }
1622
1623 static void
1624 _scr_scroll(void            *data,
1625             Evas_Object *obj __UNUSED__,
1626             void *event_info __UNUSED__)
1627 {
1628    evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
1629 }
1630
1631 static int
1632 _elm_gengrid_item_compare_data(const void *data, const void *data1)
1633 {
1634    const Elm_Gengrid_Item *item = data;
1635    const Elm_Gengrid_Item *item1 = data1;
1636
1637    return _elm_gengrid_item_compare_data_cb(item->base.data, item1->base.data);
1638 }
1639
1640 static int
1641 _elm_gengrid_item_compare(const void *data, const void *data1)
1642 {
1643    Elm_Gengrid_Item *item, *item1;
1644    item = ELM_GENGRID_ITEM_FROM_INLIST(data);
1645    item1 = ELM_GENGRID_ITEM_FROM_INLIST(data1);
1646    return _elm_gengrid_item_compare_cb(item, item1);
1647 }
1648
1649 EAPI Evas_Object *
1650 elm_gengrid_add(Evas_Object *parent)
1651 {
1652    Evas_Object *obj;
1653    Evas *e;
1654    Widget_Data *wd;
1655    static Evas_Smart *smart = NULL;
1656    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1657
1658    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1659
1660    ELM_SET_WIDTYPE(widtype, "gengrid");
1661    elm_widget_type_set(obj, "gengrid");
1662    elm_widget_sub_object_add(parent, obj);
1663    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1664    elm_widget_data_set(obj, wd);
1665    elm_widget_del_hook_set(obj, _del_hook);
1666    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1667    elm_widget_theme_hook_set(obj, _theme_hook);
1668    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1669    elm_widget_can_focus_set(obj, EINA_TRUE);
1670    elm_widget_event_hook_set(obj, _event_hook);
1671
1672    wd->scr = elm_smart_scroller_add(e);
1673    elm_smart_scroller_widget_set(wd->scr, obj);
1674    elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
1675                                        "default");
1676    elm_widget_resize_object_set(obj, wd->scr);
1677
1678    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
1679    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
1680    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
1681    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
1682    evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
1683
1684    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
1685
1686    wd->self = obj;
1687    wd->align_x = 0.5;
1688    wd->align_y = 0.5;
1689    wd->h_bounce = bounce;
1690    wd->v_bounce = bounce;
1691    wd->no_select = EINA_FALSE;
1692
1693    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1694    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1695    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1696    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1697
1698    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1699
1700    if (!smart)
1701      {
1702         static Evas_Smart_Class sc;
1703
1704         evas_object_smart_clipped_smart_set(&_pan_sc);
1705         sc = _pan_sc;
1706         sc.name = "elm_gengrid_pan";
1707         sc.version = EVAS_SMART_CLASS_VERSION;
1708         sc.add = _pan_add;
1709         sc.del = _pan_del;
1710         sc.resize = _pan_resize;
1711         sc.move = _pan_move;
1712         sc.calculate = _pan_calculate;
1713         smart = evas_smart_class_new(&sc);
1714      }
1715    if (smart)
1716      {
1717         wd->pan_smart = evas_object_smart_add(e, smart);
1718         wd->pan = evas_object_smart_data_get(wd->pan_smart);
1719         wd->pan->wd = wd;
1720      }
1721
1722    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
1723                                      _pan_set, _pan_get, _pan_max_get,
1724                                      _pan_min_get, _pan_child_size_get);
1725
1726    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1727    return obj;
1728 }
1729
1730 EAPI void
1731 elm_gengrid_item_size_set(Evas_Object *obj,
1732                           Evas_Coord   w,
1733                           Evas_Coord   h)
1734 {
1735    ELM_CHECK_WIDTYPE(obj, widtype);
1736    Widget_Data *wd = elm_widget_data_get(obj);
1737    if (!wd) return;
1738    if ((wd->item_width == w) && (wd->item_height == h)) return;
1739    wd->item_width = w;
1740    wd->item_height = h;
1741    if (wd->calc_job) ecore_job_del(wd->calc_job);
1742    wd->calc_job = ecore_job_add(_calc_job, wd);
1743 }
1744
1745 EAPI void
1746 elm_gengrid_item_size_get(const Evas_Object *obj,
1747                           Evas_Coord        *w,
1748                           Evas_Coord        *h)
1749 {
1750    ELM_CHECK_WIDTYPE(obj, widtype);
1751    Widget_Data *wd = elm_widget_data_get(obj);
1752    if (!wd) return;
1753    if (w) *w = wd->item_width;
1754    if (h) *h = wd->item_height;
1755 }
1756
1757 EAPI void
1758 elm_gengrid_align_set(Evas_Object *obj,
1759                       double       align_x,
1760                       double       align_y)
1761 {
1762    ELM_CHECK_WIDTYPE(obj, widtype);
1763
1764    Widget_Data *wd = elm_widget_data_get(obj);
1765    double old_h = wd->align_x, old_y = wd->align_y;
1766
1767    if (align_x > 1.0)
1768      align_x = 1.0;
1769    else if (align_x < 0.0)
1770      align_x = 0.0;
1771    wd->align_x = align_x;
1772
1773    if (align_y > 1.0)
1774      align_y = 1.0;
1775    else if (align_y < 0.0)
1776      align_y = 0.0;
1777    wd->align_y = align_y;
1778
1779    if ((old_h != wd->align_x) || (old_y != wd->align_y))
1780      evas_object_smart_calculate(wd->pan_smart);
1781 }
1782
1783 EAPI void
1784 elm_gengrid_align_get(const Evas_Object *obj,
1785                       double            *align_x,
1786                       double            *align_y)
1787 {
1788    ELM_CHECK_WIDTYPE(obj, widtype);
1789    Widget_Data *wd = elm_widget_data_get(obj);
1790    if (align_x) *align_x = wd->align_x;
1791    if (align_y) *align_y = wd->align_y;
1792 }
1793
1794 EAPI Elm_Gengrid_Item *
1795 elm_gengrid_item_append(Evas_Object                  *obj,
1796                         const Elm_Gengrid_Item_Class *gic,
1797                         const void                   *data,
1798                         Evas_Smart_Cb                 func,
1799                         const void                   *func_data)
1800 {
1801    Elm_Gengrid_Item *item;
1802    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1803    Widget_Data *wd = elm_widget_data_get(obj);
1804    if (!wd) return NULL;
1805
1806    item = _item_create(wd, gic, data, func, func_data);
1807    if (!item) return NULL;
1808    wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(item));
1809
1810    if (wd->calc_job) ecore_job_del(wd->calc_job);
1811    wd->calc_job = ecore_job_add(_calc_job, wd);
1812
1813    return item;
1814 }
1815
1816 EAPI Elm_Gengrid_Item *
1817 elm_gengrid_item_prepend(Evas_Object                  *obj,
1818                          const Elm_Gengrid_Item_Class *gic,
1819                          const void                   *data,
1820                          Evas_Smart_Cb                 func,
1821                          const void                   *func_data)
1822 {
1823    Elm_Gengrid_Item *item;
1824    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1825    Widget_Data *wd = elm_widget_data_get(obj);
1826    if (!wd) return NULL;
1827
1828    item = _item_create(wd, gic, data, func, func_data);
1829    if (!item) return NULL;
1830    wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(item));
1831
1832    if (wd->calc_job) ecore_job_del(wd->calc_job);
1833    wd->calc_job = ecore_job_add(_calc_job, wd);
1834
1835    return item;
1836 }
1837
1838 EAPI Elm_Gengrid_Item *
1839 elm_gengrid_item_insert_before(Evas_Object                  *obj,
1840                                const Elm_Gengrid_Item_Class *gic,
1841                                const void                   *data,
1842                                Elm_Gengrid_Item             *relative,
1843                                Evas_Smart_Cb                 func,
1844                                const void                   *func_data)
1845 {
1846    Elm_Gengrid_Item *item;
1847    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1848    EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
1849    Widget_Data *wd = elm_widget_data_get(obj);
1850    if (!wd) return NULL;
1851
1852    item = _item_create(wd, gic, data, func, func_data);
1853    if (!item) return NULL;
1854    wd->items = eina_inlist_prepend_relative
1855       (wd->items, EINA_INLIST_GET(item), EINA_INLIST_GET(relative));
1856
1857    if (wd->calc_job) ecore_job_del(wd->calc_job);
1858    wd->calc_job = ecore_job_add(_calc_job, wd);
1859
1860    return item;
1861 }
1862
1863 EAPI Elm_Gengrid_Item *
1864 elm_gengrid_item_insert_after(Evas_Object                  *obj,
1865                               const Elm_Gengrid_Item_Class *gic,
1866                               const void                   *data,
1867                               Elm_Gengrid_Item             *relative,
1868                               Evas_Smart_Cb                 func,
1869                               const void                   *func_data)
1870 {
1871    Elm_Gengrid_Item *item;
1872    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1873    EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
1874    Widget_Data *wd = elm_widget_data_get(obj);
1875    if (!wd) return NULL;
1876
1877    item = _item_create(wd, gic, data, func, func_data);
1878    if (!item) return NULL;
1879    wd->items = eina_inlist_append_relative
1880       (wd->items, EINA_INLIST_GET(item), EINA_INLIST_GET(relative));
1881
1882    if (wd->calc_job) ecore_job_del(wd->calc_job);
1883    wd->calc_job = ecore_job_add(_calc_job, wd);
1884
1885    return item;
1886 }
1887
1888 EAPI Elm_Gengrid_Item *
1889 elm_gengrid_item_direct_sorted_insert(Evas_Object                  *obj,
1890                                       const Elm_Gengrid_Item_Class *gic,
1891                                       const void                   *data,
1892                                       Eina_Compare_Cb               comp,
1893                                       Evas_Smart_Cb                 func,
1894                                       const void                   *func_data)
1895 {
1896    Elm_Gengrid_Item *item;
1897    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1898    Widget_Data *wd = elm_widget_data_get(obj);
1899    if (!wd) return NULL;
1900
1901    item = _item_create(wd, gic, data, func, func_data);
1902    if (!item) return NULL;
1903
1904    _elm_gengrid_item_compare_cb = comp;
1905    wd->items = eina_inlist_sorted_insert(wd->items, EINA_INLIST_GET(item),
1906                                          _elm_gengrid_item_compare);
1907    if (wd->calc_job) ecore_job_del(wd->calc_job);
1908    wd->calc_job = ecore_job_add(_calc_job, wd);
1909
1910    return item;
1911 }
1912
1913 EAPI Elm_Gengrid_Item *
1914 elm_gengrid_item_sorted_insert(Evas_Object                  *obj,
1915                                const Elm_Gengrid_Item_Class *gic,
1916                                const void                   *data,
1917                                Eina_Compare_Cb               comp,
1918                                Evas_Smart_Cb                 func,
1919                                const void                   *func_data)
1920 {
1921    _elm_gengrid_item_compare_data_cb = comp;
1922
1923    return elm_gengrid_item_direct_sorted_insert(obj, gic, data, _elm_gengrid_item_compare_data, func, func_data);
1924 }
1925
1926 EAPI void
1927 elm_gengrid_item_del(Elm_Gengrid_Item *item)
1928 {
1929    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1930    if ((item->relcount > 0) || (item->walking > 0))
1931      {
1932         item->delete_me = EINA_TRUE;
1933         elm_widget_item_pre_notify_del(item);
1934         if (item->selected)
1935           item->wd->selected = eina_list_remove(item->wd->selected, item);
1936         if (item->gic->func.del)
1937           item->gic->func.del((void *)item->base.data, item->wd->self);
1938         return;
1939      }
1940
1941    _item_del(item);
1942 }
1943
1944 EAPI void
1945 elm_gengrid_horizontal_set(Evas_Object *obj,
1946                            Eina_Bool    setting)
1947 {
1948    ELM_CHECK_WIDTYPE(obj, widtype);
1949    Widget_Data *wd = elm_widget_data_get(obj);
1950    if (!wd) return;
1951    if (setting == wd->horizontal) return;
1952    wd->horizontal = setting;
1953
1954    /* Update the items to conform to the new layout */
1955    if (wd->calc_job) ecore_job_del(wd->calc_job);
1956    wd->calc_job = ecore_job_add(_calc_job, wd);
1957 }
1958
1959 EAPI Eina_Bool
1960 elm_gengrid_horizontal_get(const Evas_Object *obj)
1961 {
1962    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1963    Widget_Data *wd = elm_widget_data_get(obj);
1964    if (!wd) return EINA_FALSE;
1965    return wd->horizontal;
1966 }
1967
1968 EAPI void
1969 elm_gengrid_clear(Evas_Object *obj)
1970 {
1971    ELM_CHECK_WIDTYPE(obj, widtype);
1972    Widget_Data *wd = elm_widget_data_get(obj);
1973    if (!wd) return;
1974
1975    if (wd->calc_job)
1976      {
1977         ecore_job_del(wd->calc_job);
1978         wd->calc_job = NULL;
1979      }
1980
1981    if (wd->walking > 0)
1982      {
1983         Elm_Gengrid_Item *item;
1984         wd->clear_me = 1;
1985         EINA_INLIST_FOREACH(wd->items, item)
1986            item->delete_me = 1;
1987         return;
1988      }
1989    wd->clear_me = 0;
1990    while (wd->items)
1991      {
1992         Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
1993
1994         wd->items = eina_inlist_remove(wd->items, wd->items);
1995         elm_widget_item_pre_notify_del(item);
1996         if (item->realized) _item_unrealize(item);
1997         if (item->gic->func.del)
1998           item->gic->func.del((void *)item->base.data, wd->self);
1999         if (item->long_timer) ecore_timer_del(item->long_timer);
2000         elm_widget_item_del(item);
2001      }
2002
2003    if (wd->selected)
2004      {
2005         eina_list_free(wd->selected);
2006         wd->selected = NULL;
2007      }
2008
2009    wd->pan_x = 0;
2010    wd->pan_y = 0;
2011    wd->minw = 0;
2012    wd->minh = 0;
2013    wd->count = 0;
2014    evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
2015    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2016 }
2017
2018 EAPI const Evas_Object *
2019 elm_gengrid_item_object_get(const Elm_Gengrid_Item *item)
2020 {
2021    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2022    return item->base.view;
2023 }
2024
2025 EAPI void
2026 elm_gengrid_item_update(Elm_Gengrid_Item *item)
2027 {
2028    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2029    if (!item->realized) return;
2030    if (item->want_unrealize) return;
2031    _item_unrealize(item);
2032    _item_realize(item);
2033    _item_place(item, item->x, item->y);
2034 }
2035
2036 EAPI void *
2037 elm_gengrid_item_data_get(const Elm_Gengrid_Item *item)
2038 {
2039    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2040    return elm_widget_item_data_get(item);
2041 }
2042
2043 EAPI void
2044 elm_gengrid_item_data_set(Elm_Gengrid_Item *item,
2045                           const void       *data)
2046 {
2047    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2048    elm_widget_item_data_set(item, data);
2049 }
2050
2051 EAPI const Elm_Gengrid_Item_Class *
2052 elm_gengrid_item_item_class_get(const Elm_Gengrid_Item *item)
2053 {
2054    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2055    if (item->delete_me) return NULL;
2056    return item->gic;
2057 }
2058
2059 EAPI void
2060 elm_gengrid_item_item_class_set(Elm_Gengrid_Item *item,
2061                                 const Elm_Gengrid_Item_Class *gic)
2062 {
2063    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2064    EINA_SAFETY_ON_NULL_RETURN(gic);
2065    if (item->delete_me) return;
2066    item->gic = gic;
2067    elm_gengrid_item_update(item);
2068 }
2069
2070 EAPI void
2071 elm_gengrid_item_pos_get(const Elm_Gengrid_Item *item,
2072                          unsigned int           *x,
2073                          unsigned int           *y)
2074 {
2075    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2076    if (x) *x = item->x;
2077    if (y) *y = item->y;
2078 }
2079
2080 EAPI void
2081 elm_gengrid_multi_select_set(Evas_Object *obj,
2082                              Eina_Bool    multi)
2083 {
2084    ELM_CHECK_WIDTYPE(obj, widtype);
2085    Widget_Data *wd = elm_widget_data_get(obj);
2086    if (!wd) return;
2087    wd->multi = multi;
2088 }
2089
2090 EAPI Eina_Bool
2091 elm_gengrid_multi_select_get(const Evas_Object *obj)
2092 {
2093    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2094    Widget_Data *wd = elm_widget_data_get(obj);
2095    if (!wd) return EINA_FALSE;
2096    return wd->multi;
2097 }
2098
2099 EAPI Elm_Gengrid_Item *
2100 elm_gengrid_selected_item_get(const Evas_Object *obj)
2101 {
2102    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2103    Widget_Data *wd = elm_widget_data_get(obj);
2104    if (!wd) return NULL;
2105    if (wd->selected) return wd->selected->data;
2106    return NULL;
2107 }
2108
2109 EAPI const Eina_List *
2110 elm_gengrid_selected_items_get(const Evas_Object *obj)
2111 {
2112    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2113    Widget_Data *wd = elm_widget_data_get(obj);
2114    if (!wd) return NULL;
2115    return wd->selected;
2116 }
2117
2118 EAPI void
2119 elm_gengrid_item_selected_set(Elm_Gengrid_Item *item,
2120                               Eina_Bool         selected)
2121 {
2122    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2123    Widget_Data *wd = item->wd;
2124    if (!wd) return;
2125    if (item->delete_me) return;
2126    selected = !!selected;
2127    if (item->selected == selected) return;
2128
2129    if (selected)
2130      {
2131         if (!wd->multi)
2132           {
2133              while (wd->selected)
2134                _item_unselect(wd->selected->data);
2135           }
2136         _item_highlight(item);
2137         _item_select(item);
2138      }
2139    else
2140      _item_unselect(item);
2141 }
2142
2143 EAPI Eina_Bool
2144 elm_gengrid_item_selected_get(const Elm_Gengrid_Item *item)
2145 {
2146    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2147    return item->selected;
2148 }
2149
2150 EAPI void
2151 elm_gengrid_item_disabled_set(Elm_Gengrid_Item *item,
2152                               Eina_Bool         disabled)
2153 {
2154    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2155    if (item->disabled == disabled) return;
2156    if (item->delete_me) return;
2157    item->disabled = !!disabled;
2158    if (item->realized)
2159      {
2160         if (item->disabled)
2161           edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm");
2162         else
2163           edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm");
2164      }
2165 }
2166
2167 EAPI Eina_Bool
2168 elm_gengrid_item_disabled_get(const Elm_Gengrid_Item *item)
2169 {
2170    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2171    if (item->delete_me) return EINA_FALSE;
2172    return item->disabled;
2173 }
2174
2175 static Evas_Object *
2176 _elm_gengrid_item_label_create(void        *data,
2177                                Evas_Object *obj __UNUSED__,
2178                                Evas_Object *tooltip,
2179                                void *item   __UNUSED__)
2180 {
2181    Evas_Object *label = elm_label_add(tooltip);
2182    if (!label)
2183      return NULL;
2184    elm_object_style_set(label, "tooltip");
2185    elm_object_text_set(label, data);
2186    return label;
2187 }
2188
2189 static void
2190 _elm_gengrid_item_label_del_cb(void            *data,
2191                                Evas_Object *obj __UNUSED__,
2192                                void *event_info __UNUSED__)
2193 {
2194    eina_stringshare_del(data);
2195 }
2196
2197 EAPI void
2198 elm_gengrid_item_tooltip_text_set(Elm_Gengrid_Item *item,
2199                                   const char       *text)
2200 {
2201    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2202    text = eina_stringshare_add(text);
2203    elm_gengrid_item_tooltip_content_cb_set(item, _elm_gengrid_item_label_create,
2204                                            text,
2205                                            _elm_gengrid_item_label_del_cb);
2206 }
2207
2208 EAPI void
2209 elm_gengrid_item_tooltip_content_cb_set(Elm_Gengrid_Item           *item,
2210                                         Elm_Tooltip_Item_Content_Cb func,
2211                                         const void                 *data,
2212                                         Evas_Smart_Cb               del_cb)
2213 {
2214    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(item, error);
2215
2216    if ((item->tooltip.content_cb == func) && (item->tooltip.data == data))
2217      return;
2218
2219    if (item->tooltip.del_cb)
2220      item->tooltip.del_cb((void *)item->tooltip.data,
2221                           item->base.widget, item);
2222    item->tooltip.content_cb = func;
2223    item->tooltip.data = data;
2224    item->tooltip.del_cb = del_cb;
2225    if (item->base.view)
2226      {
2227         elm_widget_item_tooltip_content_cb_set(item,
2228                                                item->tooltip.content_cb,
2229                                                item->tooltip.data, NULL);
2230         elm_widget_item_tooltip_style_set(item, item->tooltip.style);
2231         elm_widget_item_tooltip_size_restrict_disable(item, item->tooltip.free_size);
2232      }
2233
2234    return;
2235
2236 error:
2237    if (del_cb) del_cb((void *)data, NULL, NULL);
2238 }
2239
2240 EAPI void
2241 elm_gengrid_item_tooltip_unset(Elm_Gengrid_Item *item)
2242 {
2243    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2244    if ((item->base.view) && (item->tooltip.content_cb))
2245      elm_widget_item_tooltip_unset(item);
2246
2247    if (item->tooltip.del_cb)
2248      item->tooltip.del_cb((void *)item->tooltip.data, item->base.widget, item);
2249    item->tooltip.del_cb = NULL;
2250    item->tooltip.content_cb = NULL;
2251    item->tooltip.data = NULL;
2252    item->tooltip.free_size = EINA_FALSE;
2253    if (item->tooltip.style)
2254      elm_gengrid_item_tooltip_style_set(item, NULL);
2255 }
2256
2257 EAPI void
2258 elm_gengrid_item_tooltip_style_set(Elm_Gengrid_Item *item,
2259                                    const char       *style)
2260 {
2261    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2262    eina_stringshare_replace(&item->tooltip.style, style);
2263    if (item->base.view) elm_widget_item_tooltip_style_set(item, style);
2264 }
2265
2266 EAPI const char *
2267 elm_gengrid_item_tooltip_style_get(const Elm_Gengrid_Item *item)
2268 {
2269    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2270    return item->tooltip.style;
2271 }
2272
2273 EAPI Eina_Bool
2274 elm_gengrid_item_tooltip_size_restrict_disable(Elm_Gengrid_Item *item, Eina_Bool disable)
2275 {
2276    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2277    item->tooltip.free_size = disable;
2278    if (item->base.view) return elm_widget_item_tooltip_size_restrict_disable(item, disable);
2279    return EINA_TRUE;
2280 }
2281
2282 EAPI Eina_Bool
2283 elm_gengrid_item_tooltip_size_restrict_disabled_get(const Elm_Gengrid_Item *item)
2284 {
2285    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2286    return item->tooltip.free_size;
2287 }
2288
2289 EAPI void
2290 elm_gengrid_item_cursor_set(Elm_Gengrid_Item *item,
2291                             const char       *cursor)
2292 {
2293    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2294    eina_stringshare_replace(&item->mouse_cursor, cursor);
2295    if (item->base.view) elm_widget_item_cursor_set(item, cursor);
2296 }
2297
2298 EAPI const char *
2299 elm_gengrid_item_cursor_get(const Elm_Gengrid_Item *item)
2300 {
2301    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2302    return elm_widget_item_cursor_get(item);
2303 }
2304
2305 EAPI void
2306 elm_gengrid_item_cursor_unset(Elm_Gengrid_Item *item)
2307 {
2308    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2309    if (!item->mouse_cursor)
2310      return;
2311
2312    if (item->base.view)
2313      elm_widget_item_cursor_unset(item);
2314
2315    eina_stringshare_del(item->mouse_cursor);
2316    item->mouse_cursor = NULL;
2317 }
2318
2319 EAPI void
2320 elm_gengrid_item_cursor_style_set(Elm_Gengrid_Item *item,
2321                                   const char       *style)
2322 {
2323    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2324    elm_widget_item_cursor_style_set(item, style);
2325 }
2326
2327 EAPI const char *
2328 elm_gengrid_item_cursor_style_get(const Elm_Gengrid_Item *item)
2329 {
2330    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2331    return elm_widget_item_cursor_style_get(item);
2332 }
2333
2334 EAPI void
2335 elm_gengrid_item_cursor_engine_only_set(Elm_Gengrid_Item *item,
2336                                         Eina_Bool         engine_only)
2337 {
2338    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2339    elm_widget_item_cursor_engine_only_set(item, engine_only);
2340 }
2341
2342 EAPI Eina_Bool
2343 elm_gengrid_item_cursor_engine_only_get(const Elm_Gengrid_Item *item)
2344 {
2345    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2346    return elm_widget_item_cursor_engine_only_get(item);
2347 }
2348
2349 EAPI void
2350 elm_gengrid_reorder_mode_set(Evas_Object *obj,
2351                              Eina_Bool    reorder_mode)
2352 {
2353    ELM_CHECK_WIDTYPE(obj, widtype);
2354    Widget_Data *wd = elm_widget_data_get(obj);
2355    if (!wd) return;
2356    wd->reorder_mode = reorder_mode;
2357 }
2358
2359 EAPI Eina_Bool
2360 elm_gengrid_reorder_mode_get(const Evas_Object *obj)
2361 {
2362    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2363    Widget_Data *wd = elm_widget_data_get(obj);
2364    if (!wd) return EINA_FALSE;
2365    return wd->reorder_mode;
2366 }
2367
2368 EAPI void
2369 elm_gengrid_always_select_mode_set(Evas_Object *obj,
2370                                    Eina_Bool    always_select)
2371 {
2372    ELM_CHECK_WIDTYPE(obj, widtype);
2373    Widget_Data *wd = elm_widget_data_get(obj);
2374    if (!wd) return;
2375    wd->always_select = always_select;
2376 }
2377
2378 EAPI Eina_Bool
2379 elm_gengrid_always_select_mode_get(const Evas_Object *obj)
2380 {
2381    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2382    Widget_Data *wd = elm_widget_data_get(obj);
2383    if (!wd) return EINA_FALSE;
2384    return wd->always_select;
2385 }
2386
2387 EAPI void
2388 elm_gengrid_no_select_mode_set(Evas_Object *obj,
2389                                Eina_Bool    no_select)
2390 {
2391    ELM_CHECK_WIDTYPE(obj, widtype);
2392    Widget_Data *wd = elm_widget_data_get(obj);
2393    if (!wd) return;
2394    wd->no_select = no_select;
2395 }
2396
2397 EAPI Eina_Bool
2398 elm_gengrid_no_select_mode_get(const Evas_Object *obj)
2399 {
2400    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2401    Widget_Data *wd = elm_widget_data_get(obj);
2402    if (!wd) return EINA_FALSE;
2403    return wd->no_select;
2404 }
2405
2406 EAPI void
2407 elm_gengrid_bounce_set(Evas_Object *obj,
2408                        Eina_Bool    h_bounce,
2409                        Eina_Bool    v_bounce)
2410 {
2411    ELM_CHECK_WIDTYPE(obj, widtype);
2412    Widget_Data *wd = elm_widget_data_get(obj);
2413    if (!wd) return;
2414    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
2415    wd->h_bounce = h_bounce;
2416    wd->v_bounce = v_bounce;
2417 }
2418
2419 EAPI void
2420 elm_gengrid_bounce_get(const Evas_Object *obj,
2421                        Eina_Bool         *h_bounce,
2422                        Eina_Bool         *v_bounce)
2423 {
2424    ELM_CHECK_WIDTYPE(obj, widtype);
2425    Widget_Data *wd = elm_widget_data_get(obj);
2426    if (!wd) return;
2427    if (h_bounce) *h_bounce = wd->h_bounce;
2428    if (v_bounce) *v_bounce = wd->v_bounce;
2429 }
2430
2431 EAPI void
2432 elm_gengrid_page_relative_set(Evas_Object *obj,
2433                               double       h_pagerel,
2434                               double       v_pagerel)
2435 {
2436    Evas_Coord pagesize_h;
2437    Evas_Coord pagesize_v;
2438
2439    ELM_CHECK_WIDTYPE(obj, widtype);
2440    Widget_Data *wd = elm_widget_data_get(obj);
2441    if (!wd) return;
2442
2443    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
2444    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
2445                                  pagesize_v);
2446 }
2447
2448 EAPI void
2449 elm_gengrid_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel)
2450 {
2451    ELM_CHECK_WIDTYPE(obj, widtype);
2452    Widget_Data *wd = elm_widget_data_get(obj);
2453    if (!wd) return;
2454
2455    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
2456 }
2457
2458 EAPI void
2459 elm_gengrid_page_size_set(Evas_Object *obj,
2460                           Evas_Coord   h_pagesize,
2461                           Evas_Coord   v_pagesize)
2462 {
2463    double pagerel_h;
2464    double pagerel_v;
2465
2466    ELM_CHECK_WIDTYPE(obj, widtype);
2467    Widget_Data *wd = elm_widget_data_get(obj);
2468    if (!wd) return;
2469    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
2470    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
2471                                  v_pagesize);
2472 }
2473
2474 EAPI Elm_Gengrid_Item *
2475 elm_gengrid_first_item_get(const Evas_Object *obj)
2476 {
2477    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2478    Widget_Data *wd = elm_widget_data_get(obj);
2479    if (!wd) return NULL;
2480    if (!wd->items) return NULL;
2481    Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items);
2482    while ((item) && (item->delete_me))
2483      item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
2484    return item;
2485 }
2486
2487 EAPI Elm_Gengrid_Item *
2488 elm_gengrid_last_item_get(const Evas_Object *obj)
2489 {
2490    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2491    Widget_Data *wd = elm_widget_data_get(obj);
2492    if (!wd) return NULL;
2493    if (!wd->items) return NULL;
2494    Elm_Gengrid_Item *item = ELM_GENGRID_ITEM_FROM_INLIST(wd->items->last);
2495    while ((item) && (item->delete_me))
2496      item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
2497    return item;
2498 }
2499
2500 EAPI Elm_Gengrid_Item *
2501 elm_gengrid_item_next_get(const Elm_Gengrid_Item *item)
2502 {
2503    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2504    while (item)
2505      {
2506         item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
2507         if ((item) && (!item->delete_me)) break;
2508      }
2509    return (Elm_Gengrid_Item *)item;
2510 }
2511
2512 EAPI Elm_Gengrid_Item *
2513 elm_gengrid_item_prev_get(const Elm_Gengrid_Item *item)
2514 {
2515    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2516    while (item)
2517      {
2518         item = ELM_GENGRID_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
2519         if ((item) && (!item->delete_me)) break;
2520      }
2521    return (Elm_Gengrid_Item *)item;
2522 }
2523
2524 EAPI Evas_Object *
2525 elm_gengrid_item_gengrid_get(const Elm_Gengrid_Item *item)
2526 {
2527    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2528    return item->base.widget;
2529 }
2530
2531 EAPI void
2532 elm_gengrid_item_show(Elm_Gengrid_Item *item)
2533 {
2534    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2535    Widget_Data *wd = elm_widget_data_get(item->wd->self);
2536    Evas_Coord minx = 0, miny = 0;
2537
2538    if (!wd) return;
2539    if ((!item) || (item->delete_me)) return;
2540    _pan_min_get(wd->pan_smart, &minx, &miny);
2541
2542    elm_smart_scroller_child_region_show(item->wd->scr,
2543                                         item->x * wd->item_width + minx,
2544                                         item->y * wd->item_height + miny,
2545                                         item->wd->item_width,
2546                                         item->wd->item_height);
2547 }
2548
2549 EAPI void
2550 elm_gengrid_item_bring_in(Elm_Gengrid_Item *item)
2551 {
2552    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2553    if (item->delete_me) return;
2554
2555    Evas_Coord minx = 0, miny = 0;
2556    Widget_Data *wd = elm_widget_data_get(item->wd->self);
2557    if (!wd) return;
2558    _pan_min_get(wd->pan_smart, &minx, &miny);
2559
2560    elm_smart_scroller_region_bring_in(item->wd->scr,
2561                                       item->x * wd->item_width + minx,
2562                                       item->y * wd->item_height + miny,
2563                                       item->wd->item_width,
2564                                       item->wd->item_height);
2565 }