diff options
author | crupest <crupest@outlook.com> | 2022-01-24 22:14:37 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-01-24 22:14:37 +0800 |
commit | 24e1dc8723aea1e46a3aa15794747f3fa52f8eca (patch) | |
tree | 0c879b38647307d25325eb8f9993a7f690fb46b2 | |
parent | 72402c09d45b696cd58a65b4a141a804e1cd9371 (diff) | |
download | cru-24e1dc8723aea1e46a3aa15794747f3fa52f8eca.tar.gz cru-24e1dc8723aea1e46a3aa15794747f3fa52f8eca.tar.bz2 cru-24e1dc8723aea1e46a3aa15794747f3fa52f8eca.zip |
...
-rw-r--r-- | assets/cru/ui/DefaultResources.xml | 97 | ||||
-rw-r--r-- | include/cru/common/io/FileStream.hpp | 8 | ||||
-rw-r--r-- | include/cru/ui/UiManager.hpp | 7 | ||||
-rw-r--r-- | include/cru/ui/mapper/style/ClickStateConditionMapper.hpp | 2 | ||||
-rw-r--r-- | include/cru/ui/mapper/style/HoverConditionMapper.hpp | 26 | ||||
-rw-r--r-- | include/cru/xml/XmlNode.hpp | 2 | ||||
-rw-r--r-- | src/common/io/Stream.cpp | 2 | ||||
-rw-r--r-- | src/ui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/ui/UiManager.cpp | 94 | ||||
-rw-r--r-- | src/ui/controls/Button.cpp | 5 | ||||
-rw-r--r-- | src/ui/controls/TextBox.cpp | 2 | ||||
-rw-r--r-- | src/ui/mapper/MapperRegistry.cpp | 41 | ||||
-rw-r--r-- | src/ui/mapper/style/CursorStylerMapper.cpp | 2 | ||||
-rw-r--r-- | src/ui/mapper/style/HoverConditionMapper.cpp | 23 | ||||
-rw-r--r-- | src/xml/XmlNode.cpp | 9 |
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_); |