diff options
author | crupest <crupest@outlook.com> | 2020-12-03 20:51:53 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-12-03 20:51:53 +0800 |
commit | 93a8bf8b967817031cd2798cdaedfa73f867dead (patch) | |
tree | 0e1a2a72ad0e07c0f670a6feb87f211929788f0e | |
parent | c6baeb6432a4db7433aab4fc8f89cc235473f11a (diff) | |
download | cru-93a8bf8b967817031cd2798cdaedfa73f867dead.tar.gz cru-93a8bf8b967817031cd2798cdaedfa73f867dead.tar.bz2 cru-93a8bf8b967817031cd2798cdaedfa73f867dead.zip |
...
-rw-r--r-- | include/cru/common/ClonablePtr.hpp | 201 | ||||
-rw-r--r-- | include/cru/ui/style/Condition.hpp | 33 | ||||
-rw-r--r-- | include/cru/ui/style/StyleRule.hpp | 32 | ||||
-rw-r--r-- | include/cru/ui/style/StyleRuleSet.hpp | 0 | ||||
-rw-r--r-- | include/cru/ui/style/Styler.hpp | 6 | ||||
-rw-r--r-- | src/ui/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/ui/style/Condition.cpp | 22 | ||||
-rw-r--r-- | src/ui/style/StyleRule.cpp | 6 | ||||
-rw-r--r-- | src/ui/style/StyleRuleSet.cpp | 0 |
9 files changed, 238 insertions, 64 deletions
diff --git a/include/cru/common/ClonablePtr.hpp b/include/cru/common/ClonablePtr.hpp new file mode 100644 index 00000000..47a1d3bd --- /dev/null +++ b/include/cru/common/ClonablePtr.hpp @@ -0,0 +1,201 @@ +#pragma once + +#include <cstddef> +#include <functional> +#include <memory> +#include <type_traits> + +namespace cru { +template <typename TClonable> +class ClonablePtr { + public: + using element_type = typename std::unique_ptr<TClonable>::element_type; + using pointer = typename std::unique_ptr<TClonable>::pointer; + + ClonablePtr() = default; + ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} + ClonablePtr(pointer p) noexcept : ptr_(p) {} + ClonablePtr(std::unique_ptr<element_type>&& p) noexcept + : ptr_(std::move(p)) {} + template <typename O, + std::enable_if_t<std::is_convertible_v< + typename ClonablePtr<O>::pointer, pointer>, + int> = 0> + ClonablePtr(std::unique_ptr<O>&& p) : ptr_(std::move(p)) {} + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + ClonablePtr(ClonablePtr&& other) = default; + template <typename O, + std::enable_if_t<std::is_convertible_v< + typename ClonablePtr<O>::pointer, pointer>, + int> = 0> + ClonablePtr(const ClonablePtr<O>& other) : ptr_(other.ptr_->Clone()) {} + template <typename O, + std::enable_if_t<std::is_convertible_v< + typename ClonablePtr<O>::pointer, pointer>, + int> = 0> + ClonablePtr(ClonablePtr<O>&& other) noexcept : ptr_(std::move(other.ptr_)) {} + ClonablePtr& operator=(std::nullptr_t) noexcept { + ptr_ = nullptr; + return *this; + } + ClonablePtr& operator=(std::unique_ptr<element_type>&& other) noexcept { + ptr_ = std::move(other); + return *this; + } + template <typename O, + std::enable_if_t<std::is_convertible_v< + typename ClonablePtr<O>::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(std::unique_ptr<O>&& p) noexcept { + ptr_ = std::move(p); + return *this; + } + ClonablePtr& operator=(const ClonablePtr& other) { + if (this != &other) { + ptr_ = std::unique_ptr<element_type>(other.ptr->Clone()); + } + return *this; + } + ClonablePtr& operator=(ClonablePtr&& other) = default; + template <typename O, + std::enable_if_t<std::is_convertible_v< + typename ClonablePtr<O>::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(const ClonablePtr<O>& other) noexcept { + if (this != &other) { + ptr_ = std::unique_ptr<element_type>(other.ptr_->Clone()); + } + return *this; + } + template <typename O, + std::enable_if_t<std::is_convertible_v< + typename ClonablePtr<O>::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(ClonablePtr<O>&& other) noexcept { + ptr_ = std::move(other.ptr_); + } + + ~ClonablePtr() = default; + + public: + pointer release() noexcept { return ptr_.release(); } + void reset(pointer p = pointer()) noexcept { ptr_.reset(p); } + void swap(ClonablePtr& other) noexcept { ptr_.swap(other.ptr_); } + + public: + pointer get() const noexcept { return ptr_.get(); } + + operator bool() const noexcept { return ptr_; } + + element_type& operator*() const noexcept { return *ptr_; } + pointer operator->() const noexcept { return ptr_.get(); } + + private: + std::unique_ptr<element_type> ptr_; +}; + +template <typename T> +void swap(ClonablePtr<T>& left, ClonablePtr<T>& right) noexcept { + left.swap(right); +} + +template <typename T> +bool operator==(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { + return left.get() == right.get(); +} + +template <typename T> +bool operator!=(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { + return left.get() != right.get(); +} + +template <typename T> +bool operator<(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { + return left.get() < right.get(); +} + +template <typename T> +bool operator<=(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { + return left.get() <= right.get(); +} + +template <typename T> +bool operator>(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { + return left.get() > right.get(); +} + +template <typename T> +bool operator>=(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { + return left.get() >= right.get(); +} + +template <typename T> +bool operator==(const ClonablePtr<T>& left, std::nullptr_t) { + return left.get() == nullptr; +} + +template <typename T> +bool operator!=(const ClonablePtr<T>& left, std::nullptr_t) { + return left.get() != nullptr; +} + +template <typename T> +bool operator<(const ClonablePtr<T>& left, std::nullptr_t) { + return left.get() < nullptr; +} + +template <typename T> +bool operator<=(const ClonablePtr<T>& left, std::nullptr_t) { + return left.get() <= nullptr; +} + +template <typename T> +bool operator>(const ClonablePtr<T>& left, std::nullptr_t) { + return left.get() > nullptr; +} + +template <typename T> +bool operator>=(const ClonablePtr<T>& left, std::nullptr_t) { + return left.get() >= nullptr; +} + +template <typename T> +bool operator==(std::nullptr_t, const ClonablePtr<T>& right) { + return nullptr == right.get(); +} + +template <typename T> +bool operator!=(std::nullptr_t, const ClonablePtr<T>& right) { + return nullptr != right.get(); +} + +template <typename T> +bool operator<(std::nullptr_t, const ClonablePtr<T>& right) { + return nullptr < right.get(); +} + +template <typename T> +bool operator<=(std::nullptr_t, const ClonablePtr<T>& right) { + return nullptr <= right.get(); +} + +template <typename T> +bool operator>(std::nullptr_t, const ClonablePtr<T>& right) { + return nullptr > right.get(); +} + +template <typename T> +bool operator>=(std::nullptr_t, const ClonablePtr<T>& right) { + return nullptr >= right.get(); +} + +} // namespace cru + +namespace std { +template <typename T> +struct hash<cru::ClonablePtr<T>> { + std::size_t operator()(const cru::ClonablePtr<T>& p) const { + return std::hash<typename cru::ClonablePtr<T>::pointer>(p.get()); + } +}; +} // namespace std diff --git a/include/cru/ui/style/Condition.hpp b/include/cru/ui/style/Condition.hpp index c4fd2106..13ab7764 100644 --- a/include/cru/ui/style/Condition.hpp +++ b/include/cru/ui/style/Condition.hpp @@ -1,6 +1,7 @@ #pragma once #include "../Base.hpp" #include "cru/common/Base.hpp" +#include "cru/common/ClonablePtr.hpp" #include "cru/common/Event.hpp" #include "cru/ui/controls/IClickableControl.hpp" #include "cru/ui/helper/ClickDetector.hpp" @@ -17,25 +18,17 @@ class Condition : public Object { controls::Control* control) const = 0; virtual bool Judge(controls::Control* control) const = 0; - virtual std::unique_ptr<Condition> Clone() const = 0; + virtual Condition* Clone() const = 0; }; class CompoundCondition : public Condition { public: - explicit CompoundCondition( - std::vector<std::unique_ptr<Condition>> conditions); - - const std::vector<Condition*>& GetConditions() const { - return readonly_conditions_; - } - - std::vector<std::unique_ptr<Condition>> CloneConditions() const; + explicit CompoundCondition(std::vector<ClonablePtr<Condition>> conditions); std::vector<IBaseEvent*> ChangeOn(controls::Control* control) const override; - private: - std::vector<std::unique_ptr<Condition>> conditions_; - std::vector<Condition*> readonly_conditions_; + protected: + std::vector<ClonablePtr<Condition>> conditions_; }; class AndCondition : public CompoundCondition { @@ -44,9 +37,7 @@ class AndCondition : public CompoundCondition { bool Judge(controls::Control* control) const override; - std::unique_ptr<Condition> Clone() const override { - return std::make_unique<AndCondition>(CloneConditions()); - } + AndCondition* Clone() const override { return new AndCondition(conditions_); } }; class OrCondition : public CompoundCondition { @@ -55,9 +46,7 @@ class OrCondition : public CompoundCondition { bool Judge(controls::Control* control) const override; - std::unique_ptr<Condition> Clone() const override { - return std::make_unique<OrCondition>(CloneConditions()); - } + OrCondition* Clone() const override { return new OrCondition(conditions_); } }; class FocusCondition : public Condition { @@ -67,8 +56,8 @@ class FocusCondition : public Condition { std::vector<IBaseEvent*> ChangeOn(controls::Control* control) const override; bool Judge(controls::Control* control) const override; - std::unique_ptr<Condition> Clone() const override { - return std::make_unique<FocusCondition>(has_focus_); + FocusCondition* Clone() const override { + return new FocusCondition(has_focus_); } private: @@ -82,8 +71,8 @@ class ClickStateCondition : public Condition { std::vector<IBaseEvent*> ChangeOn(controls::Control* control) const override; bool Judge(controls::Control* control) const override; - std::unique_ptr<Condition> Clone() const override { - return std::make_unique<ClickStateCondition>(click_state_); + ClickStateCondition* Clone() const override { + return new ClickStateCondition(click_state_); } private: diff --git a/include/cru/ui/style/StyleRule.hpp b/include/cru/ui/style/StyleRule.hpp index f1283e24..8ac42cd0 100644 --- a/include/cru/ui/style/StyleRule.hpp +++ b/include/cru/ui/style/StyleRule.hpp @@ -2,6 +2,7 @@ #include "Condition.hpp" #include "Styler.hpp" #include "cru/common/Base.hpp" +#include "cru/common/ClonablePtr.hpp" #include "cru/ui/Base.hpp" #include <memory> @@ -11,23 +12,10 @@ namespace cru::ui::style { class StyleRule : public Object { public: - StyleRule(std::unique_ptr<Condition> condition, - std::unique_ptr<Styler> styler, std::u16string name = {}); - - StyleRule(const StyleRule& other) - : condition_(other.condition_->Clone()), - styler_(other.styler_->Clone()), - name_(other.name_) {} - - StyleRule& operator=(const StyleRule& other) { - if (this != &other) { - condition_ = other.condition_->Clone(); - styler_ = other.styler_->Clone(); - name_ = other.name_; - } - return *this; - } + StyleRule(ClonablePtr<Condition> condition, ClonablePtr<Styler> styler, + std::u16string name = {}); + CRU_DEFAULT_COPY(StyleRule) CRU_DEFAULT_MOVE(StyleRule) ~StyleRule() override = default; @@ -37,21 +25,21 @@ class StyleRule : public Object { Condition* GetCondition() const { return condition_.get(); } Styler* GetStyler() const { return styler_.get(); } - StyleRule WithNewCondition(std::unique_ptr<Condition> condition, + StyleRule WithNewCondition(ClonablePtr<Condition> condition, std::u16string name = {}) const { - return StyleRule{std::move(condition), styler_->Clone(), std::move(name)}; + return StyleRule{std::move(condition), styler_, std::move(name)}; } - StyleRule WithNewStyler(std::unique_ptr<Styler> styler, + StyleRule WithNewStyler(ClonablePtr<Styler> styler, std::u16string name = {}) const { - return StyleRule{condition_->Clone(), std::move(styler), std::move(name)}; + return StyleRule{condition_, std::move(styler), std::move(name)}; } bool CheckAndApply(controls::Control* control) const; private: - std::unique_ptr<Condition> condition_; - std::unique_ptr<Styler> styler_; + ClonablePtr<Condition> condition_; + ClonablePtr<Styler> styler_; std::u16string name_; }; } // namespace cru::ui::style diff --git a/include/cru/ui/style/StyleRuleSet.hpp b/include/cru/ui/style/StyleRuleSet.hpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/include/cru/ui/style/StyleRuleSet.hpp diff --git a/include/cru/ui/style/Styler.hpp b/include/cru/ui/style/Styler.hpp index 4f4b18ba..2aece114 100644 --- a/include/cru/ui/style/Styler.hpp +++ b/include/cru/ui/style/Styler.hpp @@ -10,7 +10,7 @@ class Styler : public Object { public: virtual void Apply(controls::Control* control) const; - virtual std::unique_ptr<Styler> Clone() const = 0; + virtual Styler* Clone() const = 0; }; class BorderStyler : public Styler { @@ -19,9 +19,7 @@ class BorderStyler : public Styler { void Apply(controls::Control* control) const override; - std::unique_ptr<Styler> Clone() const override { - return std::make_unique<BorderStyler>(style_); - } + BorderStyler* Clone() const override { return new BorderStyler(style_); } private: ApplyBorderStyleInfo style_; diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index e61ed7de..4964a1ae 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -37,6 +37,7 @@ add_library(cru_ui STATIC style/Condition.cpp style/Styler.cpp style/StyleRule.cpp + style/StyleRuleSet.cpp ) target_sources(cru_ui PUBLIC ${CRU_UI_INCLUDE_DIR}/Base.hpp @@ -79,5 +80,6 @@ target_sources(cru_ui PUBLIC ${CRU_UI_INCLUDE_DIR}/style/Condition.hpp ${CRU_UI_INCLUDE_DIR}/style/Styler.hpp ${CRU_UI_INCLUDE_DIR}/style/StyleRule.hpp + ${CRU_UI_INCLUDE_DIR}/style/StyleRuleSet.hpp ) target_link_libraries(cru_ui PUBLIC cru_platform_gui) diff --git a/src/ui/style/Condition.cpp b/src/ui/style/Condition.cpp index 2b51bde3..891eb062 100644 --- a/src/ui/style/Condition.cpp +++ b/src/ui/style/Condition.cpp @@ -1,6 +1,7 @@ #include "cru/ui/style/Condition.hpp" #include <memory> +#include "cru/common/ClonablePtr.hpp" #include "cru/common/Event.hpp" #include "cru/ui/controls/Control.hpp" #include "cru/ui/controls/IClickableControl.hpp" @@ -8,16 +9,14 @@ namespace cru::ui::style { CompoundCondition::CompoundCondition( - std::vector<std::unique_ptr<Condition>> conditions) - : conditions_(std::move(conditions)) { - for (const auto& p : conditions_) readonly_conditions_.push_back(p.get()); -} + std::vector<ClonablePtr<Condition>> conditions) + : conditions_(std::move(conditions)) {} std::vector<IBaseEvent*> CompoundCondition::ChangeOn( controls::Control* control) const { std::vector<IBaseEvent*> result; - for (auto condition : GetConditions()) { + for (auto condition : conditions_) { for (auto e : condition->ChangeOn(control)) { result.push_back(e); } @@ -26,24 +25,15 @@ std::vector<IBaseEvent*> CompoundCondition::ChangeOn( return result; } -std::vector<std::unique_ptr<Condition>> CompoundCondition::CloneConditions() - const { - std::vector<std::unique_ptr<Condition>> result; - for (auto condition : GetConditions()) { - result.push_back(condition->Clone()); - } - return result; -} - bool AndCondition::Judge(controls::Control* control) const { - for (auto condition : GetConditions()) { + for (auto condition : conditions_) { if (!condition->Judge(control)) return false; } return true; } bool OrCondition::Judge(controls::Control* control) const { - for (auto condition : GetConditions()) { + for (auto condition : conditions_) { if (condition->Judge(control)) return true; } return false; diff --git a/src/ui/style/StyleRule.cpp b/src/ui/style/StyleRule.cpp index 4a5ecf7e..1a72a970 100644 --- a/src/ui/style/StyleRule.cpp +++ b/src/ui/style/StyleRule.cpp @@ -1,6 +1,12 @@ #include "cru/ui/style/StyleRule.hpp" namespace cru::ui::style { +StyleRule::StyleRule(ClonablePtr<Condition> condition, + ClonablePtr<Styler> styler, std::u16string name) + : condition_(std::move(condition)), + styler_(std::move(styler)), + name_(std::move(name)) {} + bool StyleRule::CheckAndApply(controls::Control *control) const { auto active = condition_->Judge(control); if (active) { diff --git a/src/ui/style/StyleRuleSet.cpp b/src/ui/style/StyleRuleSet.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/ui/style/StyleRuleSet.cpp |