aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
parent56633dab8c1bf9d25a6367a651b5b054055a2130 (diff)
downloadcru-560c0ead613658a2b7444907c3d1d69e49be8c32.tar.gz
cru-560c0ead613658a2b7444907c3d1d69e49be8c32.tar.bz2
cru-560c0ead613658a2b7444907c3d1d69e49be8c32.zip
...
Diffstat (limited to 'src')
-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
10 files changed, 103 insertions, 111 deletions
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();
}
}