diff --git a/include/zwidget/core/widget.h b/include/zwidget/core/widget.h index 0151405..f5e81a5 100644 --- a/include/zwidget/core/widget.h +++ b/include/zwidget/core/widget.h @@ -36,6 +36,9 @@ class Widget : DisplayWindowHost double GetWidth() const { return GetSize().width; } double GetHeight() const { return GetSize().height; } + // Widget noncontent area + void SetNoncontentSizes(double left, double top, double right, double bottom); + // Widget frame box Rect GetFrameGeometry() const; void SetFrameGeometry(const Rect& geometry); @@ -96,6 +99,7 @@ class Widget : DisplayWindowHost Point MapToParent(const Point& pos) const { return MapTo(Parent(), pos); } protected: + virtual void OnPaintFrame(Canvas* canvas) { } virtual void OnPaint(Canvas* canvas) { } virtual void OnMouseMove(const Point& pos) { } virtual void OnMouseDown(const Point& pos, int key) { } @@ -145,7 +149,16 @@ class Widget : DisplayWindowHost Timer* FirstTimerObj = nullptr; - Rect Geometry = Rect::xywh(-1.0, -1.0, 0.0, 0.0); + Rect FrameGeometry = Rect::xywh(0.0, 0.0, 0.0, 0.0); + Rect ContentGeometry = Rect::xywh(0.0, 0.0, 0.0, 0.0); + + 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; diff --git a/include/zwidget/widgets/lineedit/lineedit.h b/include/zwidget/widgets/lineedit/lineedit.h index 464dcdc..c34ab11 100644 --- a/include/zwidget/widgets/lineedit/lineedit.h +++ b/include/zwidget/widgets/lineedit/lineedit.h @@ -69,6 +69,7 @@ class LineEdit : public Widget std::function FuncEnterPressed; protected: + void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; void OnMouseMove(const Point& pos) override; void OnMouseDown(const Point& pos, int key) override; diff --git a/include/zwidget/widgets/textedit/textedit.h b/include/zwidget/widgets/textedit/textedit.h index 8b0632e..c7dcbf5 100644 --- a/include/zwidget/widgets/textedit/textedit.h +++ b/include/zwidget/widgets/textedit/textedit.h @@ -53,7 +53,8 @@ class TextEdit : public Widget std::function FuncEnterPressed; protected: - void OnPaint(Canvas* canvas); + void OnPaintFrame(Canvas* canvas) override; + void OnPaint(Canvas* canvas) override; void OnMouseMove(const Point& pos) override; void OnMouseDown(const Point& pos, int key) override; void OnMouseDoubleclick(const Point& pos, int key) override; diff --git a/src/core/canvas.cpp b/src/core/canvas.cpp index 1a26293..7229f8c 100644 --- a/src/core/canvas.cpp +++ b/src/core/canvas.cpp @@ -88,7 +88,8 @@ class CanvasFont texture->Data.resize(destwidth * h); uint32_t* dest = (uint32_t*)texture->Data.data(); - std::unique_ptr grayscalebuffer(new uint8_t[w * h]); + std::unique_ptr grayscalebuffer(new uint8_t[w + * h]); uint8_t* grayscale = grayscalebuffer.get(); SFT_Image img = {}; @@ -109,10 +110,9 @@ class CanvasFont uint32_t blue = sline[x]; uint32_t alpha = (red | green | blue) ? 255 : 0; - uint32_t maxval = std::max(std::max(red, green), blue); - red = std::max(red, maxval / 5); - green = std::max(green, maxval / 5); - blue = std::max(blue, maxval / 5); + red = (red + green) / 2; + green = (red + green + blue) / 3; + blue = (green + blue) / 2; dline[x / 3] = (alpha << 24) | (red << 16) | (green << 8) | blue; } @@ -123,10 +123,9 @@ class CanvasFont uint32_t blue = 0; uint32_t alpha = (red | green | blue) ? 255 : 0; - uint32_t maxval = std::max(std::max(red, green), blue); - red = std::max(red, maxval / 5); - green = std::max(green, maxval / 5); - blue = std::max(blue, maxval / 5); + red = (red + green) / 2; + green = (red + green + blue) / 3; + blue = (green + blue) / 2; dline[(w - 1) / 3] = (alpha << 24) | (red << 16) | (green << 8) | blue; } @@ -137,10 +136,9 @@ class CanvasFont uint32_t blue = 0; uint32_t alpha = (red | green | blue) ? 255 : 0; - uint32_t maxval = std::max(std::max(red, green), blue); - red = std::max(red, maxval / 5); - green = std::max(green, maxval / 5); - blue = std::max(blue, maxval / 5); + red = (red + green) / 2; + green = (red + green + blue) / 3; + blue = (green + blue) / 2; dline[(w - 1) / 3] = (alpha << 24) | (red << 16) | (green << 8) | blue; } diff --git a/src/core/widget.cpp b/src/core/widget.cpp index 22b78d5..8fb2434 100644 --- a/src/core/widget.cpp +++ b/src/core/widget.cpp @@ -108,14 +108,14 @@ void Widget::SetWindowTitle(const std::string& text) Size Widget::GetSize() const { - return Geometry.size(); + return ContentGeometry.size(); } Rect Widget::GetFrameGeometry() const { if (Type == WidgetType::Child) { - return Geometry; + return FrameGeometry; } else { @@ -123,11 +123,28 @@ 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; +} + void Widget::SetFrameGeometry(const Rect& geometry) { if (Type == WidgetType::Child) { - Geometry = geometry; + 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; + left = std::min(left, FrameGeometry.right()); + top = std::min(top, FrameGeometry.right()); + right = std::max(right, FrameGeometry.left()); + bottom = std::max(bottom, FrameGeometry.top()); + ContentGeometry = Rect::ltrb(left, top, right, bottom); OnGeometryChanged(); } else @@ -218,8 +235,14 @@ void Widget::Repaint() void Widget::Paint(Canvas* canvas) { Point oldOrigin = canvas->getOrigin(); - canvas->pushClip(Geometry); - canvas->setOrigin(oldOrigin + Geometry.topLeft()); + canvas->pushClip(FrameGeometry); + canvas->setOrigin(oldOrigin + FrameGeometry.topLeft()); + OnPaintFrame(canvas); + canvas->setOrigin(oldOrigin); + canvas->popClip(); + + canvas->pushClip(ContentGeometry); + canvas->setOrigin(oldOrigin + ContentGeometry.topLeft()); OnPaint(canvas); for (Widget* w = FirstChild(); w != nullptr; w = w->NextSibling()) { @@ -334,9 +357,9 @@ Widget* Widget::ChildAt(const Point& pos) { for (Widget* cur = LastChild(); cur != nullptr; cur = cur->PrevSibling()) { - if (cur->Geometry.contains(pos)) + if (cur->FrameGeometry.contains(pos)) { - Widget* cur2 = cur->ChildAt(pos - cur->Geometry.topLeft()); + Widget* cur2 = cur->ChildAt(pos - cur->FrameGeometry.topLeft()); return cur2 ? cur2 : cur; } } @@ -350,7 +373,7 @@ Point Widget::MapFrom(const Widget* parent, const Point& pos) const { if (cur == parent) return p; - p -= cur->Geometry.topLeft(); + p -= cur->ContentGeometry.topLeft(); } throw std::runtime_error("MapFrom: not a parent of widget"); } @@ -364,7 +387,7 @@ Point Widget::MapFromGlobal(const Point& pos) const { return p - cur->GetFrameGeometry().topLeft(); } - p -= cur->Geometry.topLeft(); + p -= cur->ContentGeometry.topLeft(); } throw std::runtime_error("MapFromGlobal: no window widget found"); } @@ -376,7 +399,7 @@ Point Widget::MapTo(const Widget* parent, const Point& pos) const { if (cur == parent) return p; - p += cur->Geometry.topLeft(); + p += cur->ContentGeometry.topLeft(); } throw std::runtime_error("MapTo: not a parent of widget"); } @@ -390,7 +413,7 @@ Point Widget::MapToGlobal(const Point& pos) const { return cur->GetFrameGeometry().topLeft() + p; } - p += cur->Geometry.topLeft(); + p += cur->ContentGeometry.topLeft(); } throw std::runtime_error("MapFromGlobal: no window widget found"); } @@ -508,7 +531,8 @@ void Widget::OnWindowKeyUp(EInputKey key) void Widget::OnWindowGeometryChanged() { Size size = DispWindow->GetClientSize(); - Geometry = Rect::xywh(0.0, 0.0, size.width, size.height); + FrameGeometry = Rect::xywh(0.0, 0.0, size.width, size.height); + ContentGeometry = FrameGeometry; OnGeometryChanged(); } diff --git a/src/widgets/lineedit/lineedit.cpp b/src/widgets/lineedit/lineedit.cpp index e03e185..e8e55c0 100644 --- a/src/widgets/lineedit/lineedit.cpp +++ b/src/widgets/lineedit/lineedit.cpp @@ -5,6 +5,8 @@ LineEdit::LineEdit(Widget* parent) : Widget(parent) { + SetNoncontentSizes(5.0, 3.0, 5.0, 3.0); + timer = new Timer(this); timer->FuncExpired = [=]() { OnTimerExpired(); }; @@ -1060,18 +1062,20 @@ std::string LineEdit::GetVisibleTextAfterSelection() } } -void LineEdit::OnPaint(Canvas* canvas) +void LineEdit::OnPaintFrame(Canvas* canvas) { - // To do: draw frame elsewhere, maybe in a OnPaintFrame function? - double w = GetWidth(); - double h = GetHeight(); + double w = GetFrameGeometry().width; + double h = GetFrameGeometry().height; Colorf bordercolor(200 / 255.0f, 200 / 255.0f, 200 / 255.0f); canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf(1.0f, 1.0f, 1.0f, 1.0f)); 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(); std::string txt_selected = GetVisibleSelectedText(); std::string txt_after = GetVisibleTextAfterSelection(); diff --git a/src/widgets/textedit/textedit.cpp b/src/widgets/textedit/textedit.cpp index 37f1da7..ec26adf 100644 --- a/src/widgets/textedit/textedit.cpp +++ b/src/widgets/textedit/textedit.cpp @@ -10,6 +10,8 @@ TextEdit::TextEdit(Widget* parent) : Widget(parent) { + SetNoncontentSizes(8.0, 8.0, 8.0, 8.0); + timer = new Timer(this); timer->FuncExpired = [=]() { OnTimerExpired(); }; @@ -584,9 +586,9 @@ void TextEdit::OnVerticalScroll() void TextEdit::UpdateVerticalScroll() { Rect rect( - GetWidth() - vert_scrollbar->GetWidth(), + GetWidth() - 16.0/*vert_scrollbar->GetWidth()*/, 0.0, - GetWidth(), + 16.0/*vert_scrollbar->GetWidth()*/, GetHeight()); vert_scrollbar->SetFrameGeometry(rect); @@ -1000,18 +1002,20 @@ void TextEdit::LayoutLines(Canvas* canvas) UpdateVerticalScroll(); } -void TextEdit::OnPaint(Canvas* canvas) +void TextEdit::OnPaintFrame(Canvas* canvas) { - // To do: draw frame elsewhere, maybe in a OnPaintFrame function? - double w = GetWidth(); - double h = GetHeight(); + double w = GetFrameGeometry().width; + double h = GetFrameGeometry().height; Colorf bordercolor(200 / 255.0f, 200 / 255.0f, 200 / 255.0f); canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf(1.0f, 1.0f, 1.0f, 1.0f)); 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); for (size_t i = vert_scrollbar->GetPosition(); i < lines.size(); i++) lines[i].layout.DrawLayout(canvas);