Browse Source

Fix multiline items drawing in `Tree`

Danil Alexeev 2 years ago
parent
commit
865d6f5ed0
2 changed files with 25 additions and 20 deletions
  1. 23 18
      scene/gui/tree.cpp
  2. 2 2
      scene/gui/tree.h

+ 23 - 18
scene/gui/tree.cpp

@@ -1773,7 +1773,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
 	return height;
 	return height;
 }
 }
 
 
-void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Point2 &p_draw_ofs, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color) {
+void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color) {
 	ERR_FAIL_COND(theme_cache.font.is_null());
 	ERR_FAIL_COND(theme_cache.font.is_null());
 
 
 	Rect2i rect = p_rect;
 	Rect2i rect = p_rect;
@@ -1811,8 +1811,7 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Po
 
 
 	if (rtl && rect.size.width > 0) {
 	if (rtl && rect.size.width > 0) {
 		Point2 draw_pos = rect.position;
 		Point2 draw_pos = rect.position;
-		draw_pos.y += Math::floor(p_draw_ofs.y) - _get_title_button_height();
-		p_cell.text_buf->set_width(rect.size.width);
+		draw_pos.y += Math::floor((rect.size.y - p_cell.text_buf->get_size().y) * 0.5);
 		if (p_ol_size > 0 && p_ol_color.a > 0) {
 		if (p_ol_size > 0 && p_ol_color.a > 0) {
 			p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
 			p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
 		}
 		}
@@ -1831,8 +1830,7 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Po
 
 
 	if (!rtl && rect.size.width > 0) {
 	if (!rtl && rect.size.width > 0) {
 		Point2 draw_pos = rect.position;
 		Point2 draw_pos = rect.position;
-		draw_pos.y += Math::floor(p_draw_ofs.y) - _get_title_button_height();
-		p_cell.text_buf->set_width(rect.size.width);
+		draw_pos.y += Math::floor((rect.size.y - p_cell.text_buf->get_size().y) * 0.5);
 		if (p_ol_size > 0 && p_ol_color.a > 0) {
 		if (p_ol_size > 0 && p_ol_color.a > 0) {
 			p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
 			p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
 		}
 		}
@@ -1907,6 +1905,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
 		font_size = theme_cache.font_size;
 		font_size = theme_cache.font_size;
 	}
 	}
 	p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language);
 	p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language);
+	p_item->cells.write[p_col].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE);
 	TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
 	TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
 	p_item->cells.write[p_col].dirty = false;
 	p_item->cells.write[p_col].dirty = false;
 }
 }
@@ -1923,7 +1922,7 @@ void Tree::update_item_cache(TreeItem *p_item) {
 	}
 	}
 }
 }
 
 
