Implement TreeItem.add_child
This commit is contained in:
parent
6101240231
commit
3ed7bdc26f
3 changed files with 86 additions and 48 deletions
|
@ -22,6 +22,13 @@
|
||||||
Adds a button with [Texture2D] [param button] at column [param column]. The [param id] is used to identify the button in the according [signal Tree.button_clicked] signal and can be different from the buttons index. If not specified, the next available index is used, which may be retrieved by calling [method get_button_count] immediately before this method. Optionally, the button can be [param disabled] and have a [param tooltip_text].
|
Adds a button with [Texture2D] [param button] at column [param column]. The [param id] is used to identify the button in the according [signal Tree.button_clicked] signal and can be different from the buttons index. If not specified, the next available index is used, which may be retrieved by calling [method get_button_count] immediately before this method. Optionally, the button can be [param disabled] and have a [param tooltip_text].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="add_child">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="child" type="TreeItem" />
|
||||||
|
<description>
|
||||||
|
Adds a previously unparented [TreeItem] as a direct child of this one. The [param child] item must not be a part of any [Tree] or parented to any [TreeItem]. See also [method remove_child].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="call_recursive" qualifiers="vararg">
|
<method name="call_recursive" qualifiers="vararg">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="method" type="StringName" />
|
<param index="0" name="method" type="StringName" />
|
||||||
|
@ -430,7 +437,8 @@
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="child" type="TreeItem" />
|
<param index="0" name="child" type="TreeItem" />
|
||||||
<description>
|
<description>
|
||||||
Removes the given child [TreeItem] and all its children from the [Tree]. Note that it doesn't free the item from memory, so it can be reused later. To completely remove a [TreeItem] use [method Object.free].
|
Removes the given child [TreeItem] and all its children from the [Tree]. Note that it doesn't free the item from memory, so it can be reused later (see [method add_child]). To completely remove a [TreeItem] use [method Object.free].
|
||||||
|
[b]Note:[/b] If you want to move a child from one [Tree] to another, then instead of removing and adding it manually you can use [method move_before] or [method move_after].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="select">
|
<method name="select">
|
||||||
|
|
|
@ -677,23 +677,26 @@ TreeItem *TreeItem::create_child(int p_index) {
|
||||||
tree->queue_redraw();
|
tree->queue_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *l_prev = nullptr;
|
TreeItem *item_prev = nullptr;
|
||||||
TreeItem *c = first_child;
|
TreeItem *item_next = first_child;
|
||||||
int idx = 0;
|
|
||||||
|
|
||||||
while (c) {
|
int idx = 0;
|
||||||
if (idx++ == p_index) {
|
while (item_next) {
|
||||||
c->prev = ti;
|
if (idx == p_index) {
|
||||||
ti->next = c;
|
item_next->prev = ti;
|
||||||
|
ti->next = item_next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
l_prev = c;
|
|
||||||
c = c->next;
|
item_prev = item_next;
|
||||||
|
item_next = item_next->next;
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l_prev) {
|
if (item_prev) {
|
||||||
l_prev->next = ti;
|
item_prev->next = ti;
|
||||||
ti->prev = l_prev;
|
ti->prev = item_prev;
|
||||||
|
|
||||||
if (!children_cache.is_empty()) {
|
if (!children_cache.is_empty()) {
|
||||||
if (ti->next) {
|
if (ti->next) {
|
||||||
children_cache.insert(p_index, ti);
|
children_cache.insert(p_index, ti);
|
||||||
|
@ -713,6 +716,46 @@ TreeItem *TreeItem::create_child(int p_index) {
|
||||||
return ti;
|
return ti;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TreeItem::add_child(TreeItem *p_item) {
|
||||||
|
ERR_FAIL_NULL(p_item);
|
||||||
|
ERR_FAIL_COND(p_item->tree);
|
||||||
|
ERR_FAIL_COND(p_item->parent);
|
||||||
|
|
||||||
|
p_item->_change_tree(tree);
|
||||||
|
p_item->parent = this;
|
||||||
|
|
||||||
|
TreeItem *item_prev = first_child;
|
||||||
|
while (item_prev && item_prev->next) {
|
||||||
|
item_prev = item_prev->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item_prev) {
|
||||||
|
item_prev->next = p_item;
|
||||||
|
p_item->prev = item_prev;
|
||||||
|
} else {
|
||||||
|
first_child = p_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!children_cache.is_empty()) {
|
||||||
|
children_cache.append(p_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::remove_child(TreeItem *p_item) {
|
||||||
|
ERR_FAIL_NULL(p_item);
|
||||||
|
ERR_FAIL_COND(p_item->parent != this);
|
||||||
|
|
||||||
|
p_item->_unlink_from_tree();
|
||||||
|
p_item->_change_tree(nullptr);
|
||||||
|
p_item->prev = nullptr;
|
||||||
|
p_item->next = nullptr;
|
||||||
|
p_item->parent = nullptr;
|
||||||
|
|
||||||
|
validate_cache();
|
||||||
|
}
|
||||||
|
|
||||||
Tree *TreeItem::get_tree() const {
|
Tree *TreeItem::get_tree() const {
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
@ -888,6 +931,18 @@ TypedArray<TreeItem> TreeItem::get_children() {
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TreeItem::clear_children() {
|
||||||
|
TreeItem *c = first_child;
|
||||||
|
while (c) {
|
||||||
|
TreeItem *aux = c;
|
||||||
|
c = c->get_next();
|
||||||
|
aux->parent = nullptr; // So it won't try to recursively auto-remove from me in here.
|
||||||
|
memdelete(aux);
|
||||||
|
}
|
||||||
|
|
||||||
|
first_child = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
int TreeItem::get_index() {
|
int TreeItem::get_index() {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
TreeItem *c = this;
|
TreeItem *c = this;
|
||||||
|
@ -943,7 +998,7 @@ void TreeItem::move_before(TreeItem *p_item) {
|
||||||
} else {
|
} else {
|
||||||
parent->first_child = this;
|
parent->first_child = this;
|
||||||
// If the cache is empty, it has not been built but there
|
// If the cache is empty, it has not been built but there
|
||||||
// are items in the tree (note p_item != nullptr,) so we cannot update it.
|
// are items in the tree (note p_item != nullptr) so we cannot update it.
|
||||||
if (!parent->children_cache.is_empty()) {
|
if (!parent->children_cache.is_empty()) {
|
||||||
parent->children_cache.insert(0, this);
|
parent->children_cache.insert(0, this);
|
||||||
}
|
}
|
||||||
|
@ -1003,21 +1058,6 @@ void TreeItem::move_after(TreeItem *p_item) {
|
||||||
validate_cache();
|
validate_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeItem::remove_child(TreeItem *p_item) {
|
|
||||||
ERR_FAIL_NULL(p_item);
|
|
||||||
ERR_FAIL_COND(p_item->parent != this);
|
|
||||||
|
|
||||||
p_item->_unlink_from_tree();
|
|
||||||
p_item->prev = nullptr;
|
|
||||||
p_item->next = nullptr;
|
|
||||||
p_item->parent = nullptr;
|
|
||||||
|
|
||||||
if (tree) {
|
|
||||||
tree->queue_redraw();
|
|
||||||
}
|
|
||||||
validate_cache();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TreeItem::set_selectable(int p_column, bool p_selectable) {
|
void TreeItem::set_selectable(int p_column, bool p_selectable) {
|
||||||
ERR_FAIL_INDEX(p_column, cells.size());
|
ERR_FAIL_INDEX(p_column, cells.size());
|
||||||
cells.write[p_column].selectable = p_selectable;
|
cells.write[p_column].selectable = p_selectable;
|
||||||
|
@ -1542,6 +1582,9 @@ void TreeItem::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled);
|
ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("create_child", "index"), &TreeItem::create_child, DEFVAL(-1));
|
ClassDB::bind_method(D_METHOD("create_child", "index"), &TreeItem::create_child, DEFVAL(-1));
|
||||||
|
ClassDB::bind_method(D_METHOD("add_child", "child"), &TreeItem::add_child);
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::remove_child);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_tree"), &TreeItem::get_tree);
|
ClassDB::bind_method(D_METHOD("get_tree"), &TreeItem::get_tree);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next);
|
ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next);
|
||||||
|
@ -1563,8 +1606,6 @@ void TreeItem::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::move_before);
|
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_after", "item"), &TreeItem::move_after);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::remove_child);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
MethodInfo mi;
|
MethodInfo mi;
|
||||||
mi.name = "call_recursive";
|
mi.name = "call_recursive";
|
||||||
|
@ -1585,28 +1626,17 @@ void TreeItem::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(CELL_MODE_CUSTOM);
|
BIND_ENUM_CONSTANT(CELL_MODE_CUSTOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeItem::clear_children() {
|
|
||||||
TreeItem *c = first_child;
|
|
||||||
while (c) {
|
|
||||||
TreeItem *aux = c;
|
|
||||||
c = c->get_next();
|
|
||||||
aux->parent = nullptr; // so it won't try to recursively autoremove from me in here
|
|
||||||
memdelete(aux);
|
|
||||||
}
|
|
||||||
|
|
||||||
first_child = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
TreeItem::TreeItem(Tree *p_tree) {
|
TreeItem::TreeItem(Tree *p_tree) {
|
||||||
tree = p_tree;
|
tree = p_tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem::~TreeItem() {
|
TreeItem::~TreeItem() {
|
||||||
_unlink_from_tree();
|
_unlink_from_tree();
|
||||||
|
_change_tree(nullptr);
|
||||||
|
|
||||||
validate_cache();
|
validate_cache();
|
||||||
prev = nullptr;
|
prev = nullptr;
|
||||||
clear_children();
|
clear_children();
|
||||||
_change_tree(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
|
@ -4484,6 +4514,7 @@ bool Tree::is_column_expanding(int p_column) const {
|
||||||
|
|
||||||
return columns[p_column].expand;
|
return columns[p_column].expand;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Tree::get_column_expand_ratio(int p_column) const {
|
int Tree::get_column_expand_ratio(int p_column) const {
|
||||||
ERR_FAIL_INDEX_V(p_column, columns.size(), 1);
|
ERR_FAIL_INDEX_V(p_column, columns.size(), 1);
|
||||||
|
|
||||||
|
|
|
@ -336,6 +336,8 @@ public:
|
||||||
/* Item manipulation */
|
/* Item manipulation */
|
||||||
|
|
||||||
TreeItem *create_child(int p_index = -1);
|
TreeItem *create_child(int p_index = -1);
|
||||||
|
void add_child(TreeItem *p_item);
|
||||||
|
void remove_child(TreeItem *p_item);
|
||||||
|
|
||||||
Tree *get_tree() const;
|
Tree *get_tree() const;
|
||||||
|
|
||||||
|
@ -354,6 +356,7 @@ public:
|
||||||
int get_visible_child_count();
|
int get_visible_child_count();
|
||||||
int get_child_count();
|
int get_child_count();
|
||||||
TypedArray<TreeItem> get_children();
|
TypedArray<TreeItem> get_children();
|
||||||
|
void clear_children();
|
||||||
int get_index();
|
int get_index();
|
||||||
|
|
||||||
#ifdef DEV_ENABLED
|
#ifdef DEV_ENABLED
|
||||||
|
@ -366,12 +369,8 @@ public:
|
||||||
void move_before(TreeItem *p_item);
|
void move_before(TreeItem *p_item);
|
||||||
void move_after(TreeItem *p_item);
|
void move_after(TreeItem *p_item);
|
||||||
|
|
||||||
void remove_child(TreeItem *p_item);
|
|
||||||
|
|
||||||
void call_recursive(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
void call_recursive(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||||
|
|
||||||
void clear_children();
|
|
||||||
|
|
||||||
~TreeItem();
|
~TreeItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue