Merge pull request #17730 from RandomShaper/radio-buttons-in-menus
Radio buttons in menus
This commit is contained in:
commit
187b14ae24
|
@ -24,6 +24,19 @@
|
|||
Add a new checkable item with text "label". An id can optionally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_radio_check_item">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="label" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="id" type="int" default="-1">
|
||||
</argument>
|
||||
<argument index="2" name="accel" type="int" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
The same as [method add_check_item] but the inserted item will look as a radio button. Remember this is just cosmetic and you have to add the logic for checking/unchecking items in radio groups.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_check_shortcut">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -36,6 +49,18 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_radio_check_shortcut">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="shortcut" type="ShortCut">
|
||||
</argument>
|
||||
<argument index="1" name="id" type="int" default="-1">
|
||||
</argument>
|
||||
<argument index="2" name="global" type="bool" default="false">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_icon_check_item">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
@ -239,7 +264,16 @@
|
|||
<argument index="0" name="idx" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Return whether the item at index "idx" has a checkbox. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
|
||||
Return whether the item at index "idx" is checkable in some way, i.e., whether has a checkbox or radio button. Note that checkable items just display a checkmark or radio button, but don't have any built-in checking behavior and must be checked/unchecked manually.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_item_radio_checkable" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="idx" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Return whether the item at index "idx" has radio-button-style checkability. Remember this is just cosmetic and you have to add the logic for checking/unchecking items in radio groups.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_item_checked" qualifiers="const">
|
||||
|
@ -248,7 +282,7 @@
|
|||
<argument index="0" name="idx" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Return the checkstate status of the item at index "idx".
|
||||
Return whether the item at index "idx" is checked.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_item_disabled" qualifiers="const">
|
||||
|
@ -300,6 +334,18 @@
|
|||
Set whether the item at index "idx" has a checkbox. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_item_as_radio_checkable">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="idx" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="enable" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
The same as [method set_item_as_checkable] but placing a radio button in case of enabling. If used for disabling, it's the same.
|
||||
Remember this is just cosmetic and you have to add the logic for checking/unchecking items in radio groups.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_item_as_separator">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
|
|
@ -626,8 +626,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
|
|||
theme->set_color("font_color_disabled", "PopupMenu", font_color_disabled);
|
||||
theme->set_icon("checked", "PopupMenu", theme->get_icon("GuiChecked", "EditorIcons"));
|
||||
theme->set_icon("unchecked", "PopupMenu", theme->get_icon("GuiUnchecked", "EditorIcons"));
|
||||
theme->set_icon("radio_checked", "PopupMenu", theme->get_icon("GuiChecked", "EditorIcons"));
|
||||
theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon("GuiUnchecked", "EditorIcons"));
|
||||
theme->set_icon("radio_checked", "PopupMenu", theme->get_icon("GuiRadioChecked", "EditorIcons"));
|
||||
theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon("GuiRadioUnchecked", "EditorIcons"));
|
||||
theme->set_icon("submenu", "PopupMenu", theme->get_icon("ArrowRight", "EditorIcons"));
|
||||
theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon("GuiVisibilityHidden", "EditorIcons"));
|
||||
theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon("GuiVisibilityVisible", "EditorIcons"));
|
||||
|
|
|
@ -1679,10 +1679,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
|
|||
onion_skinning->get_popup()->add_separator();
|
||||
onion_skinning->get_popup()->add_item(TTR("Depth"), -1);
|
||||
onion_skinning->get_popup()->set_item_disabled(onion_skinning->get_popup()->get_item_count() - 1, true);
|
||||
onion_skinning->get_popup()->add_check_item(TTR("1 step"), ONION_SKINNING_1_STEP);
|
||||
onion_skinning->get_popup()->add_radio_check_item(TTR("1 step"), ONION_SKINNING_1_STEP);
|
||||
onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true);
|
||||
onion_skinning->get_popup()->add_check_item(TTR("2 steps"), ONION_SKINNING_2_STEPS);
|
||||
onion_skinning->get_popup()->add_check_item(TTR("3 steps"), ONION_SKINNING_3_STEPS);
|
||||
onion_skinning->get_popup()->add_radio_check_item(TTR("2 steps"), ONION_SKINNING_2_STEPS);
|
||||
onion_skinning->get_popup()->add_radio_check_item(TTR("3 steps"), ONION_SKINNING_3_STEPS);
|
||||
onion_skinning->get_popup()->add_separator();
|
||||
onion_skinning->get_popup()->add_check_item(TTR("Differences Only"), ONION_SKINNING_DIFFERENCES_ONLY);
|
||||
onion_skinning->get_popup()->add_check_item(TTR("Force White Modulate"), ONION_SKINNING_FORCE_WHITE_MODULATE);
|
||||
|
|
|
@ -42,9 +42,18 @@ bool ItemListPlugin::_set(const StringName &p_name, const Variant &p_value) {
|
|||
set_item_text(idx, p_value);
|
||||
else if (what == "icon")
|
||||
set_item_icon(idx, p_value);
|
||||
else if (what == "checkable")
|
||||
else if (what == "checkable") {
|
||||
// This keeps compatibility to/from versions where this property was a boolean, before radio buttons
|
||||
switch ((int)p_value) {
|
||||
case 0:
|
||||
case 1:
|
||||
set_item_checkable(idx, p_value);
|
||||
else if (what == "checked")
|
||||
break;
|
||||
case 2:
|
||||
set_item_radio_checkable(idx, true);
|
||||
break;
|
||||
}
|
||||
} else if (what == "checked")
|
||||
set_item_checked(idx, p_value);
|
||||
else if (what == "id")
|
||||
set_item_id(idx, p_value);
|
||||
|
@ -68,9 +77,14 @@ bool ItemListPlugin::_get(const StringName &p_name, Variant &r_ret) const {
|
|||
r_ret = get_item_text(idx);
|
||||
else if (what == "icon")
|
||||
r_ret = get_item_icon(idx);
|
||||
else if (what == "checkable")
|
||||
r_ret = is_item_checkable(idx);
|
||||
else if (what == "checked")
|
||||
else if (what == "checkable") {
|
||||
// This keeps compatibility to/from versions where this property was a boolean, before radio buttons
|
||||
if (!is_item_checkable(idx)) {
|
||||
r_ret = 0;
|
||||
} else {
|
||||
r_ret = is_item_radio_checkable(idx) ? 2 : 1;
|
||||
}
|
||||
} else if (what == "checked")
|
||||
r_ret = is_item_checked(idx);
|
||||
else if (what == "id")
|
||||
r_ret = get_item_id(idx);
|
||||
|
@ -95,7 +109,7 @@ void ItemListPlugin::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
int flags = get_flags();
|
||||
|
||||
if (flags & FLAG_CHECKABLE) {
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base + "checkable"));
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base + "checkable", PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"));
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base + "checked"));
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,9 @@ public:
|
|||
virtual Ref<Texture> get_item_icon(int p_idx) const { return Ref<Texture>(); };
|
||||
|
||||
virtual void set_item_checkable(int p_idx, bool p_check) {}
|
||||
virtual void set_item_radio_checkable(int p_idx, bool p_check) {}
|
||||
virtual bool is_item_checkable(int p_idx) const { return false; };
|
||||
virtual bool is_item_radio_checkable(int p_idx) const { return false; };
|
||||
|
||||
virtual void set_item_checked(int p_idx, bool p_checked) {}
|
||||
virtual bool is_item_checked(int p_idx) const { return false; };
|
||||
|
@ -145,7 +147,9 @@ public:
|
|||
virtual Ref<Texture> get_item_icon(int p_idx) const { return pp->get_item_icon(p_idx); }
|
||||
|
||||
virtual void set_item_checkable(int p_idx, bool p_check) { pp->set_item_as_checkable(p_idx, p_check); }
|
||||
virtual void set_item_radio_checkable(int p_idx, bool p_check) { pp->set_item_as_radio_checkable(p_idx, p_check); }
|
||||
virtual bool is_item_checkable(int p_idx) const { return pp->is_item_checkable(p_idx); }
|
||||
virtual bool is_item_radio_checkable(int p_idx) const { return pp->is_item_radio_checkable(p_idx); }
|
||||
|
||||
virtual void set_item_checked(int p_idx, bool p_checked) { pp->set_item_checked(p_idx, p_checked); }
|
||||
virtual bool is_item_checked(int p_idx) const { return pp->is_item_checked(p_idx); }
|
||||
|
|
|
@ -3351,14 +3351,14 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
|
|||
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/front_view"), VIEW_FRONT);
|
||||
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/rear_view"), VIEW_REAR);
|
||||
view_menu->get_popup()->add_separator();
|
||||
view_menu->get_popup()->add_check_item(TTR("Perspective") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_PERSPECTIVE);
|
||||
view_menu->get_popup()->add_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL);
|
||||
view_menu->get_popup()->add_radio_check_item(TTR("Perspective") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_PERSPECTIVE);
|
||||
view_menu->get_popup()->add_radio_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL);
|
||||
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true);
|
||||
view_menu->get_popup()->add_separator();
|
||||
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_normal", TTR("Display Normal")), VIEW_DISPLAY_NORMAL);
|
||||
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_wireframe", TTR("Display Wireframe")), VIEW_DISPLAY_WIREFRAME);
|
||||
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_overdraw", TTR("Display Overdraw")), VIEW_DISPLAY_OVERDRAW);
|
||||
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_unshaded", TTR("Display Unshaded")), VIEW_DISPLAY_SHADELESS);
|
||||
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_normal", TTR("Display Normal")), VIEW_DISPLAY_NORMAL);
|
||||
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_wireframe", TTR("Display Wireframe")), VIEW_DISPLAY_WIREFRAME);
|
||||
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_overdraw", TTR("Display Overdraw")), VIEW_DISPLAY_OVERDRAW);
|
||||
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_unshaded", TTR("Display Unshaded")), VIEW_DISPLAY_SHADELESS);
|
||||
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), true);
|
||||
view_menu->get_popup()->add_separator();
|
||||
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("View Environment")), VIEW_ENVIRONMENT);
|
||||
|
@ -5109,12 +5109,12 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
|
|||
accept = memnew(AcceptDialog);
|
||||
editor->get_gui_base()->add_child(accept);
|
||||
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD + KEY_1), MENU_VIEW_USE_1_VIEWPORT);
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS);
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT);
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD + KEY_4), MENU_VIEW_USE_4_VIEWPORTS);
|
||||
p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD + KEY_1), MENU_VIEW_USE_1_VIEWPORT);
|
||||
p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
|
||||
p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
|
||||
p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS);
|
||||
p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT);
|
||||
p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD + KEY_4), MENU_VIEW_USE_4_VIEWPORTS);
|
||||
p->add_separator();
|
||||
|
||||
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
|
||||
|
|
|
@ -805,12 +805,10 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
|
|||
snap_mode_button->set_text(TTR("<None>"));
|
||||
PopupMenu *p = snap_mode_button->get_popup();
|
||||
p->set_hide_on_checkable_item_selection(false);
|
||||
p->add_item(TTR("<None>"), 0);
|
||||
p->add_item(TTR("Pixel Snap"), 1);
|
||||
p->add_item(TTR("Grid Snap"), 2);
|
||||
p->add_item(TTR("Auto Slice"), 3);
|
||||
for (int i = 0; i < 4; i++)
|
||||
p->set_item_as_checkable(i, true);
|
||||
p->add_radio_check_item(TTR("<None>"), 0);
|
||||
p->add_radio_check_item(TTR("Pixel Snap"), 1);
|
||||
p->add_radio_check_item(TTR("Grid Snap"), 2);
|
||||
p->add_radio_check_item(TTR("Auto Slice"), 3);
|
||||
p->set_item_checked(0, true);
|
||||
p->connect("id_pressed", this, "_set_snap_mode");
|
||||
hb_grid = memnew(HBoxContainer);
|
||||
|
|
|
@ -692,6 +692,10 @@ ThemeEditor::ThemeEditor() {
|
|||
test_menu_button->get_popup()->add_check_item(TTR("Check Item"));
|
||||
test_menu_button->get_popup()->add_check_item(TTR("Checked Item"));
|
||||
test_menu_button->get_popup()->set_item_checked(2, true);
|
||||
test_menu_button->get_popup()->add_separator();
|
||||
test_menu_button->get_popup()->add_check_item(TTR("Radio Item"));
|
||||
test_menu_button->get_popup()->add_radio_check_item(TTR("Checked Radio Item"));
|
||||
test_menu_button->get_popup()->set_item_checked(5, true);
|
||||
first_vb->add_child(test_menu_button);
|
||||
|
||||
OptionButton *test_option_button = memnew(OptionButton);
|
||||
|
|
|
@ -185,6 +185,10 @@ public:
|
|||
popup->add_item("Popup");
|
||||
popup->add_check_item("Check Popup");
|
||||
popup->set_item_checked(4, true);
|
||||
popup->add_separator();
|
||||
popup->add_radio_check_item("Option A");
|
||||
popup->set_item_checked(6, true);
|
||||
popup->add_radio_check_item("Option B");
|
||||
|
||||
OptionButton *options = memnew(OptionButton);
|
||||
|
||||
|
|
|
@ -1046,14 +1046,14 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
|
|||
options->get_popup()->add_item(TTR("Previous Floor"), MENU_OPTION_PREV_LEVEL, KEY_Q);
|
||||
options->get_popup()->add_item(TTR("Next Floor"), MENU_OPTION_NEXT_LEVEL, KEY_E);
|
||||
options->get_popup()->add_separator();
|
||||
options->get_popup()->add_check_item(TTR("Clip Disabled"), MENU_OPTION_CLIP_DISABLED);
|
||||
options->get_popup()->add_radio_check_item(TTR("Clip Disabled"), MENU_OPTION_CLIP_DISABLED);
|
||||
options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED), true);
|
||||
options->get_popup()->add_check_item(TTR("Clip Above"), MENU_OPTION_CLIP_ABOVE);
|
||||
options->get_popup()->add_check_item(TTR("Clip Below"), MENU_OPTION_CLIP_BELOW);
|
||||
options->get_popup()->add_radio_check_item(TTR("Clip Above"), MENU_OPTION_CLIP_ABOVE);
|
||||
options->get_popup()->add_radio_check_item(TTR("Clip Below"), MENU_OPTION_CLIP_BELOW);
|
||||
options->get_popup()->add_separator();
|
||||
options->get_popup()->add_check_item(TTR("Edit X Axis"), MENU_OPTION_X_AXIS, KEY_Z);
|
||||
options->get_popup()->add_check_item(TTR("Edit Y Axis"), MENU_OPTION_Y_AXIS, KEY_X);
|
||||
options->get_popup()->add_check_item(TTR("Edit Z Axis"), MENU_OPTION_Z_AXIS, KEY_C);
|
||||
options->get_popup()->add_radio_check_item(TTR("Edit X Axis"), MENU_OPTION_X_AXIS, KEY_Z);
|
||||
options->get_popup()->add_radio_check_item(TTR("Edit Y Axis"), MENU_OPTION_Y_AXIS, KEY_X);
|
||||
options->get_popup()->add_radio_check_item(TTR("Edit Z Axis"), MENU_OPTION_Z_AXIS, KEY_C);
|
||||
options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_Y_AXIS), true);
|
||||
options->get_popup()->add_separator();
|
||||
options->get_popup()->add_item(TTR("Cursor Rotate X"), MENU_OPTION_CURSOR_ROTATE_X, KEY_A);
|
||||
|
|
|
@ -118,7 +118,7 @@ void OptionButton::add_icon_item(const Ref<Texture> &p_icon, const String &p_lab
|
|||
}
|
||||
void OptionButton::add_item(const String &p_label, int p_ID) {
|
||||
|
||||
popup->add_check_item(p_label, p_ID);
|
||||
popup->add_radio_check_item(p_label, p_ID);
|
||||
if (popup->get_item_count() == 1)
|
||||
select(0);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ Size2 PopupMenu::get_minimum_size() const {
|
|||
|
||||
float max_w = 0;
|
||||
int font_h = font->get_height();
|
||||
int check_w = get_icon("checked")->get_width();
|
||||
int check_w = MAX(get_icon("checked")->get_width(), get_icon("radio_checked")->get_width());
|
||||
int accel_max_w = 0;
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
|
@ -74,7 +74,7 @@ Size2 PopupMenu::get_minimum_size() const {
|
|||
|
||||
size.width += items[i].h_ofs;
|
||||
|
||||
if (items[i].checkable) {
|
||||
if (items[i].checkable_type) {
|
||||
|
||||
size.width += check_w + hseparation;
|
||||
}
|
||||
|
@ -416,8 +416,9 @@ void PopupMenu::_notification(int p_what) {
|
|||
Ref<StyleBox> style = get_stylebox("panel");
|
||||
Ref<StyleBox> hover = get_stylebox("hover");
|
||||
Ref<Font> font = get_font("font");
|
||||
Ref<Texture> check = get_icon("checked");
|
||||
Ref<Texture> uncheck = get_icon("unchecked");
|
||||
// In Item::checkable_type enum order (less the non-checkable member)
|
||||
Ref<Texture> check[] = { get_icon("checked"), get_icon("radio_checked") };
|
||||
Ref<Texture> uncheck[] = { get_icon("unchecked"), get_icon("radio_unchecked") };
|
||||
Ref<Texture> submenu = get_icon("submenu");
|
||||
Ref<StyleBox> separator = get_stylebox("separator");
|
||||
|
||||
|
@ -460,14 +461,10 @@ void PopupMenu::_notification(int p_what) {
|
|||
separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(get_size().width - style->get_minimum_size().width, sep_h)));
|
||||
}
|
||||
|
||||
if (items[i].checkable) {
|
||||
|
||||
if (items[i].checked)
|
||||
check->draw(ci, item_ofs + Point2(0, Math::floor((h - check->get_height()) / 2.0)));
|
||||
else
|
||||
uncheck->draw(ci, item_ofs + Point2(0, Math::floor((h - check->get_height()) / 2.0)));
|
||||
|
||||
item_ofs.x += check->get_width() + hseparation;
|
||||
if (items[i].checkable_type) {
|
||||
Texture *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr();
|
||||
icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)));
|
||||
item_ofs.x += icon->get_width() + hseparation;
|
||||
}
|
||||
|
||||
if (!items[i].icon.is_null()) {
|
||||
|
@ -567,10 +564,11 @@ void PopupMenu::add_icon_check_item(const Ref<Texture> &p_icon, const String &p_
|
|||
item.xl_text = tr(p_label);
|
||||
item.accel = p_accel;
|
||||
item.ID = p_ID;
|
||||
item.checkable = true;
|
||||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::add_check_item(const String &p_label, int p_ID, uint32_t p_accel) {
|
||||
|
||||
Item item;
|
||||
|
@ -578,11 +576,18 @@ void PopupMenu::add_check_item(const String &p_label, int p_ID, uint32_t p_accel
|
|||
item.xl_text = tr(p_label);
|
||||
item.accel = p_accel;
|
||||
item.ID = p_ID;
|
||||
item.checkable = true;
|
||||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::add_radio_check_item(const String &p_label, int p_ID, uint32_t p_accel) {
|
||||
|
||||
add_check_item(p_label, p_ID, p_accel);
|
||||
items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) {
|
||||
|
||||
ERR_FAIL_COND(p_shortcut.is_null());
|
||||
|
@ -611,6 +616,7 @@ void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bool p_g
|
|||
items.push_back(item);
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) {
|
||||
|
||||
ERR_FAIL_COND(p_shortcut.is_null());
|
||||
|
@ -620,7 +626,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<Sh
|
|||
Item item;
|
||||
item.ID = p_ID;
|
||||
item.shortcut = p_shortcut;
|
||||
item.checkable = true;
|
||||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
item.icon = p_icon;
|
||||
item.shortcut_is_global = p_global;
|
||||
items.push_back(item);
|
||||
|
@ -637,11 +643,18 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bo
|
|||
item.ID = p_ID;
|
||||
item.shortcut = p_shortcut;
|
||||
item.shortcut_is_global = p_global;
|
||||
item.checkable = true;
|
||||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) {
|
||||
|
||||
add_check_shortcut(p_shortcut, p_ID, p_global);
|
||||
items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_ID, uint32_t p_accel) {
|
||||
|
||||
Item item;
|
||||
|
@ -649,7 +662,6 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
|
|||
item.xl_text = tr(p_label);
|
||||
item.accel = p_accel;
|
||||
item.ID = p_ID;
|
||||
item.checkable = false;
|
||||
item.max_states = p_max_states;
|
||||
item.state = p_default_state;
|
||||
items.push_back(item);
|
||||
|
@ -824,7 +836,14 @@ bool PopupMenu::is_item_separator(int p_idx) const {
|
|||
void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
|
||||
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
items[p_idx].checkable = p_checkable;
|
||||
items[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
|
||||
update();
|
||||
}
|
||||
|
||||
void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
|
||||
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
items[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -880,7 +899,12 @@ void PopupMenu::toggle_item_multistate(int p_idx) {
|
|||
|
||||
bool PopupMenu::is_item_checkable(int p_idx) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, items.size(), false);
|
||||
return items[p_idx].checkable;
|
||||
return items[p_idx].checkable_type;
|
||||
}
|
||||
|
||||
bool PopupMenu::is_item_radio_checkable(int p_idx) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, items.size(), false);
|
||||
return items[p_idx].checkable_type == Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
}
|
||||
|
||||
int PopupMenu::get_item_count() const {
|
||||
|
@ -954,7 +978,7 @@ void PopupMenu::activate_item(int p_item) {
|
|||
// We close all parents that are chained together,
|
||||
// with hide_on_item_selection enabled
|
||||
|
||||
if (items[p_item].checkable) {
|
||||
if (items[p_item].checkable_type) {
|
||||
if (!hide_on_checkable_item_selection || !pop->is_hide_on_checkable_item_selection())
|
||||
break;
|
||||
} else if (0 < items[p_item].max_states) {
|
||||
|
@ -971,7 +995,7 @@ void PopupMenu::activate_item(int p_item) {
|
|||
// Hides popup by default; unless otherwise specified
|
||||
// by using set_hide_on_item_selection and set_hide_on_checkable_item_selection
|
||||
|
||||
if (items[p_item].checkable) {
|
||||
if (items[p_item].checkable_type) {
|
||||
if (!hide_on_checkable_item_selection)
|
||||
return;
|
||||
} else if (0 < items[p_item].max_states) {
|
||||
|
@ -1023,7 +1047,9 @@ Array PopupMenu::_get_items() const {
|
|||
|
||||
items.push_back(get_item_text(i));
|
||||
items.push_back(get_item_icon(i));
|
||||
items.push_back(is_item_checkable(i));
|
||||
// For compatibility, use false/true for no/checkbox and integers for other values
|
||||
int ct = this->items[i].checkable_type;
|
||||
items.push_back(Variant(ct <= Item::CHECKABLE_TYPE_CHECK_BOX ? is_item_checkable(i) : ct));
|
||||
items.push_back(is_item_checked(i));
|
||||
items.push_back(is_item_disabled(i));
|
||||
|
||||
|
@ -1066,7 +1092,9 @@ void PopupMenu::_set_items(const Array &p_items) {
|
|||
|
||||
String text = p_items[i + 0];
|
||||
Ref<Texture> icon = p_items[i + 1];
|
||||
// For compatibility, use false/true for no/checkbox and integers for other values
|
||||
bool checkable = p_items[i + 2];
|
||||
bool radio_checkable = (int)p_items[i + 2] == Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
bool checked = p_items[i + 3];
|
||||
bool disabled = p_items[i + 4];
|
||||
|
||||
|
@ -1079,7 +1107,13 @@ void PopupMenu::_set_items(const Array &p_items) {
|
|||
int idx = get_item_count();
|
||||
add_item(text, id);
|
||||
set_item_icon(idx, icon);
|
||||
set_item_as_checkable(idx, checkable);
|
||||
if (checkable) {
|
||||
if (radio_checkable) {
|
||||
set_item_as_radio_checkable(idx, true);
|
||||
} else {
|
||||
set_item_as_checkable(idx, true);
|
||||
}
|
||||
}
|
||||
set_item_checked(idx, checked);
|
||||
set_item_disabled(idx, disabled);
|
||||
set_item_id(idx, id);
|
||||
|
@ -1160,12 +1194,14 @@ void PopupMenu::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("add_item", "label", "id", "accel"), &PopupMenu::add_item, DEFVAL(-1), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("add_icon_check_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_check_item, DEFVAL(-1), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("add_check_item", "label", "id", "accel"), &PopupMenu::add_check_item, DEFVAL(-1), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("add_radio_check_item", "label", "id", "accel"), &PopupMenu::add_radio_check_item, DEFVAL(-1), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("add_submenu_item", "label", "submenu", "id"), &PopupMenu::add_submenu_item, DEFVAL(-1));
|
||||
|
||||
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"), &PopupMenu::add_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_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_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));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &PopupMenu::set_item_text);
|
||||
ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &PopupMenu::set_item_icon);
|
||||
|
@ -1177,6 +1213,7 @@ void PopupMenu::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_item_submenu", "idx", "submenu"), &PopupMenu::set_item_submenu);
|
||||
ClassDB::bind_method(D_METHOD("set_item_as_separator", "idx", "enable"), &PopupMenu::set_item_as_separator);
|
||||
ClassDB::bind_method(D_METHOD("set_item_as_checkable", "idx", "enable"), &PopupMenu::set_item_as_checkable);
|
||||
ClassDB::bind_method(D_METHOD("set_item_as_radio_checkable", "idx", "enable"), &PopupMenu::set_item_as_radio_checkable);
|
||||
ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip);
|
||||
ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("set_item_multistate", "idx", "state"), &PopupMenu::set_item_multistate);
|
||||
|
@ -1195,6 +1232,7 @@ void PopupMenu::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_item_submenu", "idx"), &PopupMenu::get_item_submenu);
|
||||
ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &PopupMenu::is_item_separator);
|
||||
ClassDB::bind_method(D_METHOD("is_item_checkable", "idx"), &PopupMenu::is_item_checkable);
|
||||
ClassDB::bind_method(D_METHOD("is_item_radio_checkable", "idx"), &PopupMenu::is_item_radio_checkable);
|
||||
ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &PopupMenu::get_item_tooltip);
|
||||
ClassDB::bind_method(D_METHOD("get_item_shortcut", "idx"), &PopupMenu::get_item_shortcut);
|
||||
|
||||
|
|
|
@ -46,7 +46,11 @@ class PopupMenu : public Popup {
|
|||
String text;
|
||||
String xl_text;
|
||||
bool checked;
|
||||
bool checkable;
|
||||
enum {
|
||||
CHECKABLE_TYPE_NONE,
|
||||
CHECKABLE_TYPE_CHECK_BOX,
|
||||
CHECKABLE_TYPE_RADIO_BUTTON,
|
||||
} checkable_type;
|
||||
int max_states;
|
||||
int state;
|
||||
bool separator;
|
||||
|
@ -63,7 +67,7 @@ class PopupMenu : public Popup {
|
|||
|
||||
Item() {
|
||||
checked = false;
|
||||
checkable = false;
|
||||
checkable_type = CHECKABLE_TYPE_NONE;
|
||||
separator = false;
|
||||
max_states = 0;
|
||||
state = 0;
|
||||
|
@ -117,12 +121,14 @@ public:
|
|||
void add_item(const String &p_label, int p_ID = -1, uint32_t p_accel = 0);
|
||||
void add_icon_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_ID = -1, uint32_t p_accel = 0);
|
||||
void add_check_item(const String &p_label, int p_ID = -1, uint32_t p_accel = 0);
|
||||
void add_radio_check_item(const String &p_label, int p_ID = -1, uint32_t p_accel = 0);
|
||||
void add_submenu_item(const String &p_label, const String &p_submenu, int p_ID = -1);
|
||||
|
||||
void add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
|
||||
void add_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
|
||||
void add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
|
||||
void add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
|
||||
void add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
|
||||
|
||||
void add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_ID = -1, uint32_t p_accel = 0);
|
||||
|
||||
|
@ -136,6 +142,7 @@ public:
|
|||
void set_item_submenu(int p_idx, const String &p_submenu);
|
||||
void set_item_as_separator(int p_idx, bool p_separator);
|
||||
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<ShortCut> &p_shortcut, bool p_global = false);
|
||||
void set_item_h_offset(int p_idx, int p_offset);
|
||||
|
@ -156,6 +163,7 @@ public:
|
|||
String get_item_submenu(int p_idx) const;
|
||||
bool is_item_separator(int p_idx) const;
|
||||
bool is_item_checkable(int p_idx) const;
|
||||
bool is_item_radio_checkable(int p_idx) const;
|
||||
String get_item_tooltip(int p_idx) const;
|
||||
Ref<ShortCut> get_item_shortcut(int p_idx) const;
|
||||
int get_item_state(int p_idx) const;
|
||||
|
|
|
@ -582,6 +582,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
|||
|
||||
theme->set_icon("checked", "PopupMenu", make_icon(checked_png));
|
||||
theme->set_icon("unchecked", "PopupMenu", make_icon(unchecked_png));
|
||||
theme->set_icon("radio_checked", "PopupMenu", make_icon(radio_checked_png));
|
||||
theme->set_icon("radio_unchecked", "PopupMenu", make_icon(radio_unchecked_png));
|
||||
theme->set_icon("submenu", "PopupMenu", make_icon(submenu_png));
|
||||
|
||||
theme->set_font("font", "PopupMenu", default_font);
|
||||
|
|
Loading…
Reference in New Issue