Skip to content

Commit

Permalink
Merge pull request #53276 from Phischermen/propagate_check
Browse files Browse the repository at this point in the history
  • Loading branch information
akien-mga authored Jan 20, 2022
2 parents 9e0973c + a4bac26 commit eacde08
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 160 deletions.
7 changes: 7 additions & 0 deletions doc/classes/Tree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,13 @@
Emitted when a cell is selected.
</description>
</signal>
<signal name="check_propagated_to_item">
<argument index="0" name="item" type="TreeItem" />
<argument index="1" name="column" type="int" />
<description>
Emitted when [method TreeItem.propagate_check] is called. Connect to this signal to process the items that are affected when [method TreeItem.propagate_check] is invoked. The order that the items affected will be processed is as follows: the item that invoked the method, children of that item, and finally parents of that item.
</description>
</signal>
<signal name="column_title_pressed">
<argument index="0" name="column" type="int" />
<description>
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/TreeItem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,14 @@
[b]Note:[/b] You can't move to the root or move the root.
</description>
</method>
<method name="propagate_check">
<return type="void" />
<argument index="0" name="column" type="int" />
<argument index="1" name="emit_signal" type="bool" default="true" />
<description>
Propagates this item's checked status to its children and parents for the given [code]column[/code]. It is possible to process the items affected by this method call by connecting to [signal Tree.check_propagated_to_item]. The order that the items affected will be processed is as follows: the item invoking this method, children of that item, and finally parents of that item. If [code]emit_signal[/code] is set to false, then [signal Tree.check_propagated_to_item] will not be emitted.
</description>
</method>
<method name="remove_child">
<return type="void" />
<argument index="0" name="child" type="Object" />
Expand Down
64 changes: 11 additions & 53 deletions editor/editor_asset_installer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,45 +36,6 @@
#include "editor_node.h"
#include "progress_dialog.h"

void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool p_first) {
if (p_check) {
if (p_item->get_custom_color(0) == Color()) {
p_item->set_checked(0, true);
}
} else {
p_item->set_checked(0, false);
}

if (p_item->get_first_child()) {
_update_subitems(p_item->get_first_child(), p_check);
}

if (!p_first && p_item->get_next()) {
_update_subitems(p_item->get_next(), p_check);
}
}

void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) {
if (!p_item) {
return;
}

bool any_checked = false;
TreeItem *item = p_item->get_first_child();
while (item) {
if (item->is_checked(0)) {
any_checked = true;
break;
}
item = item->get_next();
}

if (!any_checked) {
p_item->set_checked(0, false);
_uncheck_parent(p_item->get_parent());
}
}

