diff options
Diffstat (limited to 'scene/gui/popup_menu.cpp')
-rw-r--r-- | scene/gui/popup_menu.cpp | 96 |
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); |