Update to latest zwidget

This commit is contained in:
Magnus Norddahl 2024-01-20 12:26:15 +01:00
commit d08b9b8568
23 changed files with 607 additions and 432 deletions

View file

@ -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

View file

@ -0,0 +1,81 @@
#pragma once
#include <memory>
#include <string>
#include <variant>
#include <unordered_map>
#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<bool, int, double, std::string, Colorf> PropertyVariant;
std::unordered_map<std::string, std::unordered_map<std::string, PropertyVariant>> 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> widgetStyle, const std::string& widgetClass);
WidgetStyle* GetStyle(const std::string& widgetClass);
static void SetTheme(std::unique_ptr<WidgetTheme> theme);
static WidgetTheme* GetTheme();
private:
std::unordered_map<std::string, std::unique_ptr<WidgetStyle>> Styles;
};
class DarkWidgetTheme : public WidgetTheme
{
public:
DarkWidgetTheme();
};
class LightWidgetTheme : public WidgetTheme
{
public:
LightWidgetTheme();
};

View file

@ -2,6 +2,8 @@
#include <string>
#include <memory>
#include <variant>
#include <unordered_map>
#include "canvas.h"
#include "rect.h"
#include "colorf.h"
@ -39,16 +41,32 @@ public:
// 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 @@ public:
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 @@ private:
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<DisplayWindow> DispWindow;
std::unique_ptr<Canvas> DispCanvas;
@ -185,6 +195,11 @@ private:
StandardCursor CurrentCursor = StandardCursor::arrow;
std::string StyleClass = "widget";
std::string StyleState;
typedef std::variant<bool, int, double, std::string, Colorf> PropertyVariant;
std::unordered_map<std::string, PropertyVariant> StyleProperties;
Widget(const Widget&) = delete;
Widget& operator=(const Widget&) = delete;

View file

@ -69,7 +69,6 @@ public:
std::function<void()> 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;

View file

@ -24,7 +24,6 @@ public:
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;

View file

@ -19,7 +19,6 @@ public:
std::function<void()> 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 @@ protected:
private:
std::string text;
bool buttonDown = false;
bool hot = false;
};

View file

@ -37,7 +37,6 @@ public:
std::function<void()> OnCurrentChanged;
protected:
void OnPaintFrame(Canvas* canvas) override;
void OnGeometryChanged() override;
private:
@ -67,7 +66,6 @@ public:
std::function<void()> OnCurrentChanged;
protected:
void OnPaintFrame(Canvas* canvas) override;
void OnGeometryChanged() override;
private:
@ -92,7 +90,6 @@ public:
std::function<void()> 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 @@ public:
Widget* GetCurrentWidget() const { return CurrentWidget; }
protected:
void OnPaintFrame(Canvas* canvas) override;
void OnGeometryChanged() override;
private:

View file

@ -53,7 +53,6 @@ public:
std::function<void()> 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;

View file

@ -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));

View file

