1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Add text trimming in LinkButton

This commit is contained in:
Michael Alexsander
2025-10-24 19:03:40 -03:00
parent 0fdb93cde6
commit 687aa56ec8
6 changed files with 43 additions and 30 deletions

View File

@@ -27,6 +27,9 @@
<member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="Control.TextDirection" default="0"> <member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="Control.TextDirection" default="0">
Base text writing direction. Base text writing direction.
</member> </member>
<member name="text_overrun_behavior" type="int" setter="set_text_overrun_behavior" getter="get_text_overrun_behavior" enum="TextServer.OverrunBehavior" default="0">
Sets the clipping behavior when the text exceeds the node's bounding rectangle.
</member>
<member name="underline" type="int" setter="set_underline_mode" getter="get_underline_mode" enum="LinkButton.UnderlineMode" default="0"> <member name="underline" type="int" setter="set_underline_mode" getter="get_underline_mode" enum="LinkButton.UnderlineMode" default="0">
The underline mode to use for the text. The underline mode to use for the text.
</member> </member>

View File

@@ -67,20 +67,6 @@ void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, co
price->set_text(p_cost); price->set_text(p_cost);
} }
// TODO: Refactor this method to use the TextServer.
void EditorAssetLibraryItem::clamp_width(int p_max_width) {
int text_pixel_width = title->get_button_font()->get_string_size(title_text).x * EDSCALE;
if (text_pixel_width > p_max_width) {
// Truncate title text to within the current column width.
int max_length = p_max_width / (text_pixel_width / title_text.length());
String truncated_text = title_text.left(max_length - 3) + "...";
title->set_text(truncated_text);
} else {
title->set_text(title_text);
}
}
void EditorAssetLibraryItem::set_image(int p_type, int p_index, const Ref<Texture2D> &p_image) { void EditorAssetLibraryItem::set_image(int p_type, int p_index, const Ref<Texture2D> &p_image) {
ERR_FAIL_COND(p_type != EditorAssetLibrary::IMAGE_QUEUE_ICON); ERR_FAIL_COND(p_type != EditorAssetLibrary::IMAGE_QUEUE_ICON);
ERR_FAIL_COND(p_index != 0); ERR_FAIL_COND(p_index != 0);
@@ -148,11 +134,13 @@ EditorAssetLibraryItem::EditorAssetLibraryItem(bool p_clickable) {
title = memnew(LinkButton); title = memnew(LinkButton);
title->set_accessibility_name(TTRC("Title")); title->set_accessibility_name(TTRC("Title"));
title->set_auto_translate_mode(AutoTranslateMode::AUTO_TRANSLATE_MODE_DISABLED); title->set_auto_translate_mode(AutoTranslateMode::AUTO_TRANSLATE_MODE_DISABLED);
title->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
title->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); title->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
vb->add_child(title); vb->add_child(title);
category = memnew(LinkButton); category = memnew(LinkButton);
category->set_accessibility_name(TTRC("Category")); category->set_accessibility_name(TTRC("Category"));
category->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
vb->add_child(category); vb->add_child(category);
@@ -162,6 +150,7 @@ EditorAssetLibraryItem::EditorAssetLibraryItem(bool p_clickable) {
author = memnew(LinkButton); author = memnew(LinkButton);
author->set_tooltip_text(TTRC("Author")); author->set_tooltip_text(TTRC("Author"));
author->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
author->set_accessibility_name(TTRC("Author")); author->set_accessibility_name(TTRC("Author"));
author_price_hbox->add_child(author); author_price_hbox->add_child(author);
@@ -1398,7 +1387,6 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
EditorAssetLibraryItem *item = memnew(EditorAssetLibraryItem(true)); EditorAssetLibraryItem *item = memnew(EditorAssetLibraryItem(true));
asset_items->add_child(item); asset_items->add_child(item);
item->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["cost"]); item->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["cost"]);
item->clamp_width(asset_items_column_width);
item->connect("asset_selected", callable_mp(this, &EditorAssetLibrary::_select_asset)); item->connect("asset_selected", callable_mp(this, &EditorAssetLibrary::_select_asset));
item->connect("author_selected", callable_mp(this, &EditorAssetLibrary::_select_author)); item->connect("author_selected", callable_mp(this, &EditorAssetLibrary::_select_author));
item->connect("category_selected", callable_mp(this, &EditorAssetLibrary::_select_category)); item->connect("category_selected", callable_mp(this, &EditorAssetLibrary::_select_category));
@@ -1534,16 +1522,6 @@ void EditorAssetLibrary::_update_asset_items_columns() {
if (new_columns != asset_items->get_columns()) { if (new_columns != asset_items->get_columns()) {
asset_items->set_columns(new_columns); asset_items->set_columns(new_columns);
} }
asset_items_column_width = (get_size().x / new_columns) - (120 * EDSCALE);
for (int i = 0; i < asset_items->get_child_count(); i++) {
EditorAssetLibraryItem *item = Object::cast_to<EditorAssetLibraryItem>(asset_items->get_child(i));
if (!item || !item->is_visible()) {
continue;
}
item->clamp_width(asset_items_column_width);
}
} }
void EditorAssetLibrary::_set_library_message(const String &p_message) { void EditorAssetLibrary::_set_library_message(const String &p_message) {

View File

@@ -76,8 +76,6 @@ protected:
public: public:
void configure(const String &p_title, int p_asset_id, const String &p_category, int p_category_id, const String &p_author, int p_author_id, const String &p_cost); void configure(const String &p_title, int p_asset_id, const String &p_category, int p_category_id, const String &p_author, int p_author_id, const String &p_cost);
void clamp_width(int p_max_width);
EditorAssetLibraryItem(bool p_clickable = false); EditorAssetLibraryItem(bool p_clickable = false);
}; };
@@ -312,8 +310,6 @@ class EditorAssetLibrary : public PanelContainer {
void _install_external_asset(String p_zip_path, String p_title); void _install_external_asset(String p_zip_path, String p_title);
int asset_items_column_width = 0;
void _update_asset_items_columns(); void _update_asset_items_columns();
friend class EditorAssetLibraryItemDescription; friend class EditorAssetLibraryItemDescription;

View File

@@ -37,6 +37,7 @@ void LinkButton::_shape() {
int font_size = theme_cache.font_size; int font_size = theme_cache.font_size;
text_buf->clear(); text_buf->clear();
text_buf->set_width(-1);
if (text_direction == Control::TEXT_DIRECTION_INHERITED) { if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else { } else {
@@ -45,6 +46,7 @@ void LinkButton::_shape() {
TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, xl_text)); TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, xl_text));
const String &lang = language.is_empty() ? _get_locale() : language; const String &lang = language.is_empty() ? _get_locale() : language;
text_buf->add_string(xl_text, font, font_size, lang); text_buf->add_string(xl_text, font, font_size, lang);
text_buf->set_text_overrun_behavior(overrun_behavior);
queue_accessibility_update(); queue_accessibility_update();
} }
@@ -64,6 +66,19 @@ String LinkButton::get_text() const {
return text; return text;
} }
void LinkButton::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
if (overrun_behavior != p_behavior) {
overrun_behavior = p_behavior;
_shape();
update_minimum_size();
queue_redraw();
}
}
TextServer::OverrunBehavior LinkButton::get_text_overrun_behavior() const {
return overrun_behavior;
}
void LinkButton::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { void LinkButton::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
if (st_parser != p_parser) { if (st_parser != p_parser) {
st_parser = p_parser; st_parser = p_parser;
@@ -148,7 +163,12 @@ void LinkButton::pressed() {
} }
Size2 LinkButton::get_minimum_size() const { Size2 LinkButton::get_minimum_size() const {
return text_buf->get_size(); Size2 minsize = text_buf->get_size();
if (overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
minsize.width = 0;
}
return minsize;
} }
void LinkButton::_notification(int p_what) { void LinkButton::_notification(int p_what) {
@@ -178,6 +198,7 @@ void LinkButton::_notification(int p_what) {
queue_redraw(); queue_redraw();
} break; } break;
case NOTIFICATION_RESIZED:
case NOTIFICATION_THEME_CHANGED: { case NOTIFICATION_THEME_CHANGED: {
_shape(); _shape();
update_minimum_size(); update_minimum_size();
@@ -228,6 +249,9 @@ void LinkButton::_notification(int p_what) {
style->draw(ci, Rect2(Point2(), size)); style->draw(ci, Rect2(Point2(), size));
} }
if (overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
text_buf->set_width(MAX(1.0f, size.width));
}
int width = text_buf->get_line_width(); int width = text_buf->get_line_width();
Color font_outline_color = theme_cache.font_outline_color; Color font_outline_color = theme_cache.font_outline_color;
@@ -262,6 +286,8 @@ void LinkButton::_notification(int p_what) {
void LinkButton::_bind_methods() { void LinkButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &LinkButton::set_text); ClassDB::bind_method(D_METHOD("set_text", "text"), &LinkButton::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &LinkButton::get_text); ClassDB::bind_method(D_METHOD("get_text"), &LinkButton::get_text);
ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &LinkButton::set_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &LinkButton::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &LinkButton::set_text_direction); ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &LinkButton::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &LinkButton::get_text_direction); ClassDB::bind_method(D_METHOD("get_text_direction"), &LinkButton::get_text_direction);
ClassDB::bind_method(D_METHOD("set_language", "language"), &LinkButton::set_language); ClassDB::bind_method(D_METHOD("set_language", "language"), &LinkButton::set_language);
@@ -283,6 +309,9 @@ void LinkButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "uri"), "set_uri", "get_uri"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "uri"), "set_uri", "get_uri");
ADD_GROUP("Text Behavior", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis (6+ Characters),Word Ellipsis (6+ Characters),Ellipsis (Always),Word Ellipsis (Always)"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_GROUP("BiDi", ""); ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");

View File

@@ -54,6 +54,7 @@ private:
TextDirection text_direction = TEXT_DIRECTION_AUTO; TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args; Array st_args;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
struct ThemeCache { struct ThemeCache {
Ref<StyleBox> focus; Ref<StyleBox> focus;
@@ -88,6 +89,9 @@ public:
void set_uri(const String &p_uri); void set_uri(const String &p_uri);
String get_uri() const; String get_uri() const;
void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior);
TextServer::OverrunBehavior get_text_overrun_behavior() const;
void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
TextServer::StructuredTextParser get_structured_text_bidi_override() const; TextServer::StructuredTextParser get_structured_text_bidi_override() const;

View File

@@ -321,6 +321,9 @@ String TextLine::get_ellipsis_char() const {
} }
void TextLine::set_width(float p_width) { void TextLine::set_width(float p_width) {
if (width == p_width) {
return;
}
width = p_width; width = p_width;
if (alignment == HORIZONTAL_ALIGNMENT_FILL || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { if (alignment == HORIZONTAL_ALIGNMENT_FILL || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
dirty = true; dirty = true;