feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -316,32 +316,26 @@ int PopupMenu::_get_items_total_height() const {
|
|||
}
|
||||
|
||||
int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
|
||||
// Make the item area exclude shadows and the vertical margins and scrollbar.
|
||||
Rect2 item_clickable_area = panel->get_global_rect();
|
||||
if (scroll_container->get_v_scroll_bar()->is_visible_in_tree()) {
|
||||
const int scroll_width = scroll_container->get_v_scroll_bar()->get_size().width;
|
||||
if (is_layout_rtl()) {
|
||||
item_clickable_area.position.x += scroll_width;
|
||||
item_clickable_area.size.width -= scroll_width;
|
||||
}
|
||||
item_clickable_area.size.width -= scroll_width;
|
||||
}
|
||||
float win_scale = get_content_scale_factor();
|
||||
item_clickable_area.position.x += theme_cache.panel_style->get_margin(SIDE_LEFT);
|
||||
item_clickable_area.position.y += theme_cache.panel_style->get_margin(SIDE_TOP);
|
||||
item_clickable_area.position *= win_scale;
|
||||
item_clickable_area.size.y -= theme_cache.panel_style->get_margin(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_BOTTOM);
|
||||
item_clickable_area.size *= win_scale;
|
||||
// Transform to scroll_container local coordinates.
|
||||
const Point2 scaled_pos = p_over / get_content_scale_factor();
|
||||
const Point2 over_scroll_container =
|
||||
scroll_container->get_global_transform_with_canvas().xform_inv(scaled_pos);
|
||||
|
||||
if (!item_clickable_area.has_point(p_over)) {
|
||||
// Check if point is inside the item control as clipped by scroll_container.
|
||||
const Rect2 scroll_container_rect = Rect2(Point2(), scroll_container->get_size());
|
||||
const Rect2 bounding_rect = scroll_container_rect.intersection(control->get_rect());
|
||||
if (!bounding_rect.has_point(over_scroll_container)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float ofs = item_clickable_area.position.y + (float)theme_cache.v_separation * win_scale * 0.5;
|
||||
// Perform item hit check in control node local space,
|
||||
// so we don't need to worry about any of the container theming.
|
||||
const float over_control_y = control->get_transform().xform_inv(over_scroll_container).y;
|
||||
float bottom_edge = 0;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ofs += i > 0 ? (float)theme_cache.v_separation * win_scale : (float)theme_cache.v_separation * win_scale * 0.5;
|
||||
ofs += _get_item_height(i) * win_scale;
|
||||
if (p_over.y - control->get_position().y * win_scale < ofs) {
|
||||
bottom_edge += theme_cache.v_separation;
|
||||
bottom_edge += _get_item_height(i);
|
||||
if (bottom_edge > over_control_y) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
@ -499,9 +493,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
|||
bool match_found = false;
|
||||
for (int i = search_from; i < items.size(); i++) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
match_found = true;
|
||||
|
|
@ -513,9 +509,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
|||
// If the last item is not selectable, try re-searching from the start.
|
||||
for (int i = 0; i < search_from; i++) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
break;
|
||||
|
|
@ -537,9 +535,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
|||
bool match_found = false;
|
||||
for (int i = search_from; i >= 0; i--) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
match_found = true;
|
||||
|
|
@ -551,9 +551,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
|||
// If the first item is not selectable, try re-searching from the end.
|
||||
for (int i = items.size() - 1; i >= search_from; i--) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
break;
|
||||
|
|
@ -738,9 +740,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
|||
}
|
||||
|
||||
if (items[i].text.findn(search_string) == 0) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
break;
|
||||
|
|
@ -755,6 +759,7 @@ void PopupMenu::_mouse_over_update(const Point2 &p_over) {
|
|||
|
||||
if (id < 0) {
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
return;
|
||||
}
|
||||
|
|
@ -766,6 +771,7 @@ void PopupMenu::_mouse_over_update(const Point2 &p_over) {
|
|||
|
||||
if (over != mouse_over) {
|
||||
mouse_over = over;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
}
|
||||
|
|
@ -1060,7 +1066,7 @@ Rect2i PopupMenu::_popup_adjust_rect() const {
|
|||
_update_shadow_offsets();
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
current.position -= Vector2(ABS(panel->get_offset(SIDE_RIGHT)), panel->get_offset(SIDE_TOP)) * get_content_scale_factor();
|
||||
current.position -= Vector2(Math::abs(panel->get_offset(SIDE_RIGHT)), panel->get_offset(SIDE_TOP)) * get_content_scale_factor();
|
||||
} else {
|
||||
current.position -= Vector2(panel->get_offset(SIDE_LEFT), panel->get_offset(SIDE_TOP)) * get_content_scale_factor();
|
||||
}
|
||||
|
|
@ -1104,8 +1110,105 @@ void PopupMenu::remove_child_notify(Node *p_child) {
|
|||
_menu_changed();
|
||||
}
|
||||
|
||||
void PopupMenu::_accessibility_action_click(const Variant &p_data, int p_idx) {
|
||||
activate_item(p_idx);
|
||||
}
|
||||
|
||||
RID PopupMenu::get_focused_accessibility_element() const {
|
||||
if (mouse_over == -1) {
|
||||
return get_accessibility_element();
|
||||
} else {
|
||||
const Item &item = items[mouse_over];
|
||||
return item.accessibility_item_element;
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
|
||||
unbind_global_menu();
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
|
||||
case NOTIFICATION_ACCESSIBILITY_INVALIDATE: {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
items.write[i].accessibility_item_element = RID();
|
||||
}
|
||||
accessibility_scroll_element = RID();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
|
||||
RID ae = get_accessibility_element();
|
||||
ERR_FAIL_COND(ae.is_null());
|
||||
|
||||
if (has_meta("_menu_name")) {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_name(ae, get_meta("_menu_name", get_name()));
|
||||
}
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_MENU);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_count(ae, items.size());
|
||||
|
||||
if (accessibility_scroll_element.is_null()) {
|
||||
accessibility_scroll_element = DisplayServer::get_singleton()->accessibility_create_sub_element(ae, DisplayServer::AccessibilityRole::ROLE_CONTAINER);
|
||||
}
|
||||
|
||||
Transform2D scroll_xform;
|
||||
scroll_xform.set_origin(Vector2i(0, -scroll_container->get_v_scroll_bar()->get_value()));
|
||||
DisplayServer::get_singleton()->accessibility_update_set_transform(accessibility_scroll_element, scroll_xform);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_bounds(accessibility_scroll_element, Rect2(0, 0, get_size().x, scroll_container->get_v_scroll_bar()->get_max()));
|
||||
|
||||
float scroll_width = scroll_container->get_v_scroll_bar()->is_visible_in_tree() ? scroll_container->get_v_scroll_bar()->get_size().width : 0;
|
||||
float display_width = control->get_size().width - scroll_width;
|
||||
Point2 ofs;
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
const Item &item = items.write[i];
|
||||
|
||||
ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2;
|
||||
|
||||
Point2 item_ofs = ofs;
|
||||
if (item.accessibility_item_element.is_null()) {
|
||||
item.accessibility_item_element = DisplayServer::get_singleton()->accessibility_create_sub_element(accessibility_scroll_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM);
|
||||
item.accessibility_item_dirty = true;
|
||||
}
|
||||
|
||||
item_ofs.x += item.indent * theme_cache.indent;
|
||||
float h = _get_item_height(i);
|
||||
|
||||
if (item.accessibility_item_dirty || i == prev_mouse_over || i == mouse_over) {
|
||||
switch (item.checkable_type) {
|
||||
case Item::CHECKABLE_TYPE_NONE: {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(item.accessibility_item_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM);
|
||||
} break;
|
||||
case Item::CHECKABLE_TYPE_CHECK_BOX: {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(item.accessibility_item_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM_CHECK_BOX);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_checked(item.accessibility_item_element, item.checked);
|
||||
} break;
|
||||
case Item::CHECKABLE_TYPE_RADIO_BUTTON: {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(item.accessibility_item_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM_RADIO);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_checked(item.accessibility_item_element, item.checked);
|
||||
} break;
|
||||
}
|
||||
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(item.accessibility_item_element, DisplayServer::AccessibilityAction::ACTION_CLICK, callable_mp(this, &PopupMenu::_accessibility_action_click).bind(i));
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_index(item.accessibility_item_element, i);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_level(item.accessibility_item_element, 0);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_selected(item.accessibility_item_element, i == mouse_over);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_name(item.accessibility_item_element, item.xl_text);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_flag(item.accessibility_item_element, DisplayServer::AccessibilityFlags::FLAG_DISABLED, item.disabled);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_tooltip(item.accessibility_item_element, item.tooltip);
|
||||
|
||||
DisplayServer::get_singleton()->accessibility_update_set_bounds(item.accessibility_item_element, Rect2(item_ofs, Size2(display_width, h + theme_cache.v_separation)));
|
||||
|
||||
item.accessibility_item_dirty = false;
|
||||
}
|
||||
ofs.y += h;
|
||||
}
|
||||
prev_mouse_over = -1;
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent());
|
||||
if (pm) {
|
||||
|
|
@ -1118,12 +1221,6 @@ void PopupMenu::_notification(int p_what) {
|
|||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
|
||||
unbind_global_menu();
|
||||
}
|
||||
} break;
|
||||
|
||||
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
panel->add_theme_style_override(SceneStringName(panel), theme_cache.panel_style);
|
||||
|
|
@ -1146,12 +1243,14 @@ void PopupMenu::_notification(int p_what) {
|
|||
}
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Item &item = items.write[i];
|
||||
item.xl_text = atr(item.text);
|
||||
item.xl_text = _atr(i, item.text);
|
||||
item.dirty = true;
|
||||
if (is_global) {
|
||||
nmenu->set_item_text(global_menu, i, item.xl_text);
|
||||
}
|
||||
item.accessibility_item_dirty = true;
|
||||
_shape_item(i);
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1166,6 +1265,7 @@ void PopupMenu::_notification(int p_what) {
|
|||
case NOTIFICATION_WM_MOUSE_EXIT: {
|
||||
if (mouse_over >= 0 && (!items[mouse_over].submenu || submenu_over != -1)) {
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
} break;
|
||||
|
|
@ -1281,7 +1381,9 @@ void PopupMenu::_notification(int p_what) {
|
|||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
if (!is_visible()) {
|
||||
if (mouse_over >= 0) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
|
|
@ -1341,6 +1443,7 @@ void PopupMenu::add_item(const String &p_label, int p_id, Key p_accel) {
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1364,6 +1467,7 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1387,6 +1491,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, Key p_accel) {
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1412,6 +1517,7 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1435,6 +1541,7 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_acce
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1460,6 +1567,7 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1485,6 +1593,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1522,6 +1631,7 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1551,6 +1661,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1580,6 +1691,7 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1611,6 +1723,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1640,6 +1753,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1671,6 +1785,7 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1697,6 +1812,7 @@ void PopupMenu::add_submenu_node_item(const String &p_label, PopupMenu *p_submen
|
|||
item.text = p_label;
|
||||
item.xl_text = atr(p_label);
|
||||
item.id = p_id == -1 ? items.size() : p_id;
|
||||
item.accessibility_item_dirty = true;
|
||||
item.submenu = p_submenu;
|
||||
item.submenu_name = p_submenu->get_name();
|
||||
items.push_back(item);
|
||||
|
|
@ -1710,6 +1826,7 @@ void PopupMenu::add_submenu_node_item(const String &p_label, PopupMenu *p_submen
|
|||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
|
|
@ -1731,15 +1848,18 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
|
|||
return;
|
||||
}
|
||||
items.write[p_idx].text = p_text;
|
||||
items.write[p_idx].xl_text = atr(p_text);
|
||||
items.write[p_idx].xl_text = _atr(p_idx, p_text);
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_text(global_menu, p_idx, items[p_idx].xl_text);
|
||||
}
|
||||
_shape_item(p_idx);
|
||||
|
||||
_shape_item(p_idx);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
|
@ -1750,9 +1870,14 @@ void PopupMenu::set_item_text_direction(int p_idx, Control::TextDirection p_text
|
|||
}
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
|
||||
|
||||
if (items[p_idx].text_direction != p_text_direction) {
|
||||
items.write[p_idx].text_direction = p_text_direction;
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
_shape_item(p_idx);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
}
|
||||
|
|
@ -1765,10 +1890,28 @@ void PopupMenu::set_item_language(int p_idx, const String &p_language) {
|
|||
if (items[p_idx].language != p_language) {
|
||||
items.write[p_idx].language = p_language;
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
_shape_item(p_idx);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::set_item_auto_translate_mode(int p_idx, AutoTranslateMode p_mode) {
|
||||
if (p_idx < 0) {
|
||||
p_idx += get_item_count();
|
||||
}
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
if (items[p_idx].auto_translate_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
items.write[p_idx].auto_translate_mode = p_mode;
|
||||
items.write[p_idx].xl_text = _atr(p_idx, items[p_idx].text);
|
||||
items.write[p_idx].dirty = true;
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
|
||||
if (p_idx < 0) {
|
||||
p_idx += get_item_count();
|
||||
|
|
@ -1832,11 +1975,13 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
|
|||
}
|
||||
|
||||
items.write[p_idx].checked = p_checked;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_checked(global_menu, p_idx, p_checked);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
|
@ -1875,11 +2020,13 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
|
|||
|
||||
items.write[p_idx].accel = p_accel;
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_accelerator(global_menu, p_idx, p_accel);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
|
@ -1911,11 +2058,13 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
|
|||
}
|
||||
|
||||
items.write[p_idx].disabled = p_disabled;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_disabled(global_menu, p_idx, p_disabled);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
|
@ -1979,11 +2128,13 @@ void PopupMenu::set_item_submenu_node(int p_idx, PopupMenu *p_submenu) {
|
|||
void PopupMenu::toggle_item_checked(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
items.write[p_idx].checked = !items[p_idx].checked;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_checked(global_menu, p_idx, items[p_idx].checked);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
|
@ -2009,6 +2160,11 @@ String PopupMenu::get_item_language(int p_idx) const {
|
|||
return items[p_idx].language;
|
||||
}
|
||||
|
||||
Node::AutoTranslateMode PopupMenu::get_item_auto_translate_mode(int p_idx) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, items.size(), AUTO_TRANSLATE_MODE_INHERIT);
|
||||
return items[p_idx].auto_translate_mode;
|
||||
}
|
||||
|
||||
int PopupMenu::get_item_idx_from_text(const String &text) const {
|
||||
for (int idx = 0; idx < items.size(); idx++) {
|
||||
if (items[idx].text == text) {
|
||||
|
|
@ -2115,6 +2271,9 @@ void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
|
|||
}
|
||||
|
||||
items.write[p_idx].separator = p_separator;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
|
|
@ -2135,11 +2294,13 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
|
|||
}
|
||||
|
||||
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_checkable(global_menu, p_idx, p_checkable);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
|
@ -2156,11 +2317,13 @@ void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
|
|||
}
|
||||
|
||||
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_radio_checkable(global_menu, p_idx, p_radio_checkable);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
|
@ -2176,11 +2339,13 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
|
|||
}
|
||||
|
||||
items.write[p_idx].tooltip = p_tooltip;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_tooltip(global_menu, p_idx, p_tooltip);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
|
@ -2280,11 +2445,13 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) {
|
|||
}
|
||||
|
||||
items.write[p_idx].state = p_state;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_state(global_menu, p_idx, p_state);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
|
@ -2329,11 +2496,13 @@ void PopupMenu::toggle_item_multistate(int p_idx) {
|
|||
if (items.write[p_idx].max_states <= items[p_idx].state) {
|
||||
items.write[p_idx].state = 0;
|
||||
}
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_state(global_menu, p_idx, items[p_idx].state);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
|
@ -2367,11 +2536,12 @@ void PopupMenu::set_focused_item(int p_idx) {
|
|||
return;
|
||||
}
|
||||
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = p_idx;
|
||||
if (mouse_over != -1) {
|
||||
scroll_to_item(mouse_over);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
|
|
@ -2393,6 +2563,10 @@ void PopupMenu::set_item_count(int p_count) {
|
|||
if (is_global && prev_size > p_count) {
|
||||
for (int i = prev_size - 1; i >= p_count; i--) {
|
||||
nmenu->remove_item(global_menu, i);
|
||||
if (items[i].accessibility_item_element.is_valid()) {
|
||||
DisplayServer::get_singleton()->accessibility_free_element(items.write[i].accessibility_item_element);
|
||||
items.write[i].accessibility_item_element = RID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2573,6 +2747,10 @@ void PopupMenu::activate_item(int p_idx) {
|
|||
void PopupMenu::remove_item(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
|
||||
if (items[p_idx].accessibility_item_element.is_valid()) {
|
||||
DisplayServer::get_singleton()->accessibility_free_element(items.write[p_idx].accessibility_item_element);
|
||||
items.write[p_idx].accessibility_item_element = RID();
|
||||
}
|
||||
if (items[p_idx].shortcut.is_valid()) {
|
||||
_unref_shortcut(items[p_idx].shortcut);
|
||||
}
|
||||
|
|
@ -2592,6 +2770,7 @@ void PopupMenu::add_separator(const String &p_text, int p_id) {
|
|||
Item sep;
|
||||
sep.separator = true;
|
||||
sep.id = p_id;
|
||||
sep.accessibility_item_dirty = true;
|
||||
if (!p_text.is_empty()) {
|
||||
sep.text = p_text;
|
||||
sep.xl_text = atr(p_text);
|
||||
|
|
@ -2607,7 +2786,11 @@ void PopupMenu::add_separator(const String &p_text, int p_id) {
|
|||
}
|
||||
|
||||
void PopupMenu::clear(bool p_free_submenus) {
|
||||
for (const Item &I : items) {
|
||||
for (Item &I : items) {
|
||||
if (I.accessibility_item_element.is_valid()) {
|
||||
DisplayServer::get_singleton()->accessibility_free_element(I.accessibility_item_element);
|
||||
I.accessibility_item_element = RID();
|
||||
}
|
||||
if (I.shortcut.is_valid()) {
|
||||
_unref_shortcut(I.shortcut);
|
||||
}
|
||||
|
|
@ -2631,7 +2814,9 @@ void PopupMenu::clear(bool p_free_submenus) {
|
|||
}
|
||||
items.clear();
|
||||
|
||||
prev_mouse_over = -1;
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
|
|
@ -2818,6 +3003,7 @@ void PopupMenu::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_item_text", "index", "text"), &PopupMenu::set_item_text);
|
||||
ClassDB::bind_method(D_METHOD("set_item_text_direction", "index", "direction"), &PopupMenu::set_item_text_direction);
|
||||
ClassDB::bind_method(D_METHOD("set_item_language", "index", "language"), &PopupMenu::set_item_language);
|
||||
ClassDB::bind_method(D_METHOD("set_item_auto_translate_mode", "index", "mode"), &PopupMenu::set_item_auto_translate_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_item_icon", "index", "icon"), &PopupMenu::set_item_icon);
|
||||
ClassDB::bind_method(D_METHOD("set_item_icon_max_width", "index", "width"), &PopupMenu::set_item_icon_max_width);
|
||||
ClassDB::bind_method(D_METHOD("set_item_icon_modulate", "index", "modulate"), &PopupMenu::set_item_icon_modulate);
|
||||
|
|
@ -2844,6 +3030,7 @@ void PopupMenu::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_item_text", "index"), &PopupMenu::get_item_text);
|
||||
ClassDB::bind_method(D_METHOD("get_item_text_direction", "index"), &PopupMenu::get_item_text_direction);
|
||||
ClassDB::bind_method(D_METHOD("get_item_language", "index"), &PopupMenu::get_item_language);
|
||||
ClassDB::bind_method(D_METHOD("get_item_auto_translate_mode", "index"), &PopupMenu::get_item_auto_translate_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_item_icon", "index"), &PopupMenu::get_item_icon);
|
||||
ClassDB::bind_method(D_METHOD("get_item_icon_max_width", "index"), &PopupMenu::get_item_icon_max_width);
|
||||
ClassDB::bind_method(D_METHOD("get_item_icon_modulate", "index"), &PopupMenu::get_item_icon_modulate);
|
||||
|
|
@ -2983,6 +3170,23 @@ void PopupMenu::_native_popup(const Rect2i &p_rect) {
|
|||
NativeMenu::get_singleton()->popup(global_menu, popup_pos);
|
||||
}
|
||||
|
||||
String PopupMenu::_atr(int p_idx, const String &p_text) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, items.size(), atr(p_text));
|
||||
switch (items[p_idx].auto_translate_mode) {
|
||||
case AUTO_TRANSLATE_MODE_INHERIT: {
|
||||
return atr(p_text);
|
||||
} break;
|
||||
case AUTO_TRANSLATE_MODE_ALWAYS: {
|
||||
return tr(p_text);
|
||||
} break;
|
||||
case AUTO_TRANSLATE_MODE_DISABLED: {
|
||||
return p_text;
|
||||
} break;
|
||||
}
|
||||
|
||||
ERR_FAIL_V_MSG(atr(p_text), "Unexpected auto translate mode: " + itos(items[p_idx].auto_translate_mode));
|
||||
}
|
||||
|
||||
void PopupMenu::popup(const Rect2i &p_bounds) {
|
||||
bool native = global_menu.is_valid();
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
|
@ -2994,18 +3198,30 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
|
|||
if (native) {
|
||||
_native_popup(p_bounds != Rect2i() ? p_bounds : Rect2i(get_position(), Size2i()));
|
||||
} else {
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded());
|
||||
if (is_inside_tree()) {
|
||||
bool ac = get_tree()->is_accessibility_enabled();
|
||||
// Note: Native popup menus need keyboard focus to work with screen reader.
|
||||
set_flag(FLAG_POPUP, !ac);
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded() && !ac);
|
||||
if (ac) {
|
||||
set_ac_popup();
|
||||
}
|
||||
}
|
||||
|
||||
moved = Vector2();
|
||||
popup_time_msec = OS::get_singleton()->get_ticks_msec();
|
||||
if (!is_embedded()) {
|
||||
float win_scale = get_parent_visible_window()->get_content_scale_factor();
|
||||
set_content_scale_factor(win_scale);
|
||||
Size2 minsize = get_contents_minimum_size() * win_scale;
|
||||
minsize.height = Math::ceil(minsize.height); // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing.
|
||||
set_min_size(minsize); // `height` is truncated here by the cast to Size2i for Window.min_size.
|
||||
set_size(Vector2(0, 0)); // Shrinkwraps to min size.
|
||||
|
||||
Size2 scale = get_parent_viewport()->get_popup_base_transform().get_scale();
|
||||
CanvasItem *c = Object::cast_to<CanvasItem>(get_parent());
|
||||
if (c) {
|
||||
scale *= c->get_global_transform_with_canvas().get_scale();
|
||||
}
|
||||
real_t popup_scale = MIN(scale.x, scale.y);
|
||||
set_content_scale_factor(popup_scale);
|
||||
Size2 minsize = get_contents_minimum_size() * popup_scale;
|
||||
minsize.height = Math::ceil(minsize.height); // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing.
|
||||
set_min_size(minsize); // `height` is truncated here by the cast to Size2i for Window.min_size.
|
||||
set_size(Vector2(0, 0)); // Shrinkwraps to min size.
|
||||
Popup::popup(p_bounds);
|
||||
}
|
||||
}
|
||||
|
|
@ -3023,7 +3239,15 @@ void PopupMenu::set_visible(bool p_visible) {
|
|||
_native_popup(Rect2i(get_position(), get_size()));
|
||||
}
|
||||
} else {
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded());
|
||||
if (is_inside_tree()) {
|
||||
bool ac = get_tree()->is_accessibility_enabled();
|
||||
// Note: Native popup menus need keyboard focus to work with screen reader.
|
||||
set_flag(FLAG_POPUP, !ac);
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded() && !ac);
|
||||
if (ac) {
|
||||
set_ac_popup();
|
||||
}
|
||||
}
|
||||
|
||||
Popup::set_visible(p_visible);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue