Quellcode durchsuchen

Merge pull request #51886 from Geometror/fix-layout-editor-file-dialog

Fix ItemList layout (+EditorFileDialog)
Michael Alexsander vor 4 Jahren
Ursprung
Commit
2f8a58ad46

+ 3 - 0
doc/classes/ItemList.xml

@@ -403,6 +403,9 @@
 		<member name="select_mode" type="int" setter="set_select_mode" getter="get_select_mode" enum="ItemList.SelectMode" default="0">
 			Allows single or multiple item selection. See the [enum SelectMode] constants.
 		</member>
+		<member name="text_overrun_behavior" type="int" setter="set_text_overrun_behavior" getter="get_text_overrun_behavior" enum="TextParagraph.OverrunBehavior" default="0">
+			Sets the clipping behavior when the text exceeds an item's bounding rectangle. See [enum TextParagraph.OverrunBehavior] for a description of all modes.
+		</member>
 	</members>
 	<signals>
 		<signal name="item_activated">

+ 2 - 0
editor/editor_file_dialog.cpp

@@ -728,6 +728,7 @@ void EditorFileDialog::update_file_list() {
 		item_list->set_icon_mode(ItemList::ICON_MODE_TOP);
 		item_list->set_fixed_column_width(thumbnail_size * 3 / 2);
 		item_list->set_max_text_lines(2);
+		item_list->set_text_overrun_behavior(TextParagraph::OVERRUN_TRIM_ELLIPSIS);
 		item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
 
 		if (thumbnail_size < 64) {
@@ -1645,6 +1646,7 @@ EditorFileDialog::EditorFileDialog() {
 	item_list->connect("item_rmb_selected", callable_mp(this, &EditorFileDialog::_item_list_item_rmb_selected));
 	item_list->connect("rmb_clicked", callable_mp(this, &EditorFileDialog::_item_list_rmb_clicked));
 	item_list->set_allow_rmb_select(true);
+
 	list_vb->add_child(item_list);
 
 	item_menu = memnew(PopupMenu);

+ 31 - 7
scene/gui/item_list.cpp

@@ -48,6 +48,8 @@ void ItemList::_shape(int p_idx) {
 	} else {
 		item.text_buf->set_flags(TextServer::BREAK_NONE);
 	}
+	item.text_buf->set_text_overrun_behavior(text_overrun_behavior);
+	item.text_buf->set_max_lines_visible(max_text_lines);
 }
 
 int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bool p_selectable) {
@@ -453,6 +455,7 @@ void ItemList::set_max_text_lines(int p_lines) {
 		for (int i = 0; i < items.size(); i++) {
 			if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
 				items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+				items.write[i].text_buf->set_max_lines_visible(p_lines);
 			} else {
 				items.write[i].text_buf->set_flags(TextServer::BREAK_NONE);
 			}
@@ -930,8 +933,14 @@ void ItemList::_notification(int p_what) {
 				}
 
 				if (items[i].text != "") {
+					int max_width = -1;
+					if (fixed_column_width) {
+						max_width = fixed_column_width;
+					} else if (same_column_width) {
+						max_width = items[i].rect_cache.size.x;
+					}
+					items.write[i].text_buf->set_width(max_width);
 					Size2 s = items[i].text_buf->get_size();
-					//s.width=MIN(s.width,fixed_column_width);
 
 					if (icon_mode == ICON_MODE_TOP) {
 						minsize.x = MAX(minsize.x, s.width);
@@ -1139,11 +1148,8 @@ void ItemList::_notification(int p_what) {
 
 				if (icon_mode == ICON_MODE_TOP) {
 					pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width) / 2);
-					pos.y += MIN(
-							Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2),
-							items[i].rect_cache.size.height - items[i].min_rect_cache.size.height);
-					text_ofs.y = icon_size.height + icon_margin;
-					text_ofs.y += items[i].rect_cache.size.height - items[i].min_rect_cache.size.height;
+					pos.y += icon_margin;
+					text_ofs.y = icon_size.height + icon_margin * 2;
 				} else {
 					pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2);
 					text_ofs.x = icon_size.width + icon_margin;
@@ -1210,7 +1216,6 @@ void ItemList::_notification(int p_what) {
 						text_ofs.x = size.width - text_ofs.x - max_len;
 					}
 
-					items.write[i].text_buf->set_width(max_len);
 					items.write[i].text_buf->set_align(HALIGN_CENTER);
 
 					if (outline_size > 0 && font_outline_color.a > 0) {
@@ -1488,6 +1493,21 @@ bool ItemList::has_auto_height() const {
 	return auto_height;
 }
 
+void ItemList::set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavior) {
+	if (text_overrun_behavior != p_behavior) {
+		text_overrun_behavior = p_behavior;
+		for (int i = 0; i < items.size(); i++) {
+			items.write[i].text_buf->set_text_overrun_behavior(p_behavior);
+		}
+		shape_changed = true;
+		update();
+	}
+}
+
+TextParagraph::OverrunBehavior ItemList::get_text_overrun_behavior() const {
+	return text_overrun_behavior;
+}
+
 void ItemList::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("add_item", "text", "icon", "selectable"), &ItemList::add_item, DEFVAL(Variant()), DEFVAL(true));
 	ClassDB::bind_method(D_METHOD("add_icon_item", "icon", "selectable"), &ItemList::add_icon_item, DEFVAL(true));
@@ -1599,6 +1619,9 @@ void ItemList::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("_set_items"), &ItemList::_set_items);
 	ClassDB::bind_method(D_METHOD("_get_items"), &ItemList::_get_items);
 
+	ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &ItemList::set_text_overrun_behavior);
+	ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &ItemList::get_text_overrun_behavior);
+
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode");
@@ -1606,6 +1629,7 @@ void ItemList::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "max_text_lines", PROPERTY_HINT_RANGE, "1,10,1,or_greater"), "set_max_text_lines", "get_max_text_lines");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height");
+	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_GROUP("Columns", "");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width");

