2 # include "elementary_config.h"
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
7 #define ELM_WIDGET_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
9 #define EFL_UI_L10N_PROTECTED
10 #define EFL_ACCESS_COMPONENT_PROTECTED
12 #include <Elementary.h>
14 #include "elm_hoversel_eo.h"
15 #include "elm_hoversel_item_eo.h"
16 #include "elm_widget_hoversel.h"
17 #include "efl_ui_button_legacy_eo.h"
19 #define MY_CLASS ELM_HOVERSEL_CLASS
21 #define MY_CLASS_NAME "Elm_Hoversel"
22 #define MY_CLASS_NAME_LEGACY "elm_hoversel"
24 static const char SIG_SELECTED[] = "selected";
25 static const char SIG_DISMISSED[] = "dismissed";
26 static const char SIG_EXPANDED[] = "expanded";
27 static const char SIG_ITEM_FOCUSED[] = "item,focused";
28 static const char SIG_ITEM_UNFOCUSED[] = "item,unfocused";
29 static const char SIG_CLICKED[] = "clicked";
31 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
35 {SIG_ITEM_FOCUSED, ""},
36 {SIG_ITEM_UNFOCUSED, ""},
37 {SIG_CLICKED, ""}, /**< handled by parent button class */
38 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
39 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
43 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
44 static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
45 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
46 static Eina_Bool _hoversel_efl_ui_widget_widget_input_event_handler(Eo *obj, Elm_Hoversel_Data *_pd EINA_UNUSED, const Efl_Event *eo_event, Evas_Object *src EINA_UNUSED);
48 static const Elm_Action key_actions[] = {
49 {"move", _key_action_move},
50 {"activate", _key_action_activate},
51 {"escape", _key_action_escape},
56 _elm_hoversel_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
61 EINA_LIST_FOREACH(sd->items, l, it)
62 elm_wdg_item_translate(it);
64 efl_ui_l10n_translation_update(efl_super(obj, MY_CLASS));
67 EOLIAN static Eina_Error
68 _elm_hoversel_efl_ui_widget_theme_apply(Eo *obj, Elm_Hoversel_Data *sd)
70 Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
72 Elm_Object_Item *eo_item;
74 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_ERROR_GENERIC);
79 style = eina_stringshare_add(elm_widget_style_get(obj));
82 snprintf(buf, sizeof(buf), "hoversel_horizontal/%s", style);
84 snprintf(buf, sizeof(buf), "hoversel_vertical/%s", style);
86 /* hoversel's style has an extra bit: orientation */
87 elm_widget_theme_style_set(obj, buf);
89 int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
90 if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
92 elm_widget_theme_style_set(obj, style);
95 efl_ui_mirrored_set(sd->hover, efl_ui_mirrored_get(obj));
98 snprintf(buf, sizeof(buf), "hoversel_horizontal_entry/%s", style);
100 snprintf(buf, sizeof(buf), "hoversel_vertical_entry/%s", style);
102 EINA_LIST_FOREACH(sd->items, l, eo_item)
104 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
105 elm_object_style_set(VIEW(item), buf);
106 elm_object_text_set(VIEW(item), item->label);
107 elm_widget_disabled_set
108 (VIEW(item), elm_wdg_item_disabled_get(eo_item));
111 eina_stringshare_del(style);
112 elm_hoversel_hover_end(obj);
118 _on_hover_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
120 const char *dismissstr;
122 dismissstr = elm_layout_data_get(obj, "dismiss");
124 if (!dismissstr || strcmp(dismissstr, "on"))
125 elm_hoversel_hover_end(data); // for backward compatibility
126 // TIZEN_ONLY(20160812): emit dismiss signal to all items for fade out effect
127 else if (dismissstr && !strcmp(dismissstr, "on"))
130 Elm_Object_Item *eo_item;
132 ELM_HOVERSEL_DATA_GET(data, sd);
133 EINA_LIST_FOREACH(sd->items, l, eo_item)
135 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, it);
136 elm_layout_signal_emit(VIEW(it), "elm,action,dismiss", "elm");
143 _auto_update(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
145 Elm_Hoversel_Item_Data *item = data;
146 Evas_Object *obj2 = WIDGET(item);
148 ELM_HOVERSEL_DATA_GET(obj2, sd);
154 ic = elm_object_part_content_unset(obj2, "icon");
155 ELM_SAFE_FREE(ic, evas_object_del);
159 ic = elm_icon_add(obj2);
160 elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
161 if (item->icon_type == ELM_ICON_FILE)
162 elm_image_file_set(ic, item->icon_file, item->icon_group);
163 else if (item->icon_type == ELM_ICON_STANDARD)
164 elm_icon_standard_set(ic, item->icon_file);
165 elm_object_part_content_set(obj2, "icon", ic);
169 elm_object_text_set(obj2, item->label);
172 Elm_Object_Item *eo_item;
174 EINA_LIST_FOREACH(sd->items, l, eo_item)
176 if (eo_item == EO_OBJ(item))
177 elm_wdg_item_signal_emit(eo_item, "elm,state,selected", "elm");
179 elm_wdg_item_signal_emit(eo_item, "elm,state,unselected", "elm");
185 _on_item_clicked(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
187 Elm_Hoversel_Item_Data *item = data;
188 Evas_Object *obj2 = WIDGET(item);
189 Elm_Object_Item *eo_it = EO_OBJ(item);
191 ELM_HOVERSEL_DATA_GET(obj2, sd);
193 if (item->func) item->func((void *)WIDGET_ITEM_DATA_GET(eo_it), obj2, eo_it);
194 evas_object_smart_callback_call(obj2, "selected", eo_it);
196 evas_object_event_callback_add(sd->hover, EVAS_CALLBACK_DEL, _auto_update, item);
198 elm_hoversel_hover_end(obj2);
202 _item_focus_changed(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
204 Elm_Hoversel_Item_Data *it = data;
206 if (efl_ui_focus_object_focus_get(event->object))
208 efl_event_callback_legacy_call(WIDGET(it), ELM_HOVERSEL_EVENT_ITEM_FOCUSED, EO_OBJ(it));
212 efl_event_callback_legacy_call(WIDGET(it), ELM_HOVERSEL_EVENT_ITEM_UNFOCUSED, EO_OBJ(it));
216 //TIZEN_ONLY(20180607): Restore legacy focus
218 _item_focused_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
220 Elm_Hoversel_Item_Data *it = data;
222 efl_event_callback_legacy_call(WIDGET(it), ELM_HOVERSEL_EVENT_ITEM_FOCUSED, EO_OBJ(it));
226 _item_unfocused_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
229 Elm_Hoversel_Item_Data *it = data;
231 efl_event_callback_legacy_call(WIDGET(it), ELM_HOVERSEL_EVENT_ITEM_UNFOCUSED, EO_OBJ(it));
236 _create_scroller(Evas_Object *obj, Elm_Hoversel_Data *sd)
239 sd->tbl = elm_table_add(obj);
240 evas_object_size_hint_align_set(sd->tbl, EVAS_HINT_FILL, EVAS_HINT_FILL);
241 evas_object_size_hint_weight_set(sd->tbl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
244 sd->spacer = evas_object_rectangle_add(evas_object_evas_get(obj));
245 evas_object_size_hint_align_set(sd->spacer, EVAS_HINT_FILL, EVAS_HINT_FILL);
246 evas_object_size_hint_weight_set(sd->spacer, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
247 evas_object_color_set(sd->spacer, 0, 0, 0, 0);
248 elm_table_pack(sd->tbl, sd->spacer, 0, 0, 1, 1);
251 sd->scr = elm_scroller_add(sd->tbl);
252 elm_object_style_set(sd->scr, "popup/no_inset_shadow");
253 evas_object_size_hint_weight_set(sd->scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
254 evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
257 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
258 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_TRUE);
259 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
263 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
264 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_FALSE);
265 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
267 elm_table_pack(sd->tbl, sd->scr, 0, 0, 1, 1);
268 evas_object_show(sd->scr);
272 _sizing_eval(void *data)
274 Evas_Object *obj = data;
275 Elm_Object_Item *eo_item;
277 const char *max_size_str;
280 Evas_Coord box_w = -1, box_h = -1;
281 Eina_Rectangle base, adjusted, parent;
283 ELM_HOVERSEL_DATA_GET(obj, sd);
284 EINA_SAFETY_ON_NULL_RETURN(sd);
287 sd->resize_job = NULL;
289 if ((!sd->expanded) || (!sd->bx)) return;
291 elm_layout_signal_emit(sd->hover, "elm,state,align,default", "elm");
292 edje_object_message_signal_process(elm_layout_edje_get(sd->hover));
294 EINA_LIST_FOREACH(sd->items, l, eo_item)
296 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
297 efl_canvas_group_calculate(VIEW(item));
300 elm_box_recalculate(sd->bx);
301 evas_object_size_hint_combined_min_get(sd->bx, &box_w, &box_h);
303 max_size_str = elm_layout_data_get(sd->hover, "max_size");
305 max_size = (int)(atoi(max_size_str)
306 * elm_config_scale_get()
307 * elm_object_scale_get(obj))
308 / edje_object_base_scale_get(elm_layout_edje_get(sd->hover));
312 adjusted.w = (max_size > 0) ? MIN(box_w, max_size) : box_w ;
318 adjusted.h = (max_size > 0) ? MIN(box_h, max_size) : box_h ;
321 evas_object_size_hint_min_set(sd->spacer, adjusted.w, adjusted.h);
322 if (!sd->last_location)
323 sd->last_location = elm_hover_best_content_location_get(sd->hover, !sd->horizontal + 1);
325 evas_object_geometry_get(sd->hover_parent, &parent.x, &parent.y, &parent.w, &parent.h);
326 if (efl_isa(sd->hover_parent, EFL_UI_WIN_CLASS))
332 snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", sd->last_location);
333 edje_object_part_geometry_get(elm_layout_edje_get(sd->hover), buf, &adjusted.x, &adjusted.y, NULL, NULL);
334 adjusted.x += parent.x;
335 adjusted.y += parent.y;
337 evas_object_geometry_get(obj, &base.x, &base.y, &base.w, NULL);
341 if ((sd->last_location) && (!strcmp(sd->last_location, "left")))
343 adjusted.x = parent.x;
344 if ((adjusted.x + adjusted.w) > base.x)
345 adjusted.w = base.x - adjusted.x;
349 if ((adjusted.x + adjusted.w) > (parent.x + parent.w))
350 adjusted.w = (parent.x + parent.w) - adjusted.x;
353 if (adjusted.y < 0) adjusted.y = parent.y;
354 if ((adjusted.y + adjusted.h) > (parent.y + parent.h))
355 adjusted.h = (parent.y + parent.h) - adjusted.y;
359 if ((sd->last_location) && (!strcmp(sd->last_location, "top")))
361 adjusted.y = parent.y;
362 if ((adjusted.y + adjusted.h) > base.y)
363 adjusted.h = base.y - adjusted.y;
367 if ((adjusted.y + adjusted.h) > (parent.y + parent.h))
368 adjusted.h = (parent.y + parent.h) - adjusted.y;
371 if (adjusted.x < 0) adjusted.x = parent.x;
372 if ((adjusted.x + adjusted.w) > (parent.x + parent.w))
374 if ((base.x + base.w) > (parent.x + parent.w))
376 if (efl_ui_mirrored_get(obj))
377 elm_object_signal_emit(sd->hover, "elm,state,align,right", "elm");
379 elm_object_signal_emit(sd->hover, "elm,state,align,default", "elm");
381 if ((base.x + base.w - adjusted.w) < parent.x)
382 adjusted.w = base.x + base.w - parent.x;
386 if (efl_ui_mirrored_get(obj))
387 elm_object_signal_emit(sd->hover, "elm,state,align,default", "elm");
389 elm_object_signal_emit(sd->hover, "elm,state,align,right", "elm");
391 // TIZEN_ONLY(20201116): elm_hoversel: Fix spacer size calculation
392 // NOTE: Resize spacer(adjusted) only when left area of spacer is
393 // smaller than size of spacer.
394 if ((base.x + base.w ) - parent.x < adjusted.w)
395 adjusted.w = (base.x + base.w ) - parent.x;
396 //adjusted.w = (parent.x + parent.w) - adjusted.x;
401 evas_object_size_hint_min_set(sd->spacer, adjusted.w, adjusted.h);
403 // TIZEN_ONLY(20150828): shrink item width expanding over hover parent
408 Evas_Coord it_w, it_h;
410 l = elm_box_children_get(sd->bx);
411 EINA_LIST_FREE(l, it)
413 evas_object_size_hint_min_get(it, &it_w, &it_h);
414 if (it_w > adjusted.w)
415 evas_object_size_hint_min_set(it, adjusted.w, it_h);
422 _hover_del(Evas_Object *obj)
424 Elm_Object_Item *eo_item;
427 ELM_HOVERSEL_DATA_GET(obj, sd);
429 //TIZEN_ONLY(20230112): Handle default label object
430 _elm_win_default_label_obj_remove(obj);
433 sd->expanded = EINA_FALSE;
435 EINA_LIST_FOREACH(sd->items, l, eo_item)
437 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, it);
438 elm_box_unpack(sd->bx, VIEW(it));
439 evas_object_hide(VIEW(it));
441 ELM_SAFE_FREE(sd->hover, evas_object_del);
444 sd->last_location = NULL;
446 efl_event_callback_legacy_call(obj, ELM_HOVERSEL_EVENT_DISMISSED, NULL);
450 _hover_end_finished(void *data,
451 Evas_Object *obj EINA_UNUSED,
452 const char *emission EINA_UNUSED,
453 const char *source EINA_UNUSED)
455 const char *dismissstr;
457 ELM_HOVERSEL_DATA_GET(data, sd);
459 dismissstr = elm_layout_data_get(sd->hover, "dismiss");
461 if (dismissstr && !strcmp(dismissstr, "on"))
468 _access_info_cb(void *data, Evas_Object *obj)
471 Elm_Hoversel_Item_Data *it;
475 it = (Elm_Hoversel_Item_Data *)data;
476 if (it->label) return strdup(it->label);
480 txt = elm_widget_access_info_get(obj);
481 if (!txt) txt = elm_layout_text_get(obj, NULL);
482 if (txt) return strdup(txt);
489 _access_widget_item_register(Elm_Hoversel_Data *sd)
492 Elm_Object_Item *eo_item;
495 EINA_LIST_FOREACH(sd->items, l, eo_item)
497 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
498 _elm_access_widget_item_register(item->base);
499 ai = _elm_access_info_get(item->base->access_obj);
500 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, item);
505 _access_state_cb(void *data EINA_UNUSED, Evas_Object *obj)
507 if (elm_widget_disabled_get(obj))
508 return strdup(E_("State: Disabled"));
515 _hover_key_down(void *data, const Efl_Event *ev)
517 ELM_HOVERSEL_DATA_GET(ev->object, sd);
519 _hoversel_efl_ui_widget_widget_input_event_handler(data, sd, ev, ev->object);
523 _activate(Evas_Object *obj)
525 Elm_Object_Item *eo_item;
529 ELM_HOVERSEL_DATA_GET(obj, sd);
533 elm_hoversel_hover_end(obj);
537 if (elm_widget_disabled_get(obj)) return;
538 if (!sd->items) return;
540 sd->expanded = EINA_TRUE;
542 efl_wref_add(elm_hover_add(sd->hover_parent), &sd->hover);
543 efl_event_callback_add(sd->hover, EFL_EVENT_KEY_DOWN, _hover_key_down, obj);
545 elm_widget_sub_object_add(obj, sd->hover);
546 evas_object_layer_set(sd->hover, evas_object_layer_get(sd->hover_parent));
549 snprintf(buf, sizeof(buf), "hoversel_horizontal/%s",
550 elm_widget_style_get(obj));
552 snprintf(buf, sizeof(buf), "hoversel_vertical/%s",
553 elm_widget_style_get(obj));
555 elm_object_style_set(sd->hover, buf);
557 evas_object_smart_callback_add(sd->hover, "clicked", _on_hover_clicked, obj);
558 elm_layout_signal_callback_add
559 (sd->hover, "elm,action,hide,finished", "elm", _hover_end_finished, obj);
560 elm_hover_target_set(sd->hover, obj);
562 /* hover's content */
563 sd->bx = elm_box_add(sd->hover);
564 elm_box_homogeneous_set(sd->bx, EINA_TRUE);
565 elm_box_horizontal_set(sd->bx, sd->horizontal);
566 evas_object_size_hint_align_set(sd->bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
567 evas_object_size_hint_weight_set(sd->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
569 EINA_LIST_FOREACH(sd->items, l, eo_item)
571 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
572 evas_object_show(VIEW(item));
573 elm_box_pack_end(sd->bx, VIEW(item));
576 _create_scroller(obj, sd);
577 elm_object_content_set(sd->scr, sd->bx);
580 ELM_SAFE_FREE(sd->resize_job, ecore_job_del);
582 elm_object_part_content_set(sd->hover, sd->last_location, sd->tbl);
584 if (_elm_config->access_mode) _access_widget_item_register(sd);
586 efl_event_callback_legacy_call(obj, ELM_HOVERSEL_EVENT_EXPANDED, NULL);
587 efl_canvas_group_calculate(sd->hover);
590 //TIZEN_ONLY(20230112): Handle default label object
591 _elm_win_default_label_obj_append(obj);
594 evas_object_show(sd->hover);
598 _on_clicked(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
604 _on_parent_del(void *data, const Efl_Event *ev EINA_UNUSED)
606 elm_hoversel_hover_parent_set(data, NULL);
610 _elm_hoversel_item_elm_widget_item_disable(Eo *eo_hoversel_it,
611 Elm_Hoversel_Item_Data *hoversel_it EINA_UNUSED)
613 elm_widget_disabled_set
614 (VIEW(hoversel_it), elm_wdg_item_disabled_get(eo_hoversel_it));
618 _elm_hoversel_item_elm_widget_item_part_text_set(Eo *eo_it EINA_UNUSED,
619 Elm_Hoversel_Item_Data *it,
623 if (part && strcmp(part, "default")) return;
624 eina_stringshare_replace(&it->label, label);
627 elm_object_text_set(VIEW(it), label);
631 _elm_hoversel_item_elm_widget_item_part_text_get(const Eo *eo_it EINA_UNUSED,
632 Elm_Hoversel_Item_Data *it,
635 if (part && strcmp(part, "default")) return NULL;
640 _elm_hoversel_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED,
641 Elm_Hoversel_Item_Data *it,
642 const char *emission,
645 elm_object_signal_emit(VIEW(it), emission, source);
649 _elm_hoversel_item_elm_widget_item_style_set(Eo *eo_it EINA_UNUSED,
650 Elm_Hoversel_Item_Data *it,
653 elm_object_style_set(VIEW(it), style);
656 EOLIAN static const char *
657 _elm_hoversel_item_elm_widget_item_style_get(const Eo *eo_it EINA_UNUSED,
658 Elm_Hoversel_Item_Data *it)
660 return elm_object_style_get(VIEW(it));
664 _elm_hoversel_item_elm_widget_item_item_focus_set(Eo *eo_it EINA_UNUSED,
665 Elm_Hoversel_Item_Data *it,
668 elm_object_focus_set(VIEW(it), focused);
671 EOLIAN static Eina_Bool
672 _elm_hoversel_item_elm_widget_item_item_focus_get(const Eo *eo_it EINA_UNUSED,
673 Elm_Hoversel_Item_Data *it)
675 return efl_ui_focus_object_focus_get(VIEW(it));
679 _elm_hoversel_item_efl_object_destructor(Eo *eo_item, Elm_Hoversel_Item_Data *item)
681 ELM_HOVERSEL_DATA_GET_OR_RETURN(WIDGET(item), sd);
683 evas_object_event_callback_del_full(sd->hover, EVAS_CALLBACK_DEL, _auto_update, eo_item);
684 elm_hoversel_hover_end(WIDGET(item));
685 sd->items = eina_list_remove(sd->items, eo_item);
686 eina_stringshare_del(item->label);
687 eina_stringshare_del(item->icon_file);
688 eina_stringshare_del(item->icon_group);
690 efl_destructor(efl_super(eo_item, ELM_HOVERSEL_ITEM_CLASS));
694 _on_geometry_changed(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
696 Elm_Hoversel_Data *pd = data;
699 ELM_SAFE_FREE(pd->resize_job, ecore_job_del);
701 pd->resize_job = ecore_job_add(_sizing_eval, obj);
705 _on_parent_resize(void *data, const Efl_Event *ev EINA_UNUSED)
707 Evas_Object *obj = (Evas_Object *)data;
708 ELM_HOVERSEL_DATA_GET(obj, pd);
710 _on_geometry_changed(pd, NULL, obj, NULL);
714 _elm_hoversel_efl_canvas_group_group_add(Eo *obj, Elm_Hoversel_Data *pd)
716 efl_canvas_group_add(efl_super(obj, MY_CLASS));
718 evas_object_smart_callback_add(obj, "clicked", _on_clicked, obj);
719 //What are you doing here?
720 efl_ui_widget_theme_apply(obj);
722 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_geometry_changed, pd);
723 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _on_geometry_changed, pd);
726 (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("Hoversel"));
727 _elm_access_callback_set
728 (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL);
729 _elm_access_callback_set
730 (_elm_access_info_get(obj), ELM_ACCESS_STATE, _access_state_cb, obj);
734 _elm_hoversel_efl_canvas_group_group_del(Eo *obj, Elm_Hoversel_Data *sd)
736 Elm_Object_Item *eo_item;
738 EINA_LIST_FREE(sd->items, eo_item)
740 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, it);
741 ELM_SAFE_FREE(VIEW(it), evas_object_del);
744 elm_hoversel_hover_parent_set(obj, NULL);
746 efl_canvas_group_del(efl_super(obj, MY_CLASS));
750 _elm_hoversel_efl_gfx_entity_visible_set(Eo *obj, Elm_Hoversel_Data *sd, Eina_Bool vis)
752 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
755 efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
757 efl_gfx_entity_visible_set(sd->hover, vis);
761 _elm_hoversel_efl_ui_autorepeat_autorepeat_enabled_set(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd EINA_UNUSED, Eina_Bool enabled)
764 ERR("You cannot enable autorepeat on this object");
765 efl_ui_autorepeat_enabled_set(efl_super(obj, MY_CLASS), EINA_FALSE);
769 elm_hoversel_add(Evas_Object *parent)
771 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
772 return elm_legacy_add(MY_CLASS, parent);
776 _elm_hoversel_efl_object_constructor(Eo *obj, Elm_Hoversel_Data *_pd EINA_UNUSED)
778 obj = efl_constructor(efl_super(obj, MY_CLASS));
779 efl_ui_autorepeat_enabled_set(obj, EINA_FALSE);
780 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
781 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
782 //TIZEN_ONLY(20220812): Set COMBO_BOX role for Hoversel
783 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_COMBO_BOX);
785 legacy_object_focus_handle(obj);
786 elm_hoversel_hover_parent_set(obj, efl_parent_get(obj));
792 _elm_hoversel_efl_object_destructor(Eo *obj, Elm_Hoversel_Data *_pd)
795 ELM_SAFE_FREE(_pd->resize_job, ecore_job_del);
797 elm_obj_hoversel_clear(obj);
798 efl_destructor(efl_super(obj, MY_CLASS));
801 EFL_CALLBACKS_ARRAY_DEFINE(_on_parent,
802 { EFL_EVENT_DEL, _on_parent_del },
803 { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _on_parent_resize });
806 _elm_hoversel_hover_parent_set(Eo *obj, Elm_Hoversel_Data *sd, Evas_Object *parent)
808 if (sd->hover_parent)
810 efl_event_callback_array_del(sd->hover_parent, _on_parent(), obj);
813 sd->hover_parent = parent;
814 if (sd->hover_parent)
816 efl_event_callback_array_add(sd->hover_parent, _on_parent(), obj);
820 EOLIAN static Evas_Object*
821 _elm_hoversel_hover_parent_get(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
823 return sd->hover_parent;
827 _elm_hoversel_horizontal_set(Eo *obj, Elm_Hoversel_Data *sd, Eina_Bool horizontal)
829 sd->horizontal = !!horizontal;
835 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
836 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_TRUE);
837 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
841 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
842 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_FALSE);
843 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
847 efl_ui_widget_theme_apply(obj);
850 EOLIAN static Eina_Bool
851 _elm_hoversel_horizontal_get(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
853 return sd->horizontal;
857 _elm_hoversel_hover_begin(Eo *obj, Elm_Hoversel_Data *sd)
859 if (sd->hover) return;
865 _elm_hoversel_hover_end(Eo *obj, Elm_Hoversel_Data *sd)
867 const char *dismissstr;
869 if (!sd->hover) return;
871 dismissstr = elm_layout_data_get(sd->hover, "dismiss");
873 if (dismissstr && !strcmp(dismissstr, "on"))
875 elm_hover_dismiss(sd->hover);
880 } // for backward compatibility
881 elm_object_focus_set(obj, EINA_TRUE);
884 EOLIAN static Eina_Bool
885 _elm_hoversel_expanded_get(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
887 return (sd->hover) ? EINA_TRUE : EINA_FALSE;
891 _elm_hoversel_clear(Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
895 EINA_LIST_FREE(sd->items, it)
901 EOLIAN static const Eina_List*
902 _elm_hoversel_items_get(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
908 _elm_hoversel_item_efl_object_constructor(Eo *obj, Elm_Hoversel_Item_Data *it)
910 obj = efl_constructor(efl_super(obj, ELM_HOVERSEL_ITEM_CLASS));
911 it->base = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
916 EOLIAN static Elm_Object_Item*
917 _elm_hoversel_item_add(Eo *obj, Elm_Hoversel_Data *sd, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data)
919 Evas_Object *bt, *ic;
922 Eo *eo_item = efl_add(ELM_HOVERSEL_ITEM_CLASS, obj);
923 if (!eo_item) return NULL;
925 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
927 item->label = eina_stringshare_add(label);
928 item->icon_file = eina_stringshare_add(icon_file);
929 item->icon_type = icon_type;
931 WIDGET_ITEM_DATA_SET(eo_item, data);
934 snprintf(buf, sizeof(buf), "hoversel_horizontal_entry/%s",
935 elm_widget_style_get(obj));
937 snprintf(buf, sizeof(buf), "hoversel_vertical_entry/%s",
938 elm_widget_style_get(obj));
940 bt = elm_button_add(obj);
942 efl_ui_mirrored_set(bt, efl_ui_mirrored_get(obj));
943 elm_object_style_set(bt, buf);
944 elm_object_text_set(bt, item->label);
948 ic = elm_icon_add(bt);
949 elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
950 if (item->icon_type == ELM_ICON_FILE)
951 elm_image_file_set(ic, item->icon_file, item->icon_group);
952 else if (item->icon_type == ELM_ICON_STANDARD)
953 elm_icon_standard_set(ic, item->icon_file);
954 elm_object_part_content_set(bt, "icon", ic);
957 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
958 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
959 evas_object_smart_callback_add(bt, "clicked", _on_item_clicked, item);
961 //TIZEN_ONLY(20180607): Restore legacy focus
962 evas_object_smart_callback_add(bt, "focused", _item_focused_cb, item);
963 evas_object_smart_callback_add(bt, "unfocused", _item_unfocused_cb, item);
965 efl_event_callback_add(bt, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED, _item_focus_changed, item);
968 sd->items = eina_list_append(sd->items, eo_item);
974 _elm_hoversel_item_icon_set(Eo *eo_item EINA_UNUSED,
975 Elm_Hoversel_Item_Data *item,
976 const char *icon_file,
977 const char *icon_group,
978 Elm_Icon_Type icon_type)
980 eina_stringshare_replace(&item->icon_file, icon_file);
981 eina_stringshare_replace(&item->icon_group, icon_group);
983 item->icon_type = icon_type;
987 _elm_hoversel_item_icon_get(const Eo *eo_item EINA_UNUSED,
988 Elm_Hoversel_Item_Data *item,
989 const char **icon_file,
990 const char **icon_group,
991 Elm_Icon_Type *icon_type)
993 if (icon_file) *icon_file = item->icon_file;
994 if (icon_group) *icon_group = item->icon_group;
995 if (icon_type) *icon_type = item->icon_type;
998 static Elm_Object_Item *
999 item_focused_get(Elm_Hoversel_Data *sd)
1001 Elm_Object_Item *eo_item;
1004 EINA_LIST_FOREACH(sd->items, l, eo_item)
1006 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
1007 if (elm_object_focus_get(VIEW(item)))
1014 item_focused_set(Elm_Object_Item *eo_item, Eina_Bool focus)
1016 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, item);
1017 if (elm_object_disabled_get(VIEW(item)))
1019 elm_object_focus_set(VIEW(item), focus);
1024 _key_action_move(Evas_Object *obj, const char *params)
1027 Elm_Object_Item *focused_item, *eo_item;
1028 Eina_Bool ret, next = EINA_FALSE;
1030 ELM_HOVERSEL_DATA_GET(obj, sd);
1031 const char *dir = params;
1033 if (!sd->hover) return EINA_FALSE;
1034 _elm_widget_focus_auto_show(obj);
1035 if (!strcmp(dir, "down") || !strcmp(dir, "right"))
1037 focused_item = item_focused_get(sd);
1038 EINA_LIST_FOREACH(sd->items, l, eo_item)
1042 ret = item_focused_set(eo_item, EINA_TRUE);
1043 if (ret) return EINA_TRUE;
1045 if (eo_item == focused_item) next = EINA_TRUE;
1047 EINA_LIST_FOREACH(sd->items, l, eo_item)
1049 if (eo_item == focused_item) return EINA_FALSE;
1051 ret = item_focused_set(eo_item, EINA_TRUE);
1052 if (ret) return EINA_TRUE;
1056 else if (!strcmp(dir, "up") || !strcmp(dir, "left"))
1058 focused_item = item_focused_get(sd);
1059 EINA_LIST_REVERSE_FOREACH(sd->items, l, eo_item)
1063 ret = item_focused_set(eo_item, EINA_TRUE);
1064 if (ret) return EINA_TRUE;
1066 if (eo_item == focused_item) next = EINA_TRUE;
1068 EINA_LIST_REVERSE_FOREACH(sd->items, l, eo_item)
1070 if (eo_item == focused_item) return EINA_FALSE;
1072 ret = item_focused_set(eo_item, EINA_TRUE);
1073 if (ret) return EINA_TRUE;
1077 else return EINA_FALSE;
1081 _key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
1088 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
1090 ELM_HOVERSEL_DATA_GET(obj, sd);
1091 if (!sd->hover) return EINA_FALSE;
1092 elm_hoversel_hover_end(obj);
1096 // _hoversel_elm_widget_widget_event()
1097 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(hoversel, Elm_Hoversel_Data)
1099 EOLIAN static Eina_Bool
1100 _elm_hoversel_efl_ui_widget_widget_input_event_handler(Eo *obj, Elm_Hoversel_Data *sd, const Efl_Event *eo_event, Evas_Object *src)
1102 if (efl_ui_widget_input_event_handler(efl_super(obj, MY_CLASS), eo_event, src))
1103 return EINA_TRUE; // note: this was FALSE but likely wrong
1105 return _hoversel_efl_ui_widget_widget_input_event_handler(obj, sd, eo_event, src);
1109 _elm_hoversel_class_constructor(Efl_Class *klass)
1111 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1114 EOLIAN const Efl_Access_Action_Data *
1115 _elm_hoversel_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *pd EINA_UNUSED)
1117 static Efl_Access_Action_Data atspi_actions[] = {
1118 { "activate", "activate", NULL, _key_action_activate},
1119 { "move,up", "move", "up", _key_action_move},
1120 { "move,down", "move", "down", _key_action_move},
1121 { "move,left", "move", "left", _key_action_move},
1122 { "move,right", "move", "right", _key_action_move},
1123 { "escape", "escape", NULL, _key_action_escape},
1124 { NULL, NULL, NULL, NULL}
1126 return &atspi_actions[0];
1129 //TIZEN_ONLY(20230119) : fix accessible_at_point getter
1131 _elm_hoversel_efl_access_component_accessible_at_point_get(const Eo *obj, Elm_Hoversel_Data *sd, Eina_Bool screen_coords, int x, int y)
1133 Evas_Coord wx, wy, ww, wh;
1138 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
1139 if (!ee) return NULL;
1140 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
1145 Elm_Object_Item *eo_item;
1147 EINA_LIST_FOREACH(sd->items, l, eo_item)
1149 ELM_HOVERSEL_ITEM_DATA_GET(eo_item, it);
1150 evas_object_geometry_get(VIEW(it), &wx, &wy, &ww, &wh);
1151 Efl_Access_State_Set ss = efl_access_object_state_set_get(VIEW(it));
1152 Eina_Bool is_item_showing = !!STATE_TYPE_GET(ss, EFL_ACCESS_STATE_TYPE_SHOWING);
1153 if (is_item_showing && IS_INSIDE(x, y, wx, wy, ww, wh))
1162 _elm_hoversel_auto_update_set(Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd, Eina_Bool auto_update)
1164 sd->auto_update = !!auto_update;
1168 _elm_hoversel_auto_update_get(const Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd)
1170 return sd->auto_update;
1173 /* Internal EO APIs and hidden overrides */
1175 #define ELM_HOVERSEL_EXTRA_OPS \
1176 EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_hoversel)
1178 #include "elm_hoversel_item_eo.c"
1179 #include "elm_hoversel_eo.c"