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