From 5d569206b579d164dc8bc61966d3f17f311ed9bc Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 20 Jan 2024 01:32:24 +0100 Subject: [PATCH] Update to latest zwidget --- SurrealEngine/DebuggerApp.cpp | 2 + SurrealEngine/EditorApp.cpp | 2 + SurrealEngine/GameApp.cpp | 2 + SurrealEngine/UI/Launcher/LauncherWindow.cpp | 4 - Thirdparty/ZWidget/CMakeLists.txt | 2 + .../ZWidget/include/zwidget/core/theme.h | 81 +++++ .../ZWidget/include/zwidget/core/widget.h | 41 ++- .../zwidget/widgets/lineedit/lineedit.h | 1 - .../zwidget/widgets/listview/listview.h | 1 - .../zwidget/widgets/pushbutton/pushbutton.h | 3 - .../zwidget/widgets/tabwidget/tabwidget.h | 4 - .../zwidget/widgets/textedit/textedit.h | 1 - Thirdparty/ZWidget/src/core/canvas.cpp | 16 +- Thirdparty/ZWidget/src/core/theme.cpp | 307 ++++++++++++++++++ Thirdparty/ZWidget/src/core/widget.cpp | 123 ++++++- .../ZWidget/src/widgets/lineedit/lineedit.cpp | 24 +- .../ZWidget/src/widgets/listview/listview.cpp | 21 +- .../src/widgets/pushbutton/pushbutton.cpp | 43 +-- .../src/widgets/scrollbar/scrollbar.cpp | 5 +- .../src/widgets/tabwidget/tabwidget.cpp | 45 +-- .../ZWidget/src/widgets/textedit/textedit.cpp | 21 +- .../src/widgets/textlabel/textlabel.cpp | 2 +- 22 files changed, 586 insertions(+), 165 deletions(-) create mode 100644 Thirdparty/ZWidget/include/zwidget/core/theme.h create mode 100644 Thirdparty/ZWidget/src/core/theme.cpp diff --git a/SurrealEngine/DebuggerApp.cpp b/SurrealEngine/DebuggerApp.cpp index 3753f117..75721699 100644 --- a/SurrealEngine/DebuggerApp.cpp +++ b/SurrealEngine/DebuggerApp.cpp @@ -18,6 +18,7 @@ #include "UI/WidgetResourceData.h" #include "VM/Frame.h" #include "UTF16.h" +#include #include #ifndef WIN32 @@ -28,6 +29,7 @@ int DebuggerApp::Main(std::vector args) { InitWidgetResources(); + WidgetTheme::SetTheme(std::make_unique()); WriteOutput(ColorEscape(96) + "Welcome to the Surreal Engine debugger!" + ResetEscape() + NewLine()); WriteOutput(NewLine()); diff --git a/SurrealEngine/EditorApp.cpp b/SurrealEngine/EditorApp.cpp index c24832cf..ca5bcbcb 100644 --- a/SurrealEngine/EditorApp.cpp +++ b/SurrealEngine/EditorApp.cpp @@ -6,10 +6,12 @@ #include "Engine.h" #include "UI/Editor/EditorMainWindow.h" #include "UI/WidgetResourceData.h" +#include int EditorApp::main(std::vector args) { InitWidgetResources(); + WidgetTheme::SetTheme(std::make_unique()); CommandLine cmd(args); commandline = &cmd; diff --git a/SurrealEngine/GameApp.cpp b/SurrealEngine/GameApp.cpp index bb0f0f09..9b257318 100644 --- a/SurrealEngine/GameApp.cpp +++ b/SurrealEngine/GameApp.cpp @@ -8,10 +8,12 @@ #include "VM/NativeFuncExtractor.h" #include "UI/WidgetResourceData.h" #include "File.h" +#include int GameApp::main(std::vector args) { InitWidgetResources(); + WidgetTheme::SetTheme(std::make_unique()); CommandLine cmd(args); commandline = &cmd; diff --git a/SurrealEngine/UI/Launcher/LauncherWindow.cpp b/SurrealEngine/UI/Launcher/LauncherWindow.cpp index c984fe5b..fe02e9b0 100644 --- a/SurrealEngine/UI/Launcher/LauncherWindow.cpp +++ b/SurrealEngine/UI/Launcher/LauncherWindow.cpp @@ -28,10 +28,6 @@ int LauncherWindow::ExecModal(const std::vector& games) LauncherWindow::LauncherWindow(const std::vector& games) : Widget(nullptr, WidgetType::Window) { - SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); - SetWindowBorderColor(Colorf::fromRgba8(51, 51, 51)); - SetWindowCaptionColor(Colorf::fromRgba8(33, 33, 33)); - SetWindowCaptionTextColor(Colorf::fromRgba8(226, 223, 219)); SetWindowTitle("Surreal Engine"); Banner = new LauncherBanner(this); diff --git a/Thirdparty/ZWidget/CMakeLists.txt b/Thirdparty/ZWidget/CMakeLists.txt index 3afd3cce..16d2b49c 100644 --- a/Thirdparty/ZWidget/CMakeLists.txt +++ b/Thirdparty/ZWidget/CMakeLists.txt @@ -8,6 +8,7 @@ set(ZWIDGET_SOURCES src/core/span_layout.cpp src/core/timer.cpp src/core/widget.cpp + src/core/theme.cpp src/core/utf8reader.cpp src/core/pathfill.cpp src/core/truetypefont.cpp @@ -44,6 +45,7 @@ set(ZWIDGET_INCLUDES include/zwidget/core/span_layout.h include/zwidget/core/timer.h include/zwidget/core/widget.h + include/zwidget/core/theme.h include/zwidget/core/utf8reader.h include/zwidget/core/resourcedata.h include/zwidget/widgets/lineedit/lineedit.h diff --git a/Thirdparty/ZWidget/include/zwidget/core/theme.h b/Thirdparty/ZWidget/include/zwidget/core/theme.h new file mode 100644 index 00000000..5a5271bc --- /dev/null +++ b/Thirdparty/ZWidget/include/zwidget/core/theme.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include +#include +#include "rect.h" +#include "colorf.h" + +class Widget; +class Canvas; + +class WidgetStyle +{ +public: + WidgetStyle(WidgetStyle* parentStyle = nullptr) : ParentStyle(parentStyle) { } + virtual ~WidgetStyle() = default; + virtual void Paint(Widget* widget, Canvas* canvas, Size size) = 0; + + void SetBool(const std::string& state, const std::string& propertyName, bool value); + void SetInt(const std::string& state, const std::string& propertyName, int value); + void SetDouble(const std::string& state, const std::string& propertyName, double value); + void SetString(const std::string& state, const std::string& propertyName, const std::string& value); + void SetColor(const std::string& state, const std::string& propertyName, const Colorf& value); + + void SetBool(const std::string& propertyName, bool value) { SetBool(std::string(), propertyName, value); } + void SetInt(const std::string& propertyName, int value) { SetInt(std::string(), propertyName, value); } + void SetDouble(const std::string& propertyName, double value) { SetDouble(std::string(), propertyName, value); } + void SetString(const std::string& propertyName, const std::string& value) { SetString(std::string(), propertyName, value); } + void SetColor(const std::string& propertyName, const Colorf& value) { SetColor(std::string(), propertyName, value); } + +private: + // Note: do not call these directly. Use widget->GetStyleXX instead since a widget may explicitly override a class style + bool GetBool(const std::string& state, const std::string& propertyName) const; + int GetInt(const std::string& state, const std::string& propertyName) const; + double GetDouble(const std::string& state, const std::string& propertyName) const; + std::string GetString(const std::string& state, const std::string& propertyName) const; + Colorf GetColor(const std::string& state, const std::string& propertyName) const; + + WidgetStyle* ParentStyle = nullptr; + typedef std::variant PropertyVariant; + std::unordered_map> StyleProperties; + + const PropertyVariant* FindProperty(const std::string& state, const std::string& propertyName) const; + + friend class Widget; +}; + +class BasicWidgetStyle : public WidgetStyle +{ +public: + using WidgetStyle::WidgetStyle; + void Paint(Widget* widget, Canvas* canvas, Size size) override; +}; + +class WidgetTheme +{ +public: + virtual ~WidgetTheme() = default; + + WidgetStyle* RegisterStyle(std::unique_ptr widgetStyle, const std::string& widgetClass); + WidgetStyle* GetStyle(const std::string& widgetClass); + + static void SetTheme(std::unique_ptr theme); + static WidgetTheme* GetTheme(); + +private: + std::unordered_map> Styles; +}; + +class DarkWidgetTheme : public WidgetTheme +{ +public: + DarkWidgetTheme(); +}; + +class LightWidgetTheme : public WidgetTheme +{ +public: + LightWidgetTheme(); +}; diff --git a/Thirdparty/ZWidget/include/zwidget/core/widget.h b/Thirdparty/ZWidget/include/zwidget/core/widget.h index 8835922b..02e87729 100644 --- a/Thirdparty/ZWidget/include/zwidget/core/widget.h +++ b/Thirdparty/ZWidget/include/zwidget/core/widget.h @@ -2,6 +2,8 @@ #include #include +#include +#include #include "canvas.h" #include "rect.h" #include "colorf.h" @@ -39,16 +41,32 @@ class Widget : DisplayWindowHost // Widget noncontent area void SetNoncontentSizes(double left, double top, double right, double bottom); - double GetNoncontentLeft() const { return Noncontent.Left; } - double GetNoncontentTop() const { return Noncontent.Top; } - double GetNoncontentRight() const { return Noncontent.Right; } - double GetNoncontentBottom() const { return Noncontent.Bottom; } + double GetNoncontentLeft() const { return GetStyleDouble("noncontent-left"); } + double GetNoncontentTop() const { return GetStyleDouble("noncontent-top"); } + double GetNoncontentRight() const { return GetStyleDouble("noncontent-right"); } + double GetNoncontentBottom() const { return GetStyleDouble("noncontent-bottom"); } // Widget frame box Rect GetFrameGeometry() const; void SetFrameGeometry(const Rect& geometry); void SetFrameGeometry(double x, double y, double width, double height) { SetFrameGeometry(Rect::xywh(x, y, width, height)); } + // Style properties + void SetStyleClass(const std::string& styleClass); + const std::string& GetStyleClass() const { return StyleClass; } + void SetStyleState(const std::string& state); + const std::string& GetStyleState() const { return StyleState; } + void SetStyleBool(const std::string& propertyName, bool value); + void SetStyleInt(const std::string& propertyName, int value); + void SetStyleDouble(const std::string& propertyName, double value); + void SetStyleString(const std::string& propertyName, const std::string& value); + void SetStyleColor(const std::string& propertyName, const Colorf& value); + bool GetStyleBool(const std::string& propertyName) const; + int GetStyleInt(const std::string& propertyName) const; + double GetStyleDouble(const std::string& propertyName) const; + std::string GetStyleString(const std::string& propertyName) const; + Colorf GetStyleColor(const std::string& propertyName) const; + void SetWindowBackground(const Colorf& color); void SetWindowBorderColor(const Colorf& color); void SetWindowCaptionColor(const Colorf& color); @@ -112,7 +130,7 @@ class Widget : DisplayWindowHost static Size GetScreenSize(); protected: - virtual void OnPaintFrame(Canvas* canvas) { } + virtual void OnPaintFrame(Canvas* canvas); virtual void OnPaint(Canvas* canvas) { } virtual bool OnMouseDown(const Point& pos, InputKey key) { return false; } virtual bool OnMouseDoubleclick(const Point& pos, InputKey key) { return false; } @@ -167,14 +185,6 @@ class Widget : DisplayWindowHost Colorf WindowBackground = Colorf::fromRgba8(240, 240, 240); - struct - { - double Left = 0.0; - double Top = 0.0; - double Right = 0.0; - double Bottom = 0.0; - } Noncontent; - std::string WindowTitle; std::unique_ptr DispWindow; std::unique_ptr DispCanvas; @@ -185,6 +195,11 @@ class Widget : DisplayWindowHost StandardCursor CurrentCursor = StandardCursor::arrow; + std::string StyleClass = "widget"; + std::string StyleState; + typedef std::variant PropertyVariant; + std::unordered_map StyleProperties; + Widget(const Widget&) = delete; Widget& operator=(const Widget&) = delete; diff --git a/Thirdparty/ZWidget/include/zwidget/widgets/lineedit/lineedit.h b/Thirdparty/ZWidget/include/zwidget/widgets/lineedit/lineedit.h index 02f3025b..8c5dcfa8 100644 --- a/Thirdparty/ZWidget/include/zwidget/widgets/lineedit/lineedit.h +++ b/Thirdparty/ZWidget/include/zwidget/widgets/lineedit/lineedit.h @@ -69,7 +69,6 @@ class LineEdit : public Widget std::function FuncEnterPressed; protected: - void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; void OnMouseMove(const Point& pos) override; bool OnMouseDown(const Point& pos, InputKey key) override; diff --git a/Thirdparty/ZWidget/include/zwidget/widgets/listview/listview.h b/Thirdparty/ZWidget/include/zwidget/widgets/listview/listview.h index 00d4c249..3d317039 100644 --- a/Thirdparty/ZWidget/include/zwidget/widgets/listview/listview.h +++ b/Thirdparty/ZWidget/include/zwidget/widgets/listview/listview.h @@ -24,7 +24,6 @@ class ListView : public Widget protected: void OnPaint(Canvas* canvas) override; - void OnPaintFrame(Canvas* canvas) override; bool OnMouseDown(const Point& pos, InputKey key) override; bool OnMouseDoubleclick(const Point& pos, InputKey key) override; bool OnMouseWheel(const Point& pos, InputKey key) override; diff --git a/Thirdparty/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h b/Thirdparty/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h index 36dee957..d3fe0295 100644 --- a/Thirdparty/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h +++ b/Thirdparty/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h @@ -19,7 +19,6 @@ class PushButton : public Widget std::function OnClick; protected: - void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; bool OnMouseDown(const Point& pos, InputKey key) override; bool OnMouseUp(const Point& pos, InputKey key) override; @@ -30,6 +29,4 @@ class PushButton : public Widget private: std::string text; - bool buttonDown = false; - bool hot = false; }; diff --git a/Thirdparty/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h b/Thirdparty/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h index dec6965d..00bb3d89 100644 --- a/Thirdparty/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h +++ b/Thirdparty/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h @@ -37,7 +37,6 @@ class TabWidget : public Widget std::function OnCurrentChanged; protected: - void OnPaintFrame(Canvas* canvas) override; void OnGeometryChanged() override; private: @@ -67,7 +66,6 @@ class TabBar : public Widget std::function OnCurrentChanged; protected: - void OnPaintFrame(Canvas* canvas) override; void OnGeometryChanged() override; private: @@ -92,7 +90,6 @@ class TabBarTab : public Widget std::function OnClick; protected: - void OnPaintFrame(Canvas* canvas) override; void OnGeometryChanged() override; bool OnMouseDown(const Point& pos, InputKey key) override; bool OnMouseUp(const Point& pos, InputKey key) override; @@ -116,7 +113,6 @@ class TabWidgetStack : public Widget Widget* GetCurrentWidget() const { return CurrentWidget; } protected: - void OnPaintFrame(Canvas* canvas) override; void OnGeometryChanged() override; private: diff --git a/Thirdparty/ZWidget/include/zwidget/widgets/textedit/textedit.h b/Thirdparty/ZWidget/include/zwidget/widgets/textedit/textedit.h index 3480a7f8..f392f85d 100644 --- a/Thirdparty/ZWidget/include/zwidget/widgets/textedit/textedit.h +++ b/Thirdparty/ZWidget/include/zwidget/widgets/textedit/textedit.h @@ -53,7 +53,6 @@ class TextEdit : public Widget std::function FuncEnterPressed; protected: - void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; void OnMouseMove(const Point& pos) override; bool OnMouseDown(const Point& pos, InputKey key) override; diff --git a/Thirdparty/ZWidget/src/core/canvas.cpp b/Thirdparty/ZWidget/src/core/canvas.cpp index 1a630b38..9faccfa0 100644 --- a/Thirdparty/ZWidget/src/core/canvas.cpp +++ b/Thirdparty/ZWidget/src/core/canvas.cpp @@ -529,7 +529,7 @@ int BitmapCanvas::getClipMaxY() const void BitmapCanvas::fillTile(float left, float top, float width, float height, Colorf color) { - if (width <= 0.0f || height <= 0.0f) + if (width <= 0.0f || height <= 0.0f || color.a <= 0.0f) return; int dwidth = this->width; @@ -558,7 +558,7 @@ void BitmapCanvas::fillTile(float left, float top, float width, float height, Co { uint32_t c = (calpha << 24) | (cred << 16) | (cgreen << 8) | cblue; #ifdef USE_SSE2 - __m128i crgba = _mm_set1_epi32(c); + __m128i cargb = _mm_set1_epi32(c); #endif for (int y = y0; y < y1; y++) @@ -570,7 +570,7 @@ void BitmapCanvas::fillTile(float left, float top, float width, float height, Co int ssex1 = x0 + (((x1 - x0) >> 2) << 2); while (x < ssex1) { - _mm_storeu_si128((__m128i*)(dline + x), crgba); + _mm_storeu_si128((__m128i*)(dline + x), cargb); x += 4; } #endif @@ -589,7 +589,7 @@ void BitmapCanvas::fillTile(float left, float top, float width, float height, Co cblue <<= 8; calpha <<= 8; #ifdef USE_SSE2 - __m128i crgba = _mm_set_epi16(calpha, cblue, cgreen, cred, calpha, cblue, cgreen, cred); + __m128i cargb = _mm_set_epi16(calpha, cred, cgreen, cblue, calpha, cred, cgreen, cblue); __m128i cinvalpha = _mm_set1_epi16(invalpha); #endif @@ -606,7 +606,7 @@ void BitmapCanvas::fillTile(float left, float top, float width, float height, Co dpixel = _mm_unpacklo_epi8(dpixel, _mm_setzero_si128()); // dest.rgba = color.rgba + dest.rgba * (1-color.a) - __m128i result = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(crgba, _mm_mullo_epi16(dpixel, cinvalpha)), _mm_set1_epi16(127)), 8); + __m128i result = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(cargb, _mm_mullo_epi16(dpixel, cinvalpha)), _mm_set1_epi16(127)), 8); _mm_storel_epi64((__m128i*)(dline + x), _mm_packus_epi16(result, _mm_setzero_si128())); x += 2; } @@ -634,7 +634,7 @@ void BitmapCanvas::fillTile(float left, float top, float width, float height, Co void BitmapCanvas::drawTile(CanvasTexture* texture, float left, float top, float width, float height, float u, float v, float uvwidth, float uvheight, Colorf color) { - if (width <= 0.0f || height <= 0.0f) + if (width <= 0.0f || height <= 0.0f || color.a <= 0.0f) return; int swidth = texture->Width; @@ -662,7 +662,7 @@ void BitmapCanvas::drawTile(CanvasTexture* texture, float left, float top, float uint32_t cblue = (int32_t)clamp(color.b * 256.0f, 0.0f, 256.0f); uint32_t calpha = (int32_t)clamp(color.a * 256.0f, 0.0f, 256.0f); #ifdef USE_SSE2 - __m128i crgba = _mm_set_epi16(calpha, cblue, cgreen, cred, calpha, cblue, cgreen, cred); + __m128i cargb = _mm_set_epi16(calpha, cred, cgreen, cblue, calpha, cred, cgreen, cblue); #endif float uscale = uvwidth / width; @@ -690,7 +690,7 @@ void BitmapCanvas::drawTile(CanvasTexture* texture, float left, float top, float dpixel = _mm_unpacklo_epi8(dpixel, _mm_setzero_si128()); // Pixel shade - spixel = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(spixel, crgba), _mm_set1_epi16(127)), 8); + spixel = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(spixel, cargb), _mm_set1_epi16(127)), 8); // Rescale from [0,255] to [0,256] __m128i sa = _mm_shufflehi_epi16(_mm_shufflelo_epi16(spixel, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3)); diff --git a/Thirdparty/ZWidget/src/core/theme.cpp b/Thirdparty/ZWidget/src/core/theme.cpp new file mode 100644 index 00000000..de779561 --- /dev/null +++ b/Thirdparty/ZWidget/src/core/theme.cpp @@ -0,0 +1,307 @@ + +#include "core/theme.h" +#include "core/widget.h" +#include "core/canvas.h" + +void WidgetStyle::SetBool(const std::string& state, const std::string& propertyName, bool value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetInt(const std::string& state, const std::string& propertyName, int value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetDouble(const std::string& state, const std::string& propertyName, double value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetString(const std::string& state, const std::string& propertyName, const std::string& value) +{ + StyleProperties[state][propertyName] = value; +} + +void WidgetStyle::SetColor(const std::string& state, const std::string& propertyName, const Colorf& value) +{ + StyleProperties[state][propertyName] = value; +} + +const WidgetStyle::PropertyVariant* WidgetStyle::FindProperty(const std::string& state, const std::string& propertyName) const +{ + const WidgetStyle* style = this; + do + { + // Look for property in the specific state + auto stateIt = style->StyleProperties.find(state); + if (stateIt != style->StyleProperties.end()) + { + auto it = stateIt->second.find(propertyName); + if (it != stateIt->second.end()) + return &it->second; + } + + // Fall back to the widget main style + if (state != std::string()) + { + stateIt = style->StyleProperties.find(std::string()); + if (stateIt != style->StyleProperties.end()) + { + auto it = stateIt->second.find(propertyName); + if (it != stateIt->second.end()) + return &it->second; + } + } + + style = style->ParentStyle; + } while (style); + return nullptr; +} + +bool WidgetStyle::GetBool(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : false; +} + +int WidgetStyle::GetInt(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : 0; +} + +double WidgetStyle::GetDouble(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : 0.0; +} + +std::string WidgetStyle::GetString(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : std::string(); +} + +Colorf WidgetStyle::GetColor(const std::string& state, const std::string& propertyName) const +{ + const PropertyVariant* prop = FindProperty(state, propertyName); + return prop ? std::get(*prop) : Colorf::transparent(); +} + +///////////////////////////////////////////////////////////////////////////// + +void BasicWidgetStyle::Paint(Widget* widget, Canvas* canvas, Size size) +{ + Colorf bgcolor = widget->GetStyleColor("background-color"); + if (bgcolor.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, 0.0, size.width, size.height), bgcolor); + + Colorf borderleft = widget->GetStyleColor("border-left-color"); + Colorf bordertop = widget->GetStyleColor("border-top-color"); + Colorf borderright = widget->GetStyleColor("border-right-color"); + Colorf borderbottom = widget->GetStyleColor("border-bottom-color"); + + if (bordertop.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, 0.0, size.width, 1.0), bordertop); + if (borderbottom.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, size.height - 1.0, size.width, 1.0), borderbottom); + if (borderleft.a > 0.0f) + canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, size.height - 0.0), borderleft); + if (borderright.a > 0.0f) + canvas->fillRect(Rect::xywh(size.width - 1.0, 0.0, 1.0, size.height - 0.0), borderright); +} + +///////////////////////////////////////////////////////////////////////////// + +static std::unique_ptr CurrentTheme; + +WidgetStyle* WidgetTheme::RegisterStyle(std::unique_ptr widgetStyle, const std::string& widgetClass) +{ + auto& style = Styles[widgetClass]; + style = std::move(widgetStyle); + return style.get(); +} + +WidgetStyle* WidgetTheme::GetStyle(const std::string& widgetClass) +{ + auto it = Styles.find(widgetClass); + return it != Styles.end() ? it->second.get() : nullptr; +} + +void WidgetTheme::SetTheme(std::unique_ptr theme) +{ + CurrentTheme = std::move(theme); +} + +WidgetTheme* WidgetTheme::GetTheme() +{ + return CurrentTheme.get(); +} + +///////////////////////////////////////////////////////////////////////////// + +DarkWidgetTheme::DarkWidgetTheme() +{ + auto widget = RegisterStyle(std::make_unique(), "widget"); + auto textlabel = RegisterStyle(std::make_unique(widget), "textlabel"); + auto pushbutton = RegisterStyle(std::make_unique(widget), "pushbutton"); + auto lineedit = RegisterStyle(std::make_unique(widget), "lineedit"); + auto textedit = RegisterStyle(std::make_unique(widget), "textedit"); + auto listview = RegisterStyle(std::make_unique(widget), "listview"); + auto scrollbar = RegisterStyle(std::make_unique(widget), "scrollbar"); + auto tabbar = RegisterStyle(std::make_unique(widget), "tabbar"); + auto tabbar_tab = RegisterStyle(std::make_unique(widget), "tabbar-tab"); + auto tabwidget_stack = RegisterStyle(std::make_unique(widget), "tabwidget-stack"); + + widget->SetString("font-family", "NotoSans"); + widget->SetColor("color", Colorf::fromRgba8(226, 223, 219)); + widget->SetColor("window-background", Colorf::fromRgba8(51, 51, 51)); + widget->SetColor("window-border", Colorf::fromRgba8(51, 51, 51)); + widget->SetColor("window-caption-color", Colorf::fromRgba8(33, 33, 33)); + widget->SetColor("window-caption-text-color", Colorf::fromRgba8(226, 223, 219)); + + pushbutton->SetDouble("noncontent-left", 10.0); + pushbutton->SetDouble("noncontent-top", 5.0); + pushbutton->SetDouble("noncontent-right", 10.0); + pushbutton->SetDouble("noncontent-bottom", 5.0); + pushbutton->SetColor("background-color", Colorf::fromRgba8(68, 68, 68)); + pushbutton->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + pushbutton->SetColor("hover", "background-color", Colorf::fromRgba8(78, 78, 78)); + pushbutton->SetColor("down", "background-color", Colorf::fromRgba8(88, 88, 88)); + + lineedit->SetDouble("noncontent-left", 5.0); + lineedit->SetDouble("noncontent-top", 3.0); + lineedit->SetDouble("noncontent-right", 5.0); + lineedit->SetDouble("noncontent-bottom", 3.0); + lineedit->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + lineedit->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("selection-color", Colorf::fromRgba8(100, 100, 100)); + lineedit->SetColor("no-focus-selection-color", Colorf::fromRgba8(68, 68, 68)); + + textedit->SetDouble("noncontent-left", 8.0); + textedit->SetDouble("noncontent-top", 8.0); + textedit->SetDouble("noncontent-right", 8.0); + textedit->SetDouble("noncontent-bottom", 8.0); + textedit->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + textedit->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + textedit->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + textedit->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + textedit->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + + listview->SetDouble("noncontent-left", 10.0); + listview->SetDouble("noncontent-top", 10.0); + listview->SetDouble("noncontent-right", 3.0); + listview->SetDouble("noncontent-bottom", 10.0); + listview->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + listview->SetColor("border-left-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("border-top-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("border-right-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("border-bottom-color", Colorf::fromRgba8(100, 100, 100)); + listview->SetColor("selection-color", Colorf::fromRgba8(100, 100, 100)); + + scrollbar->SetColor("track-color", Colorf::fromRgba8(33, 33, 33)); + scrollbar->SetColor("thumb-color", Colorf::fromRgba8(58, 58, 58)); + + tabbar->SetDouble("noncontent-left", 20.0); + tabbar->SetDouble("noncontent-right", 20.0); + tabbar->SetColor("background-color", Colorf::fromRgba8(38, 38, 38)); + + tabbar_tab->SetDouble("noncontent-left", 15.0); + tabbar_tab->SetDouble("noncontent-right", 15.0); + tabbar_tab->SetColor("hover", "background-color", Colorf::fromRgba8(45, 45, 45)); + tabbar_tab->SetColor("active", "background-color", Colorf::fromRgba8(51, 51, 51)); + + tabwidget_stack->SetDouble("noncontent-left", 20.0); + tabwidget_stack->SetDouble("noncontent-top", 5.0); + tabwidget_stack->SetDouble("noncontent-right", 20.0); + tabwidget_stack->SetDouble("noncontent-bottom", 5.0); +} + +///////////////////////////////////////////////////////////////////////////// + +LightWidgetTheme::LightWidgetTheme() +{ + auto widget = RegisterStyle(std::make_unique(), "widget"); + auto textlabel = RegisterStyle(std::make_unique(widget), "textlabel"); + auto pushbutton = RegisterStyle(std::make_unique(widget), "pushbutton"); + auto lineedit = RegisterStyle(std::make_unique(widget), "lineedit"); + auto textedit = RegisterStyle(std::make_unique(widget), "textedit"); + auto listview = RegisterStyle(std::make_unique(widget), "listview"); + auto scrollbar = RegisterStyle(std::make_unique(widget), "scrollbar"); + auto tabbar = RegisterStyle(std::make_unique(widget), "tabbar"); + auto tabbar_tab = RegisterStyle(std::make_unique(widget), "tabbar-tab"); + auto tabwidget_stack = RegisterStyle(std::make_unique(widget), "tabwidget-stack"); + + widget->SetString("font-family", "NotoSans"); + widget->SetColor("color", Colorf::fromRgba8(0, 0, 0)); + widget->SetColor("window-background", Colorf::fromRgba8(240, 240, 240)); + + pushbutton->SetDouble("noncontent-left", 10.0); + pushbutton->SetDouble("noncontent-top", 5.0); + pushbutton->SetDouble("noncontent-right", 10.0); + pushbutton->SetDouble("noncontent-bottom", 5.0); + pushbutton->SetColor("background-color", Colorf::fromRgba8(210, 210, 210)); + pushbutton->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + pushbutton->SetColor("hover", "background-color", Colorf::fromRgba8(200, 200, 200)); + pushbutton->SetColor("down", "background-color", Colorf::fromRgba8(190, 190, 190)); + + lineedit->SetDouble("noncontent-left", 5.0); + lineedit->SetDouble("noncontent-top", 3.0); + lineedit->SetDouble("noncontent-right", 5.0); + lineedit->SetDouble("noncontent-bottom", 3.0); + lineedit->SetColor("background-color", Colorf::fromRgba8(255, 255, 255)); + lineedit->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + lineedit->SetColor("selection-color", Colorf::fromRgba8(210, 210, 255)); + lineedit->SetColor("no-focus-selection-color", Colorf::fromRgba8(240, 240, 255)); + + textedit->SetDouble("noncontent-left", 8.0); + textedit->SetDouble("noncontent-top", 8.0); + textedit->SetDouble("noncontent-right", 8.0); + textedit->SetDouble("noncontent-bottom", 8.0); + textedit->SetColor("background-color", Colorf::fromRgba8(255, 255, 255)); + textedit->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + textedit->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + textedit->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + textedit->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + + listview->SetDouble("noncontent-left", 10.0); + listview->SetDouble("noncontent-top", 10.0); + listview->SetDouble("noncontent-right", 3.0); + listview->SetDouble("noncontent-bottom", 10.0); + listview->SetColor("background-color", Colorf::fromRgba8(230, 230, 230)); + listview->SetColor("border-left-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("border-top-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("border-right-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("border-bottom-color", Colorf::fromRgba8(155, 155, 155)); + listview->SetColor("selection-color", Colorf::fromRgba8(200, 200, 200)); + + scrollbar->SetColor("track-color", Colorf::fromRgba8(210, 210, 220)); + scrollbar->SetColor("thumb-color", Colorf::fromRgba8(180, 180, 180)); + + tabbar->SetDouble("noncontent-left", 20.0); + tabbar->SetDouble("noncontent-right", 20.0); + tabbar->SetColor("background-color", Colorf::fromRgba8(220, 220, 220)); + + tabbar_tab->SetDouble("noncontent-left", 15.0); + tabbar_tab->SetDouble("noncontent-right", 15.0); + tabbar_tab->SetColor("hover", "background-color", Colorf::fromRgba8(210, 210, 210)); + tabbar_tab->SetColor("active", "background-color", Colorf::fromRgba8(240, 240, 240)); + + tabwidget_stack->SetDouble("noncontent-left", 20.0); + tabwidget_stack->SetDouble("noncontent-top", 5.0); + tabwidget_stack->SetDouble("noncontent-right", 20.0); + tabwidget_stack->SetDouble("noncontent-bottom", 5.0); +} diff --git a/Thirdparty/ZWidget/src/core/widget.cpp b/Thirdparty/ZWidget/src/core/widget.cpp index 1d2f61a6..9cf5dda2 100644 --- a/Thirdparty/ZWidget/src/core/widget.cpp +++ b/Thirdparty/ZWidget/src/core/widget.cpp @@ -2,6 +2,7 @@ #include "core/widget.h" #include "core/timer.h" #include "core/colorf.h" +#include "core/theme.h" #include Widget::Widget(Widget* parent, WidgetType type) : Type(type) @@ -10,6 +11,15 @@ Widget::Widget(Widget* parent, WidgetType type) : Type(type) { DispWindow = DisplayWindow::Create(this); DispCanvas = Canvas::create(DispWindow.get()); + SetStyleState("root"); + + SetWindowBackground(GetStyleColor("window-background")); + if (GetStyleColor("window-border").a > 0.0f) + SetWindowBorderColor(GetStyleColor("window-border")); + if (GetStyleColor("window-caption-color").a > 0.0f) + SetWindowCaptionColor(GetStyleColor("window-caption-color")); + if (GetStyleColor("window-caption-text-color").a > 0.0f) + SetWindowCaptionTextColor(GetStyleColor("window-caption-text-color")); } SetParent(parent); @@ -138,10 +148,10 @@ Rect Widget::GetFrameGeometry() const void Widget::SetNoncontentSizes(double left, double top, double right, double bottom) { - Noncontent.Left = left; - Noncontent.Top = top; - Noncontent.Right = right; - Noncontent.Bottom = bottom; + SetStyleDouble("noncontent-left", left); + SetStyleDouble("noncontent-top", top); + SetStyleDouble("noncontent-right", right); + SetStyleDouble("noncontent-bottom", bottom); } void Widget::SetFrameGeometry(const Rect& geometry) @@ -149,10 +159,10 @@ void Widget::SetFrameGeometry(const Rect& geometry) if (Type == WidgetType::Child) { FrameGeometry = geometry; - double left = FrameGeometry.left() + Noncontent.Left; - double top = FrameGeometry.top() + Noncontent.Top; - double right = FrameGeometry.right() - Noncontent.Right; - double bottom = FrameGeometry.bottom() - Noncontent.Bottom; + double left = FrameGeometry.left() + GetNoncontentLeft(); + double top = FrameGeometry.top() + GetNoncontentTop(); + double right = FrameGeometry.right() - GetNoncontentRight(); + double bottom = FrameGeometry.bottom() - GetNoncontentBottom(); left = std::min(left, FrameGeometry.right()); top = std::min(top, FrameGeometry.bottom()); right = std::max(right, FrameGeometry.left()); @@ -316,6 +326,15 @@ void Widget::Paint(Canvas* canvas) canvas->popClip(); } +void Widget::OnPaintFrame(Canvas* canvas) +{ + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + if (style) + { + style->Paint(this, canvas, GetFrameGeometry().size()); + } +} + bool Widget::GetKeyState(InputKey key) { Widget* window = Window(); @@ -711,3 +730,91 @@ Size Widget::GetScreenSize() { return DisplayWindow::GetScreenSize(); } + +void Widget::SetStyleClass(const std::string& themeClass) +{ + if (StyleClass != themeClass) + { + StyleClass = themeClass; + Update(); + } +} + +void Widget::SetStyleState(const std::string& state) +{ + if (StyleState != state) + { + StyleState = state; + Update(); + } +} + +void Widget::SetStyleBool(const std::string& propertyName, bool value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleInt(const std::string& propertyName, int value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleDouble(const std::string& propertyName, double value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleString(const std::string& propertyName, const std::string& value) +{ + StyleProperties[propertyName] = value; +} + +void Widget::SetStyleColor(const std::string& propertyName, const Colorf& value) +{ + StyleProperties[propertyName] = value; +} + +bool Widget::GetStyleBool(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetBool(StyleState, propertyName) : false; +} + +int Widget::GetStyleInt(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetInt(StyleState, propertyName) : 0; +} + +double Widget::GetStyleDouble(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetDouble(StyleState, propertyName) : 0.0; +} + +std::string Widget::GetStyleString(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetString(StyleState, propertyName) : std::string(); +} + +Colorf Widget::GetStyleColor(const std::string& propertyName) const +{ + auto it = StyleProperties.find(propertyName); + if (it != StyleProperties.end()) + return std::get(it->second); + WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass); + return style ? style->GetColor(StyleState, propertyName) : Colorf::transparent(); +} diff --git a/Thirdparty/ZWidget/src/widgets/lineedit/lineedit.cpp b/Thirdparty/ZWidget/src/widgets/lineedit/lineedit.cpp index 8b7695b8..38b928f9 100644 --- a/Thirdparty/ZWidget/src/widgets/lineedit/lineedit.cpp +++ b/Thirdparty/ZWidget/src/widgets/lineedit/lineedit.cpp @@ -5,7 +5,7 @@ LineEdit::LineEdit(Widget* parent) : Widget(parent) { - SetNoncontentSizes(5.0, 3.0, 5.0, 3.0); + SetStyleClass("lineedit"); timer = new Timer(this); timer->FuncExpired = [=]() { OnTimerExpired(); }; @@ -1067,18 +1067,6 @@ std::string LineEdit::GetVisibleTextAfterSelection() } } -void LineEdit::OnPaintFrame(Canvas* canvas) -{ - double w = GetFrameGeometry().width; - double h = GetFrameGeometry().height; - Colorf bordercolor = Colorf::fromRgba8(100, 100, 100); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38)); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, h - 1.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, h - 0.0), bordercolor); - canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor); -} - void LineEdit::OnPaint(Canvas* canvas) { std::string txt_before = GetVisibleTextBeforeSelection(); @@ -1101,21 +1089,21 @@ void LineEdit::OnPaint(Canvas* canvas) { // Draw selection box. Rect selection_rect = GetSelectionRect(); - canvas->fillRect(selection_rect, HasFocus() ? Colorf::fromRgba8(100, 100, 100) : Colorf::fromRgba8(68, 68, 68)); + canvas->fillRect(selection_rect, HasFocus() ? GetStyleColor("selection-color") : GetStyleColor("no-focus-selection-color")); } // Draw text before selection if (!txt_before.empty()) { - canvas->drawText(Point(0.0, canvas->verticalTextAlign().baseline), Colorf::fromRgba8(255, 255, 255), txt_before); + canvas->drawText(Point(0.0, canvas->verticalTextAlign().baseline), GetStyleColor("color"), txt_before); } if (!txt_selected.empty()) { - canvas->drawText(Point(size_before.width, canvas->verticalTextAlign().baseline), Colorf::fromRgba8(255, 255, 255), txt_selected); + canvas->drawText(Point(size_before.width, canvas->verticalTextAlign().baseline), GetStyleColor("color"), txt_selected); } if (!txt_after.empty()) { - canvas->drawText(Point(size_before.width + size_selected.width, canvas->verticalTextAlign().baseline), Colorf::fromRgba8(255, 255, 255), txt_after); + canvas->drawText(Point(size_before.width + size_selected.width, canvas->verticalTextAlign().baseline), GetStyleColor("color"), txt_after); } // draw cursor @@ -1124,7 +1112,7 @@ void LineEdit::OnPaint(Canvas* canvas) if (cursor_blink_visible) { Rect cursor_rect = GetCursorRect(); - canvas->fillRect(cursor_rect, Colorf::fromRgba8(255, 255, 255)); + canvas->fillRect(cursor_rect, GetStyleColor("color")); } } } diff --git a/Thirdparty/ZWidget/src/widgets/listview/listview.cpp b/Thirdparty/ZWidget/src/widgets/listview/listview.cpp index f1c585be..9c9704f4 100644 --- a/Thirdparty/ZWidget/src/widgets/listview/listview.cpp +++ b/Thirdparty/ZWidget/src/widgets/listview/listview.cpp @@ -4,7 +4,7 @@ ListView::ListView(Widget* parent) : Widget(parent) { - SetNoncontentSizes(10.0, 10.0, 3.0, 10.0); + SetStyleClass("listview"); scrollbar = new Scrollbar(this); scrollbar->FuncScroll = [=]() { OnScrollbarScroll(); }; @@ -67,6 +67,9 @@ void ListView::OnPaint(Canvas* canvas) double w = GetWidth() - scrollbar->GetPreferredWidth() - 2.0; double h = 20.0; + Colorf textColor = GetStyleColor("color"); + Colorf selectionColor = GetStyleColor("selection-color"); + int index = 0; for (const std::string& item : items) { @@ -75,27 +78,15 @@ void ListView::OnPaint(Canvas* canvas) { if (index == selectedItem) { - canvas->fillRect(Rect::xywh(x - 2.0, itemY, w, h), Colorf::fromRgba8(100, 100, 100)); + canvas->fillRect(Rect::xywh(x - 2.0, itemY, w, h), selectionColor); } - canvas->drawText(Point(x, y + 15.0), Colorf::fromRgba8(255, 255, 255), item); + canvas->drawText(Point(x, y + 15.0), textColor, item); } y += h; index++; } } -void ListView::OnPaintFrame(Canvas* canvas) -{ - double w = GetFrameGeometry().width; - double h = GetFrameGeometry().height; - Colorf bordercolor = Colorf::fromRgba8(100, 100, 100); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38)); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, h - 1.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, h - 0.0), bordercolor); - canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor); -} - bool ListView::OnMouseDown(const Point& pos, InputKey key) { SetFocus(); diff --git a/Thirdparty/ZWidget/src/widgets/pushbutton/pushbutton.cpp b/Thirdparty/ZWidget/src/widgets/pushbutton/pushbutton.cpp index 16b255d5..e85b2c55 100644 --- a/Thirdparty/ZWidget/src/widgets/pushbutton/pushbutton.cpp +++ b/Thirdparty/ZWidget/src/widgets/pushbutton/pushbutton.cpp @@ -3,7 +3,7 @@ PushButton::PushButton(Widget* parent) : Widget(parent) { - SetNoncontentSizes(10.0, 5.0, 10.0, 5.0); + SetStyleClass("pushbutton"); } void PushButton::SetText(const std::string& value) @@ -25,52 +25,32 @@ double PushButton::GetPreferredHeight() const return 30.0; } -void PushButton::OnPaintFrame(Canvas* canvas) -{ - double w = GetFrameGeometry().width; - double h = GetFrameGeometry().height; - Colorf bordercolor = Colorf::fromRgba8(100, 100, 100); - Colorf buttoncolor = Colorf::fromRgba8(68, 68, 68); - if (buttonDown) - buttoncolor = Colorf::fromRgba8(88, 88, 88); - else if (hot) - buttoncolor = Colorf::fromRgba8(78, 78, 78); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), buttoncolor); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, h - 1.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, h - 0.0), bordercolor); - canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor); -} - void PushButton::OnPaint(Canvas* canvas) { Rect box = canvas->measureText(text); - canvas->drawText(Point((GetWidth() - box.width) * 0.5, GetHeight() - 5.0), Colorf::fromRgba8(255, 255, 255), text); + canvas->drawText(Point((GetWidth() - box.width) * 0.5, GetHeight() - 5.0), GetStyleColor("color"), text); } void PushButton::OnMouseMove(const Point& pos) { - if (!hot) + if (GetStyleState().empty()) { - hot = true; - Update(); + SetStyleState("hover"); } } bool PushButton::OnMouseDown(const Point& pos, InputKey key) { SetFocus(); - buttonDown = true; - Update(); + SetStyleState("down"); return true; } bool PushButton::OnMouseUp(const Point& pos, InputKey key) { - if (buttonDown) + if (GetStyleState() == "down") { - buttonDown = false; - hot = false; + SetStyleState(""); Repaint(); Click(); } @@ -79,16 +59,14 @@ bool PushButton::OnMouseUp(const Point& pos, InputKey key) void PushButton::OnMouseLeave() { - hot = false; - buttonDown = false; - Update(); + SetStyleState(""); } void PushButton::OnKeyDown(InputKey key) { if (key == InputKey::Space || key == InputKey::Enter) { - buttonDown = true; + SetStyleState("down"); Update(); } } @@ -97,8 +75,7 @@ void PushButton::OnKeyUp(InputKey key) { if (key == InputKey::Space || key == InputKey::Enter) { - buttonDown = false; - hot = false; + SetStyleState(""); Repaint(); Click(); } diff --git a/Thirdparty/ZWidget/src/widgets/scrollbar/scrollbar.cpp b/Thirdparty/ZWidget/src/widgets/scrollbar/scrollbar.cpp index 7a3810a4..634403fa 100644 --- a/Thirdparty/ZWidget/src/widgets/scrollbar/scrollbar.cpp +++ b/Thirdparty/ZWidget/src/widgets/scrollbar/scrollbar.cpp @@ -5,6 +5,7 @@ Scrollbar::Scrollbar(Widget* parent) : Widget(parent) { + SetStyleClass("scrollbar"); UpdatePartPositions(); mouse_down_timer = new Timer(this); @@ -294,8 +295,8 @@ void Scrollbar::OnPaint(Canvas* canvas) part_button_increment.render_box(canvas, rect_button_increment); */ - canvas->fillRect(Rect::shrink(Rect::xywh(0.0, 0.0, GetWidth(), GetHeight()), 4.0, 0.0, 4.0, 0.0), Colorf::fromRgba8(33, 33, 33)); - canvas->fillRect(Rect::shrink(rect_thumb, 4.0, 0.0, 4.0, 0.0), Colorf::fromRgba8(58, 58, 58)); + canvas->fillRect(Rect::shrink(Rect::xywh(0.0, 0.0, GetWidth(), GetHeight()), 4.0, 0.0, 4.0, 0.0), GetStyleColor("track-color")); + canvas->fillRect(Rect::shrink(rect_thumb, 4.0, 0.0, 4.0, 0.0), GetStyleColor("thumb-color")); } // Calculates positions of all parts. Returns true if thumb position was changed compared to previously, false otherwise. diff --git a/Thirdparty/ZWidget/src/widgets/tabwidget/tabwidget.cpp b/Thirdparty/ZWidget/src/widgets/tabwidget/tabwidget.cpp index 0cf6f328..4bd7551c 100644 --- a/Thirdparty/ZWidget/src/widgets/tabwidget/tabwidget.cpp +++ b/Thirdparty/ZWidget/src/widgets/tabwidget/tabwidget.cpp @@ -98,10 +98,6 @@ void TabWidget::OnBarCurrentChanged() OnCurrentChanged(); } -void TabWidget::OnPaintFrame(Canvas* canvas) -{ -} - void TabWidget::OnGeometryChanged() { double w = GetWidth(); @@ -115,7 +111,7 @@ void TabWidget::OnGeometryChanged() TabBar::TabBar(Widget* parent) : Widget(parent) { - SetNoncontentSizes(20.0, 0.0, 20.0, 0.0); + SetStyleClass("tabbar"); } int TabBar::AddTab(const std::string& label) @@ -187,13 +183,6 @@ int TabBar::GetTabIndex(TabBarTab* tab) return -1; } -void TabBar::OnPaintFrame(Canvas* canvas) -{ - double w = GetFrameGeometry().width; - double h = GetFrameGeometry().height; - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38)); -} - void TabBar::OnGeometryChanged() { double w = GetWidth(); @@ -211,7 +200,7 @@ void TabBar::OnGeometryChanged() TabBarTab::TabBarTab(Widget* parent) : Widget(parent) { - SetNoncontentSizes(15.0, 0.0, 15.0, 0.0); + SetStyleClass("tabbar-tab"); } void TabBarTab::SetText(const std::string& text) @@ -257,7 +246,7 @@ void TabBarTab::SetCurrent(bool value) if (IsCurrent != value) { IsCurrent = value; - Update(); + SetStyleState(value ? "active" : ""); } } @@ -268,20 +257,6 @@ double TabBarTab::GetPreferredWidth() const return x; } -void TabBarTab::OnPaintFrame(Canvas* canvas) -{ - double w = GetFrameGeometry().width; - double h = GetFrameGeometry().height; - if (IsCurrent) - { - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(51, 51, 51)); - } - else if (hot) - { - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(45, 45, 45)); - } -} - void TabBarTab::OnGeometryChanged() { double x = 0.0; @@ -300,10 +275,9 @@ void TabBarTab::OnGeometryChanged() void TabBarTab::OnMouseMove(const Point& pos) { - if (!hot) + if (GetStyleState().empty()) { - hot = true; - Update(); + SetStyleState("hover"); } } @@ -321,7 +295,8 @@ bool TabBarTab::OnMouseUp(const Point& pos, InputKey key) void TabBarTab::OnMouseLeave() { - hot = false; + if (GetStyleState() == "hover") + SetStyleState(""); Update(); } @@ -329,7 +304,7 @@ void TabBarTab::OnMouseLeave() TabWidgetStack::TabWidgetStack(Widget* parent) : Widget(parent) { - SetNoncontentSizes(20.0, 5.0, 20.0, 5.0); + SetStyleClass("tabwidget-stack"); } void TabWidgetStack::SetCurrentWidget(Widget* widget) @@ -347,10 +322,6 @@ void TabWidgetStack::SetCurrentWidget(Widget* widget) } } -void TabWidgetStack::OnPaintFrame(Canvas* canvas) -{ -} - void TabWidgetStack::OnGeometryChanged() { if (CurrentWidget) diff --git a/Thirdparty/ZWidget/src/widgets/textedit/textedit.cpp b/Thirdparty/ZWidget/src/widgets/textedit/textedit.cpp index 19dbbe77..27a2d023 100644 --- a/Thirdparty/ZWidget/src/widgets/textedit/textedit.cpp +++ b/Thirdparty/ZWidget/src/widgets/textedit/textedit.cpp @@ -10,7 +10,7 @@ TextEdit::TextEdit(Widget* parent) : Widget(parent) { - SetNoncontentSizes(8.0, 8.0, 8.0, 8.0); + SetStyleClass("textedit"); timer = new Timer(this); timer->FuncExpired = [=]() { OnTimerExpired(); }; @@ -961,6 +961,7 @@ void TextEdit::LayoutLines(Canvas* canvas) sel_end = selection_start; } + Colorf textColor = GetStyleColor("color"); Point draw_pos; for (size_t i = (size_t)vert_scrollbar->GetPosition(); i < lines.size(); i++) { @@ -969,9 +970,9 @@ void TextEdit::LayoutLines(Canvas* canvas) { line.layout.Clear(); if (!line.text.empty()) - line.layout.AddText(line.text, font, Colorf::fromRgba8(255, 255, 255)); + line.layout.AddText(line.text, font, textColor); else - line.layout.AddText(" ", font, Colorf::fromRgba8(255, 255, 255)); // Draw one space character to get the correct height + line.layout.AddText(" ", font, textColor); // Draw one space character to get the correct height line.layout.Layout(canvas, GetWidth()); line.box = Rect(draw_pos, line.layout.GetSize()); line.invalidated = false; @@ -992,7 +993,7 @@ void TextEdit::LayoutLines(Canvas* canvas) if (cursor_blink_visible && cursor_pos.y == i) { line.layout.SetCursorPos(cursor_pos.x); - line.layout.SetCursorColor(Colorf::fromRgba8(255, 255, 255)); + line.layout.SetCursorColor(textColor); line.layout.ShowCursor(); } } @@ -1006,18 +1007,6 @@ void TextEdit::LayoutLines(Canvas* canvas) UpdateVerticalScroll(); } -void TextEdit::OnPaintFrame(Canvas* canvas) -{ - double w = GetFrameGeometry().width; - double h = GetFrameGeometry().height; - Colorf bordercolor = Colorf::fromRgba8(100, 100, 100); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38)); - canvas->fillRect(Rect::xywh(0.0, 0.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, h - 1.0, w, 1.0), bordercolor); - canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, h - 0.0), bordercolor); - canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor); -} - void TextEdit::OnPaint(Canvas* canvas) { LayoutLines(canvas); diff --git a/Thirdparty/ZWidget/src/widgets/textlabel/textlabel.cpp b/Thirdparty/ZWidget/src/widgets/textlabel/textlabel.cpp index 55518f0a..aa6e7e73 100644 --- a/Thirdparty/ZWidget/src/widgets/textlabel/textlabel.cpp +++ b/Thirdparty/ZWidget/src/widgets/textlabel/textlabel.cpp @@ -56,5 +56,5 @@ void TextLabel::OnPaint(Canvas* canvas) x = GetWidth() - canvas->measureText(text).width; } - canvas->drawText(Point(x, GetHeight() - 5.0), Colorf::fromRgba8(255, 255, 255), text); + canvas->drawText(Point(x, GetHeight() - 5.0), GetStyleColor("color"), text); }