Add alignment options to icons on buttons.

They can now be centered and right-aligned.

Co-authored-by: jitspoe <jitspoe@yahoo.com>
This commit is contained in:
Raul Santos 2022-02-07 19:56:27 +01:00
parent 8acdd0502d
commit 1d3de163dc
3 changed files with 75 additions and 18 deletions

View file

@ -43,6 +43,9 @@
Button's icon, if text is present the icon will be placed before the text. 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. 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>
<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;"> <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. The button's text that will be displayed inside the button's area.
</member> </member>

View file

@ -49,9 +49,14 @@ Size2 Button::get_minimum_size() const {
if (!_icon.is_null()) { if (!_icon.is_null()) {
minsize.height = MAX(minsize.height, _icon->get_height()); minsize.height = MAX(minsize.height, _icon->get_height());
minsize.width += _icon->get_width();
if (xl_text != "") { if (icon_align != ALIGN_CENTER) {
minsize.width += get_constant("hseparation"); minsize.width += _icon->get_width();
if (xl_text != "") {
minsize.width += get_constant("hseparation");
}
} else {
minsize.width = MAX(minsize.width, _icon->get_width());
} }
} }
} }
@ -175,14 +180,27 @@ void Button::_notification(int p_what) {
int valign = size.height - style->get_minimum_size().y; int valign = size.height - style->get_minimum_size().y;
float icon_ofs_region = 0; float icon_ofs_region = 0;
if (_internal_margin[MARGIN_LEFT] > 0) { Point2 style_offset;
icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_constant("hseparation"); 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) { if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2; Size2 _size = get_size() - style->get_offset() * 2;
_size.width -= get_constant("hseparation") + icon_ofs_region; _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; _size.width -= get_font("font")->get_string_size(xl_text).width;
} }
float icon_width = _icon->get_width() * _size.height / _icon->get_height(); float icon_width = _icon->get_width() * _size.height / _icon->get_height();
@ -193,13 +211,26 @@ void Button::_notification(int p_what) {
icon_height = _icon->get_height() * icon_width / _icon->get_width(); 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 { } 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(); 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; int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
if (_internal_margin[MARGIN_LEFT] > 0) { if (_internal_margin[MARGIN_LEFT] > 0) {
text_clip -= _internal_margin[MARGIN_LEFT] + get_constant("hseparation"); text_clip -= _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
@ -212,6 +243,9 @@ void Button::_notification(int p_what) {
switch (align) { switch (align) {
case ALIGN_LEFT: { case ALIGN_LEFT: {
if (icon_align != ALIGN_LEFT) {
icon_ofs.x = 0;
}
if (_internal_margin[MARGIN_LEFT] > 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"); text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
} else { } else {
@ -223,25 +257,27 @@ void Button::_notification(int p_what) {
if (text_ofs.x < 0) { if (text_ofs.x < 0) {
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(); text_ofs += style->get_offset();
} break; } break;
case ALIGN_RIGHT: { case ALIGN_RIGHT: {
int text_width = font->get_string_size(xl_text).x;
if (_internal_margin[MARGIN_RIGHT] > 0) { 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 { } 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; text_ofs.y += style->get_offset().y;
if (icon_align == ALIGN_RIGHT) {
text_ofs.x -= icon_ofs.x;
}
} break; } break;
} }
text_ofs.y += font->get_ascent(); text_ofs.y += font->get_ascent();
font->draw(ci, text_ofs.floor(), xl_text, color, clip_text ? text_clip : -1); 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; } break;
} }
} }
@ -313,19 +349,31 @@ Button::TextAlign Button::get_text_align() const {
return align; 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() { void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text); 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("get_text"), &Button::get_text);
ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon); 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("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("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("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("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("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("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_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER); BIND_ENUM_CONSTANT(ALIGN_CENTER);
@ -336,6 +384,7 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); 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::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, "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"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
} }
@ -346,6 +395,7 @@ Button::Button(const String &p_text) {
set_mouse_filter(MOUSE_FILTER_STOP); set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text); set_text(p_text);
align = ALIGN_CENTER; align = ALIGN_CENTER;
icon_align = ALIGN_LEFT;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
_internal_margin[i] = 0; _internal_margin[i] = 0;

View file

@ -51,6 +51,7 @@ private:
bool expand_icon; bool expand_icon;
bool clip_text; bool clip_text;
TextAlign align; TextAlign align;
TextAlign icon_align;
float _internal_margin[4]; float _internal_margin[4];
protected: protected:
@ -79,6 +80,9 @@ public:
void set_text_align(TextAlign p_align); void set_text_align(TextAlign p_align);
TextAlign get_text_align() const; TextAlign get_text_align() const;
void set_icon_align(TextAlign p_align);
TextAlign get_icon_align() const;
Button(const String &p_text = String()); Button(const String &p_text = String());
~Button(); ~Button();
}; };