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