From 75866c81e7163a264bbbf1684a4564fae37fc50f Mon Sep 17 00:00:00 2001
From: Kevin Fischer <46539626+Phischermen@users.noreply.github.com>
Date: Thu, 22 Jul 2021 13:34:54 -0700
Subject: [PATCH] Added icons and API for indeterminate checkmarks for the Tree
class.
---
doc/classes/Tree.xml | 3 +++
doc/classes/TreeItem.xml | 18 ++++++++++++-
editor/editor_themes.cpp | 2 ++
editor/icons/GuiIndeterminate.svg | 1 +
scene/gui/tree.cpp | 25 +++++++++++++++++-
scene/gui/tree.h | 4 +++
.../resources/default_theme/default_theme.cpp | 1 +
.../resources/default_theme/indeterminate.png | Bin 0 -> 242 bytes
scene/resources/default_theme/theme_data.h | 8 ++++++
9 files changed, 60 insertions(+), 2 deletions(-)
create mode 100644 editor/icons/GuiIndeterminate.svg
create mode 100644 scene/resources/default_theme/indeterminate.png
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 50a573d30f..ed24905254 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -552,6 +552,9 @@
The horizontal space between item cells. This is also used as the margin at the start of an item when folding is disabled.
+
+ The check icon to display when the [constant TreeItem.CELL_MODE_CHECK] mode cell is indeterminate.
+
The horizontal margin at the start of an item. This is used when folding is enabled for the item.
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index 944b9fdc06..406c074758 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -340,6 +340,13 @@
Returns [code]true[/code] if column [code]column[/code] is editable.
+
+
+
+
+ Returns [code]true[/code] if the given column is indeterminate.
+
+
@@ -415,7 +422,7 @@
- If [code]true[/code], the column [code]column[/code] is checked.
+ If [code]true[/code], the column [code]column[/code] is checked. Clears column's indeterminate status.
@@ -507,6 +514,15 @@
Sets the given column's icon's texture region.
+
+
+
+
+
+ If [code]true[/code], the column [code]column[/code] is marked indeterminate.
+ [b]Note:[/b] If set [code]true[/code] from [code]false[/code], then column is cleared of checked status.
+
+
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 2c83fb2df6..8e41a07b79 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -219,6 +219,7 @@ void editor_register_and_generate_icons(Ref p_theme, bool p_dark_theme =
exceptions.insert("DefaultProjectIcon");
exceptions.insert("GuiChecked");
exceptions.insert("GuiRadioChecked");
+ exceptions.insert("GuiIndeterminate");
exceptions.insert("GuiCloseCustomizable");
exceptions.insert("GuiGraphNodePort");
exceptions.insert("GuiResizer");
@@ -812,6 +813,7 @@ Ref create_editor_theme(const Ref p_theme) {
// Tree
theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
+ theme->set_icon("indeterminate", "Tree", theme->get_icon("GuiIndeterminate", "EditorIcons"));
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("arrow", "Tree", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
theme->set_icon("arrow_collapsed", "Tree", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
diff --git a/editor/icons/GuiIndeterminate.svg b/editor/icons/GuiIndeterminate.svg
new file mode 100644
index 0000000000..79e5d95c9a
--- /dev/null
+++ b/editor/icons/GuiIndeterminate.svg
@@ -0,0 +1 @@
+
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 09db3205d9..d9892b53fc 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -167,6 +167,18 @@ TreeItem::TreeCellMode TreeItem::get_cell_mode(int p_column) const {
void TreeItem::set_checked(int p_column, bool p_checked) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].checked = p_checked;
+ cells.write[p_column].indeterminate = false;
+ _changed_notify(p_column);
+}
+
+void TreeItem::set_indeterminate(int p_column, bool p_indeterminate) {
+ ERR_FAIL_INDEX(p_column, cells.size());
+ // Prevent uncheck if indeterminate set to false twice
+ if (p_indeterminate == cells[p_column].indeterminate) {
+ return;
+ }
+ cells.write[p_column].indeterminate = p_indeterminate;
+ cells.write[p_column].checked = false;
_changed_notify(p_column);
}
@@ -175,6 +187,11 @@ bool TreeItem::is_checked(int p_column) const {
return cells[p_column].checked;
}
+bool TreeItem::is_indeterminate(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), false);
+ return cells[p_column].indeterminate;
+}
+
void TreeItem::set_text(int p_column, String p_text) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].text = p_text;
@@ -1042,7 +1059,9 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cell_mode", "column"), &TreeItem::get_cell_mode);
ClassDB::bind_method(D_METHOD("set_checked", "column", "checked"), &TreeItem::set_checked);
+ ClassDB::bind_method(D_METHOD("set_indeterminate", "column", "indeterminate"), &TreeItem::set_indeterminate);
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("set_text", "column", "text"), &TreeItem::set_text);
ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text);
@@ -1228,6 +1247,7 @@ void Tree::update_cache() {
cache.checked = get_theme_icon(SNAME("checked"));
cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ cache.indeterminate = get_theme_icon(SNAME("indeterminate"));
if (is_layout_rtl()) {
cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
} else {
@@ -1721,10 +1741,13 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
case TreeItem::CELL_MODE_CHECK: {
Ref checked = cache.checked;
Ref unchecked = cache.unchecked;
+ Ref indeterminate = cache.indeterminate;
Point2i check_ofs = item_rect.position;
check_ofs.y += Math::floor((real_t)(item_rect.size.y - checked->get_height()) / 2);
- if (p_item->cells[i].checked) {
+ if (p_item->cells[i].indeterminate) {
+ indeterminate->draw(ci, check_ofs);
+ } else if (p_item->cells[i].checked) {
checked->draw(ci, check_ofs);
} else {
unchecked->draw(ci, check_ofs);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index be711b4c4f..c207737cc0 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -82,6 +82,7 @@ private:
int icon_max_w = 0;
bool expr = false;
bool checked = false;
+ bool indeterminate = false;
bool editable = false;
bool selected = false;
bool selectable = true;
@@ -209,7 +210,9 @@ public:
/* check mode */
void set_checked(int p_column, bool p_checked);
+ void set_indeterminate(int p_column, bool p_indeterminate);
bool is_checked(int p_column) const;
+ bool is_indeterminate(int p_column) const;
void set_text(int p_column, String p_text);
String get_text(int p_column) const;
@@ -491,6 +494,7 @@ private:
Ref checked;
Ref unchecked;
+ Ref indeterminate;
Ref arrow_collapsed;
Ref arrow;
Ref select_arrow;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 8208c55801..5f70a31844 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -704,6 +704,7 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const
theme->set_icon("checked", "Tree", make_icon(checked_png));
theme->set_icon("unchecked", "Tree", make_icon(unchecked_png));
+ theme->set_icon("indeterminate", "Tree", make_icon(indeterminate_png));
theme->set_icon("updown", "Tree", make_icon(updown_png));
theme->set_icon("select_arrow", "Tree", make_icon(dropdown_png));
theme->set_icon("arrow", "Tree", make_icon(arrow_down_png));
diff --git a/scene/resources/default_theme/indeterminate.png b/scene/resources/default_theme/indeterminate.png
new file mode 100644
index 0000000000000000000000000000000000000000..28a457b251e5b76c21ec6d116d3d521e6ef6a37b
GIT binary patch
literal 242
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!S%6Q7E0Ff}jzmTl<_-!9DnMjm
z24twp$tlUpD+9SoO6tnW8mg*V|Ni}(;j23fs8gsU$S;_IT|FQzW6Q7KTYmkA0GaZ*
zdZ28ir;B5V#MIXF2Zb6GI9xBXi0~f$^?!cvoSa!(Uh189ns?gh3B$?l90w&G5>Dzq
zWMDhtn(fWKn6Wc2Tr1^4@!NpS^AFd3XRXiYNuPiCktI*io6FZ(HlN>X#js!z$DVI3
SR-tFnGH9xvX