void EditorAssetInstaller::_item_edited() {
if (updating) {
return;
Expand All @@ -85,22 +46,17 @@ void EditorAssetInstaller::_item_edited() {
return;
}

String path = item->get_metadata(0);

updating = true;
if (path.is_empty() || item == tree->get_root()) { //a dir or root
_update_subitems(item, item->is_checked(0), true);
}
item->propagate_check(0);
updating = false;
}

if (item->is_checked(0)) {
while (item) {
item->set_checked(0, true);
item = item->get_parent();
}
} else {
_uncheck_parent(item->get_parent());
void EditorAssetInstaller::_check_propagated_to_item(Object *p_obj, int column) {
TreeItem *affected_item = Object::cast_to<TreeItem>(p_obj);
if (affected_item && affected_item->get_custom_color(0) != Color()) {
affected_item->set_checked(0, false);
affected_item->propagate_check(0, false);
}
updating = false;
}

void EditorAssetInstaller::open(const String &p_path, int p_depth) {
Expand Down Expand Up @@ -259,6 +215,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
ti->set_custom_color(0, tree->get_theme_color(SNAME("error_color"), SNAME("Editor")));
ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path));
ti->set_checked(0, false);
ti->propagate_check(0);
} else {
ti->set_tooltip(0, res_path);
}
Expand Down Expand Up @@ -304,7 +261,7 @@ void EditorAssetInstaller::ok_pressed() {

String name = String::utf8(fname);

if (status_map.has(name) && status_map[name]->is_checked(0)) {
if (status_map.has(name) && (status_map[name]->is_checked(0) || status_map[name]->is_indeterminate(0))) {
String path = status_map[name]->get_metadata(0);
if (path.is_empty()) { // a dir

Expand Down Expand Up @@ -392,6 +349,7 @@ EditorAssetInstaller::EditorAssetInstaller() {
tree = memnew(Tree);
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited));
tree->connect("check_propagated_to_item", callable_mp(this, &EditorAssetInstaller::_check_propagated_to_item));
vb->add_child(tree);

error = memnew(AcceptDialog);
Expand Down
3 changes: 1 addition & 2 deletions editor/editor_asset_installer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ class EditorAssetInstaller : public ConfirmationDialog {
AcceptDialog *error;
Map<String, TreeItem *> status_map;
bool updating;
void _update_subitems(TreeItem *p_item, bool p_check, bool p_first = false);
void _uncheck_parent(TreeItem *p_item);
void _item_edited();
void _check_propagated_to_item(Object *p_obj, int column);
virtual void ok_pressed() override;

protected:
Expand Down
75 changes: 19 additions & 56 deletions editor/plugins/theme_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ void ThemeItemImportTree::_update_items_tree() {

bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1);
bool has_filtered_items = false;
bool any_checked = false;
bool any_checked_with_data = false;

for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
Theme::DataType dt = (Theme::DataType)i;
Expand Down Expand Up @@ -178,9 +176,6 @@ void ThemeItemImportTree::_update_items_tree() {
break; // Can't happen, but silences warning.
}

bool data_type_any_checked = false;
bool data_type_any_checked_with_data = false;

filtered_names.sort_custom<StringName::AlphCompare>();
for (const StringName &F : filtered_names) {
TreeItem *item_node = import_items_tree->create_item(data_type_node);
Expand All @@ -194,20 +189,11 @@ void ThemeItemImportTree::_update_items_tree() {
item_node->set_editable(IMPORT_ITEM_DATA, true);

_restore_selected_item(item_node);
if (item_node->is_checked(IMPORT_ITEM)) {
data_type_any_checked = true;
any_checked = true;
}
if (item_node->is_checked(IMPORT_ITEM_DATA)) {
data_type_any_checked_with_data = true;
any_checked_with_data = true;
}
item_node->propagate_check(IMPORT_ITEM, false);
item_node->propagate_check(IMPORT_ITEM_DATA, false);

item_list->push_back(item_node);
}

data_type_node->set_checked(IMPORT_ITEM, data_type_any_checked);
data_type_node->set_checked(IMPORT_ITEM_DATA, data_type_any_checked && data_type_any_checked_with_data);
}

// Remove the item if it doesn't match the filter in any way.
Expand All @@ -221,9 +207,6 @@ void ThemeItemImportTree::_update_items_tree() {
if (!filter_text.is_empty() && has_filtered_items) {
type_node->set_collapsed(false);
}

type_node->set_checked(IMPORT_ITEM, any_checked);
type_node->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
}

if (color_amount > 0) {
Expand Down Expand Up @@ -471,23 +454,26 @@ void ThemeItemImportTree::_tree_item_edited() {
if (is_checked) {
if (edited_column == IMPORT_ITEM_DATA) {
edited_item->set_checked(IMPORT_ITEM, true);
edited_item->propagate_check(IMPORT_ITEM);
}

_select_all_subitems(edited_item, (edited_column == IMPORT_ITEM_DATA));
} else {
if (edited_column == IMPORT_ITEM) {
edited_item->set_checked(IMPORT_ITEM_DATA, false);
edited_item->propagate_check(IMPORT_ITEM_DATA);
}

_deselect_all_subitems(edited_item, (edited_column == IMPORT_ITEM));
}

_update_parent_items(edited_item);
_store_selected_item(edited_item);

edited_item->propagate_check(edited_column);
updating_tree = false;
}

void ThemeItemImportTree::_check_propagated_to_tree_item(Object *p_obj, int p_column) {
TreeItem *item = Object::cast_to<TreeItem>(p_obj);
// Skip "category" tree items by checking for children.
if (item && !item->get_first_child()) {
_store_selected_item(item);
}
}

void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) {
TreeItem *child_item = p_root_item->get_first_child();
while (child_item) {
Expand Down Expand Up @@ -516,32 +502,6 @@ void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_d
}
}

void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) {
TreeItem *parent_item = p_root_item->get_parent();
if (!parent_item) {
return;
}

bool any_checked = false;
bool any_checked_with_data = false;

TreeItem *child_item = parent_item->get_first_child();
while (child_item) {
if (child_item->is_checked(IMPORT_ITEM)) {
any_checked = true;
}
if (child_item->is_checked(IMPORT_ITEM_DATA)) {
any_checked_with_data = true;
}

child_item = child_item->get_next();
}

parent_item->set_checked(IMPORT_ITEM, any_checked);
parent_item->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
_update_parent_items(parent_item);
}

void ThemeItemImportTree::_select_all_items_pressed() {
if (updating_tree) {
return;
Expand Down Expand Up @@ -629,7 +589,7 @@ void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) {
}

child_item->set_checked(IMPORT_ITEM, true);
_update_parent_items(child_item);
child_item->propagate_check(IMPORT_ITEM, false);
_store_selected_item(child_item);
}

Expand Down Expand Up @@ -685,7 +645,8 @@ void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) {

child_item->set_checked(IMPORT_ITEM, true);
child_item->set_checked(IMPORT_ITEM_DATA, true);
_update_parent_items(child_item);
child_item->propagate_check(IMPORT_ITEM, false);
child_item->propagate_check(IMPORT_ITEM_DATA, false);
_store_selected_item(child_item);
}

Expand Down Expand Up @@ -741,7 +702,8 @@ void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) {

child_item->set_checked(IMPORT_ITEM, false);
child_item->set_checked(IMPORT_ITEM_DATA, false);
_update_parent_items(child_item);
child_item->propagate_check(IMPORT_ITEM, false);
child_item->propagate_check(IMPORT_ITEM_DATA, false);
_store_selected_item(child_item);
}

Expand Down Expand Up @@ -937,6 +899,7 @@ ThemeItemImportTree::ThemeItemImportTree() {
import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
import_main_hb->add_child(import_items_tree);
import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited));
import_items_tree->connect("check_propagated_to_item", callable_mp(this, &ThemeItemImportTree::_check_propagated_to_tree_item));

import_items_tree->set_columns(3);
import_items_tree->set_column_titles_visible(true);
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/theme_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ class ThemeItemImportTree : public VBoxContainer {
void _update_total_selected(Theme::DataType p_data_type);

void _tree_item_edited();
void _check_propagated_to_tree_item(Object *p_obj, int p_column);
void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
void _update_parent_items(TreeItem *p_root_item);

void _select_all_items_pressed();
void _select_full_items_pressed();
Expand Down
Loading

0 comments on commit eacde08

Please sign in to comment.