summaryrefslogtreecommitdiffstats
path: root/scene/gui/tree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/tree.cpp')
-rw-r--r--scene/gui/tree.cpp116
1 files changed, 65 insertions, 51 deletions
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index ee9c6573f4..3c1be2d5fe 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -247,29 +247,30 @@ void TreeItem::_propagate_check_through_parents(int p_column, bool p_emit_signal
return;
}
- bool all_unchecked_and_not_indeterminate = true;
- bool any_unchecked_or_indeterminate = false;
+ bool any_checked = false;
+ bool any_unchecked = false;
+ bool any_indeterminate = false;
TreeItem *child_item = current->get_first_child();
while (child_item) {
if (!child_item->is_checked(p_column)) {
- any_unchecked_or_indeterminate = true;
+ any_unchecked = true;
if (child_item->is_indeterminate(p_column)) {
- all_unchecked_and_not_indeterminate = false;
+ any_indeterminate = true;
break;
}
} else {
- all_unchecked_and_not_indeterminate = false;
+ any_checked = true;
}
child_item = child_item->get_next();
}
- if (all_unchecked_and_not_indeterminate) {
- current->set_checked(p_column, false);
- } else if (any_unchecked_or_indeterminate) {
+ if (any_indeterminate || (any_checked && any_unchecked)) {
current->set_indeterminate(p_column, true);
+ } else if (current->is_indeterminate(p_column) && !any_checked) {
+ current->set_indeterminate(p_column, false);
} else {
- current->set_checked(p_column, true);
+ current->set_checked(p_column, any_checked);
}
if (p_emit_signal) {
@@ -1921,7 +1922,8 @@ void Tree::update_column(int p_col) {
columns.write[p_col].text_buf->set_direction((TextServer::Direction)columns[p_col].text_direction);
}
- columns.write[p_col].text_buf->add_string(columns[p_col].title, theme_cache.font, theme_cache.font_size, columns[p_col].language);
+ columns.write[p_col].text_buf->add_string(columns[p_col].title, theme_cache.tb_font, theme_cache.tb_font_size, columns[p_col].language);
+ columns.write[p_col].cached_minimum_width_dirty = true;
}
void Tree::update_item_cell(TreeItem *p_item, int p_col) {
@@ -2014,7 +2016,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 *r_self_height) {
+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!
}
@@ -2096,11 +2098,12 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
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;
+ r_self_height = compute_item_height(p_item);
+ label_h = r_self_height + theme_cache.v_separation;
+
+ if (p_pos.y + label_h - theme_cache.offset.y < 0) {
+ continue; // No need to draw.
}
- 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;
@@ -2449,7 +2452,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
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_self_height);
+ child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c, child_self_height);
child_self_height += theme_cache.v_separation;
}
@@ -4105,7 +4108,7 @@ void Tree::update_scrollbars() {
}
int Tree::_get_title_button_height() const {
- ERR_FAIL_COND_V(theme_cache.font.is_null() || theme_cache.title_button.is_null(), 0);
+ ERR_FAIL_COND_V(theme_cache.tb_font.is_null() || theme_cache.title_button.is_null(), 0);
int h = 0;
if (show_column_titles) {
for (int i = 0; i < columns.size(); i++) {
@@ -4231,7 +4234,8 @@ void Tree::_notification(int p_what) {
cache.rtl = is_layout_rtl();
if (root && get_size().x > 0 && get_size().y > 0) {
- draw_item(Point2(), draw_ofs, draw_size, root);
+ int self_height = 0; // Just to pass a reference, we don't need the root's `self_height`.
+ draw_item(Point2(), draw_ofs, draw_size, root, self_height);
}
if (show_column_titles) {
@@ -4239,7 +4243,6 @@ void Tree::_notification(int p_what) {
int ofs2 = theme_cache.panel_style->get_margin(SIDE_LEFT);
for (int i = 0; i < columns.size(); i++) {
Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? theme_cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? theme_cache.title_button_hover : theme_cache.title_button);
- Ref<Font> f = theme_cache.tb_font;
Rect2 tbrect = Rect2(ofs2 - theme_cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
if (cache.rtl) {
tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
@@ -4249,6 +4252,7 @@ void Tree::_notification(int p_what) {
//text
int clip_w = tbrect.size.width - sb->get_minimum_size().width;
columns.write[i].text_buf->set_width(clip_w);
+ columns.write[i].cached_minimum_width_dirty = true;
Vector2 text_pos = Point2i(tbrect.position.x, tbrect.position.y + (tbrect.size.height - columns[i].text_buf->get_size().y) / 2);
switch (columns[i].title_alignment) {
@@ -4386,6 +4390,7 @@ void Tree::item_edited(int p_column, TreeItem *p_item, MouseButton p_custom_mous
void Tree::item_changed(int p_column, TreeItem *p_item) {
if (p_item != nullptr && p_column >= 0 && p_column < p_item->cells.size()) {
p_item->cells.write[p_column].dirty = true;
+ columns.write[p_column].cached_minimum_width_dirty = true;
}
queue_redraw();
}
@@ -4517,6 +4522,7 @@ void Tree::set_column_custom_minimum_width(int p_column, int p_min_width) {
return;
}
columns.write[p_column].custom_min_width = p_min_width;
+ columns.write[p_column].cached_minimum_width_dirty = true;
queue_redraw();
}
@@ -4528,6 +4534,7 @@ void Tree::set_column_expand(int p_column, bool p_expand) {
}
columns.write[p_column].expand = p_expand;
+ columns.write[p_column].cached_minimum_width_dirty = true;
queue_redraw();
}
@@ -4539,6 +4546,7 @@ void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
}
columns.write[p_column].expand_ratio = p_ratio;
+ columns.write[p_column].cached_minimum_width_dirty = true;
queue_redraw();
}
@@ -4550,6 +4558,7 @@ void Tree::set_column_clip_content(int p_column, bool p_fit) {
}
columns.write[p_column].clip_content = p_fit;
+ columns.write[p_column].cached_minimum_width_dirty = true;
queue_redraw();
}
@@ -4632,46 +4641,51 @@ TreeItem *Tree::get_next_selected(TreeItem *p_item) {
int Tree::get_column_minimum_width(int p_column) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- // Use the custom minimum width.
- int min_width = columns[p_column].custom_min_width;
+ if (columns[p_column].cached_minimum_width_dirty) {
+ // Use the custom minimum width.
+ int min_width = columns[p_column].custom_min_width;
- // Check if the visible title of the column is wider.
- if (show_column_titles) {
- min_width = MAX(theme_cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.panel_style->get_margin(SIDE_RIGHT), min_width);
- }
-
- if (!columns[p_column].clip_content) {
- int depth = 0;
- TreeItem *next;
- for (TreeItem *item = get_root(); item; item = next) {
- next = item->get_next_visible();
- // Compute the depth in tree.
- if (next && p_column == 0) {
- if (next->get_parent() == item) {
- depth += 1;
- } else {
- TreeItem *common_parent = item->get_parent();
- while (common_parent != next->get_parent() && common_parent) {
- common_parent = common_parent->get_parent();
- depth -= 1;
+ // Check if the visible title of the column is wider.
+ if (show_column_titles) {
+ min_width = MAX(theme_cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.panel_style->get_margin(SIDE_RIGHT), min_width);
+ }
+
+ if (!columns[p_column].clip_content) {
+ int depth = 0;
+ TreeItem *next;
+ for (TreeItem *item = get_root(); item; item = next) {
+ next = item->get_next_visible();
+ // Compute the depth in tree.
+ if (next && p_column == 0) {
+ if (next->get_parent() == item) {
+ depth += 1;
+ } else {
+ TreeItem *common_parent = item->get_parent();
+ while (common_parent != next->get_parent() && common_parent) {
+ common_parent = common_parent->get_parent();
+ depth -= 1;
+ }
}
}
- }
- // Get the item minimum size.
- Size2 item_size = item->get_minimum_size(p_column);
- if (p_column == 0) {
- item_size.width += theme_cache.item_margin * depth;
- } else {
- item_size.width += theme_cache.h_separation;
- }
+ // Get the item minimum size.
+ Size2 item_size = item->get_minimum_size(p_column);
+ if (p_column == 0) {
+ item_size.width += theme_cache.item_margin * depth;
+ } else {
+ item_size.width += theme_cache.h_separation;
+ }
- // Check if the item is wider.
- min_width = MAX(min_width, item_size.width);
+ // Check if the item is wider.
+ min_width = MAX(min_width, item_size.width);
+ }
}
+
+ columns.get(p_column).cached_minimum_width = min_width;
+ columns.get(p_column).cached_minimum_width_dirty = false;
}
- return min_width;
+ return columns[p_column].cached_minimum_width;
}
int Tree::get_column_width(int p_column) const {