aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/UiManager.cpp91
-rw-r--r--src/ui/controls/Button.cpp19
-rw-r--r--src/ui/controls/Control.cpp7
-rw-r--r--src/ui/controls/TextBox.cpp29
-rw-r--r--src/ui/render/BorderRenderObject.cpp9
-rw-r--r--src/ui/style/Condition.cpp10
-rw-r--r--src/ui/style/StyleRuleSet.cpp58
-rw-r--r--src/win/gui/Window.cpp2
8 files changed, 135 insertions, 90 deletions
diff --git a/src/ui/UiManager.cpp b/src/ui/UiManager.cpp
index 62995f86..bb7f5841 100644
--- a/src/ui/UiManager.cpp
+++ b/src/ui/UiManager.cpp
@@ -5,9 +5,14 @@
#include "cru/platform/graphics/Factory.hpp"
#include "cru/platform/graphics/Font.hpp"
#include "cru/platform/gui/UiApplication.hpp"
+#include "cru/ui/style/ApplyBorderStyleInfo.hpp"
+#include "cru/ui/style/Condition.hpp"
+#include "cru/ui/style/Styler.hpp"
namespace cru::ui {
using namespace cru::platform::graphics;
+using namespace cru::ui::style;
+using namespace cru::ui::helper;
namespace {
std::unique_ptr<ISolidColorBrush> CreateSolidColorBrush(IGraphFactory* factory,
@@ -35,49 +40,59 @@ UiManager::UiManager() {
theme_resource_.default_font =
factory->CreateFont(theme_resource_.default_font_family, 24.0f);
- const auto black_brush = std::shared_ptr<platform::graphics::ISolidColorBrush>(
- CreateSolidColorBrush(factory, colors::black));
+ const auto black_brush =
+ std::shared_ptr<platform::graphics::ISolidColorBrush>(
+ CreateSolidColorBrush(factory, colors::black));
theme_resource_.text_brush = black_brush;
theme_resource_.text_selection_brush =
CreateSolidColorBrush(factory, colors::skyblue);
theme_resource_.caret_brush = black_brush;
- theme_resource_.button_style.normal.border_brush =
- CreateSolidColorBrush(factory, Color::FromHex(0x00bfff));
- theme_resource_.button_style.hover.border_brush =
- CreateSolidColorBrush(factory, Color::FromHex(0x47d1ff));
- theme_resource_.button_style.press.border_brush =
- CreateSolidColorBrush(factory, Color::FromHex(0x91e4ff));
- theme_resource_.button_style.press_cancel.border_brush =
- CreateSolidColorBrush(factory, Color::FromHex(0x91e4ff));
-
- theme_resource_.button_style.normal.border_thickness =
- theme_resource_.button_style.hover.border_thickness =
- theme_resource_.button_style.press.border_thickness =
- theme_resource_.button_style.press_cancel.border_thickness =
- Thickness(3);
-
- theme_resource_.button_style.normal.border_radius =
- theme_resource_.button_style.hover.border_radius =
- theme_resource_.button_style.press.border_radius =
- theme_resource_.button_style.press_cancel.border_radius =
- CornerRadius({5, 5});
-
- theme_resource_.text_box_border_style.normal.border_brush =
- CreateSolidColorBrush(factory, Color::FromHex(0xced4da));
- theme_resource_.text_box_border_style.normal.border_radius = CornerRadius(5);
- theme_resource_.text_box_border_style.normal.border_thickness = Thickness(1);
-
- theme_resource_.text_box_border_style.hover =
- theme_resource_.text_box_border_style.normal;
-
- theme_resource_.text_box_border_style.focus.border_brush =
- CreateSolidColorBrush(factory, Color::FromHex(0x495057));
- theme_resource_.text_box_border_style.focus.border_radius = CornerRadius(5);
- theme_resource_.text_box_border_style.focus.border_thickness = Thickness(1);
-
- theme_resource_.text_box_border_style.focus_hover =
- theme_resource_.text_box_border_style.focus;
+ theme_resource_.button_style.AddStyleRule(
+ {ClickStateCondition::Create(ClickState::None),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0x00bfff)),
+ Thickness(3), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultButtonNormal"});
+ theme_resource_.button_style.AddStyleRule(
+ {ClickStateCondition::Create(ClickState::Hover),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0x47d1ff)),
+ Thickness(3), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultButtonHover"});
+ theme_resource_.button_style.AddStyleRule(
+ {ClickStateCondition::Create(ClickState::Press),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0x91e4ff)),
+ Thickness(3), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultButtonPress"});
+ theme_resource_.button_style.AddStyleRule(
+ {ClickStateCondition::Create(ClickState::PressInactive),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0x91e4ff)),
+ Thickness(3), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultButtonPressInactive"});
+
+ theme_resource_.text_box_style.AddStyleRule(
+ {HoverCondition::Create(false),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0xced4da)),
+ Thickness(1), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultTextBoxNormal"});
+
+ theme_resource_.text_box_style.AddStyleRule(
+ {HoverCondition::Create(true),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0xced4da)),
+ Thickness(1), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultTextBoxHover"});
+
+ theme_resource_.text_box_style.AddStyleRule(
+ {FocusCondition::Create(true),
+ BorderStyler::Create(ApplyBorderStyleInfo{
+ CreateSolidColorBrush(factory, Color::FromHex(0x495057)),
+ Thickness(1), CornerRadius(5), nullptr, nullptr}),
+ u"DefaultTextBoxHover"});
}
UiManager::~UiManager() = default;
diff --git a/src/ui/controls/Button.cpp b/src/ui/controls/Button.cpp
index 6f19e6b9..7858eadb 100644
--- a/src/ui/controls/Button.cpp
+++ b/src/ui/controls/Button.cpp
@@ -13,50 +13,37 @@ namespace cru::ui::controls {
using cru::platform::gui::SystemCursorType;
namespace {
-void Set(render::BorderRenderObject* o, const ButtonStateStyle& s) {
- o->SetBorderBrush(s.border_brush);
- o->SetBorderThickness(s.border_thickness);
- o->SetBorderRadius(s.border_radius);
- o->SetForegroundBrush(s.foreground_brush);
- o->SetBackgroundBrush(s.background_brush);
-}
-
std::shared_ptr<platform::gui::ICursor> GetSystemCursor(SystemCursorType type) {
return GetUiApplication()->GetCursorManager()->GetSystemCursor(type);
}
} // namespace
Button::Button() : click_detector_(this) {
- style_ = UiManager::GetInstance()->GetThemeResources()->button_style;
-
render_object_ = std::make_unique<render::BorderRenderObject>();
render_object_->SetAttachedControl(this);
SetContainerRenderObject(render_object_.get());
-
- Set(render_object_.get(), style_.normal);
render_object_->SetBorderEnabled(true);
click_detector_.StateChangeEvent()->AddHandler(
[this](const helper::ClickState& state) {
switch (state) {
case helper::ClickState::None:
- Set(render_object_.get(), style_.normal);
SetCursor(GetSystemCursor(SystemCursorType::Arrow));
break;
case helper::ClickState::Hover:
- Set(render_object_.get(), style_.hover);
SetCursor(GetSystemCursor(SystemCursorType::Hand));
break;
case helper::ClickState::Press:
- Set(render_object_.get(), style_.press);
SetCursor(GetSystemCursor(SystemCursorType::Hand));
break;
case helper::ClickState::PressInactive:
- Set(render_object_.get(), style_.press_cancel);
SetCursor(GetSystemCursor(SystemCursorType::Arrow));
break;
}
});
+
+ GetStyleRuleSet()->Set(
+ UiManager::GetInstance()->GetThemeResources()->button_style);
}
Button::~Button() = default;
diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp
index c1316a62..1c4ffe51 100644
--- a/src/ui/controls/Control.cpp
+++ b/src/ui/controls/Control.cpp
@@ -6,6 +6,7 @@
#include "cru/ui/Base.hpp"
#include "cru/ui/host/WindowHost.hpp"
#include "cru/ui/render/RenderObject.hpp"
+#include "cru/ui/style/StyleRuleSet.hpp"
#include <memory>
@@ -15,6 +16,8 @@ using platform::gui::IUiApplication;
using platform::gui::SystemCursorType;
Control::Control() {
+ style_rule_set_ = std::make_unique<style::StyleRuleSet>(this);
+
MouseEnterEvent()->Direct()->AddHandler([this](event::MouseEventArgs&) {
this->is_mouse_over_ = true;
this->OnMouseHoverChange(true);
@@ -94,6 +97,10 @@ void Control::SetCursor(std::shared_ptr<ICursor> cursor) {
}
}
+style::StyleRuleSet* Control::GetStyleRuleSet() {
+ return style_rule_set_.get();
+}
+
void Control::AddChild(Control* control, const Index position) {
Expects(control->GetParent() ==
nullptr); // The control already has a parent.
diff --git a/src/ui/controls/TextBox.cpp b/src/ui/controls/TextBox.cpp
index 6ba6ecb2..031894c0 100644
--- a/src/ui/controls/TextBox.cpp
+++ b/src/ui/controls/TextBox.cpp
@@ -18,8 +18,6 @@ TextBox::TextBox()
scroll_render_object_(new ScrollRenderObject()) {
const auto theme_resources = UiManager::GetInstance()->GetThemeResources();
- border_style_ = theme_resources->text_box_border_style;
-
text_render_object_ = std::make_unique<TextRenderObject>(
theme_resources->text_brush, theme_resources->default_font,
theme_resources->text_selection_brush, theme_resources->caret_brush);
@@ -38,17 +36,8 @@ TextBox::TextBox()
service_->SetEditable(true);
border_render_object_->SetBorderEnabled(true);
- border_render_object_->SetBorderStyle(border_style_.normal);
-
- GainFocusEvent()->Direct()->AddHandler([this](event::FocusChangeEventArgs&) {
- this->service_->SetCaretVisible(true);
- this->UpdateBorderStyle();
- });
- LoseFocusEvent()->Direct()->AddHandler([this](event::FocusChangeEventArgs&) {
- this->service_->SetCaretVisible(false);
- this->UpdateBorderStyle();
- });
+ GetStyleRuleSet()->Set(theme_resources->text_box_style);
}
TextBox::~TextBox() {}
@@ -65,19 +54,7 @@ render::ScrollRenderObject* TextBox::GetScrollRenderObject() {
return scroll_render_object_.get();
}
-const TextBoxBorderStyle& TextBox::GetBorderStyle() { return border_style_; }
-
-void TextBox::SetBorderStyle(TextBoxBorderStyle border_style) {
- border_style_ = std::move(border_style);
-}
-
-void TextBox::OnMouseHoverChange(bool) { UpdateBorderStyle(); }
-
-void TextBox::UpdateBorderStyle() {
- const auto focus = HasFocus();
- const auto hover = IsMouseOver();
- border_render_object_->SetBorderStyle(
- focus ? (hover ? border_style_.focus_hover : border_style_.focus)
- : (hover ? border_style_.hover : border_style_.normal));
+void TextBox::ApplyBorderStyle(const style::ApplyBorderStyleInfo& style) {
+ border_render_object_->ApplyBorderStyle(style);
}
} // namespace cru::ui::controls
diff --git a/src/ui/render/BorderRenderObject.cpp b/src/ui/render/BorderRenderObject.cpp
index 5abc7832..c176e760 100644
--- a/src/ui/render/BorderRenderObject.cpp
+++ b/src/ui/render/BorderRenderObject.cpp
@@ -17,15 +17,6 @@ BorderRenderObject::BorderRenderObject() {
BorderRenderObject::~BorderRenderObject() {}
-void BorderRenderObject::SetBorderStyle(const BorderStyle& style) {
- border_brush_ = style.border_brush;
- border_thickness_ = style.border_thickness;
- border_radius_ = style.border_radius;
- foreground_brush_ = style.foreground_brush;
- background_brush_ = style.background_brush;
- InvalidateLayout();
-}
-
void BorderRenderObject::ApplyBorderStyle(
const style::ApplyBorderStyleInfo& style) {
if (style.border_brush != nullptr) border_brush_ = style.border_brush;
diff --git a/src/ui/style/Condition.cpp b/src/ui/style/Condition.cpp
index 891eb062..f4866c04 100644
--- a/src/ui/style/Condition.cpp
+++ b/src/ui/style/Condition.cpp
@@ -51,6 +51,16 @@ bool FocusCondition::Judge(controls::Control* control) const {
return control->HasFocus() == has_focus_;
}
+std::vector<IBaseEvent*> HoverCondition::ChangeOn(
+ controls::Control* control) const {
+ return {control->MouseEnterEvent()->Direct(),
+ control->MouseLeaveEvent()->Direct()};
+}
+
+bool HoverCondition::Judge(controls::Control* control) const {
+ return control->IsMouseOver() == hover_;
+}
+
ClickStateCondition::ClickStateCondition(helper::ClickState click_state)
: click_state_(click_state) {}
diff --git a/src/ui/style/StyleRuleSet.cpp b/src/ui/style/StyleRuleSet.cpp
index e69de29b..403fe114 100644
--- a/src/ui/style/StyleRuleSet.cpp
+++ b/src/ui/style/StyleRuleSet.cpp
@@ -0,0 +1,58 @@
+#include "cru/ui/style/StyleRuleSet.hpp"
+#include "cru/common/Event.hpp"
+#include "gsl/gsl_assert"
+
+#include <unordered_set>
+
+namespace cru::ui::style {
+void StyleRuleSet::AddStyleRule(StyleRule rule, gsl::index index) {
+ Expects(index >= 0 && index <= GetSize());
+
+ rules_.insert(rules_.cbegin() + index, std::move(rule));
+
+ UpdateChangeListener();
+ UpdateStyle();
+}
+
+void StyleRuleSet::RemoveStyleRule(gsl::index index, gsl::index count) {
+ Expects(index >= 0);
+ Expects(count >= 0 && index + count <= GetSize());
+
+ rules_.erase(rules_.cbegin() + index, rules_.cbegin() + index + count);
+
+ UpdateChangeListener();
+ UpdateStyle();
+}
+
+void StyleRuleSet::Set(const StyleRuleSet& other) {
+ rules_ = other.rules_;
+ UpdateChangeListener();
+ UpdateStyle();
+}
+
+void StyleRuleSet::UpdateChangeListener() {
+ if (control_ == nullptr) return;
+
+ guard_.Clear();
+
+ std::unordered_set<IBaseEvent*> events;
+ for (const auto& rule : rules_) {
+ auto e = rule.GetCondition()->ChangeOn(control_);
+ events.insert(e.cbegin(), e.cend());
+ }
+
+ for (auto e : events) {
+ guard_ += e->AddSpyOnlyHandler([this] { this->UpdateStyle(); });
+ }
+}
+
+void StyleRuleSet::UpdateStyle() {
+ if (control_ == nullptr) return;
+
+ for (const auto& rule : rules_) {
+ if (rule.GetCondition()->Judge(control_)) {
+ rule.GetStyler()->Apply(control_);
+ }
+ }
+}
+} // namespace cru::ui::style
diff --git a/src/win/gui/Window.cpp b/src/win/gui/Window.cpp
index 174b8931..efd3bfcc 100644
--- a/src/win/gui/Window.cpp
+++ b/src/win/gui/Window.cpp
@@ -367,9 +367,9 @@ RECT WinNativeWindow::GetClientRectPixel() {
}
void WinNativeWindow::OnDestroyInternal() {
+ destroy_event_.Raise(nullptr);
application_->GetWindowManager()->UnregisterWindow(hwnd_);
hwnd_ = nullptr;
- destroy_event_.Raise(nullptr);
if (!sync_flag_) {
sync_flag_ = true;
delete this;