aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-03-13 18:51:19 +0800
committercrupest <crupest@outlook.com>2022-03-13 18:51:19 +0800
commit7320f082c4bce5939cfa7c9a23765249dac55d07 (patch)
treef51d8684d04c1d78e45f391be7965b618186231f
parent1d14ce416bb4e5651b956790b621308acf73b64c (diff)
downloadcru-7320f082c4bce5939cfa7c9a23765249dac55d07.tar.gz
cru-7320f082c4bce5939cfa7c9a23765249dac55d07.tar.bz2
cru-7320f082c4bce5939cfa7c9a23765249dac55d07.zip
...
-rw-r--r--include/cru/ui/model/IListChangeNotify.h47
-rw-r--r--include/cru/ui/style/StyleRuleSet.h12
-rw-r--r--src/theme_builder/components/StyleRuleSetEditor.cpp77
-rw-r--r--src/theme_builder/components/StyleRuleSetEditor.h4
-rw-r--r--src/ui/style/StyleRuleSet.cpp11
5 files changed, 128 insertions, 23 deletions
diff --git a/include/cru/ui/model/IListChangeNotify.h b/include/cru/ui/model/IListChangeNotify.h
new file mode 100644
index 00000000..a9fcd65b
--- /dev/null
+++ b/include/cru/ui/model/IListChangeNotify.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "../Base.h"
+#include "cru/common/Base.h"
+#include "cru/common/Event.h"
+
+namespace cru::ui::model {
+enum ListChangeType {
+ kItemAdd,
+ kItemRemove,
+ kItemSet,
+ kItemMove,
+ kClear,
+};
+
+struct CRU_UI_API ListChange {
+ ListChangeType type;
+ union {
+ Index position;
+ };
+ union {
+ Index count;
+ Index new_position;
+ };
+
+ constexpr static ListChange ItemAdd(Index index, Index count = 1) {
+ return {ListChangeType::kItemAdd, index, count};
+ }
+
+ constexpr static ListChange ItemRemove(Index index, Index count = 1) {
+ return {ListChangeType::kItemRemove, index, count};
+ }
+
+ constexpr static ListChange ItemSet(Index index, Index count = 1) {
+ return {ListChangeType::kItemSet, index, count};
+ }
+
+ constexpr static ListChange ItemMove(Index position, Index new_position) {
+ return {ListChangeType::kItemMove, position, new_position};
+ }
+
+ constexpr static ListChange Clear() { return {ListChangeType::kClear}; }
+};
+
+struct CRU_UI_API IListChangeNotify : virtual Interface {
+ virtual IEvent<ListChange>* ListChangeEvent() = 0;
+};
+} // namespace cru::ui::model
diff --git a/include/cru/ui/style/StyleRuleSet.h b/include/cru/ui/style/StyleRuleSet.h
index 8bf9c9ff..8f3495bc 100644
--- a/include/cru/ui/style/StyleRuleSet.h
+++ b/include/cru/ui/style/StyleRuleSet.h
@@ -2,6 +2,7 @@
#include "StyleRule.h"
#include "cru/common/Base.h"
#include "cru/common/Event.h"
+#include "cru/ui/model/IListChangeNotify.h"
#include <cstddef>
@@ -12,7 +13,7 @@ namespace cru::ui::style {
* mutable and has reference semantics. Change of it will be notified by
* StyleRuleSet::ChangeEvent.
*/
-class CRU_UI_API StyleRuleSet : public Object {
+class CRU_UI_API StyleRuleSet : public Object, public model::IListChangeNotify {
public:
StyleRuleSet() = default;
explicit StyleRuleSet(std::shared_ptr<StyleRuleSet> parent);
@@ -50,11 +51,20 @@ class CRU_UI_API StyleRuleSet : public Object {
// change ...). Subscribe to this and update style change listeners and style.
IEvent<std::nullptr_t>* ChangeEvent() { return &change_event_; }
+ IEvent<model::ListChange>* ListChangeEvent() override {
+ return &list_change_event_;
+ }
+
private:
void RaiseChangeEvent() { change_event_.Raise(nullptr); }
+ void RaiseChangeEvent(model::ListChange list_change) {
+ list_change_event_.Raise(list_change);
+ change_event_.Raise(nullptr);
+ }
private:
Event<std::nullptr_t> change_event_;
+ Event<model::ListChange> list_change_event_;
std::shared_ptr<StyleRuleSet> parent_ = nullptr;
EventRevokerGuard parent_change_event_guard_;
diff --git a/src/theme_builder/components/StyleRuleSetEditor.cpp b/src/theme_builder/components/StyleRuleSetEditor.cpp
index 8c64f9cf..5e942827 100644
--- a/src/theme_builder/components/StyleRuleSetEditor.cpp
+++ b/src/theme_builder/components/StyleRuleSetEditor.cpp
@@ -1,6 +1,11 @@
#include "StyleRuleSetEditor.h"
+#include <memory>
+#include <optional>
+#include "cru/common/Exception.h"
+#include "cru/common/String.h"
#include "cru/ui/ThemeManager.h"
#include "cru/ui/controls/FlexLayout.h"
+#include "cru/ui/model/IListChangeNotify.h"
#include "cru/ui/render/FlexLayoutRenderObject.h"
#include "cru/ui/style/Condition.h"
#include "cru/ui/style/Styler.h"
@@ -39,25 +44,63 @@ void StyleRuleSetEditor::BindStyleRuleSet(
Expects(style_rule_set_ == nullptr && rule_set);
style_rule_set_ = std::move(rule_set);
UpdateView(style_rule_set_.get());
- style_rule_set_->ChangeEvent()->AddSpyOnlyHandler(
- [this] { UpdateView(style_rule_set_.get()); });
+ style_rule_set_->ListChangeEvent()->AddHandler(
+ [this](const ui::model::ListChange& change) {
+ UpdateView(style_rule_set_.get(), change);
+ });
}
-void StyleRuleSetEditor::UpdateView(ui::style::StyleRuleSet* style_rule_set) {
- style_rule_editors_.clear();
-
- for (Index i = 0; i < style_rule_set->GetSize(); ++i) {
- const auto& rule = style_rule_set->GetStyleRule(i);
- auto style_rule_editor = std::make_unique<StyleRuleEditor>();
- style_rule_editor->SetValue(rule, false);
- style_rule_editor->RemoveEvent()->AddSpyOnlyHandler(
- [this, i] { style_rule_set_->RemoveStyleRule(i); });
- style_rule_editor->ChangeEvent()->AddSpyOnlyHandler(
- [this, i, editor = style_rule_editor.get()]() {
- style_rule_set_->SetStyleRule(i, editor->GetValue());
- });
- style_rule_editors_.push_back(std::move(style_rule_editor));
- rules_layout_.AddChild(style_rule_editors_.back()->GetRootControl());
+void StyleRuleSetEditor::UpdateView(
+ ui::style::StyleRuleSet* style_rule_set,
+ std::optional<ui::model::ListChange> change) {
+ if (change) {
+ switch (change->type) {
+ case ui::model::ListChangeType::kItemAdd: {
+ for (auto i = change->position; i < change->position + change->count;
+ ++i) {
+ const auto& rule = style_rule_set->GetStyleRule(i);
+ auto style_rule_editor = std::make_unique<StyleRuleEditor>();
+ style_rule_editor->SetValue(rule, false);
+ style_rule_editor->RemoveEvent()->AddSpyOnlyHandler(
+ [this, i] { style_rule_set_->RemoveStyleRule(i); });
+ style_rule_editor->ChangeEvent()->AddSpyOnlyHandler(
+ [this, i, editor = style_rule_editor.get()]() {
+ style_rule_set_->SetStyleRule(i, editor->GetValue());
+ });
+ style_rule_editors_.insert(style_rule_editors_.cbegin() + i,
+ std::move(style_rule_editor));
+ rules_layout_.AddChildAt(style_rule_editors_.back()->GetRootControl(),
+ i);
+ }
+ break;
+ }
+ case ui::model::ListChangeType::kItemRemove: {
+ for (auto i = change->position; i < change->position + change->count;
+ ++i) {
+ style_rule_editors_.erase(style_rule_editors_.begin() + i);
+ }
+ break;
+ }
+ case ui::model::ListChangeType::kItemSet: {
+ for (auto i = change->position; i < change->position + change->count;
+ ++i) {
+ const auto& rule = style_rule_set->GetStyleRule(i);
+ style_rule_editors_[i]->SetValue(rule, false);
+ }
+ break;
+ }
+ case ui::model::ListChangeType::kItemMove: {
+ throw Exception(u"Not supported now!");
+ break;
+ }
+ case ui::model::ListChangeType::kClear: {
+ style_rule_editors_.clear();
+ }
+ }
+ } else {
+ UpdateView(style_rule_set, ui::model::ListChange::Clear());
+ UpdateView(style_rule_set,
+ ui::model::ListChange::ItemAdd(0, style_rule_set->GetSize()));
}
}
} // namespace cru::theme_builder::components
diff --git a/src/theme_builder/components/StyleRuleSetEditor.h b/src/theme_builder/components/StyleRuleSetEditor.h
index 1f2ae216..864262eb 100644
--- a/src/theme_builder/components/StyleRuleSetEditor.h
+++ b/src/theme_builder/components/StyleRuleSetEditor.h
@@ -5,6 +5,7 @@
#include "cru/ui/controls/Control.h"
#include "cru/ui/controls/FlexLayout.h"
#include "cru/ui/controls/ScrollView.h"
+#include "cru/ui/model/IListChangeNotify.h"
#include "cru/ui/style/StyleRuleSet.h"
namespace cru::theme_builder::components {
@@ -23,7 +24,8 @@ class StyleRuleSetEditor : public ui::components::Component {
void BindStyleRuleSet(std::shared_ptr<ui::style::StyleRuleSet> rule_set);
private:
- void UpdateView(ui::style::StyleRuleSet* style_rule_set);
+ void UpdateView(ui::style::StyleRuleSet* style_rule_set,
+ std::optional<ui::model::ListChange> change = std::nullopt);
private:
std::shared_ptr<ui::style::StyleRuleSet> style_rule_set_;
diff --git a/src/ui/style/StyleRuleSet.cpp b/src/ui/style/StyleRuleSet.cpp
index 6b475c8c..74aba5b1 100644
--- a/src/ui/style/StyleRuleSet.cpp
+++ b/src/ui/style/StyleRuleSet.cpp
@@ -1,6 +1,7 @@
#include "cru/ui/style/StyleRuleSet.h"
#include "cru/common/Event.h"
#include "cru/ui/controls/Control.h"
+#include "cru/ui/model/IListChangeNotify.h"
#include "gsl/gsl_assert"
#include <unordered_set>
@@ -42,7 +43,7 @@ void StyleRuleSet::AddStyleRule(StyleRule rule, gsl::index index) {
rules_.insert(rules_.cbegin() + index, std::move(rule));
- RaiseChangeEvent();
+ RaiseChangeEvent(model::ListChange::ItemAdd(index));
}
void StyleRuleSet::RemoveStyleRule(gsl::index index, gsl::index count) {
@@ -51,20 +52,22 @@ void StyleRuleSet::RemoveStyleRule(gsl::index index, gsl::index count) {
rules_.erase(rules_.cbegin() + index, rules_.cbegin() + index + count);
- RaiseChangeEvent();
+ RaiseChangeEvent(model::ListChange::ItemRemove(index, count));
}
void StyleRuleSet::SetStyleRule(Index index, StyleRule rule) {
Expects(index >= 0 && index < GetSize());
rules_[index] = std::move(rule);
- RaiseChangeEvent();
+ RaiseChangeEvent(model::ListChange::ItemSet(index));
}
void StyleRuleSet::Set(const StyleRuleSet& other, bool set_parent) {
rules_ = other.rules_;
if (set_parent) parent_ = other.parent_;
- RaiseChangeEvent();
+ list_change_event_.Raise(model::ListChange::Clear());
+ list_change_event_.Raise(model::ListChange::ItemAdd(0, GetSize()));
+ change_event_.Raise(nullptr);
}
StyleRuleSetBind::StyleRuleSetBind(controls::Control* control,