aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/ClonablePtr.hpp201
-rw-r--r--include/cru/ui/style/Condition.hpp33
-rw-r--r--include/cru/ui/style/StyleRule.hpp32
-rw-r--r--include/cru/ui/style/StyleRuleSet.hpp0
-rw-r--r--include/cru/ui/style/Styler.hpp6
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/style/Condition.cpp22
-rw-r--r--src/ui/style/StyleRule.cpp6
-rw-r--r--src/ui/style/StyleRuleSet.cpp0
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