Merge pull request #87025 from bruvzg/button_wrap

[Button] Add autowrap feature.
This commit is contained in:
Rémi Verschelde 2024-02-23 11:29:32 +01:00
commit 12817f2993
No known key found for this signature in database
GPG key ID: C3336907360768E1
3 changed files with 51 additions and 2 deletions

View file

@ -43,6 +43,9 @@
<member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" enum="HorizontalAlignment" default="1"> <member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" enum="HorizontalAlignment" default="1">
Text alignment policy for the button's text, use one of the [enum HorizontalAlignment] constants. Text alignment policy for the button's text, use one of the [enum HorizontalAlignment] constants.
</member> </member>
<member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="TextServer.AutowrapMode" default="0">
If set to something other than [constant TextServer.AUTOWRAP_OFF], the text gets wrapped inside the node's bounding rectangle.
</member>
<member name="clip_text" type="bool" setter="set_clip_text" getter="get_clip_text" default="false"> <member name="clip_text" type="bool" setter="set_clip_text" getter="get_clip_text" default="false">
When this property is enabled, text that is too large to fit the button is clipped, when disabled the Button will always be wide enough to hold the text. When this property is enabled, text that is too large to fit the button is clipped, when disabled the Button will always be wide enough to hold the text.
</member> </member>

View file

@ -128,6 +128,15 @@ void Button::_notification(int p_what) {
queue_redraw(); queue_redraw();
} break; } break;
case NOTIFICATION_RESIZED: {
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
_shape();
update_minimum_size();
queue_redraw();
}
} break;
case NOTIFICATION_DRAW: { case NOTIFICATION_DRAW: {
const RID ci = get_canvas_item(); const RID ci = get_canvas_item();
const Size2 size = get_size(); const Size2 size = get_size();
@ -261,7 +270,7 @@ void Button::_notification(int p_what) {
} break; } break;
} }
const bool is_clipped = clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING; const bool is_clipped = clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING || autowrap_mode != TextServer::AUTOWRAP_OFF;
const Size2 custom_element_size = drawable_size_remained; const Size2 custom_element_size = drawable_size_remained;
// Draw the icon. // Draw the icon.
@ -415,7 +424,7 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
} }
Size2 minsize = paragraph->get_size(); Size2 minsize = paragraph->get_size();
if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { if (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING || autowrap_mode != TextServer::AUTOWRAP_OFF) {
minsize.width = 0; minsize.width = 0;
} }
@ -468,6 +477,23 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
return; return;
} }
BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
case TextServer::AUTOWRAP_WORD_SMART:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
break;
case TextServer::AUTOWRAP_WORD:
autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
break;
case TextServer::AUTOWRAP_ARBITRARY:
autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
break;
case TextServer::AUTOWRAP_OFF:
break;
}
autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
p_paragraph->set_break_flags(autowrap_flags);
if (text_direction == Control::TEXT_DIRECTION_INHERITED) { if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else { } else {
@ -510,6 +536,19 @@ String Button::get_text() const {
return text; return text;
} }
void Button::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
if (autowrap_mode != p_mode) {
autowrap_mode = p_mode;
_shape();
queue_redraw();
update_minimum_size();
}
}
TextServer::AutowrapMode Button::get_autowrap_mode() const {
return autowrap_mode;
}
void Button::set_text_direction(Control::TextDirection p_text_direction) { void Button::set_text_direction(Control::TextDirection p_text_direction) {
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (text_direction != p_text_direction) { if (text_direction != p_text_direction) {
@ -649,6 +688,8 @@ void Button::_bind_methods() {
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_text_overrun_behavior", "overrun_behavior"), &Button::set_text_overrun_behavior); ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &Button::set_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Button::get_text_overrun_behavior); ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Button::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Button::set_autowrap_mode);
ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Button::get_autowrap_mode);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction); ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction); ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language); ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language);
@ -675,6 +716,7 @@ void Button::_bind_methods() {
ADD_GROUP("Text Behavior", ""); ADD_GROUP("Text Behavior", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_alignment", "get_text_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_alignment", "get_text_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
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_GROUP("Icon Behavior", ""); ADD_GROUP("Icon Behavior", "");

View file

@ -45,6 +45,7 @@ private:
String language; String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO; TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING; TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
Ref<Texture2D> icon; Ref<Texture2D> icon;
@ -120,6 +121,9 @@ public:
void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior); void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
TextServer::OverrunBehavior get_text_overrun_behavior() const; TextServer::OverrunBehavior get_text_overrun_behavior() const;
void set_autowrap_mode(TextServer::AutowrapMode p_mode);
TextServer::AutowrapMode get_autowrap_mode() const;
void set_text_direction(TextDirection p_text_direction); void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const; TextDirection get_text_direction() const;