Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Added alignment options to icons on buttons. They can now be centered and right-aligned. #57771

Merged
merged 1 commit into from
Feb 7, 2022
Merged
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
3 changes: 3 additions & 0 deletions doc/classes/Button.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
Button's icon, if text is present the icon will be placed before the text.
To edit margin and spacing of the icon, use [code]hseparation[/code] theme property of [Button] and [code]content_margin_*[/code] properties of the used [StyleBox]es.
</member>
<member name="icon_align" type="int" setter="set_icon_align" getter="get_icon_align" enum="Button.TextAlign" default="0">
Specifies if the icon should be aligned to the left, right, or center of a button. Uses the same [enum TextAlign] constants as the text alignment. If centered, text will draw on top of the icon.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
The button's text that will be displayed inside the button's area.
</member>
Expand Down
86 changes: 68 additions & 18 deletions scene/gui/button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,14 @@ Size2 Button::get_minimum_size() const {

if (!_icon.is_null()) {
minsize.height = MAX(minsize.height, _icon->get_height());
minsize.width += _icon->get_width();
if (xl_text != "") {
minsize.width += get_constant("hseparation");

if (icon_align != ALIGN_CENTER) {
minsize.width += _icon->get_width();
if (xl_text != "") {
minsize.width += get_constant("hseparation");
}
} else {
minsize.width = MAX(minsize.width, _icon->get_width());
}
}
}
Expand Down Expand Up @@ -175,14 +180,27 @@ void Button::_notification(int p_what) {
int valign = size.height - style->get_minimum_size().y;

float icon_ofs_region = 0;
if (_internal_margin[MARGIN_LEFT] > 0) {
icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
Point2 style_offset;
Size2 icon_size = _icon->get_size();
if (icon_align == ALIGN_LEFT) {
style_offset.x = style->get_margin(MARGIN_LEFT);
if (_internal_margin[MARGIN_LEFT] > 0) {
icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
}
} else if (icon_align == ALIGN_CENTER) {
style_offset.x = 0;
} else if (icon_align == ALIGN_RIGHT) {
style_offset.x = -style->get_margin(MARGIN_RIGHT);
if (_internal_margin[MARGIN_RIGHT] > 0) {
icon_ofs_region = -_internal_margin[MARGIN_RIGHT] - get_constant("hseparation");
}
}
style_offset.y = style->get_margin(MARGIN_TOP);

if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2;
_size.width -= get_constant("hseparation") + icon_ofs_region;
if (!clip_text) {
if (!clip_text && icon_align != ALIGN_CENTER) {
_size.width -= get_font("font")->get_string_size(xl_text).width;
}
float icon_width = _icon->get_width() * _size.height / _icon->get_height();
Expand All @@ -193,13 +211,26 @@ void Button::_notification(int p_what) {
icon_height = _icon->get_height() * icon_width / _icon->get_width();
}

icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, (_size.height - icon_height) / 2), Size2(icon_width, icon_height));
icon_size = Size2(icon_width, icon_height);
}

if (icon_align == ALIGN_LEFT) {
icon_region = Rect2(style_offset + Point2(icon_ofs_region, Math::floor((valign - icon_size.y) * 0.5)), icon_size);
} else if (icon_align == ALIGN_CENTER) {
icon_region = Rect2(style_offset + Point2(icon_ofs_region + Math::floor((size.x - icon_size.x) * 0.5), Math::floor((valign - icon_size.y) * 0.5)), icon_size);
} else {
icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, Math::floor((valign - _icon->get_height()) / 2.0)), _icon->get_size());
icon_region = Rect2(style_offset + Point2(icon_ofs_region + size.x - icon_size.x, Math::floor((valign - icon_size.y) * 0.5)), icon_size);
}

if (icon_region.size.width > 0) {
draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon);
}
}

Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_constant("hseparation"), 0) : Point2();
if (align == ALIGN_CENTER && icon_align == ALIGN_CENTER) {
icon_ofs.x = 0;
}
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
if (_internal_margin[MARGIN_LEFT] > 0) {
text_clip -= _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
Expand All @@ -212,6 +243,9 @@ void Button::_notification(int p_what) {

switch (align) {
case ALIGN_LEFT: {
if (icon_align != ALIGN_LEFT) {
icon_ofs.x = 0;
}
if (_internal_margin[MARGIN_LEFT] > 0) {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
} else {
Expand All @@ -223,25 +257,27 @@ void Button::_notification(int p_what) {
if (text_ofs.x < 0) {
text_ofs.x = 0;
}
text_ofs += icon_ofs;
if (icon_align == ALIGN_LEFT) {
text_ofs += icon_ofs;
}
text_ofs += style->get_offset();
} break;
case ALIGN_RIGHT: {
int text_width = font->get_string_size(xl_text).x;
if (_internal_margin[MARGIN_RIGHT] > 0) {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_constant("hseparation");
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - text_width - _internal_margin[MARGIN_RIGHT] - get_constant("hseparation");
} else {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - text_width;
}
text_ofs.y += style->get_offset().y;
if (icon_align == ALIGN_RIGHT) {
text_ofs.x -= icon_ofs.x;
}
} break;
}

text_ofs.y += font->get_ascent();
font->draw(ci, text_ofs.floor(), xl_text, color, clip_text ? text_clip : -1);

if (!_icon.is_null() && icon_region.size.width > 0) {
draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon);
}
} break;
}
}
Expand Down Expand Up @@ -313,19 +349,31 @@ Button::TextAlign Button::get_text_align() const {
return align;
}

void Button::set_icon_align(TextAlign p_align) {
icon_align = p_align;
minimum_size_changed();
update();
}

Button::TextAlign Button::get_icon_align() const {
return icon_align;
}

void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text);
ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon);
ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_icon);
ClassDB::bind_method(D_METHOD("set_expand_icon"), &Button::set_expand_icon);
ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);
ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &Button::set_flat);
ClassDB::bind_method(D_METHOD("is_flat"), &Button::is_flat);
ClassDB::bind_method(D_METHOD("set_clip_text", "enabled"), &Button::set_clip_text);
ClassDB::bind_method(D_METHOD("get_clip_text"), &Button::get_clip_text);
ClassDB::bind_method(D_METHOD("set_text_align", "align"), &Button::set_text_align);
ClassDB::bind_method(D_METHOD("get_text_align"), &Button::get_text_align);
ClassDB::bind_method(D_METHOD("is_flat"), &Button::is_flat);
ClassDB::bind_method(D_METHOD("set_icon_align", "icon_align"), &Button::set_icon_align);
ClassDB::bind_method(D_METHOD("get_icon_align"), &Button::get_icon_align);
ClassDB::bind_method(D_METHOD("set_expand_icon"), &Button::set_expand_icon);
ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);

BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
Expand All @@ -336,6 +384,7 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_align", "get_icon_align");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
}

Expand All @@ -346,6 +395,7 @@ Button::Button(const String &p_text) {
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
align = ALIGN_CENTER;
icon_align = ALIGN_LEFT;

for (int i = 0; i < 4; i++) {
_internal_margin[i] = 0;
Expand Down
4 changes: 4 additions & 0 deletions scene/gui/button.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class Button : public BaseButton {
bool expand_icon;
bool clip_text;
TextAlign align;
TextAlign icon_align;
float _internal_margin[4];

protected:
Expand Down Expand Up @@ -79,6 +80,9 @@ class Button : public BaseButton {
void set_text_align(TextAlign p_align);
TextAlign get_text_align() const;

void set_icon_align(TextAlign p_align);
TextAlign get_icon_align() const;

Button(const String &p_text = String());
~Button();
};
Expand Down