aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-01-27 21:21:51 +0800
committercrupest <crupest@outlook.com>2022-01-27 21:21:51 +0800
commit560c0ead613658a2b7444907c3d1d69e49be8c32 (patch)
tree37938098f0e80403d572accf9f7a275ec8792c00
parent56633dab8c1bf9d25a6367a651b5b054055a2130 (diff)
downloadcru-560c0ead613658a2b7444907c3d1d69e49be8c32.tar.gz
cru-560c0ead613658a2b7444907c3d1d69e49be8c32.tar.bz2
cru-560c0ead613658a2b7444907c3d1d69e49be8c32.zip
...
-rw-r--r--CMakeLists.txt3
-rw-r--r--assets/cru/ui/DefaultResources.xml58
-rw-r--r--include/cru/ui/ThemeManager.hpp33
-rw-r--r--include/cru/ui/UiManager.hpp5
-rw-r--r--include/cru/ui/controls/Control.hpp4
-rw-r--r--include/cru/ui/mapper/Mapper.hpp4
-rw-r--r--include/cru/ui/style/StyleRuleSet.hpp13
-rw-r--r--src/ui/ThemeManager.cpp87
-rw-r--r--src/ui/UiManager.cpp46
-rw-r--r--src/ui/components/Menu.cpp3
-rw-r--r--src/ui/controls/Button.cpp5
-rw-r--r--src/ui/controls/Control.cpp8
-rw-r--r--src/ui/controls/TextBox.cpp5
-rw-r--r--src/ui/mapper/ColorMapper.cpp13
-rw-r--r--src/ui/mapper/MapperRegistry.cpp2
-rw-r--r--src/ui/render/ScrollBar.cpp11
-rw-r--r--src/ui/style/StyleRuleSet.cpp34
17 files changed, 196 insertions, 138 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4040df29..6d07ecdd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,7 +34,8 @@ function(target_add_resources target res_dir)
target_sources(${target} PUBLIC ${RES_SOURCES})
foreach (RES_FILE ${RES_SOURCES})
file(RELATIVE_PATH RES_PATH ${CRU_ASSETS_DIR} ${RES_FILE})
- set_property(SOURCE ${RES_FILE} PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${RES_PATH}/..")
+ cmake_path(GET RES_PATH PARENT_PATH RES_PATH)
+ set_property(SOURCE ${RES_FILE} PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${RES_PATH}")
endforeach(RES_FILE)
endfunction()
diff --git a/assets/cru/ui/DefaultResources.xml b/assets/cru/ui/DefaultResources.xml
index b831be2c..68b7a31a 100644
--- a/assets/cru/ui/DefaultResources.xml
+++ b/assets/cru/ui/DefaultResources.xml
@@ -1,9 +1,57 @@
<Theme>
<Resource key="scrollbar.collapse-thumb.color">
- <Color value="gray" />
+ <Color value="gray" alpha="0.5" />
+ </Resource>
+ <Resource key="scrollbar.arrow.normal.color">
+ <Color value="#505050" />
+ </Resource>
+ <Resource key="scrollbar.arrow.hover.color">
+ <Color value="#505050" />
+ </Resource>
+ <Resource key="scrollbar.arrow.press.color">
+ <Color value="#ffffff" />
+ </Resource>
+ <Resource key="scrollbar.arrow.disable.color">
+ <Color value="#a3a3a3" />
+ </Resource>
+ <Resource key="scrollbar.arrow-background.normal.color">
+ <Color value="#f1f1f1" />
+ </Resource>
+ <Resource key="scrollbar.arrow-background.hover.color">
+ <Color value="#d2d2d2" />
+ </Resource>
+ <Resource key="scrollbar.arrow-background.press.color">
+ <Color value="#787878" />
+ </Resource>
+ <Resource key="scrollbar.arrow-background.disable.color">
+ <Color value="#f1f1f1" />
+ </Resource>
+ <Resource key="scrollbar.slot.normal.color">
+ <Color value="#f1f1f1" />
+ </Resource>
+ <Resource key="scrollbar.slot.hover.color">
+ <Color value="#f1f1f1" />
+ </Resource>
+ <Resource key="scrollbar.slot.press.color">
+ <Color value="#f1f1f1" />
+ </Resource>
+ <Resource key="scrollbar.slot.disable.color">
+ <Color value="#f1f1f1" />
+ </Resource>
+ <Resource key="scrollbar.thumb.normal.color">
+ <Color value="#c1c1c1" />
+ </Resource>
+ <Resource key="scrollbar.thumb.hover.color">
+ <Color value="#a8a8a8" />
+ </Resource>
+ <Resource key="scrollbar.thumb.press.color">
+ <Color value="#787878" />
+ </Resource>
+ <Resource key="scrollbar.thumb.disable.color">
+ <Color value="#c1c1c1" />
</Resource>
- <Resource key="button-style">
+ <Resource key="button.style">
<StyleRuleSet>
<StyleRule>
<NoCondition />
@@ -61,7 +109,7 @@
</StyleRuleSet>
</Resource>
- <Resource key="text-box-style">
+ <Resource key="textbox.style">
<StyleRuleSet>
<StyleRule>
<NoCondition />
@@ -98,4 +146,8 @@
</StyleRule>
</StyleRuleSet>
</Resource>
+
+ <Resource key="menuitem.style">
+ <StyleRuleSet></StyleRuleSet>
+ </Resource>
</Theme>
diff --git a/include/cru/ui/ThemeManager.hpp b/include/cru/ui/ThemeManager.hpp
index 07b5f57b..7d52fa48 100644
--- a/include/cru/ui/ThemeManager.hpp
+++ b/include/cru/ui/ThemeManager.hpp
@@ -4,6 +4,9 @@
#include "cru/common/Event.hpp"
#include "cru/common/Exception.hpp"
#include "cru/platform/graphics/Brush.hpp"
+#include "cru/ui/mapper/MapperRegistry.hpp"
+#include "cru/ui/style/StyleRuleSet.hpp"
+#include "cru/xml/XmlNode.hpp"
#include <unordered_map>
@@ -29,22 +32,36 @@ class CRU_UI_API ThemeManager : public Object {
CRU_DELETE_COPY(ThemeManager)
CRU_DELETE_MOVE(ThemeManager)
- ~ThemeManager() override = default;
+ ~ThemeManager() override;
IEvent<std::nullptr_t>* ThemeResourceChangeEvent() {
return &theme_resource_change_event_;
}
- gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> GetBrush(
- StringView key);
+ void ReadResourcesFile(const String& file_path);
- private:
- void Init();
+ template <typename T>
+ T GetResource(const String& key) {
+ auto find_result = theme_resource_map_.find(key);
+ if (find_result == theme_resource_map_.cend()) {
+ throw ThemeResourceKeyNotExistException(
+ Format(u"Theme resource key \"%s\" not exist.", key));
+ }
+
+ auto mapper_registry = mapper::MapperRegistry::GetInstance();
+ auto mapper = mapper_registry->GetMapper<T>();
+ return mapper->MapFromXml(find_result->second);
+ }
+
+ std::shared_ptr<platform::graphics::IBrush> GetResourceBrush(
+ const String& key);
+
+ std::shared_ptr<style::StyleRuleSet> GetResourceStyleRuleSet(
+ const String& key);
private:
Event<std::nullptr_t> theme_resource_change_event_;
- std::unordered_map<String, String> theme_resource_map_;
- std::unordered_map<String, std::shared_ptr<platform::graphics::IBrush>>
- brushes_;
+ std::unique_ptr<xml::XmlElementNode> theme_resource_xml_root_;
+ std::unordered_map<String, xml::XmlElementNode*> theme_resource_map_;
};
} // namespace cru::ui
diff --git a/include/cru/ui/UiManager.hpp b/include/cru/ui/UiManager.hpp
index d16adc4f..9ac7f416 100644
--- a/include/cru/ui/UiManager.hpp
+++ b/include/cru/ui/UiManager.hpp
@@ -18,11 +18,6 @@ struct ThemeResources {
std::shared_ptr<platform::graphics::IBrush> text_brush;
std::shared_ptr<platform::graphics::IBrush> text_selection_brush;
std::shared_ptr<platform::graphics::IBrush> caret_brush;
-
- std::shared_ptr<style::StyleRuleSet> button_style;
- std::shared_ptr<style::StyleRuleSet> text_box_style;
-
- style::StyleRuleSet menu_item_style;
};
class CRU_UI_API UiManager : public Object {
diff --git a/include/cru/ui/controls/Control.hpp b/include/cru/ui/controls/Control.hpp
index ed6233a9..c51643be 100644
--- a/include/cru/ui/controls/Control.hpp
+++ b/include/cru/ui/controls/Control.hpp
@@ -67,7 +67,7 @@ class CRU_UI_API Control : public Object {
void SetCursor(std::shared_ptr<platform::gui::ICursor> cursor);
public:
- style::StyleRuleSet* GetStyleRuleSet();
+ std::shared_ptr<style::StyleRuleSet> GetStyleRuleSet();
//*************** region: events ***************
public:
@@ -151,7 +151,7 @@ class CRU_UI_API Control : public Object {
std::shared_ptr<platform::gui::ICursor> cursor_ = nullptr;
- std::unique_ptr<style::StyleRuleSet> style_rule_set_;
+ std::shared_ptr<style::StyleRuleSet> style_rule_set_;
std::unique_ptr<style::StyleRuleSetBind> style_rule_set_bind_;
};
} // namespace cru::ui::controls
diff --git a/include/cru/ui/mapper/Mapper.hpp b/include/cru/ui/mapper/Mapper.hpp
index ceda8e0f..c52bec70 100644
--- a/include/cru/ui/mapper/Mapper.hpp
+++ b/include/cru/ui/mapper/Mapper.hpp
@@ -69,11 +69,11 @@ class CRU_UI_API BasicMapper : public MapperBase {
T MapFromXml(xml::XmlElementNode* node) {
if (!SupportMapFromXml()) {
- throw new Exception(u"This mapper does not support map from xml.");
+ throw Exception(u"This mapper does not support map from xml.");
}
if (!XmlElementIsOfThisType(node)) {
- throw new Exception(u"This xml element is not of mapping type.");
+ throw Exception(u"This xml element is not of mapping type.");
}
return DoMapFromXml(node);
diff --git a/include/cru/ui/style/StyleRuleSet.hpp b/include/cru/ui/style/StyleRuleSet.hpp
index b3c4f683..32b02d78 100644
--- a/include/cru/ui/style/StyleRuleSet.hpp
+++ b/include/cru/ui/style/StyleRuleSet.hpp
@@ -9,7 +9,7 @@ namespace cru::ui::style {
class StyleRuleSet : public Object {
public:
StyleRuleSet() = default;
- explicit StyleRuleSet(StyleRuleSet* parent);
+ explicit StyleRuleSet(std::shared_ptr<StyleRuleSet> parent);
CRU_DELETE_COPY(StyleRuleSet)
CRU_DELETE_MOVE(StyleRuleSet)
@@ -17,8 +17,8 @@ class StyleRuleSet : public Object {
~StyleRuleSet() override = default;
public:
- StyleRuleSet* GetParent() const { return parent_; }
- void SetParent(StyleRuleSet* parent);
+ std::shared_ptr<StyleRuleSet> GetParent() const { return parent_; }
+ void SetParent(std::shared_ptr<StyleRuleSet> parent);
gsl::index GetSize() const { return static_cast<gsl::index>(rules_.size()); }
const std::vector<StyleRule>& GetRules() const { return rules_; }
@@ -47,7 +47,7 @@ class StyleRuleSet : public Object {
private:
Event<std::nullptr_t> change_event_;
- StyleRuleSet* parent_ = nullptr;
+ std::shared_ptr<StyleRuleSet> parent_ = nullptr;
EventRevokerGuard parent_change_event_guard_;
std::vector<StyleRule> rules_;
@@ -55,7 +55,8 @@ class StyleRuleSet : public Object {
class StyleRuleSetBind {
public:
- StyleRuleSetBind(controls::Control* control, StyleRuleSet* ruleset);
+ StyleRuleSetBind(controls::Control* control,
+ std::shared_ptr<StyleRuleSet> ruleset);
CRU_DELETE_COPY(StyleRuleSetBind)
CRU_DELETE_MOVE(StyleRuleSetBind)
@@ -69,7 +70,7 @@ class StyleRuleSetBind {
private:
controls::Control* control_;
- StyleRuleSet* ruleset_;
+ std::shared_ptr<StyleRuleSet> ruleset_;
// child first, parent last.
std::vector<StyleRuleSet*> ruleset_chain_cache_;
diff --git a/src/ui/ThemeManager.cpp b/src/ui/ThemeManager.cpp
index e26da3fb..4ed5c5b6 100644
--- a/src/ui/ThemeManager.cpp
+++ b/src/ui/ThemeManager.cpp
@@ -1,10 +1,15 @@
#include "cru/ui/ThemeManager.hpp"
+#include <memory>
#include "Helper.hpp"
#include "cru/common/StringUtil.hpp"
+#include "cru/common/io/FileStream.hpp"
+#include "cru/common/io/Resource.hpp"
#include "cru/platform/graphics/Brush.hpp"
#include "cru/platform/graphics/Factory.hpp"
#include "cru/platform/gui/UiApplication.hpp"
+#include "cru/ui/style/StyleRuleSet.hpp"
+#include "cru/xml/XmlParser.hpp"
namespace cru::ui {
ThemeManager* ThemeManager::GetInstance() {
@@ -12,52 +17,52 @@ ThemeManager* ThemeManager::GetInstance() {
return &instance;
}
-ThemeManager::ThemeManager() { Init(); }
-
-void ThemeManager::Init() {
- theme_resource_map_.emplace(u"scrollbar.collapse-thumb.color",
- colors::gray.WithAlpha(128).ToString());
- theme_resource_map_.emplace(u"scrollbar.arrow.normal.color", u"#505050");
- theme_resource_map_.emplace(u"scrollbar.arrow.hover.color", u"#505050");
- theme_resource_map_.emplace(u"scrollbar.arrow.press.color", u"#ffffff");
- theme_resource_map_.emplace(u"scrollbar.arrow.disable.color", u"#a3a3a3");
- theme_resource_map_.emplace(u"scrollbar.arrow-background.normal.color",
- u"#f1f1f1");
- theme_resource_map_.emplace(u"scrollbar.arrow-background.hover.color",
- u"#d2d2d2");
- theme_resource_map_.emplace(u"scrollbar.arrow-background.press.color",
- u"#787878");
- theme_resource_map_.emplace(u"scrollbar.arrow-background.disable.color",
- u"#f1f1f1");
- theme_resource_map_.emplace(u"scrollbar.slot.normal.color", u"#f1f1f1");
- theme_resource_map_.emplace(u"scrollbar.slot.hover.color", u"#f1f1f1");
- theme_resource_map_.emplace(u"scrollbar.slot.press.color", u"#f1f1f1");
- theme_resource_map_.emplace(u"scrollbar.slot.disable.color", u"#f1f1f1");
- theme_resource_map_.emplace(u"scrollbar.thumb.normal.color", u"#c1c1c1");
- theme_resource_map_.emplace(u"scrollbar.thumb.hover.color", u"#a8a8a8");
- theme_resource_map_.emplace(u"scrollbar.thumb.press.color", u"#787878");
- theme_resource_map_.emplace(u"scrollbar.thumb.disable.color", u"#c1c1c1");
-}
+ThemeManager::ThemeManager() {
+ std::filesystem::path resourses_file =
+ cru::io::GetResourceDir() / "cru/ui/DefaultResources.xml";
-gsl::not_null<std::shared_ptr<platform::graphics::IBrush>>
-ThemeManager::GetBrush(StringView key) {
- auto k = key.ToString();
- auto cached_brush_iter = brushes_.find(k);
- if (cached_brush_iter != brushes_.cend()) {
- return cached_brush_iter->second;
+ if (!std::filesystem::exists(resourses_file)) {
+ throw Exception(u"Default resources file not found.");
}
- auto color_string_iter = theme_resource_map_.find(k);
- if (color_string_iter == theme_resource_map_.cend()) {
- throw ThemeResourceKeyNotExistException(u"Key do not exist.");
+ ReadResourcesFile(String::FromStdPath(resourses_file));
+}
+
+ThemeManager::~ThemeManager() {}
+
+std::shared_ptr<platform::graphics::IBrush> ThemeManager::GetResourceBrush(
+ const String& key) {
+ return GetResource<std::shared_ptr<platform::graphics::IBrush>>(key);
+}
+
+std::shared_ptr<style::StyleRuleSet> ThemeManager::GetResourceStyleRuleSet(
+ const String& key) {
+ return GetResource<std::shared_ptr<style::StyleRuleSet>>(key);
+}
+
+void ThemeManager::ReadResourcesFile(const String& file_path) {
+ io::FileStream stream(file_path, io::OpenFileFlags::Read);
+ auto xml_string = stream.ReadAllAsString();
+ auto parser = xml::XmlParser(xml_string);
+ theme_resource_xml_root_.reset(parser.Parse());
+ theme_resource_map_.clear();
+
+ if (!theme_resource_xml_root_->GetTag().CaseInsensitiveEqual(u"Theme")) {
+ throw Exception(u"Root tag of theme resource file must be \"Theme\".");
}
- auto color = Color::Parse(color_string_iter->second);
- if (!color) throw BadThemeResourceException(u"Value is not a valid color.");
- std::shared_ptr<platform::graphics::IBrush> brush =
- GetUiApplication()->GetGraphicsFactory()->CreateSolidColorBrush(*color);
- brushes_[k] = brush;
- return brush;
+ for (auto child : theme_resource_xml_root_->GetChildren()) {
+ if (child->IsElementNode()) {
+ auto c = child->AsElement();
+ if (c->GetTag().CaseInsensitiveEqual(u"Resource")) {
+ auto key_attr = c->GetOptionalAttributeCaseInsensitive(u"key");
+ if (!key_attr) {
+ throw Exception(u"\"key\" attribute is required for resource.");
+ }
+ theme_resource_map_[*key_attr] = c->GetFirstChildElement();
+ }
+ }
+ }
}
} // namespace cru::ui
diff --git a/src/ui/UiManager.cpp b/src/ui/UiManager.cpp
index 62dce6a7..0c8f258d 100644
--- a/src/ui/UiManager.cpp
+++ b/src/ui/UiManager.cpp
@@ -1,9 +1,6 @@
#include "cru/ui/UiManager.hpp"
#include "Helper.hpp"
-#include "cru/common/io/FileStream.hpp"
-#include "cru/common/io/OpenFileFlag.hpp"
-#include "cru/common/io/Resource.hpp"
#include "cru/platform/graphics/Brush.hpp"
#include "cru/platform/graphics/Factory.hpp"
#include "cru/platform/graphics/Font.hpp"
@@ -38,15 +35,6 @@ UiManager* UiManager::GetInstance() {
UiManager::UiManager() {
const auto factory = GetGraphicsFactory();
- std::filesystem::path resourses_file =
- cru::io::GetResourceDir() / "cru/ui/DefaultResources.xml";
-
- if (!std::filesystem::exists(resourses_file)) {
- throw Exception(u"Default resources file not found.");
- }
-
- ReadResourcesFile(String::FromStdPath(resourses_file));
-
theme_resource_.default_font_family = u"";
theme_resource_.default_font =
@@ -59,42 +47,8 @@ UiManager::UiManager() {
theme_resource_.text_selection_brush =
factory->CreateSolidColorBrush(colors::skyblue);
theme_resource_.caret_brush = black_brush;
-
- theme_resource_.menu_item_style.AddStyleRule(
- {NoCondition::Create(),
- BorderStyler::Create(
- ApplyBorderStyleInfo{std::nullopt, Thickness{0}, CornerRadius{0}}),
- u"DefaultMenuItem"});
}
UiManager::~UiManager() = default;
-void UiManager::ReadResourcesFile(const String& file_path) {
- io::FileStream stream(file_path, io::OpenFileFlags::Read);
- auto xml_string = stream.ReadAllAsString();
- auto parser = xml::XmlParser(xml_string);
- auto xml_root = parser.Parse();
-
- for (auto child : xml_root->GetChildren()) {
- if (child->GetType() == xml::XmlNode::Type::Element) {
- auto c = child->AsElement();
- if (c->GetTag().CaseInsensitiveEqual(u"Resource")) {
- auto key = c->GetAttributeCaseInsensitive(u"key");
- if (key.CaseInsensitiveEqual(u"button-style")) {
- auto style_rule_set_mapper = mapper::MapperRegistry::GetInstance()
- ->GetRefMapper<StyleRuleSet>();
- auto style_rule_set =
- style_rule_set_mapper->MapFromXml(c->GetFirstChildElement());
- theme_resource_.button_style = style_rule_set;
- } else if (key.CaseInsensitiveEqual(u"text-box-style")) {
- auto style_rule_set_mapper = mapper::MapperRegistry::GetInstance()
- ->GetRefMapper<StyleRuleSet>();
- auto style_rule_set =
- style_rule_set_mapper->MapFromXml(c->GetFirstChildElement());
- theme_resource_.text_box_style = style_rule_set;
- }
- }
- }
- }
-}
} // namespace cru::ui
diff --git a/src/ui/components/Menu.cpp b/src/ui/components/Menu.cpp
index 05324865..7405b23c 100644
--- a/src/ui/components/Menu.cpp
+++ b/src/ui/components/Menu.cpp
@@ -1,6 +1,7 @@
#include "cru/ui/components/Menu.hpp"
#include <functional>
#include "cru/platform/gui/Window.hpp"
+#include "cru/ui/ThemeManager.hpp"
#include "cru/ui/UiManager.hpp"
#include "cru/ui/controls/Button.hpp"
#include "cru/ui/controls/Control.hpp"
@@ -16,7 +17,7 @@ MenuItem::MenuItem() {
text_ = controls::TextBlock::Create();
container_->SetChild(text_);
container_->GetStyleRuleSet()->SetParent(
- &UiManager::GetInstance()->GetThemeResources()->menu_item_style);
+ ThemeManager::GetInstance()->GetResourceStyleRuleSet(u"menuitem.style"));
container_->ClickEvent()->AddHandler([this](const helper::ClickEventArgs&) {
if (this->on_click_) this->on_click_();
});
diff --git a/src/ui/controls/Button.cpp b/src/ui/controls/Button.cpp
index 0f122650..887bcae6 100644
--- a/src/ui/controls/Button.cpp
+++ b/src/ui/controls/Button.cpp
@@ -4,6 +4,7 @@
#include "cru/platform/graphics/Brush.hpp"
#include "cru/platform/gui/Cursor.hpp"
#include "cru/platform/gui/UiApplication.hpp"
+#include "cru/ui/ThemeManager.hpp"
#include "cru/ui/UiManager.hpp"
#include "cru/ui/helper/ClickDetector.hpp"
#include "cru/ui/render/BorderRenderObject.hpp"
@@ -16,8 +17,8 @@ Button::Button() : click_detector_(this) {
render_object_->SetBorderEnabled(true);
auto default_button_style =
- UiManager::GetInstance()->GetThemeResources()->button_style.get();
- GetStyleRuleSet()->SetParent(default_button_style);
+ ThemeManager::GetInstance()->GetResourceStyleRuleSet(u"button.style");
+ GetStyleRuleSet()->SetParent(std::move(default_button_style));
}
Button::~Button() = default;
diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp
index 44da7f6f..04199d1d 100644
--- a/src/ui/controls/Control.cpp
+++ b/src/ui/controls/Control.cpp
@@ -16,9 +16,9 @@ using platform::gui::IUiApplication;
using platform::gui::SystemCursorType;
Control::Control() {
- style_rule_set_ = std::make_unique<style::StyleRuleSet>();
+ style_rule_set_ = std::make_shared<style::StyleRuleSet>();
style_rule_set_bind_ =
- std::make_unique<style::StyleRuleSetBind>(this, style_rule_set_.get());
+ std::make_unique<style::StyleRuleSetBind>(this, style_rule_set_);
MouseEnterEvent()->Direct()->AddHandler([this](events::MouseEventArgs&) {
this->is_mouse_over_ = true;
@@ -99,8 +99,8 @@ void Control::SetCursor(std::shared_ptr<ICursor> cursor) {
}
}
-style::StyleRuleSet* Control::GetStyleRuleSet() {
- return style_rule_set_.get();
+std::shared_ptr<style::StyleRuleSet> Control::GetStyleRuleSet() {
+ return style_rule_set_;
}
void Control::AddChild(Control* control, const Index position) {
diff --git a/src/ui/controls/TextBox.cpp b/src/ui/controls/TextBox.cpp
index bf72b494..20e89028 100644
--- a/src/ui/controls/TextBox.cpp
+++ b/src/ui/controls/TextBox.cpp
@@ -1,5 +1,6 @@
#include "cru/ui/controls/TextBox.hpp"
+#include "cru/ui/ThemeManager.hpp"
#include "cru/ui/UiManager.hpp"
#include "cru/ui/render/BorderRenderObject.hpp"
#include "cru/ui/render/CanvasRenderObject.hpp"
@@ -16,6 +17,7 @@ TextBox::TextBox()
: border_render_object_(new BorderRenderObject()),
scroll_render_object_(new ScrollRenderObject()) {
const auto theme_resources = UiManager::GetInstance()->GetThemeResources();
+ auto theme_manager = ThemeManager::GetInstance();
text_render_object_ = std::make_unique<TextRenderObject>(
theme_resources->text_brush, theme_resources->default_font,
@@ -37,7 +39,8 @@ TextBox::TextBox()
border_render_object_->SetBorderEnabled(true);
- GetStyleRuleSet()->SetParent(theme_resources->text_box_style.get());
+ GetStyleRuleSet()->SetParent(
+ theme_manager->GetResourceStyleRuleSet(u"textbox.style"));
}
TextBox::~TextBox() {}
diff --git a/src/ui/mapper/ColorMapper.cpp b/src/ui/mapper/ColorMapper.cpp
index ddfa6b9b..063b2359 100644
--- a/src/ui/mapper/ColorMapper.cpp
+++ b/src/ui/mapper/ColorMapper.cpp
@@ -15,9 +15,16 @@ Color ColorMapper::DoMapFromString(String str) {
Color ColorMapper::DoMapFromXml(xml::XmlElementNode* node) {
auto value_attr = node->GetOptionalAttributeCaseInsensitive(u"value");
- if (!value_attr) {
- return colors::transparent;
+ Color result = colors::transparent;
+ if (value_attr) {
+ result = DoMapFromString(*value_attr);
}
- return DoMapFromString(*value_attr);
+
+ auto alpha_value_attr = node->GetOptionalAttributeCaseInsensitive(u"alpha");
+ if (alpha_value_attr) {
+ result.alpha = alpha_value_attr->ParseToDouble() * 255;
+ }
+
+ return result;
}
} // namespace cru::ui::mapper
diff --git a/src/ui/mapper/MapperRegistry.cpp b/src/ui/mapper/MapperRegistry.cpp
index a9c53129..97c5cf21 100644
--- a/src/ui/mapper/MapperRegistry.cpp
+++ b/src/ui/mapper/MapperRegistry.cpp
@@ -1,5 +1,6 @@
#include "cru/ui/mapper/MapperRegistry.hpp"
#include "cru/ui/mapper/BorderStyleMapper.hpp"
+#include "cru/ui/mapper/BrushMapper.hpp"
#include "cru/ui/mapper/ColorMapper.hpp"
#include "cru/ui/mapper/CornerRadiusMapper.hpp"
#include "cru/ui/mapper/CursorMapper.hpp"
@@ -26,6 +27,7 @@ MapperRegistry *MapperRegistry::GetInstance() {
MapperRegistry::MapperRegistry() {
using namespace style;
+ RegisterMapper(new BrushMapper());
RegisterMapper(new CornerRadiusMapper());
RegisterMapper(new PointMapper());
RegisterMapper(new SizeMapper());
diff --git a/src/ui/render/ScrollBar.cpp b/src/ui/render/ScrollBar.cpp
index 8e16862f..8676de61 100644
--- a/src/ui/render/ScrollBar.cpp
+++ b/src/ui/render/ScrollBar.cpp
@@ -264,9 +264,10 @@ void ScrollBar::InstallHandlers(controls::Control* control) {
gsl::not_null<std::shared_ptr<platform::graphics::IBrush>>
ScrollBar::GetCollapsedThumbBrush() {
- return collapsed_thumb_brush_ ? gsl::not_null(collapsed_thumb_brush_)
- : ThemeManager::GetInstance()->GetBrush(
- u"scrollbar.collapse-thumb.color");
+ return collapsed_thumb_brush_
+ ? gsl::not_null(collapsed_thumb_brush_)
+ : gsl::not_null(ThemeManager::GetInstance()->GetResourceBrush(
+ u"scrollbar.collapse-thumb.color"));
}
void ScrollBar::SetCollapsedThumbBrush(
@@ -280,8 +281,8 @@ gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> ScrollBar::GetBrush(
ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state) {
auto b = brushes_[usage][state];
return b ? gsl::not_null(b)
- : ThemeManager::GetInstance()->GetBrush(
- GenerateScrollBarThemeColorKey(usage, state));
+ : gsl::not_null(ThemeManager::GetInstance()->GetResourceBrush(
+ GenerateScrollBarThemeColorKey(usage, state)));
}
// Brush could be nullptr to use the theme brush.
diff --git a/src/ui/style/StyleRuleSet.cpp b/src/ui/style/StyleRuleSet.cpp
index 537d1956..88109350 100644
--- a/src/ui/style/StyleRuleSet.cpp
+++ b/src/ui/style/StyleRuleSet.cpp
@@ -6,12 +6,30 @@
#include <unordered_set>
namespace cru::ui::style {
-StyleRuleSet::StyleRuleSet(StyleRuleSet* parent) { SetParent(parent); }
+namespace {
+bool CheckCycle(StyleRuleSet* t, StyleRuleSet* p) {
+ while (p != nullptr) {
+ if (p == t) {
+ return true;
+ }
+ p = p->GetParent().get();
+ }
+
+ return false;
+}
+} // namespace
-void StyleRuleSet::SetParent(StyleRuleSet* parent) {
+StyleRuleSet::StyleRuleSet(std::shared_ptr<StyleRuleSet> parent) {
+ SetParent(std::move(parent));
+}
+
+void StyleRuleSet::SetParent(std::shared_ptr<StyleRuleSet> parent) {
if (parent == parent_) return;
+ if (CheckCycle(this, parent.get())) {
+ throw Exception(u"Cycle detected in StyleRuleSet parent.");
+ }
parent_change_event_guard_.Reset();
- parent_ = parent;
+ parent_ = std::move(parent);
if (parent != nullptr) {
parent_change_event_guard_.Reset(parent->ChangeEvent()->AddSpyOnlyHandler(
[this] { this->RaiseChangeEvent(); }));
@@ -44,12 +62,12 @@ void StyleRuleSet::Set(const StyleRuleSet& other, bool set_parent) {
}
StyleRuleSetBind::StyleRuleSetBind(controls::Control* control,
- StyleRuleSet* ruleset)
- : control_(control), ruleset_(ruleset) {
+ std::shared_ptr<StyleRuleSet> ruleset)
+ : control_(control), ruleset_(std::move(ruleset)) {
Expects(control);
- Expects(ruleset);
+ Expects(ruleset_);
- ruleset->ChangeEvent()->AddSpyOnlyHandler([this] {
+ ruleset_->ChangeEvent()->AddSpyOnlyHandler([this] {
UpdateRuleSetChainCache();
UpdateChangeListener();
UpdateStyle();
@@ -60,7 +78,7 @@ void StyleRuleSetBind::UpdateRuleSetChainCache() {
ruleset_chain_cache_.clear();
auto parent = ruleset_;
while (parent != nullptr) {
- ruleset_chain_cache_.push_back(parent);
+ ruleset_chain_cache_.push_back(parent.get());
parent = parent->GetParent();
}
}