aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/StringUtil.hpp5
-rw-r--r--include/cru/platform/Color.hpp3
-rw-r--r--include/cru/ui/ThemeManager.hpp27
-rw-r--r--include/cru/ui/UiManager.hpp8
-rw-r--r--include/cru/ui/render/ScrollBar.hpp10
-rw-r--r--src/common/StringUtil.cpp26
-rw-r--r--src/platform/Color.cpp38
-rw-r--r--src/ui/ThemeManager.cpp54
-rw-r--r--src/ui/UiManager.cpp36
-rw-r--r--src/ui/render/ScrollBar.cpp87
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();