diff options
Diffstat (limited to 'src/ui/style/StyleRuleSet.cpp')
-rw-r--r-- | src/ui/style/StyleRuleSet.cpp | 74 |
1 files changed, 56 insertions, 18 deletions
diff --git a/src/ui/style/StyleRuleSet.cpp b/src/ui/style/StyleRuleSet.cpp index 403fe114..24b88af9 100644 --- a/src/ui/style/StyleRuleSet.cpp +++ b/src/ui/style/StyleRuleSet.cpp @@ -1,17 +1,30 @@ #include "cru/ui/style/StyleRuleSet.hpp" #include "cru/common/Event.hpp" +#include "cru/ui/controls/Control.hpp" #include "gsl/gsl_assert" #include <unordered_set> namespace cru::ui::style { +StyleRuleSet::StyleRuleSet(StyleRuleSet* parent) { SetParent(parent); } + +void StyleRuleSet::SetParent(StyleRuleSet* parent) { + if (parent == parent_) return; + parent_change_event_guard_.Reset(); + parent_ = parent; + if (parent != nullptr) { + parent_change_event_guard_.Reset(parent->ChangeEvent()->AddSpyOnlyHandler( + [this] { this->RaiseChangeEvent(); })); + } + RaiseChangeEvent(); +} + void StyleRuleSet::AddStyleRule(StyleRule rule, gsl::index index) { Expects(index >= 0 && index <= GetSize()); rules_.insert(rules_.cbegin() + index, std::move(rule)); - UpdateChangeListener(); - UpdateStyle(); + RaiseChangeEvent(); } void StyleRuleSet::RemoveStyleRule(gsl::index index, gsl::index count) { @@ -20,25 +33,48 @@ void StyleRuleSet::RemoveStyleRule(gsl::index index, gsl::index count) { rules_.erase(rules_.cbegin() + index, rules_.cbegin() + index + count); - UpdateChangeListener(); - UpdateStyle(); + RaiseChangeEvent(); } void StyleRuleSet::Set(const StyleRuleSet& other) { rules_ = other.rules_; - UpdateChangeListener(); - UpdateStyle(); + + RaiseChangeEvent(); +} + +StyleRuleSetBind::StyleRuleSetBind(controls::Control* control, + StyleRuleSet* ruleset) + : control_(control), ruleset_(ruleset) { + Expects(control); + Expects(ruleset); + + ruleset->ChangeEvent()->AddSpyOnlyHandler([this] { + UpdateRuleSetChainCache(); + UpdateChangeListener(); + UpdateStyle(); + }); } -void StyleRuleSet::UpdateChangeListener() { - if (control_ == nullptr) return; +void StyleRuleSetBind::UpdateRuleSetChainCache() { + ruleset_chain_cache_.clear(); + auto parent = ruleset_; + while (parent != nullptr) { + ruleset_chain_cache_.push_back(parent); + parent = parent->GetParent(); + } +} +void StyleRuleSetBind::UpdateChangeListener() { guard_.Clear(); std::unordered_set<IBaseEvent*> events; - for (const auto& rule : rules_) { - auto e = rule.GetCondition()->ChangeOn(control_); - events.insert(e.cbegin(), e.cend()); + + // ruleset order does not matter + for (auto ruleset : ruleset_chain_cache_) { + for (const auto& rule : ruleset->GetRules()) { + auto e = rule.GetCondition()->ChangeOn(control_); + events.insert(e.cbegin(), e.cend()); + } } for (auto e : events) { @@ -46,13 +82,15 @@ void StyleRuleSet::UpdateChangeListener() { } } -void StyleRuleSet::UpdateStyle() { - if (control_ == nullptr) return; - - for (const auto& rule : rules_) { - if (rule.GetCondition()->Judge(control_)) { - rule.GetStyler()->Apply(control_); - } +void StyleRuleSetBind::UpdateStyle() { + // cache is parent last, but when calculate style, parent first, so iterate + // reverse. + for (auto iter = ruleset_chain_cache_.crbegin(); + iter != ruleset_chain_cache_.crend(); ++iter) { + for (const auto& rule : (*iter)->GetRules()) + if (rule.GetCondition()->Judge(control_)) { + rule.GetStyler()->Apply(control_); + } } } } // namespace cru::ui::style |