From dd7c42167a041b3ae73262e7fd8716d35803ed77 Mon Sep 17 00:00:00 2001
From: Vincent D <40196601+deakcor@users.noreply.github.com>
Date: Fri, 12 Aug 2022 00:39:05 +0200
Subject: [PATCH] add allow_echo parameter for popup menu item shortcut
---
doc/classes/PopupMenu.xml | 3 +++
scene/gui/menu_button.cpp | 4 ++--
scene/gui/popup_menu.cpp | 46 ++++++++++++++++++++++-----------------
scene/gui/popup_menu.h | 9 ++++----
4 files changed, 36 insertions(+), 26 deletions(-)
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 284c5a18704a..a2e84758354b 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -96,6 +96,7 @@
+
Adds a new item and assigns the specified [Shortcut] and icon [code]texture[/code] to it. Sets the label of the checkbox to the [Shortcut]'s name.
An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index.
@@ -161,6 +162,7 @@
+
Adds a [Shortcut].
An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index.
@@ -442,6 +444,7 @@
+
Sets a [Shortcut] for the item at the given [code]index[/code].
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 069a31d9d2df..f0cc601dcad8 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -44,12 +44,12 @@ void MenuButton::shortcut_input(const Ref &p_event) {
return;
}
- if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr()) || Object::cast_to(*p_event) || Object::cast_to(*p_event))) {
+ if (p_event->is_pressed() && (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr()) || Object::cast_to(*p_event) || Object::cast_to(*p_event))) {
if (!get_parent() || !is_visible_in_tree() || is_disabled()) {
return;
}
- if (popup->activate_item_by_event(p_event, false)) {
+ if (popup->activate_item_by_event(p_event, false, p_event->is_echo())) {
accept_event();
}
}
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index cd0d4370513c..bc8fa912c0c4 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -955,27 +955,28 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
child_controls_changed();
}
-#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \
+#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo) \
ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid Shortcut."); \
_ref_shortcut(p_shortcut); \
item.text = p_shortcut->get_name(); \
item.xl_text = atr(item.text); \
item.id = p_id == -1 ? items.size() : p_id; \
item.shortcut = p_shortcut; \
- item.shortcut_is_global = p_global;
+ item.shortcut_is_global = p_global; \
+ item.shortcut_allow_echo = p_allow_echo;
-void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_global, bool p_allow_echo) {
Item item;
- ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo);
items.push_back(item);
_shape_item(items.size() - 1);
control->update();
child_controls_changed();
}
-void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) {
+void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global, bool p_allow_echo) {
Item item;
- ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo);
item.icon = p_icon;
items.push_back(item);
_shape_item(items.size() - 1);
@@ -985,7 +986,7 @@ void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) {
Item item;
- ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
_shape_item(items.size() - 1);
@@ -995,7 +996,7 @@ void PopupMenu::add_check_shortcut(const Ref &p_shortcut, int p_id, bo
void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) {
Item item;
- ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false);
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
@@ -1006,7 +1007,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref<
void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_id, bool p_global) {
Item item;
- ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false);
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
_shape_item(items.size() - 1);
@@ -1016,7 +1017,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_
void PopupMenu::add_icon_radio_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) {
Item item;
- ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false);
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
@@ -1298,7 +1299,7 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
control->update();
}
-void PopupMenu::set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global) {
+void PopupMenu::set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global, bool p_allow_echo) {
if (p_idx < 0) {
p_idx += get_item_count();
}
@@ -1308,6 +1309,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref &p_shortcut, bo
}
items.write[p_idx].shortcut = p_shortcut;
items.write[p_idx].shortcut_is_global = p_global;
+ items.write[p_idx].shortcut_allow_echo = p_allow_echo;
items.write[p_idx].dirty = true;
if (items[p_idx].shortcut.is_valid()) {
@@ -1419,7 +1421,7 @@ void PopupMenu::scroll_to_item(int p_item) {
}
}
-bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_for_global_only) {
+bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_for_global_only, bool p_is_echo) {
Key code = Key::NONE;
Ref k = p_event;
@@ -1448,13 +1450,17 @@ bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_fo
}
if (items[i].shortcut.is_valid() && items[i].shortcut->matches_event(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) {
- activate_item(i);
- return true;
+ if (!p_is_echo || items[i].shortcut_allow_echo) {
+ activate_item(i);
+ return true;
+ }
}
if (code != Key::NONE && items[i].accel == code) {
- activate_item(i);
- return true;
+ if (!p_is_echo) {
+ activate_item(i);
+ return true;
+ }
}
if (!items[i].submenu.is_empty()) {
@@ -1468,7 +1474,7 @@ bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_fo
continue;
}
- if (pm->activate_item_by_event(p_event, p_for_global_only)) {
+ if (pm->activate_item_by_event(p_event, p_for_global_only, p_is_echo)) {
return true;
}
}
@@ -1815,8 +1821,8 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_multistate_item", "label", "max_states", "default_state", "id", "accel"), &PopupMenu::add_multistate_item, DEFVAL(0), DEFVAL(-1), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global", "p_allow_echo"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global", "p_allow_echo"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_radio_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_radio_check_shortcut, DEFVAL(-1), DEFVAL(false));
@@ -1838,7 +1844,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_as_checkable", "index", "enable"), &PopupMenu::set_item_as_checkable);
ClassDB::bind_method(D_METHOD("set_item_as_radio_checkable", "index", "enable"), &PopupMenu::set_item_as_radio_checkable);
ClassDB::bind_method(D_METHOD("set_item_tooltip", "index", "tooltip"), &PopupMenu::set_item_tooltip);
- ClassDB::bind_method(D_METHOD("set_item_shortcut", "index", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_item_shortcut", "index", "shortcut", "global", "allow_echo"), &PopupMenu::set_item_shortcut, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_item_horizontal_offset", "index", "offset"), &PopupMenu::set_item_horizontal_offset);
ClassDB::bind_method(D_METHOD("set_item_multistate", "index", "state"), &PopupMenu::set_item_multistate);
ClassDB::bind_method(D_METHOD("set_item_shortcut_disabled", "index", "disabled"), &PopupMenu::set_item_shortcut_disabled);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index e203793c2e17..0bb930fc6724 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -72,6 +72,7 @@ class PopupMenu : public Popup {
Ref shortcut;
bool shortcut_is_global = false;
bool shortcut_is_disabled = false;
+ bool shortcut_allow_echo = false;
// Returns (0,0) if icon is null.
Size2 get_icon_size() const {
@@ -158,8 +159,8 @@ class PopupMenu : public Popup {
void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, Key p_accel = Key::NONE);
- void add_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false);
- void add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false, bool p_allow_echo = false);
+ void add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false, bool p_allow_echo = false);
void add_check_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false);
void add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false);
void add_radio_check_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false);
@@ -182,7 +183,7 @@ class PopupMenu : public Popup {
void set_item_as_checkable(int p_idx, bool p_checkable);
void set_item_as_radio_checkable(int p_idx, bool p_radio_checkable);
void set_item_tooltip(int p_idx, const String &p_tooltip);
- void set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global = false);
+ void set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global = false, bool p_allow_echo = false);
void set_item_horizontal_offset(int p_idx, int p_offset);
void set_item_multistate(int p_idx, int p_state);
void toggle_item_multistate(int p_idx);
@@ -219,7 +220,7 @@ class PopupMenu : public Popup {
void scroll_to_item(int p_item);
- bool activate_item_by_event(const Ref &p_event, bool p_for_global_only = false);
+ bool activate_item_by_event(const Ref &p_event, bool p_for_global_only = false, bool p_is_echo = false);
void activate_item(int p_item);
void remove_item(int p_idx);