diff options
author | crupest <crupest@outlook.com> | 2021-05-10 19:34:01 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-05-10 19:34:01 +0800 |
commit | 43a1883ac80ce3ff4782cd74e5ad16a03887c2aa (patch) | |
tree | daa3c374813f478e0ce99dfca858393b6ad95a3a | |
parent | ae5042599688af2d8b462e49e3cd103b6ec92fe9 (diff) | |
download | cru-43a1883ac80ce3ff4782cd74e5ad16a03887c2aa.tar.gz cru-43a1883ac80ce3ff4782cd74e5ad16a03887c2aa.tar.bz2 cru-43a1883ac80ce3ff4782cd74e5ad16a03887c2aa.zip |
...
-rw-r--r-- | include/cru/common/StringUtil.hpp | 5 | ||||
-rw-r--r-- | include/cru/platform/Color.hpp | 3 | ||||
-rw-r--r-- | include/cru/ui/ThemeManager.hpp | 27 | ||||
-rw-r--r-- | include/cru/ui/UiManager.hpp | 8 | ||||
-rw-r--r-- | include/cru/ui/render/ScrollBar.hpp | 10 | ||||
-rw-r--r-- | src/common/StringUtil.cpp | 26 | ||||
-rw-r--r-- | src/platform/Color.cpp | 38 | ||||
-rw-r--r-- | src/ui/ThemeManager.cpp | 54 | ||||
-rw-r--r-- | src/ui/UiManager.cpp | 36 | ||||
-rw-r--r-- | src/ui/render/ScrollBar.cpp | 87 |
10 files changed, 218 insertions, 76 deletions
diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp index 62999d53..912106c3 100644 --- a/include/cru/common/StringUtil.hpp +++ b/include/cru/common/StringUtil.hpp @@ -145,4 +145,9 @@ gsl::index Utf16PreviousWord(std::u16string_view str, gsl::index position, bool* is_space = nullptr); gsl::index Utf16NextWord(std::u16string_view str, gsl::index position, bool* is_space = nullptr); + +char16_t ToLower(char16_t c); +char16_t ToUpper(char16_t c); +std::u16string ToLower(std::u16string_view s); +std::u16string ToUpper(std::u16string_view s); } // namespace cru diff --git a/include/cru/platform/Color.hpp b/include/cru/platform/Color.hpp index d1a9b678..efa02848 100644 --- a/include/cru/platform/Color.hpp +++ b/include/cru/platform/Color.hpp @@ -30,6 +30,9 @@ struct Color { return result; } + std::string ToUtf8String() const; + std::u16string ToString() const; + std::uint8_t red; std::uint8_t green; std::uint8_t blue; diff --git a/include/cru/ui/ThemeManager.hpp b/include/cru/ui/ThemeManager.hpp index c9e17680..1da29a0e 100644 --- a/include/cru/ui/ThemeManager.hpp +++ b/include/cru/ui/ThemeManager.hpp @@ -2,26 +2,49 @@ #include "Base.hpp" #include "cru/common/Base.hpp" #include "cru/common/Event.hpp" +#include "cru/platform/graphics/Brush.hpp" #include <boost/property_tree/ptree.hpp> #include <cstddef> +#include <memory> +#include <stdexcept> +#include <string_view> +#include <unordered_map> namespace cru::ui { +class BadThemeResourceException : public std::runtime_error { + public: + using std::runtime_error::runtime_error; +}; + class ThemeManager : public Object { public: + static ThemeManager* GetInstance(); + + private: ThemeManager(); + public: CRU_DELETE_COPY(ThemeManager) CRU_DELETE_MOVE(ThemeManager) - ~ThemeManager() override; + ~ThemeManager() override = default; IEvent<std::nullptr_t>* ThemeResourceChangeEvent() { return &theme_resource_change_event_; } + gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> GetBrush( + std::u16string key); + + private: + void Init(); + private: Event<std::nullptr_t> theme_resource_change_event_; - boost::property_tree::iptree theme_tree_; + boost::property_tree::ptree theme_tree_; + std::unordered_map<std::u16string, + std::shared_ptr<platform::graphics::IBrush>> + brushes_; }; } // namespace cru::ui diff --git a/include/cru/ui/UiManager.hpp b/include/cru/ui/UiManager.hpp index b9af0065..10b12e87 100644 --- a/include/cru/ui/UiManager.hpp +++ b/include/cru/ui/UiManager.hpp @@ -4,7 +4,6 @@ #include "controls/Base.hpp" #include "cru/platform/graphics/Brush.hpp" #include "cru/ui/helper/ClickDetector.hpp" -#include "render/ScrollBar.hpp" #include "style/StyleRuleSet.hpp" #include <gsl/pointers> @@ -23,13 +22,6 @@ struct ThemeResources { style::StyleRuleSet text_box_style; style::StyleRuleSet menu_item_style; - - std::shared_ptr<platform::graphics::IBrush> scroll_bar_colllapsed_thumb_brush; - std::unordered_map< - render::ScrollBarBrushUsageKind, - std::unordered_map<helper::ClickState, - std::shared_ptr<platform::graphics::IBrush>>> - scroll_bar_brushes; }; class UiManager : public Object { diff --git a/include/cru/ui/render/ScrollBar.hpp b/include/cru/ui/render/ScrollBar.hpp index f72aef9b..8f18c821 100644 --- a/include/cru/ui/render/ScrollBar.hpp +++ b/include/cru/ui/render/ScrollBar.hpp @@ -38,6 +38,10 @@ enum class ScrollBarAreaKind { }; enum class ScrollBarBrushUsageKind { Arrow, ArrowBackground, Slot, Thumb }; +enum class ScrollBarBrushStateKind { Normal, Hover, Press, Disable }; + +std::u16string GenerateScrollBarThemeColorKey(ScrollBarBrushUsageKind usage, + ScrollBarBrushStateKind state); class ScrollBar : public Object { public: @@ -71,9 +75,9 @@ class ScrollBar : public Object { void SetCollapsedThumbBrush( std::shared_ptr<platform::graphics::IBrush> brush); gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> GetBrush( - ScrollBarBrushUsageKind kind, helper::ClickState click_state); + ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state); // Brush could be nullptr to use the theme brush. - void SetBrush(ScrollBarBrushUsageKind kind, helper::ClickState click_state, + void SetBrush(ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state, std::shared_ptr<platform::graphics::IBrush> brush); protected: @@ -124,7 +128,7 @@ class ScrollBar : public Object { std::shared_ptr<platform::graphics::IBrush> collapsed_thumb_brush_; std::unordered_map< ScrollBarBrushUsageKind, - std::unordered_map<helper::ClickState, + std::unordered_map<ScrollBarBrushStateKind, std::shared_ptr<platform::graphics::IBrush>>> brushes_; diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp index 0cadc545..bf95f88d 100644 --- a/src/common/StringUtil.cpp +++ b/src/common/StringUtil.cpp @@ -284,4 +284,30 @@ gsl::index Utf16NextWord(std::u16string_view str, gsl::index position, return Utf16ForwardUntil(str, position, IsSpace); } } + +char16_t ToLower(char16_t c) { + if (c >= u'A' && c <= u'Z') { + return c - u'A' + u'a'; + } + return c; +} + +char16_t ToUpper(char16_t c) { + if (c >= u'a' && c <= u'z') { + return c - u'a' + u'A'; + } + return c; +} + +std::u16string ToLower(std::u16string_view s) { + std::u16string result; + for (auto c : s) result.push_back(ToLower(c)); + return result; +} + +std::u16string ToUpper(std::u16string_view s) { + std::u16string result; + for (auto c : s) result.push_back(ToUpper(c)); + return result; +} } // namespace cru diff --git a/src/platform/Color.cpp b/src/platform/Color.cpp index 325cf413..d1c60217 100644 --- a/src/platform/Color.cpp +++ b/src/platform/Color.cpp @@ -1,12 +1,48 @@ #include "cru/platform/Color.hpp" #include <cstdint> +#include <gsl/gsl> #include <optional> #include <stdexcept> +#include <string> #include <string_view> -#include "gsl/gsl_util" +#include "fmt/core.h" namespace cru::platform { +std::string Color::ToUtf8String() const { + auto to_hex = [](std::uint8_t v) -> char { + return v >= 10 ? v - 10 + 'a' : v + '0'; + }; + + auto to_two_hex_digit = [to_hex](std::uint8_t v) -> std::string { + return {to_hex(v /= 16), to_hex(v %= 16)}; + }; + + std::string result = "#"; + result.append(to_two_hex_digit(alpha)); + result.append(to_two_hex_digit(red)); + result.append(to_two_hex_digit(green)); + result.append(to_two_hex_digit(blue)); + return result; +} + +std::u16string Color::ToString() const { + auto to_hex = [](std::uint8_t v) -> char16_t { + return v >= 10 ? v - 10 + u'a' : v + u'0'; + }; + + auto to_two_hex_digit = [to_hex](std::uint8_t v) -> std::u16string { + return {to_hex(v /= 16), to_hex(v %= 16)}; + }; + + std::u16string result = u"#"; + result.append(to_two_hex_digit(alpha)); + result.append(to_two_hex_digit(red)); + result.append(to_two_hex_digit(green)); + result.append(to_two_hex_digit(blue)); + return result; +} + std::optional<Color> Color::Parse(std::u16string_view string, bool parse_predefined_color) { if (parse_predefined_color) { diff --git a/src/ui/ThemeManager.cpp b/src/ui/ThemeManager.cpp index 993edc34..9311a3df 100644 --- a/src/ui/ThemeManager.cpp +++ b/src/ui/ThemeManager.cpp @@ -1 +1,55 @@ #include "cru/ui/ThemeManager.hpp" + +#include "Helper.hpp" +#include "cru/common/StringUtil.hpp" +#include "cru/platform/graphics/Brush.hpp" +#include "cru/platform/graphics/Factory.hpp" +#include "cru/platform/gui/UiApplication.hpp" + +namespace cru::ui { +ThemeManager* ThemeManager::GetInstance() { + static ThemeManager instance; + return &instance; +} + +ThemeManager::ThemeManager() { Init(); } + +void ThemeManager::Init() { + theme_tree_.put("scrollbar.collapse-thumb.color", + colors::gray.WithAlpha(128).ToUtf8String()); + theme_tree_.put("scrollbar.arrow.normal.color", "black"); + theme_tree_.put("scrollbar.arrow.hover.color", "black"); + theme_tree_.put("scrollbar.arrow.press.color", "black"); + theme_tree_.put("scrollbar.arrow.disable.color", "black"); + theme_tree_.put("scrollbar.arrow-background.normal.color", "seashell"); + theme_tree_.put("scrollbar.arrow-background.hover.color", "seashell"); + theme_tree_.put("scrollbar.arrow-background.press.color", "seashell"); + theme_tree_.put("scrollbar.arrow-background.disable.color", "seashell"); + theme_tree_.put("scrollbar.slot.normal.color", "seashell"); + theme_tree_.put("scrollbar.slot.hover.color", "seashell"); + theme_tree_.put("scrollbar.slot.press.color", "seashell"); + theme_tree_.put("scrollbar.slot.disable.color", "seashell"); + theme_tree_.put("scrollbar.thumb.normal.color", "gray"); + theme_tree_.put("scrollbar.thumb.hover.color", "gray"); + theme_tree_.put("scrollbar.thumb.press.color", "gray"); + theme_tree_.put("scrollbar.thumb.disable.color", "gray"); +} + +gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> +ThemeManager::GetBrush(std::u16string key) { + std::u16string k = ToLower(key); + auto cached_brush_iter = brushes_.find(k); + if (cached_brush_iter != brushes_.cend()) { + return cached_brush_iter->second; + } + + auto color_string = ToUtf16(theme_tree_.get_value<std::string>(ToUtf8(key))); + auto color = Color::Parse(color_string); + if (!color) throw BadThemeResourceException("Value is not a valid color."); + std::shared_ptr<platform::graphics::IBrush> brush = + GetUiApplication()->GetGraphFactory()->CreateSolidColorBrush(*color); + brushes_[k] = brush; + return brush; +} + +} // namespace cru::ui diff --git a/src/ui/UiManager.cpp b/src/ui/UiManager.cpp index 65490f6d..45dd1775 100644 --- a/src/ui/UiManager.cpp +++ b/src/ui/UiManager.cpp @@ -115,42 +115,6 @@ UiManager::UiManager() { BorderStyler::Create( ApplyBorderStyleInfo{std::nullopt, Thickness{0}, CornerRadius{0}}), u"DefaultMenuItem"}); - - theme_resource_.scroll_bar_colllapsed_thumb_brush = - factory->CreateSolidColorBrush(colors::gray.WithAlpha(128)); - theme_resource_.scroll_bar_brushes[render::ScrollBarBrushUsageKind::Arrow] = { - {helper::ClickState::None, factory->CreateSolidColorBrush(colors::black)}, - {helper::ClickState::Hover, - factory->CreateSolidColorBrush(colors::black)}, - {helper::ClickState::Press, - factory->CreateSolidColorBrush(colors::black)}, - {helper::ClickState::PressInactive, - factory->CreateSolidColorBrush(colors::black)}}; - theme_resource_ - .scroll_bar_brushes[render::ScrollBarBrushUsageKind::ArrowBackground] = { - {helper::ClickState::None, - factory->CreateSolidColorBrush(colors::seashell)}, - {helper::ClickState::Hover, - factory->CreateSolidColorBrush(colors::seashell)}, - {helper::ClickState::Press, - factory->CreateSolidColorBrush(colors::seashell)}, - {helper::ClickState::PressInactive, - factory->CreateSolidColorBrush(colors::seashell)}}; - theme_resource_.scroll_bar_brushes[render::ScrollBarBrushUsageKind::Slot] = { - {helper::ClickState::None, - factory->CreateSolidColorBrush(colors::seashell)}, - {helper::ClickState::Hover, - factory->CreateSolidColorBrush(colors::seashell)}, - {helper::ClickState::Press, - factory->CreateSolidColorBrush(colors::seashell)}, - {helper::ClickState::PressInactive, - factory->CreateSolidColorBrush(colors::seashell)}}; - theme_resource_.scroll_bar_brushes[render::ScrollBarBrushUsageKind::Thumb] = { - {helper::ClickState::None, factory->CreateSolidColorBrush(colors::gray)}, - {helper::ClickState::Hover, factory->CreateSolidColorBrush(colors::gray)}, - {helper::ClickState::Press, factory->CreateSolidColorBrush(colors::gray)}, - {helper::ClickState::PressInactive, - factory->CreateSolidColorBrush(colors::gray)}}; } UiManager::~UiManager() = default; diff --git a/src/ui/render/ScrollBar.cpp b/src/ui/render/ScrollBar.cpp index 198e0a6e..fa8e0118 100644 --- a/src/ui/render/ScrollBar.cpp +++ b/src/ui/render/ScrollBar.cpp @@ -10,6 +10,7 @@ #include "cru/platform/gui/Base.hpp" #include "cru/platform/gui/Cursor.hpp" #include "cru/ui/Base.hpp" +#include "cru/ui/ThemeManager.hpp" #include "cru/ui/UiManager.hpp" #include "cru/ui/events/UiEvent.hpp" #include "cru/ui/helper/ClickDetector.hpp" @@ -22,6 +23,7 @@ #include <memory> #include <optional> #include <stdexcept> +#include <string> namespace cru::ui::render { using namespace std::chrono_literals; @@ -36,6 +38,42 @@ constexpr std::array<ScrollBarAreaKind, 5> kScrollBarAreaKindList{ ScrollBarAreaKind::UpSlot, ScrollBarAreaKind::DownSlot, ScrollBarAreaKind::Thumb}; +std::u16string GenerateScrollBarThemeColorKey(ScrollBarBrushUsageKind usage, + ScrollBarBrushStateKind state) { + std::u16string result = u"scrollbar."; + switch (usage) { + case ScrollBarBrushUsageKind::Arrow: + result.append(u"arrow"); + break; + case ScrollBarBrushUsageKind::ArrowBackground: + result.append(u"arrow-background"); + break; + case ScrollBarBrushUsageKind::Slot: + result.append(u"slot"); + break; + case ScrollBarBrushUsageKind::Thumb: + result.append(u"thumb"); + break; + } + result.push_back(u'.'); + switch (state) { + case ScrollBarBrushStateKind::Normal: + result.append(u"normal"); + break; + case ScrollBarBrushStateKind::Hover: + result.append(u"hover"); + break; + case ScrollBarBrushStateKind::Press: + result.append(u"press"); + break; + case ScrollBarBrushStateKind::Disable: + result.append(u"disable"); + break; + } + result.append(u".color"); + return result; +} + namespace { std::unique_ptr<platform::graphics::IGeometry> CreateScrollBarArrowGeometry() { auto geometry_builder = GetGraphFactory()->CreateGeometryBuilder(); @@ -207,10 +245,9 @@ void ScrollBar::InstallHandlers(controls::Control* control) { gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> ScrollBar::GetCollapsedThumbBrush() { - return collapsed_thumb_brush_ ? collapsed_thumb_brush_ - : UiManager::GetInstance() - ->GetThemeResources() - ->scroll_bar_colllapsed_thumb_brush; + return collapsed_thumb_brush_ ? gsl::not_null(collapsed_thumb_brush_) + : ThemeManager::GetInstance()->GetBrush( + u"scrollbar.collapse-thumb.color"); } void ScrollBar::SetCollapsedThumbBrush( @@ -221,21 +258,19 @@ void ScrollBar::SetCollapsedThumbBrush( } gsl::not_null<std::shared_ptr<platform::graphics::IBrush>> ScrollBar::GetBrush( - ScrollBarBrushUsageKind kind, helper::ClickState click_state) { - auto b = brushes_[kind][click_state]; - return b ? b - : UiManager::GetInstance() - ->GetThemeResources() - ->scroll_bar_brushes.at(kind) - .at(click_state); + ScrollBarBrushUsageKind usage, ScrollBarBrushStateKind state) { + auto b = brushes_[usage][state]; + return b ? gsl::not_null(b) + : ThemeManager::GetInstance()->GetBrush( + GenerateScrollBarThemeColorKey(usage, state)); } // Brush could be nullptr to use the theme brush. -void ScrollBar::SetBrush(ScrollBarBrushUsageKind kind, - helper::ClickState click_state, +void ScrollBar::SetBrush(ScrollBarBrushUsageKind usage, + ScrollBarBrushStateKind state, std::shared_ptr<platform::graphics::IBrush> brush) { - if (brushes_[kind][click_state] == brush) return; - brushes_[kind][click_state] = std::move(brush); + if (brushes_[usage][state] == brush) return; + brushes_[usage][state] = std::move(brush); render_object_->InvalidatePaint(); } @@ -244,14 +279,14 @@ void ScrollBar::OnDraw(platform::graphics::IPainter* painter, if (is_expanded) { auto thumb_rect = GetExpandedAreaRect(ScrollBarAreaKind::Thumb); if (thumb_rect) - painter->FillRectangle( - *thumb_rect, - GetBrush(ScrollBarBrushUsageKind::Thumb, helper::ClickState::None) - .get() - .get()); + painter->FillRectangle(*thumb_rect, + GetBrush(ScrollBarBrushUsageKind::Thumb, + ScrollBarBrushStateKind::Normal) + .get() + .get()); auto slot_brush = - GetBrush(ScrollBarBrushUsageKind::Slot, helper::ClickState::None) + GetBrush(ScrollBarBrushUsageKind::Slot, ScrollBarBrushStateKind::Normal) .get() .get(); @@ -261,13 +296,13 @@ void ScrollBar::OnDraw(platform::graphics::IPainter* painter, auto down_slot_rect = GetExpandedAreaRect(ScrollBarAreaKind::DownSlot); if (down_slot_rect) painter->FillRectangle(*down_slot_rect, slot_brush); - auto arrow_brush = - GetBrush(ScrollBarBrushUsageKind::Arrow, helper::ClickState::None) - .get() - .get(); + auto arrow_brush = GetBrush(ScrollBarBrushUsageKind::Arrow, + ScrollBarBrushStateKind::Normal) + .get() + .get(); auto arrow_background_brush = GetBrush(ScrollBarBrushUsageKind::ArrowBackground, - helper::ClickState::None) + ScrollBarBrushStateKind::Normal) .get() .get(); |