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