Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions doc/classes/SpinBox.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
<member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">
Changes the alignment of the underlying [LineEdit].
</member>
<member name="button_alignment" type="int" setter="set_button_alignment" getter="get_button_alignment" enum="SpinBox.ButtonAlignment" default="0">
Controls which side the up and down buttons appear on. [constant BUTTON_ALIGNMENT_DEFAULT] follows the layout direction (right in LTR, left in RTL). [constant BUTTON_ALIGNMENT_LEFT] and [constant BUTTON_ALIGNMENT_RIGHT] override this regardless of layout direction.
</member>
<member name="custom_arrow_round" type="bool" setter="set_custom_arrow_round" getter="is_custom_arrow_rounding" default="false">
If [code]true[/code], the value will be rounded to a multiple of [member custom_arrow_step] when interacting with the arrow buttons. Otherwise, increments the value by [member custom_arrow_step] and then rounds it according to [member Range.step].
</member>
Expand All @@ -75,6 +78,17 @@
[b]Note:[/b] If set to [code]true[/code], this will interfere with entering mathematical expressions in the [SpinBox]. The [SpinBox] will try to evaluate the expression as you type, which means symbols like a trailing [code]+[/code] are removed immediately by the expression being evaluated.
</member>
</members>
<constants>
<constant name="BUTTON_ALIGNMENT_DEFAULT" value="0" enum="ButtonAlignment">
The up and down buttons follow the layout direction: on the right in left-to-right layouts, on the left in right-to-left layouts.
</constant>
<constant name="BUTTON_ALIGNMENT_LEFT" value="1" enum="ButtonAlignment">
The up and down buttons are always placed on the left, regardless of layout direction.
</constant>
<constant name="BUTTON_ALIGNMENT_RIGHT" value="2" enum="ButtonAlignment">
The up and down buttons are always placed on the right, regardless of layout direction.
</constant>
</constants>
<theme_items>
<theme_item name="down_disabled_icon_modulate" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)">
Down button icon modulation color, when the button is disabled.
Expand Down
2 changes: 2 additions & 0 deletions editor/animation/animation_blend_space_1d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
min_value->set_step(STEP_UNIT);
min_value->get_line_edit()->set_expand_to_text_length_enabled(true);
min_value->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT);
min_value->set_button_alignment(SpinBox::BUTTON_ALIGNMENT_RIGHT);
min_value->set_accessibility_name(TTRC("Min"));

max_value = memnew(SpinBox);
Expand All @@ -1088,6 +1089,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
max_value->set_step(STEP_UNIT);
max_value->get_line_edit()->set_expand_to_text_length_enabled(true);
max_value->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
max_value->set_button_alignment(SpinBox::BUTTON_ALIGNMENT_LEFT);
max_value->set_accessibility_name(TTRC("Max"));

label_value = memnew(LineEdit);
Expand Down
4 changes: 4 additions & 0 deletions editor/animation/animation_blend_space_2d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
max_y_value->set_accessibility_name(TTRC("Max Y"));
max_y_value->get_line_edit()->set_expand_to_text_length_enabled(true);
max_y_value->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
max_y_value->set_button_alignment(SpinBox::BUTTON_ALIGNMENT_LEFT);
left_vbox->add_child(max_y_value);
left_vbox->add_spacer();
label_y = memnew(LineEdit);
Expand All @@ -1351,6 +1352,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
min_y_value->set_accessibility_name(TTRC("Min Y"));
min_y_value->get_line_edit()->set_expand_to_text_length_enabled(true);
min_y_value->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
min_y_value->set_button_alignment(SpinBox::BUTTON_ALIGNMENT_LEFT);
left_vbox->add_child(min_y_value);

max_y_value->set_max(ABS_MAX);
Expand Down Expand Up @@ -1385,6 +1387,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
min_x_value->set_accessibility_name(TTRC("Min X"));
min_x_value->get_line_edit()->set_expand_to_text_length_enabled(true);
min_x_value->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT);
min_x_value->set_button_alignment(SpinBox::BUTTON_ALIGNMENT_RIGHT);
bottom_vbox->add_child(min_x_value);
bottom_vbox->add_spacer();
label_x = memnew(LineEdit);
Expand All @@ -1397,6 +1400,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
max_x_value->set_accessibility_name(TTRC("Max X"));
max_x_value->get_line_edit()->set_expand_to_text_length_enabled(true);
max_x_value->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
max_x_value->set_button_alignment(SpinBox::BUTTON_ALIGNMENT_LEFT);
bottom_vbox->add_child(max_x_value);

