summaryrefslogtreecommitdiffstats
path: root/scene/gui/popup_menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/popup_menu.cpp')
-rw-r--r--scene/gui/popup_menu.cpp96
1 files changed, 88 insertions, 8 deletions
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 1a6adca121..03860c7449 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -47,6 +47,26 @@ String PopupMenu::_get_accel_text(const Item &p_item) const {
return String();
}
+Size2 PopupMenu::_get_item_icon_size(int p_item) const {
+ const PopupMenu::Item &item = items[p_item];
+ Size2 icon_size = item.get_icon_size();
+
+ int max_width = 0;
+ if (theme_cache.icon_max_width > 0) {
+ max_width = theme_cache.icon_max_width;
+ }
+ if (item.icon_max_width > 0 && (max_width == 0 || item.icon_max_width < max_width)) {
+ max_width = item.icon_max_width;
+ }
+
+ if (max_width > 0 && icon_size.width > max_width) {
+ icon_size.height = icon_size.height * max_width / icon_size.width;
+ icon_size.width = max_width;
+ }
+
+ return icon_size;
+}
+
Size2 PopupMenu::_get_contents_minimum_size() const {
Size2 minsize = theme_cache.panel_style->get_minimum_size(); // Accounts for margin in the margin container
minsize.x += scroll_container->get_v_scroll_bar()->get_size().width * 2; // Adds a buffer so that the scrollbar does not render over the top of content
@@ -61,7 +81,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
Size2 item_size;
const_cast<PopupMenu *>(this)->_shape_item(i);
- Size2 icon_size = items[i].get_icon_size();
+ Size2 icon_size = _get_item_icon_size(i);
item_size.height = _get_item_height(i);
icon_w = MAX(icon_size.width, icon_w);
@@ -109,7 +129,8 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
int PopupMenu::_get_item_height(int p_item) const {
ERR_FAIL_INDEX_V(p_item, items.size(), 0);
- int icon_height = items[p_item].get_icon_size().height;
+ Size2 icon_size = _get_item_icon_size(p_item);
+ int icon_height = icon_size.height;
if (items[p_item].checkable_type && !items[p_item].separator) {
icon_height = MAX(icon_height, MAX(theme_cache.checked->get_height(), theme_cache.radio_checked->get_height()));
}
@@ -540,7 +561,8 @@ void PopupMenu::_draw_items() {
continue;
}
- icon_ofs = MAX(items[i].get_icon_size().width, icon_ofs);
+ Size2 icon_size = _get_item_icon_size(i);
+ icon_ofs = MAX(icon_size.width, icon_ofs);
if (items[i].checkable_type) {
has_check = true;
@@ -569,7 +591,7 @@ void PopupMenu::_draw_items() {
_shape_item(i);
Point2 item_ofs = ofs;
- Size2 icon_size = items[i].get_icon_size();
+ Size2 icon_size = _get_item_icon_size(i);
float h = _get_item_height(i);
if (i == mouse_over) {
@@ -631,21 +653,26 @@ void PopupMenu::_draw_items() {
// Icon
if (!items[i].icon.is_null()) {
+ const Point2 icon_offset = Point2(0, Math::floor((h - icon_size.height) / 2.0));
+ Point2 icon_pos;
+
if (items[i].separator) {
separator_ofs -= (icon_size.width + theme_cache.h_separation) / 2;
if (rtl) {
- items[i].icon->draw(ci, Size2(control->get_size().width - item_ofs.x - separator_ofs - icon_size.width, item_ofs.y) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
+ icon_pos = Size2(control->get_size().width - item_ofs.x - separator_ofs - icon_size.width, item_ofs.y);
} else {
- items[i].icon->draw(ci, item_ofs + Size2(separator_ofs, 0) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
+ icon_pos = item_ofs + Size2(separator_ofs, 0);
}
} else {
if (rtl) {
- items[i].icon->draw(ci, Size2(control->get_size().width - item_ofs.x - check_ofs - icon_size.width, item_ofs.y) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
+ icon_pos = Size2(control->get_size().width - item_ofs.x - check_ofs - icon_size.width, item_ofs.y);
} else {
- items[i].icon->draw(ci, item_ofs + Size2(check_ofs, 0) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
+ icon_pos = item_ofs + Size2(check_ofs, 0);
}
}
+
+ items[i].icon->draw_rect(ci, Rect2(icon_pos + icon_offset, icon_size), false, icon_color);
}
// Submenu arrow on right hand side.
@@ -802,6 +829,7 @@ void PopupMenu::_update_theme_item_cache() {
theme_cache.indent = get_theme_constant(SNAME("indent"));
theme_cache.item_start_padding = get_theme_constant(SNAME("item_start_padding"));
theme_cache.item_end_padding = get_theme_constant(SNAME("item_end_padding"));
+ theme_cache.icon_max_width = get_theme_constant(SNAME("icon_max_width"));
theme_cache.checked = get_theme_icon(SNAME("checked"));
theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
@@ -946,8 +974,10 @@ void PopupMenu::add_item(const String &p_label, int p_id, Key p_accel) {
Item item;
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
notify_property_list_changed();
_menu_changed();
@@ -958,8 +988,10 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.icon = p_icon;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
notify_property_list_changed();
_menu_changed();
@@ -970,8 +1002,10 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, Key p_accel) {
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -982,8 +1016,10 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
}
@@ -992,8 +1028,10 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_acce
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1004,8 +1042,10 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1016,8 +1056,10 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
item.max_states = p_max_states;
item.state = p_default_state;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1035,8 +1077,10 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1046,8 +1090,10 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.icon = p_icon;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1057,8 +1103,10 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1069,8 +1117,10 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1080,8 +1130,10 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1092,8 +1144,10 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1105,8 +1159,10 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu,
item.id = p_id == -1 ? items.size() : p_id;
item.submenu = p_submenu;
items.push_back(item);
+
_shape_item(items.size() - 1);
control->queue_redraw();
+
child_controls_changed();
_menu_changed();
}
@@ -1176,6 +1232,23 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
_menu_changed();
}
+void PopupMenu::set_item_icon_max_width(int p_idx, int p_width) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
+ ERR_FAIL_INDEX(p_idx, items.size());
+
+ if (items[p_idx].icon_max_width == p_width) {
+ return;
+ }
+
+ items.write[p_idx].icon_max_width = p_width;
+
+ control->queue_redraw();
+ child_controls_changed();
+ _menu_changed();
+}
+
void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
if (p_idx < 0) {
p_idx += get_item_count();
@@ -1314,6 +1387,11 @@ Ref<Texture2D> PopupMenu::get_item_icon(int p_idx) const {
return items[p_idx].icon;
}
+int PopupMenu::get_item_icon_max_width(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), 0);
+ return items[p_idx].icon_max_width;
+}
+
Key PopupMenu::get_item_accelerator(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), Key::NONE);
return items[p_idx].accel;
@@ -2023,6 +2101,7 @@ void PopupMenu::_bind_methods() {
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_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_checked", "index", "checked"), &PopupMenu::set_item_checked);
ClassDB::bind_method(D_METHOD("set_item_id", "index", "id"), &PopupMenu::set_item_id);
ClassDB::bind_method(D_METHOD("set_item_accelerator", "index", "accel"), &PopupMenu::set_item_accelerator);
@@ -2045,6 +2124,7 @@ void PopupMenu::_bind_methods() {
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_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("is_item_checked", "index"), &PopupMenu::is_item_checked);
ClassDB::bind_method(D_METHOD("get_item_id", "index"), &PopupMenu::get_item_id);
ClassDB::bind_method(D_METHOD("get_item_index", "id"), &PopupMenu::get_item_index);