aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-01-24 22:14:37 +0800
committercrupest <crupest@outlook.com>2022-01-24 22:14:37 +0800
commit24e1dc8723aea1e46a3aa15794747f3fa52f8eca (patch)
tree0c879b38647307d25325eb8f9993a7f690fb46b2
parent72402c09d45b696cd58a65b4a141a804e1cd9371 (diff)
downloadcru-24e1dc8723aea1e46a3aa15794747f3fa52f8eca.tar.gz
cru-24e1dc8723aea1e46a3aa15794747f3fa52f8eca.tar.bz2
cru-24e1dc8723aea1e46a3aa15794747f3fa52f8eca.zip
...
-rw-r--r--assets/cru/ui/DefaultResources.xml97
-rw-r--r--include/cru/common/io/FileStream.hpp8
-rw-r--r--include/cru/ui/UiManager.hpp7
-rw-r--r--include/cru/ui/mapper/style/ClickStateConditionMapper.hpp2
-rw-r--r--include/cru/ui/mapper/style/HoverConditionMapper.hpp26
-rw-r--r--include/cru/xml/XmlNode.hpp2
-rw-r--r--src/common/io/Stream.cpp2
-rw-r--r--src/ui/CMakeLists.txt1
-rw-r--r--src/ui/UiManager.cpp94
-rw-r--r--src/ui/controls/Button.cpp5
-rw-r--r--src/ui/controls/TextBox.cpp2
-rw-r--r--src/ui/mapper/MapperRegistry.cpp41
-rw-r--r--src/ui/mapper/style/CursorStylerMapper.cpp2
-rw-r--r--src/ui/mapper/style/HoverConditionMapper.cpp23
-rw-r--r--src/xml/XmlNode.cpp9
15 files changed, 236 insertions, 85 deletions
diff --git a/assets/cru/ui/DefaultResources.xml b/assets/cru/ui/DefaultResources.xml
new file mode 100644
index 00000000..fbe48182
--- /dev/null
+++ b/assets/cru/ui/DefaultResources.xml
@@ -0,0 +1,97 @@
+<Theme>
+ <Resource key="button-style">
+ <StyleRuleSet>
+ <StyleRule>
+ <NoCondition />
+ <BorderStyler>
+ <BorderStyle>
+ <Thickness value="5" />
+ <CornerRadius all="5" />
+ </BorderStyle>
+ </BorderStyler>
+ </StyleRule>
+ <StyleRule>
+ <ClickStateCondition value="none" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#00bfff" />
+ </BorderStyle>
+ </BorderStyler>
+ <CursorStyler>
+ <Cursor value="arrow" />
+ </CursorStyler>
+ </StyleRule>
+ <StyleRule>
+ <ClickStateCondition value="hover" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#47d1ff" />
+ </BorderStyle>
+ </BorderStyler>
+ <CursorStyler>
+ <Cursor value="hand" />
+ </CursorStyler>
+ </StyleRule>
+ <StyleRule>
+ <ClickStateCondition value="press" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#91e4ff" />
+ </BorderStyle>
+ </BorderStyler>
+ <CursorStyler>
+ <Cursor value="hand" />
+ </CursorStyler>
+ </StyleRule>
+ <StyleRule>
+ <ClickStateCondition value="pressinactive" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#91e4ff" />
+ </BorderStyle>
+ </BorderStyler>
+ <CursorStyler>
+ <Cursor value="arrow" />
+ </CursorStyler>
+ </StyleRule>
+ </StyleRuleSet>
+ </Resource>
+
+ <Resource key="text-box-style">
+ <StyleRuleSet>
+ <StyleRule>
+ <NoCondition />
+ <BorderStyler>
+ <BorderStyle>
+ <Thickness value="1" />
+ <CornerRadius all="5" />
+ </BorderStyle>
+ </BorderStyler>
+ </StyleRule>
+ <StyleRule>
+ <HoverCondition value="false" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#ced4da" />
+ </BorderStyle>
+ </BorderStyler>
+ </StyleRule>
+ <StyleRule>
+ <HoverCondition value="true" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#ced4da" />
+ </BorderStyle>
+ </BorderStyler>
+ </StyleRule>
+ <StyleRule>
+ <FocusCondition value="true" />
+ <BorderStyler>
+ <BorderStyle>
+ <Color value="#495057" />
+ </BorderStyle>
+ </BorderStyler>
+ </StyleRule>
+ </StyleRuleSet>
+ </Resource>
+</Theme>
diff --git a/include/cru/common/io/FileStream.hpp b/include/cru/common/io/FileStream.hpp
new file mode 100644
index 00000000..da7849cd
--- /dev/null
+++ b/include/cru/common/io/FileStream.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#ifdef CRU_PLATFORM_UNIX
+#include "UnixFileStream.hpp"
+namespace cru::io {
+using FileStream = UnixFileStream;
+}
+#endif
diff --git a/include/cru/ui/UiManager.hpp b/include/cru/ui/UiManager.hpp
index 4a2a7a77..d16adc4f 100644
--- a/include/cru/ui/UiManager.hpp
+++ b/include/cru/ui/UiManager.hpp
@@ -19,9 +19,8 @@ struct ThemeResources {
std::shared_ptr<platform::graphics::IBrush> text_selection_brush;
std::shared_ptr<platform::graphics::IBrush> caret_brush;
- style::StyleRuleSet button_style;
-
- style::StyleRuleSet text_box_style;
+ std::shared_ptr<style::StyleRuleSet> button_style;
+ std::shared_ptr<style::StyleRuleSet> text_box_style;
style::StyleRuleSet menu_item_style;
};
@@ -42,6 +41,8 @@ class CRU_UI_API UiManager : public Object {
ThemeResources* GetThemeResources() { return &theme_resource_; }
+ void ReadResourcesFile(const String& file_path);
+
private:
ThemeResources theme_resource_;
};
diff --git a/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp b/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp
index 2fea5353..63577641 100644
--- a/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp
+++ b/include/cru/ui/mapper/style/ClickStateConditionMapper.hpp
@@ -6,7 +6,7 @@
namespace cru::ui::mapper::style {
class CRU_UI_API ClickStateConditionMapper
: public BasicPtrMapper<ui::style::ClickStateCondition>,
- public IConditionMapper {
+ public virtual IConditionMapper {
public:
CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(ClickStateConditionMapper)
diff --git a/include/cru/ui/mapper/style/HoverConditionMapper.hpp b/include/cru/ui/mapper/style/HoverConditionMapper.hpp
new file mode 100644
index 00000000..bbd840f0
--- /dev/null
+++ b/include/cru/ui/mapper/style/HoverConditionMapper.hpp
@@ -0,0 +1,26 @@
+#pragma once
+#include "../Mapper.hpp"
+#include "IConditionMapper.hpp"
+#include "cru/ui/style/Condition.hpp"
+
+namespace cru::ui::mapper::style {
+class CRU_UI_API HoverConditionMapper
+ : public BasicPtrMapper<ui::style::HoverCondition>,
+ public virtual IConditionMapper {
+ public:
+ CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(HoverConditionMapper)
+
+ public:
+ bool SupportMapFromXml() override { return true; }
+ bool XmlElementIsOfThisType(xml::XmlElementNode* node) override;
+
+ ClonablePtr<ui::style::Condition> MapConditionFromXml(
+ xml::XmlElementNode* node) override {
+ return MapFromXml(node);
+ }
+
+ protected:
+ ClonablePtr<ui::style::HoverCondition> DoMapFromXml(
+ xml::XmlElementNode* node) override;
+};
+} // namespace cru::ui::mapper::style
diff --git a/include/cru/xml/XmlNode.hpp b/include/cru/xml/XmlNode.hpp
index c9e538c0..f308c9de 100644
--- a/include/cru/xml/XmlNode.hpp
+++ b/include/cru/xml/XmlNode.hpp
@@ -118,6 +118,8 @@ class CRU_XML_API XmlElementNode : public XmlNode {
void AddAttribute(String key, String value);
void AddChild(XmlNode* child);
+ XmlElementNode* GetFirstChildElement() const;
+
XmlNode* Clone() const override;
private:
diff --git a/src/common/io/Stream.cpp b/src/common/io/Stream.cpp
index bf102441..4f2953f9 100644
--- a/src/common/io/Stream.cpp
+++ b/src/common/io/Stream.cpp
@@ -7,7 +7,7 @@ Index Stream::GetSize() {
Index current_position = Tell();
Seek(0, SeekOrigin::End);
Index size = Tell();
- Seek(current_position);
+ Seek(current_position, SeekOrigin::Begin);
return size;
}
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 47197569..353695a4 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -40,6 +40,7 @@ add_library(cru_ui SHARED
mapper/style/ClickStateConditionMapper.cpp
mapper/style/CursorStylerMapper.cpp
mapper/style/FocusConditionMapper.cpp
+ mapper/style/HoverConditionMapper.cpp
mapper/style/NoConditionMapper.cpp
mapper/style/OrConditionMapper.cpp
mapper/style/StyleRuleMapper.cpp
diff --git a/src/ui/UiManager.cpp b/src/ui/UiManager.cpp
index 7f3d3b16..e374cc2e 100644
--- a/src/ui/UiManager.cpp
+++ b/src/ui/UiManager.cpp
@@ -1,6 +1,8 @@
#include "cru/ui/UiManager.hpp"
#include "Helper.hpp"
+#include "cru/common/io/FileStream.hpp"
+#include "cru/common/io/OpenFileFlag.hpp"
#include "cru/platform/graphics/Brush.hpp"
#include "cru/platform/graphics/Factory.hpp"
#include "cru/platform/graphics/Font.hpp"
@@ -8,10 +10,13 @@
#include "cru/platform/gui/UiApplication.hpp"
#include "cru/ui/Base.hpp"
#include "cru/ui/helper/ClickDetector.hpp"
+#include "cru/ui/mapper/MapperRegistry.hpp"
#include "cru/ui/render/ScrollBar.hpp"
#include "cru/ui/style/ApplyBorderStyleInfo.hpp"
#include "cru/ui/style/Condition.hpp"
#include "cru/ui/style/Styler.hpp"
+#include "cru/xml/XmlNode.hpp"
+#include "cru/xml/XmlParser.hpp"
#include <optional>
@@ -32,6 +37,10 @@ UiManager* UiManager::GetInstance() {
UiManager::UiManager() {
const auto factory = GetGraphicsFactory();
+ // TODO: Resource file path!!!
+ ReadResourcesFile(
+ u"/Users/crupest/codes/cru/assets/cru/ui/DefaultResources.xml");
+
theme_resource_.default_font_family = u"";
theme_resource_.default_font =
@@ -45,62 +54,6 @@ UiManager::UiManager() {
factory->CreateSolidColorBrush(colors::skyblue);
theme_resource_.caret_brush = black_brush;
- theme_resource_.button_style.AddStyleRule(
- {NoCondition::Create(),
- BorderStyler::Create(ApplyBorderStyleInfo{std::nullopt, Thickness(3),
- CornerRadius(5), std::nullopt,
- std::nullopt}),
- u"DefaultButton"});
- theme_resource_.button_style.AddStyleRule(
- {ClickStateCondition::Create(ClickState::None),
- CompoundStyler::Create(
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0x00bfff))}),
- CursorStyler::Create(platform::gui::SystemCursorType::Arrow)),
- u"DefaultButtonNormal"});
- theme_resource_.button_style.AddStyleRule(
- {ClickStateCondition::Create(ClickState::Hover),
- CompoundStyler::Create(
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0x47d1ff))}),
- CursorStyler::Create(platform::gui::SystemCursorType::Hand)),
- u"DefaultButtonHover"});
- theme_resource_.button_style.AddStyleRule(
- {ClickStateCondition::Create(ClickState::Press),
- CompoundStyler::Create(
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0x91e4ff))}),
- CursorStyler::Create(platform::gui::SystemCursorType::Hand)),
- u"DefaultButtonPress"});
- theme_resource_.button_style.AddStyleRule(
- {ClickStateCondition::Create(ClickState::PressInactive),
- CompoundStyler::Create(
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0x91e4ff))}),
- CursorStyler::Create(platform::gui::SystemCursorType::Arrow)),
- u"DefaultButtonPressInactive"});
-
- theme_resource_.text_box_style.AddStyleRule(
- {NoCondition::Create(),
- BorderStyler::Create(
- ApplyBorderStyleInfo{std::nullopt, Thickness{1}, CornerRadius{5}}),
- u"DefaultTextBox"});
- theme_resource_.text_box_style.AddStyleRule(
- {HoverCondition::Create(false),
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0xced4da))}),
- u"DefaultTextBoxNormal"});
- theme_resource_.text_box_style.AddStyleRule(
- {HoverCondition::Create(true),
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0xced4da))}),
- u"DefaultTextBoxHover"});
- theme_resource_.text_box_style.AddStyleRule(
- {FocusCondition::Create(true),
- BorderStyler::Create(ApplyBorderStyleInfo{
- factory->CreateSolidColorBrush(Color::FromHex(0x495057))}),
- u"DefaultTextBoxFocus"});
-
theme_resource_.menu_item_style.AddStyleRule(
{NoCondition::Create(),
BorderStyler::Create(
@@ -109,4 +62,33 @@ UiManager::UiManager() {
}
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/controls/Button.cpp b/src/ui/controls/Button.cpp
index c6480b77..0f122650 100644
--- a/src/ui/controls/Button.cpp
+++ b/src/ui/controls/Button.cpp
@@ -15,8 +15,9 @@ Button::Button() : click_detector_(this) {
SetContainerRenderObject(render_object_.get());
render_object_->SetBorderEnabled(true);
- GetStyleRuleSet()->SetParent(
- &UiManager::GetInstance()->GetThemeResources()->button_style);
+ auto default_button_style =
+ UiManager::GetInstance()->GetThemeResources()->button_style.get();
+ GetStyleRuleSet()->SetParent(default_button_style);
}
Button::~Button() = default;
diff --git a/src/ui/controls/TextBox.cpp b/src/ui/controls/TextBox.cpp
index 47706174..bf72b494 100644
--- a/src/ui/controls/TextBox.cpp
+++ b/src/ui/controls/TextBox.cpp
@@ -37,7 +37,7 @@ TextBox::TextBox()
border_render_object_->SetBorderEnabled(true);
- GetStyleRuleSet()->SetParent(&theme_resources->text_box_style);
+ GetStyleRuleSet()->SetParent(theme_resources->text_box_style.get());
}
TextBox::~TextBox() {}
diff --git a/src/ui/mapper/MapperRegistry.cpp b/src/ui/mapper/MapperRegistry.cpp
index d7131e33..a9c53129 100644
--- a/src/ui/mapper/MapperRegistry.cpp
+++ b/src/ui/mapper/MapperRegistry.cpp
@@ -11,6 +11,7 @@
#include "cru/ui/mapper/style/ClickStateConditionMapper.hpp"
#include "cru/ui/mapper/style/CursorStylerMapper.hpp"
#include "cru/ui/mapper/style/FocusConditionMapper.hpp"
+#include "cru/ui/mapper/style/HoverConditionMapper.hpp"
#include "cru/ui/mapper/style/NoConditionMapper.hpp"
#include "cru/ui/mapper/style/OrConditionMapper.hpp"
#include "cru/ui/mapper/style/StyleRuleMapper.hpp"
@@ -19,31 +20,31 @@
namespace cru::ui::mapper {
MapperRegistry *MapperRegistry::GetInstance() {
static MapperRegistry instance;
+ return &instance;
+}
+MapperRegistry::MapperRegistry() {
using namespace style;
- instance.RegisterMapper(new CornerRadiusMapper());
- instance.RegisterMapper(new PointMapper());
- instance.RegisterMapper(new SizeMapper());
- instance.RegisterMapper(new ThicknessMapper());
- instance.RegisterMapper(new BorderStyleMapper());
- instance.RegisterMapper(new ColorMapper());
- instance.RegisterMapper(new CursorMapper());
- instance.RegisterMapper(new AndConditionMapper());
- instance.RegisterMapper(new BorderStylerMapper());
- instance.RegisterMapper(new ClickStateConditionMapper());
- instance.RegisterMapper(new CursorStylerMapper());
- instance.RegisterMapper(new FocusConditionMapper());
- instance.RegisterMapper(new NoConditionMapper());
- instance.RegisterMapper(new OrConditionMapper());
- instance.RegisterMapper(new StyleRuleMapper());
- instance.RegisterMapper(new StyleRuleSetMapper());
-
- return &instance;
+ RegisterMapper(new CornerRadiusMapper());
+ RegisterMapper(new PointMapper());
+ RegisterMapper(new SizeMapper());
+ RegisterMapper(new ThicknessMapper());
+ RegisterMapper(new BorderStyleMapper());
+ RegisterMapper(new ColorMapper());
+ RegisterMapper(new CursorMapper());
+ RegisterMapper(new AndConditionMapper());
+ RegisterMapper(new BorderStylerMapper());
+ RegisterMapper(new ClickStateConditionMapper());
+ RegisterMapper(new CursorStylerMapper());
+ RegisterMapper(new FocusConditionMapper());
+ RegisterMapper(new HoverConditionMapper());
+ RegisterMapper(new NoConditionMapper());
+ RegisterMapper(new OrConditionMapper());
+ RegisterMapper(new StyleRuleMapper());
+ RegisterMapper(new StyleRuleSetMapper());
}
-MapperRegistry::MapperRegistry() {}
-
MapperRegistry::~MapperRegistry() {
for (auto mapper : mapper_list_) {
delete mapper;
diff --git a/src/ui/mapper/style/CursorStylerMapper.cpp b/src/ui/mapper/style/CursorStylerMapper.cpp
index 0b29c938..c63d451c 100644
--- a/src/ui/mapper/style/CursorStylerMapper.cpp
+++ b/src/ui/mapper/style/CursorStylerMapper.cpp
@@ -6,7 +6,7 @@
namespace cru::ui::mapper::style {
bool CursorStylerMapper::XmlElementIsOfThisType(xml::XmlElementNode* node) {
- return node->GetTag().CaseInsensitiveEqual(u"cursor");
+ return node->GetTag().CaseInsensitiveEqual(u"CursorStyler");
}
ClonablePtr<ui::style::CursorStyler> CursorStylerMapper::DoMapFromXml(
diff --git a/src/ui/mapper/style/HoverConditionMapper.cpp b/src/ui/mapper/style/HoverConditionMapper.cpp
new file mode 100644
index 00000000..b78c12e9
--- /dev/null
+++ b/src/ui/mapper/style/HoverConditionMapper.cpp
@@ -0,0 +1,23 @@
+#include "cru/ui/mapper/style/HoverConditionMapper.hpp"
+#include "cru/common/ClonablePtr.hpp"
+#include "cru/ui/style/Condition.hpp"
+
+namespace cru::ui::mapper::style {
+using namespace cru::ui::style;
+
+bool HoverConditionMapper::XmlElementIsOfThisType(xml::XmlElementNode* node) {
+ return node->GetTag().CaseInsensitiveEqual(u"HoverCondition");
+}
+
+ClonablePtr<HoverCondition> HoverConditionMapper::DoMapFromXml(
+ xml::XmlElementNode* node) {
+ auto value = node->GetAttributeCaseInsensitive(u"value");
+ if (value.CaseInsensitiveEqual(u"true")) {
+ return ui::style::HoverCondition::Create(true);
+ } else if (value.CaseInsensitiveEqual(u"false")) {
+ return ui::style::HoverCondition::Create(false);
+ } else {
+ throw Exception(u"Invalid value for HoverCondition: " + value);
+ }
+}
+} // namespace cru::ui::mapper::style
diff --git a/src/xml/XmlNode.cpp b/src/xml/XmlNode.cpp
index 5c6294c8..79847544 100644
--- a/src/xml/XmlNode.cpp
+++ b/src/xml/XmlNode.cpp
@@ -32,6 +32,15 @@ void XmlElementNode::AddChild(XmlNode* child) {
child->parent_ = this;
}
+XmlElementNode* XmlElementNode::GetFirstChildElement() const {
+ for (auto child : children_) {
+ if (child->GetType() == XmlNode::Type::Element) {
+ return child->AsElement();
+ }
+ }
+ return nullptr;
+}
+
XmlNode* XmlElementNode::Clone() const {
XmlElementNode* node = new XmlElementNode(tag_, attributes_);