deprecate elm_genlist_item_selected_set and elm_gengrid_item_selected_set: use elm_ge...
[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    Ecore_Cb          del_cb, calc_cb, sizing_cb;
63    Ecore_Cb          clear_cb;
64    ////////////////////////////////////
65    double            align_x, align_y;
66
67    Evas_Coord        old_pan_x, old_pan_y;
68    Evas_Coord        reorder_item_x, reorder_item_y;
69    unsigned int      nmax;
70    long              items_lost;
71
72    Eina_Bool         horizontal : 1;
73    Eina_Bool         longpressed : 1;
74    Eina_Bool         h_bounce : 1;
75    Eina_Bool         v_bounce : 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_gengrid_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_gengrid_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_gengrid_item_prev_get(wd->last_selected_item);
365    if (!prev) return EINA_TRUE;
366    if (elm_gengrid_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_gengrid_item_next_get(wd->last_selected_item);
387    if (!next) return EINA_TRUE;
388    if (elm_gengrid_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_gengrid_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_gengrid_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_gengrid_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_gengrid_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_gengrid_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_gengrid_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), l->data);
952              if (s)
953                {
954                   edje_object_part_text_set(VIEW(it), l->data, s);
955                   free(s);
956                }
957           }
958      }
959
960    if (it->itc->func.icon_get)
961      {
962         const Eina_List *l;
963         const char *key;
964
965         it->icons =
966            elm_widget_stringlist_get(edje_object_data_get(VIEW(it),
967                                                           "icons"));
968         EINA_LIST_FOREACH(it->icons, l, key)
969           {
970              Evas_Object *ic = it->itc->func.icon_get
971                 ((void *)it->base.data, WIDGET(it), l->data);
972              if (ic)
973                {
974                   it->icon_objs = eina_list_append(it->icon_objs, ic);
975                   edje_object_part_swallow(VIEW(it), key, ic);
976                   evas_object_show(ic);
977                   elm_widget_sub_object_add(WIDGET(it), ic);
978                }
979           }
980      }
981
982    if (it->itc->func.state_get)
983      {
984         const Eina_List *l;
985         const char *key;
986
987         it->states =
988            elm_widget_stringlist_get(edje_object_data_get(VIEW(it),
989                                                           "states"));
990         EINA_LIST_FOREACH(it->states, l, key)
991           {
992              Eina_Bool on = it->itc->func.state_get
993                 ((void *)it->base.data, WIDGET(it), l->data);
994              if (on)
995                {
996                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
997                   edje_object_signal_emit(VIEW(it), buf, "elm");
998                }
999           }
1000      }
1001
1002    if (it->group)
1003      {
1004         if ((!it->wd->group_item_width) && (!it->wd->group_item_height))
1005           {
1006              edje_object_size_min_restricted_calc(VIEW(it),
1007                                                   &it->wd->group_item_width,
1008                                                   &it->wd->group_item_height,
1009                                                   it->wd->group_item_width,
1010                                                   it->wd->group_item_height);
1011           }
1012      }
1013    else
1014      {
1015         if ((!it->wd->item_width) && (!it->wd->item_height))
1016           {
1017              edje_object_size_min_restricted_calc(VIEW(it),
1018                                                   &it->wd->item_width,
1019                                                   &it->wd->item_height,
1020                                                   it->wd->item_width,
1021                                                   it->wd->item_height);
1022              elm_coords_finger_size_adjust(1, &it->wd->item_width,
1023                                            1, &it->wd->item_height);
1024           }
1025
1026         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1027                                        _mouse_down, it);
1028         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1029                                        _mouse_up, it);
1030         evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1031                                        _mouse_move, it);
1032
1033         if (it->selected)
1034           edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
1035         if (it->disabled)
1036           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
1037      }
1038    evas_object_show(VIEW(it));
1039
1040    if (it->tooltip.content_cb)
1041      {
1042         elm_widget_item_tooltip_content_cb_set(it,
1043                                                it->tooltip.content_cb,
1044                                                it->tooltip.data, NULL);
1045         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
1046         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
1047      }
1048
1049    if (it->mouse_cursor)
1050      elm_widget_item_cursor_set(it, it->mouse_cursor);
1051
1052    it->realized = EINA_TRUE;
1053    it->want_unrealize = EINA_FALSE;
1054 }
1055
1056 static void
1057 _item_unrealize_cb(Elm_Gen_Item *it)
1058 {
1059    evas_object_del(VIEW(it));
1060    VIEW(it) = NULL;
1061    evas_object_del(it->spacer);
1062    it->spacer = NULL;
1063 }
1064
1065 static Eina_Bool
1066 _reorder_item_moving_effect_timer_cb(void *data)
1067 {
1068    Elm_Gen_Item *it = data;
1069    double time, t;
1070    Evas_Coord dx, dy;
1071
1072    time = REORDER_EFFECT_TIME;
1073    t = ((0.0 > (t = ecore_loop_time_get()-it->item->moving_effect_start_time)) ? 0.0 : t);
1074    dx = ((it->item->tx - it->item->ox) / 10) * _elm_config->scale;
1075    dy = ((it->item->ty - it->item->oy) / 10) * _elm_config->scale;
1076
1077    if (t <= time)
1078      {
1079         it->item->rx += (1 * sin((t / time) * (M_PI / 2)) * dx);
1080         it->item->ry += (1 * sin((t / time) * (M_PI / 2)) * dy);
1081      }
1082    else
1083      {
1084         it->item->rx += dx;
1085         it->item->ry += dy;
1086      }
1087
1088    if ((((dx > 0) && (it->item->rx >= it->item->tx)) || ((dx <= 0) && (it->item->rx <= it->item->tx))) &&
1089        (((dy > 0) && (it->item->ry >= it->item->ty)) || ((dy <= 0) && (it->item->ry <= it->item->ty))))
1090      {
1091         evas_object_move(VIEW(it), it->item->tx, it->item->ty);
1092         if (it->group)
1093           {
1094              Evas_Coord vw, vh;
1095              evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &vw, &vh);
1096              if (it->wd->horizontal)
1097                evas_object_resize(VIEW(it), it->wd->group_item_width, vh);
1098              else
1099                evas_object_resize(VIEW(it), vw, it->wd->group_item_height);
1100           }
1101         else
1102           evas_object_resize(VIEW(it), it->wd->item_width, it->wd->item_height);
1103         it->item->moving = EINA_FALSE;
1104         it->item->item_moving_effect_timer = NULL;
1105         return ECORE_CALLBACK_CANCEL;
1106      }
1107
1108    evas_object_move(VIEW(it), it->item->rx, it->item->ry);
1109    if (it->group)
1110      {
1111         Evas_Coord vw, vh;
1112         evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &vw, &vh);
1113         if (it->wd->horizontal)
1114           evas_object_resize(VIEW(it), it->wd->group_item_width, vh);
1115         else
1116           evas_object_resize(VIEW(it), vw, it->wd->group_item_height);
1117      }
1118    else
1119      evas_object_resize(VIEW(it), it->wd->item_width, it->wd->item_height);
1120
1121    return ECORE_CALLBACK_RENEW;
1122 }
1123
1124 static void
1125 _group_item_place(Pan *sd)
1126 {
1127    Evas_Coord iw, ih, vw, vh;
1128    Eina_List *l;
1129    Eina_Bool was_realized;
1130    Elm_Gen_Item *it;
1131    evas_object_geometry_get(sd->wd->pan_smart, NULL, NULL, &vw, &vh);
1132    if (sd->wd->horizontal)
1133      {
1134         iw = sd->wd->group_item_width;
1135         ih = vh;
1136      }
1137    else
1138      {
1139         iw = vw;
1140         ih = sd->wd->group_item_height;
1141      }
1142    EINA_LIST_FOREACH(sd->wd->group_items, l, it)
1143      {
1144         was_realized = it->realized;
1145         if (it->item->group_realized)
1146           {
1147              _item_realize(it);
1148              if (!was_realized)
1149                evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1150              evas_object_move(VIEW(it), it->item->gx, it->item->gy);
1151              evas_object_resize(VIEW(it), iw, ih);
1152              evas_object_raise(VIEW(it));
1153           }
1154         else
1155           elm_gen_item_unrealize(it, EINA_FALSE);
1156      }
1157 }
1158
1159
1160 static void
1161 _item_place(Elm_Gen_Item *it,
1162             Evas_Coord        cx,
1163             Evas_Coord        cy)
1164 {
1165    Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh, iw, ih, ww;
1166    Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
1167    Eina_Bool reorder_item_move_forward = EINA_FALSE;
1168    long items_count;
1169    it->x = cx;
1170    it->y = cy;
1171    evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &vw, &vh);
1172
1173    /* Preload rows/columns at each side of the Gengrid */
1174    cvx = ox - PRELOAD * it->wd->item_width;
1175    cvy = oy - PRELOAD * it->wd->item_height;
1176    cvw = vw + 2 * PRELOAD * it->wd->item_width;
1177    cvh = vh + 2 * PRELOAD * it->wd->item_height;
1178
1179    alignh = 0;
1180    alignw = 0;
1181
1182    items_count = it->wd->count - eina_list_count(it->wd->group_items) + it->wd->items_lost;
1183    if (it->wd->horizontal)
1184      {
1185         int columns, items_visible = 0, items_row;
1186
1187         if (it->wd->item_height > 0)
1188           items_visible = vh / it->wd->item_height;
1189         if (items_visible < 1)
1190           items_visible = 1;
1191
1192         columns = items_count / items_visible;
1193         if (items_count % items_visible)
1194           columns++;
1195
1196         tcw = (it->wd->item_width * columns) + (it->wd->group_item_width * eina_list_count(it->wd->group_items));
1197         alignw = (vw - tcw) * it->wd->align_x;
1198
1199         items_row = items_visible;
1200         if (items_row > it->wd->count)
1201           items_row = it->wd->count;
1202         tch = items_row * it->wd->item_height;
1203         alignh = (vh - tch) * it->wd->align_y;
1204      }
1205    else
1206      {
1207         int rows, items_visible = 0, items_col;
1208
1209         if (it->wd->item_width > 0)
1210           items_visible = vw / it->wd->item_width;
1211         if (items_visible < 1)
1212           items_visible = 1;
1213
1214         rows = items_count / items_visible;
1215         if (items_count % items_visible)
1216           rows++;
1217
1218         tch = (it->wd->item_height * rows) + (it->wd->group_item_height * eina_list_count(it->wd->group_items));
1219         alignh = (vh - tch) * it->wd->align_y;
1220
1221         items_col = items_visible;
1222         if (items_col > it->wd->count)
1223           items_col = it->wd->count;
1224         tcw = items_col * it->wd->item_width;
1225         alignw = (vw - tcw) * it->wd->align_x;
1226      }
1227
1228    if (it->group)
1229      {
1230         if (it->wd->horizontal)
1231           {
1232              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;
1233              y = 0;
1234              iw = it->wd->group_item_width;
1235              ih = vh;
1236           }
1237         else
1238           {
1239              x = 0;
1240              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;
1241              iw = vw;
1242              ih = it->wd->group_item_height;
1243           }
1244         it->item->gx = x;
1245         it->item->gy = y;
1246      }
1247    else
1248      {
1249         if (it->wd->horizontal)
1250           {
1251              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;
1252              y = (cy * it->wd->item_height) - it->wd->pan_y + oy + alignh;
1253           }
1254         else
1255           {
1256              x = (cx * it->wd->item_width) - it->wd->pan_x + ox + alignw;
1257              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;
1258           }
1259         if (elm_widget_mirrored_get(WIDGET(it)))
1260           {  /* Switch items side and componsate for pan_x when in RTL mode */
1261              evas_object_geometry_get(WIDGET(it), NULL, NULL, &ww, NULL);
1262              x = ww - x - it->wd->item_width - it->wd->pan_x - it->wd->pan_x;
1263           }
1264         iw = it->wd->item_width;
1265         ih = it->wd->item_height;
1266      }
1267
1268    Eina_Bool was_realized = it->realized;
1269    if (ELM_RECTS_INTERSECT(x, y, iw, ih, cvx, cvy, cvw, cvh))
1270      {
1271         _item_realize(it);
1272         if (!was_realized)
1273           evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1274         if (it->parent)
1275           {
1276              if (it->wd->horizontal)
1277                {
1278                   if (it->parent->item->gx < 0)
1279                     {
1280                        it->parent->item->gx = x + it->wd->item_width - it->wd->group_item_width;
1281                        if (it->parent->item->gx > 0)
1282                          it->parent->item->gx = 0;
1283                     }
1284                }
1285              else
1286                {
1287                   if (it->parent->item->gy < 0)
1288                     {
1289                        it->parent->item->gy = y + it->wd->item_height - it->wd->group_item_height;
1290                        if (it->parent->item->gy > 0)
1291                          it->parent->item->gy = 0;
1292                     }
1293                   it->parent->item->group_realized = EINA_TRUE;
1294                }
1295           }
1296         if (it->wd->reorder_mode)
1297           {
1298              if (it->wd->reorder_it)
1299                {
1300                   if (it->item->moving) return;
1301
1302                   if (!it->wd->move_effect_enabled)
1303                     {
1304                        it->item->ox = x;
1305                        it->item->oy = y;
1306                     }
1307                   if (it->wd->reorder_it == it)
1308                     {
1309                        evas_object_move(VIEW(it),
1310                                         it->wd->reorder_item_x, it->wd->reorder_item_y);
1311                        evas_object_resize(VIEW(it), iw, ih);
1312                        return;
1313                     }
1314                   else
1315                     {
1316                        if (it->wd->move_effect_enabled)
1317                          {
1318                             if ((it->item->ox != x) || (it->item->oy != y))
1319                               {
1320                                  if (((it->wd->old_pan_x == it->wd->pan_x) && (it->wd->old_pan_y == it->wd->pan_y)) ||
1321                                      ((it->wd->old_pan_x != it->wd->pan_x) && !(it->item->ox - it->wd->pan_x + it->wd->old_pan_x == x)) ||
1322                                      ((it->wd->old_pan_y != it->wd->pan_y) && !(it->item->oy - it->wd->pan_y + it->wd->old_pan_y == y)))
1323                                    {
1324                                       it->item->tx = x;
1325                                       it->item->ty = y;
1326                                       it->item->rx = it->item->ox;
1327                                       it->item->ry = it->item->oy;
1328                                       it->item->moving = EINA_TRUE;
1329                                       it->item->moving_effect_start_time = ecore_loop_time_get();
1330                                       it->item->item_moving_effect_timer = ecore_animator_add(_reorder_item_moving_effect_timer_cb, it);
1331                                       return;
1332                                    }
1333                               }
1334                          }
1335
1336                        /* need fix here */
1337                        Evas_Coord nx, ny, nw, nh;
1338                        if (it->group)
1339                          {
1340                             if (it->wd->horizontal)
1341                               {
1342                                  nx = x + (it->wd->group_item_width / 2);
1343                                  ny = y;
1344                                  nw = 1;
1345                                  nh = vh;
1346                               }
1347                             else
1348                               {
1349                                  nx = x;
1350                                  ny = y + (it->wd->group_item_height / 2);
1351                                  nw = vw;
1352                                  nh = 1;
1353                               }
1354                          }
1355                        else
1356                          {
1357                             nx = x + (it->wd->item_width / 2);
1358                             ny = y + (it->wd->item_height / 2);
1359                             nw = 1;
1360                             nh = 1;
1361                          }
1362
1363                        if ( ELM_RECTS_INTERSECT(it->wd->reorder_item_x, it->wd->reorder_item_y,
1364                                                 it->wd->item_width, it->wd->item_height,
1365                                                 nx, ny, nw, nh))
1366                          {
1367                             if (it->wd->horizontal)
1368                               {
1369                                  if ((it->wd->nmax * it->wd->reorder_it->x + it->wd->reorder_it->y) >
1370                                      (it->wd->nmax * it->x + it->y))
1371                                    reorder_item_move_forward = EINA_TRUE;
1372                               }
1373                             else
1374                               {
1375                                  if ((it->wd->nmax * it->wd->reorder_it->y + it->wd->reorder_it->x) >
1376                                      (it->wd->nmax * it->y + it->x))
1377                                    reorder_item_move_forward = EINA_TRUE;
1378                               }
1379
1380                             it->wd->items = eina_inlist_remove(it->wd->items,
1381                                                                  EINA_INLIST_GET(it->wd->reorder_it));
1382                             if (reorder_item_move_forward)
1383                               it->wd->items = eina_inlist_prepend_relative(it->wd->items,
1384                                                                              EINA_INLIST_GET(it->wd->reorder_it),
1385                                                                              EINA_INLIST_GET(it));
1386                             else
1387                               it->wd->items = eina_inlist_append_relative(it->wd->items,
1388                                                                             EINA_INLIST_GET(it->wd->reorder_it),
1389                                                                             EINA_INLIST_GET(it));
1390
1391                             it->wd->reorder_item_changed = EINA_TRUE;
1392                             it->wd->move_effect_enabled = EINA_TRUE;
1393                             if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1394                               it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1395
1396                             return;
1397                          }
1398                     }
1399                }
1400              else if (it->item->item_moving_effect_timer)
1401                {
1402                   ecore_animator_del(it->item->item_moving_effect_timer);
1403                   it->item->item_moving_effect_timer = NULL;
1404                   it->item->moving = EINA_FALSE;
1405                }
1406           }
1407         if (!it->group)
1408           {
1409              evas_object_move(VIEW(it), x, y);
1410              evas_object_resize(VIEW(it), iw, ih);
1411           }
1412         else
1413           it->item->group_realized = EINA_TRUE;
1414      }
1415    else
1416      {
1417         if (!it->group)
1418           elm_gen_item_unrealize(it, EINA_FALSE);
1419         else
1420           it->item->group_realized = EINA_FALSE;
1421      }
1422 }
1423
1424 static void
1425 _item_del(Elm_Gen_Item *it)
1426 {
1427    Evas_Object *obj = WIDGET(it);
1428
1429    evas_event_freeze(evas_object_evas_get(obj));
1430    it->wd->selected = eina_list_remove(it->wd->selected, it);
1431    if (it->realized) elm_gen_item_unrealize(it, EINA_FALSE);
1432    it->wd->count--;
1433    elm_gen_item_del_serious(it);
1434    evas_event_thaw(evas_object_evas_get(obj));
1435    evas_event_thaw_eval(evas_object_evas_get(obj));
1436 }
1437
1438 static void
1439 _item_unselect(Elm_Gen_Item *it)
1440 {
1441    if ((it->delete_me) || (!it->highlighted)) return;
1442    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
1443    it->highlighted = EINA_FALSE;
1444    if (it->selected)
1445      {
1446         it->selected = EINA_FALSE;
1447         it->wd->selected = eina_list_remove(it->wd->selected, it);
1448         evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
1449      }
1450 }
1451
1452 static void
1453 _calc_job(void *data)
1454 {
1455    Widget_Data *wd = data;
1456    Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
1457    Elm_Gen_Item *it, *group_item = NULL;
1458    int count_group = 0;
1459    long count = 0;
1460    wd->items_lost = 0;
1461
1462    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &cvw, &cvh);
1463    if ((cvw != 0) || (cvh != 0))
1464      {
1465         if ((wd->horizontal) && (wd->item_height > 0))
1466           nmax = cvh / wd->item_height;
1467         else if (wd->item_width > 0)
1468           nmax = cvw / wd->item_width;
1469
1470         if (nmax < 1)
1471           nmax = 1;
1472
1473         EINA_INLIST_FOREACH(wd->items, it)
1474           {
1475              if (it->item->prev_group != count_group)
1476                it->item->prev_group = count_group;
1477              if (it->group)
1478                {
1479                   count = count % nmax;
1480                   if (count)
1481                     wd->items_lost += nmax - count;
1482                   //printf("%d items and I lost %d\n", count, wd->items_lost);
1483                   count_group++;
1484                   if (count) count = 0;
1485                   group_item = it;
1486                }
1487              else
1488                {
1489                   if (it->parent != group_item)
1490                     it->parent = group_item;
1491                   count++;
1492                }
1493           }
1494         count = wd->count + wd->items_lost - count_group;
1495         if (wd->horizontal)
1496           {
1497              minw = (ceil(count / (float)nmax) * wd->item_width) + (count_group * wd->group_item_width);
1498              minh = nmax * wd->item_height;
1499           }
1500         else
1501           {
1502              minw = nmax * wd->item_width;
1503              minh = (ceil(count / (float)nmax) * wd->item_height) + (count_group * wd->group_item_height);
1504           }
1505
1506         if ((minw != wd->minw) || (minh != wd->minh))
1507           {
1508              wd->minh = minh;
1509              wd->minw = minw;
1510              evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
1511           }
1512
1513         wd->nmax = nmax;
1514         evas_object_smart_changed(wd->pan_smart);
1515      }
1516    wd->calc_job = NULL;
1517 }
1518
1519 static void
1520 _pan_add(Evas_Object *obj)
1521 {
1522    Pan *sd;
1523    Evas_Object_Smart_Clipped_Data *cd;
1524
1525    _pan_sc.add(obj);
1526    cd = evas_object_smart_data_get(obj);
1527    sd = ELM_NEW(Pan);
1528    if (!sd) return;
1529    sd->__clipped_data = *cd;
1530    free(cd);
1531    evas_object_smart_data_set(obj, sd);
1532 }
1533
1534 static void
1535 _pan_del(Evas_Object *obj)
1536 {
1537    Pan *sd = evas_object_smart_data_get(obj);
1538
1539    if (!sd) return;
1540    _pan_sc.del(obj);
1541 }
1542
1543 static void
1544 _pan_set(Evas_Object *obj,
1545          Evas_Coord   x,
1546          Evas_Coord   y)
1547 {
1548    Pan *sd = evas_object_smart_data_get(obj);
1549    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
1550    sd->wd->pan_x = x;
1551    sd->wd->pan_y = y;
1552    evas_object_smart_changed(obj);
1553 }
1554
1555 static void
1556 _pan_get(Evas_Object *obj,
1557          Evas_Coord  *x,
1558          Evas_Coord  *y)
1559 {
1560    Pan *sd = evas_object_smart_data_get(obj);
1561    if (x) *x = sd->wd->pan_x;
1562    if (y) *y = sd->wd->pan_y;
1563 }
1564
1565 static void
1566 _pan_child_size_get(Evas_Object *obj,
1567                     Evas_Coord  *w,
1568                     Evas_Coord  *h)
1569 {
1570    Pan *sd = evas_object_smart_data_get(obj);
1571    if (w) *w = sd->wd->minw;
1572    if (h) *h = sd->wd->minh;
1573 }
1574
1575 static void
1576 _pan_max_get(Evas_Object *obj,
1577              Evas_Coord  *x,
1578              Evas_Coord  *y)
1579 {
1580    Pan *sd = evas_object_smart_data_get(obj);
1581    Evas_Coord ow, oh;
1582
1583    if (!sd) return;
1584    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1585    if (x)
1586      *x = (ow < sd->wd->minw) ? sd->wd->minw - ow : 0;
1587    if (y)
1588      *y = (oh < sd->wd->minh) ? sd->wd->minh - oh : 0;
1589 }
1590
1591 static void
1592 _pan_min_get(Evas_Object *obj,
1593              Evas_Coord  *x,
1594              Evas_Coord  *y)
1595 {
1596    Pan *sd = evas_object_smart_data_get(obj);
1597    Evas_Coord mx, my;
1598
1599    if (!sd) return;
1600    _pan_max_get(obj, &mx, &my);
1601    if (x)
1602      *x = -mx * sd->wd->align_x;
1603    if (y)
1604      *y = -my * sd->wd->align_y;
1605 }
1606
1607 static void
1608 _pan_resize(Evas_Object *obj,
1609             Evas_Coord   w,
1610             Evas_Coord   h)
1611 {
1612    Pan *sd = evas_object_smart_data_get(obj);
1613    Evas_Coord ow, oh;
1614
1615    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1616    if ((ow == w) && (oh == h)) return;
1617    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1618    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1619 }
1620
1621 static void
1622 _pan_calculate(Evas_Object *obj)
1623 {
1624    Pan *sd = evas_object_smart_data_get(obj);
1625    Evas_Coord cx = 0, cy = 0;
1626    Elm_Gen_Item *it;
1627
1628    if (!sd) return;
1629    if (!sd->wd->nmax) return;
1630
1631    sd->wd->reorder_item_changed = EINA_FALSE;
1632
1633    EINA_INLIST_FOREACH(sd->wd->items, it)
1634      {
1635         if (it->group)
1636           {
1637              if (sd->wd->horizontal)
1638                {
1639                   if (cy)
1640                     {
1641                        cx++;
1642                        cy = 0;
1643                     }
1644                }
1645              else
1646                {
1647                   if (cx)
1648                     {
1649                        cx = 0;
1650                        cy++;
1651                     }
1652                }
1653           }
1654         _item_place(it, cx, cy);
1655         if (sd->wd->reorder_item_changed) return;
1656         if (it->group)
1657           {
1658              if (sd->wd->horizontal)
1659                {
1660                   cx++;
1661                   cy = 0;
1662                }
1663              else
1664                {
1665                   cx = 0;
1666                   cy++;
1667                }
1668           }
1669         else
1670           {
1671              if (sd->wd->horizontal)
1672                {
1673                   cy = (cy + 1) % sd->wd->nmax;
1674                   if (!cy) cx++;
1675                }
1676              else
1677                {
1678                   cx = (cx + 1) % sd->wd->nmax;
1679                   if (!cx) cy++;
1680                }
1681           }
1682      }
1683    _group_item_place(sd);
1684
1685
1686    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
1687      {
1688         if (!sd->wd->reorder_item_changed)
1689           {
1690              sd->wd->old_pan_x = sd->wd->pan_x;
1691              sd->wd->old_pan_y = sd->wd->pan_y;
1692           }
1693         sd->wd->move_effect_enabled = EINA_FALSE;
1694      }
1695    evas_object_smart_callback_call(sd->wd->obj, SIG_CHANGED, NULL);
1696 }
1697
1698 static void
1699 _pan_move(Evas_Object *obj,
1700           Evas_Coord x __UNUSED__,
1701           Evas_Coord y __UNUSED__)
1702 {
1703    Pan *sd = evas_object_smart_data_get(obj);
1704    if (!sd) return;
1705    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1706    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1707 }
1708
1709 static void
1710 _hold_on(void *data       __UNUSED__,
1711          Evas_Object     *obj,
1712          void *event_info __UNUSED__)
1713 {
1714    Widget_Data *wd = elm_widget_data_get(obj);
1715    if (!wd) return;
1716    elm_smart_scroller_hold_set(wd->scr, 1);
1717 }
1718
1719 static void
1720 _hold_off(void *data       __UNUSED__,
1721           Evas_Object     *obj,
1722           void *event_info __UNUSED__)
1723 {
1724    Widget_Data *wd = elm_widget_data_get(obj);
1725    if (!wd) return;
1726    elm_smart_scroller_hold_set(wd->scr, 0);
1727 }
1728
1729 static void
1730 _freeze_on(void *data       __UNUSED__,
1731            Evas_Object     *obj,
1732            void *event_info __UNUSED__)
1733 {
1734    Widget_Data *wd = elm_widget_data_get(obj);
1735    if (!wd) return;
1736    elm_smart_scroller_freeze_set(wd->scr, 1);
1737 }
1738
1739 static void
1740 _freeze_off(void *data       __UNUSED__,
1741             Evas_Object     *obj,
1742             void *event_info __UNUSED__)
1743 {
1744    Widget_Data *wd = elm_widget_data_get(obj);
1745    if (!wd) return;
1746    elm_smart_scroller_freeze_set(wd->scr, 0);
1747 }
1748
1749 static void
1750 _scr_anim_start(void        *data,
1751                 Evas_Object *obj __UNUSED__,
1752                 void        *event_info __UNUSED__)
1753 {
1754    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
1755 }
1756
1757 static void
1758 _scr_anim_stop(void        *data,
1759                 Evas_Object *obj __UNUSED__,
1760                 void        *event_info __UNUSED__)
1761 {
1762    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
1763 }
1764
1765 static void
1766 _scr_drag_start(void            *data,
1767                 Evas_Object *obj __UNUSED__,
1768                 void *event_info __UNUSED__)
1769 {
1770    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
1771 }
1772
1773 static void
1774 _scr_drag_stop(void            *data,
1775                Evas_Object *obj __UNUSED__,
1776                void *event_info __UNUSED__)
1777 {
1778    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
1779 }
1780
1781 static void
1782 _edge_left(void        *data,
1783            Evas_Object *scr __UNUSED__,
1784            void        *event_info __UNUSED__)
1785 {
1786    evas_object_smart_callback_call(data, SIG_SCROLL_EDGE_LEFT, NULL);
1787    evas_object_smart_callback_call(data, SIG_EDGE_LEFT, NULL);
1788 }
1789
1790 static void
1791 _edge_right(void        *data,
1792             Evas_Object *scr __UNUSED__,
1793             void        *event_info __UNUSED__)
1794 {
1795    evas_object_smart_callback_call(data, SIG_SCROLL_EDGE_RIGHT, NULL);
1796    evas_object_smart_callback_call(data, SIG_EDGE_RIGHT, NULL);
1797 }
1798
1799 static void
1800 _edge_top(void        *data,
1801           Evas_Object *scr __UNUSED__,
1802           void        *event_info __UNUSED__)
1803 {
1804    evas_object_smart_callback_call(data, SIG_SCROLL_EDGE_TOP, NULL);
1805    evas_object_smart_callback_call(data, SIG_EDGE_TOP, NULL);
1806 }
1807
1808 static void
1809 _edge_bottom(void        *data,
1810              Evas_Object *scr __UNUSED__,
1811              void        *event_info __UNUSED__)
1812 {
1813    evas_object_smart_callback_call(data, SIG_SCROLL_EDGE_BOTTOM, NULL);
1814    evas_object_smart_callback_call(data, SIG_EDGE_BOTTOM, NULL);
1815 }
1816
1817 static void
1818 _scr_scroll(void            *data,
1819             Evas_Object *obj __UNUSED__,
1820             void *event_info __UNUSED__)
1821 {
1822    evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
1823 }
1824
1825 static int
1826 _elm_gengrid_item_compare_data(const void *data, const void *data1)
1827 {
1828    const Elm_Gen_Item *it = data;
1829    const Elm_Gen_Item *item1 = data1;
1830
1831    return _elm_gengrid_item_compare_data_cb(it->base.data, item1->base.data);
1832 }
1833
1834 static int
1835 _elm_gengrid_item_compare(const void *data, const void *data1)
1836 {
1837    Elm_Gen_Item *it, *item1;
1838    it = ELM_GEN_ITEM_FROM_INLIST(data);
1839    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
1840    return _elm_gengrid_item_compare_cb(it, item1);
1841 }
1842
1843 static Elm_Gen_Item *
1844 _item_new(Widget_Data                  *wd,
1845           const Elm_Gengrid_Item_Class *itc,
1846           const void                   *data,
1847           Evas_Smart_Cb                 func,
1848           const void                   *func_data)
1849 {
1850    Elm_Gen_Item *it;
1851
1852    it = elm_gen_item_new(wd, itc, data, NULL, func, func_data);
1853    if (!it) return NULL;
1854    it->item = ELM_NEW(Elm_Gen_Item_Type);
1855    wd->count++;
1856    it->group = !strcmp(it->itc->item_style, "group_index");
1857    ELM_GEN_ITEM_SETUP(it);
1858
1859    return it;
1860 }
1861
1862 EAPI Evas_Object *
1863 elm_gengrid_add(Evas_Object *parent)
1864 {
1865    Evas_Object *obj;
1866    Evas *e;
1867    Widget_Data *wd;
1868    static Evas_Smart *smart = NULL;
1869    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1870
1871    if (!smart)
1872      {
1873         static Evas_Smart_Class sc;
1874
1875         evas_object_smart_clipped_smart_set(&_pan_sc);
1876         sc = _pan_sc;
1877         sc.name = "elm_gengrid_pan";
1878         sc.version = EVAS_SMART_CLASS_VERSION;
1879         sc.add = _pan_add;
1880         sc.del = _pan_del;
1881         sc.resize = _pan_resize;
1882         sc.move = _pan_move;
1883         sc.calculate = _pan_calculate;
1884         if (!(smart = evas_smart_class_new(&sc))) return NULL;
1885      }
1886
1887    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1888
1889    ELM_SET_WIDTYPE(widtype, "gengrid");
1890    ELM_GEN_SETUP(wd);
1891    elm_widget_type_set(obj, "gengrid");
1892    elm_widget_sub_object_add(parent, obj);
1893    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1894    elm_widget_data_set(obj, wd);
1895    elm_widget_del_hook_set(obj, _del_hook);
1896    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1897    elm_widget_theme_hook_set(obj, _theme_hook);
1898    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1899    elm_widget_can_focus_set(obj, EINA_TRUE);
1900    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
1901    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
1902    elm_widget_event_hook_set(obj, _event_hook);
1903
1904    wd->scr = elm_smart_scroller_add(e);
1905    elm_smart_scroller_widget_set(wd->scr, obj);
1906    elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
1907                                        "default");
1908    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
1909    elm_widget_resize_object_set(obj, wd->scr);
1910
1911    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
1912    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
1913    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
1914    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
1915    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
1916    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
1917    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
1918    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom,
1919                                   obj);
1920    evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
1921
1922    wd->obj = obj;
1923    wd->align_x = 0.5;
1924    wd->align_y = 0.5;
1925    wd->h_bounce = bounce;
1926    wd->v_bounce = bounce;
1927
1928    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1929    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1930    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1931    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1932
1933    wd->pan_smart = evas_object_smart_add(e, smart);
1934    wd->pan = evas_object_smart_data_get(wd->pan_smart);
1935    wd->pan->wd = wd;
1936
1937    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
1938                                      _pan_set, _pan_get, _pan_max_get,
1939                                      _pan_min_get, _pan_child_size_get);
1940
1941    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1942
1943    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1944    return obj;
1945 }
1946
1947 EAPI void
1948 elm_gengrid_item_size_set(Evas_Object *obj,
1949                           Evas_Coord   w,
1950                           Evas_Coord   h)
1951 {
1952    ELM_CHECK_WIDTYPE(obj, widtype);
1953    Widget_Data *wd = elm_widget_data_get(obj);
1954    if (!wd) return;
1955    if ((wd->item_width == w) && (wd->item_height == h)) return;
1956    wd->item_width = w;
1957    wd->item_height = h;
1958    if (wd->calc_job) ecore_job_del(wd->calc_job);
1959    wd->calc_job = ecore_job_add(_calc_job, wd);
1960 }
1961
1962 EAPI void
1963 elm_gengrid_item_size_get(const Evas_Object *obj,
1964                           Evas_Coord        *w,
1965                           Evas_Coord        *h)
1966 {
1967    ELM_CHECK_WIDTYPE(obj, widtype);
1968    Widget_Data *wd = elm_widget_data_get(obj);
1969    if (!wd) return;
1970    if (w) *w = wd->item_width;
1971    if (h) *h = wd->item_height;
1972 }
1973
1974 EAPI void
1975 elm_gengrid_group_item_size_set(Evas_Object *obj,
1976                           Evas_Coord   w,
1977                           Evas_Coord   h)
1978 {
1979    ELM_CHECK_WIDTYPE(obj, widtype);
1980    Widget_Data *wd = elm_widget_data_get(obj);
1981    if (!wd) return;
1982    if ((wd->group_item_width == w) && (wd->group_item_height == h)) return;
1983    wd->group_item_width = w;
1984    wd->group_item_height = h;
1985    if (wd->calc_job) ecore_job_del(wd->calc_job);
1986    wd->calc_job = ecore_job_add(_calc_job, wd);
1987 }
1988
1989 EAPI void
1990 elm_gengrid_group_item_size_get(const Evas_Object *obj,
1991                           Evas_Coord        *w,
1992                           Evas_Coord        *h)
1993 {
1994    ELM_CHECK_WIDTYPE(obj, widtype);
1995    Widget_Data *wd = elm_widget_data_get(obj);
1996    if (!wd) return;
1997    if (w) *w = wd->group_item_width;
1998    if (h) *h = wd->group_item_height;
1999 }
2000
2001 EAPI void
2002 elm_gengrid_align_set(Evas_Object *obj,
2003                       double       align_x,
2004                       double       align_y)
2005 {
2006    ELM_CHECK_WIDTYPE(obj, widtype);
2007
2008    Widget_Data *wd = elm_widget_data_get(obj);
2009    double old_h = wd->align_x, old_y = wd->align_y;
2010
2011    if (align_x > 1.0)
2012      align_x = 1.0;
2013    else if (align_x < 0.0)
2014      align_x = 0.0;
2015    wd->align_x = align_x;
2016
2017    if (align_y > 1.0)
2018      align_y = 1.0;
2019    else if (align_y < 0.0)
2020      align_y = 0.0;
2021    wd->align_y = align_y;
2022
2023    if ((old_h != wd->align_x) || (old_y != wd->align_y))
2024      evas_object_smart_calculate(wd->pan_smart);
2025 }
2026
2027 EAPI void
2028 elm_gengrid_align_get(const Evas_Object *obj,
2029                       double            *align_x,
2030                       double            *align_y)
2031 {
2032    ELM_CHECK_WIDTYPE(obj, widtype);
2033    Widget_Data *wd = elm_widget_data_get(obj);
2034    if (align_x) *align_x = wd->align_x;
2035    if (align_y) *align_y = wd->align_y;
2036 }
2037
2038 EAPI Elm_Gen_Item *
2039 elm_gengrid_item_append(Evas_Object                  *obj,
2040                         const Elm_Gengrid_Item_Class *itc,
2041                         const void                   *data,
2042                         Evas_Smart_Cb                 func,
2043                         const void                   *func_data)
2044 {
2045    Elm_Gen_Item *it;
2046    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2047    Widget_Data *wd = elm_widget_data_get(obj);
2048    if (!wd) return NULL;
2049
2050    it = _item_new(wd, itc, data, func, func_data);
2051    if (!it) return NULL;
2052    wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
2053
2054    if (it->group)
2055      wd->group_items = eina_list_prepend(wd->group_items, it);
2056
2057    if (wd->calc_job) ecore_job_del(wd->calc_job);
2058    wd->calc_job = ecore_job_add(_calc_job, wd);
2059
2060    return it;
2061 }
2062
2063 EAPI Elm_Gen_Item *
2064 elm_gengrid_item_prepend(Evas_Object                  *obj,
2065                          const Elm_Gengrid_Item_Class *itc,
2066                          const void                   *data,
2067                          Evas_Smart_Cb                 func,
2068                          const void                   *func_data)
2069 {
2070    Elm_Gen_Item *it;
2071    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2072    Widget_Data *wd = elm_widget_data_get(obj);
2073    if (!wd) return NULL;
2074
2075    it = _item_new(wd, itc, data, func, func_data);
2076    if (!it) return NULL;
2077    wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
2078    if (it->group)
2079      wd->group_items = eina_list_append(wd->group_items, it);
2080
2081    if (wd->calc_job) ecore_job_del(wd->calc_job);
2082    wd->calc_job = ecore_job_add(_calc_job, wd);
2083
2084    return it;
2085 }
2086
2087 EAPI Elm_Gen_Item *
2088 elm_gengrid_item_insert_before(Evas_Object                  *obj,
2089                                const Elm_Gengrid_Item_Class *itc,
2090                                const void                   *data,
2091                                Elm_Gen_Item             *relative,
2092                                Evas_Smart_Cb                 func,
2093                                const void                   *func_data)
2094 {
2095    Elm_Gen_Item *it;
2096    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2097    EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
2098    Widget_Data *wd = elm_widget_data_get(obj);
2099    if (!wd) return NULL;
2100
2101    it = _item_new(wd, itc, data, func, func_data);
2102    if (!it) return NULL;
2103    wd->items = eina_inlist_prepend_relative
2104       (wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(relative));
2105    if (it->group)
2106      wd->group_items = eina_list_append_relative(wd->group_items, it, relative->parent);
2107
2108    if (wd->calc_job) ecore_job_del(wd->calc_job);
2109    wd->calc_job = ecore_job_add(_calc_job, wd);
2110
2111    return it;
2112 }
2113
2114 EAPI Elm_Gen_Item *
2115 elm_gengrid_item_insert_after(Evas_Object                  *obj,
2116                               const Elm_Gengrid_Item_Class *itc,
2117                               const void                   *data,
2118                               Elm_Gen_Item             *relative,
2119                               Evas_Smart_Cb                 func,
2120                               const void                   *func_data)
2121 {
2122    Elm_Gen_Item *it;
2123    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2124    EINA_SAFETY_ON_NULL_RETURN_VAL(relative, NULL);
2125    Widget_Data *wd = elm_widget_data_get(obj);
2126    if (!wd) return NULL;
2127
2128    it = _item_new(wd, itc, data, func, func_data);
2129    if (!it) return NULL;
2130    wd->items = eina_inlist_append_relative
2131       (wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(relative));
2132    if (it->group)
2133      wd->group_items = eina_list_prepend_relative(wd->group_items, it, relative->parent);
2134
2135    if (wd->calc_job) ecore_job_del(wd->calc_job);
2136    wd->calc_job = ecore_job_add(_calc_job, wd);
2137
2138    return it;
2139 }
2140
2141 EAPI Elm_Gen_Item *
2142 elm_gengrid_item_direct_sorted_insert(Evas_Object                  *obj,
2143                                       const Elm_Gengrid_Item_Class *itc,
2144                                       const void                   *data,
2145                                       Eina_Compare_Cb               comp,
2146                                       Evas_Smart_Cb                 func,
2147                                       const void                   *func_data)
2148 {
2149    Elm_Gen_Item *it;
2150    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2151    Widget_Data *wd = elm_widget_data_get(obj);
2152    if (!wd) return NULL;
2153
2154    it = _item_new(wd, itc, data, func, func_data);
2155    if (!it) return NULL;
2156
2157    if (!wd->state)
2158      wd->state = eina_inlist_sorted_state_new();
2159
2160    _elm_gengrid_item_compare_cb = comp;
2161    wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
2162                                          _elm_gengrid_item_compare, wd->state);
2163    if (wd->calc_job) ecore_job_del(wd->calc_job);
2164    wd->calc_job = ecore_job_add(_calc_job, wd);
2165
2166    return it;
2167 }
2168
2169 EAPI Elm_Gen_Item *
2170 elm_gengrid_item_sorted_insert(Evas_Object                  *obj,
2171                                const Elm_Gengrid_Item_Class *itc,
2172                                const void                   *data,
2173                                Eina_Compare_Cb               comp,
2174                                Evas_Smart_Cb                 func,
2175                                const void                   *func_data)
2176 {
2177    _elm_gengrid_item_compare_data_cb = comp;
2178
2179    return elm_gengrid_item_direct_sorted_insert(obj, itc, data, _elm_gengrid_item_compare_data, func, func_data);
2180 }
2181
2182 EAPI void
2183 elm_gengrid_item_del(Elm_Gen_Item *it)
2184 {
2185    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2186    if ((it->relcount > 0) || (it->walking > 0))
2187      {
2188         elm_gen_item_del_notserious(it);
2189         return;
2190      }
2191
2192    _item_del(it);
2193 }
2194
2195 EAPI void
2196 elm_gengrid_horizontal_set(Evas_Object *obj,
2197                            Eina_Bool    setting)
2198 {
2199    ELM_CHECK_WIDTYPE(obj, widtype);
2200    Widget_Data *wd = elm_widget_data_get(obj);
2201    if (!wd) return;
2202    if (setting == wd->horizontal) return;
2203    wd->horizontal = setting;
2204
2205    /* Update the items to conform to the new layout */
2206    if (wd->calc_job) ecore_job_del(wd->calc_job);
2207    wd->calc_job = ecore_job_add(_calc_job, wd);
2208 }
2209
2210 EAPI Eina_Bool
2211 elm_gengrid_horizontal_get(const Evas_Object *obj)
2212 {
2213    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2214    Widget_Data *wd = elm_widget_data_get(obj);
2215    if (!wd) return EINA_FALSE;
2216    return wd->horizontal;
2217 }
2218
2219 EAPI void
2220 elm_gengrid_clear(Evas_Object *obj)
2221 {
2222    elm_gen_clear(obj);
2223 }
2224
2225 EAPI const Evas_Object *
2226 elm_gengrid_item_object_get(const Elm_Gen_Item *it)
2227 {
2228    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2229    return VIEW(it);
2230 }
2231
2232 EAPI void
2233 elm_gengrid_item_update(Elm_Gen_Item *it)
2234 {
2235    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2236    if (!it->realized) return;
2237    if (it->want_unrealize) return;
2238    elm_gen_item_unrealize(it, EINA_FALSE);
2239    _item_realize(it);
2240    _item_place(it, it->x, it->y);
2241 }
2242
2243 EAPI void *
2244 elm_gengrid_item_data_get(const Elm_Gen_Item *it)
2245 {
2246    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2247    return elm_widget_item_data_get(it);
2248 }
2249
2250 EAPI void
2251 elm_gengrid_item_data_set(Elm_Gen_Item *it,
2252                           const void       *data)
2253 {
2254    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2255    elm_widget_item_data_set(it, data);
2256 }
2257
2258 EAPI const Elm_Gengrid_Item_Class *
2259 elm_gengrid_item_item_class_get(const Elm_Gen_Item *it)
2260 {
2261    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2262    if (it->delete_me) return NULL;
2263    return it->itc;
2264 }
2265
2266 EAPI void
2267 elm_gengrid_item_item_class_set(Elm_Gen_Item *it,
2268                                 const Elm_Gengrid_Item_Class *itc)
2269 {
2270    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2271    EINA_SAFETY_ON_NULL_RETURN(itc);
2272    if (it->delete_me) return;
2273    it->itc = itc;
2274    elm_gengrid_item_update(it);
2275 }
2276
2277 EAPI void
2278 elm_gengrid_item_pos_get(const Elm_Gen_Item *it,
2279                          unsigned int           *x,
2280                          unsigned int           *y)
2281 {
2282    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2283    if (x) *x = it->x;
2284    if (y) *y = it->y;
2285 }
2286
2287 EAPI void
2288 elm_gengrid_multi_select_set(Evas_Object *obj,
2289                              Eina_Bool    multi)
2290 {
2291    ELM_CHECK_WIDTYPE(obj, widtype);
2292    Widget_Data *wd = elm_widget_data_get(obj);
2293    if (!wd) return;
2294    wd->multi = multi;
2295 }
2296
2297 EAPI Eina_Bool
2298 elm_gengrid_multi_select_get(const Evas_Object *obj)
2299 {
2300    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2301    Widget_Data *wd = elm_widget_data_get(obj);
2302    if (!wd) return EINA_FALSE;
2303    return wd->multi;
2304 }
2305
2306 EAPI Elm_Gen_Item *
2307 elm_gengrid_selected_item_get(const Evas_Object *obj)
2308 {
2309    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2310    Widget_Data *wd = elm_widget_data_get(obj);
2311    if (!wd) return NULL;
2312    if (wd->selected) return wd->selected->data;
2313    return NULL;
2314 }
2315
2316 EAPI const Eina_List *
2317 elm_gengrid_selected_items_get(const Evas_Object *obj)
2318 {
2319    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2320    Widget_Data *wd = elm_widget_data_get(obj);
2321    if (!wd) return NULL;
2322    return wd->selected;
2323 }
2324
2325 EAPI void
2326 elm_gengrid_item_selected_set(Elm_Gen_Item *it,
2327                               Eina_Bool         selected)
2328 {
2329    elm_gen_item_selected_set(it, selected);
2330 }
2331
2332 EAPI Eina_Bool
2333 elm_gengrid_item_selected_get(const Elm_Gen_Item *it)
2334 {
2335    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
2336    return it->selected;
2337 }
2338
2339 EAPI void
2340 elm_gengrid_item_disabled_set(Elm_Gen_Item *it,
2341                               Eina_Bool         disabled)
2342 {
2343    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2344    if (it->disabled == disabled) return;
2345    if (it->delete_me) return;
2346    it->disabled = !!disabled;
2347    if (it->realized)
2348      {
2349         if (it->disabled)
2350           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
2351         else
2352           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
2353      }
2354 }
2355
2356 EAPI Eina_Bool
2357 elm_gengrid_item_disabled_get(const Elm_Gen_Item *it)
2358 {
2359    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
2360    if (it->delete_me) return EINA_FALSE;
2361    return it->disabled;
2362 }
2363
2364 static Evas_Object *
2365 _elm_gengrid_item_label_create(void        *data,
2366                                Evas_Object *obj __UNUSED__,
2367                                Evas_Object *tooltip,
2368                                void *it   __UNUSED__)
2369 {
2370    Evas_Object *label = elm_label_add(tooltip);
2371    if (!label)
2372      return NULL;
2373    elm_object_style_set(label, "tooltip");
2374    elm_object_text_set(label, data);
2375    return label;
2376 }
2377
2378 static void
2379 _elm_gengrid_item_label_del_cb(void            *data,
2380                                Evas_Object *obj __UNUSED__,
2381                                void *event_info __UNUSED__)
2382 {
2383    eina_stringshare_del(data);
2384 }
2385
2386 EAPI void
2387 elm_gengrid_item_tooltip_text_set(Elm_Gen_Item *it,
2388                                   const char       *text)
2389 {
2390    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2391    text = eina_stringshare_add(text);
2392    elm_gengrid_item_tooltip_content_cb_set(it, _elm_gengrid_item_label_create,
2393                                            text,
2394                                            _elm_gengrid_item_label_del_cb);
2395 }
2396
2397 EAPI void
2398 elm_gengrid_item_tooltip_content_cb_set(Elm_Gen_Item           *it,
2399                                         Elm_Tooltip_Item_Content_Cb func,
2400                                         const void                 *data,
2401                                         Evas_Smart_Cb               del_cb)
2402 {
2403    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, error);
2404
2405    if ((it->tooltip.content_cb == func) && (it->tooltip.data == data))
2406      return;
2407
2408    if (it->tooltip.del_cb)
2409      it->tooltip.del_cb((void *)it->tooltip.data,
2410                           WIDGET(it), it);
2411    it->tooltip.content_cb = func;
2412    it->tooltip.data = data;
2413    it->tooltip.del_cb = del_cb;
2414    if (VIEW(it))
2415      {
2416         elm_widget_item_tooltip_content_cb_set(it,
2417                                                it->tooltip.content_cb,
2418                                                it->tooltip.data, NULL);
2419         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
2420         elm_widget_item_tooltip_size_restrict_disable(it, it->tooltip.free_size);
2421      }
2422
2423    return;
2424
2425 error:
2426    if (del_cb) del_cb((void *)data, NULL, NULL);
2427 }
2428
2429 EAPI void
2430 elm_gengrid_item_tooltip_unset(Elm_Gen_Item *it)
2431 {
2432    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2433    if ((VIEW(it)) && (it->tooltip.content_cb))
2434      elm_widget_item_tooltip_unset(it);
2435
2436    if (it->tooltip.del_cb)
2437      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
2438    it->tooltip.del_cb = NULL;
2439    it->tooltip.content_cb = NULL;
2440    it->tooltip.data = NULL;
2441    it->tooltip.free_size = EINA_FALSE;
2442    if (it->tooltip.style)
2443      elm_gengrid_item_tooltip_style_set(it, NULL);
2444 }
2445
2446 EAPI void
2447 elm_gengrid_item_tooltip_style_set(Elm_Gen_Item *it,
2448                                    const char       *style)
2449 {
2450    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2451    eina_stringshare_replace(&it->tooltip.style, style);
2452    if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
2453 }
2454
2455 EAPI const char *
2456 elm_gengrid_item_tooltip_style_get(const Elm_Gen_Item *it)
2457 {
2458    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2459    return it->tooltip.style;
2460 }
2461
2462 EAPI Eina_Bool
2463 elm_gengrid_item_tooltip_size_restrict_disable(Elm_Gen_Item *it, Eina_Bool disable)
2464 {
2465    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
2466    it->tooltip.free_size = disable;
2467    if (VIEW(it)) return elm_widget_item_tooltip_size_restrict_disable(it, disable);
2468    return EINA_TRUE;
2469 }
2470
2471 EAPI Eina_Bool
2472 elm_gengrid_item_tooltip_size_restrict_disabled_get(const Elm_Gen_Item *it)
2473 {
2474    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
2475    return it->tooltip.free_size;
2476 }
2477
2478 EAPI void
2479 elm_gengrid_item_cursor_set(Elm_Gen_Item *it,
2480                             const char       *cursor)
2481 {
2482    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2483    eina_stringshare_replace(&it->mouse_cursor, cursor);
2484    if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
2485 }
2486
2487 EAPI const char *
2488 elm_gengrid_item_cursor_get(const Elm_Gen_Item *it)
2489 {
2490    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2491    return elm_widget_item_cursor_get(it);
2492 }
2493
2494 EAPI void
2495 elm_gengrid_item_cursor_unset(Elm_Gen_Item *it)
2496 {
2497    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2498    if (!it->mouse_cursor)
2499      return;
2500
2501    if (VIEW(it))
2502      elm_widget_item_cursor_unset(it);
2503
2504    eina_stringshare_del(it->mouse_cursor);
2505    it->mouse_cursor = NULL;
2506 }
2507
2508 EAPI void
2509 elm_gengrid_item_cursor_style_set(Elm_Gen_Item *it,
2510                                   const char       *style)
2511 {
2512    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2513    elm_widget_item_cursor_style_set(it, style);
2514 }
2515
2516 EAPI const char *
2517 elm_gengrid_item_cursor_style_get(const Elm_Gen_Item *it)
2518 {
2519    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2520    return elm_widget_item_cursor_style_get(it);
2521 }
2522
2523 EAPI void
2524 elm_gengrid_item_cursor_engine_only_set(Elm_Gen_Item *it,
2525                                         Eina_Bool         engine_only)
2526 {
2527    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2528    elm_widget_item_cursor_engine_only_set(it, engine_only);
2529 }
2530
2531 EAPI Eina_Bool
2532 elm_gengrid_item_cursor_engine_only_get(const Elm_Gen_Item *it)
2533 {
2534    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
2535    return elm_widget_item_cursor_engine_only_get(it);
2536 }
2537
2538 EAPI void
2539 elm_gengrid_reorder_mode_set(Evas_Object *obj,
2540                              Eina_Bool    reorder_mode)
2541 {
2542    ELM_CHECK_WIDTYPE(obj, widtype);
2543    Widget_Data *wd = elm_widget_data_get(obj);
2544    if (!wd) return;
2545    wd->reorder_mode = reorder_mode;
2546 }
2547
2548 EAPI Eina_Bool
2549 elm_gengrid_reorder_mode_get(const Evas_Object *obj)
2550 {
2551    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2552    Widget_Data *wd = elm_widget_data_get(obj);
2553    if (!wd) return EINA_FALSE;
2554    return wd->reorder_mode;
2555 }
2556
2557 EAPI void
2558 elm_gengrid_always_select_mode_set(Evas_Object *obj,
2559                                    Eina_Bool    always_select)
2560 {
2561    ELM_CHECK_WIDTYPE(obj, widtype);
2562    Widget_Data *wd = elm_widget_data_get(obj);
2563    if (!wd) return;
2564    wd->always_select = always_select;
2565 }
2566
2567 EAPI Eina_Bool
2568 elm_gengrid_always_select_mode_get(const Evas_Object *obj)
2569 {
2570    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2571    Widget_Data *wd = elm_widget_data_get(obj);
2572    if (!wd) return EINA_FALSE;
2573    return wd->always_select;
2574 }
2575
2576 EAPI void
2577 elm_gengrid_no_select_mode_set(Evas_Object *obj,
2578                                Eina_Bool    no_select)
2579 {
2580    ELM_CHECK_WIDTYPE(obj, widtype);
2581    Widget_Data *wd = elm_widget_data_get(obj);
2582    if (!wd) return;
2583    wd->no_select = no_select;
2584 }
2585
2586 EAPI Eina_Bool
2587 elm_gengrid_no_select_mode_get(const Evas_Object *obj)
2588 {
2589    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2590    Widget_Data *wd = elm_widget_data_get(obj);
2591    if (!wd) return EINA_FALSE;
2592    return wd->no_select;
2593 }
2594
2595 EAPI void
2596 elm_gengrid_bounce_set(Evas_Object *obj,
2597                        Eina_Bool    h_bounce,
2598                        Eina_Bool    v_bounce)
2599 {
2600    ELM_CHECK_WIDTYPE(obj, widtype);
2601    Widget_Data *wd = elm_widget_data_get(obj);
2602    if (!wd) return;
2603    elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
2604    wd->h_bounce = h_bounce;
2605    wd->v_bounce = v_bounce;
2606 }
2607
2608 EAPI void
2609 elm_gengrid_bounce_get(const Evas_Object *obj,
2610                        Eina_Bool         *h_bounce,
2611                        Eina_Bool         *v_bounce)
2612 {
2613    ELM_CHECK_WIDTYPE(obj, widtype);
2614    Widget_Data *wd = elm_widget_data_get(obj);
2615    if (!wd) return;
2616    if (h_bounce) *h_bounce = wd->h_bounce;
2617    if (v_bounce) *v_bounce = wd->v_bounce;
2618 }
2619
2620 EAPI void
2621 elm_gengrid_page_relative_set(Evas_Object *obj,
2622                               double       h_pagerel,
2623                               double       v_pagerel)
2624 {
2625    Evas_Coord pagesize_h;
2626    Evas_Coord pagesize_v;
2627
2628    ELM_CHECK_WIDTYPE(obj, widtype);
2629    Widget_Data *wd = elm_widget_data_get(obj);
2630    if (!wd) return;
2631
2632    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
2633    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
2634                                  pagesize_v);
2635 }
2636
2637 EAPI void
2638 elm_gengrid_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel)
2639 {
2640    ELM_CHECK_WIDTYPE(obj, widtype);
2641    Widget_Data *wd = elm_widget_data_get(obj);
2642    if (!wd) return;
2643
2644    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
2645 }
2646
2647 EAPI void
2648 elm_gengrid_page_size_set(Evas_Object *obj,
2649                           Evas_Coord   h_pagesize,
2650                           Evas_Coord   v_pagesize)
2651 {
2652    double pagerel_h;
2653    double pagerel_v;
2654
2655    ELM_CHECK_WIDTYPE(obj, widtype);
2656    Widget_Data *wd = elm_widget_data_get(obj);
2657    if (!wd) return;
2658    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
2659    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
2660                                  v_pagesize);
2661 }
2662
2663 EAPI void
2664 elm_gengrid_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
2665 {
2666    ELM_CHECK_WIDTYPE(obj, widtype);
2667    Widget_Data *wd = elm_widget_data_get(obj);
2668    if (!wd) return;
2669    if (wd->scr)
2670      elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
2671 }
2672
2673 EAPI void
2674 elm_gengrid_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
2675 {
2676    ELM_CHECK_WIDTYPE(obj, widtype);
2677    Widget_Data *wd = elm_widget_data_get(obj);
2678    if (!wd) return;
2679    if (wd->scr)
2680      elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
2681 }
2682
2683 EAPI void
2684 elm_gengrid_page_show(const Evas_Object *obj, int h_pagenumber, int v_pagenumber)
2685 {
2686    ELM_CHECK_WIDTYPE(obj, widtype);
2687    Widget_Data *wd = elm_widget_data_get(obj);
2688    if (!wd) return;
2689    if (wd->scr)
2690      elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
2691 }
2692
2693 EAPI void
2694 elm_gengrid_page_bring_in(const Evas_Object *obj, int h_pagenumber, int v_pagenumber)
2695 {
2696    ELM_CHECK_WIDTYPE(obj, widtype);
2697    Widget_Data *wd = elm_widget_data_get(obj);
2698    if (!wd) return;
2699    if (wd->scr)
2700      elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
2701 }
2702
2703 EAPI Elm_Gen_Item *
2704 elm_gengrid_first_item_get(const Evas_Object *obj)
2705 {
2706    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2707    Widget_Data *wd = elm_widget_data_get(obj);
2708    if (!wd) return NULL;
2709    if (!wd->items) return NULL;
2710    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
2711    while ((it) && (it->delete_me))
2712      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
2713    return it;
2714 }
2715
2716 EAPI Elm_Gen_Item *
2717 elm_gengrid_last_item_get(const Evas_Object *obj)
2718 {
2719    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2720    Widget_Data *wd = elm_widget_data_get(obj);
2721    if (!wd) return NULL;
2722    if (!wd->items) return NULL;
2723    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
2724    while ((it) && (it->delete_me))
2725      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
2726    return it;
2727 }
2728
2729 EAPI Elm_Gen_Item *
2730 elm_gengrid_item_next_get(const Elm_Gen_Item *it)
2731 {
2732    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2733    while (it)
2734      {
2735         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
2736         if ((it) && (!it->delete_me)) break;
2737      }
2738    return (Elm_Gen_Item *)it;
2739 }
2740
2741 EAPI Elm_Gen_Item *
2742 elm_gengrid_item_prev_get(const Elm_Gen_Item *it)
2743 {
2744    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2745    while (it)
2746      {
2747         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
2748         if ((it) && (!it->delete_me)) break;
2749      }
2750    return (Elm_Gen_Item *)it;
2751 }
2752
2753 EAPI Evas_Object *
2754 elm_gengrid_item_gengrid_get(const Elm_Gen_Item *it)
2755 {
2756    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
2757    return WIDGET(it);
2758 }
2759
2760 EAPI void
2761 elm_gengrid_item_show(Elm_Gen_Item *it)
2762 {
2763    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2764    Widget_Data *wd = it->wd;
2765    Evas_Coord minx = 0, miny = 0;
2766
2767    if (!wd) return;
2768    if ((!it) || (it->delete_me)) return;
2769    _pan_min_get(wd->pan_smart, &minx, &miny);
2770
2771    if (wd->horizontal)
2772      elm_smart_scroller_region_bring_in(it->wd->scr,
2773                                         ((it->x - it->item->prev_group) * wd->item_width) + (it->item->prev_group * it->wd->group_item_width) + minx,
2774                                         it->y * wd->item_height + miny,
2775                                         it->wd->item_width,
2776                                         it->wd->item_height);
2777    else
2778      elm_smart_scroller_region_bring_in(it->wd->scr,
2779                                         it->x * wd->item_width + minx,
2780                                         ((it->y - it->item->prev_group)* wd->item_height) + (it->item->prev_group * it->wd->group_item_height) + miny,
2781                                         it->wd->item_width,
2782                                         it->wd->item_height);
2783 }
2784
2785 EAPI void
2786 elm_gengrid_item_bring_in(Elm_Gen_Item *it)
2787 {
2788    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
2789    if (it->delete_me) return;
2790
2791    Evas_Coord minx = 0, miny = 0;
2792    Widget_Data *wd = it->wd;
2793    if (!wd) return;
2794    _pan_min_get(wd->pan_smart, &minx, &miny);
2795
2796    if (wd->horizontal)
2797      elm_smart_scroller_region_bring_in(it->wd->scr,
2798                                         ((it->x - it->item->prev_group) * wd->item_width) + (it->item->prev_group * it->wd->group_item_width) + minx,
2799                                         it->y * wd->item_height + miny,
2800                                         it->wd->item_width,
2801                                         it->wd->item_height);
2802    else
2803      elm_smart_scroller_region_bring_in(it->wd->scr,
2804                                         it->x * wd->item_width + minx,
2805                                         ((it->y - it->item->prev_group)* wd->item_height) + (it->item->prev_group * it->wd->group_item_height) + miny,
2806                                         it->wd->item_width,
2807                                         it->wd->item_height);
2808 }