|
@@ -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);
|