+ 4 - 0
scene/gui/item_list.h

@@ -95,6 +95,7 @@ private:
 	SelectMode select_mode = SELECT_SINGLE;
 	IconMode icon_mode = ICON_MODE_LEFT;
 	VScrollBar *scroll_bar;
+	TextParagraph::OverrunBehavior text_overrun_behavior = TextParagraph::OVERRUN_NO_TRIMMING;
 
 	uint64_t search_time_msec = 0;
 	String search_string;
@@ -182,6 +183,9 @@ public:
 	void set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color);
 	Color get_item_custom_fg_color(int p_idx) const;
 
+	void set_text_overrun_behavior(TextParagraph::OverrunBehavior p_behavior);
+	TextParagraph::OverrunBehavior get_text_overrun_behavior() const;
+
 	void select(int p_idx, bool p_single = true);
 	void deselect(int p_idx);
 	void deselect_all();

+ 9 - 8
scene/resources/text_paragraph.cpp

@@ -437,7 +437,8 @@ Size2 TextParagraph::get_non_wraped_size() const {
 Size2 TextParagraph::get_size() const {
 	const_cast<TextParagraph *>(this)->_shape_lines();
 	Size2 size;
-	for (int i = 0; i < lines_rid.size(); i++) {
+	int visible_lines = (max_lines_visible >= 0) ? MIN(max_lines_visible, lines_rid.size()) : lines_rid.size();
+	for (int i = 0; i < visible_lines; i++) {
 		Size2 lsize = TS->shaped_text_get_size(lines_rid[i]);
 		if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
 			size.x = MAX(size.x, lsize.x);
@@ -587,15 +588,15 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
 				l_width -= h_offset;
 			}
 		}
-		float length = TS->shaped_text_get_width(lines_rid[i]);
+		float line_width = TS->shaped_text_get_width(lines_rid[i]);
 		if (width > 0) {
 			switch (align) {
 				case HALIGN_FILL:
 					if (TS->shaped_text_get_direction(lines_rid[i]) == TextServer::DIRECTION_RTL) {
 						if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
-							ofs.x += l_width - length;
+							ofs.x += l_width - line_width;
 						} else {
-							ofs.y += l_width - length;
+							ofs.y += l_width - line_width;
 						}
 					}
 					break;
@@ -603,16 +604,16 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
 					break;
 				case HALIGN_CENTER: {
 					if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
-						ofs.x += Math::floor((l_width - length) / 2.0);
+						ofs.x += Math::floor((l_width - line_width) / 2.0);
 					} else {
-						ofs.y += Math::floor((l_width - length) / 2.0);
+						ofs.y += Math::floor((l_width - line_width) / 2.0);
 					}
 				} break;
 				case HALIGN_RIGHT: {
 					if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
-						ofs.x += l_width - length;
+						ofs.x += l_width - line_width;
 					} else {
-						ofs.y += l_width - length;
+						ofs.y += l_width - line_width;
 					}
 				} break;
 			}

+ 2 - 4
servers/text_server.cpp

@@ -665,9 +665,7 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
 			continue;
 		}
 		if (l_gl[i].count > 0) {
-			//Ignore trailing spaces.
-			bool is_space = (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE;
-			if ((p_width > 0) && (width + (is_space ? 0 : l_gl[i].advance) > p_width) && (last_safe_break >= 0)) {
+			if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
 				lines.push_back(Vector2i(line_start, l_gl[last_safe_break].end));
 				line_start = l_gl[last_safe_break].end;
 				i = last_safe_break;
@@ -698,7 +696,7 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_w
 				last_safe_break = i;
 			}
 		}
-		width += l_gl[i].advance;
+		width += l_gl[i].advance * l_gl[i].repeat;
 	}
 
 	if (l_size > 0) {