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