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