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.cpp599
1 files changed, 344 insertions, 255 deletions
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 1245a37c4d..ff8d2b88b1 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,10 +37,9 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
+#include "scene/gui/box_container.h"
#include "scene/main/window.h"
-#include "box_container.h"
-
#include <limits.h>
Size2 TreeItem::Cell::get_icon_size() const {
@@ -198,6 +197,65 @@ bool TreeItem::is_indeterminate(int p_column) const {
return cells[p_column].indeterminate;
}
+void TreeItem::propagate_check(int p_column, bool p_emit_signal) {
+ bool ch = cells[p_column].checked;
+
+ if (p_emit_signal) {
+ tree->emit_signal(SNAME("check_propagated_to_item"), this, p_column);
+ }
+ _propagate_check_through_children(p_column, ch, p_emit_signal);
+ _propagate_check_through_parents(p_column, p_emit_signal);
+}
+
+void TreeItem::_propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal) {
+ TreeItem *current = get_first_child();
+ while (current) {
+ current->set_checked(p_column, p_checked);
+ if (p_emit_signal) {
+ current->tree->emit_signal(SNAME("check_propagated_to_item"), current, p_column);
+ }
+ current->_propagate_check_through_children(p_column, p_checked, p_emit_signal);
+ current = current->get_next();
+ }
+}
+
+void TreeItem::_propagate_check_through_parents(int p_column, bool p_emit_signal) {
+ TreeItem *current = get_parent();
+ if (!current) {
+ return;
+ }
+
+ bool all_unchecked_and_not_indeterminate = true;
+ bool any_unchecked_or_indeterminate = false;
+
+ TreeItem *child_item = current->get_first_child();
+ while (child_item) {
+ if (!child_item->is_checked(p_column)) {
+ any_unchecked_or_indeterminate = true;
+ if (child_item->is_indeterminate(p_column)) {
+ all_unchecked_and_not_indeterminate = false;
+ break;
+ }
+ } else {
+ all_unchecked_and_not_indeterminate = false;
+ }
+ child_item = child_item->get_next();
+ }
+
+ if (all_unchecked_and_not_indeterminate) {
+ current->set_checked(p_column, false);
+ } else if (any_unchecked_or_indeterminate) {
+ current->set_indeterminate(p_column, true);
+ } else {
+ current->set_checked(p_column, true);
+ }
+
+ if (p_emit_signal) {
+ current->tree->emit_signal(SNAME("check_propagated_to_item"), current, p_column);
+ }
+ current->_propagate_check_through_parents(p_column, p_emit_signal);
+}
+
void TreeItem::set_text(int p_column, String p_text) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].text = p_text;
@@ -496,8 +554,9 @@ void TreeItem::uncollapse_tree() {
void TreeItem::set_custom_minimum_height(int p_height) {
custom_min_height = p_height;
- for (Cell &c : cells)
+ for (Cell &c : cells) {
c.cached_minimum_size_dirty = true;
+ }
_changed_notify();
}
@@ -845,10 +904,16 @@ String TreeItem::get_button_tooltip(int p_column, int p_idx) const {
return cells[p_column].buttons[p_idx].tooltip;
}
+int TreeItem::get_button_id(int p_column, int p_idx) const {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), -1);
+ ERR_FAIL_INDEX_V(p_idx, cells[p_column].buttons.size(), -1);
+ return cells[p_column].buttons[p_idx].id;
+}
+
void TreeItem::erase_button(int p_column, int p_idx) {
ERR_FAIL_INDEX(p_column, cells.size());
ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
- cells.write[p_column].buttons.remove(p_idx);
+ cells.write[p_column].buttons.remove_at(p_idx);
_changed_notify(p_column);
}
@@ -1002,18 +1067,18 @@ bool TreeItem::is_custom_set_as_button(int p_column) const {
return cells[p_column].custom_button;
}
-void TreeItem::set_text_align(int p_column, TextAlign p_align) {
+void TreeItem::set_text_alignment(int p_column, HorizontalAlignment p_alignment) {
ERR_FAIL_INDEX(p_column, cells.size());
- cells.write[p_column].text_align = p_align;
+ cells.write[p_column].text_alignment = p_alignment;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
-TreeItem::TextAlign TreeItem::get_text_align(int p_column) const {
- ERR_FAIL_INDEX_V(p_column, cells.size(), ALIGN_LEFT);
- return cells[p_column].text_align;
+HorizontalAlignment TreeItem::get_text_alignment(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), HORIZONTAL_ALIGNMENT_LEFT);
+ return cells[p_column].text_alignment;
}
void TreeItem::set_expand_right(int p_column, bool p_enable) {
@@ -1033,8 +1098,9 @@ bool TreeItem::get_expand_right(int p_column) const {
void TreeItem::set_disable_folding(bool p_disable) {
disable_folding = p_disable;
- for (Cell &c : cells)
+ for (Cell &c : cells) {
c.cached_minimum_size_dirty = true;
+ }
_changed_notify(0);
}
@@ -1120,7 +1186,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari
if (!p_item) {
return;
}
- p_item->call(p_method, p_args, p_argcount, r_error);
+ p_item->callp(p_method, p_args, p_argcount, r_error);
TreeItem *c = p_item->get_first_child();
while (c) {
recursive_call_aux(c, p_method, p_args, p_argcount, r_error);
@@ -1141,6 +1207,8 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_checked", "column"), &TreeItem::is_checked);
ClassDB::bind_method(D_METHOD("is_indeterminate", "column"), &TreeItem::is_indeterminate);
+ ClassDB::bind_method(D_METHOD("propagate_check", "column", "emit_signal"), &TreeItem::propagate_check, DEFVAL(true));
+
ClassDB::bind_method(D_METHOD("set_text", "column", "text"), &TreeItem::set_text);
ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text);
@@ -1220,9 +1288,11 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_as_button", "column", "enable"), &TreeItem::set_custom_as_button);
ClassDB::bind_method(D_METHOD("is_custom_set_as_button", "column"), &TreeItem::is_custom_set_as_button);
- ClassDB::bind_method(D_METHOD("add_button", "column", "button", "button_idx", "disabled", "tooltip"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false), DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_button", "column", "button", "id", "disabled", "tooltip"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false), DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_button_count", "column"), &TreeItem::get_button_count);
ClassDB::bind_method(D_METHOD("get_button_tooltip", "column", "button_idx"), &TreeItem::get_button_tooltip);
+ ClassDB::bind_method(D_METHOD("get_button_id", "column", "button_idx"), &TreeItem::get_button_id);
+ ClassDB::bind_method(D_METHOD("get_button_by_id", "column", "id"), &TreeItem::get_button_by_id);
ClassDB::bind_method(D_METHOD("get_button", "column", "button_idx"), &TreeItem::get_button);
ClassDB::bind_method(D_METHOD("set_button", "column", "button_idx", "button"), &TreeItem::set_button);
ClassDB::bind_method(D_METHOD("erase_button", "column", "button_idx"), &TreeItem::erase_button);
@@ -1231,8 +1301,8 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tooltip", "column", "tooltip"), &TreeItem::set_tooltip);
ClassDB::bind_method(D_METHOD("get_tooltip", "column"), &TreeItem::get_tooltip);
- ClassDB::bind_method(D_METHOD("set_text_align", "column", "text_align"), &TreeItem::set_text_align);
- ClassDB::bind_method(D_METHOD("get_text_align", "column"), &TreeItem::get_text_align);
+ ClassDB::bind_method(D_METHOD("set_text_alignment", "column", "text_alignment"), &TreeItem::set_text_alignment);
+ ClassDB::bind_method(D_METHOD("get_text_alignment", "column"), &TreeItem::get_text_alignment);
ClassDB::bind_method(D_METHOD("set_expand_right", "column", "enable"), &TreeItem::set_expand_right);
ClassDB::bind_method(D_METHOD("get_expand_right", "column"), &TreeItem::get_expand_right);
@@ -1256,10 +1326,10 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
ClassDB::bind_method(D_METHOD("get_index"), &TreeItem::get_index);
- ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::_move_before);
- ClassDB::bind_method(D_METHOD("move_after", "item"), &TreeItem::_move_after);
+ ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::move_before);
+ ClassDB::bind_method(D_METHOD("move_after", "item"), &TreeItem::move_after);
- ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
+ ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::remove_child);
{
MethodInfo mi;
@@ -1278,10 +1348,6 @@ void TreeItem::_bind_methods() {
BIND_ENUM_CONSTANT(CELL_MODE_RANGE);
BIND_ENUM_CONSTANT(CELL_MODE_ICON);
BIND_ENUM_CONSTANT(CELL_MODE_CUSTOM);
-
- BIND_ENUM_CONSTANT(ALIGN_LEFT);
- BIND_ENUM_CONSTANT(ALIGN_CENTER);
- BIND_ENUM_CONSTANT(ALIGN_RIGHT);
}
void TreeItem::clear_children() {
@@ -1477,16 +1543,17 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
}
w += ts.width;
- switch (p_cell.text_align) {
- case TreeItem::ALIGN_LEFT:
+ switch (p_cell.text_alignment) {
+ case HORIZONTAL_ALIGNMENT_FILL:
+ case HORIZONTAL_ALIGNMENT_LEFT: {
if (rtl) {
rect.position.x += MAX(0, (rect.size.width - w));
}
- break;
- case TreeItem::ALIGN_CENTER:
+ } break;
+ case HORIZONTAL_ALIGNMENT_CENTER:
rect.position.x += MAX(0, (rect.size.width - w) / 2);
break;
- case TreeItem::ALIGN_RIGHT:
+ case HORIZONTAL_ALIGNMENT_RIGHT:
if (!rtl) {
rect.position.x += MAX(0, (rect.size.width - w));
}
@@ -1539,7 +1606,7 @@ 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, cache.font, cache.font_size, columns[p_col].opentype_features, (columns[p_col].language != "") ? columns[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
+ columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].opentype_features, !columns[p_col].language.is_empty() ? columns[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
}
void Tree::update_item_cell(TreeItem *p_item, int p_col) {
@@ -1547,7 +1614,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
p_item->cells.write[p_col].text_buf->clear();
if (p_item->cells[p_col].mode == TreeItem::CELL_MODE_RANGE) {
- if (p_item->cells[p_col].text != "") {
+ if (!p_item->cells[p_col].text.is_empty()) {
if (!p_item->cells[p_col].editable) {
return;
}
@@ -1574,7 +1641,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
valtext = p_item->cells[p_col].text;
}
- if (p_item->cells[p_col].suffix != String()) {
+ if (!p_item->cells[p_col].suffix.is_empty()) {
valtext += " " + p_item->cells[p_col].suffix;
}
@@ -1597,7 +1664,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
} else {
font_size = cache.font_size;
}
- p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].opentype_features, (p_item->cells[p_col].language != "") ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
+ p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].opentype_features, !p_item->cells[p_col].language.is_empty() ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
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;
}
@@ -1634,8 +1701,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
bool skip = (p_item == root && hide_root);
if (!skip && (p_pos.y + label_h - cache.offset.y) > 0) {
- //draw separation.
- //if (p_item->get_parent()!=root || !hide_root)
+ // Draw separation.
ERR_FAIL_COND_V(cache.font.is_null(), -1);
@@ -1663,7 +1729,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].expand_right) {
int plus = 1;
- while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text == "" && p_item->cells[i + plus].icon.is_null()) {
+ while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text.is_empty() && p_item->cells[i + plus].icon.is_null()) {
w += get_column_width(i + plus);
plus++;
skip2++;
@@ -1860,7 +1926,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
} break;
case TreeItem::CELL_MODE_RANGE: {
- if (p_item->cells[i].text != "") {
+ if (!p_item->cells[i].text.is_empty()) {
if (!p_item->cells[i].editable) {
break;
}
@@ -1955,7 +2021,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].custom_button) {
if (cache.hover_item == p_item && cache.hover_cell == i) {
- if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) {
+ if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
draw_style_box(cache.custom_button_pressed, ir);
} else {
draw_style_box(cache.custom_button_hover, ir);
@@ -2192,14 +2258,11 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c
emit_signal(SNAME("item_selected"));
emitted_row = true;
}
- /*
- if (p_col==i)
- p_current->selected_signal.call(p_col);
- */
-
} else if (c.selected) {
- c.selected = false;
- //p_current->deselected_signal.call(p_col);
+ if (p_selected != p_current) {
+ // Deselect other rows.
+ c.selected = false;
+ }
}
} else if (select_mode == SELECT_SINGLE || select_mode == SELECT_MULTI) {
if (!r_in_range && &selected_cell == &c) {
@@ -2256,7 +2319,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
}
void Tree::_range_click_timeout() {
- if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) {
+ if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
@@ -2284,7 +2347,7 @@ void Tree::_range_click_timeout() {
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, x_limit + cache.offset.width, false, root, MOUSE_BUTTON_LEFT, mb);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MouseButton::LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -2307,7 +2370,7 @@ void Tree::_range_click_timeout() {
}
}
-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 Tree::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 item_h = compute_item_height(p_item) + cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -2319,12 +2382,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return -1;
}
- if (!p_item->disable_folding && !hide_folding && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) {
- if (p_item->first_child) {
- p_item->set_collapsed(!p_item->is_collapsed());
- }
-
- return -1; //handled!
+ if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) {
+ p_item->set_collapsed(!p_item->is_collapsed());
+ return -1;
}
int x = p_pos.x;
@@ -2340,7 +2400,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (p_item->cells[i].expand_right) {
int plus = 1;
- while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text == "" && p_item->cells[i + plus].icon.is_null()) {
+ while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text.is_empty() && p_item->cells[i + plus].icon.is_null()) {
col_width += cache.hseparation;
col_width += get_column_width(i + plus);
plus++;
@@ -2427,11 +2487,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
col_width -= w + cache.button_margin;
}
- if (p_button == MOUSE_BUTTON_LEFT || (p_button == MOUSE_BUTTON_RIGHT && allow_rmb_select)) {
+ if (p_button == MouseButton::LEFT || (p_button == MouseButton::RIGHT && allow_rmb_select)) {
/* process selection */
if (p_double_click && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check
-
+ // Emits the "item_activated" signal.
propagate_mouse_activated = true;
incr_search.clear();
@@ -2439,10 +2499,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) {
- if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) {
+ if (!c.selected || p_button == MouseButton::RIGHT) {
p_item->select(col);
emit_signal(SNAME("multi_selected"), p_item, col, true);
- if (p_button == MOUSE_BUTTON_RIGHT) {
+ if (p_button == MouseButton::RIGHT) {
emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
@@ -2459,21 +2519,21 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
bool inrange = false;
select_single_item(p_item, root, col, selected_item, &inrange);
- if (p_button == MOUSE_BUTTON_RIGHT) {
+ if (p_button == MouseButton::RIGHT) {
emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
} else {
int icount = _count_selected_items(root);
- if (select_mode == SELECT_MULTI && icount > 1 && p_button != MOUSE_BUTTON_RIGHT) {
+ if (select_mode == SELECT_MULTI && icount > 1 && p_button != MouseButton::RIGHT) {
single_select_defer = p_item;
single_select_defer_column = col;
} else {
- if (p_button != MOUSE_BUTTON_RIGHT || !c.selected) {
+ if (p_button != MouseButton::RIGHT || !c.selected) {
select_single_item(p_item, root, col);
}
- if (p_button == MOUSE_BUTTON_RIGHT) {
+ if (p_button == MouseButton::RIGHT) {
emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position());
}
}
@@ -2523,7 +2583,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
} break;
case TreeItem::CELL_MODE_RANGE: {
- if (c.text != "") {
+ if (!c.text.is_empty()) {
//if (x >= (get_column_width(col)-item_h/2)) {
popup_menu->clear();
for (int i = 0; i < c.text.get_slice_count(","); i++) {
@@ -2532,7 +2592,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
popup_menu->set_size(Size2(col_width, 0));
- popup_menu->set_position(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset);
+ popup_menu->set_position(get_screen_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset);
popup_menu->popup();
popup_edited_item = p_item;
popup_edited_item_col = col;
@@ -2543,7 +2603,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
/* touching the combo */
bool up = p_pos.y < (item_h / 2);
- if (p_button == MOUSE_BUTTON_LEFT) {
+ if (p_button == MouseButton::LEFT) {
if (range_click_timer->get_time_left() == 0) {
range_item_last = p_item;
range_up_last = up;
@@ -2560,13 +2620,13 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
item_edited(col, p_item);
- } else if (p_button == MOUSE_BUTTON_RIGHT) {
+ } else if (p_button == MouseButton::RIGHT) {
p_item->set_range(col, (up ? c.max : c.min));
item_edited(col, p_item);
- } else if (p_button == MOUSE_BUTTON_WHEEL_UP) {
+ } else if (p_button == MouseButton::WHEEL_UP) {
p_item->set_range(col, c.val + c.step);
item_edited(col, p_item);
- } else if (p_button == MOUSE_BUTTON_WHEEL_DOWN) {
+ } else if (p_button == MouseButton::WHEEL_DOWN) {
p_item->set_range(col, c.val - c.step);
item_edited(col, p_item);
}
@@ -2599,14 +2659,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
if (!p_item->cells[col].custom_button || !on_arrow) {
- item_edited(col, p_item, p_button == MOUSE_BUTTON_LEFT);
+ item_edited(col, p_item, p_button == MouseButton::LEFT);
}
click_handled = true;
return -1;
} break;
};
- if (!bring_up_editor || p_button != MOUSE_BUTTON_LEFT) {
+ if (!bring_up_editor || p_button != MouseButton::LEFT) {
return -1;
}
@@ -2646,7 +2706,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
item_h += child_h;
}
}
- if (p_item == root && p_button == MOUSE_BUTTON_RIGHT) {
+ if (p_item == root && p_button == MouseButton::RIGHT) {
emit_signal(SNAME("empty_rmb"), get_local_mouse_position());
}
}
@@ -2655,9 +2715,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
void Tree::_text_editor_modal_close() {
- if (Input::get_singleton()->is_key_pressed(KEY_ESCAPE) ||
- Input::get_singleton()->is_key_pressed(KEY_KP_ENTER) ||
- Input::get_singleton()->is_key_pressed(KEY_ENTER)) {
+ if (Input::get_singleton()->is_key_pressed(Key::ESCAPE) ||
+ Input::get_singleton()->is_key_pressed(Key::KP_ENTER) ||
+ Input::get_singleton()->is_key_pressed(Key::ENTER)) {
return;
}
@@ -3048,7 +3108,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
return;
} else {
- if (k->get_keycode() != KEY_SHIFT) {
+ if (k->get_keycode() != Key::SHIFT) {
last_keypress = 0;
}
}
@@ -3164,7 +3224,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
} else {
const TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col];
float diff_y = -mm->get_relative().y;
- diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y);
+ diff_y = Math::pow(ABS(diff_y), 1.8f) * SIGN(diff_y);
diff_y *= 0.1;
range_drag_base = CLAMP(range_drag_base + c.step * diff_y, c.min, c.max);
popup_edited_item->set_range(popup_edited_item_col, range_drag_base);
@@ -3175,7 +3235,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (drag_touching && !drag_touching_deaccel) {
drag_accum -= mm->get_relative().y;
v_scroll->set_value(drag_from + drag_accum);
- drag_speed = -mm->get_speed().y;
+ drag_speed = -mm->get_velocity().y;
}
}
@@ -3189,7 +3249,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
bool rtl = is_layout_rtl();
if (!b->is_pressed()) {
- if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (b->get_button_index() == MouseButton::LEFT) {
Point2 pos = b->get_position();
if (rtl) {
pos.x = get_size().width - pos.x;
@@ -3226,8 +3286,21 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
} else {
Rect2 rect = get_selected()->get_meta("__focus_rect");
Point2 mpos = b->get_position();
+ int icon_size_x = 0;
+ Ref<Texture2D> icon = get_selected()->get_icon(selected_col);
+ if (icon.is_valid()) {
+ Rect2i icon_region = get_selected()->get_icon_region(selected_col);
+ if (icon_region == Rect2i()) {
+ icon_size_x = icon->get_width();
+ } else {
+ icon_size_x = icon_region.size.width;
+ }
+ }
+ // Icon is treated as if it is outside of the rect so that double clicking on it will emit the item_double_clicked signal.
if (rtl) {
- mpos.x = get_size().width - mpos.x;
+ mpos.x = get_size().width - (mpos.x + icon_size_x);
+ } else {
+ mpos.x -= icon_size_x;
}
if (rect.has_point(mpos)) {
if (!edit_selected()) {
@@ -3270,8 +3343,8 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
}
switch (b->get_button_index()) {
- case MOUSE_BUTTON_RIGHT:
- case MOUSE_BUTTON_LEFT: {
+ case MouseButton::RIGHT:
+ case MouseButton::LEFT: {
Ref<StyleBox> bg = cache.bg;
Point2 pos = b->get_position();
@@ -3284,7 +3357,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (b->get_button_index() == MouseButton::LEFT) {
pos.x += cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
@@ -3302,7 +3375,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
}
}
if (!root || (!root->get_first_child() && hide_root)) {
- if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) {
+ if (b->get_button_index() == MouseButton::RIGHT && allow_rmb_select) {
emit_signal(SNAME("empty_tree_rmb_selected"), get_local_mouse_position());
}
break;
@@ -3329,7 +3402,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (b->get_button_index() == MOUSE_BUTTON_RIGHT) {
+ if (b->get_button_index() == MouseButton::RIGHT) {
break;
}
@@ -3352,7 +3425,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
set_physics_process_internal(true);
}
- if (b->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (b->get_button_index() == MouseButton::LEFT) {
if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) {
emit_signal(SNAME("nothing_selected"));
}
@@ -3365,7 +3438,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
}
} break;
- case MOUSE_BUTTON_WHEEL_UP: {
+ case MouseButton::WHEEL_UP: {
double prev_value = v_scroll->get_value();
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
if (v_scroll->get_value() != prev_value) {
@@ -3373,7 +3446,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
}
} break;
- case MOUSE_BUTTON_WHEEL_DOWN: {
+ case MouseButton::WHEEL_DOWN: {
double prev_value = v_scroll->get_value();
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8);
if (v_scroll->get_value() != prev_value) {
@@ -3433,7 +3506,7 @@ bool Tree::edit_selected() {
item_edited(col, s);
return true;
- } else if (c.mode == TreeItem::CELL_MODE_RANGE && c.text != "") {
+ } else if (c.mode == TreeItem::CELL_MODE_RANGE && !c.text.is_empty()) {
popup_menu->clear();
for (int i = 0; i < c.text.get_slice_count(","); i++) {
String s2 = c.text.get_slicec(',', i);
@@ -3441,7 +3514,7 @@ bool Tree::edit_selected() {
}
popup_menu->set_size(Size2(rect.size.width, 0));
- popup_menu->set_position(get_global_position() + rect.position + Point2i(0, rect.size.height));
+ popup_menu->set_position(get_screen_position() + rect.position + Point2i(0, rect.size.height));
popup_menu->popup();
popup_edited_item = s;
popup_edited_item_col = col;
@@ -3569,178 +3642,187 @@ int Tree::_get_title_button_height() const {
}
void Tree::_notification(int p_what) {
- if (p_what == NOTIFICATION_FOCUS_ENTER) {
- if (get_viewport()) {
- focus_in_id = get_viewport()->get_processed_events_count();
- }
- }
- if (p_what == NOTIFICATION_MOUSE_EXIT) {
- if (cache.hover_type != Cache::CLICK_NONE) {
- cache.hover_type = Cache::CLICK_NONE;
- update();
- }
- }
-
- if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- drag_touching = false;
- }
+ switch (p_what) {
+ case NOTIFICATION_FOCUS_ENTER: {
+ if (get_viewport()) {
+ focus_in_id = get_viewport()->get_processed_events_count();
+ }
+ } break;
- if (p_what == NOTIFICATION_ENTER_TREE) {
- update_cache();
- }
- if (p_what == NOTIFICATION_DRAG_END) {
- drop_mode_flags = 0;
- scrolling = false;
- set_physics_process_internal(false);
- update();
- }
- if (p_what == NOTIFICATION_DRAG_BEGIN) {
- single_select_defer = nullptr;
- if (cache.scroll_speed > 0) {
- scrolling = true;
- set_physics_process_internal(true);
- }
- }
- if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
- if (drag_touching) {
- if (drag_touching_deaccel) {
- float pos = v_scroll->get_value();
- pos += drag_speed * get_physics_process_delta_time();
+ case NOTIFICATION_MOUSE_EXIT: {
+ if (cache.hover_type != Cache::CLICK_NONE) {
+ cache.hover_type = Cache::CLICK_NONE;
+ update();
+ }
+ } break;
- bool turnoff = false;
- if (pos < 0) {
- pos = 0;
- turnoff = true;
- set_physics_process_internal(false);
- drag_touching = false;
- drag_touching_deaccel = false;
- }
- if (pos > (v_scroll->get_max() - v_scroll->get_page())) {
- pos = v_scroll->get_max() - v_scroll->get_page();
- turnoff = true;
- }
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ drag_touching = false;
+ } break;
- v_scroll->set_value(pos);
- float sgn = drag_speed < 0 ? -1 : 1;
- float val = Math::abs(drag_speed);
- val -= 1000 * get_physics_process_delta_time();
+ case NOTIFICATION_ENTER_TREE: {
+ update_cache();
+ } break;
- if (val < 0) {
- turnoff = true;
- }
- drag_speed = sgn * val;
+ case NOTIFICATION_DRAG_END: {
+ drop_mode_flags = 0;
+ scrolling = false;
+ set_physics_process_internal(false);
+ update();
+ } break;
- if (turnoff) {
- set_physics_process_internal(false);
- drag_touching = false;
- drag_touching_deaccel = false;
- }
+ case NOTIFICATION_DRAG_BEGIN: {
+ single_select_defer = nullptr;
+ if (cache.scroll_speed > 0) {
+ scrolling = true;
+ set_physics_process_internal(true);
}
- }
+ } break;
- Point2 mouse_position = get_viewport()->get_mouse_position() - get_global_position();
- if (scrolling && get_rect().grow(cache.scroll_border).has_point(mouse_position)) {
- Point2 point;
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ if (drag_touching) {
+ if (drag_touching_deaccel) {
+ float pos = v_scroll->get_value();
+ pos += drag_speed * get_physics_process_delta_time();
- if ((ABS(mouse_position.x) < ABS(mouse_position.x - get_size().width)) && (ABS(mouse_position.x) < cache.scroll_border)) {
- point.x = mouse_position.x - cache.scroll_border;
- } else if (ABS(mouse_position.x - get_size().width) < cache.scroll_border) {
- point.x = mouse_position.x - (get_size().width - cache.scroll_border);
- }
+ bool turnoff = false;
+ if (pos < 0) {
+ pos = 0;
+ turnoff = true;
+ set_physics_process_internal(false);
+ drag_touching = false;
+ drag_touching_deaccel = false;
+ }
+ if (pos > (v_scroll->get_max() - v_scroll->get_page())) {
+ pos = v_scroll->get_max() - v_scroll->get_page();
+ turnoff = true;
+ }
- if ((ABS(mouse_position.y) < ABS(mouse_position.y - get_size().height)) && (ABS(mouse_position.y) < cache.scroll_border)) {
- point.y = mouse_position.y - cache.scroll_border;
- } else if (ABS(mouse_position.y - get_size().height) < cache.scroll_border) {
- point.y = mouse_position.y - (get_size().height - cache.scroll_border);
+ v_scroll->set_value(pos);
+ float sgn = drag_speed < 0 ? -1 : 1;
+ float val = Math::abs(drag_speed);
+ val -= 1000 * get_physics_process_delta_time();
+
+ if (val < 0) {
+ turnoff = true;
+ }
+ drag_speed = sgn * val;
+
+ if (turnoff) {
+ set_physics_process_internal(false);
+ drag_touching = false;
+ drag_touching_deaccel = false;
+ }
+ }
}
- point *= cache.scroll_speed * get_physics_process_delta_time();
- point += get_scroll();
- h_scroll->set_value(point.x);
- v_scroll->set_value(point.y);
- }
- }
+ Point2 mouse_position = get_viewport()->get_mouse_position() - get_global_position();
+ if (scrolling && get_rect().grow(cache.scroll_border).has_point(mouse_position)) {
+ Point2 point;
- if (p_what == NOTIFICATION_DRAW) {
- update_cache();
- update_scrollbars();
- RID ci = get_canvas_item();
+ if ((ABS(mouse_position.x) < ABS(mouse_position.x - get_size().width)) && (ABS(mouse_position.x) < cache.scroll_border)) {
+ point.x = mouse_position.x - cache.scroll_border;
+ } else if (ABS(mouse_position.x - get_size().width) < cache.scroll_border) {
+ point.x = mouse_position.x - (get_size().width - cache.scroll_border);
+ }
- Ref<StyleBox> bg = cache.bg;
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ if ((ABS(mouse_position.y) < ABS(mouse_position.y - get_size().height)) && (ABS(mouse_position.y) < cache.scroll_border)) {
+ point.y = mouse_position.y - cache.scroll_border;
+ } else if (ABS(mouse_position.y - get_size().height) < cache.scroll_border) {
+ point.y = mouse_position.y - (get_size().height - cache.scroll_border);
+ }
- 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;
- }
+ point *= cache.scroll_speed * get_physics_process_delta_time();
+ point += get_scroll();
+ h_scroll->set_value(point.x);
+ v_scroll->set_value(point.y);
+ }
+ } break;
- bg->draw(ci, Rect2(Point2(), get_size()));
+ case NOTIFICATION_DRAW: {
+ update_cache();
+ update_scrollbars();
+ RID ci = get_canvas_item();
+
+ Ref<StyleBox> bg = cache.bg;
+ 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;
+ }
- int tbh = _get_title_button_height();
+ bg->draw(ci, Rect2(Point2(), get_size()));
- draw_ofs.y += tbh;
- draw_size.y -= tbh;
+ int tbh = _get_title_button_height();
- cache.rtl = is_layout_rtl();
+ draw_ofs.y += tbh;
+ draw_size.y -= tbh;
- if (root && get_size().x > 0 && get_size().y > 0) {
- draw_item(Point2(), draw_ofs, draw_size, root);
- }
+ cache.rtl = is_layout_rtl();
- if (show_column_titles) {
- //title buttons
- int ofs2 = cache.bg->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) ? 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 (cache.rtl) {
- tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
- }
- sb->draw(ci, tbrect);
- ofs2 += tbrect.size.width;
- //text
- int clip_w = tbrect.size.width - sb->get_minimum_size().width;
- columns.write[i].text_buf->set_width(clip_w);
-
- Vector2 text_pos = tbrect.position + Point2i(sb->get_offset().x + (tbrect.size.width - columns[i].text_buf->get_size().x) / 2, (tbrect.size.height - columns[i].text_buf->get_size().y) / 2);
- if (outline_size > 0 && font_outline_color.a > 0) {
- columns[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
- }
- columns[i].text_buf->draw(ci, text_pos, cache.title_button_color);
+ if (root && get_size().x > 0 && get_size().y > 0) {
+ draw_item(Point2(), draw_ofs, draw_size, root);
}
- }
- // Draw the background focus outline last, so that it is drawn in front of the section headings.
- // 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(SNAME("bg_focus"));
- bg_focus->draw(ci, Rect2(Point2(), get_size()));
- RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
- }
- }
+ if (show_column_titles) {
+ //title buttons
+ int ofs2 = cache.bg->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) ? 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 (cache.rtl) {
+ tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
+ }
+ sb->draw(ci, tbrect);
+ ofs2 += tbrect.size.width;
+ //text
+ int clip_w = tbrect.size.width - sb->get_minimum_size().width;
+ columns.write[i].text_buf->set_width(clip_w);
+
+ Vector2 text_pos = tbrect.position + Point2i(sb->get_offset().x + (tbrect.size.width - columns[i].text_buf->get_size().x) / 2, (tbrect.size.height - columns[i].text_buf->get_size().y) / 2);
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ columns[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ columns[i].text_buf->draw(ci, text_pos, cache.title_button_color);
+ }
+ }
- if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
- update_cache();
- _update_all();
- }
+ // Draw the background focus outline last, so that it is drawn in front of the section headings.
+ // 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(SNAME("bg_focus"));
+ bg_focus->draw(ci, Rect2(Point2(), get_size()));
+ RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
+ }
+ } break;
- if (p_what == NOTIFICATION_RESIZED || p_what == NOTIFICATION_TRANSFORM_CHANGED) {
- if (popup_edited_item != nullptr) {
- Rect2 rect = popup_edited_item->get_meta("__focus_rect");
- Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2);
- Point2i textedpos = get_global_position() + rect.position - ofs;
+ case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
+ case NOTIFICATION_TRANSLATION_CHANGED: {
+ update_cache();
+ _update_all();
+ } break;
- if (cache.text_editor_position != textedpos) {
- cache.text_editor_position = textedpos;
- text_editor->set_position(textedpos);
- value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height));
+ case NOTIFICATION_RESIZED:
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ if (popup_edited_item != nullptr) {
+ Rect2 rect = popup_edited_item->get_meta("__focus_rect");
+ Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2);
+ Point2i textedpos = get_global_position() + rect.position - ofs;
+
+ if (cache.text_editor_position != textedpos) {
+ cache.text_editor_position = textedpos;
+ text_editor->set_position(textedpos);
+ value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height));
+ }
}
- }
+ } break;
}
}
@@ -3990,10 +4072,6 @@ int Tree::get_edited_column() const {
}
TreeItem *Tree::get_next_selected(TreeItem *p_item) {
- /*
- if (!p_item)
- return nullptr;
- */
if (!root) {
return nullptr;
}
@@ -4350,27 +4428,35 @@ Point2 Tree::get_scroll() const {
return ofs;
}
-void Tree::scroll_to_item(TreeItem *p_item) {
+void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
if (!is_visible_in_tree()) {
- // hack to work around crash in get_item_rect() if Tree is not in tree.
- return;
+ return; // Hack to work around crash in get_item_rect() if Tree is not in tree.
}
- // make sure the scrollbar min and max are up to date with latest changes.
update_scrollbars();
- const Rect2 r = get_item_rect(p_item);
+ const real_t tree_height = get_size().y;
+ const Rect2 item_rect = get_item_rect(p_item);
+ const real_t item_y = item_rect.position.y;
+ const real_t item_height = item_rect.size.y + cache.vseparation;
- if (r.position.y <= v_scroll->get_value()) {
- v_scroll->set_value(r.position.y);
- } else if (r.position.y + r.size.y + 2 * cache.vseparation > v_scroll->get_value() + get_size().y) {
- v_scroll->set_value(r.position.y + r.size.y + 2 * cache.vseparation - get_size().y);
+ if (p_center_on_item) {
+ v_scroll->set_value(item_y - (tree_height - item_height) / 2.0f);
+ } else {
+ if (item_y < v_scroll->get_value()) {
+ v_scroll->set_value(item_y);
+ } else {
+ const real_t new_position = item_y + item_height - tree_height;
+ if (new_position > v_scroll->get_value()) {
+ v_scroll->set_value(new_position);
+ }
+ }
}
}
void Tree::set_h_scroll_enabled(bool p_enable) {
h_scroll_enabled = p_enable;
- minimum_size_changed();
+ update_minimum_size();
}
bool Tree::is_h_scroll_enabled() const {
@@ -4379,7 +4465,7 @@ bool Tree::is_h_scroll_enabled() const {
void Tree::set_v_scroll_enabled(bool p_enable) {
v_scroll_enabled = p_enable;
- minimum_size_changed();
+ update_minimum_size();
}
bool Tree::is_v_scroll_enabled() const {
@@ -4682,7 +4768,7 @@ String Tree::get_tooltip(const Point2 &p_pos) const {
Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
if (pos.x > col_width - size.width) {
String tooltip = c.buttons[j].tooltip;
- if (tooltip != "") {
+ if (!tooltip.is_empty()) {
return tooltip;
}
}
@@ -4756,7 +4842,7 @@ bool Tree::get_allow_reselect() const {
void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &Tree::clear);
- ClassDB::bind_method(D_METHOD("create_item", "parent", "idx"), &Tree::_create_item, DEFVAL(Variant()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("create_item", "parent", "idx"), &Tree::create_item, DEFVAL(Variant()), DEFVAL(-1));
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);
@@ -4771,7 +4857,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hide_root", "enable"), &Tree::set_hide_root);
ClassDB::bind_method(D_METHOD("is_root_hidden"), &Tree::is_root_hidden);
- ClassDB::bind_method(D_METHOD("get_next_selected", "from"), &Tree::_get_next_selected);
+ ClassDB::bind_method(D_METHOD("get_next_selected", "from"), &Tree::get_next_selected);
ClassDB::bind_method(D_METHOD("get_selected"), &Tree::get_selected);
ClassDB::bind_method(D_METHOD("get_selected_column"), &Tree::get_selected_column);
ClassDB::bind_method(D_METHOD("get_pressed_button"), &Tree::get_pressed_button);
@@ -4785,10 +4871,11 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column);
ClassDB::bind_method(D_METHOD("edit_selected"), &Tree::edit_selected);
ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect);
- ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::_get_item_rect, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::get_item_rect, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
ClassDB::bind_method(D_METHOD("get_column_at_position", "position"), &Tree::get_column_at_position);
ClassDB::bind_method(D_METHOD("get_drop_section_at_position", "position"), &Tree::get_drop_section_at_position);
+ ClassDB::bind_method(D_METHOD("get_button_id_at_position", "position"), &Tree::get_button_id_at_position);
ClassDB::bind_method(D_METHOD("ensure_cursor_is_visible"), &Tree::ensure_cursor_is_visible);
@@ -4809,7 +4896,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_column_title_language", "column"), &Tree::get_column_title_language);
ClassDB::bind_method(D_METHOD("get_scroll"), &Tree::get_scroll);
- ClassDB::bind_method(D_METHOD("scroll_to_item", "item"), &Tree::_scroll_to_item);
+ ClassDB::bind_method(D_METHOD("scroll_to_item", "item", "center_on_item"), &Tree::scroll_to_item, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_h_scroll_enabled", "h_scroll"), &Tree::set_h_scroll_enabled);
ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &Tree::is_h_scroll_enabled);
@@ -4830,6 +4917,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_allow_reselect"), &Tree::get_allow_reselect);
ADD_PROPERTY(PropertyInfo(Variant::INT, "columns"), "set_columns", "get_columns");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "column_titles_visible"), "set_column_titles_visible", "are_column_titles_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_folding"), "set_hide_folding", "is_folding_hidden");
@@ -4850,6 +4938,7 @@ void Tree::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
ADD_SIGNAL(MethodInfo("item_double_clicked"));
ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem")));
+ ADD_SIGNAL(MethodInfo("check_propagated_to_item", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column")));
//ADD_SIGNAL( MethodInfo("item_double_clicked" ) );
ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked")));