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