|
@@ -563,6 +563,57 @@ bool TreeItem::is_collapsed() {
|
|
|
return collapsed;
|
|
|
}
|
|
|
|
|
|
+void TreeItem::set_collapsed_recursive(bool p_collapsed) {
|
|
|
+ if (!tree) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ set_collapsed(p_collapsed);
|
|
|
+
|
|
|
+ TreeItem *child = get_first_child();
|
|
|
+ while (child) {
|
|
|
+ child->set_collapsed_recursive(p_collapsed);
|
|
|
+ child = child->get_next();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool TreeItem::_is_any_collapsed(bool p_only_visible) {
|
|
|
+ TreeItem *child = get_first_child();
|
|
|
+
|
|
|
+ // Check on children directly first (avoid recursing if possible).
|
|
|
+ while (child) {
|
|
|
+ if (child->get_first_child() && child->is_collapsed() && (!p_only_visible || (child->is_visible() && child->get_visible_child_count()))) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ child = child->get_next();
|
|
|
+ }
|
|
|
+
|
|
|
+ child = get_first_child();
|
|
|
+
|
|
|
+ // Otherwise recurse on children.
|
|
|
+ while (child) {
|
|
|
+ if (child->get_first_child() && (!p_only_visible || (child->is_visible() && child->get_visible_child_count())) && child->_is_any_collapsed(p_only_visible)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ child = child->get_next();
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool TreeItem::is_any_collapsed(bool p_only_visible) {
|
|
|
+ if (p_only_visible && !is_visible()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Collapsed if this is collapsed and it has children (only considers visible if only visible is set).
|
|
|
+ if (is_collapsed() && get_first_child() && (!p_only_visible || get_visible_child_count())) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return _is_any_collapsed(p_only_visible);
|
|
|
+}
|
|
|
+
|
|
|
void TreeItem::set_visible(bool p_visible) {
|
|
|
if (visible == p_visible) {
|
|
|
return;
|
|
@@ -1406,6 +1457,9 @@ void TreeItem::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed);
|
|
|
ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed);
|
|
|
|
|
|
+ ClassDB::bind_method(D_METHOD("set_collapsed_recursive", "enable"), &TreeItem::set_collapsed_recursive);
|
|
|
+ ClassDB::bind_method(D_METHOD("is_any_collapsed", "only_visible"), &TreeItem::is_any_collapsed, DEFVAL(false));
|
|
|
+
|
|
|
ClassDB::bind_method(D_METHOD("set_visible", "enable"), &TreeItem::set_visible);
|
|
|
ClassDB::bind_method(D_METHOD("is_visible"), &TreeItem::is_visible);
|
|
|
|
|
@@ -2572,7 +2626,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
|
|
|
}
|
|
|
|
|
|
if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + theme_cache.item_margin))) {
|
|
|
- p_item->set_collapsed(!p_item->is_collapsed());
|
|
|
+ if (enable_recursive_folding && p_mod->is_shift_pressed()) {
|
|
|
+ p_item->set_collapsed_recursive(!p_item->is_collapsed());
|
|
|
+ } else {
|
|
|
+ p_item->set_collapsed(!p_item->is_collapsed());
|
|
|
+ }
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
@@ -2623,7 +2681,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
|
|
|
}
|
|
|
|
|
|
if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) {
|
|
|
- p_item->set_collapsed(!p_item->is_collapsed());
|
|
|
+ if (enable_recursive_folding && p_mod->is_shift_pressed()) {
|
|
|
+ p_item->set_collapsed_recursive(!p_item->is_collapsed());
|
|
|
+ } else {
|
|
|
+ p_item->set_collapsed(!p_item->is_collapsed());
|
|
|
+ }
|
|
|
return -1; //collapse/uncollapse because nothing can be done with item
|
|
|
}
|
|
|
|
|
@@ -5026,6 +5088,14 @@ bool Tree::is_folding_hidden() const {
|
|
|
return hide_folding;
|
|
|
}
|
|
|
|
|
|
+void Tree::set_enable_recursive_folding(bool p_enable) {
|
|
|
+ enable_recursive_folding = p_enable;
|
|
|
+}
|
|
|
+
|
|
|
+bool Tree::is_recursive_folding_enabled() const {
|
|
|
+ return enable_recursive_folding;
|
|
|
+}
|
|
|
+
|
|
|
void Tree::set_drop_mode_flags(int p_flags) {
|
|
|
if (drop_mode_flags == p_flags) {
|
|
|
return;
|
|
@@ -5129,6 +5199,9 @@ void Tree::_bind_methods() {
|
|
|
ClassDB::bind_method(D_METHOD("set_hide_folding", "hide"), &Tree::set_hide_folding);
|
|
|
ClassDB::bind_method(D_METHOD("is_folding_hidden"), &Tree::is_folding_hidden);
|
|
|
|
|
|
+ ClassDB::bind_method(D_METHOD("set_enable_recursive_folding", "enable"), &Tree::set_enable_recursive_folding);
|
|
|
+ ClassDB::bind_method(D_METHOD("is_recursive_folding_enabled"), &Tree::is_recursive_folding_enabled);
|
|
|
+
|
|
|
ClassDB::bind_method(D_METHOD("set_drop_mode_flags", "flags"), &Tree::set_drop_mode_flags);
|
|
|
ClassDB::bind_method(D_METHOD("get_drop_mode_flags"), &Tree::get_drop_mode_flags);
|
|
|
|
|
@@ -5143,6 +5216,7 @@ void Tree::_bind_methods() {
|
|
|
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");
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_recursive_folding"), "set_enable_recursive_folding", "is_recursive_folding_enabled");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode");
|