Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multiline items drawing in Tree #76532

Merged
merged 1 commit into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 23 additions & 18 deletions scene/gui/tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1773,7 +1773,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
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());

Rect2i rect = p_rect;
Expand Down Expand Up @@ -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) {
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) {
p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
}
Expand All @@ -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) {
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) {
p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
}
Expand Down Expand Up @@ -1907,6 +1905,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
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->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap mode probably should be exposed as item property (similar to Label and other controls).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be done as a separate PR, as AutowrapMode includes more than just LineBreakFlag.

Copy link
Contributor

@capnm capnm Apr 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the start LineBreakFlag would e.g. fix this here in editor.
More then one line makes it IMO unreadable, for more info we have the tooltip.
image

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;
}
Expand All @@ -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)) {
return -1; //draw no more!
}
Expand All @@ -1936,17 +1935,14 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2

int htotal = 0;

int label_h = compute_item_height(p_item);
int label_h = 0;
bool rtl = cache.rtl;

/* Calculate height of the label part */
label_h += theme_cache.v_separation;

/* Draw label, if height fits */

bool skip = (p_item == root && hide_root);

if (!skip && (p_pos.y + label_h - theme_cache.offset.y) > 0) {
if (!skip) {
// Draw separation.

ERR_FAIL_COND_V(theme_cache.font.is_null(), -1);
Expand Down Expand Up @@ -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;
}

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 cell_rect = item_rect;
if (i != 0) {
Expand Down Expand Up @@ -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) {
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;
case TreeItem::CELL_MODE_CHECK: {
Ref<Texture2D> checked = theme_cache.checked;
Expand All @@ -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.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;
case TreeItem::CELL_MODE_RANGE: {
Expand All @@ -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;
int cell_width = item_rect.size.x - downarrow->get_width();

p_item->cells.write[i].text_buf->set_width(cell_width);
if (rtl) {
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);
Expand Down Expand Up @@ -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) {
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;
}

Expand Down Expand Up @@ -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();
}

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);

Expand Down Expand Up @@ -2352,15 +2355,17 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2

while (c) {
int child_h = -1;
int child_self_height = 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.
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 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) {
root_pos -= Point2i(theme_cache.arrow->get_width(), 0);
Expand Down
4 changes: 2 additions & 2 deletions scene/gui/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,8 @@ class Tree : public Control {
void update_item_cell(TreeItem *p_item, int p_col);
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_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);
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);
Expand Down