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