summaryrefslogtreecommitdiff
path: root/scene/gui/tree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/tree.cpp')
-rw-r--r--scene/gui/tree.cpp404
1 files changed, 248 insertions, 156 deletions
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index aac15cd9a5..09db3205d9 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -99,39 +99,44 @@ void TreeItem::_change_tree(Tree *p_tree) {
c = c->next;
}
- if (tree && tree->root == this) {
- tree->root = nullptr;
- }
+ if (tree) {
+ if (tree->root == this) {
+ tree->root = nullptr;
+ }
- if (tree && tree->popup_edited_item == this) {
- tree->popup_edited_item = nullptr;
- tree->pressing_for_editor = false;
- }
+ if (tree->popup_edited_item == this) {
+ tree->popup_edited_item = nullptr;
+ tree->pressing_for_editor = false;
+ }
- if (tree && tree->cache.hover_item == this) {
- tree->cache.hover_item = nullptr;
- }
+ if (tree->cache.hover_item == this) {
+ tree->cache.hover_item = nullptr;
+ }
- if (tree && tree->selected_item == this) {
- tree->selected_item = nullptr;
- }
+ if (tree->selected_item == this) {
+ tree->selected_item = nullptr;
+ }
- if (tree && tree->drop_mode_over == this) {
- tree->drop_mode_over = nullptr;
- }
+ if (tree->drop_mode_over == this) {
+ tree->drop_mode_over = nullptr;
+ }
- if (tree && tree->single_select_defer == this) {
- tree->single_select_defer = nullptr;
- }
+ if (tree->single_select_defer == this) {
+ tree->single_select_defer = nullptr;
+ }
- if (tree && tree->edited_item == this) {
- tree->edited_item = nullptr;
- tree->pressing_for_editor = false;
+ if (tree->edited_item == this) {
+ tree->edited_item = nullptr;
+ tree->pressing_for_editor = false;
+ }
+
+ tree->update();
}
tree = p_tree;
if (tree) {
+ tree->update();
cells.resize(tree->columns.size());
}
}
@@ -411,7 +416,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
if (tree->select_mode == Tree::SELECT_MULTI) {
tree->selected_item = this;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
} else {
select(tree->selected_col);
}
@@ -421,7 +426,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
}
_changed_notify();
- tree->emit_signal("item_collapsed", this);
+ tree->emit_signal(SNAME("item_collapsed"), this);
}
bool TreeItem::is_collapsed() {
@@ -451,6 +456,7 @@ TreeItem *TreeItem::create_child(int p_idx) {
TreeItem *ti = memnew(TreeItem(tree));
if (tree) {
ti->cells.resize(tree->columns.size());
+ tree->update();
}
TreeItem *l_prev = nullptr;
@@ -654,11 +660,7 @@ void TreeItem::move_before(TreeItem *p_item) {
next = p_item;
p_item->prev = this;
- if (old_tree && old_tree != tree) {
- old_tree->update();
- }
-
- if (tree) {
+ if (tree && old_tree == tree) {
tree->update();
}
}
@@ -696,11 +698,7 @@ void TreeItem::move_after(TreeItem *p_item) {
parent->children_cache.append(this);
}
- if (old_tree && old_tree != tree) {
- old_tree->update();
- }
-
- if (tree) {
+ if (tree && old_tree == tree) {
tree->update();
}
}
@@ -975,6 +973,9 @@ Size2 TreeItem::get_minimum_size(int p_column) {
}
// Icon.
+ if (cell.mode == CELL_MODE_CHECK) {
+ size.width += tree->cache.checked->get_width() + tree->cache.hseparation;
+ }
if (cell.icon.is_valid()) {
Size2i icon_size = cell.get_icon_size();
if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
@@ -1214,59 +1215,62 @@ TreeItem::~TreeItem() {
/**********************************************/
void Tree::update_cache() {
- cache.font = get_theme_font("font");
- cache.font_size = get_theme_font_size("font_size");
- cache.tb_font = get_theme_font("title_button_font");
- cache.tb_font_size = get_theme_font_size("title_button_font_size");
- cache.bg = get_theme_stylebox("bg");
- cache.selected = get_theme_stylebox("selected");
- cache.selected_focus = get_theme_stylebox("selected_focus");
- cache.cursor = get_theme_stylebox("cursor");
- cache.cursor_unfocus = get_theme_stylebox("cursor_unfocused");
- cache.button_pressed = get_theme_stylebox("button_pressed");
-
- cache.checked = get_theme_icon("checked");
- cache.unchecked = get_theme_icon("unchecked");
+ cache.font = get_theme_font(SNAME("font"));
+ cache.font_size = get_theme_font_size(SNAME("font_size"));
+ cache.tb_font = get_theme_font(SNAME("title_button_font"));
+ cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
+ cache.bg = get_theme_stylebox(SNAME("bg"));
+ cache.selected = get_theme_stylebox(SNAME("selected"));
+ cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
+ cache.cursor = get_theme_stylebox(SNAME("cursor"));
+ cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
+ cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
+
+ cache.checked = get_theme_icon(SNAME("checked"));
+ cache.unchecked = get_theme_icon(SNAME("unchecked"));
if (is_layout_rtl()) {
- cache.arrow_collapsed = get_theme_icon("arrow_collapsed_mirrored");
+ cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
} else {
- cache.arrow_collapsed = get_theme_icon("arrow_collapsed");
- }
- cache.arrow = get_theme_icon("arrow");
- cache.select_arrow = get_theme_icon("select_arrow");
- cache.updown = get_theme_icon("updown");
-
- cache.custom_button = get_theme_stylebox("custom_button");
- cache.custom_button_hover = get_theme_stylebox("custom_button_hover");
- cache.custom_button_pressed = get_theme_stylebox("custom_button_pressed");
- cache.custom_button_font_highlight = get_theme_color("custom_button_font_highlight");
-
- cache.font_color = get_theme_color("font_color");
- cache.font_selected_color = get_theme_color("font_selected_color");
- cache.drop_position_color = get_theme_color("drop_position_color");
- cache.hseparation = get_theme_constant("hseparation");
- cache.vseparation = get_theme_constant("vseparation");
- cache.item_margin = get_theme_constant("item_margin");
- cache.button_margin = get_theme_constant("button_margin");
-
- cache.draw_guides = get_theme_constant("draw_guides");
- cache.guide_color = get_theme_color("guide_color");
- cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
- cache.relationship_line_width = get_theme_constant("relationship_line_width");
- cache.parent_hl_line_width = get_theme_constant("parent_hl_line_width");
- cache.children_hl_line_width = get_theme_constant("children_hl_line_width");
- cache.parent_hl_line_margin = get_theme_constant("parent_hl_line_margin");
- cache.relationship_line_color = get_theme_color("relationship_line_color");
- cache.parent_hl_line_color = get_theme_color("parent_hl_line_color");
- cache.children_hl_line_color = get_theme_color("children_hl_line_color");
-
- cache.scroll_border = get_theme_constant("scroll_border");
- cache.scroll_speed = get_theme_constant("scroll_speed");
-
- cache.title_button = get_theme_stylebox("title_button_normal");
- cache.title_button_pressed = get_theme_stylebox("title_button_pressed");
- cache.title_button_hover = get_theme_stylebox("title_button_hover");
- cache.title_button_color = get_theme_color("title_button_color");
+ cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
+ }
+ cache.arrow = get_theme_icon(SNAME("arrow"));
+ cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
+ cache.updown = get_theme_icon(SNAME("updown"));
+
+ cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
+ cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
+ cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
+ cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
+
+ cache.font_color = get_theme_color(SNAME("font_color"));
+ cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
+ cache.hseparation = get_theme_constant(SNAME("hseparation"));
+ cache.vseparation = get_theme_constant(SNAME("vseparation"));
+ cache.item_margin = get_theme_constant(SNAME("item_margin"));
+ cache.button_margin = get_theme_constant(SNAME("button_margin"));
+
+ cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+
+ cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
+ cache.guide_color = get_theme_color(SNAME("guide_color"));
+ cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
+ cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
+ cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
+ cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
+ cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
+ cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
+ cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
+ cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
+
+ cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
+ cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
+
+ cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
+ cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
+ cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
+ cache.title_button_color = get_theme_color(SNAME("title_button_color"));
v_scroll->set_custom_step(cache.font->get_height(cache.font_size));
}
@@ -1510,7 +1514,7 @@ 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);
- bool rtl = is_layout_rtl();
+ bool rtl = cache.rtl;
/* Calculate height of the label part */
label_h += cache.vseparation;
@@ -1556,6 +1560,20 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
+ if (!rtl && p_item->cells[i].buttons.size()) {
+ int button_w = 0;
+ for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
+ button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ }
+
+ int total_ofs = ofs - cache.offset.x;
+
+ if (total_ofs + w > p_draw_size.width) {
+ w = MAX(button_w, p_draw_size.width - total_ofs);
+ }
+ }
+
int bw = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
@@ -1680,8 +1698,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_selected_color" : "font_color");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = cache.font_outline_color;
+ int outline_size = cache.font_outline_size;
Color icon_col = p_item->cells[i].icon_color;
if (p_item->cells[i].dirty) {
@@ -2057,7 +2075,7 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c
selected_item = p_selected;
selected_col = 0;
if (!emitted_row) {
- emit_signal("item_selected");
+ emit_signal(SNAME("item_selected"));
emitted_row = true;
}
/*
@@ -2077,28 +2095,28 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c
selected_item = p_selected;
selected_col = i;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
if (select_mode == SELECT_MULTI) {
- emit_signal("multi_selected", p_current, i, true);
+ emit_signal(SNAME("multi_selected"), p_current, i, true);
} else if (select_mode == SELECT_SINGLE) {
- emit_signal("item_selected");
+ emit_signal(SNAME("item_selected"));
}
} else if (select_mode == SELECT_MULTI && (selected_item != p_selected || selected_col != i)) {
selected_item = p_selected;
selected_col = i;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
}
} else {
if (r_in_range && *r_in_range && !p_force_deselect) {
if (!c.selected && c.selectable) {
c.selected = true;
- emit_signal("multi_selected", p_current, i, true);
+ emit_signal(SNAME("multi_selected"), p_current, i, true);
}
} else if (!r_in_range || p_force_deselect) {
if (select_mode == SELECT_MULTI && c.selected) {
- emit_signal("multi_selected", p_current, i, false);
+ emit_signal(SNAME("multi_selected"), p_current, i, false);
}
c.selected = false;
}
@@ -2135,13 +2153,24 @@ void Tree::_range_click_timeout() {
}
}
+ if (!root) {
+ return;
+ }
+
click_handled = false;
Ref<InputEventMouseButton> mb;
mb.instantiate();
+ int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ if (h_scroll->is_visible()) {
+ x_limit -= h_scroll->get_minimum_size().width;
+ }
+
+ cache.rtl = is_layout_rtl();
+
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, false, root, MOUSE_BUTTON_LEFT, mb);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MOUSE_BUTTON_LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -2155,7 +2184,7 @@ void Tree::_range_click_timeout() {
}
if (propagate_mouse_activated) {
- emit_signal("item_activated");
+ emit_signal(SNAME("item_activated"));
propagate_mouse_activated = false;
}
@@ -2164,7 +2193,7 @@ void Tree::_range_click_timeout() {
}
}
-int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
+int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
int item_h = compute_item_height(p_item) + cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -2189,6 +2218,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
int col = -1;
int col_ofs = 0;
int col_width = 0;
+
+ int limit_w = x_limit;
+
for (int i = 0; i < columns.size(); i++) {
col_width = get_column_width(i);
@@ -2204,6 +2236,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (x > col_width) {
col_ofs += col_width;
x -= col_width;
+ limit_w -= col_width;
continue;
}
@@ -2217,10 +2250,12 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
int margin = x_ofs + cache.item_margin; //-cache.hseparation;
//int lm = cache.bg->get_margin(SIDE_LEFT);
col_width -= margin;
+ limit_w -= margin;
col_ofs += margin;
x -= margin;
} else {
col_width -= cache.hseparation;
+ limit_w -= cache.hseparation;
x -= cache.hseparation;
}
@@ -2234,6 +2269,16 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
bool already_selected = c.selected;
bool already_cursor = (p_item == selected_item) && col == selected_col;
+ if (!cache.rtl && p_item->cells[col].buttons.size()) {
+ int button_w = 0;
+ for (int j = p_item->cells[col].buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = p_item->cells[col].buttons[j].texture;
+ button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ }
+
+ col_width = MAX(button_w, MIN(limit_w, col_width));
+ }
+
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
int w = b->get_size().width + cache.button_pressed->get_minimum_size().width;
@@ -2252,9 +2297,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
cache.click_column = col;
cache.click_pos = get_global_mouse_position() - get_global_position();
update();
- //emit_signal("button_pressed");
+ //emit_signal(SNAME("button_pressed"));
return -1;
}
+
col_width -= w + cache.button_margin;
}
@@ -2272,15 +2318,15 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) {
if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) {
p_item->select(col);
- emit_signal("multi_selected", p_item, col, true);
+ emit_signal(SNAME("multi_selected"), p_item, col, true);
if (p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
//p_item->selected_signal.call(col);
} else {
p_item->deselect(col);
- emit_signal("multi_selected", p_item, col, false);
+ emit_signal(SNAME("multi_selected"), p_item, col, false);
//p_item->deselected_signal.call(col);
}
@@ -2291,7 +2337,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
select_single_item(p_item, root, col, selected_item, &inrange);
if (p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
} else {
int icount = _count_selected_items(root);
@@ -2305,14 +2351,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
}
}
/*
if (!c.selected && select_mode==SELECT_MULTI) {
- emit_signal("multi_selected",p_item,col,true);
+ emit_signal(SNAME("multi_selected"),p_item,col,true);
}
*/
update();
@@ -2426,7 +2472,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - cache.offset.y), Size2(get_column_width(col), item_h));
if (on_arrow || !p_item->cells[col].custom_button) {
- emit_signal("custom_popup_edited", ((bool)(x >= (col_width - item_h / 2))));
+ emit_signal(SNAME("custom_popup_edited"), ((bool)(x >= (col_width - item_h / 2))));
}
if (!p_item->cells[col].custom_button || !on_arrow) {
@@ -2465,7 +2511,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
TreeItem *c = p_item->first_child;
while (c) {
- int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_double_click, c, p_button, p_mod);
+ int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, x_limit, p_double_click, c, p_button, p_mod);
if (child_h < 0) {
return -1; // break, stop propagating, no need to anymore
@@ -2478,7 +2524,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
}
if (p_item == root && p_button == MOUSE_BUTTON_RIGHT) {
- emit_signal("empty_rmb", get_local_mouse_position());
+ emit_signal(SNAME("empty_rmb"), get_local_mouse_position());
}
}
@@ -2584,7 +2630,7 @@ void Tree::_go_left() {
} else {
if (select_mode == SELECT_MULTI) {
selected_col--;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
} else {
selected_item->select(selected_col - 1);
}
@@ -2605,7 +2651,7 @@ void Tree::_go_right() {
} else {
if (select_mode == SELECT_MULTI) {
selected_col++;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
} else {
selected_item->select(selected_col + 1);
}
@@ -2638,7 +2684,7 @@ void Tree::_go_up() {
return;
}
selected_item = prev;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
int col = selected_col < 0 ? 0 : selected_col;
@@ -2681,7 +2727,7 @@ void Tree::_go_down() {
}
selected_item = next;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
int col = selected_col < 0 ? 0 : selected_col;
@@ -2782,7 +2828,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (select_mode == SELECT_MULTI) {
selected_item = next;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
while (next && !next->cells[selected_col].selectable) {
@@ -2820,7 +2866,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (select_mode == SELECT_MULTI) {
selected_item = prev;
- emit_signal("cell_selected");
+ emit_signal(SNAME("cell_selected"));
update();
} else {
while (prev && !prev->cells[selected_col].selectable) {
@@ -2836,7 +2882,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (selected_item) {
//bring up editor if possible
if (!edit_selected()) {
- emit_signal("item_activated");
+ emit_signal(SNAME("item_activated"));
incr_search.clear();
}
}
@@ -2848,10 +2894,10 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (selected_item->is_selected(selected_col)) {
selected_item->deselect(selected_col);
- emit_signal("multi_selected", selected_item, selected_col, false);
+ emit_signal(SNAME("multi_selected"), selected_item, selected_col, false);
} else if (selected_item->is_selectable(selected_col)) {
selected_item->select(selected_col);
- emit_signal("multi_selected", selected_item, selected_col, true);
+ emit_signal(SNAME("multi_selected"), selected_item, selected_col, true);
}
}
accept_event();
@@ -3035,7 +3081,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
if (pos.x < len) {
- emit_signal("column_title_pressed", i);
+ emit_signal(SNAME("column_title_pressed"), i);
break;
}
}
@@ -3062,10 +3108,10 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (rect.has_point(mpos)) {
if (!edit_selected()) {
- emit_signal("item_double_clicked");
+ emit_signal(SNAME("item_double_clicked"));
}
} else {
- emit_signal("item_double_clicked");
+ emit_signal(SNAME("item_double_clicked"));
}
}
pressing_for_editor = false;
@@ -3074,7 +3120,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item != nullptr) {
// make sure in case of wrong reference after reconstructing whole TreeItems
cache.click_item = get_item_at_position(cache.click_pos);
- emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id);
+ emit_signal(SNAME("button_pressed"), cache.click_item, cache.click_column, cache.click_id);
}
cache.click_type = Cache::CLICK_NONE;
cache.click_index = -1;
@@ -3134,7 +3180,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (!root || (!root->get_first_child() && hide_root)) {
if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) {
- emit_signal("empty_tree_rmb_selected", get_local_mouse_position());
+ emit_signal(SNAME("empty_tree_rmb_selected"), get_local_mouse_position());
}
break;
}
@@ -3143,8 +3189,14 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
pressing_for_editor = false;
propagate_mouse_activated = false;
+ int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ if (h_scroll->is_visible()) {
+ x_limit -= h_scroll->get_minimum_size().width;
+ }
+
+ cache.rtl = is_layout_rtl();
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, b->is_double_click(), root, b->get_button_index(), b);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, b->is_double_click(), root, b->get_button_index(), b);
blocked--;
if (pressing_for_editor) {
@@ -3179,13 +3231,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) {
- emit_signal("nothing_selected");
+ emit_signal(SNAME("nothing_selected"));
}
}
}
if (propagate_mouse_activated) {
- emit_signal("item_activated");
+ emit_signal(SNAME("item_activated"));
propagate_mouse_activated = false;
}
@@ -3254,7 +3306,7 @@ bool Tree::edit_selected() {
edited_item = s;
edited_col = col;
custom_popup_rect = Rect2i(get_global_position() + rect.position, rect.size);
- emit_signal("custom_popup_edited", false);
+ emit_signal(SNAME("custom_popup_edited"), false);
item_edited(col, s);
return true;
@@ -3490,12 +3542,15 @@ void Tree::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> bg = cache.bg;
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ int outline_size = get_theme_constant(SNAME("outline_size"));
Point2 draw_ofs;
draw_ofs += bg->get_offset();
Size2 draw_size = get_size() - bg->get_minimum_size();
+ if (h_scroll->is_visible()) {
+ draw_size.width -= h_scroll->get_minimum_size().width;
+ }
bg->draw(ci, Rect2(Point2(), get_size()));
@@ -3504,6 +3559,8 @@ void Tree::_notification(int p_what) {
draw_ofs.y += tbh;
draw_size.y -= tbh;
+ cache.rtl = is_layout_rtl();
+
if (root && get_size().x > 0 && get_size().y > 0) {
draw_item(Point2(), draw_ofs, draw_size, root);
}
@@ -3515,7 +3572,7 @@ void Tree::_notification(int p_what) {
Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button);
Ref<Font> f = cache.tb_font;
Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
- if (is_layout_rtl()) {
+ if (cache.rtl) {
tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
}
sb->draw(ci, tbrect);
@@ -3536,7 +3593,7 @@ void Tree::_notification(int p_what) {
// Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- const Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus");
+ const Ref<StyleBox> bg_focus = get_theme_stylebox(SNAME("bg_focus"));
bg_focus->draw(ci, Rect2(Point2(), get_size()));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
@@ -3637,9 +3694,9 @@ void Tree::item_edited(int p_column, TreeItem *p_item, bool p_lmb) {
edited_item->cells.write[p_column].dirty = true;
}
if (p_lmb) {
- emit_signal("item_edited");
+ emit_signal(SNAME("item_edited"));
} else {
- emit_signal("item_rmb_edited");
+ emit_signal(SNAME("item_rmb_edited"));
}
}
@@ -3657,7 +3714,7 @@ void Tree::item_selected(int p_column, TreeItem *p_item) {
}
p_item->cells.write[p_column].selected = true;
- //emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select
+ //emit_signal(SNAME("multi_selected"),p_item,p_column,true); - NO this is for TreeItem::select
selected_col = p_column;
if (!selected_item) {
@@ -3761,6 +3818,36 @@ void Tree::set_column_expand(int p_column, bool p_expand) {
update();
}
+void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+ columns.write[p_column].expand_ratio = p_ratio;
+ update();
+}
+
+void Tree::set_column_clip_content(int p_column, bool p_fit) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+
+ columns.write[p_column].clip_content = p_fit;
+ update();
+}
+
+bool Tree::is_column_expanding(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), false);
+
+ return columns[p_column].expand;
+}
+int Tree::get_column_expand_ratio(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), 1);
+
+ return columns[p_column].expand_ratio;
+}
+
+bool Tree::is_column_clipping_content(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), false);
+
+ return columns[p_column].clip_content;
+}
+
TreeItem *Tree::get_selected() const {
return selected_item;
}
@@ -3820,11 +3907,14 @@ 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);
- if (columns[p_column].custom_min_width != 0) {
- return columns[p_column].custom_min_width;
- } else {
+ int min_width = columns[p_column].custom_min_width;
+
+ if (show_column_titles) {
+ min_width = MAX(cache.font->get_string_size(columns[p_column].title).width, min_width);
+ }
+
+ if (!columns[p_column].clip_content) {
int depth = 0;
- int min_width = 0;
TreeItem *next;
for (TreeItem *item = get_root(); item; item = next) {
next = item->get_next_visible();
@@ -3848,13 +3938,16 @@ int Tree::get_column_minimum_width(int p_column) const {
}
min_width = MAX(min_width, item_size.width);
}
- return min_width;
}
+
+ return min_width;
}
int Tree::get_column_width(int p_column) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
+ int column_width = get_column_minimum_width(p_column);
+
if (columns[p_column].expand) {
int expand_area = get_size().width;
@@ -3868,31 +3961,24 @@ int Tree::get_column_width(int p_column) const {
expand_area -= v_scroll->get_combined_minimum_size().width;
}
- int expanding_columns = 0;
int expanding_total = 0;
for (int i = 0; i < columns.size(); i++) {
- if (!columns[i].expand) {
- expand_area -= get_column_minimum_width(i);
- } else {
- expanding_total += get_column_minimum_width(i);
- expanding_columns++;
+ expand_area -= get_column_minimum_width(i);
+ if (columns[i].expand) {
+ expanding_total += columns[i].expand_ratio;
}
}
- if (expand_area < expanding_total) {
- return get_column_minimum_width(p_column);
+ if (expand_area >= expanding_total && expanding_total > 0) {
+ column_width += expand_area * columns[p_column].expand_ratio / expanding_total;
}
+ }
- ERR_FAIL_COND_V(expanding_columns == 0, -1); // shouldn't happen
- if (expanding_total == 0) {
- return 0;
- } else {
- return expand_area * get_column_minimum_width(p_column) / expanding_total;
- }
- } else {
- return get_column_minimum_width(p_column);
+ if (p_column < columns.size() - 1) {
+ column_width += cache.hseparation;
}
+ return column_width;
}
void Tree::propagate_set_columns(TreeItem *p_item) {
@@ -3989,7 +4075,7 @@ void Tree::ensure_cursor_is_visible() {
if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
v_scroll->set_value(y_offset);
} else if (y_offset + cell_h > v_scroll->get_value() + screen_h) {
- v_scroll->call_deferred("set_value", y_offset - screen_h + cell_h);
+ v_scroll->call_deferred(SNAME("set_value"), y_offset - screen_h + cell_h);
} else if (y_offset < v_scroll->get_value()) {
v_scroll->set_value(y_offset);
}
@@ -4007,7 +4093,7 @@ void Tree::ensure_cursor_is_visible() {
if (cell_w > screen_w) {
h_scroll->set_value(x_offset);
} else if (x_offset + cell_w > h_scroll->get_value() + screen_w) {
- h_scroll->call_deferred("set_value", x_offset - screen_w + cell_w);
+ h_scroll->call_deferred(SNAME("set_value"), x_offset - screen_w + cell_w);
} else if (x_offset < h_scroll->get_value()) {
h_scroll->set_value(x_offset);
}
@@ -4549,6 +4635,12 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root);
ClassDB::bind_method(D_METHOD("set_column_custom_minimum_width", "column", "min_width"), &Tree::set_column_custom_minimum_width);
ClassDB::bind_method(D_METHOD("set_column_expand", "column", "expand"), &Tree::set_column_expand);
+ ClassDB::bind_method(D_METHOD("set_column_expand_ratio", "column", "ratio"), &Tree::set_column_expand_ratio);
+ ClassDB::bind_method(D_METHOD("set_column_clip_content", "column", "enable"), &Tree::set_column_clip_content);
+ ClassDB::bind_method(D_METHOD("is_column_expanding", "column"), &Tree::is_column_expanding);
+ ClassDB::bind_method(D_METHOD("is_column_clipping_content", "column"), &Tree::is_column_clipping_content);
+ ClassDB::bind_method(D_METHOD("get_column_expand_ratio", "column"), &Tree::get_column_expand_ratio);
+
ClassDB::bind_method(D_METHOD("get_column_width", "column"), &Tree::get_column_width);
ClassDB::bind_method(D_METHOD("set_hide_root", "enable"), &Tree::set_hide_root);