-int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item) {
+int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item, int *r_self_height) {
 	if (p_pos.y - theme_cache.offset.y > (p_draw_size.height)) {
 	if (p_pos.y - theme_cache.offset.y > (p_draw_size.height)) {
 		return -1; //draw no more!
 		return -1; //draw no more!
 	}
 	}
@@ -1936,17 +1935,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 
 
 	int htotal = 0;
 	int htotal = 0;
 
 
-	int label_h = compute_item_height(p_item);
+	int label_h = 0;
 	bool rtl = cache.rtl;
 	bool rtl = cache.rtl;
 
 
-	/* Calculate height of the label part */
-	label_h += theme_cache.v_separation;
-
 	/* Draw label, if height fits */
 	/* Draw label, if height fits */
 
 
 	bool skip = (p_item == root && hide_root);
 	bool skip = (p_item == root && hide_root);
 
 
-	if (!skip && (p_pos.y + label_h - theme_cache.offset.y) > 0) {
+	if (!skip) {
 		// Draw separation.
 		// Draw separation.
 
 
 		ERR_FAIL_COND_V(theme_cache.font.is_null(), -1);
 		ERR_FAIL_COND_V(theme_cache.font.is_null(), -1);
@@ -2006,6 +2002,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 				buttons_width += button_size.width + theme_cache.button_margin;
 				buttons_width += button_size.width + theme_cache.button_margin;
 			}
 			}
 
 
+			p_item->cells.write[i].text_buf->set_width(item_width);
+
+			label_h = compute_item_height(p_item);
+			if (r_self_height != nullptr) {
+				*r_self_height = label_h;
+			}
+			label_h += theme_cache.v_separation;
+
 			Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - theme_cache.offset + p_draw_ofs, Size2i(item_width, label_h));
 			Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - theme_cache.offset + p_draw_ofs, Size2i(item_width, label_h));
 			Rect2i cell_rect = item_rect;
 			Rect2i cell_rect = item_rect;
 			if (i != 0) {
 			if (i != 0) {
@@ -2129,7 +2133,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 
 
 			switch (p_item->cells[i].mode) {
 			switch (p_item->cells[i].mode) {
 				case TreeItem::CELL_MODE_STRING: {
 				case TreeItem::CELL_MODE_STRING: {
-					draw_item_rect(p_item->cells.write[i], item_rect, p_draw_ofs, cell_color, icon_col, outline_size, font_outline_color);
+					draw_item_rect(p_item->cells.write[i], item_rect, cell_color, icon_col, outline_size, font_outline_color);
 				} break;
 				} break;
 				case TreeItem::CELL_MODE_CHECK: {
 				case TreeItem::CELL_MODE_CHECK: {
 					Ref<Texture2D> checked = theme_cache.checked;
 					Ref<Texture2D> checked = theme_cache.checked;
@@ -2153,7 +2157,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 					item_rect.size.x -= check_w;
 					item_rect.size.x -= check_w;
 					item_rect.position.x += check_w;
 					item_rect.position.x += check_w;
 
 
-					draw_item_rect(p_item->cells.write[i], item_rect, p_draw_ofs, cell_color, icon_col, outline_size, font_outline_color);
+					draw_item_rect(p_item->cells.write[i], item_rect, cell_color, icon_col, outline_size, font_outline_color);
 
 
 				} break;
 				} break;
 				case TreeItem::CELL_MODE_RANGE: {
 				case TreeItem::CELL_MODE_RANGE: {
@@ -2165,7 +2169,6 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 						Ref<Texture2D> downarrow = theme_cache.select_arrow;
 						Ref<Texture2D> downarrow = theme_cache.select_arrow;
 						int cell_width = item_rect.size.x - downarrow->get_width();
 						int cell_width = item_rect.size.x - downarrow->get_width();
 
 
-						p_item->cells.write[i].text_buf->set_width(cell_width);
 						if (rtl) {
 						if (rtl) {
 							if (outline_size > 0 && font_outline_color.a > 0) {
 							if (outline_size > 0 && font_outline_color.a > 0) {
 								p_item->cells[i].text_buf->draw_outline(ci, text_pos + Vector2(cell_width - text_width, 0), outline_size, font_outline_color);
 								p_item->cells[i].text_buf->draw_outline(ci, text_pos + Vector2(cell_width - text_width, 0), outline_size, font_outline_color);
@@ -2232,7 +2235,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 					}
 					}
 
 
 					if (!p_item->cells[i].editable) {
 					if (!p_item->cells[i].editable) {
-						draw_item_rect(p_item->cells.write[i], item_rect, p_draw_ofs, cell_color, icon_col, outline_size, font_outline_color);
+						draw_item_rect(p_item->cells.write[i], item_rect, cell_color, icon_col, outline_size, font_outline_color);
 						break;
 						break;
 					}
 					}
 
 
@@ -2260,7 +2263,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 						ir.position += theme_cache.custom_button->get_offset();
 						ir.position += theme_cache.custom_button->get_offset();
 					}
 					}
 
 
-					draw_item_rect(p_item->cells.write[i], ir, p_draw_ofs, cell_color, icon_col, outline_size, font_outline_color);
+					draw_item_rect(p_item->cells.write[i], ir, cell_color, icon_col, outline_size, font_outline_color);
 
 
 					downarrow->draw(ci, arrow_pos);
 					downarrow->draw(ci, arrow_pos);
 
 
@@ -2352,15 +2355,17 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 
 
 		while (c) {
 		while (c) {
 			int child_h = -1;
 			int child_h = -1;
+			int child_self_height = 0;
 			if (htotal >= 0) {
 			if (htotal >= 0) {
-				child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c);
+				child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c, &child_self_height);
+				child_self_height += theme_cache.v_separation;
 			}
 			}
 
 
 			// Draw relationship lines.
 			// Draw relationship lines.
 			if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
 			if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
 				int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin);
 				int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin);
 				int parent_ofs = p_pos.x + theme_cache.item_margin;
 				int parent_ofs = p_pos.x + theme_cache.item_margin;
-				Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - theme_cache.offset + p_draw_ofs;
+				Point2i root_pos = Point2i(root_ofs, children_pos.y + child_self_height / 2) - theme_cache.offset + p_draw_ofs;
 
 
 				if (c->get_visible_child_count() > 0) {
 				if (c->get_visible_child_count() > 0) {
 					root_pos -= Point2i(theme_cache.arrow->get_width(), 0);
 					root_pos -= Point2i(theme_cache.arrow->get_width(), 0);

+ 2 - 2
scene/gui/tree.h

@@ -476,8 +476,8 @@ private:
 	void update_item_cell(TreeItem *p_item, int p_col);
 	void update_item_cell(TreeItem *p_item, int p_col);
 	void update_item_cache(TreeItem *p_item);
 	void update_item_cache(TreeItem *p_item);
 	//void draw_item_text(String p_text,const Ref<Texture2D>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);
 	//void draw_item_text(String p_text,const Ref<Texture2D>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);
-	void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Point2 &p_draw_ofs, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color);
-	int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
+	void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color);
+	int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item, int *r_self_height = nullptr);
 	void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
 	void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
 	int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, MouseButton p_button, const Ref<InputEventWithModifiers> &p_mod);
 	int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, MouseButton p_button, const Ref<InputEventWithModifiers> &p_mod);
 	void _line_editor_submit(String p_text);
 	void _line_editor_submit(String p_text);