max_x_value->set_max(ABS_MAX);
Expand Down
43 changes: 39 additions & 4 deletions scene/gui/spin_box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,23 +401,26 @@ inline void SpinBox::_compute_sizes() {
#endif
int w = min_width_from_icons != 0 ? MAX(buttons_block_icon_enforced_width, buttons_block_wanted_width) : buttons_block_wanted_width;

if (w != sizing_cache.buttons_block_width) {
if (_are_buttons_on_left()) {
line_edit->set_offset(SIDE_LEFT, w);
line_edit->set_offset(SIDE_RIGHT, 0);
} else {
line_edit->set_offset(SIDE_LEFT, 0);
line_edit->set_offset(SIDE_RIGHT, -w);
sizing_cache.buttons_block_width = w;
}
sizing_cache.buttons_block_width = w;

Size2i size = get_size();

sizing_cache.buttons_width = w - theme_cache.field_and_buttons_separation;
sizing_cache.buttons_vertical_separation = CLAMP(theme_cache.buttons_vertical_separation, 0, size.height);
sizing_cache.buttons_left = is_layout_rtl() ? 0 : size.width - sizing_cache.buttons_width;
sizing_cache.buttons_left = _are_buttons_on_left() ? 0 : size.width - sizing_cache.buttons_width;
sizing_cache.button_up_height = (size.height - sizing_cache.buttons_vertical_separation) / 2;
sizing_cache.button_down_height = size.height - sizing_cache.button_up_height - sizing_cache.buttons_vertical_separation;
sizing_cache.second_button_top = size.height - sizing_cache.button_down_height;

sizing_cache.buttons_separator_top = sizing_cache.button_up_height;
sizing_cache.field_and_buttons_separator_left = is_layout_rtl() ? sizing_cache.buttons_width : size.width - sizing_cache.buttons_block_width;
sizing_cache.field_and_buttons_separator_left = _are_buttons_on_left() ? sizing_cache.buttons_width : size.width - sizing_cache.buttons_block_width;
sizing_cache.field_and_buttons_separator_width = theme_cache.field_and_buttons_separation;
}

Expand All @@ -437,6 +440,17 @@ inline int SpinBox::_get_widest_button_icon_width() {
return max;
}

inline bool SpinBox::_are_buttons_on_left() const {
switch (button_alignment) {
case BUTTON_ALIGNMENT_LEFT:
return true;
case BUTTON_ALIGNMENT_RIGHT:
return false;
default:
return is_layout_rtl();
}
}

void SpinBox::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
Expand Down Expand Up @@ -545,6 +559,7 @@ void SpinBox::_notification(int p_what) {
} break;

case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
_compute_sizes();
queue_redraw();
} break;
}
Expand Down Expand Up @@ -639,6 +654,19 @@ bool SpinBox::is_custom_arrow_rounding() const {
return custom_arrow_round;
}

void SpinBox::set_button_alignment(ButtonAlignment p_side) {
if (button_alignment == p_side) {
return;
}
button_alignment = p_side;
_compute_sizes();
queue_redraw();
}

SpinBox::ButtonAlignment SpinBox::get_button_alignment() const {
return button_alignment;
}

void SpinBox::_value_changed(double p_value) {
_update_buttons_state_for_current_value();
}
Expand Down Expand Up @@ -680,6 +708,12 @@ void SpinBox::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_select_all_on_focus"), &SpinBox::is_select_all_on_focus);
ClassDB::bind_method(D_METHOD("apply"), &SpinBox::apply);
ClassDB::bind_method(D_METHOD("get_line_edit"), &SpinBox::get_line_edit);
ClassDB::bind_method(D_METHOD("set_button_alignment", "side"), &SpinBox::set_button_alignment);
ClassDB::bind_method(D_METHOD("get_button_alignment"), &SpinBox::get_button_alignment);

BIND_ENUM_CONSTANT(BUTTON_ALIGNMENT_DEFAULT);
BIND_ENUM_CONSTANT(BUTTON_ALIGNMENT_LEFT);
BIND_ENUM_CONSTANT(BUTTON_ALIGNMENT_RIGHT);

ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
Expand All @@ -689,6 +723,7 @@ void SpinBox::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_arrow_step", PROPERTY_HINT_RANGE, "0,10000,0.0001,or_greater"), "set_custom_arrow_step", "get_custom_arrow_step");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_arrow_round"), "set_custom_arrow_round", "is_custom_arrow_rounding");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_all_on_focus"), "set_select_all_on_focus", "is_select_all_on_focus");
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_alignment", PROPERTY_HINT_ENUM, "Default,Left,Right"), "set_button_alignment", "get_button_alignment");

BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, SpinBox, buttons_vertical_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, SpinBox, field_and_buttons_separation);
Expand Down
16 changes: 16 additions & 0 deletions scene/gui/spin_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ class SpinBoxLineEdit : public LineEdit {
class SpinBox : public Range {
GDCLASS(SpinBox, Range);

public:
enum ButtonAlignment {
BUTTON_ALIGNMENT_DEFAULT,
BUTTON_ALIGNMENT_LEFT,
BUTTON_ALIGNMENT_RIGHT,
};

private:
SpinBoxLineEdit *line_edit = nullptr;
bool update_on_text_changed = false;
bool accepted = true;
Expand Down Expand Up @@ -81,6 +89,8 @@ class SpinBox : public Range {
double custom_arrow_step = 0.0;
bool custom_arrow_round = false;

ButtonAlignment button_alignment = BUTTON_ALIGNMENT_DEFAULT;

void _line_edit_input(const Ref<InputEvent> &p_event);

struct Drag {
Expand All @@ -104,6 +114,7 @@ class SpinBox : public Range {

inline void _compute_sizes();
inline int _get_widest_button_icon_width();
inline bool _are_buttons_on_left() const;

struct ThemeCache {
Ref<Texture2D> up_icon;
Expand Down Expand Up @@ -187,5 +198,10 @@ class SpinBox : public Range {
void set_custom_arrow_round(bool p_round);
bool is_custom_arrow_rounding() const;

void set_button_alignment(ButtonAlignment p_alignment);
ButtonAlignment get_button_alignment() const;

SpinBox();
};

VARIANT_ENUM_CAST(SpinBox::ButtonAlignment);
Loading