diff options
Diffstat (limited to 'scene/gui/tree.cpp')
-rw-r--r-- | scene/gui/tree.cpp | 599 |
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"))); |