gengrid: add unhighlight callback
[platform/upstream/elementary.git] / src / lib / elm_gengrid.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
9
10 #include <Elementary.h>
11 #include <Elementary_Cursor.h>
12 #include "elm_priv.h"
13 #include "elm_widget_gengrid.h"
14 #include "elm_interface_scrollable.h"
15
16 #define MY_PAN_CLASS ELM_GENGRID_PAN_CLASS
17
18 #define MY_PAN_CLASS_NAME "Elm_Gengrid_Pan"
19 #define MY_PAN_CLASS_NAME_LEGACY "elm_gengrid_pan"
20
21 #define MY_CLASS ELM_GENGRID_CLASS
22
23 #define MY_CLASS_NAME "Elm_Gengrid"
24 #define MY_CLASS_NAME_LEGACY "elm_gengrid"
25
26 // internally allocated
27 #define CLASS_ALLOCATED     0x3a70f00f
28
29 /* --
30  * TODO:
31  * Handle non-homogeneous objects too.
32  */
33
34 #define PRELOAD             1
35 #define REORDER_EFFECT_TIME 0.5
36
37 #define CACHE_MAX 40
38
39 EAPI const char ELM_GENGRID_SMART_NAME[] = "elm_gengrid";
40 EAPI const char ELM_GENGRID_PAN_SMART_NAME[] = "elm_gengrid_pan";
41
42 #define ELM_PRIV_GENGRID_SIGNALS(cmd) \
43    cmd(SIG_ACTIVATED, "activated", "") \
44    cmd(SIG_CLICKED_DOUBLE, "clicked,double", "") \
45    cmd(SIG_CLICKED_RIGHT, "clicked,right", "") \
46    cmd(SIG_LONGPRESSED, "longpressed", "") \
47    cmd(SIG_SELECTED, "selected", "") \
48    cmd(SIG_UNSELECTED, "unselected", "") \
49    cmd(SIG_REALIZED, "realized", "") \
50    cmd(SIG_UNREALIZED, "unrealized", "") \
51    cmd(SIG_CHANGED, "changed", "") \
52    cmd(SIG_DRAG_START_UP, "drag,start,up", "") \
53    cmd(SIG_DRAG_START_DOWN, "drag,start,down", "") \
54    cmd(SIG_DRAG_START_LEFT, "drag,start,left", "") \
55    cmd(SIG_DRAG_START_RIGHT, "drag,start,right", "") \
56    cmd(SIG_DRAG_STOP, "drag,stop", "") \
57    cmd(SIG_DRAG, "drag", "") \
58    cmd(SIG_SCROLL, "scroll", "") \
59    cmd(SIG_SCROLL_ANIM_START, "scroll,anim,start", "") \
60    cmd(SIG_SCROLL_ANIM_STOP, "scroll,anim,stop", "") \
61    cmd(SIG_SCROLL_DRAG_START, "scroll,drag,start", "") \
62    cmd(SIG_SCROLL_DRAG_STOP, "scroll,drag,stop", "") \
63    cmd(SIG_SCROLL_PAGE_CHANGE, "scroll,page,changed", "") \
64    cmd(SIG_EDGE_TOP, "edge,top", "") \
65    cmd(SIG_EDGE_BOTTOM, "edge,bottom", "") \
66    cmd(SIG_EDGE_LEFT, "edge,left", "") \
67    cmd(SIG_EDGE_RIGHT, "edge,right", "") \
68    cmd(SIG_MOVED, "moved", "") \
69    cmd(SIG_INDEX_UPDATE, "index,update", "") \
70    cmd(SIG_HIGHLIGHTED, "highlighted", "") \
71    cmd(SIG_UNHIGHLIGHTED, "unhighlighted", "") \
72    cmd(SIG_ITEM_FOCUSED, "item,focused", "") \
73    cmd(SIG_ITEM_UNFOCUSED, "item,unfocused", "") \
74    cmd(SIG_PRESSED, "pressed", "") \
75    cmd(SIG_RELEASED, "released", "") \
76    cmd(SIG_ITEM_REORDER_START, "item,reorder,anim,start", "") \
77    cmd(SIG_ITEM_REORDER_STOP, "item,reorder,anim,stop", "")
78
79 ELM_PRIV_GENGRID_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
80
81 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
82    ELM_PRIV_GENGRID_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
83    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
84    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
85    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
86    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
87    {SIG_ITEM_FOCUSED, ""},
88    {SIG_ITEM_UNFOCUSED, ""},
89
90    {NULL, NULL}
91 };
92 #undef ELM_PRIV_GENGRID_SIGNALS
93
94 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
95 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
96 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
97 static void _item_position_update(Eina_Inlist *list, int idx);
98 static void _item_mouse_callbacks_add(Elm_Gen_Item *it, Evas_Object *view);
99 static void _item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view);
100
101
102 static const Elm_Action key_actions[] = {
103    {"move", _key_action_move},
104    {"select", _key_action_select},
105    {"escape", _key_action_escape},
106    {NULL, NULL}
107 };
108
109
110 //-- item cache handle routine --//
111 // push item cache into caches
112 static Eina_Bool
113 _item_cache_push(Elm_Gengrid_Data *sd, Item_Cache *itc)
114 {
115    if (!itc || (sd->item_cache_max <= 0))
116      return EINA_FALSE;
117
118    sd->item_cache_count++;
119    sd->item_cache =
120      eina_inlist_prepend(sd->item_cache, EINA_INLIST_GET(itc));
121
122    return EINA_TRUE;
123 }
124
125 // pop item cache from caches
126 static Item_Cache *
127 _item_cache_pop(Elm_Gengrid_Data *sd, Item_Cache *itc)
128 {
129    if ((!itc) || (!sd->item_cache) ||
130        (sd->item_cache_count <= 0))
131      return NULL;
132
133    sd->item_cache =
134      eina_inlist_remove (sd->item_cache, EINA_INLIST_GET(itc));
135    sd->item_cache_count--;
136
137    return itc;
138 }
139
140 // free one item cache from caches
141 static void
142 _item_cache_free(Item_Cache *itc)
143 {
144    if (!itc) return;
145
146    evas_object_del(itc->spacer);
147    evas_object_del(itc->base_view);
148    eina_stringshare_del(itc->item_style);
149    ELM_SAFE_FREE(itc ,free);
150 }
151
152 // clean up item cache by removing overflowed caches
153 static void
154 _item_cache_clean(Elm_Gengrid_Data *sd)
155 {
156    evas_event_freeze(evas_object_evas_get(sd->obj));
157
158    while ((sd->item_cache) && (sd->item_cache_count > sd->item_cache_max))
159      {
160         Item_Cache *itc =
161            EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache);
162         _item_cache_free(_item_cache_pop(sd, itc));
163      }
164    evas_event_thaw(evas_object_evas_get(sd->obj));
165    evas_event_thaw_eval(evas_object_evas_get(sd->obj));
166 }
167
168 // empty all item caches
169 static void
170 _item_cache_zero(Elm_Gengrid_Data *sd)
171 {
172    int pmax = sd->item_cache_max;
173
174    sd->item_cache_max = 0;
175    _item_cache_clean(sd);
176    sd->item_cache_max = pmax;
177 }
178
179 // add an item to item cache
180 static Eina_Bool
181 _item_cache_add(Elm_Gen_Item *it)
182 {
183    if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
184
185    Item_Cache *itc = NULL;
186    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
187    Evas_Object *obj = sd->obj;
188
189    evas_event_freeze(evas_object_evas_get(obj));
190    if (sd->item_cache_max > 0)
191      itc = ELM_NEW(Item_Cache);
192    if (!_item_cache_push(sd, itc))
193      {
194         if (itc) ELM_SAFE_FREE(itc, free);
195
196         evas_event_thaw(evas_object_evas_get(obj));
197         evas_event_thaw_eval(evas_object_evas_get(obj));
198         return EINA_FALSE;
199      }
200
201    itc->spacer = it->spacer;
202    itc->base_view = VIEW(it);
203    itc->item_style = eina_stringshare_add(it->itc->item_style);
204
205    if (!it->group)
206      {
207         Eina_Bool tmp;
208         if (it->selected)
209           edje_object_signal_emit(itc->base_view, "elm,state,unselected", "elm");
210         if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
211           edje_object_signal_emit(itc->base_view, "elm,state,enabled", "elm");
212         if (it == (Elm_Gen_Item *)sd->focused_item &&
213             elm_widget_focus_highlight_enabled_get(obj))
214           edje_object_signal_emit(itc->base_view, "elm,state,unfocused", "elm");
215
216         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
217         // FIXME: other callbacks?
218         _item_mouse_callbacks_del(it, itc->base_view);
219      }
220
221    edje_object_mirrored_set(VIEW(it),
222                             elm_widget_mirrored_get(WIDGET(it)));
223    edje_object_scale_set(VIEW(it),
224                          elm_widget_scale_get(WIDGET(it))
225                          * elm_config_scale_get());
226
227    evas_object_hide(itc->base_view);
228    evas_object_move(itc->base_view, -9999, -9999);
229    it->spacer = NULL;
230    VIEW(it) = NULL;
231
232    _item_cache_clean(sd);
233
234    evas_event_thaw(evas_object_evas_get(obj));
235    evas_event_thaw_eval(evas_object_evas_get(obj));
236
237    return EINA_TRUE;
238 }
239
240 // find an item from item cache and remove it from the cache
241 static Eina_Bool
242 _item_cache_find(Elm_Gen_Item *it)
243 {
244    if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
245
246    Item_Cache *itc = NULL;
247    Eina_Inlist *l;
248    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
249
250    EINA_INLIST_FOREACH_SAFE(sd->item_cache, l, itc)
251      {
252         if (((!it->itc->item_style) && (!itc->item_style)) ||
253             (it->itc->item_style && itc->item_style &&
254              (!strcmp(it->itc->item_style, itc->item_style))))
255           {
256              itc = _item_cache_pop(sd, itc);
257              if (!itc) continue;
258
259              it->spacer = itc->spacer;
260              VIEW(it) = itc->base_view;
261              itc->spacer = NULL;
262              itc->base_view = NULL;
263
264              _item_cache_free(itc);
265              return EINA_TRUE;
266           }
267      }
268    return EINA_FALSE;
269 }
270
271 static Eina_Bool
272 _is_no_select(Elm_Gen_Item *it)
273 {
274    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
275
276    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
277        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
278        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
279        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
280      return EINA_TRUE;
281    return EINA_FALSE;
282 }
283
284 EOLIAN static Elm_Object_Item *
285 _elm_gengrid_search_by_text_item_get(Eo *obj EINA_UNUSED,
286                                      Elm_Gengrid_Data *sd,
287                                      Elm_Object_Item *eo_item_to_search_from,
288                                      const char *part_name,
289                                      const char *pattern,
290                                      Elm_Glob_Match_Flags flags)
291 {
292    Elm_Gen_Item *it = NULL;
293    char *str = NULL;
294    Eina_Inlist *start = NULL;
295    int fnflags = 0;
296
297    if (!pattern) return NULL;
298    if (!sd->items) return NULL;
299
300    if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE;
301    if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME;
302    if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD;
303 #ifdef FNM_CASEFOLD
304    if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD;
305 #endif
306
307    ELM_GENGRID_ITEM_DATA_GET(eo_item_to_search_from, item_to_search_from);
308    start = (item_to_search_from) ?
309      EINA_INLIST_GET(item_to_search_from) :
310      sd->items;
311    EINA_INLIST_FOREACH(start, it)
312      {
313         if (!it->itc->func.text_get) continue;
314         str = it->itc->func.text_get((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)),
315                                      WIDGET(it), part_name);
316         if (!str) continue;
317         if (!fnmatch(pattern, str, fnflags))
318           {
319              free(str);
320              return EO_OBJ(it);
321           }
322         free(str);
323      }
324    return NULL;
325 }
326
327 static void
328 _item_show_region(void *data)
329 {
330    Elm_Gengrid_Data *sd = data;
331    Evas_Coord cvw, cvh, it_xpos = 0, it_ypos = 0, col = 0, row = 0, minx = 0, miny = 0;
332    Evas_Coord vw = 0, vh = 0;
333    Elm_Object_Item *eo_it = NULL;
334    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
335
336    if ((cvw != 0) && (cvh != 0))
337        {
338           int x = 0, y = 0;
339           if (sd->show_region)
340             eo_it = sd->show_it;
341           else if (sd->bring_in)
342             eo_it = sd->bring_in_it;
343
344           if (!eo_it) return;
345           ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
346
347           eo_do(sd->pan_obj, elm_obj_pan_pos_min_get(&minx, &miny));
348           if (sd->horizontal && (sd->item_height > 0))
349             {
350                row = cvh / sd->item_height;
351                if (row <= 0) row = 1;
352                x = (it->position - 1) / row;
353                if (elm_widget_mirrored_get(sd->obj))
354                  {
355                     col = sd->item_count / row;
356                     if (sd->item_count % row == 0)
357                       col--;
358                     x = col - x;
359                  }
360
361                y = (it->position - 1) % row;
362                if (x >= 1)
363                  it_xpos = ((x - GG_IT(it)->prev_group) * sd->item_width)
364                     + (GG_IT(it)->prev_group * sd->group_item_width)
365                     + minx;
366                else it_xpos = minx;
367                miny = miny + ((cvh - (sd->item_height * row))
368                     * sd->align_y);
369                it_ypos = y * sd->item_height + miny;
370                it->x = x;
371                it->y = y;
372             }
373           else if (sd->item_width > 0)
374             {
375                col = cvw / sd->item_width;
376                if (col <= 0) col = 1;
377                y = (it->position - 1) / col;
378                x = (it->position - 1) % col;
379                it_xpos = x * sd->item_width + minx;
380                if (y >= 1)
381                  it_ypos = ((y - GG_IT(it)->prev_group) * sd->item_height)
382                     + (GG_IT(it)->prev_group * sd->group_item_height)
383                     + miny;
384                else it_ypos = miny;
385                minx = minx + ((cvw - (sd->item_width * col))
386                     * sd->align_x);
387                it->x = x;
388                it->y = y;
389             }
390
391           switch (sd->scroll_to_type)
392             {
393                case ELM_GENGRID_ITEM_SCROLLTO_TOP:
394                   eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
395                         (NULL, NULL, &vw, &vh));
396                   break;
397                case ELM_GENGRID_ITEM_SCROLLTO_MIDDLE:
398                   eo_do(WIDGET(it), elm_interface_scrollable_content_viewport_geometry_get
399                         (NULL, NULL, &vw, &vh));
400                   it_xpos = it_xpos - ((vw - sd->item_width) / 2);
401                   it_ypos = it_ypos - ((vh - sd->item_height) / 2);
402                   break;
403                default:
404                   vw = sd->item_width;
405                   vh = sd->item_height;
406                   break;
407             }
408
409           if (sd->show_region)
410             {
411                eo_do(WIDGET(it), elm_interface_scrollable_content_region_show(
412                                                      it_xpos, it_ypos, vw, vh));
413                sd->show_region = EINA_FALSE;
414             }
415           if (sd->bring_in)
416             {
417                eo_do(WIDGET(it), elm_interface_scrollable_region_bring_in(
418                                                  it_xpos, it_ypos, vw, vh));
419                sd->bring_in = EINA_FALSE;
420             }
421        }
422 }
423
424 static void
425 _calc_job(void *data)
426 {
427    ELM_GENGRID_DATA_GET(data, sd);
428    Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
429    Elm_Gen_Item *it, *group_item = NULL;
430    int count_group = 0;
431    long count = 0;
432
433    sd->items_lost = 0;
434
435    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
436
437    if ((cvw != 0) || (cvh != 0))
438      {
439         if ((sd->horizontal) && (sd->item_height > 0))
440           nmax = cvh / sd->item_height;
441         else if (sd->item_width > 0)
442           nmax = cvw / sd->item_width;
443
444         if (nmax < 1)
445           nmax = 1;
446
447         EINA_INLIST_FOREACH(sd->items, it)
448           {
449              if (GG_IT(it)->prev_group != count_group)
450                GG_IT(it)->prev_group = count_group;
451              if (it->group)
452                {
453                   count = count % nmax;
454                   if (count)
455                     sd->items_lost += nmax - count;
456                   count_group++;
457                   if (count) count = 0;
458                   group_item = it;
459                }
460              else
461                {
462                   if (it->parent != group_item)
463                     it->parent = group_item;
464                   count++;
465                }
466           }
467         count = sd->item_count + sd->items_lost - count_group;
468         if (sd->horizontal)
469           {
470              minw = (ceil(count / (float)nmax) * sd->item_width) +
471                (count_group * sd->group_item_width);
472              minh = nmax * sd->item_height;
473           }
474         else
475           {
476              minw = nmax * sd->item_width;
477              minh = (ceil(count / (float)nmax) * sd->item_height) +
478                (count_group * sd->group_item_height);
479           }
480
481         if ((minw != sd->minw) || (minh != sd->minh))
482           {
483              sd->minh = minh;
484              sd->minw = minw;
485              evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
486           }
487
488         sd->nmax = nmax;
489         evas_object_smart_changed(sd->pan_obj);
490
491         if (sd->show_region || sd->bring_in)
492           _item_show_region(sd);
493      }
494    sd->calc_job = NULL;
495 }
496
497 EOLIAN static void
498 _elm_gengrid_pan_eo_base_destructor(Eo *obj, Elm_Gengrid_Pan_Data *psd)
499 {
500    eo_data_unref(psd->wobj, psd->wsd);
501    eo_do_super(obj, MY_PAN_CLASS, eo_destructor());
502 }
503
504 EOLIAN static void
505 _elm_gengrid_pan_evas_object_smart_move(Eo *obj EINA_UNUSED, Elm_Gengrid_Pan_Data *psd, Evas_Coord _gen_param2 EINA_UNUSED, Evas_Coord _gen_param3 EINA_UNUSED)
506 {
507    ecore_job_del(psd->wsd->calc_job);
508    psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wobj);
509 }
510
511 EOLIAN static void
512 _elm_gengrid_pan_evas_object_smart_resize(Eo *obj, Elm_Gengrid_Pan_Data *psd, Evas_Coord w, Evas_Coord h)
513 {
514    Evas_Coord ow, oh;
515
516    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
517    if ((ow == w) && (oh == h)) return;
518    ecore_job_del(psd->wsd->calc_job);
519    psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wobj);
520 }
521
522 static void
523 _item_unselect(Elm_Gen_Item *it)
524 {
525    Elm_Gen_Item_Type *item = GG_IT(it);
526    Elm_Gengrid_Data *sd = item->wsd;
527    Elm_Object_Item *eo_it = EO_OBJ(it);
528
529    if ((it->generation < sd->generation) || (!it->selected))
530      return;
531
532    if (it->selected)
533      {
534         it->selected = EINA_FALSE;
535         sd->selected = eina_list_remove(sd->selected, eo_it);
536         evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, eo_it);
537      }
538 }
539
540 static void
541 _item_mouse_in_cb(void *data,
542                   Evas *evas EINA_UNUSED,
543                   Evas_Object *obj EINA_UNUSED,
544                   void *event_info EINA_UNUSED)
545 {
546    Elm_Gen_Item *it = data;
547    if (!elm_object_item_disabled_get(EO_OBJ(it)) &&
548        (_elm_config->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN))
549      elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
550 }
551
552 static void
553 _item_mouse_move_cb(void *data,
554                     Evas *evas EINA_UNUSED,
555                     Evas_Object *obj,
556                     void *event_info)
557 {
558    Elm_Gen_Item *it = data;
559    Evas_Event_Mouse_Move *ev = event_info;
560    Evas_Coord ox, oy, ow, oh, it_scrl_x, it_scrl_y;
561    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
562    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
563    Elm_Object_Item *eo_it = EO_OBJ(it);
564
565    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
566      {
567         if (!sd->on_hold)
568           {
569              sd->on_hold = EINA_TRUE;
570              if (!sd->was_selected)
571                {
572                   it->unhighlight_cb(it);
573                   it->unsel_cb(it);
574                }
575           }
576      }
577
578    if ((it->dragging) && (it->down))
579      {
580         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
581         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, eo_it);
582         return;
583      }
584
585    if ((!it->down) || (sd->longpressed))
586      {
587         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
588         if ((sd->reorder_mode) && (sd->reorder_it))
589           {
590              evas_object_geometry_get
591                (sd->pan_obj, &ox, &oy, &ow, &oh);
592
593              it_scrl_x = ev->cur.canvas.x - sd->reorder_it->dx;
594              it_scrl_y = ev->cur.canvas.y - sd->reorder_it->dy;
595
596              if (it_scrl_x < ox) sd->reorder_item_x = ox;
597              else if (it_scrl_x + sd->item_width > ox + ow)
598                sd->reorder_item_x = ox + ow - sd->item_width;
599              else sd->reorder_item_x = it_scrl_x;
600
601              if (it_scrl_y < oy) sd->reorder_item_y = oy;
602              else if (it_scrl_y + sd->item_height > oy + oh)
603                sd->reorder_item_y = oy + oh - sd->item_height;
604              else sd->reorder_item_y = it_scrl_y;
605
606              ecore_job_del(sd->calc_job);
607              sd->calc_job = ecore_job_add(_calc_job, sd->obj);
608           }
609         return;
610      }
611
612    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
613      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
614
615    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
616    x = ev->cur.canvas.x - x;
617    y = ev->cur.canvas.y - y;
618    dx = x - it->dx;
619    adx = dx;
620
621    if (adx < 0) adx = -dx;
622    dy = y - it->dy;
623    ady = dy;
624
625    if (ady < 0) ady = -dy;
626    minw /= 2;
627    minh /= 2;
628
629    if ((adx > minw) || (ady > minh))
630      {
631         const char *left_drag, *right_drag;
632
633         if (!elm_widget_mirrored_get(WIDGET(it)))
634           {
635              left_drag = SIG_DRAG_START_LEFT;
636              right_drag = SIG_DRAG_START_RIGHT;
637           }
638         else
639           {
640              left_drag = SIG_DRAG_START_RIGHT;
641              right_drag = SIG_DRAG_START_LEFT;
642           }
643
644         it->dragging = 1;
645         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
646         if (!sd->was_selected)
647           {
648              it->unhighlight_cb(it);
649              it->unsel_cb(it);
650           }
651
652         if (dy < 0)
653           {
654              if (ady > adx)
655                evas_object_smart_callback_call
656                  (WIDGET(it), SIG_DRAG_START_UP, eo_it);
657              else
658                {
659                   if (dx < 0)
660                     evas_object_smart_callback_call(WIDGET(it), left_drag, eo_it);
661                }
662           }
663         else
664           {
665              if (ady > adx)
666                evas_object_smart_callback_call
667                  (WIDGET(it), SIG_DRAG_START_DOWN, eo_it);
668              else
669                {
670                   if (dx < 0)
671                     evas_object_smart_callback_call(WIDGET(it), left_drag, eo_it);
672                   else
673                     evas_object_smart_callback_call
674                       (WIDGET(it), right_drag, eo_it);
675                }
676           }
677      }
678 }
679
680 static Eina_Bool
681 _long_press_cb(void *data)
682 {
683    Eina_Bool tmp;
684    Elm_Gen_Item *it = data;
685    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
686
687    it->long_timer = NULL;
688    if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()) || (it->dragging))
689      return ECORE_CALLBACK_CANCEL;
690    sd->longpressed = EINA_TRUE;
691    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, EO_OBJ(it));
692
693    if (sd->reorder_mode)
694      {
695         sd->reorder_it = it;
696         evas_object_raise(VIEW(it));
697         eo_do(WIDGET(it), elm_interface_scrollable_hold_set(EINA_TRUE));
698         eo_do(WIDGET(it), elm_interface_scrollable_bounce_allow_get(
699           &(sd->old_h_bounce),
700           &(sd->old_v_bounce)));
701
702         eo_do(WIDGET(it), elm_interface_scrollable_bounce_allow_set(EINA_FALSE, EINA_FALSE));
703         edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
704      }
705
706    return ECORE_CALLBACK_CANCEL;
707 }
708
709 static void
710 _item_highlight(Elm_Gen_Item *it)
711 {
712    const char *selectraise = NULL;
713    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
714
715    if (_is_no_select(it) ||
716        (!sd->highlight) || (it->highlighted) ||
717        (it->generation < sd->generation))
718      return;
719
720    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
721    evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, EO_OBJ(it));
722
723    selectraise = edje_object_data_get(VIEW(it), "selectraise");
724    if ((selectraise) && (!strcmp(selectraise, "on")))
725      evas_object_stack_above(VIEW(it), sd->stack);
726
727    it->highlighted = EINA_TRUE;
728 }
729
730 static void
731 _item_unhighlight(Elm_Gen_Item *it)
732 {
733    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
734    Elm_Object_Item *eo_it = EO_OBJ(it);
735
736    if (!it->highlighted ||
737        (it->generation < sd->generation))
738      return;
739
740    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
741    evas_object_smart_callback_call(WIDGET(it), SIG_UNHIGHLIGHTED, eo_it);
742
743    evas_object_stack_below(VIEW(it), sd->stack);
744
745    it->highlighted = EINA_FALSE;
746 }
747
748 static void
749 _item_mouse_down_cb(void *data,
750                     Evas *evas EINA_UNUSED,
751                     Evas_Object *obj,
752                     void *event_info)
753 {
754    Evas_Event_Mouse_Down *ev = event_info;
755    Elm_Gen_Item *it = data;
756    Evas_Coord x, y;
757    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
758
759    if (ev->button == 3)
760      {
761         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
762         it->dx = ev->canvas.x - x;
763         it->dy = ev->canvas.y - y;
764         return;
765      }
766
767    if (ev->button != 1) return;
768
769    it->down = 1;
770    sd->mouse_down = EINA_TRUE;
771    it->dragging = 0;
772    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
773    it->dx = ev->canvas.x - x;
774    it->dy = ev->canvas.y - y;
775    sd->longpressed = EINA_FALSE;
776
777    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
778      sd->on_hold = EINA_TRUE;
779    else sd->on_hold = EINA_FALSE;
780
781    if (sd->on_hold) return;
782
783    sd->was_selected = it->selected;
784    it->highlight_cb(it);
785    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
786      {
787         evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, EO_OBJ(it));
788         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, EO_OBJ(it));
789      }
790
791    evas_object_smart_callback_call(WIDGET(it), SIG_PRESSED, EO_OBJ(it));
792    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
793    if (it->realized)
794      it->long_timer = ecore_timer_add
795          (_elm_config->longpress_timeout, _long_press_cb, it);
796    else
797      it->long_timer = NULL;
798 }
799
800 static void
801 _item_text_realize(Elm_Gen_Item *it,
802                    Evas_Object *target,
803                    Eina_List **source,
804                    const char *parts)
805 {
806    const Eina_List *l;
807    const char *key;
808    char *s;
809
810    if (!it->itc->func.text_get) return;
811
812    if (!(*source))
813      *source = elm_widget_stringlist_get
814         (edje_object_data_get(target, "texts"));
815    EINA_LIST_FOREACH(*source, l, key)
816      {
817         if (parts && fnmatch(parts, key, FNM_PERIOD)) continue;
818
819         s = it->itc->func.text_get
820            ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
821         if (s)
822           {
823              edje_object_part_text_escaped_set(target, key, s);
824              free(s);
825           }
826         else
827           {
828              edje_object_part_text_set(target, key, "");
829           }
830         if (_elm_config->atspi_mode)
831           elm_interface_atspi_accessible_name_changed_signal_emit(EO_OBJ(it));
832      }
833 }
834
835 static void
836 _item_content_realize(Elm_Gen_Item *it,
837                       Evas_Object *target,
838                       Eina_List **contents,
839                       const char *src,
840                       const char *parts)
841 {
842    Eina_Bool tmp;
843    Evas_Object *content;
844
845    if (!parts)
846      {
847         EINA_LIST_FREE(*contents, content)
848           evas_object_del(content);
849      }
850    if (it->itc->func.content_get)
851      {
852         Eina_List *source;
853         const char *key;
854
855         source = elm_widget_stringlist_get(edje_object_data_get(target, src));
856
857         EINA_LIST_FREE(source, key)
858           {
859              if (parts && fnmatch(parts, key, FNM_PERIOD))
860                continue;
861
862              Evas_Object *old = edje_object_part_swallow_get(target, key);
863              if (old)
864                {
865                   *contents = eina_list_remove(*contents, old);
866                   evas_object_del(old);
867                }
868              content = NULL;
869              if (it->itc->func.content_get)
870                content = it->itc->func.content_get
871                   ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
872              if (!content) continue;
873              *contents = eina_list_append(*contents, content);
874              if (!edje_object_part_swallow(target, key, content))
875                {
876                   ERR("%s (%p) can not be swallowed into %s",
877                       evas_object_type_get(content), content, key);
878                   evas_object_hide(content);
879                   continue;
880                }
881              elm_widget_sub_object_add(WIDGET(it), content);
882              if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
883                elm_widget_disabled_set(content, EINA_TRUE);
884           }
885      }
886 }
887
888 static void
889 _item_state_realize(Elm_Gen_Item *it, Evas_Object *target, const char *parts)
890 {
891    Eina_List *src;
892    const char *key;
893    char buf[4096];
894
895    if (!it->itc->func.state_get) return;
896
897    src = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
898    EINA_LIST_FREE(src, key)
899      {
900         if (parts && fnmatch(parts, key, FNM_PERIOD)) continue;
901
902         Eina_Bool on = it->itc->func.state_get
903            ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
904
905         if (on)
906           {
907              snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
908              edje_object_signal_emit(target, buf, "elm");
909           }
910         else
911           {
912              snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
913              edje_object_signal_emit(target, buf, "elm");
914           }
915      }
916    edje_object_message_signal_process(target);
917 }
918
919 static void
920 _view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources,
921               Eina_List **contents)
922 {
923    if (!view) return;
924    if (sources) _item_text_realize(it, view, sources, NULL);
925    if (contents) _item_content_realize(it, view, contents, "contents", NULL);
926    _item_state_realize(it, view, NULL);
927 }
928
929 /**
930  * Apply the right style for the created item view.
931  */
932 static void
933 _view_style_update(Elm_Gen_Item *it, Evas_Object *view, const char *style)
934 {
935    char buf[1024];
936    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
937    snprintf(buf, sizeof(buf), "item/%s", style ? style : "default");
938
939    if (!elm_widget_theme_object_set(WIDGET(it), view,
940                                     "gengrid", buf,
941                                     elm_widget_style_get(WIDGET(it))))
942      {
943         ERR("%s is not a valid gengrid item style. "
944             "Automatically falls back into default style.",
945             style);
946         elm_widget_theme_object_set
947           (WIDGET(it), view, "gengrid", "item/default", "default");
948      }
949
950    edje_object_mirrored_set(view, elm_widget_mirrored_get(WIDGET(it)));
951    edje_object_scale_set(view, elm_widget_scale_get(WIDGET(it)) *
952                          elm_config_scale_get());
953    evas_object_stack_below(view, sd->stack);
954 }
955
956 /**
957  * Create a VIEW(it) during _item_realize()
958  */
959 static Evas_Object *
960 _view_create(Elm_Gen_Item *it, const char *style)
961 {
962    Evas_Object *view = edje_object_add(evas_object_evas_get(WIDGET(it)));
963    evas_object_smart_member_add(view, GG_IT(it)->wsd->pan_obj);
964    elm_widget_sub_object_add(WIDGET(it), view);
965    edje_object_scale_set(view, elm_widget_scale_get(WIDGET(it)) *
966                          elm_config_scale_get());
967
968    _view_style_update(it, view, style);
969    return view;
970 }
971
972 static void
973 _view_clear(Evas_Object *view, Eina_List **texts, Eina_List **contents)
974 {
975    const char *part;
976    Evas_Object *c;
977    const Eina_List *l;
978
979    EINA_LIST_FOREACH(*texts, l, part)
980      edje_object_part_text_set(view, part, NULL);
981    ELM_SAFE_FREE(*texts, elm_widget_stringlist_free);
982
983    EINA_LIST_FREE(*contents, c)
984      evas_object_del(c);
985 }
986
987 static void
988 _elm_gengrid_item_unrealize(Elm_Gen_Item *it,
989                             Eina_Bool calc)
990 {
991    if (!it->realized) return;
992    if (GG_IT(it)->wsd->reorder_it == it) return;
993
994    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
995    if (!calc)
996      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, EO_OBJ(it));
997    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
998
999    _view_clear(VIEW(it), &(it->texts), &(it->contents));
1000
1001    ELM_SAFE_FREE(it->states, elm_widget_stringlist_free);
1002    eo_do(EO_OBJ(it), elm_wdg_item_track_cancel());
1003
1004    it->unrealize_cb(it);
1005
1006    it->realized = EINA_FALSE;
1007    it->want_unrealize = EINA_FALSE;
1008
1009    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
1010    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
1011 }
1012
1013 static void
1014 _item_mouse_up_cb(void *data,
1015                   Evas *evas EINA_UNUSED,
1016                   Evas_Object *obj EINA_UNUSED,
1017                   void *event_info)
1018 {
1019    Eina_Bool tmp;
1020    Evas_Event_Mouse_Up *ev = event_info;
1021    Eina_Bool dragged = EINA_FALSE;
1022    Elm_Gen_Item *it = data;
1023    Elm_Object_Item *eo_it = EO_OBJ(it);
1024    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
1025    Evas_Coord x, y, dx, dy;
1026
1027    if ((ev->button == 3) && (!it->dragging))
1028      {
1029         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1030         dx = it->dx - (ev->canvas.x - x);
1031         dy = it->dy - (ev->canvas.y - y);
1032         if (dx < 0) dx = -dx;
1033         if (dy < 0) dy = -dy;
1034         if ((dx < 5) && (dy < 5))
1035           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_RIGHT, EO_OBJ(it));
1036         return;
1037      }
1038
1039    if (ev->button != 1) return;
1040
1041    it->down = EINA_FALSE;
1042    sd->mouse_down = EINA_FALSE;
1043    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1044      sd->on_hold = EINA_TRUE;
1045    else sd->on_hold = EINA_FALSE;
1046
1047    evas_object_smart_callback_call(WIDGET(it), SIG_RELEASED, eo_it);
1048    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1049    if (it->dragging)
1050      {
1051         it->dragging = EINA_FALSE;
1052         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, eo_it);
1053         dragged = EINA_TRUE;
1054      }
1055    if (sd->on_hold)
1056      {
1057         sd->longpressed = EINA_FALSE;
1058         sd->on_hold = EINA_FALSE;
1059         return;
1060      }
1061    if ((sd->reorder_mode) &&
1062        (sd->reorder_it))
1063      {
1064         evas_object_smart_callback_call
1065           (WIDGET(it), SIG_MOVED, EO_OBJ(sd->reorder_it));
1066         sd->reorder_it = NULL;
1067         sd->move_effect_enabled = EINA_FALSE;
1068         ecore_job_del(sd->calc_job);
1069         sd->calc_job =
1070           ecore_job_add(_calc_job, sd->obj);
1071
1072         eo_do(WIDGET(it), elm_interface_scrollable_hold_set(EINA_FALSE));
1073         eo_do(WIDGET(it), elm_interface_scrollable_bounce_allow_set(
1074               sd->old_h_bounce, sd->old_v_bounce));
1075
1076         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1077      }
1078    if (sd->longpressed)
1079      {
1080         sd->longpressed = EINA_FALSE;
1081         if (!sd->was_selected)
1082           {
1083              it->unhighlight_cb(it);
1084              it->unsel_cb(it);
1085           }
1086         sd->was_selected = EINA_FALSE;
1087         return;
1088      }
1089    if (dragged)
1090      {
1091         if (it->want_unrealize)
1092           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1093      }
1094
1095    if (eo_do_ret(eo_it, tmp, elm_wdg_item_disabled_get()) || (dragged)) return;
1096
1097    if (sd->focused_item != eo_it)
1098      elm_object_item_focus_set(eo_it, EINA_TRUE);
1099
1100    if (sd->multi &&
1101        ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
1102         (evas_key_modifier_is_set(ev->modifiers, "Control"))))
1103      {
1104         if (!it->selected)
1105           {
1106              it->highlight_cb(it);
1107              it->sel_cb(it);
1108           }
1109         else
1110           {
1111              it->unhighlight_cb(it);
1112              it->unsel_cb(it);
1113           }
1114      }
1115    else
1116      {
1117         if (!it->selected)
1118           {
1119              while (sd->selected)
1120                {
1121                   Elm_Object_Item *eo_sel = sd->selected->data;
1122                   Elm_Gen_Item *sel = eo_data_scope_get(eo_sel, ELM_GENGRID_ITEM_CLASS);
1123                   it->unhighlight_cb(sel);
1124                   it->unsel_cb(sel);
1125                }
1126           }
1127         else
1128           {
1129              const Eina_List *l, *l_next;
1130              Elm_Object_Item *eo_item2;
1131
1132              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_item2)
1133                {
1134                   ELM_GENGRID_ITEM_DATA_GET(eo_item2, item2);
1135                   if (item2 != it)
1136                     {
1137                        it->unhighlight_cb(item2);
1138                        it->unsel_cb(item2);
1139                     }
1140                }
1141           }
1142         it->highlight_cb(it);
1143         it->sel_cb(it);
1144      }
1145 }
1146
1147 static void
1148 _item_mouse_callbacks_add(Elm_Gen_Item *it,
1149                           Evas_Object *view)
1150 {
1151    evas_object_event_callback_add
1152      (view, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in_cb, it);
1153    evas_object_event_callback_add
1154      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
1155    evas_object_event_callback_add
1156      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
1157    evas_object_event_callback_add
1158      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
1159 }
1160
1161 static void
1162 _item_mouse_callbacks_del(Elm_Gen_Item *it,
1163                           Evas_Object *view)
1164 {
1165    evas_object_event_callback_del_full
1166      (view, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in_cb, it);
1167    evas_object_event_callback_del_full
1168      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
1169    evas_object_event_callback_del_full
1170      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
1171    evas_object_event_callback_del_full
1172      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
1173 }
1174
1175
1176
1177 static void
1178 _elm_gengrid_item_index_update(Elm_Gen_Item *it)
1179 {
1180    if (it->position_update)
1181      {
1182         evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, EO_OBJ(it));
1183         it->position_update = EINA_FALSE;
1184      }
1185 }
1186
1187 static void
1188 _item_unrealize_cb(Elm_Gen_Item *it)
1189 {
1190    if (!_item_cache_add(it))
1191      {
1192         ELM_SAFE_FREE(VIEW(it), evas_object_del);
1193         ELM_SAFE_FREE(it->spacer, evas_object_del);
1194      }
1195 }
1196
1197 static char *
1198 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
1199 {
1200    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1201    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
1202
1203    if (it->itc->func.text_get)
1204      {
1205         const Eina_List *l;
1206         const char *key;
1207
1208         if (!(it->texts)) it->texts =
1209           elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
1210
1211         EINA_LIST_FOREACH(it->texts, l, key)
1212           {
1213              char *s = it->itc->func.text_get
1214                 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
1215              return s;
1216           }
1217      }
1218
1219    return NULL;
1220 }
1221
1222 static char *
1223 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
1224 {
1225    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1226    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
1227
1228    if (it->base->disabled)
1229      return strdup(E_("State: Disabled"));
1230
1231    return NULL;
1232 }
1233
1234 static void
1235 _access_on_highlight_cb(void *data)
1236 {
1237    Evas_Coord x, y, w, h;
1238    Evas_Coord sx, sy, sw, sh;
1239    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1240    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
1241
1242    evas_object_geometry_get(it->base->view, &x, &y, &w, &h);
1243
1244    evas_object_geometry_get(it->base->widget, &sx, &sy, &sw, &sh);
1245    if ((x < sx) || (y < sy) || ((x + w) > (sx + sw)) || ((y + h) > (sy + sh)))
1246      elm_gengrid_item_bring_in(EO_OBJ(it),
1247                                ELM_GENGRID_ITEM_SCROLLTO_IN);
1248 }
1249
1250 static void
1251 _access_widget_item_register(Elm_Gen_Item *it)
1252 {
1253    Elm_Access_Info *ai;
1254
1255    _elm_access_widget_item_register(it->base);
1256
1257    ai = _elm_access_info_get(it->base->access_obj);
1258
1259    _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Gengrid Item"));
1260    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
1261    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
1262    _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, it);
1263 }
1264
1265 static void
1266 _item_realize(Elm_Gen_Item *it)
1267 {
1268    Eina_Bool tmp;
1269    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
1270    Elm_Object_Item *eo_it = EO_OBJ(it);
1271
1272    if ((it->realized) ||
1273        (it->generation < sd->generation))
1274      return;
1275
1276    if (!_item_cache_find(it))
1277      {
1278         VIEW(it) = _view_create(it, it->itc->item_style);
1279         if (it->item->nocache_once)
1280           it->item->nocache_once = EINA_FALSE;
1281      }
1282
1283    if (it->spacer && edje_object_part_exists(VIEW(it), "elm.swallow.pad"))
1284      {
1285         it->spacer =
1286            evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1287         evas_object_color_set(it->spacer, 0, 0, 0, 0);
1288         elm_widget_sub_object_add(WIDGET(it), it->spacer);
1289         evas_object_size_hint_min_set(it->spacer, 2 * elm_config_scale_get(), 1);
1290         edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1291      }
1292
1293    /* access */
1294    if (_elm_config->access_mode) _access_widget_item_register(it);
1295
1296    /* infate texts, contents and states of view object */
1297    _view_inflate(VIEW(it), it, &it->texts, &it->contents);
1298
1299    if (it->group)
1300      {
1301         if ((!sd->group_item_width)
1302             && (!sd->group_item_height))
1303           {
1304              edje_object_size_min_restricted_calc
1305                (VIEW(it), &sd->group_item_width,
1306                &sd->group_item_height,
1307                sd->group_item_width,
1308                sd->group_item_height);
1309           }
1310      }
1311    else
1312      {
1313         if ((!sd->item_width)
1314             && (!sd->item_height))
1315           {
1316              edje_object_size_min_restricted_calc
1317                (VIEW(it), &sd->item_width,
1318                &sd->item_height,
1319                sd->item_width,
1320                sd->item_height);
1321              elm_coords_finger_size_adjust
1322                (1, &sd->item_width, 1,
1323                &sd->item_height);
1324           }
1325
1326         _item_mouse_callbacks_add(it, VIEW(it));
1327         _elm_gengrid_item_index_update(it);
1328
1329         if (it->selected)
1330           edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
1331         if (eo_do_ret(eo_it, tmp, elm_wdg_item_disabled_get()))
1332           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
1333      }
1334    edje_object_message_signal_process(VIEW(it));
1335    evas_object_show(VIEW(it));
1336
1337    if (it->tooltip.content_cb)
1338      {
1339         eo_do(eo_it,
1340               elm_wdg_item_tooltip_content_cb_set(
1341                  it->tooltip.content_cb, it->tooltip.data, NULL),
1342               elm_wdg_item_tooltip_style_set(it->tooltip.style),
1343               elm_wdg_item_tooltip_window_mode_set(it->tooltip.free_size));
1344      }
1345
1346    if (it->mouse_cursor)
1347      eo_do(eo_it, elm_wdg_item_cursor_set(it->mouse_cursor));
1348
1349    if (it->cursor_engine_only)
1350      eo_do(eo_it, elm_wdg_item_cursor_engine_only_set(it->cursor_engine_only));
1351
1352    if (eo_it == sd->focused_item)
1353      {
1354         const char *focus_raise;
1355         if (elm_widget_focus_highlight_enabled_get(WIDGET(it)))
1356           {
1357              edje_object_signal_emit
1358                 (VIEW(it), "elm,state,focused", "elm");
1359           }
1360
1361         focus_raise = edje_object_data_get(VIEW(it), "focusraise");
1362         if ((focus_raise) && (!strcmp(focus_raise, "on")))
1363           evas_object_raise(VIEW(it));
1364
1365         _elm_widget_item_highlight_in_theme(WIDGET(it), EO_OBJ(it));
1366         _elm_widget_highlight_in_theme_update(WIDGET(it));
1367         _elm_widget_focus_highlight_start(WIDGET(it));
1368      }
1369
1370    it->realized = EINA_TRUE;
1371    it->want_unrealize = EINA_FALSE;
1372 }
1373
1374 static Eina_Bool
1375 _reorder_item_move_animator_cb(void *data)
1376 {
1377    Elm_Gen_Item *it = data;
1378    Evas_Coord dx, dy;
1379    double tt, t;
1380    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
1381
1382    tt = REORDER_EFFECT_TIME;
1383    t = ((0.0 > (t = ecore_loop_time_get() -
1384                   GG_IT(it)->moving_effect_start_time)) ? 0.0 : t);
1385    dx = ((GG_IT(it)->tx - GG_IT(it)->ox) / 10)
1386      * elm_config_scale_get();
1387    dy = ((GG_IT(it)->ty - GG_IT(it)->oy) / 10)
1388      * elm_config_scale_get();
1389
1390    if (t <= tt)
1391      {
1392         GG_IT(it)->rx += (1 * sin((t / tt) * (M_PI / 2)) * dx);
1393         GG_IT(it)->ry += (1 * sin((t / tt) * (M_PI / 2)) * dy);
1394      }
1395    else
1396      {
1397         GG_IT(it)->rx += dx;
1398         GG_IT(it)->ry += dy;
1399      }
1400
1401    if (((dx > 0) && (GG_IT(it)->rx >= GG_IT(it)->tx)) ||
1402         ((dx <= 0) && (GG_IT(it)->rx <= GG_IT(it)->tx))
1403        || ((dy > 0) && (GG_IT(it)->ry >= GG_IT(it)->ty)) ||
1404            ((dy <= 0) && (GG_IT(it)->ry <= GG_IT(it)->ty)))
1405      {
1406         evas_object_move(VIEW(it), GG_IT(it)->tx, GG_IT(it)->ty);
1407         if (it->group)
1408           {
1409              Evas_Coord vw, vh;
1410
1411              evas_object_geometry_get
1412                (sd->pan_obj, NULL, NULL, &vw, &vh);
1413              if (sd->horizontal)
1414                evas_object_resize
1415                  (VIEW(it), sd->group_item_width, vh);
1416              else
1417                evas_object_resize
1418                  (VIEW(it), vw, sd->group_item_height);
1419           }
1420         else
1421           evas_object_resize(VIEW(it), sd->item_width, sd->item_height);
1422         GG_IT(it)->moving = EINA_FALSE;
1423         GG_IT(it)->item_reorder_move_animator = NULL;
1424
1425         return ECORE_CALLBACK_CANCEL;
1426      }
1427
1428    evas_object_move(VIEW(it), GG_IT(it)->rx, GG_IT(it)->ry);
1429    if (it->group)
1430      {
1431         Evas_Coord vw, vh;
1432
1433         evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
1434         if (sd->horizontal)
1435           evas_object_resize(VIEW(it), sd->group_item_width, vh);
1436         else
1437           evas_object_resize(VIEW(it), vw, sd->group_item_height);
1438      }
1439    else
1440      evas_object_resize(VIEW(it), sd->item_width, sd->item_height);
1441
1442    return ECORE_CALLBACK_RENEW;
1443 }
1444
1445 static void
1446 _item_place(Elm_Gen_Item *it,
1447             Evas_Coord cx,
1448             Evas_Coord cy)
1449 {
1450    Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh, iw, ih, ww;
1451    Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
1452    Eina_Bool reorder_item_move_forward = EINA_FALSE;
1453    Eina_Bool was_realized;
1454    Elm_Gen_Item_Type *item;
1455    long items_count;
1456    int item_pos;
1457
1458    item = GG_IT(it);
1459    ELM_GENGRID_DATA_GET_FROM_ITEM(it, wsd);
1460
1461    it->x = cx;
1462    it->y = cy;
1463    evas_object_geometry_get(wsd->pan_obj, &ox, &oy, &vw, &vh);
1464
1465    /* Preload rows/columns at each side of the Gengrid */
1466    cvx = ox - PRELOAD * wsd->item_width;
1467    cvy = oy - PRELOAD * wsd->item_height;
1468    cvw = vw + 2 * PRELOAD * wsd->item_width;
1469    cvh = vh + 2 * PRELOAD * wsd->item_height;
1470
1471    items_count = wsd->item_count -
1472      eina_list_count(wsd->group_items) + wsd->items_lost;
1473    if (wsd->horizontal)
1474      {
1475         int columns, items_visible = 0, items_row;
1476
1477         if (wsd->item_height > 0)
1478           items_visible = vh / wsd->item_height;
1479         if (items_visible < 1)
1480           items_visible = 1;
1481
1482         columns = items_count / items_visible;
1483         if (items_count % items_visible)
1484           columns++;
1485
1486         tcw = (wsd->item_width * columns) + (wsd->group_item_width *
1487                                              eina_list_count(wsd->group_items));
1488         alignw = (vw - tcw) * wsd->align_x;
1489
1490         items_row = items_visible;
1491         if ((unsigned int)items_row > wsd->item_count)
1492           items_row = wsd->item_count;
1493         if (wsd->filled && (unsigned int)wsd->nmax
1494             > (unsigned int)wsd->item_count)
1495           tch = wsd->nmax * wsd->item_height;
1496         else
1497           tch = items_row * wsd->item_height;
1498         alignh = (vh - tch) * wsd->align_y;
1499         item_pos = items_row * cx + cy + 1;
1500         if (item_pos != it->position)
1501           {
1502              it->position = item_pos;
1503              it->position_update = EINA_TRUE;
1504           }
1505      }
1506    else
1507      {
1508         unsigned int rows, items_visible = 0, items_col;
1509
1510         if (wsd->item_width > 0)
1511           items_visible = vw / wsd->item_width;
1512         if (items_visible < 1)
1513           items_visible = 1;
1514
1515         rows = items_count / items_visible;
1516         if (items_count % items_visible)
1517           rows++;
1518
1519         tch = (wsd->item_height * rows) + (wsd->group_item_height *
1520                                            eina_list_count(wsd->group_items));
1521         alignh = (vh - tch) * wsd->align_y;
1522
1523         items_col = items_visible;
1524         if (items_col > wsd->item_count)
1525           items_col = wsd->item_count;
1526         if (wsd->filled && (unsigned int)wsd->nmax
1527             > (unsigned int)wsd->item_count)
1528           tcw = wsd->nmax * wsd->item_width;
1529         else
1530           tcw = items_col * wsd->item_width;
1531         alignw = (vw - tcw) * wsd->align_x;
1532         item_pos = cx + items_col * cy + 1;
1533         if (item_pos != it->position)
1534           {
1535              it->position = item_pos;
1536              it->position_update = EINA_TRUE;
1537           }
1538      }
1539
1540    if (it->group)
1541      {
1542         if (wsd->horizontal)
1543           {
1544              x = (((cx - item->prev_group) * wsd->item_width)
1545                   + (item->prev_group * wsd->group_item_width)) -
1546                wsd->pan_x + ox + alignw;
1547              y = oy;
1548              iw = wsd->group_item_width;
1549              ih = vh;
1550           }
1551         else
1552           {
1553              x = ox;
1554              y = (((cy - item->prev_group) * wsd->item_height)
1555                   + (item->prev_group * wsd->group_item_height))
1556                - wsd->pan_y + oy + alignh;
1557              iw = vw;
1558              ih = wsd->group_item_height;
1559           }
1560         item->gx = x;
1561         item->gy = y;
1562      }
1563    else
1564      {
1565         if (wsd->horizontal)
1566           {
1567              x = (((cx - item->prev_group) * wsd->item_width)
1568                   + (item->prev_group * wsd->group_item_width)) -
1569                wsd->pan_x + ox + alignw;
1570              y = (cy * wsd->item_height) - wsd->pan_y + oy + alignh;
1571           }
1572         else
1573           {
1574              x = (cx * wsd->item_width) - wsd->pan_x + ox + alignw;
1575              y = (((cy - item->prev_group)
1576                    * wsd->item_height) + (item->prev_group *
1577                                           wsd->group_item_height)) -
1578                wsd->pan_y + oy + alignh;
1579           }
1580         if (elm_widget_mirrored_get(WIDGET(it))) /* Switch items side
1581                                                   * and componsate for
1582                                                   * pan_x when in RTL
1583                                                   * mode */
1584           {
1585              evas_object_geometry_get(WIDGET(it), NULL, NULL, &ww, NULL);
1586              x = ww - x - wsd->item_width - wsd->pan_x - wsd->pan_x + ox + ox;
1587           }
1588         iw = wsd->item_width;
1589         ih = wsd->item_height;
1590      }
1591
1592    was_realized = it->realized;
1593    if (ELM_RECTS_INTERSECT(x, y, iw, ih, cvx, cvy, cvw, cvh))
1594      {
1595         _item_realize(it);
1596         if (!was_realized)
1597           evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, EO_OBJ(it));
1598         if (it->parent)
1599           {
1600              if (wsd->horizontal)
1601                {
1602                   if (it->parent->item->gx < ox)
1603                     {
1604                        it->parent->item->gx = x + wsd->item_width -
1605                          wsd->group_item_width;
1606                        if (it->parent->item->gx > ox)
1607                          it->parent->item->gx = ox;
1608                     }
1609                   it->parent->item->group_realized = EINA_TRUE;
1610                }
1611              else
1612                {
1613                   if (it->parent->item->gy < oy)
1614                     {
1615                        it->parent->item->gy = y + wsd->item_height -
1616                          wsd->group_item_height;
1617                        if (it->parent->item->gy > oy)
1618                          it->parent->item->gy = oy;
1619                     }
1620                   it->parent->item->group_realized = EINA_TRUE;
1621                }
1622           }
1623         if (wsd->reorder_mode)
1624           {
1625              if (wsd->reorder_it)
1626                {
1627                   if (item->moving) return;
1628
1629                   if (!wsd->move_effect_enabled)
1630                     {
1631                        item->ox = x;
1632                        item->oy = y;
1633                     }
1634                   if (wsd->reorder_it == it)
1635                     {
1636                        evas_object_move(VIEW(it), wsd->reorder_item_x,
1637                                         wsd->reorder_item_y);
1638                        evas_object_resize(VIEW(it), iw, ih);
1639                        return;
1640                     }
1641                   else
1642                     {
1643                        Evas_Coord nx, ny, nw, nh;
1644
1645                        if (wsd->move_effect_enabled)
1646                          {
1647                             if ((item->ox != x) || (item->oy != y))
1648                               if (((wsd->old_pan_x == wsd->pan_x)
1649                                    && (wsd->old_pan_y == wsd->pan_y))
1650                                   || ((wsd->old_pan_x != wsd->pan_x) &&
1651                                       !(item->ox - wsd->pan_x
1652                                         + wsd->old_pan_x == x)) ||
1653                                   ((wsd->old_pan_y != wsd->pan_y) &&
1654                                    !(item->oy - wsd->pan_y +
1655                                      wsd->old_pan_y == y)))
1656                                 {
1657                                    item->tx = x;
1658                                    item->ty = y;
1659                                    item->rx = item->ox;
1660                                    item->ry = item->oy;
1661                                    item->moving = EINA_TRUE;
1662                                    item->moving_effect_start_time =
1663                                      ecore_loop_time_get();
1664                                    item->item_reorder_move_animator =
1665                                      ecore_animator_add
1666                                        (_reorder_item_move_animator_cb, it);
1667                                    return;
1668                                 }
1669                          }
1670
1671                        /* need fix here */
1672                        if (it->group)
1673                          {
1674                             if (wsd->horizontal)
1675                               {
1676                                  nx = x + (wsd->group_item_width / 2);
1677                                  ny = y;
1678                                  nw = 1;
1679                                  nh = vh;
1680                               }
1681                             else
1682                               {
1683                                  nx = x;
1684                                  ny = y + (wsd->group_item_height / 2);
1685                                  nw = vw;
1686                                  nh = 1;
1687                               }
1688                          }
1689                        else
1690                          {
1691                             nx = x + (wsd->item_width / 2);
1692                             ny = y + (wsd->item_height / 2);
1693                             nw = 1;
1694                             nh = 1;
1695                          }
1696
1697                        if (ELM_RECTS_INTERSECT
1698                              (wsd->reorder_item_x, wsd->reorder_item_y,
1699                              wsd->item_width, wsd->item_height,
1700                              nx, ny, nw, nh))
1701                          {
1702                             if (wsd->horizontal)
1703                               {
1704                                  if ((wsd->nmax * wsd->reorder_it->x +
1705                                       wsd->reorder_it->y) >
1706                                      (wsd->nmax * it->x + it->y))
1707                                    reorder_item_move_forward = EINA_TRUE;
1708                               }
1709                             else
1710                               {
1711                                  if ((wsd->nmax * wsd->reorder_it->y +
1712                                       wsd->reorder_it->x) >
1713                                      (wsd->nmax * it->y + it->x))
1714                                    reorder_item_move_forward = EINA_TRUE;
1715                               }
1716
1717                             wsd->items = eina_inlist_remove
1718                                 (wsd->items,
1719                                 EINA_INLIST_GET(wsd->reorder_it));
1720                             if (reorder_item_move_forward)
1721                               wsd->items = eina_inlist_prepend_relative
1722                                   (wsd->items,
1723                                   EINA_INLIST_GET(wsd->reorder_it),
1724                                   EINA_INLIST_GET(it));
1725                             else
1726                               wsd->items = eina_inlist_append_relative
1727                                   (wsd->items,
1728                                   EINA_INLIST_GET(wsd->reorder_it),
1729                                   EINA_INLIST_GET(it));
1730
1731                             wsd->reorder_item_changed = EINA_TRUE;
1732                             wsd->move_effect_enabled = EINA_TRUE;
1733                             ecore_job_del(wsd->calc_job);
1734                             wsd->calc_job =
1735                               ecore_job_add(_calc_job, wsd->obj);
1736
1737                             return;
1738                          }
1739                     }
1740                }
1741              else if (item->item_reorder_move_animator)
1742                {
1743                   ELM_SAFE_FREE(item->item_reorder_move_animator,
1744                                 ecore_animator_del);
1745                   item->moving = EINA_FALSE;
1746                }
1747           }
1748         if (!it->group)
1749           {
1750              evas_object_move(VIEW(it), x, y);
1751              evas_object_resize(VIEW(it), iw, ih);
1752           }
1753         else
1754           item->group_realized = EINA_TRUE;
1755      }
1756    else
1757      {
1758         if (!it->group)
1759           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1760         else
1761           item->group_realized = EINA_FALSE;
1762      }
1763 }
1764
1765 static void
1766 _group_item_place(Elm_Gengrid_Pan_Data *psd)
1767 {
1768    Evas_Coord iw, ih, vw, vh;
1769    Eina_Bool was_realized;
1770    Elm_Gen_Item *it;
1771    Eina_List *l;
1772
1773    evas_object_geometry_get(psd->wsd->pan_obj, NULL, NULL, &vw, &vh);
1774    if (psd->wsd->horizontal)
1775      {
1776         iw = psd->wsd->group_item_width;
1777         ih = vh;
1778      }
1779    else
1780      {
1781         iw = vw;
1782         ih = psd->wsd->group_item_height;
1783      }
1784    EINA_LIST_FOREACH(psd->wsd->group_items, l, it)
1785      {
1786         was_realized = it->realized;
1787         if (GG_IT(it)->group_realized)
1788           {
1789              _item_realize(it);
1790              if (!was_realized)
1791                evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, EO_OBJ(it));
1792              evas_object_move
1793                (VIEW(it), GG_IT(it)->gx,
1794                GG_IT(it)->gy);
1795              evas_object_resize(VIEW(it), iw, ih);
1796              evas_object_raise(VIEW(it));
1797           }
1798         else
1799           _elm_gengrid_item_unrealize(it, EINA_FALSE);
1800      }
1801 }
1802
1803 EOLIAN static void
1804 _elm_gengrid_pan_evas_object_smart_calculate(Eo *obj EINA_UNUSED, Elm_Gengrid_Pan_Data *psd)
1805 {
1806    Evas_Coord cx = 0, cy = 0;
1807    Elm_Gen_Item *it;
1808
1809    Elm_Gengrid_Data *sd = psd->wsd;
1810
1811    if (!sd->nmax) return;
1812
1813    sd->reorder_item_changed = EINA_FALSE;
1814
1815    EINA_INLIST_FOREACH(sd->items, it)
1816      {
1817         if (it->group)
1818           {
1819              if (sd->horizontal)
1820                {
1821                   if (cy)
1822                     {
1823                        cx++;
1824                        cy = 0;
1825                     }
1826                }
1827              else
1828                {
1829                   if (cx)
1830                     {
1831                        cx = 0;
1832                        cy++;
1833                     }
1834                }
1835           }
1836
1837         _item_place(it, cx, cy);
1838         if (sd->reorder_item_changed) return;
1839         if (it->group)
1840           {
1841              if (sd->horizontal)
1842                {
1843                   cx++;
1844                   cy = 0;
1845                }
1846              else
1847                {
1848                   cx = 0;
1849                   cy++;
1850                }
1851           }
1852         else
1853           {
1854              if (sd->horizontal)
1855                {
1856                   cy = (cy + 1) % sd->nmax;
1857                   if (!cy) cx++;
1858                }
1859              else
1860                {
1861                   cx = (cx + 1) % sd->nmax;
1862                   if (!cx) cy++;
1863                }
1864           }
1865      }
1866    _group_item_place(psd);
1867
1868    if ((sd->reorder_mode) && (sd->reorder_it))
1869      {
1870         if (!sd->reorder_item_changed)
1871           {
1872              sd->old_pan_x = sd->pan_x;
1873              sd->old_pan_y = sd->pan_y;
1874           }
1875         sd->move_effect_enabled = EINA_FALSE;
1876      }
1877
1878    evas_object_smart_callback_call
1879      (psd->wobj, SIG_CHANGED, NULL);
1880
1881    if (sd->focused_item)
1882      _elm_widget_focus_highlight_start(psd->wobj);
1883 }
1884
1885 EOLIAN static void
1886 _elm_gengrid_pan_elm_pan_pos_set(Eo *obj, Elm_Gengrid_Pan_Data *psd, Evas_Coord x, Evas_Coord y)
1887 {
1888    if ((x == psd->wsd->pan_x) && (y == psd->wsd->pan_y)) return;
1889    psd->wsd->pan_x = x;
1890    psd->wsd->pan_y = y;
1891    evas_object_smart_changed(obj);
1892 }
1893
1894 EOLIAN static void
1895 _elm_gengrid_pan_elm_pan_pos_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
1896 {
1897    if (x) *x = psd->wsd->pan_x;
1898    if (y) *y = psd->wsd->pan_y;
1899 }
1900
1901 EOLIAN static void
1902 _elm_gengrid_pan_elm_pan_content_size_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Pan_Data *psd, Evas_Coord *w, Evas_Coord *h)
1903 {
1904    if (w) *w = psd->wsd->minw;
1905    if (h) *h = psd->wsd->minh;
1906 }
1907
1908 EOLIAN static void
1909 _elm_gengrid_pan_elm_pan_pos_max_get(Eo *obj, Elm_Gengrid_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
1910 {
1911    Evas_Coord ow, oh;
1912
1913    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1914    if (x)
1915      *x = (ow < psd->wsd->minw) ? psd->wsd->minw - ow : 0;
1916    if (y)
1917      *y = (oh < psd->wsd->minh) ? psd->wsd->minh - oh : 0;
1918 }
1919
1920 EOLIAN static void
1921 _elm_gengrid_pan_elm_pan_pos_min_get(Eo *obj, Elm_Gengrid_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
1922 {
1923    Evas_Coord mx = 0, my = 0;
1924    Eina_Bool mirrored = elm_widget_mirrored_get(psd->wsd->obj);
1925
1926    eo_do(obj, elm_obj_pan_pos_max_get(&mx, &my));
1927    if (x)
1928      *x = -mx * (mirrored ? 1 - psd->wsd->align_x : psd->wsd->align_x);
1929    if (y)
1930      *y = -my * psd->wsd->align_y;
1931 }
1932
1933 EOLIAN static void
1934 _elm_gengrid_pan_class_constructor(Eo_Class *klass)
1935 {
1936    evas_smart_legacy_type_register(MY_PAN_CLASS_NAME_LEGACY, klass);
1937 }
1938
1939 #include "elm_gengrid_pan.eo.c"
1940
1941 static void
1942 _elm_gengrid_item_focused(Elm_Object_Item *eo_it)
1943 {
1944    Eina_Bool tmp;
1945    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
1946    Evas_Object *obj = WIDGET(it);
1947    ELM_GENGRID_DATA_GET(obj, sd);
1948    const char *focus_raise;
1949
1950    if (it->generation < sd->generation)
1951      return;
1952
1953    if (_is_no_select(it) ||
1954        (eo_it == sd->focused_item) ||
1955        (eo_do_ret(eo_it, tmp, elm_wdg_item_disabled_get())))
1956      return;
1957
1958    switch (_elm_config->focus_autoscroll_mode)
1959      {
1960       case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
1961          elm_gengrid_item_show
1962             (eo_it, ELM_GENGRID_ITEM_SCROLLTO_IN);
1963          break;
1964       case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
1965          elm_gengrid_item_bring_in
1966             (eo_it, ELM_GENGRID_ITEM_SCROLLTO_IN);
1967          break;
1968       default:
1969          break;
1970      }
1971
1972    sd->focused_item = eo_it;
1973
1974    if (it->realized)
1975      {
1976         if (elm_widget_focus_highlight_enabled_get(obj))
1977           {
1978              edje_object_signal_emit
1979                 (VIEW(it), "elm,state,focused", "elm");
1980           }
1981
1982         focus_raise = edje_object_data_get(VIEW(it), "focusraise");
1983         if ((focus_raise) && (!strcmp(focus_raise, "on")))
1984           evas_object_raise(VIEW(it));
1985      }
1986    evas_object_smart_callback_call(obj, SIG_ITEM_FOCUSED, eo_it);
1987    if (_elm_config->atspi_mode)
1988      elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_FOCUSED, EINA_TRUE);
1989 }
1990
1991 static void
1992 _elm_gengrid_item_unfocused(Elm_Object_Item *eo_it)
1993 {
1994    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
1995    Evas_Object *obj = WIDGET(it);
1996    ELM_GENGRID_DATA_GET(obj, sd);
1997
1998    if (it->generation < sd->generation)
1999      return;
2000
2001    if (_is_no_select(it))
2002      return;
2003
2004    if ((!sd->focused_item) ||
2005        (eo_it != sd->focused_item))
2006      return;
2007
2008    if (elm_widget_focus_highlight_enabled_get(obj))
2009      {
2010         ELM_GENGRID_ITEM_DATA_GET(sd->focused_item, focus_it);
2011         edje_object_signal_emit
2012            (VIEW(focus_it), "elm,state,unfocused", "elm");
2013      }
2014
2015    sd->focused_item = NULL;
2016    evas_object_smart_callback_call(obj, SIG_ITEM_UNFOCUSED, eo_it);
2017    if (_elm_config->atspi_mode)
2018      elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_FOCUSED, EINA_FALSE);
2019 }
2020
2021 static Eina_Bool
2022 _item_focus_up(Elm_Gengrid_Data *sd)
2023 {
2024    unsigned int i;
2025    Elm_Gen_Item *prev = NULL;
2026
2027    if (!sd->focused_item)
2028      {
2029         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2030         while ((prev) && (prev->generation < sd->generation))
2031           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
2032         elm_object_item_focus_set(EO_OBJ(prev), EINA_TRUE);
2033         return EINA_TRUE;
2034      }
2035    else
2036      {
2037         Elm_Object_Item *eo_prev = elm_gengrid_item_prev_get(sd->focused_item);
2038         if (!eo_prev) return EINA_FALSE;
2039         prev = eo_data_scope_get(eo_prev, ELM_GENGRID_ITEM_CLASS);
2040         if (eo_prev == sd->focused_item) return EINA_FALSE;
2041      }
2042
2043    for (i = 1; i < sd->nmax; i++)
2044      {
2045         Elm_Object_Item *eo_tmp =
2046           elm_gengrid_item_prev_get(EO_OBJ(prev));
2047         if (!eo_tmp) return EINA_FALSE;
2048         prev = eo_data_scope_get(eo_tmp, ELM_GENGRID_ITEM_CLASS);
2049      }
2050
2051    elm_object_item_focus_set(EO_OBJ(prev), EINA_TRUE);
2052
2053    return EINA_TRUE;
2054 }
2055
2056 static Eina_Bool
2057 _item_focus_down(Elm_Gengrid_Data *sd)
2058 {
2059    unsigned int i;
2060    Elm_Gen_Item *next = NULL;
2061
2062    if (!sd->focused_item)
2063      {
2064         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2065         while ((next) && (next->generation < sd->generation))
2066           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
2067
2068         elm_object_item_focus_set(EO_OBJ(next), EINA_TRUE);
2069         return EINA_TRUE;
2070      }
2071    else
2072      {
2073         Elm_Object_Item *eo_next = elm_gengrid_item_next_get(sd->focused_item);
2074         if (!eo_next) return EINA_FALSE;
2075         next = eo_data_scope_get(eo_next, ELM_GENGRID_ITEM_CLASS);
2076         if (eo_next == sd->focused_item) return EINA_FALSE;
2077      }
2078
2079    for (i = 1; i < sd->nmax; i++)
2080      {
2081         Elm_Object_Item *eo_tmp =
2082           elm_gengrid_item_next_get(EO_OBJ(next));
2083         if (!eo_tmp) return EINA_FALSE;
2084         next = eo_data_scope_get(eo_tmp, ELM_GENGRID_ITEM_CLASS);
2085      }
2086
2087    elm_object_item_focus_set(EO_OBJ(next), EINA_TRUE);
2088
2089    return EINA_TRUE;
2090 }
2091
2092 static Eina_Bool
2093 _item_focus_left(Elm_Gengrid_Data *sd)
2094 {
2095    Elm_Gen_Item *prev;
2096
2097    if (!sd->focused_item)
2098      {
2099         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2100         while ((prev) && (prev->generation < sd->generation))
2101           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
2102      }
2103    else
2104      {
2105         Elm_Object_Item *eo_prev = elm_gengrid_item_prev_get(sd->focused_item);
2106         if (!eo_prev) return EINA_FALSE;
2107         prev = eo_data_scope_get(eo_prev, ELM_GENGRID_ITEM_CLASS);
2108         if (eo_prev == sd->focused_item) return EINA_FALSE;
2109      }
2110
2111    elm_object_item_focus_set(EO_OBJ(prev), EINA_TRUE);
2112
2113    return EINA_TRUE;
2114 }
2115
2116 static Eina_Bool
2117 _item_focus_right(Elm_Gengrid_Data *sd)
2118 {
2119    Elm_Gen_Item *next;
2120
2121    if (!sd->focused_item)
2122      {
2123         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2124         while ((next) && (next->generation < sd->generation))
2125           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
2126      }
2127    else
2128      {
2129         Elm_Object_Item *eo_next = elm_gengrid_item_next_get(sd->focused_item);
2130         if (!eo_next) return EINA_FALSE;
2131         next = eo_data_scope_get(eo_next, ELM_GENGRID_ITEM_CLASS);
2132         if (eo_next == sd->focused_item) return EINA_FALSE;
2133      }
2134
2135    elm_object_item_focus_set(EO_OBJ(next), EINA_TRUE);
2136
2137    return EINA_TRUE;
2138 }
2139
2140 static Eina_Bool
2141 _item_multi_select_left(Elm_Gengrid_Data *sd)
2142 {
2143    Elm_Object_Item *eo_prev;
2144
2145    if (!sd->selected) return EINA_FALSE;
2146
2147    eo_prev = elm_gengrid_item_prev_get(sd->last_selected_item);
2148    if (!eo_prev) return EINA_TRUE;
2149
2150    if (elm_gengrid_item_selected_get(eo_prev))
2151      {
2152         elm_gengrid_item_selected_set(sd->last_selected_item, EINA_FALSE);
2153         sd->last_selected_item = eo_prev;
2154         elm_gengrid_item_show
2155           (eo_prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
2156      }
2157    else
2158      {
2159         elm_gengrid_item_selected_set(eo_prev, EINA_TRUE);
2160         elm_gengrid_item_show(eo_prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
2161      }
2162
2163    return EINA_TRUE;
2164 }
2165
2166 static Eina_Bool
2167 _item_multi_select_right(Elm_Gengrid_Data *sd)
2168 {
2169    Elm_Object_Item *eo_next;
2170
2171    if (!sd->selected) return EINA_FALSE;
2172
2173    eo_next = elm_gengrid_item_next_get(sd->last_selected_item);
2174    if (!eo_next) return EINA_TRUE;
2175
2176    if (elm_gengrid_item_selected_get(eo_next))
2177      {
2178         elm_gengrid_item_selected_set(sd->last_selected_item, EINA_FALSE);
2179         sd->last_selected_item = eo_next;
2180         elm_gengrid_item_show
2181           (eo_next, ELM_GENGRID_ITEM_SCROLLTO_IN);
2182      }
2183    else
2184      {
2185         elm_gengrid_item_selected_set(eo_next, EINA_TRUE);
2186         elm_gengrid_item_show(eo_next, ELM_GENGRID_ITEM_SCROLLTO_IN);
2187      }
2188
2189    return EINA_TRUE;
2190 }
2191
2192 static Eina_Bool
2193 _item_multi_select_up(Elm_Gengrid_Data *sd)
2194 {
2195    unsigned int i;
2196    Eina_Bool r = EINA_TRUE;
2197
2198    if (!sd->selected) return EINA_FALSE;
2199
2200    for (i = 0; (r) && (i < sd->nmax); i++)
2201      r &= _item_multi_select_left(sd);
2202
2203    return r;
2204 }
2205
2206 static Eina_Bool
2207 _item_multi_select_down(Elm_Gengrid_Data *sd)
2208 {
2209    unsigned int i;
2210    Eina_Bool r = EINA_TRUE;
2211
2212    if (!sd->selected) return EINA_FALSE;
2213
2214    for (i = 0; (r) && (i < sd->nmax); i++)
2215      r &= _item_multi_select_right(sd);
2216
2217    return r;
2218 }
2219
2220 static Eina_Bool
2221 _all_items_deselect(Elm_Gengrid_Data *sd)
2222 {
2223    if (!sd->selected) return EINA_FALSE;
2224
2225    while (sd->selected)
2226      {
2227         Elm_Object_Item *eo_it = sd->selected->data;
2228         elm_gengrid_item_selected_set(eo_it, EINA_FALSE);
2229      }
2230
2231    return EINA_TRUE;
2232 }
2233
2234 static Eina_Bool
2235 _item_single_select_up(Elm_Gengrid_Data *sd)
2236 {
2237    unsigned int i;
2238    Elm_Object_Item *eo_prev;
2239
2240    if (!sd->selected)
2241      eo_prev = EO_OBJ(ELM_GEN_ITEM_FROM_INLIST(sd->items->last));
2242    else
2243      eo_prev = sd->last_selected_item;
2244
2245    while (eo_prev)
2246      {
2247         for (i = 0; i < sd->nmax; i++)
2248           {
2249              eo_prev = elm_gengrid_item_prev_get(eo_prev);
2250              if (!eo_prev) return EINA_FALSE;
2251           }
2252
2253         if (!elm_object_item_disabled_get(eo_prev)) break;
2254      }
2255
2256    if (!eo_prev) return EINA_FALSE;
2257
2258    _all_items_deselect(sd);
2259    elm_gengrid_item_selected_set(eo_prev, EINA_TRUE);
2260
2261    return EINA_TRUE;
2262 }
2263
2264 static Eina_Bool
2265 _item_single_select_down(Elm_Gengrid_Data *sd)
2266 {
2267    unsigned int i;
2268    unsigned int idx;
2269    Elm_Object_Item *eo_next, *eo_orig;
2270
2271    if (!sd->selected)
2272      eo_next = EO_OBJ(ELM_GEN_ITEM_FROM_INLIST(sd->items));
2273    else
2274      eo_next = sd->last_selected_item;
2275    eo_orig = eo_next;
2276
2277    while (eo_next)
2278      {
2279         for (i = 0; i < sd->nmax; i++)
2280           {
2281              eo_next = elm_gengrid_item_next_get(eo_next);
2282              if (!eo_next) break;
2283           }
2284
2285         if (eo_next && !elm_object_item_disabled_get(eo_next)) break;
2286      }
2287
2288    if (!eo_next)
2289      {
2290         idx = elm_gengrid_item_index_get(eo_orig);
2291         if ((idx == sd->item_count) || ((sd->item_count) % (sd->nmax) == 0))
2292            return EINA_FALSE;
2293         else
2294            eo_next = elm_gengrid_last_item_get(sd->obj);
2295      }
2296
2297    _all_items_deselect(sd);
2298    elm_gengrid_item_selected_set(eo_next, EINA_TRUE);
2299
2300    return EINA_TRUE;
2301 }
2302
2303 static Eina_Bool
2304 _item_single_select_left(Elm_Gengrid_Data *sd)
2305 {
2306    Elm_Gen_Item *prev;
2307
2308    if (!sd->selected)
2309      {
2310         prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2311         while ((prev) && (prev->generation < sd->generation)
2312                && elm_object_item_disabled_get(EO_OBJ(prev)))
2313           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
2314      }
2315    else
2316      {
2317         Elm_Object_Item *eo_prev =
2318            elm_gengrid_item_prev_get(sd->last_selected_item);
2319         while (eo_prev)
2320           {
2321              if (!elm_object_item_disabled_get(eo_prev))
2322                break;
2323              eo_prev = elm_gengrid_item_prev_get(eo_prev);
2324           }
2325         prev = eo_data_scope_get(eo_prev, ELM_GENGRID_ITEM_CLASS);
2326      }
2327
2328    if (!prev) return EINA_FALSE;
2329
2330    _all_items_deselect(sd);
2331
2332    elm_gengrid_item_selected_set(EO_OBJ(prev), EINA_TRUE);
2333
2334    return EINA_TRUE;
2335 }
2336
2337 static Eina_Bool
2338 _item_single_select_right(Elm_Gengrid_Data *sd)
2339 {
2340    Elm_Gen_Item *next;
2341
2342    if (!sd->selected)
2343      {
2344         next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2345         while ((next) && (next->generation < sd->generation)
2346                && elm_object_item_disabled_get(EO_OBJ(next)))
2347           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
2348      }
2349    else
2350      {
2351         Elm_Object_Item *eo_next =
2352            elm_gengrid_item_next_get(sd->last_selected_item);
2353         while (eo_next)
2354           {
2355              if (!elm_object_item_disabled_get(eo_next))
2356                break;
2357              eo_next = elm_gengrid_item_next_get(eo_next);
2358           }
2359         next = eo_data_scope_get(eo_next, ELM_GENGRID_ITEM_CLASS);
2360      }
2361
2362    if (!next) return EINA_FALSE;
2363
2364    _all_items_deselect(sd);
2365
2366    elm_gengrid_item_selected_set(EO_OBJ(next), EINA_TRUE);
2367
2368    return EINA_TRUE;
2369 }
2370
2371 static Eina_Bool
2372 _elm_gengrid_item_edge_check(Elm_Object_Item *eo_it,
2373                              Elm_Focus_Direction dir)
2374 {
2375    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
2376    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2377    ELM_GENGRID_DATA_GET(WIDGET(it), sd);
2378    Evas_Coord ix = 0, iy = 0; //item's geometry
2379    Evas_Coord cx = 0, cy = 0; //prev or next item's geometry
2380    Elm_Object_Item *eo_item = NULL;
2381    Elm_Gen_Item *tmp = it;
2382    Eina_Bool mirrored = elm_widget_mirrored_get(WIDGET(it));
2383
2384    evas_object_geometry_get(VIEW(it), &ix, &iy, NULL, NULL);
2385
2386    if (((sd->horizontal) && (dir == ELM_FOCUS_UP)) ||
2387        ((!sd->horizontal) && (dir == ELM_FOCUS_LEFT)))
2388      {
2389         eo_item = elm_gengrid_item_prev_get(EO_OBJ(it));
2390         while (eo_item)
2391           {
2392              if (sd->reorder_mode || !elm_object_item_disabled_get(eo_item)) break;
2393              eo_item = elm_gengrid_item_prev_get(eo_item);
2394           }
2395         if (eo_item)
2396           {
2397              ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
2398              evas_object_geometry_get(VIEW(item), &cx, &cy, NULL, NULL);
2399              if ((sd->horizontal) && (ix == cx) && (iy > cy))
2400                return EINA_FALSE;
2401              else if ((!sd->horizontal) && (iy == cy))
2402                if ((!mirrored && (ix >cx)) || (mirrored && (ix < cx)))
2403                  return EINA_FALSE;
2404                else
2405                  return EINA_TRUE;
2406              else
2407                return EINA_TRUE;
2408           }
2409         if ((dir == ELM_FOCUS_UP) || (!eo_item && sd->reorder_mode))
2410           return EINA_TRUE;
2411      }
2412    else if (((sd->horizontal) && (dir == ELM_FOCUS_DOWN)) ||
2413             ((!sd->horizontal) && (dir == ELM_FOCUS_RIGHT)))
2414      {
2415         eo_item = elm_gengrid_item_next_get(EO_OBJ(it));
2416         while (eo_item)
2417           {
2418              if (sd->reorder_mode || !elm_object_item_disabled_get(eo_item)) break;
2419              eo_item = elm_gengrid_item_next_get(eo_item);
2420           }
2421         if (eo_item)
2422           {
2423              ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
2424              evas_object_geometry_get(VIEW(item), &cx, &cy, NULL, NULL);
2425              if ((sd->horizontal) && (ix == cx) && (iy < cy))
2426                return EINA_FALSE;
2427              else if ((!sd->horizontal) && (iy == cy))
2428                if ((!mirrored && (ix < cx)) || (mirrored && (ix > cx)))
2429                  return EINA_FALSE;
2430                else
2431                  return EINA_TRUE;
2432              else
2433                return EINA_TRUE;
2434           }
2435         if ((dir == ELM_FOCUS_DOWN) || (!eo_item && sd->reorder_mode))
2436           return EINA_TRUE;
2437      }
2438    else if (((!sd->horizontal) && (dir == ELM_FOCUS_UP)) ||
2439             ((sd->horizontal) && (dir == ELM_FOCUS_LEFT)))
2440      {
2441         Evas_Coord col, row, cvw, cvh;
2442
2443         evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
2444         if (sd->horizontal && sd->item_height > 0)
2445           {
2446              row = cvh / sd->item_height;
2447              if (row <= 0) row = 1;
2448              if (tmp->position <= row)
2449                return EINA_TRUE;
2450           }
2451         else if (sd->item_width > 0)
2452           {
2453              col = cvw / sd->item_width;
2454              if (col <= 0) col = 1;
2455              if (tmp->position <= col)
2456                return EINA_TRUE;
2457           }
2458      }
2459    else if (((!sd->horizontal) && (dir == ELM_FOCUS_DOWN)) ||
2460             ((sd->horizontal) && (dir == ELM_FOCUS_RIGHT)))
2461      {
2462         Evas_Coord col = 0, row = 0, cvw, cvh;
2463         int x = 0;
2464
2465         evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
2466         if (sd->horizontal && sd->item_height > 0)
2467           {
2468              row = cvh / sd->item_height;
2469              if (row <= 0) row = 1;
2470              col = sd->item_count / row;
2471              x = sd->item_count % row;
2472              if (x == 0)
2473                {
2474                   if ((tmp->position <= (row * col)) &&
2475                       (tmp->position > (row * (col - 1))))
2476                     return EINA_TRUE;
2477                }
2478              else
2479                {
2480                   if ((tmp->position <= ((col * row) + x)) &&
2481                       (tmp->position > ((col - 1) * row) + x))
2482                     return EINA_TRUE;
2483                }
2484           }
2485         else if (sd->item_width > 0)
2486           {
2487              col = cvw / sd->item_width;
2488              if (col <= 0) col = 1;
2489              row = sd->item_count / col;
2490              x = sd->item_count % col;
2491              if (x == 0)
2492                {
2493                   if ((tmp->position <= (col * row)) &&
2494                       (tmp->position > (col * (row - 1))))
2495                        return EINA_TRUE;
2496                }
2497              else
2498                {
2499                   if ((tmp->position <= ((col * row) + x)) &&
2500                       (tmp->position > (((col * (row - 1)) + x))))
2501                     return EINA_TRUE;
2502                }
2503           }
2504      }
2505
2506    return EINA_FALSE;
2507 }
2508
2509 static Elm_Object_Item *
2510 get_up_item(Elm_Gengrid_Data *sd, Elm_Object_Item *eo_it)
2511 {
2512    Elm_Object_Item *eo_prev = NULL;
2513    unsigned int i;
2514
2515    eo_prev = elm_gengrid_item_prev_get(eo_it);
2516    if (!eo_prev)
2517      return NULL;
2518
2519    for (i = 1; i < sd->nmax; i++)
2520      {
2521         Elm_Object_Item *eo_tmp = elm_gengrid_item_prev_get(eo_prev);
2522         if (!eo_tmp) return eo_prev;
2523         eo_prev = eo_tmp;
2524      }
2525
2526    return eo_prev;
2527 }
2528
2529 static Elm_Object_Item *
2530 get_down_item(Elm_Gengrid_Data *sd, Elm_Object_Item *eo_it)
2531 {
2532    Elm_Object_Item *eo_next = NULL;
2533    unsigned int i;
2534
2535    eo_next = elm_gengrid_item_next_get(eo_it);
2536    if (!eo_next)
2537      return NULL;
2538
2539    for (i = 1; i < sd->nmax; i++)
2540      {
2541         Elm_Object_Item *eo_tmp = elm_gengrid_item_next_get(eo_next);
2542         if (!eo_tmp) return eo_next;
2543         eo_next = eo_tmp;
2544      }
2545
2546    return eo_next;
2547 }
2548
2549 typedef struct _Item_Info
2550 {
2551    Elm_Gen_Item *it;
2552    Evas_Coord x, y;
2553 } Item_Info;
2554
2555 typedef struct _Reorder_Normal_Data
2556 {
2557    Item_Info *items;
2558    Elm_Gen_Item *corner_item;
2559    int no;
2560 } Reorder_Normal_Data;
2561
2562 static void
2563 _free_reorder_normal_data(Reorder_Normal_Data *rnd)
2564 {
2565    free(rnd->items);
2566    free(rnd);
2567 }
2568
2569 static void
2570 _anim_end(Elm_Gengrid_Data *sd)
2571 {
2572    Eina_Inlist *tmp = NULL;
2573    Elm_Gen_Item *it1_prev = NULL, *it2_prev = NULL;
2574    it1_prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(sd->reorder.it1)->prev);
2575    it2_prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(sd->reorder.it2)->prev);
2576
2577    if ((sd->reorder.type == ELM_GENGRID_REORDER_TYPE_NORMAL) &&
2578        ((!sd->horizontal && ((sd->reorder.dir == ELM_FOCUS_UP) || (sd->reorder.dir == ELM_FOCUS_DOWN))) ||
2579        (sd->horizontal && ((sd->reorder.dir == ELM_FOCUS_LEFT) || (sd->reorder.dir == ELM_FOCUS_RIGHT)))))
2580      {
2581         sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2582         if ((sd->reorder.dir == ELM_FOCUS_UP) ||
2583             (sd->reorder.dir == ELM_FOCUS_LEFT))
2584           {
2585              if (it2_prev)
2586                {
2587                   tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it2_prev));
2588                   sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2589                                                           tmp);
2590                }
2591              else
2592                sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2593           }
2594         else if ((sd->reorder.dir == ELM_FOCUS_DOWN) ||
2595                  (sd->reorder.dir == ELM_FOCUS_RIGHT))
2596           {
2597              tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2598              sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2599                                                           tmp);
2600           }
2601      }
2602    else if ((sd->reorder.type == ELM_GENGRID_REORDER_TYPE_SWAP) &&
2603             ((!sd->horizontal && ((sd->reorder.dir == ELM_FOCUS_UP) || (sd->reorder.dir == ELM_FOCUS_DOWN))) ||
2604        (sd->horizontal && ((sd->reorder.dir == ELM_FOCUS_LEFT) || (sd->reorder.dir == ELM_FOCUS_RIGHT)))))
2605      {
2606         sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2607         sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2608
2609         if (it1_prev)
2610           {
2611              tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it1_prev));
2612              sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it2),
2613                                                      tmp);
2614           }
2615         else
2616           sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2617         if (it2_prev)
2618           {
2619              tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it2_prev));
2620              sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2621                                                      tmp);
2622           }
2623         else
2624           sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2625      }
2626    else if ((!sd->horizontal && (sd->reorder.dir == ELM_FOCUS_LEFT)) ||
2627             (sd->horizontal && (sd->reorder.dir == ELM_FOCUS_UP)))
2628      {
2629          if (!(sd->reorder.it2 == it1_prev))
2630            {
2631               sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2632               sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2633            
2634               if (it1_prev)
2635                 {
2636                    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it1_prev));
2637                    sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it2),
2638                                                            tmp);
2639                 }
2640               else
2641                 sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2642            
2643               if (it2_prev)
2644                 {
2645                    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it2_prev));
2646                    sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2647                                                            tmp);
2648                 }
2649               else
2650                 sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2651            }
2652          else
2653            {
2654               sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2655               sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2656                                                        EINA_INLIST_GET(sd->reorder.it2));
2657            }
2658      }
2659    else if ((!sd->horizontal && (sd->reorder.dir == ELM_FOCUS_RIGHT)) ||
2660             (sd->horizontal && (sd->reorder.dir == ELM_FOCUS_DOWN)))
2661      {
2662         if (!(sd->reorder.it1 == it2_prev))
2663           {
2664              sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2665              sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2666           
2667              if (it1_prev)
2668                {  
2669                   tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it1_prev));
2670                   sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it2),
2671                                                           tmp);
2672                }
2673              else
2674                sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2675         
2676              if (it2_prev)
2677                {
2678                   tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it2_prev));
2679                   sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2680                                                           tmp);
2681                }
2682              else
2683                sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2684           }
2685         else
2686           {
2687              sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2688              sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it1),
2689                                                      EINA_INLIST_GET(sd->reorder.it2));
2690           }
2691      }
2692    _item_position_update(sd->items, 0);
2693
2694    ecore_job_del(sd->calc_job);
2695    sd->calc_job = ecore_job_add(_calc_job, sd->obj);
2696 }
2697
2698 static Eina_Bool
2699 _item_move_cb(void *data, double pos)
2700 {
2701    Elm_Gengrid_Data *sd = data;
2702    double frame = pos;
2703    Evas_Coord xx1, yy1, xx2, yy2;
2704    double dx, dy;
2705
2706    switch (sd->reorder.tween_mode)
2707      {
2708       case ECORE_POS_MAP_LINEAR:
2709          frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 0, 0);
2710          break;
2711       case ECORE_POS_MAP_ACCELERATE:
2712       case ECORE_POS_MAP_DECELERATE:
2713       case ECORE_POS_MAP_SINUSOIDAL:
2714          frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 1.0, 0);
2715          break;
2716       case ECORE_POS_MAP_DIVISOR_INTERP:
2717       case ECORE_POS_MAP_BOUNCE:
2718       case ECORE_POS_MAP_SPRING:
2719          frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 1.0, 1.0);
2720          break;
2721       default:
2722          frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 0, 0);
2723          break;
2724      }
2725
2726    dx = sd->reorder.x2 - sd->reorder.x1;
2727    dy = sd->reorder.y2 - sd->reorder.y1;
2728    xx1 = sd->reorder.x1 + (dx * frame);
2729    yy1 = sd->reorder.y1 + (dy * frame);
2730
2731    if (sd->reorder.type == ELM_GENGRID_REORDER_TYPE_NORMAL)
2732      {
2733         int i = 0;
2734         Reorder_Normal_Data *rnd = sd->reorder.data;
2735
2736         for (;i < rnd->no; i++)
2737           {
2738              dx = rnd->items[i + 1].x - rnd->items[i].x;
2739              dy = rnd->items[i + 1].y - rnd->items[i].y;
2740              xx2 = rnd->items[i].x + (frame * dx);
2741              yy2 = rnd->items[i].y + (frame * dy);
2742              evas_object_move(VIEW(rnd->items[i].it), xx2, yy2);
2743           }
2744      }
2745    else if (sd->reorder.type == ELM_GENGRID_REORDER_TYPE_SWAP)
2746      {
2747         xx2 = sd->reorder.x2 - (dx * frame);
2748         yy2 = sd->reorder.y2 - (dy * frame);
2749         evas_object_move(VIEW(sd->reorder.it2), xx2, yy2);
2750      }
2751
2752    evas_object_move(VIEW(sd->reorder.it1), xx1, yy1);
2753
2754    if (pos == 1.0)
2755      {
2756         _anim_end(sd);
2757         if (sd->reorder.type == ELM_GENGRID_REORDER_TYPE_NORMAL)
2758           _free_reorder_normal_data(sd->reorder.data);
2759         elm_gengrid_item_show(EO_OBJ(sd->reorder.it1),
2760                               ELM_GENGRID_ITEM_SCROLLTO_IN);
2761         evas_object_smart_callback_call(sd->obj, SIG_ITEM_REORDER_STOP,
2762                                         EO_OBJ(sd->reorder.it1));
2763         evas_object_smart_callback_call(sd->obj, SIG_MOVED,
2764                                         EO_OBJ(sd->reorder.it1));
2765         sd->reorder.running = EINA_FALSE;
2766      }
2767    _elm_widget_focus_highlight_start(sd->obj);
2768
2769    return EINA_TRUE;
2770 }
2771
2772 static void
2773 _store_nearby_items(Elm_Gengrid_Data *sd)
2774 {
2775    Reorder_Normal_Data *rnd = sd->reorder.data;
2776    Eina_Inlist *itr;
2777    Evas_Coord x, y, cvw, cvh, col = 0, row = 0;
2778    int i = 0;
2779    int corner_item_pos = 0;
2780    Eina_Inlist *it1_list, *it2_list;
2781
2782    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &cvw, &cvh);
2783
2784    rnd->no = abs(sd->reorder.it2->position - sd->reorder.it1->position);
2785    rnd->items = malloc(sizeof(Item_Info) * (rnd->no + 1));
2786
2787   if (sd->horizontal && sd->item_height > 0)
2788     {
2789        row = cvh / sd->item_height;
2790        if (row <= 0) row = 1;
2791        if (sd->reorder.dir == ELM_FOCUS_RIGHT)
2792          {
2793             corner_item_pos = (sd->reorder.it2->position + 1) / row;
2794             corner_item_pos = corner_item_pos * row;
2795             corner_item_pos = sd->reorder.it2->position - corner_item_pos;
2796          }
2797        else if (sd->reorder.dir == ELM_FOCUS_LEFT)
2798          {
2799             corner_item_pos = (sd->reorder.it2->position + 1) / row;
2800             corner_item_pos = (corner_item_pos + 1) * row;
2801             corner_item_pos = corner_item_pos - sd->reorder.it2->position;
2802          }
2803     }
2804   else if (sd->item_width > 0)
2805     {
2806        col = cvw / sd->item_width;
2807        if (col <= 0) col = 1;
2808        if (sd->reorder.dir == ELM_FOCUS_DOWN)
2809          {
2810             corner_item_pos = (sd->reorder.it2->position + 1) / col;
2811             corner_item_pos = corner_item_pos * col;
2812             corner_item_pos = sd->reorder.it2->position - corner_item_pos;
2813          }
2814        else if (sd->reorder.dir == ELM_FOCUS_UP)
2815          {
2816             corner_item_pos = (sd->reorder.it2->position + 1) / col;
2817             corner_item_pos = (corner_item_pos + 1) * col;
2818             corner_item_pos = corner_item_pos - sd->reorder.it2->position;
2819          }
2820     }
2821
2822   it1_list = eina_inlist_find(sd->items, EINA_INLIST_GET(sd->reorder.it1));
2823   it2_list = eina_inlist_find(sd->items, EINA_INLIST_GET(sd->reorder.it2));
2824
2825   if ((sd->reorder.it1->position) < (sd->reorder.it2)->position)
2826     {
2827        for (itr = it2_list; itr != it1_list; itr = itr->prev)
2828          {
2829             Elm_Gen_Item *cur = EINA_INLIST_CONTAINER_GET(itr, Elm_Gen_Item);
2830             evas_object_geometry_get(VIEW(cur), &x, &y, NULL, NULL);
2831             rnd->items[i].it = cur;
2832             rnd->items[i].x = x;
2833             rnd->items[i].y = y;
2834             if (i == (corner_item_pos - 1))
2835               rnd->corner_item = cur;
2836             i++;
2837          }
2838        rnd->items[i].it = sd->reorder.it1;
2839        rnd->items[i].x = sd->reorder.x1;
2840        rnd->items[i].y = sd->reorder.y1;
2841     }
2842   else if (sd->reorder.it1->position > sd->reorder.it2->position)
2843     {
2844        for (itr = it2_list; itr != it1_list; itr = itr->next)
2845          {
2846             Elm_Gen_Item *cur = EINA_INLIST_CONTAINER_GET(itr, Elm_Gen_Item);
2847             evas_object_geometry_get(VIEW(cur), &x, &y, NULL, NULL);
2848             rnd->items[i].it = cur;
2849             rnd->items[i].x = x;
2850             rnd->items[i].y = y;
2851             if (i == (corner_item_pos - 1))
2852               rnd->corner_item = cur;
2853             i++;
2854          }
2855        rnd->items[i].it = sd->reorder.it1;
2856        rnd->items[i].x = sd->reorder.x1;
2857        rnd->items[i].y = sd->reorder.y1;
2858     }
2859 }
2860
2861 static void
2862 _swap_items(Elm_Object_Item *eo_it1, Elm_Object_Item *eo_it2, Elm_Focus_Direction dir)
2863 {
2864    ELM_GENGRID_ITEM_DATA_GET(eo_it1, it1);
2865    ELM_GENGRID_ITEM_DATA_GET(eo_it2, it2);
2866    ELM_GENGRID_DATA_GET(WIDGET(it1), sd);
2867    Evas_Coord xx1, yy1, xx2, yy2;
2868
2869    sd->reorder.running = EINA_TRUE;
2870    sd->reorder.dir = dir;
2871    sd->reorder.it1 = it1;
2872    sd->reorder.it2 = it2;
2873
2874    evas_object_geometry_get(VIEW(it1), &xx1, &yy1, NULL, NULL);
2875    evas_object_geometry_get(VIEW(it2), &xx2, &yy2, NULL, NULL);
2876    sd->reorder.x1 = xx1;
2877    sd->reorder.y1 = yy1;
2878    sd->reorder.x2 = xx2;
2879    sd->reorder.y2 = yy2;
2880
2881    if (sd->reorder.type == ELM_GENGRID_REORDER_TYPE_NORMAL)
2882      {
2883         Reorder_Normal_Data *rnd = malloc(sizeof(Reorder_Normal_Data));
2884         memset(rnd, 0, sizeof(Reorder_Normal_Data));
2885         sd->reorder.data = rnd;
2886         _store_nearby_items(sd);
2887         if (rnd->corner_item)
2888           evas_object_raise(VIEW(rnd->corner_item));
2889      }
2890    evas_object_raise(VIEW(it1));
2891    evas_object_smart_callback_call(sd->obj, SIG_ITEM_REORDER_START,
2892                                    EO_OBJ(sd->reorder.it1));
2893    //TODO: Add elm config for time
2894    ecore_animator_timeline_add(0.3, _item_move_cb, sd);
2895 }
2896
2897 static Eina_Bool
2898 _item_horizontal_loop(Evas_Object *obj, Elm_Focus_Direction dir)
2899 {
2900    ELM_GENGRID_DATA_GET(obj, sd);
2901    Elm_Object_Item *eo_item = sd->focused_item;
2902    unsigned int counter, i;
2903
2904    ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
2905    if (sd->horizontal)
2906      {
2907         if (dir == ELM_FOCUS_UP)
2908           {
2909              counter = 0;
2910              while (!_elm_gengrid_item_edge_check(EO_OBJ(item), dir))
2911                {
2912                   eo_item = elm_gengrid_item_prev_get(eo_item);
2913                   item = eo_data_scope_get(eo_item, ELM_GENGRID_ITEM_CLASS);
2914                   counter++;
2915                }
2916              eo_item = elm_gengrid_first_item_get(obj);
2917              for (i = 0; i < counter; i++)
2918                eo_item = elm_gengrid_item_next_get(eo_item);
2919           }
2920         else
2921           {
2922              while (1)
2923                {
2924                   if (_elm_gengrid_item_edge_check(EO_OBJ(item), dir))
2925                     break;
2926                   else
2927                     {
2928                        for (i = 0; i < sd->nmax; i++)
2929                          eo_item = elm_gengrid_item_next_get(eo_item);
2930                        item = eo_data_scope_get(eo_item, ELM_GENGRID_ITEM_CLASS);
2931                     }
2932                }
2933           }
2934      }
2935    else
2936      {
2937         if (dir == ELM_FOCUS_RIGHT)
2938           {
2939              while (!_elm_gengrid_item_edge_check(EO_OBJ(item), dir))
2940                {
2941                   if (!elm_gengrid_item_next_get(eo_item))
2942                     break;
2943                   eo_item = elm_gengrid_item_next_get(eo_item);
2944                   item = eo_data_scope_get(eo_item, ELM_GENGRID_ITEM_CLASS);
2945                }
2946           }
2947         else if (dir == ELM_FOCUS_LEFT)
2948           {
2949              while (!_elm_gengrid_item_edge_check(EO_OBJ(item), dir))
2950                {
2951                   if (!elm_gengrid_item_prev_get(EO_OBJ(item)))
2952                     break;
2953                   eo_item = elm_gengrid_item_prev_get(eo_item);
2954                   item = eo_data_scope_get(eo_item, ELM_GENGRID_ITEM_CLASS);
2955                }
2956           }
2957         else
2958           return EINA_FALSE;
2959      }
2960    if (!eo_item) return EINA_FALSE;
2961    if (sd->reorder_mode && !(sd->focused_item == eo_item))
2962      {
2963         _swap_items(sd->focused_item, eo_item, ELM_FOCUS_RIGHT);
2964         return EINA_TRUE;
2965      }
2966    else
2967      {
2968         elm_gengrid_item_selected_set(eo_item, EINA_TRUE);
2969         return EINA_TRUE;
2970      }
2971    return EINA_FALSE;
2972 }
2973
2974 static Eina_Bool
2975 _key_action_move(Evas_Object *obj, const char *params)
2976 {
2977    ELM_GENGRID_DATA_GET(obj, sd);
2978    const char *dir = params;
2979
2980    Evas_Coord x = 0;
2981    Evas_Coord y = 0;
2982    Evas_Coord v_w = 0;
2983    Evas_Coord v_h = 0;
2984    Evas_Coord step_x = 0;
2985    Evas_Coord step_y = 0;
2986    Evas_Coord page_x = 0;
2987    Evas_Coord page_y = 0;
2988    Elm_Object_Item *it = NULL;
2989    Eina_Bool mirrored = elm_widget_mirrored_get(obj);
2990
2991    eo_do(obj,
2992          elm_interface_scrollable_content_pos_get(&x, &y),
2993          elm_interface_scrollable_step_size_get(&step_x, &step_y),
2994          elm_interface_scrollable_page_size_get(&page_x, &page_y),
2995          elm_interface_scrollable_content_viewport_geometry_get
2996          (NULL, NULL, &v_w, &v_h));
2997
2998    if (sd->reorder_mode && sd->reorder.running) return EINA_TRUE;
2999
3000    if ((!strcmp(dir, "left") && !mirrored) ||
3001        (!strcmp(dir, "right") && mirrored))
3002      {
3003         if (sd->reorder_mode)
3004           {
3005              Elm_Object_Item *eo_left;
3006
3007              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_LEFT))
3008                {
3009                   if (sd->item_loop_enable)
3010                     {
3011                        if (_item_horizontal_loop(obj, ELM_FOCUS_RIGHT))
3012                          return EINA_TRUE;
3013                     }
3014                   return EINA_FALSE;
3015                }
3016              if (!sd->horizontal)
3017                eo_left = elm_gengrid_item_prev_get(sd->focused_item);
3018              else
3019                eo_left = get_up_item(sd, sd->focused_item);
3020              if (!eo_left)
3021                return EINA_TRUE;
3022              _swap_items(sd->focused_item, eo_left, ELM_FOCUS_LEFT);
3023
3024              return EINA_TRUE;
3025           }
3026         if (sd->horizontal)
3027           {
3028              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_LEFT))
3029                {
3030                   if (sd->item_loop_enable)
3031                     {
3032                        if (_item_horizontal_loop(obj, ELM_FOCUS_RIGHT))
3033                          return EINA_TRUE;
3034                     }
3035                   return EINA_FALSE;
3036                }
3037              if (!_elm_config->item_select_on_focus_disable)
3038                {
3039                   return _item_single_select_up(sd);
3040                }
3041              else
3042                return _item_focus_up(sd);
3043           }
3044         else
3045           {
3046              if (sd->focused_item && (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_LEFT) ||
3047                  !elm_gengrid_item_prev_get(sd->focused_item)))
3048                {
3049                   if (sd->item_loop_enable)
3050                     {
3051                        if (_item_horizontal_loop(obj, ELM_FOCUS_RIGHT))
3052                          return EINA_TRUE;
3053                     }
3054                   return EINA_FALSE;
3055                }
3056              if (!_elm_config->item_select_on_focus_disable)
3057                {
3058                   return _item_single_select_left(sd);
3059                }
3060              else
3061                return _item_focus_left(sd);
3062           }
3063      }
3064    else if ((!strcmp(dir, "left_multi") && !mirrored) ||
3065             (!strcmp(dir, "right_multi") && mirrored))
3066      {
3067         if (sd->horizontal)
3068           {
3069              if (_item_multi_select_up(sd)) return EINA_TRUE;
3070              else if (_item_single_select_up(sd)) return EINA_TRUE;
3071              else return EINA_FALSE;
3072           }
3073         else
3074           {
3075              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_LEFT))
3076                return EINA_FALSE;
3077              if (_item_multi_select_left(sd)) return EINA_TRUE;
3078              else if (_item_single_select_left(sd)) return EINA_TRUE;
3079              else return EINA_FALSE;
3080           }
3081      }
3082    else if ((!strcmp(dir, "right") && !mirrored) ||
3083             (!strcmp(dir, "left") && mirrored))
3084      {
3085         if (sd->reorder_mode)
3086           {
3087              Elm_Object_Item *eo_right;
3088
3089              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_RIGHT))
3090                {
3091                   if (sd->item_loop_enable && !sd->horizontal)
3092                     {
3093                        if (_item_horizontal_loop(obj, ELM_FOCUS_LEFT))
3094                          return EINA_TRUE;
3095                     }
3096                   else if (sd->item_loop_enable)
3097                     {
3098                        if (_item_horizontal_loop(obj, ELM_FOCUS_UP))
3099                          return EINA_TRUE;
3100                     }
3101                   return EINA_FALSE;
3102                }
3103              if (!sd->horizontal)
3104                eo_right = elm_gengrid_item_next_get(sd->focused_item);
3105              else
3106                eo_right = get_down_item(sd, sd->focused_item);
3107              if (!eo_right)
3108                return EINA_TRUE;
3109              _swap_items(sd->focused_item, eo_right, ELM_FOCUS_RIGHT);
3110
3111              return EINA_TRUE;
3112           }
3113         if (sd->horizontal)
3114           {
3115              if (sd->focused_item && _elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_RIGHT))
3116                {
3117                   if (sd->item_loop_enable)
3118                     {
3119                        if (_item_horizontal_loop(obj, ELM_FOCUS_UP))
3120                          return EINA_TRUE;
3121                     } 
3122                   return EINA_FALSE;
3123                }
3124              if (!_elm_config->item_select_on_focus_disable)
3125                {
3126                   return _item_single_select_down(sd);
3127                }
3128              else
3129                return _item_focus_down(sd);
3130           }
3131         else
3132           {
3133              if (sd->focused_item && (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_RIGHT) ||
3134                  !elm_gengrid_item_next_get(sd->focused_item)))
3135                {
3136                   if (sd->item_loop_enable)
3137                     {
3138                        if (_item_horizontal_loop(obj, ELM_FOCUS_LEFT))
3139                          return EINA_TRUE;
3140                     }
3141                   return EINA_FALSE;
3142                }
3143              if (!_elm_config->item_select_on_focus_disable)
3144                {
3145                   return _item_single_select_right(sd);
3146                }
3147              else
3148                return _item_focus_right(sd);
3149           }
3150      }
3151    else if ((!strcmp(dir, "right_multi") && !mirrored) ||
3152             (!strcmp(dir, "left_multi") && mirrored))
3153      {
3154         if (sd->horizontal)
3155           {
3156              if (_item_multi_select_down(sd)) return EINA_TRUE;
3157              else if (_item_single_select_down(sd)) return EINA_TRUE;
3158              else return EINA_FALSE;
3159           }
3160         else
3161           {
3162              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_RIGHT))
3163                return EINA_FALSE;
3164              if (_item_multi_select_right(sd)) return EINA_TRUE;
3165              else if (_item_single_select_right(sd)) return EINA_TRUE;
3166              else return EINA_FALSE;
3167           }
3168      }
3169    else if (!strcmp(dir, "up"))
3170      {
3171         if (sd->reorder_mode)
3172           {
3173              Elm_Object_Item *eo_up;
3174
3175              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_UP))
3176                return EINA_FALSE;
3177              if (!sd->horizontal)
3178                eo_up = get_up_item(sd, sd->focused_item);
3179              else
3180                eo_up = elm_gengrid_item_prev_get(sd->focused_item);
3181              if (!eo_up)
3182                return EINA_TRUE;
3183              _swap_items(sd->focused_item, eo_up, ELM_FOCUS_UP);
3184
3185              return EINA_TRUE;
3186           }
3187         if (sd->horizontal)
3188           {
3189              if (sd->focused_item && _elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_UP))
3190                return EINA_FALSE;
3191              if (!_elm_config->item_select_on_focus_disable)
3192                {
3193                   if (_item_single_select_left(sd)) return EINA_TRUE;
3194                   else return EINA_FALSE;
3195                }
3196              else
3197                return _item_focus_left(sd);
3198           }
3199         else
3200           {
3201              if (!_elm_config->item_select_on_focus_disable)
3202                {
3203                   return _item_single_select_up(sd);
3204                }
3205              else
3206                return _item_focus_up(sd);
3207           }
3208      }
3209    else if (!strcmp(dir, "up_multi"))
3210      {
3211         if (sd->horizontal)
3212           {
3213              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_UP))
3214                return EINA_FALSE;
3215              if (_item_multi_select_left(sd)) return EINA_TRUE;
3216              else if (_item_single_select_left(sd)) return EINA_TRUE;
3217              else return EINA_FALSE;
3218           }
3219         else
3220           {
3221              if (_item_multi_select_up(sd)) return EINA_TRUE;
3222              else if (_item_single_select_up(sd)) return EINA_TRUE;
3223              else return EINA_FALSE;
3224           }
3225      }
3226    else if (!strcmp(dir, "down"))
3227      {
3228         if (sd->reorder_mode)
3229           {
3230              Elm_Object_Item *eo_down;
3231
3232              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_DOWN))
3233                return EINA_FALSE;
3234              if (!sd->horizontal)
3235                eo_down = get_down_item(sd, sd->focused_item);
3236              else
3237                eo_down = elm_gengrid_item_next_get(sd->focused_item);
3238              if (!eo_down)
3239                return EINA_TRUE;
3240              _swap_items(sd->focused_item, eo_down, ELM_FOCUS_DOWN);
3241
3242              return EINA_TRUE;
3243           }
3244         if (sd->horizontal)
3245           {
3246              if (sd->focused_item && _elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_DOWN))
3247                return EINA_FALSE;
3248              if (!_elm_config->item_select_on_focus_disable)
3249                {
3250                   return _item_single_select_right(sd);
3251                }
3252              else
3253                return _item_focus_right(sd);
3254           }
3255         else
3256           {
3257              if (!_elm_config->item_select_on_focus_disable)
3258                {
3259                   return _item_single_select_down(sd);
3260                }
3261              else
3262                return _item_focus_down(sd);
3263           }
3264      }
3265    else if (!strcmp(dir, "down_multi"))
3266      {
3267         if (sd->horizontal)
3268           {
3269              if (_elm_gengrid_item_edge_check(sd->focused_item, ELM_FOCUS_DOWN))
3270                return EINA_FALSE;
3271              if (_item_multi_select_right(sd)) return EINA_TRUE;
3272              else if (_item_single_select_right(sd)) return EINA_TRUE;
3273              else return EINA_FALSE;
3274           }
3275         else
3276           {
3277              if (_item_multi_select_down(sd)) return EINA_TRUE;
3278              else if (_item_single_select_down(sd)) return EINA_TRUE;
3279              else return EINA_FALSE;
3280           }
3281      }
3282    else if (!strcmp(dir, "first"))
3283      {
3284         it = elm_gengrid_first_item_get(obj);
3285         if (!_elm_config->item_select_on_focus_disable)
3286           elm_gengrid_item_selected_set(it, EINA_TRUE);
3287         else
3288           elm_object_item_focus_set(it, EINA_TRUE);
3289         return EINA_TRUE;
3290      }
3291    else if (!strcmp(dir, "last"))
3292      {
3293         it = elm_gengrid_last_item_get(obj);
3294         if (!_elm_config->item_select_on_focus_disable)
3295           elm_gengrid_item_selected_set(it, EINA_TRUE);
3296         else
3297           elm_object_item_focus_set(it, EINA_TRUE);
3298         return EINA_TRUE;
3299      }
3300    else if (!strcmp(dir, "prior"))
3301      {
3302         if (sd->horizontal)
3303           {
3304              if (page_x < 0)
3305                x -= -(page_x * v_w) / 100;
3306              else
3307                x -= page_x;
3308           }
3309         else
3310           {
3311              if (page_y < 0)
3312                y -= -(page_y * v_h) / 100;
3313              else
3314                y -= page_y;
3315           }
3316      }
3317    else if (!strcmp(dir, "next"))
3318      {
3319         if (sd->horizontal)
3320           {
3321              if (page_x < 0)
3322                x += -(page_x * v_w) / 100;
3323              else
3324                x += page_x;
3325           }
3326         else
3327           {
3328              if (page_y < 0)
3329                y += -(page_y * v_h) / 100;
3330              else
3331                y += page_y;
3332           }
3333      }
3334    else return EINA_FALSE;
3335
3336    eo_do(obj, elm_interface_scrollable_content_pos_set(x, y, EINA_TRUE));
3337    return EINA_TRUE;
3338 }
3339
3340 static Eina_Bool
3341 _key_action_select(Evas_Object *obj, const char *params)
3342 {
3343    ELM_GENGRID_DATA_GET(obj, sd);
3344    Elm_Object_Item *eo_it = elm_object_focused_item_get(obj);
3345    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
3346
3347    if (sd->multi &&
3348        ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
3349         (!strcmp(params, "multi"))))
3350      {
3351         if (!it->selected)
3352           {
3353              it->highlight_cb(it);
3354              it->sel_cb(it);
3355           }
3356         else it->unsel_cb(it);
3357      }
3358    else
3359      {
3360         if (!it->selected)
3361           {
3362              while (sd->selected)
3363                {
3364                   Elm_Object_Item *eo_sel = sd->selected->data;
3365                   Elm_Gen_Item *sel = eo_data_scope_get(eo_sel, ELM_GENGRID_ITEM_CLASS);
3366                   it->unsel_cb(sel);
3367                }
3368           }
3369         else
3370           {
3371              const Eina_List *l, *l_next;
3372              Elm_Object_Item *eo_item2;
3373
3374              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_item2)
3375                {
3376                   ELM_GENGRID_ITEM_DATA_GET(eo_item2, item2);
3377                   if (item2 != it) it->unsel_cb(item2);
3378                }
3379           }
3380         it->highlight_cb(it);
3381         it->sel_cb(it);
3382      }
3383
3384    if (!sd->multi)
3385      evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, eo_it);
3386
3387    return EINA_TRUE;
3388 }
3389
3390 static Eina_Bool
3391 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
3392 {
3393    ELM_GENGRID_DATA_GET(obj, sd);
3394
3395    if (!_all_items_deselect(sd)) return EINA_FALSE;
3396    return EINA_TRUE;
3397 }
3398
3399 EOLIAN static Eina_Bool
3400 _elm_gengrid_elm_widget_event(Eo *obj, Elm_Gengrid_Data *sd, Evas_Object *src, Evas_Callback_Type type, void *event_info)
3401 {
3402    Evas_Event_Key_Down *ev = event_info;
3403    (void) src;
3404
3405    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
3406    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
3407    if (!sd->items) return EINA_FALSE;
3408
3409    if (!_elm_config_key_binding_call(obj, ev, key_actions))
3410      return EINA_FALSE;
3411
3412    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
3413    return EINA_TRUE;
3414 }
3415
3416 /*
3417  * This function searches the nearest visible item based on the given item.
3418  * If the given item is in the gengrid viewport, this returns the given item.
3419  * Or this searches the realized items and checks the nearest fully visible item
3420  * according to the given item's position.
3421  */
3422 static Elm_Object_Item *
3423 _elm_gengrid_nearest_visible_item_get(Evas_Object *obj, Elm_Object_Item *eo_it)
3424 {
3425    Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0; // gengrid viewport geometry
3426    Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0; // given item geometry
3427    Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0; // candidate item geometry
3428    Eina_List *item_list = NULL, *l = NULL;
3429    Elm_Object_Item *eo_item = NULL;
3430    ELM_GENGRID_DATA_GET(obj, sd);
3431    Eina_Bool search_next = EINA_FALSE;
3432
3433    if (!eo_it) return NULL;
3434    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
3435
3436    evas_object_geometry_get(sd->pan_obj, &vx, &vy, &vw, &vh);
3437    evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih); // FIXME: check if the item is realized or not
3438
3439    if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, ix, iy, iw, ih))
3440      {
3441         if (!elm_object_item_disabled_get(eo_it))
3442           return eo_it;
3443         else
3444           search_next = EINA_TRUE;
3445      }
3446
3447    item_list = elm_gengrid_realized_items_get(obj);
3448
3449    if ((iy < vy) || search_next)
3450      {
3451         EINA_LIST_FOREACH(item_list, l, eo_item)
3452           {
3453              ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
3454              evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
3455              if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
3456                  !elm_object_item_disabled_get(eo_item))
3457                {
3458                   eina_list_free(item_list);
3459                   return eo_item;
3460                }
3461           }
3462      }
3463    else
3464      {
3465         EINA_LIST_REVERSE_FOREACH(item_list, l, eo_item)
3466           {
3467              ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
3468              evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
3469              if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
3470                  !elm_object_item_disabled_get(eo_item))
3471                {
3472                   eina_list_free(item_list);
3473                   return eo_item;
3474                }
3475           }
3476      }
3477    eina_list_free(item_list);
3478
3479    return eo_it;
3480 }
3481
3482 EOLIAN static Eina_Bool
3483 _elm_gengrid_elm_widget_on_focus(Eo *obj, Elm_Gengrid_Data *sd)
3484 {
3485    Eina_Bool int_ret = EINA_FALSE;
3486    Elm_Object_Item *eo_it = NULL;
3487    Eina_Bool is_sel = EINA_FALSE;
3488
3489    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_on_focus());
3490    if (!int_ret) return EINA_FALSE;
3491
3492    if (elm_widget_focus_get(obj) && (sd->selected) &&
3493        (!sd->last_selected_item))
3494      {
3495         Elm_Object_Item *sel = eina_list_data_get(sd->selected);
3496         sd->last_selected_item = eo_data_scope_get(sel, ELM_GENGRID_ITEM_CLASS);
3497      }
3498
3499    if (elm_widget_focus_get(obj) && !sd->mouse_down)
3500      {
3501         if (sd->last_focused_item)
3502           eo_it = sd->last_focused_item;
3503         else if (sd->last_selected_item)
3504           eo_it = sd->last_selected_item;
3505         else if (_elm_config->first_item_focus_on_first_focus_in)
3506           {
3507              eo_it = elm_gengrid_first_item_get(obj);
3508              is_sel = EINA_TRUE;
3509           }
3510         if (eo_it)
3511           {
3512              eo_it = _elm_gengrid_nearest_visible_item_get(obj, eo_it);
3513              if (eo_it)
3514                {
3515                   if (!_elm_config->item_select_on_focus_disable && is_sel)
3516                     elm_gengrid_item_selected_set(eo_it, EINA_TRUE);
3517                   else
3518                     elm_object_item_focus_set(eo_it, EINA_TRUE);
3519                   _elm_widget_focus_highlight_start(obj);
3520                }
3521           }
3522      }
3523    else
3524      {
3525         if (sd->focused_item)
3526           {
3527              sd->last_focused_item = sd->focused_item;
3528              _elm_gengrid_item_unfocused(sd->focused_item);
3529           }
3530      }
3531
3532    return EINA_TRUE;
3533 }
3534
3535 static Eina_Bool _elm_gengrid_smart_focus_next_enable = EINA_FALSE;
3536
3537 EOLIAN static Eina_Bool
3538 _elm_gengrid_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *_pd EINA_UNUSED)
3539 {
3540    return _elm_gengrid_smart_focus_next_enable;
3541 }
3542
3543 EOLIAN static Eina_Bool
3544 _elm_gengrid_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *_pd EINA_UNUSED)
3545 {
3546    return EINA_FALSE;
3547 }
3548
3549 EOLIAN static Eina_Bool
3550 _elm_gengrid_elm_widget_focus_next(Eo *obj, Elm_Gengrid_Data *sd, Elm_Focus_Direction dir, Evas_Object **next)
3551 {
3552    Eina_List *items = NULL;
3553    Elm_Gen_Item *it;
3554
3555    EINA_INLIST_FOREACH(sd->items, it)
3556      {
3557         if (it->realized)
3558           items = eina_list_append(items, it->base->access_obj);
3559      }
3560
3561    return elm_widget_focus_list_next_get
3562             (obj, items, eina_list_data_get, dir, next);
3563 }
3564
3565 static void
3566 _mirrored_set(Evas_Object *obj,
3567               Eina_Bool rtl)
3568 {
3569    Elm_Gen_Item *it;
3570
3571    ELM_GENGRID_DATA_GET(obj, sd);
3572
3573    _item_cache_zero(sd);
3574    eo_do_super(obj, MY_CLASS, elm_interface_scrollable_mirrored_set(rtl));
3575
3576    if (!sd->items) return;
3577    it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
3578
3579    while (it)
3580      {
3581         edje_object_mirrored_set(VIEW(it), rtl);
3582         elm_gengrid_item_update(EO_OBJ(it));
3583         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
3584      }
3585 }
3586
3587 EOLIAN static Eina_Bool
3588 _elm_gengrid_elm_widget_theme_apply(Eo *obj, Elm_Gengrid_Data *sd EINA_UNUSED)
3589 {
3590    Eina_Bool int_ret = EINA_FALSE;
3591    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
3592    if (!int_ret) return EINA_FALSE;
3593
3594    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3595
3596    return EINA_TRUE;
3597 }
3598
3599 static void
3600 _item_position_update(Eina_Inlist *list,
3601                       int idx)
3602 {
3603    Elm_Gen_Item *it;
3604
3605    EINA_INLIST_FOREACH(list, it)
3606      {
3607         it->position = idx++;
3608         it->position_update = EINA_TRUE;
3609      }
3610 }
3611
3612 static void
3613 _elm_gengrid_item_del_not_serious(Elm_Gen_Item *it)
3614 {
3615    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
3616    Elm_Object_Item *eo_it = EO_OBJ(it);
3617
3618    eo_do(eo_it, elm_wdg_item_pre_notify_del());
3619    it->generation = sd->generation - 1; /* This means that the item is deleted */
3620
3621    if (it->walking > 0) return;
3622
3623    if (it->selected)
3624      sd->selected = eina_list_remove(sd->selected, eo_it);
3625    if (sd->last_selected_item == eo_it)
3626      sd->last_selected_item = NULL;
3627    if (sd->focused_item == eo_it)
3628      sd->focused_item = NULL;
3629    if (sd->last_focused_item == eo_it)
3630      sd->last_focused_item = NULL;
3631
3632    if (it->itc->func.del)
3633      it->itc->func.del((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it));
3634 }
3635
3636 static void
3637 _elm_gengrid_item_del_serious(Elm_Gen_Item *it)
3638 {
3639    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
3640
3641    sd->item_count--;
3642    _elm_gengrid_item_del_not_serious(it);
3643    sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
3644    if (it->tooltip.del_cb)
3645      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3646    sd->walking -= it->walking;
3647    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
3648    if (it->group)
3649      sd->group_items = eina_list_remove(sd->group_items, it);
3650
3651    ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
3652    ecore_job_del(sd->calc_job);
3653    sd->calc_job = ecore_job_add(sd->calc_cb, sd->obj);
3654
3655    ELM_SAFE_FREE(it->item, free);
3656 }
3657
3658 static void
3659 _item_del(Elm_Gen_Item *it)
3660 {
3661    Evas_Object *obj = WIDGET(it);
3662    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
3663
3664    evas_event_freeze(evas_object_evas_get(obj));
3665    sd->selected = eina_list_remove(sd->selected, it);
3666    if (it->realized) _elm_gengrid_item_unrealize(it, EINA_FALSE);
3667    _elm_gengrid_item_del_serious(it);
3668    elm_gengrid_item_class_unref((Elm_Gengrid_Item_Class *)it->itc);
3669    evas_event_thaw(evas_object_evas_get(obj));
3670    evas_event_thaw_eval(evas_object_evas_get(obj));
3671 }
3672
3673 static void
3674 _scroll_animate_start_cb(Evas_Object *obj,
3675                          void *data EINA_UNUSED)
3676 {
3677    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
3678 }
3679
3680 static void
3681 _scroll_animate_stop_cb(Evas_Object *obj,
3682                         void *data EINA_UNUSED)
3683 {
3684    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
3685 }
3686
3687 static void
3688 _scroll_drag_start_cb(Evas_Object *obj,
3689                       void *data EINA_UNUSED)
3690 {
3691    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_START, NULL);
3692 }
3693
3694 static void
3695 _scroll_drag_stop_cb(Evas_Object *obj,
3696                      void *data EINA_UNUSED)
3697 {
3698    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_STOP, NULL);
3699 }
3700
3701 static void
3702 _edge_left_cb(Evas_Object *obj,
3703               void *data EINA_UNUSED)
3704 {
3705    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3706 }
3707
3708 static void
3709 _edge_right_cb(Evas_Object *obj,
3710                void *data EINA_UNUSED)
3711 {
3712    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3713 }
3714
3715 static void
3716 _edge_top_cb(Evas_Object *obj,
3717              void *data EINA_UNUSED)
3718 {
3719    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3720 }
3721
3722 static void
3723 _edge_bottom_cb(Evas_Object *obj,
3724                 void *data EINA_UNUSED)
3725 {
3726    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3727 }
3728
3729 static void
3730 _scroll_page_change_cb(Evas_Object *obj,
3731                      void *data EINA_UNUSED)
3732 {
3733    evas_object_smart_callback_call(obj, SIG_SCROLL_PAGE_CHANGE, NULL);
3734 }
3735
3736 static void
3737 _scroll_cb(Evas_Object *obj,
3738            void *data EINA_UNUSED)
3739 {
3740    evas_object_smart_callback_call(obj, SIG_SCROLL, NULL);
3741 }
3742
3743 static int
3744 _elm_gengrid_item_compare(const void *data,
3745                           const void *data1)
3746 {
3747    Elm_Gen_Item *it, *item1;
3748    Eina_Compare_Cb cb = NULL;
3749    ptrdiff_t d;
3750
3751    it = ELM_GEN_ITEM_FROM_INLIST(data);
3752    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
3753    if (it && GG_IT(it)->wsd->item_compare_cb)
3754      cb = GG_IT(it)->wsd->item_compare_cb;
3755    else if (item1 && GG_IT(item1)->wsd->item_compare_cb)
3756      cb = GG_IT(item1)->wsd->item_compare_cb;
3757    if (cb && it && item1) return cb(EO_OBJ(it), EO_OBJ(item1));
3758    d = (char *)data - (char *)data1;
3759    if (d < 0) return -1;
3760    if (!d) return 0;
3761    return 1;
3762 }
3763
3764 EOLIAN static void
3765 _elm_gengrid_item_elm_widget_item_disable(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
3766 {
3767    Eina_Bool tmp;
3768    if (it->generation < GG_IT(it)->wsd->generation) return;
3769
3770    if (it->realized)
3771      {
3772         if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
3773           edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
3774         else
3775           edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
3776      }
3777 }
3778
3779 EOLIAN static Eina_Bool
3780 _elm_gengrid_item_elm_widget_item_del_pre(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
3781 {
3782    if (it->walking > 0)
3783      {
3784         _elm_gengrid_item_del_not_serious(it);
3785         return EINA_FALSE;
3786      }
3787
3788    _item_del(it);
3789    return EINA_TRUE;
3790 }
3791
3792 EOLIAN static Evas_Object *
3793 _elm_gengrid_item_elm_widget_item_part_content_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char * part)
3794 {
3795    return edje_object_part_swallow_get(VIEW(it), part);
3796 }
3797
3798 EOLIAN static const char *
3799 _elm_gengrid_item_elm_widget_item_part_text_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char * part)
3800 {
3801    if (!it->itc->func.text_get) return NULL;
3802    return edje_object_part_text_get(VIEW(it), part);
3803 }
3804
3805 EOLIAN static void
3806 _elm_gengrid_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char *emission, const char *source)
3807 {
3808    edje_object_signal_emit(VIEW(it), emission, source);
3809 }
3810
3811 EOLIAN static void
3812 _elm_gengrid_item_elm_widget_item_focus_set(Eo *eo_it, Elm_Gen_Item *it, Eina_Bool focused)
3813 {
3814    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
3815    Evas_Object *obj = WIDGET(it);
3816    ELM_GENGRID_DATA_GET(obj, sd);
3817
3818    if (focused)
3819      {
3820         sd->last_focused_item = eo_it;
3821         if (!elm_object_focus_get(obj))
3822           elm_object_focus_set(obj, EINA_TRUE);
3823
3824         if (!elm_widget_focus_get(obj))
3825           return;
3826
3827         if (eo_it != sd->focused_item)
3828           {
3829              if (sd->focused_item)
3830                _elm_gengrid_item_unfocused(sd->focused_item);
3831              _elm_gengrid_item_focused(eo_it);
3832
3833              /* If item is not realized state, widget couldn't get focus_highlight data. */
3834              if (it->realized)
3835                {
3836                   const char *focus_raise;
3837                   if (elm_widget_focus_highlight_enabled_get(obj))
3838                     {
3839                        edje_object_signal_emit
3840                           (VIEW(it), "elm,state,focused", "elm");
3841                     }
3842
3843                   focus_raise = edje_object_data_get(VIEW(it), "focusraise");
3844                   if ((focus_raise) && (!strcmp(focus_raise, "on")))
3845                     evas_object_raise(VIEW(it));
3846
3847                   _elm_widget_item_highlight_in_theme(obj, eo_it);
3848                   _elm_widget_highlight_in_theme_update(obj);
3849                   _elm_widget_focus_highlight_start(obj);
3850                }
3851           }
3852      }
3853    else
3854      {
3855         if (!elm_widget_focus_get(obj))
3856           return;
3857         _elm_gengrid_item_unfocused(eo_it);
3858      }
3859 }
3860
3861 EOLIAN static Eina_Bool
3862 _elm_gengrid_item_elm_widget_item_focus_get(Eo *eo_it, Elm_Gen_Item *it)
3863 {
3864    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3865    Evas_Object *obj = WIDGET(it);
3866    ELM_GENGRID_DATA_GET(obj, sd);
3867
3868    if (eo_it == sd->focused_item)
3869      return EINA_TRUE;
3870
3871    return EINA_FALSE;
3872 }
3873
3874 static void
3875 _internal_elm_gengrid_clear(Evas_Object *obj,
3876                    Eina_Bool standby)
3877 {
3878    Eina_Inlist *next, *l;
3879
3880    ELM_GENGRID_DATA_GET(obj, sd);
3881    if (!sd->items) return;
3882
3883    if (!standby) sd->generation++;
3884
3885    ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
3886
3887    if (sd->walking > 0)
3888      {
3889         sd->clear_me = EINA_TRUE;
3890         return;
3891      }
3892    evas_event_freeze(evas_object_evas_get(obj));
3893    for (l = sd->items, next = l ? l->next : NULL;
3894         l;
3895         l = next, next = next ? next->next : NULL)
3896      {
3897         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
3898
3899         if (it->generation < sd->generation)
3900           {
3901              Elm_Gen_Item *itn = NULL;
3902
3903              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
3904              if (itn) itn->walking++;  /* prevent early death of subitem */
3905              it->del_cb(it);
3906              eo_del(EO_OBJ(it));
3907              if (itn) itn->walking--;
3908           }
3909      }
3910    sd->clear_me = EINA_FALSE;
3911    sd->pan_changed = EINA_TRUE;
3912    ELM_SAFE_FREE(sd->calc_job, ecore_job_del);
3913    sd->selected = eina_list_free(sd->selected);
3914    if (sd->clear_cb) sd->clear_cb(sd);
3915    sd->pan_x = 0;
3916    sd->pan_y = 0;
3917    sd->minw = 0;
3918    sd->minh = 0;
3919
3920    if (sd->pan_obj)
3921      {
3922         evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
3923         evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
3924      }
3925    eo_do(obj, elm_interface_scrollable_content_region_show(0, 0, 0, 0));
3926    evas_event_thaw(evas_object_evas_get(obj));
3927    evas_event_thaw_eval(evas_object_evas_get(obj));
3928 }
3929
3930 static void
3931 _item_select(Elm_Gen_Item *it)
3932 {
3933    Evas_Object *obj = WIDGET(it);
3934    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
3935    Elm_Object_Item *eo_it = EO_OBJ(it);
3936
3937    if (_is_no_select(it) ||
3938        (it->generation < sd->generation) ||
3939        (it->decorate_it_set))
3940      return;
3941
3942    if (!it->selected)
3943      {
3944         it->selected = EINA_TRUE;
3945         sd->selected = eina_list_append(sd->selected, eo_it);
3946      }
3947    else if ((sd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) &&
3948             (it->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS))
3949      return;
3950
3951    evas_object_ref(obj);
3952    it->walking++;
3953    sd->walking++;
3954    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), eo_it);
3955    if (it->generation == sd->generation)
3956      {
3957         evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, eo_it);
3958         elm_object_item_focus_set(eo_it, EINA_TRUE);
3959      }
3960
3961    it->walking--;
3962    sd->walking--;
3963    if ((sd->clear_me) && (!sd->walking))
3964      _internal_elm_gengrid_clear(WIDGET(it), EINA_TRUE);
3965    else
3966      {
3967         if ((!it->walking) && (it->generation < sd->generation))
3968           {
3969              it->del_cb(it);
3970              eo_del(eo_it);
3971           }
3972         else
3973           sd->last_selected_item = eo_it;
3974      }
3975    evas_object_unref(obj);
3976 }
3977
3978 EOLIAN static Eo *
3979 _elm_gengrid_item_eo_base_constructor(Eo *eo_it, Elm_Gen_Item *it)
3980 {
3981    eo_it = eo_do_super_ret(eo_it, ELM_GENGRID_ITEM_CLASS, eo_it, eo_constructor());
3982    it->base = eo_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
3983    eo_do(eo_it, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_LIST_ITEM));
3984
3985    return eo_it;
3986 }
3987
3988 static Elm_Gen_Item *
3989 _elm_gengrid_item_new(Elm_Gengrid_Data *sd,
3990                       const Elm_Gen_Item_Class *itc,
3991                       const void *data,
3992                       Evas_Smart_Cb func,
3993                       const void *func_data)
3994 {
3995    if (!itc) return NULL;
3996
3997    Eo *eo_it = eo_add(ELM_GENGRID_ITEM_CLASS, sd->obj);
3998    if (!eo_it) return NULL;
3999    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
4000
4001    it->generation = sd->generation;
4002    it->itc = itc;
4003    elm_gengrid_item_class_ref((Elm_Gengrid_Item_Class *)itc);
4004
4005    WIDGET_ITEM_DATA_SET(EO_OBJ(it), data);
4006    it->parent = NULL;
4007    it->func.func = func;
4008    it->func.data = func_data;
4009
4010    it->del_cb = (Ecore_Cb)_item_del;
4011    it->highlight_cb = (Ecore_Cb)_item_highlight;
4012    it->unhighlight_cb = (Ecore_Cb)_item_unhighlight;
4013    it->sel_cb = (Ecore_Cb)_item_select;
4014    it->unsel_cb = (Ecore_Cb)_item_unselect;
4015    it->unrealize_cb = (Ecore_Cb)_item_unrealize_cb;
4016
4017    GG_IT(it) = ELM_NEW(Elm_Gen_Item_Type);
4018    GG_IT(it)->wsd = sd;
4019
4020    it->group = it->itc->item_style &&
4021      (!strcmp(it->itc->item_style, "group_index"));
4022    sd->item_count++;
4023
4024   return it;
4025 }
4026
4027 /* common layout sizing won't apply here */
4028 EOLIAN static void
4029 _elm_gengrid_elm_layout_sizing_eval(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *_pd EINA_UNUSED)
4030 {
4031    return;  /* no-op */
4032 }
4033
4034 EOLIAN static void
4035 _elm_gengrid_evas_object_smart_add(Eo *obj, Elm_Gengrid_Data *priv)
4036 {
4037    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
4038    Elm_Gengrid_Pan_Data *pan_data;
4039    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
4040
4041    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
4042    elm_widget_sub_object_parent_add(obj);
4043
4044    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
4045    evas_object_smart_member_add(priv->hit_rect, obj);
4046    elm_widget_sub_object_add(obj, priv->hit_rect);
4047
4048    /* common scroller hit rectangle setup */
4049    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
4050    evas_object_show(priv->hit_rect);
4051    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
4052
4053    elm_widget_can_focus_set(obj, EINA_TRUE);
4054
4055    priv->calc_cb = (Ecore_Cb)_calc_job;
4056
4057    priv->generation = 1;
4058
4059    if (!elm_layout_theme_set(obj, "gengrid", "base",
4060                              elm_widget_style_get(obj)))
4061      CRI("Failed to set layout!");
4062
4063    eo_do(obj, elm_interface_scrollable_objects_set(wd->resize_obj, priv->hit_rect));
4064
4065    priv->old_h_bounce = bounce;
4066    priv->old_v_bounce = bounce;
4067
4068    eo_do(obj, elm_interface_scrollable_bounce_allow_set(bounce, bounce));
4069
4070    eo_do(obj,
4071          elm_interface_scrollable_animate_start_cb_set
4072          (_scroll_animate_start_cb),
4073          elm_interface_scrollable_animate_stop_cb_set(_scroll_animate_stop_cb),
4074          elm_interface_scrollable_drag_start_cb_set(_scroll_drag_start_cb),
4075          elm_interface_scrollable_drag_stop_cb_set(_scroll_drag_stop_cb),
4076          elm_interface_scrollable_edge_left_cb_set(_edge_left_cb),
4077          elm_interface_scrollable_edge_right_cb_set(_edge_right_cb),
4078          elm_interface_scrollable_edge_top_cb_set(_edge_top_cb),
4079          elm_interface_scrollable_edge_bottom_cb_set(_edge_bottom_cb),
4080          elm_interface_scrollable_scroll_cb_set(_scroll_cb),
4081          elm_interface_scrollable_page_change_cb_set(_scroll_page_change_cb));
4082
4083    priv->align_x = 0.5;
4084    priv->align_y = 0.5;
4085    priv->highlight = EINA_TRUE;
4086    priv->item_cache_max = CACHE_MAX;
4087
4088    priv->pan_obj = eo_add(MY_PAN_CLASS, evas_object_evas_get(obj));
4089    pan_data = eo_data_scope_get(priv->pan_obj, MY_PAN_CLASS);
4090    eo_data_ref(obj, NULL);
4091    pan_data->wobj = obj;
4092    pan_data->wsd = priv;
4093
4094    priv->stack = evas_object_rectangle_add(evas_object_evas_get(obj));
4095    evas_object_smart_member_add(priv->stack, priv->pan_obj);
4096    evas_object_raise(priv->stack);
4097
4098    eo_do(obj, elm_interface_scrollable_extern_pan_set(priv->pan_obj));
4099 }
4100
4101 EOLIAN static void
4102 _elm_gengrid_evas_object_smart_del(Eo *obj, Elm_Gengrid_Data *sd)
4103 {
4104    elm_gengrid_clear(obj);
4105    ELM_SAFE_FREE(sd->pan_obj, evas_object_del);
4106    ELM_SAFE_FREE(sd->stack, evas_object_del);
4107
4108    _item_cache_zero(sd);
4109    ecore_job_del(sd->calc_job);
4110
4111    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
4112 }
4113
4114 EOLIAN static void
4115 _elm_gengrid_evas_object_smart_move(Eo *obj, Elm_Gengrid_Data *sd, Evas_Coord x, Evas_Coord y)
4116 {
4117    eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
4118
4119    evas_object_move(sd->hit_rect, x, y);
4120 }
4121
4122 EOLIAN static void
4123 _elm_gengrid_evas_object_smart_resize(Eo *obj, Elm_Gengrid_Data *sd, Evas_Coord w, Evas_Coord h)
4124 {
4125    eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
4126
4127    evas_object_resize(sd->hit_rect, w, h);
4128 }
4129
4130 EOLIAN static void
4131 _elm_gengrid_evas_object_smart_member_add(Eo *obj, Elm_Gengrid_Data *sd, Evas_Object *member)
4132 {
4133    eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(member));
4134
4135    if (sd->hit_rect)
4136      evas_object_raise(sd->hit_rect);
4137 }
4138
4139 static void
4140 _access_obj_process(Elm_Gengrid_Data * sd, Eina_Bool is_access)
4141 {
4142    Elm_Gen_Item *it;
4143
4144    EINA_INLIST_FOREACH(sd->items, it)
4145      {
4146         if (!it->realized) continue;
4147         if (is_access) _access_widget_item_register(it);
4148         else
4149           _elm_access_widget_item_unregister(it->base);
4150
4151      }
4152 }
4153
4154 EOLIAN static void
4155 _elm_gengrid_elm_widget_access(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Eina_Bool acs)
4156 {
4157    _elm_gengrid_smart_focus_next_enable = acs;
4158    _access_obj_process(sd, _elm_gengrid_smart_focus_next_enable);
4159 }
4160
4161 EAPI Evas_Object *
4162 elm_gengrid_add(Evas_Object *parent)
4163 {
4164    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
4165    Evas_Object *obj = eo_add(MY_CLASS, parent);
4166    return obj;
4167 }
4168
4169 EOLIAN static Eo *
4170 _elm_gengrid_eo_base_constructor(Eo *obj, Elm_Gengrid_Data *sd)
4171 {
4172    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
4173    sd->obj = obj;
4174
4175    eo_do(obj,
4176          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
4177          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
4178          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_TREE_TABLE));
4179
4180    return obj;
4181 }
4182
4183 EOLIAN static void
4184 _elm_gengrid_item_size_set(Eo *obj, Elm_Gengrid_Data *sd, Evas_Coord w, Evas_Coord h)
4185 {
4186    if ((sd->item_width == w) && (sd->item_height == h)) return;
4187    sd->item_width = w;
4188    sd->item_height = h;
4189    ecore_job_del(sd->calc_job);
4190    sd->calc_job = ecore_job_add(_calc_job, obj);
4191 }
4192
4193 EOLIAN static void
4194 _elm_gengrid_item_size_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Evas_Coord *w, Evas_Coord *h)
4195 {
4196    if (w) *w = sd->item_width;
4197    if (h) *h = sd->item_height;
4198 }
4199
4200 EOLIAN static void
4201 _elm_gengrid_group_item_size_set(Eo *obj, Elm_Gengrid_Data *sd, Evas_Coord w, Evas_Coord h)
4202 {
4203    if ((sd->group_item_width == w) && (sd->group_item_height == h)) return;
4204    sd->group_item_width = w;
4205    sd->group_item_height = h;
4206    ecore_job_del(sd->calc_job);
4207    sd->calc_job = ecore_job_add(_calc_job, obj);
4208 }
4209
4210 EOLIAN static void
4211 _elm_gengrid_group_item_size_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Evas_Coord *w, Evas_Coord *h)
4212 {
4213    if (w) *w = sd->group_item_width;
4214    if (h) *h = sd->group_item_height;
4215 }
4216
4217 EOLIAN static void
4218 _elm_gengrid_align_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, double align_x, double align_y)
4219 {
4220    double old_h, old_y;
4221
4222    old_h = sd->align_x;
4223    old_y = sd->align_y;
4224
4225    if (align_x > 1.0)
4226      align_x = 1.0;
4227    else if (align_x < 0.0)
4228      align_x = 0.0;
4229    sd->align_x = align_x;
4230
4231    if (align_y > 1.0)
4232      align_y = 1.0;
4233    else if (align_y < 0.0)
4234      align_y = 0.0;
4235    sd->align_y = align_y;
4236
4237    if ((old_h != sd->align_x) || (old_y != sd->align_y))
4238      evas_object_smart_calculate(sd->pan_obj);
4239 }
4240
4241 EOLIAN static void
4242 _elm_gengrid_align_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, double *align_x, double *align_y)
4243 {
4244    if (align_x) *align_x = sd->align_x;
4245    if (align_y) *align_y = sd->align_y;
4246 }
4247
4248 EOLIAN static Elm_Object_Item*
4249 _elm_gengrid_item_append(Eo *obj, Elm_Gengrid_Data *sd, const Elm_Gengrid_Item_Class *itc, const void *data, Evas_Smart_Cb func, const void *func_data)
4250 {
4251    Elm_Gen_Item *it;
4252
4253    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
4254    if (!it) return NULL;
4255
4256    sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
4257    it->position = sd->item_count;
4258    it->position_update = EINA_TRUE;
4259
4260    if (it->group)
4261      sd->group_items = eina_list_prepend(sd->group_items, it);
4262
4263    ecore_job_del(sd->calc_job);
4264    sd->calc_job = ecore_job_add(_calc_job, obj);
4265
4266    return EO_OBJ(it);
4267 }
4268
4269 EOLIAN static Elm_Object_Item*
4270 _elm_gengrid_item_prepend(Eo *obj, Elm_Gengrid_Data *sd, const Elm_Gengrid_Item_Class *itc, const void *data, Evas_Smart_Cb func, const void *func_data)
4271 {
4272    Elm_Gen_Item *it;
4273
4274    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
4275    if (!it) return NULL;
4276
4277    sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
4278    _item_position_update(sd->items, 0);
4279
4280    if (it->group)
4281      sd->group_items = eina_list_append(sd->group_items, it);
4282
4283    ecore_job_del(sd->calc_job);
4284    sd->calc_job = ecore_job_add(_calc_job, obj);
4285
4286    return EO_OBJ(it);
4287 }
4288
4289 EOLIAN static Elm_Object_Item*
4290 _elm_gengrid_item_insert_before(Eo *obj, Elm_Gengrid_Data *sd, const Elm_Gengrid_Item_Class *itc, const void *data, Elm_Object_Item *eo_relative, Evas_Smart_Cb func, const void *func_data)
4291 {
4292    Elm_Gen_Item *it;
4293    Eina_Inlist *tmp;
4294    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_relative, NULL);
4295    ELM_GENGRID_ITEM_DATA_GET(eo_relative, relative);
4296
4297    ELM_GENGRID_ITEM_CHECK_OR_RETURN(relative, NULL);
4298
4299    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
4300    if (!it) return NULL;
4301    sd->items = eina_inlist_prepend_relative
4302        (sd->items, EINA_INLIST_GET(it),
4303        EINA_INLIST_GET(relative));
4304    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it));
4305    _item_position_update(tmp, relative->position);
4306
4307    if (it->group)
4308      sd->group_items = eina_list_append_relative
4309          (sd->group_items, it, relative->parent);
4310
4311    ecore_job_del(sd->calc_job);
4312    sd->calc_job = ecore_job_add(_calc_job, obj);
4313
4314    return EO_OBJ(it);
4315 }
4316
4317 EOLIAN static Elm_Object_Item*
4318 _elm_gengrid_item_insert_after(Eo *obj, Elm_Gengrid_Data *sd, const Elm_Gengrid_Item_Class *itc, const void *data, Elm_Object_Item *eo_relative, Evas_Smart_Cb func, const void *func_data)
4319 {
4320    Elm_Gen_Item *it;
4321    Eina_Inlist *tmp;
4322    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_relative, NULL);
4323    ELM_GENGRID_ITEM_DATA_GET(eo_relative, relative);
4324
4325    ELM_GENGRID_ITEM_CHECK_OR_RETURN(relative, NULL);
4326
4327    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
4328    if (!it) return NULL;
4329    sd->items = eina_inlist_append_relative
4330        (sd->items, EINA_INLIST_GET(it),
4331        EINA_INLIST_GET(relative));
4332    tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it));
4333    _item_position_update(tmp, relative->position + 1);
4334
4335    if (it->group)
4336      sd->group_items = eina_list_prepend_relative
4337          (sd->group_items, it, relative->parent);
4338
4339    ecore_job_del(sd->calc_job);
4340    sd->calc_job = ecore_job_add(_calc_job, obj);
4341
4342    return EO_OBJ(it);
4343 }
4344
4345 EOLIAN static Elm_Object_Item*
4346 _elm_gengrid_item_sorted_insert(Eo *obj, Elm_Gengrid_Data *sd, const Elm_Gengrid_Item_Class *itc, const void *data, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data)
4347 {
4348    Elm_Gen_Item *it;
4349
4350    it = _elm_gengrid_item_new(sd, itc, data, func, func_data);
4351    if (!it) return NULL;
4352
4353    if (!sd->state)
4354      {
4355         sd->state = eina_inlist_sorted_state_new();
4356         eina_inlist_sorted_state_init(sd->state, sd->items);
4357      }
4358
4359    sd->item_compare_cb = comp;
4360    sd->items = eina_inlist_sorted_state_insert
4361        (sd->items, EINA_INLIST_GET(it), _elm_gengrid_item_compare, sd->state);
4362    _item_position_update(sd->items, 0);
4363
4364    ecore_job_del(sd->calc_job);
4365    sd->calc_job = ecore_job_add(_calc_job, obj);
4366
4367    return EO_OBJ(it);
4368 }
4369
4370 EOLIAN static void
4371 _elm_gengrid_horizontal_set(Eo *obj, Elm_Gengrid_Data *sd, Eina_Bool horizontal)
4372 {
4373    horizontal = !!horizontal;
4374    if (horizontal == sd->horizontal) return;
4375    sd->horizontal = horizontal;
4376
4377    /* Update the items to conform to the new layout */
4378    ecore_job_del(sd->calc_job);
4379    sd->calc_job = ecore_job_add(_calc_job, obj);
4380 }
4381
4382 EOLIAN static Eina_Bool
4383 _elm_gengrid_horizontal_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4384 {
4385    return sd->horizontal;
4386 }
4387
4388 EOLIAN static void
4389 _elm_gengrid_clear(Eo *obj, Elm_Gengrid_Data *_pd EINA_UNUSED)
4390 {
4391    _internal_elm_gengrid_clear(obj, EINA_FALSE);
4392 }
4393
4394 EINA_DEPRECATED EAPI const Evas_Object *
4395 elm_gengrid_item_object_get(const Elm_Object_Item *eo_it)
4396 {
4397    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
4398    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
4399
4400    return VIEW(it);
4401 }
4402
4403 EOLIAN static void
4404 _elm_gengrid_item_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
4405 {
4406    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
4407
4408    if (!it->realized) return;
4409    if (it->want_unrealize) return;
4410
4411    _elm_gengrid_item_unrealize(it, EINA_TRUE);
4412    _item_realize(it);
4413    _item_place(it, it->x, it->y);
4414 }
4415
4416 EOLIAN static void
4417 _elm_gengrid_item_fields_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
4418                                 const char *parts,
4419                                 Elm_Gengrid_Item_Field_Type itf)
4420 {
4421    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
4422
4423    if (!it->realized) return;
4424    if (it->want_unrealize) return;
4425
4426    if ((!itf) || (itf & ELM_GENGRID_ITEM_FIELD_TEXT))
4427      _item_text_realize(it, VIEW(it), &it->texts, parts);
4428
4429    if ((!itf) || (itf & ELM_GENGRID_ITEM_FIELD_CONTENT))
4430      _item_content_realize(it, VIEW(it), &it->contents, "contents", parts);
4431
4432    if ((!itf) || (itf & ELM_GENGRID_ITEM_FIELD_STATE))
4433      _item_state_realize(it, VIEW(it), parts);
4434
4435    _item_place(it, it->x, it->y);
4436 }
4437
4438 EOLIAN static const Elm_Gengrid_Item_Class *
4439 _elm_gengrid_item_item_class_get(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item)
4440 {
4441    if (item->generation < GG_IT(item)->wsd->generation) return NULL;
4442    return item->itc;
4443 }
4444
4445 EOLIAN static void
4446 _elm_gengrid_item_item_class_update(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
4447                                    const Elm_Gengrid_Item_Class *itc)
4448 {
4449    EINA_SAFETY_ON_NULL_RETURN(itc);
4450
4451    if (it->generation < GG_IT(it)->wsd->generation) return;
4452    it->itc = itc;
4453    it->item->nocache_once = EINA_TRUE;
4454
4455    elm_gengrid_item_update(EO_OBJ(it));
4456 }
4457
4458 EOLIAN static void
4459 _elm_gengrid_item_pos_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
4460                          unsigned int *x,
4461                          unsigned int *y)
4462 {
4463    if (x) *x = it->x;
4464    if (y) *y = it->y;
4465 }
4466
4467 EOLIAN static void
4468 _elm_gengrid_multi_select_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Eina_Bool multi)
4469 {
4470    sd->multi = !!multi;
4471 }
4472
4473 EOLIAN static Eina_Bool
4474 _elm_gengrid_multi_select_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4475 {
4476    return sd->multi;
4477 }
4478
4479 EOLIAN static void
4480 _elm_gengrid_multi_select_mode_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Elm_Object_Multi_Select_Mode mode)
4481 {
4482    if (mode >= ELM_OBJECT_MULTI_SELECT_MODE_MAX)
4483      return;
4484
4485    if (sd->multi_select_mode != mode)
4486      sd->multi_select_mode = mode;
4487 }
4488
4489 EOLIAN static Elm_Object_Multi_Select_Mode
4490 _elm_gengrid_multi_select_mode_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4491 {
4492    return sd->multi_select_mode;
4493 }
4494
4495 EOLIAN static Elm_Object_Item*
4496 _elm_gengrid_selected_item_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4497 {
4498    if (sd->selected) return sd->selected->data;
4499    return NULL;
4500 }
4501
4502 EOLIAN static const Eina_List*
4503 _elm_gengrid_selected_items_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4504 {
4505    return sd->selected;
4506 }
4507
4508 EOLIAN static void
4509 _elm_gengrid_item_selected_set(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
4510       Eina_Bool selected)
4511 {
4512    Eina_Bool tmp;
4513    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
4514    if ((it->generation < sd->generation) || eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
4515      return;
4516    selected = !!selected;
4517    if (it->selected == selected) return;
4518
4519    if (selected)
4520      {
4521         if (!sd->multi)
4522           {
4523              while (sd->selected)
4524                {
4525                   Elm_Object_Item *eo_sel = sd->selected->data;
4526                   ELM_GENGRID_ITEM_DATA_GET(eo_sel, sel);
4527                   it->unhighlight_cb(sel);
4528                   it->unsel_cb(sel);
4529                }
4530           }
4531         it->highlight_cb(it);
4532         it->sel_cb(it);
4533         return;
4534      }
4535    it->unhighlight_cb(it);
4536    it->unsel_cb(it);
4537 }
4538
4539 EOLIAN static Eina_Bool
4540 _elm_gengrid_item_selected_get(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
4541 {
4542    return it->selected;
4543 }
4544
4545 EOLIAN static Eina_List*
4546 _elm_gengrid_realized_items_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4547 {
4548    Elm_Gen_Item *it;
4549    Eina_Bool done = EINA_FALSE;
4550
4551    Eina_List *ret = NULL;
4552
4553    EINA_INLIST_FOREACH(sd->items, it)
4554      {
4555         if (it->realized)
4556           {
4557              done = EINA_TRUE;
4558              ret = eina_list_append(ret, EO_OBJ(it));
4559           }
4560         else
4561           {
4562              if (done) break;
4563           }
4564      }
4565
4566    return ret;
4567 }
4568
4569 EOLIAN static void
4570 _elm_gengrid_realized_items_update(Eo *obj, Elm_Gengrid_Data *_pd EINA_UNUSED)
4571 {
4572    Eina_List *list;
4573    Elm_Object_Item *it;
4574
4575    list = elm_gengrid_realized_items_get(obj);
4576    EINA_LIST_FREE(list, it)
4577      elm_gengrid_item_update(it);
4578 }
4579
4580 static Evas_Object *
4581 _elm_gengrid_item_label_create(void *data,
4582                                Evas_Object *obj EINA_UNUSED,
4583                                Evas_Object *tooltip,
4584                                void *it   EINA_UNUSED)
4585 {
4586    Evas_Object *label = elm_label_add(tooltip);
4587    if (!label)
4588      return NULL;
4589    elm_object_style_set(label, "tooltip");
4590    elm_object_text_set(label, data);
4591    return label;
4592 }
4593
4594 static void
4595 _elm_gengrid_item_label_del_cb(void *data,
4596                                Evas_Object *obj EINA_UNUSED,
4597                                void *event_info EINA_UNUSED)
4598 {
4599    eina_stringshare_del(data);
4600 }
4601
4602 EAPI void
4603 elm_gengrid_item_tooltip_text_set(Elm_Object_Item *it,
4604                                   const char *text)
4605 {
4606    eo_do(it, elm_wdg_item_tooltip_text_set(text));
4607 }
4608
4609 EOLIAN static void
4610 _elm_gengrid_item_elm_widget_item_tooltip_text_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char *text)
4611 {
4612    text = eina_stringshare_add(text);
4613    elm_gengrid_item_tooltip_content_cb_set
4614      (EO_OBJ(it), _elm_gengrid_item_label_create, text,
4615      _elm_gengrid_item_label_del_cb);
4616 }
4617
4618 EAPI void
4619 elm_gengrid_item_tooltip_content_cb_set(Elm_Object_Item *item,
4620                                         Elm_Tooltip_Item_Content_Cb func,
4621                                         const void *data,
4622                                         Evas_Smart_Cb del_cb)
4623 {
4624    eo_do(item, elm_wdg_item_tooltip_content_cb_set(func, data, del_cb));
4625 }
4626
4627 EOLIAN static void
4628 _elm_gengrid_item_elm_widget_item_tooltip_content_cb_set(Eo *eo_it, Elm_Gen_Item *it,
4629                                         Elm_Tooltip_Item_Content_Cb func,
4630                                         const void *data,
4631                                         Evas_Smart_Cb del_cb)
4632 {
4633    ELM_GENGRID_ITEM_CHECK_OR_GOTO(it, error);
4634
4635    if ((it->tooltip.content_cb != func) || (it->tooltip.data != data))
4636      {
4637         if (it->tooltip.del_cb)
4638            it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
4639         it->tooltip.content_cb = func;
4640         it->tooltip.data = data;
4641         it->tooltip.del_cb = del_cb;
4642      }
4643    if (VIEW(it))
4644      {
4645         eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS,
4646               elm_wdg_item_tooltip_content_cb_set
4647               (it->tooltip.content_cb, it->tooltip.data, NULL));
4648         eo_do(eo_it,
4649               elm_wdg_item_tooltip_style_set(it->tooltip.style),
4650               elm_wdg_item_tooltip_window_mode_set(it->tooltip.free_size));
4651      }
4652
4653    return;
4654
4655 error:
4656    if (del_cb) del_cb((void *)data, NULL, NULL);
4657 }
4658
4659 EAPI void
4660 elm_gengrid_item_tooltip_unset(Elm_Object_Item *item)
4661 {
4662    eo_do(item, elm_wdg_item_tooltip_unset());
4663 }
4664
4665 EOLIAN static void
4666 _elm_gengrid_item_elm_widget_item_tooltip_unset(Eo *eo_it, Elm_Gen_Item *it)
4667 {
4668    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
4669
4670    if ((VIEW(it)) && (it->tooltip.content_cb))
4671      eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS,
4672            elm_wdg_item_tooltip_unset());
4673
4674    if (it->tooltip.del_cb)
4675      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
4676    it->tooltip.del_cb = NULL;
4677    it->tooltip.content_cb = NULL;
4678    it->tooltip.data = NULL;
4679    it->tooltip.free_size = EINA_FALSE;
4680    if (it->tooltip.style)
4681      eo_do(eo_it, elm_wdg_item_tooltip_style_set(NULL));
4682 }
4683
4684 EAPI void
4685 elm_gengrid_item_tooltip_style_set(Elm_Object_Item *it,
4686                                    const char *style)
4687 {
4688    eo_do(it, elm_wdg_item_tooltip_style_set(style));
4689 }
4690
4691 EOLIAN static void
4692 _elm_gengrid_item_elm_widget_item_tooltip_style_set(Eo *eo_it, Elm_Gen_Item *it,
4693                                    const char *style)
4694 {
4695    eina_stringshare_replace(&it->tooltip.style, style);
4696    if (VIEW(it)) eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS,
4697          elm_wdg_item_tooltip_style_set(style));
4698 }
4699
4700 EAPI const char *
4701 elm_gengrid_item_tooltip_style_get(const Elm_Object_Item *it)
4702 {
4703    const char *ret;
4704    return eo_do_ret(it, ret, elm_wdg_item_tooltip_style_get());
4705 }
4706
4707 EOLIAN static const char *
4708 _elm_gengrid_item_elm_widget_item_tooltip_style_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
4709 {
4710    return it->tooltip.style;
4711 }
4712
4713 EAPI Eina_Bool
4714 elm_gengrid_item_tooltip_window_mode_set(Elm_Object_Item *it,
4715                                          Eina_Bool disable)
4716 {
4717    Eina_Bool ret;
4718    return eo_do_ret(it, ret, elm_wdg_item_tooltip_window_mode_set(disable));
4719 }
4720
4721 EOLIAN static Eina_Bool
4722 _elm_gengrid_item_elm_widget_item_tooltip_window_mode_set(Eo *eo_it, Elm_Gen_Item *it,
4723                                    Eina_Bool disable)
4724 {
4725    it->tooltip.free_size = disable;
4726    if (VIEW(it))
4727      {
4728         Eina_Bool ret;
4729         eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS,
4730             ret = elm_wdg_item_tooltip_window_mode_set(disable));
4731         return ret;
4732      }
4733
4734    return EINA_TRUE;
4735 }
4736
4737 EAPI Eina_Bool
4738 elm_gengrid_item_tooltip_window_mode_get(const Elm_Object_Item *it)
4739 {
4740    Eina_Bool ret;
4741    return eo_do_ret(it, ret, elm_wdg_item_tooltip_window_mode_get());
4742 }
4743
4744 EOLIAN static Eina_Bool
4745 _elm_gengrid_item_elm_widget_item_tooltip_window_mode_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
4746 {
4747    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4748
4749    return it->tooltip.free_size;
4750 }
4751
4752 EAPI void
4753 elm_gengrid_item_cursor_set(Elm_Object_Item *it,
4754                             const char *cursor)
4755 {
4756    eo_do(it, elm_wdg_item_cursor_set(cursor));
4757 }
4758
4759 EOLIAN static void
4760 _elm_gengrid_item_elm_widget_item_cursor_set(Eo *eo_it, Elm_Gen_Item *it,
4761                             const char *cursor)
4762 {
4763    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
4764
4765    eina_stringshare_replace(&it->mouse_cursor, cursor);
4766    if (VIEW(it)) eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS,
4767          elm_wdg_item_cursor_set(cursor));
4768 }
4769
4770 EAPI const char *
4771 elm_gengrid_item_cursor_get(const Elm_Object_Item *it)
4772 {
4773    const char *ret;
4774    return eo_do_ret(it, ret, elm_wdg_item_cursor_get());
4775 }
4776
4777 EAPI void
4778 elm_gengrid_item_cursor_unset(Elm_Object_Item *item)
4779 {
4780    eo_do(item, elm_wdg_item_cursor_unset());
4781 }
4782
4783 EOLIAN static void
4784 _elm_gengrid_item_elm_widget_item_cursor_unset(Eo *eo_it, Elm_Gen_Item *it)
4785 {
4786    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
4787    if (!it->mouse_cursor)
4788      return;
4789
4790    if (VIEW(it)) eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS,
4791          elm_wdg_item_cursor_unset());
4792
4793    ELM_SAFE_FREE(it->mouse_cursor, eina_stringshare_del);
4794 }
4795
4796 EAPI void
4797 elm_gengrid_item_cursor_style_set(Elm_Object_Item *it,
4798                                   const char *style)
4799 {
4800    eo_do(it, elm_wdg_item_cursor_style_set(style));
4801 }
4802
4803 EAPI const char *
4804 elm_gengrid_item_cursor_style_get(const Elm_Object_Item *it)
4805 {
4806    const char *ret;
4807    return eo_do_ret(it, ret, elm_wdg_item_cursor_style_get());
4808 }
4809
4810 EAPI void
4811 elm_gengrid_item_cursor_engine_only_set(Elm_Object_Item *eo_it,
4812                                         Eina_Bool engine_only)
4813 {
4814    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
4815    it->cursor_engine_only = engine_only;
4816    if (it->realized)
4817      eo_do(eo_it, elm_wdg_item_cursor_engine_only_set(engine_only));
4818 }
4819
4820 EAPI Eina_Bool
4821 elm_gengrid_item_cursor_engine_only_get(const Elm_Object_Item *eo_it)
4822 {
4823    ELM_GENGRID_ITEM_DATA_GET(eo_it, it);
4824    Eina_Bool ret;
4825    if (it->realized)
4826      return eo_do_ret(eo_it, ret, elm_wdg_item_cursor_engine_only_get());
4827    else return it->cursor_engine_only;
4828 }
4829
4830 EAPI void
4831 elm_gengrid_reorder_mode_start(Evas_Object *obj, Ecore_Pos_Map tween_mode)
4832 {
4833    ELM_GENGRID_CHECK(obj);
4834    ELM_GENGRID_DATA_GET(obj, sd);
4835
4836    sd->reorder_mode = EINA_TRUE;
4837    sd->reorder.tween_mode = tween_mode;
4838    sd->reorder.type = ELM_GENGRID_REORDER_TYPE_NORMAL;
4839 }
4840
4841 EAPI void
4842 elm_gengrid_reorder_mode_stop(Evas_Object *obj)
4843 {
4844    ELM_GENGRID_CHECK(obj);
4845    ELM_GENGRID_DATA_GET(obj, sd);
4846
4847    sd->reorder_mode = EINA_FALSE;
4848    sd->reorder.tween_mode = -1;
4849 }
4850
4851 EAPI void
4852 elm_gengrid_reorder_type_set(Evas_Object *obj, Elm_Gengrid_Reorder_Type type)
4853 {
4854    ELM_GENGRID_CHECK(obj);
4855    ELM_GENGRID_DATA_GET(obj, sd);
4856
4857    sd->reorder.type = type;
4858 }
4859
4860 EOLIAN static void
4861 _elm_gengrid_reorder_mode_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Eina_Bool reorder_mode)
4862 {
4863    sd->reorder_mode = !!reorder_mode;
4864 }
4865
4866 EOLIAN static Eina_Bool
4867 _elm_gengrid_reorder_mode_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
4868 {
4869    return sd->reorder_mode;
4870 }
4871
4872 EAPI void
4873 elm_gengrid_bounce_set(Evas_Object *obj,
4874                        Eina_Bool h_bounce,
4875                        Eina_Bool v_bounce)
4876 {
4877    ELM_GENGRID_CHECK(obj);
4878    eo_do(obj, elm_interface_scrollable_bounce_allow_set(h_bounce, v_bounce));
4879 }
4880
4881 EOLIAN static void
4882 _elm_gengrid_elm_interface_scrollable_bounce_allow_set(Eo *obj, Elm_Gengrid_Data *sd EINA_UNUSED, Eina_Bool h_bounce, Eina_Bool v_bounce)
4883 {
4884    eo_do_super(obj, MY_CLASS, elm_interface_scrollable_bounce_allow_set(!!h_bounce, !!v_bounce));
4885 }
4886
4887 EAPI void
4888 elm_gengrid_bounce_get(const Evas_Object *obj,
4889                        Eina_Bool *h_bounce,
4890                        Eina_Bool *v_bounce)
4891 {
4892    ELM_GENGRID_CHECK(obj);
4893    eo_do( obj, elm_interface_scrollable_bounce_allow_get(h_bounce, v_bounce));
4894 }
4895
4896 EOLIAN static void
4897 _elm_gengrid_page_relative_set(Eo *obj, Elm_Gengrid_Data *_pd EINA_UNUSED, double h_pagerel, double v_pagerel)
4898 {
4899    Evas_Coord pagesize_h;
4900    Evas_Coord pagesize_v;
4901
4902    eo_do( obj, elm_interface_scrollable_paging_get(NULL, NULL, &pagesize_h, &pagesize_v));
4903    eo_do( obj, elm_interface_scrollable_paging_set
4904      (h_pagerel, v_pagerel, pagesize_h, pagesize_v));
4905 }
4906
4907 EOLIAN static void
4908 _elm_gengrid_page_relative_get(Eo *obj, Elm_Gengrid_Data *_pd EINA_UNUSED, double *h_pagerel, double *v_pagerel)
4909 {
4910    eo_do( obj, elm_interface_scrollable_paging_get(h_pagerel, v_pagerel, NULL, NULL));
4911 }
4912
4913 EOLIAN static void
4914 _elm_gengrid_page_size_set(Eo *obj, Elm_Gengrid_Data *_pd EINA_UNUSED, Evas_Coord h_pagesize, Evas_Coord v_pagesize)
4915 {
4916    double pagerel_h;
4917    double pagerel_v;
4918
4919    eo_do( obj, elm_interface_scrollable_paging_get(&pagerel_h, &pagerel_v, NULL, NULL));
4920    eo_do( obj, elm_interface_scrollable_paging_set
4921      (pagerel_h, pagerel_v, h_pagesize, v_pagesize));
4922 }
4923
4924 EAPI void
4925 elm_gengrid_current_page_get(const Evas_Object *obj,
4926                              int *h_pagenumber,
4927                              int *v_pagenumber)
4928 {
4929    ELM_GENGRID_CHECK(obj);
4930    eo_do( obj, elm_interface_scrollable_current_page_get(h_pagenumber, v_pagenumber));
4931 }
4932
4933 EAPI void
4934 elm_gengrid_last_page_get(const Evas_Object *obj,
4935                           int *h_pagenumber,
4936                           int *v_pagenumber)
4937 {
4938    ELM_GENGRID_CHECK(obj);
4939    eo_do( obj, elm_interface_scrollable_last_page_get(h_pagenumber, v_pagenumber));
4940 }
4941
4942 EINA_DEPRECATED EAPI void
4943 elm_gengrid_page_show(const Evas_Object *obj,
4944                       int h_pagenumber,
4945                       int v_pagenumber)
4946 {
4947    ELM_GENGRID_CHECK(obj);
4948    eo_do( obj, elm_interface_scrollable_page_show(h_pagenumber, v_pagenumber));
4949 }
4950
4951 EINA_DEPRECATED EAPI void
4952 elm_gengrid_page_bring_in(const Evas_Object *obj,
4953                           int h_pagenumber,
4954                           int v_pagenumber)
4955 {
4956    ELM_GENGRID_CHECK(obj);
4957    eo_do( obj, elm_interface_scrollable_page_bring_in(h_pagenumber, v_pagenumber));
4958 }
4959
4960 EAPI void
4961 elm_gengrid_scroller_policy_set(Evas_Object *obj,
4962                                 Elm_Scroller_Policy policy_h,
4963                                 Elm_Scroller_Policy policy_v)
4964 {
4965    ELM_GENGRID_CHECK(obj);
4966    eo_do(obj, elm_interface_scrollable_policy_set(policy_h, policy_v));
4967 }
4968
4969 EOLIAN static void
4970 _elm_gengrid_elm_interface_scrollable_policy_set(Eo *obj, Elm_Gengrid_Data *sd EINA_UNUSED, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
4971 {
4972    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
4973        (policy_v >= ELM_SCROLLER_POLICY_LAST))
4974      return;
4975
4976    eo_do_super(obj, MY_CLASS, elm_interface_scrollable_policy_set(policy_h, policy_v));
4977 }
4978
4979 EAPI void
4980 elm_gengrid_scroller_policy_get(const Evas_Object *obj,
4981                                 Elm_Scroller_Policy *policy_h,
4982                                 Elm_Scroller_Policy *policy_v)
4983 {
4984    ELM_GENGRID_CHECK(obj);
4985    eo_do( obj, elm_interface_scrollable_policy_get(policy_h, policy_v));
4986 }
4987
4988 EOLIAN static void
4989 _elm_gengrid_elm_interface_scrollable_policy_get(Eo *obj, Elm_Gengrid_Data *sd EINA_UNUSED, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
4990 {
4991    Elm_Scroller_Policy s_policy_h, s_policy_v;
4992
4993    eo_do_super(obj, MY_CLASS, elm_interface_scrollable_policy_get(&s_policy_h, &s_policy_v));
4994    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
4995    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
4996 }
4997
4998 EOLIAN static Elm_Object_Item*
4999 _elm_gengrid_first_item_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5000 {
5001    if (!sd->items) return NULL;
5002
5003    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
5004
5005    while ((it) && (it->generation < sd->generation))
5006      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5007
5008    return EO_OBJ(it);
5009 }
5010
5011 EOLIAN static Elm_Object_Item*
5012 _elm_gengrid_at_xy_item_get(const Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Evas_Coord x, Evas_Coord y, int *xposret, int *yposret)
5013 {
5014    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
5015
5016    Evas_Coord l = 0, r = 0, t = 0, b = 0; /* left, right, top, bottom */
5017    Eina_Bool init = EINA_TRUE;
5018
5019    while ((it) && (it->generation < sd->generation))
5020      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5021
5022    if (it)
5023      do
5024        {
5025           Evas_Coord itx, ity;
5026           Evas_Coord itw, ith;
5027           evas_object_geometry_get(VIEW(it), &itx, &ity, &itw, &ith);
5028
5029           /* Record leftmost, rightmost, top, bottom cords to set posret */
5030           if ((itw > 0) && (ith > 0) && (itx >= 0) && (ity >= 0))
5031             {  /* A scroller, ignore items in negative cords,or not rendered */
5032                if (init)
5033                  {
5034                     l = itx;
5035                     r = itx + itw;
5036                     t = ity;
5037                     b = ity + ith;
5038                     init = EINA_FALSE;
5039                  }
5040                else
5041                  {
5042                     if (itx < l)
5043                       l = itx;
5044                     if ((itx + itw) > r)
5045                       r = itx + itw;
5046                     if (ity < t)
5047                       t = ity;
5048                     if ((ity + ith) > b)
5049                       b = ity + ith;
5050                  }
5051             }
5052
5053           if (ELM_RECTS_INTERSECT
5054                 (itx, ity, itw, ith, x, y, 1, 1))
5055             {
5056                if (yposret)
5057                  {
5058                     if (y <= (ity + (ith / 4))) *yposret = -1;
5059                     else if (y >= (ity + ith - (ith / 4)))
5060                       *yposret = 1;
5061                     else *yposret = 0;
5062                  }
5063
5064                if (xposret)
5065                  {
5066                     if (x <= (itx + (itw / 4))) *xposret = -1;
5067                     else if (x >= (itx + itw - (itw / 4)))
5068                       *xposret = 1;
5069                     else *xposret = 0;
5070                  }
5071
5072                return EO_OBJ(it);
5073             }
5074
5075        } while ((it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next)));
5076
5077    /* No item found, tell the user if hit left/right/top/bottom of items */
5078    if (xposret)
5079      {
5080         *xposret = 0;
5081         if (x < l)
5082           *xposret = (-1);
5083         else if (x > r)
5084           *xposret = (1);
5085      }
5086
5087    if (yposret)
5088      {
5089         *yposret = 0;
5090         if (y < t)
5091           *yposret = (-1);
5092         else if (y > b)
5093           *yposret = (1);
5094      }
5095
5096    return NULL;
5097 }
5098
5099 EOLIAN static Elm_Object_Item*
5100 _elm_gengrid_last_item_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5101 {
5102    if (!sd->items) return NULL;
5103
5104    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
5105    while ((it) && (it->generation < sd->generation))
5106      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5107
5108    return EO_OBJ(it);
5109 }
5110
5111 EOLIAN static Elm_Object_Item *
5112 _elm_gengrid_item_next_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
5113 {
5114    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
5115
5116    while (it)
5117      {
5118         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
5119         if ((it) && (it->generation == GG_IT(it)->wsd->generation)) break;
5120      }
5121
5122    return EO_OBJ(it);
5123 }
5124
5125 EOLIAN static Elm_Object_Item *
5126 _elm_gengrid_item_prev_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
5127 {
5128    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, NULL);
5129
5130    while (it)
5131      {
5132         it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
5133         if ((it) && (it->generation == GG_IT(it)->wsd->generation)) break;
5134      }
5135
5136    return EO_OBJ(it);
5137 }
5138
5139 EOLIAN static void
5140 _elm_gengrid_item_show(Eo *eo_it, Elm_Gen_Item *it, Elm_Gengrid_Item_Scrollto_Type type)
5141 {
5142    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
5143
5144    if ((it->generation < sd->generation)) return;
5145
5146    sd->show_region = EINA_TRUE;
5147    sd->show_it = eo_it;
5148    sd->scroll_to_type = type;
5149
5150    _item_show_region(sd);
5151 }
5152
5153 EOLIAN static void
5154 _elm_gengrid_item_bring_in(Eo *eo_it, Elm_Gen_Item *it, Elm_Gengrid_Item_Scrollto_Type type)
5155 {
5156    ELM_GENGRID_DATA_GET_FROM_ITEM(it, sd);
5157
5158    if (it->generation < sd->generation) return;
5159
5160    sd->bring_in = EINA_TRUE;
5161    sd->bring_in_it = eo_it;
5162    sd->scroll_to_type = type;
5163
5164    _item_show_region(sd);
5165 }
5166
5167 EOLIAN static void
5168 _elm_gengrid_filled_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Eina_Bool fill)
5169 {
5170    fill = !!fill;
5171    if (sd->filled != fill)
5172      sd->filled = fill;
5173 }
5174
5175 EOLIAN static Eina_Bool
5176 _elm_gengrid_filled_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5177 {
5178    return sd->filled;
5179 }
5180
5181 EOLIAN static unsigned int
5182 _elm_gengrid_items_count(const Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5183 {
5184    return sd->item_count;
5185 }
5186
5187 EAPI Elm_Gengrid_Item_Class *
5188 elm_gengrid_item_class_new(void)
5189 {
5190    Elm_Gengrid_Item_Class *itc;
5191
5192    itc = calloc(1, sizeof(Elm_Gengrid_Item_Class));
5193    if (!itc)
5194      return NULL;
5195    itc->version = CLASS_ALLOCATED;
5196    itc->refcount = 1;
5197    itc->delete_me = EINA_FALSE;
5198
5199    return itc;
5200 }
5201
5202 EAPI void
5203 elm_gengrid_item_class_free(Elm_Gengrid_Item_Class *itc)
5204 {
5205    if (!itc || (itc->version != CLASS_ALLOCATED)) return;
5206
5207    if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5208    if (itc->refcount > 0) elm_gengrid_item_class_unref(itc);
5209    else
5210      {
5211         itc->version = 0;
5212         free(itc);
5213      }
5214 }
5215
5216 EAPI void
5217 elm_gengrid_item_class_ref(Elm_Gengrid_Item_Class *itc)
5218 {
5219    if (itc && (itc->version == CLASS_ALLOCATED))
5220      {
5221         itc->refcount++;
5222         if (itc->refcount == 0) itc->refcount--;
5223      }
5224 }
5225
5226 EAPI void
5227 elm_gengrid_item_class_unref(Elm_Gengrid_Item_Class *itc)
5228 {
5229    if (itc && (itc->version == CLASS_ALLOCATED))
5230      {
5231         if (itc->refcount > 0) itc->refcount--;
5232         if (itc->delete_me && (!itc->refcount))
5233           elm_gengrid_item_class_free(itc);
5234      }
5235 }
5236
5237 EOLIAN static void
5238 _elm_gengrid_select_mode_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Elm_Object_Select_Mode mode)
5239 {
5240    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5241      return;
5242
5243    if (sd->select_mode != mode)
5244      sd->select_mode = mode;
5245 }
5246
5247 EOLIAN static Elm_Object_Select_Mode
5248 _elm_gengrid_select_mode_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5249 {
5250    return sd->select_mode;
5251 }
5252
5253 EOLIAN static void
5254 _elm_gengrid_highlight_mode_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Eina_Bool highlight)
5255 {
5256    sd->highlight = !!highlight;
5257 }
5258
5259 EOLIAN static Eina_Bool
5260 _elm_gengrid_highlight_mode_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5261 {
5262    return sd->highlight;
5263 }
5264
5265 EOLIAN static int
5266 _elm_gengrid_item_index_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
5267 {
5268    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, -1);
5269
5270    return it->position;
5271 }
5272
5273 EOLIAN static void
5274 _elm_gengrid_item_select_mode_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
5275                                  Elm_Object_Select_Mode mode)
5276 {
5277    if (it->generation < GG_IT(it)->wsd->generation) return;
5278    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5279      return;
5280
5281    if (it->select_mode != mode)
5282      it->select_mode = mode;
5283
5284    if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5285      elm_gengrid_item_update(EO_OBJ(it));
5286 }
5287
5288 EOLIAN static Elm_Object_Select_Mode
5289 _elm_gengrid_item_select_mode_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
5290 {
5291    ELM_GENGRID_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
5292
5293    return it->select_mode;
5294 }
5295
5296 EOLIAN Elm_Atspi_State_Set
5297 _elm_gengrid_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_it, Elm_Gen_Item *it EINA_UNUSED)
5298 {
5299    Elm_Atspi_State_Set ret;
5300    Eina_Bool sel;
5301
5302    eo_do_super(eo_it, ELM_GENGRID_ITEM_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
5303
5304    eo_do(eo_it, sel = elm_obj_gengrid_item_selected_get());
5305
5306    STATE_TYPE_SET(ret, ELM_ATSPI_STATE_SELECTABLE);
5307
5308    if (sel)
5309       STATE_TYPE_SET(ret, ELM_ATSPI_STATE_SELECTED);
5310
5311    return ret;
5312 }
5313
5314 EOLIAN char*
5315 _elm_gengrid_item_elm_interface_atspi_accessible_name_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
5316 {
5317    char *ret;
5318    Eina_Strbuf *buf;
5319
5320    buf = eina_strbuf_new();
5321
5322    if (it->itc->func.text_get)
5323      {
5324         Eina_List *texts;
5325         const char *key;
5326
5327         texts =
5328            elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
5329
5330         EINA_LIST_FREE(texts, key)
5331           {
5332              char *str_markup = it->itc->func.text_get
5333                 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
5334
5335              char *str_utf8 = _elm_util_mkup_to_text(str_markup);
5336
5337              free(str_markup);
5338
5339              if (str_utf8)
5340                {
5341                   if (eina_strbuf_length_get(buf) > 0)
5342                     eina_strbuf_append(buf, ", ");
5343                   eina_strbuf_append(buf, str_utf8);
5344                   free(str_utf8);
5345                }
5346           }
5347      }
5348
5349    ret = eina_strbuf_string_steal(buf);
5350    eina_strbuf_free(buf);
5351    return ret;
5352 }
5353
5354 EOLIAN Eina_List*
5355 _elm_gengrid_item_elm_interface_atspi_accessible_children_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
5356 {
5357    Eina_List *ret = NULL;
5358    if (VIEW(it))
5359      {
5360         Eina_List *parts;
5361         const char *key;
5362         parts = elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "contents"));
5363
5364         EINA_LIST_FREE(parts, key)
5365           {
5366              Evas_Object *part;
5367              part = edje_object_part_swallow_get(VIEW(it), key);
5368              if (part && eo_isa(part, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
5369                ret = eina_list_append(ret, part);
5370           }
5371      }
5372    return ret;
5373 }
5374
5375 EAPI Elm_Object_Item *
5376 elm_gengrid_nth_item_get(const Evas_Object *obj, unsigned int nth)
5377 {
5378    Elm_Gen_Item *it = NULL;
5379    Eina_Accessor *a;
5380    void *data;
5381
5382    ELM_GENGRID_CHECK(obj) NULL;
5383    ELM_GENGRID_DATA_GET(obj, sd);
5384
5385    if (!sd->items) return NULL;
5386
5387    a = eina_inlist_accessor_new(sd->items);
5388    if (!a) return NULL;
5389    if (eina_accessor_data_get(a, nth, &data))
5390      it = ELM_GEN_ITEM_FROM_INLIST(data);
5391    eina_accessor_free(a);
5392    return EO_OBJ(it);
5393 }
5394
5395 EOLIAN static void
5396 _elm_gengrid_elm_widget_focus_highlight_geometry_get(const Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
5397 {
5398    Evas_Coord ox, oy, oh, ow, item_x = 0, item_y = 0, item_w = 0, item_h = 0;
5399
5400    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
5401
5402    if (sd->focused_item)
5403      {
5404         ELM_GENGRID_ITEM_DATA_GET(sd->focused_item, focus_it);
5405         evas_object_geometry_get(VIEW(focus_it), &item_x, &item_y, &item_w, &item_h);
5406         elm_widget_focus_highlight_focus_part_geometry_get(VIEW(focus_it), &item_x, &item_y, &item_w, &item_h);
5407      }
5408
5409    *x = item_x;
5410    *y = item_y;
5411    *w = item_w;
5412    *h = item_h;
5413
5414    if (sd->horizontal)
5415      {
5416         if (item_x < ox)
5417           {
5418              *x = ox;
5419           }
5420         else if (item_x > (ox + ow - item_w))
5421           {
5422              *x = ox + ow - item_w;
5423           }
5424      }
5425    else
5426      {
5427         if (item_y < oy)
5428           {
5429              *y = oy;
5430           }
5431         else if (item_y > (oy + oh - item_h))
5432           {
5433              *y = oy + oh - item_h;
5434           }
5435      }
5436 }
5437
5438 EOLIAN static Elm_Object_Item *
5439 _elm_gengrid_elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5440 {
5441    return sd->focused_item;
5442 }
5443
5444 EOLIAN static void
5445 _elm_gengrid_elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd, Eina_Bool enable)
5446 {
5447    sd->item_loop_enable = !!enable;
5448 }
5449
5450 EOLIAN static Eina_Bool
5451 _elm_gengrid_elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5452 {
5453    return sd->item_loop_enable;
5454 }
5455
5456 EOLIAN static void
5457 _elm_gengrid_wheel_disabled_set(Eo *obj, Elm_Gengrid_Data *sd, Eina_Bool disabled)
5458 {
5459    disabled = !!disabled;
5460    if (sd->wheel_disabled != disabled)
5461      eo_do(obj,
5462            elm_interface_scrollable_wheel_disabled_set(disabled));
5463
5464    sd->wheel_disabled = disabled;
5465 }
5466
5467 EOLIAN static Eina_Bool
5468 _elm_gengrid_wheel_disabled_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5469 {
5470    return sd->wheel_disabled;
5471 }
5472
5473 EOLIAN static void
5474 _elm_gengrid_class_constructor(Eo_Class *klass)
5475 {
5476    if (_elm_config->access_mode)
5477       _elm_gengrid_smart_focus_next_enable = EINA_TRUE;
5478
5479    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
5480 }
5481
5482 EOLIAN const Elm_Atspi_Action *
5483 _elm_gengrid_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd EINA_UNUSED)
5484 {
5485    static Elm_Atspi_Action atspi_actions[] = {
5486           { "move,prior", "move", "prior", _key_action_move},
5487           { "move,next", "move", "next", _key_action_move},
5488           { "move,left", "move", "left", _key_action_move},
5489           { "move,left,multi", "move", "left_multi", _key_action_move},
5490           { "move,right", "move", "right", _key_action_move},
5491           { "move,right,multi", "move", "right_multi", _key_action_move},
5492           { "move,up", "move", "up", _key_action_move},
5493           { "move,up,multi", "move", "up_multi", _key_action_move},
5494           { "move,down", "move", "down", _key_action_move},
5495           { "move,down,multi", "move", "down_multi", _key_action_move},
5496           { "move,first", "move", "first", _key_action_move},
5497           { "move,last", "move", "last", _key_action_move},
5498           { "select", "select", NULL, _key_action_select},
5499           { "select,multi", "select", "multi", _key_action_select},
5500           { "escape", "escape", NULL, _key_action_escape},
5501           { NULL, NULL, NULL, NULL }
5502    };
5503    return &atspi_actions[0];
5504 }
5505
5506 EOLIAN Eina_List*
5507 _elm_gengrid_elm_interface_atspi_accessible_children_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *sd)
5508 {
5509    Eina_List *ret = NULL;
5510    Elm_Gen_Item *it;
5511
5512    EINA_INLIST_FOREACH(sd->items, it)
5513       ret = eina_list_append(ret, EO_OBJ(it));
5514
5515    return ret;
5516 }
5517
5518 EOLIAN Elm_Atspi_State_Set
5519 _elm_gengrid_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Gengrid_Data *sd EINA_UNUSED)
5520 {
5521    Elm_Atspi_State_Set ret;
5522
5523    eo_do_super(obj, ELM_GENGRID_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
5524
5525    STATE_TYPE_SET(ret, ELM_ATSPI_STATE_MANAGES_DESCENDANTS);
5526
5527    return ret;
5528 }
5529
5530 EOLIAN int
5531 _elm_gengrid_elm_interface_atspi_selection_selected_children_count_get(Eo *objm EINA_UNUSED, Elm_Gengrid_Data *pd)
5532 {
5533    return eina_list_count(pd->selected);
5534 }
5535
5536 EOLIAN Eo*
5537 _elm_gengrid_elm_interface_atspi_selection_selected_child_get(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd, int child_idx)
5538 {
5539    return eina_list_nth(pd->selected, child_idx);
5540 }
5541
5542 EOLIAN Eina_Bool
5543 _elm_gengrid_elm_interface_atspi_selection_child_select(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd, int child_index)
5544 {
5545    Elm_Gen_Item *item;
5546    if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
5547      {
5548         EINA_INLIST_FOREACH(pd->items, item)
5549           {
5550              if (child_index-- == 0)
5551                {
5552                   elm_gengrid_item_selected_set(EO_OBJ(item), EINA_TRUE);
5553                   return EINA_TRUE;
5554                }
5555           }
5556      }
5557    return EINA_FALSE;
5558 }
5559
5560 EOLIAN Eina_Bool
5561 _elm_gengrid_elm_interface_atspi_selection_selected_child_deselect(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd, int child_index)
5562 {
5563    Eo *item;
5564    Eina_List *l;
5565
5566    EINA_LIST_FOREACH(pd->selected, l, item)
5567      {
5568         if (child_index-- == 0)
5569           {
5570              elm_gengrid_item_selected_set(item, EINA_FALSE);
5571              return EINA_TRUE;
5572           }
5573      }
5574    return EINA_FALSE;
5575 }
5576
5577 EOLIAN Eina_Bool
5578 _elm_gengrid_elm_interface_atspi_selection_is_child_selected(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd, int child_index)
5579 {
5580    Elm_Gen_Item *item;
5581
5582    EINA_INLIST_FOREACH(pd->items, item)
5583      {
5584         if (child_index-- == 0)
5585           {
5586              return elm_gengrid_item_selected_get(EO_OBJ(item));
5587           }
5588      }
5589    return EINA_FALSE;
5590 }
5591
5592 EOLIAN Eina_Bool
5593 _elm_gengrid_elm_interface_atspi_selection_all_children_select(Eo *obj, Elm_Gengrid_Data *pd)
5594 {
5595    Elm_Gen_Item *item;
5596
5597    if (!elm_gengrid_multi_select_get(obj))
5598      return EINA_FALSE;
5599
5600    EINA_INLIST_FOREACH(pd->items, item)
5601       elm_gengrid_item_selected_set(EO_OBJ(item), EINA_TRUE);
5602
5603    return EINA_TRUE;
5604 }
5605
5606 EOLIAN Eina_Bool
5607 _elm_gengrid_elm_interface_atspi_selection_clear(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd)
5608 {
5609    return _all_items_deselect(pd);
5610 }
5611
5612 EOLIAN Eina_Bool
5613 _elm_gengrid_elm_interface_atspi_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_Gengrid_Data *pd, int child_index)
5614 {
5615    Elm_Gen_Item *item;
5616    if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
5617      {
5618         EINA_INLIST_FOREACH(pd->items, item)
5619           {
5620              if (child_index-- == 0)
5621                {
5622                   elm_gengrid_item_selected_set(EO_OBJ(item), EINA_FALSE);
5623                   return EINA_TRUE;
5624                }
5625           }
5626      }
5627    return EINA_FALSE;
5628 }
5629
5630 #include "elm_gengrid.eo.c"
5631 #include "elm_gengrid_item.eo.c"