@ -0,0 +1,324 @@
#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<bool>(*prop) : false;
}
int WidgetStyle::GetInt(const std::string& state, const std::string& propertyName) const
{
const PropertyVariant* prop = FindProperty(state, propertyName);
return prop ? std::get<int>(*prop) : 0;
}
double WidgetStyle::GetDouble(const std::string& state, const std::string& propertyName) const
{
const PropertyVariant* prop = FindProperty(state, propertyName);
return prop ? std::get<double>(*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<std::string>(*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<Colorf>(*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<WidgetTheme> CurrentTheme;
WidgetStyle* WidgetTheme::RegisterStyle(std::unique_ptr<WidgetStyle> 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<WidgetTheme> theme)
{
CurrentTheme = std::move(theme);
}
WidgetTheme* WidgetTheme::GetTheme()
{
return CurrentTheme.get();
}
/////////////////////////////////////////////////////////////////////////////
DarkWidgetTheme::DarkWidgetTheme()
{
auto widget = RegisterStyle(std::make_unique<BasicWidgetStyle>(), "widget");
auto textlabel = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "textlabel");
auto pushbutton = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "pushbutton");
auto lineedit = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "lineedit");
auto textedit = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "textedit");
auto listview = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "listview");
auto scrollbar = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "scrollbar");
auto tabbar = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "tabbar");
auto tabbar_tab = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "tabbar-tab");
auto tabwidget_stack = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "tabwidget-stack");
auto checkbox_label = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "checkbox-label");
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);
checkbox_label->SetColor("checked-outer-border-color", Colorf::fromRgba8(100, 100, 100));
checkbox_label->SetColor("checked-inner-border-color", Colorf::fromRgba8(51, 51, 51));
checkbox_label->SetColor("checked-color", Colorf::fromRgba8(226, 223, 219));
checkbox_label->SetColor("unchecked-outer-border-color", Colorf::fromRgba8(99, 99, 99));
checkbox_label->SetColor("unchecked-inner-border-color", Colorf::fromRgba8(51, 51, 51));
}
/////////////////////////////////////////////////////////////////////////////
LightWidgetTheme::LightWidgetTheme()
{
auto widget = RegisterStyle(std::make_unique<BasicWidgetStyle>(), "widget");
auto textlabel = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "textlabel");
auto pushbutton = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "pushbutton");
auto lineedit = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "lineedit");
auto textedit = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "textedit");
auto listview = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "listview");
auto scrollbar = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "scrollbar");
auto tabbar = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "tabbar");
auto tabbar_tab = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "tabbar-tab");
auto tabwidget_stack = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "tabwidget-stack");
auto checkbox_label = RegisterStyle(std::make_unique<BasicWidgetStyle>(widget), "checkbox-label");
widget->SetString("font-family", "NotoSans");
widget->SetColor("color", Colorf::fromRgba8(0, 0, 0));
widget->SetColor("window-background", Colorf::fromRgba8(240, 240, 240));
widget->SetColor("window-border", Colorf::fromRgba8(100, 100, 100));
widget->SetColor("window-caption-color", Colorf::fromRgba8(70, 70, 70));
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(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);
checkbox_label->SetColor("checked-outer-border-color", Colorf::fromRgba8(155, 155, 155));
checkbox_label->SetColor("checked-inner-border-color", Colorf::fromRgba8(200, 200, 200));
checkbox_label->SetColor("checked-color", Colorf::fromRgba8(50, 50, 50));
checkbox_label->SetColor("unchecked-outer-border-color", Colorf::fromRgba8(156, 156, 156));
checkbox_label->SetColor("unchecked-inner-border-color", Colorf::fromRgba8(200, 200, 200));
}

View file

@ -2,6 +2,7 @@
#include "core/widget.h"
#include "core/timer.h"
#include "core/colorf.h"
#include "core/theme.h"
#include <stdexcept>
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<bool>(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<int>(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<double>(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<std::string>(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<Colorf>(it->second);
WidgetStyle* style = WidgetTheme::GetTheme()->GetStyle(StyleClass);
return style ? style->GetColor(StyleState, propertyName) : Colorf::transparent();
}

View file

@ -3,6 +3,7 @@
CheckboxLabel::CheckboxLabel(Widget* parent) : Widget(parent)
{
SetStyleClass("checkbox-label");
}
void CheckboxLabel::SetText(const std::string& value)
@ -42,17 +43,17 @@ void CheckboxLabel::OnPaint(Canvas* canvas)
{
if (checked)
{
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 6.0, 10.0, 10.0), Colorf::fromRgba8(100, 100, 100));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 5.0, 8.0, 8.0), Colorf::fromRgba8(51, 51, 51));
canvas->fillRect(Rect::xywh(2.0, GetHeight() * 0.5 - 4.0, 6.0, 6.0), Colorf::fromRgba8(226, 223, 219));
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 6.0, 10.0, 10.0), GetStyleColor("checked-outer-border-color"));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 5.0, 8.0, 8.0), GetStyleColor("checked-inner-border-color"));
canvas->fillRect(Rect::xywh(2.0, GetHeight() * 0.5 - 4.0, 6.0, 6.0), GetStyleColor("checked-color"));
}
else
{
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 6.0, 10.0, 10.0), Colorf::fromRgba8(99, 99, 99));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 5.0, 8.0, 8.0), Colorf::fromRgba8(51, 51, 51));
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 6.0, 10.0, 10.0), GetStyleColor("unchecked-outer-border-color"));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 5.0, 8.0, 8.0), GetStyleColor("unchecked-inner-border-color"));
}
canvas->drawText(Point(14.0, GetHeight() - 5.0), Colorf::fromRgba8(255, 255, 255), text);
canvas->drawText(Point(14.0, GetHeight() - 5.0), GetStyleColor("color"), text);
}
bool CheckboxLabel::OnMouseDown(const Point& pos, InputKey key)

View file

@ -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"));
}
}
}

View file

@ -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();

View file

@ -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();
}

View file

@ -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.

View file

@ -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)

View file

@ -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);

View file

@ -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);
}