Skip to content

Commit

Permalink
Add non-content areas to widgets
Browse files Browse the repository at this point in the history
Improve font subpixel rendering
Fix scrollbar position
  • Loading branch information
dpjudas committed Nov 6, 2023
1 parent 821c96b commit e74601e
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 37 deletions.
15 changes: 14 additions & 1 deletion include/zwidget/core/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) { }
Expand Down Expand Up @@ -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<DisplayWindow> DispWindow;
Expand Down
1 change: 1 addition & 0 deletions include/zwidget/widgets/lineedit/lineedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class LineEdit : public Widget
std::function<void()> 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;
Expand Down
3 changes: 2 additions & 1 deletion include/zwidget/widgets/textedit/textedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class TextEdit : public Widget
std::function<void()> 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;
Expand Down
24 changes: 11 additions & 13 deletions src/core/canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ class CanvasFont
texture->Data.resize(destwidth * h);
uint32_t* dest = (uint32_t*)texture->Data.data();

std::unique_ptr<uint8_t[]> grayscalebuffer(new uint8_t[w * h]);
std::unique_ptr<uint8_t[]> grayscalebuffer(new uint8_t[w
* h]);
uint8_t* grayscale = grayscalebuffer.get();

SFT_Image img = {};
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
48 changes: 36 additions & 12 deletions src/core/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,26 +108,43 @@ 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
{
return DispWindow->GetWindowFrame();
}
}

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
Expand Down Expand Up @@ -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())
{
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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");
}
Expand All @@ -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");
}
Expand All @@ -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");
}
Expand All @@ -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");
}
Expand Down Expand Up @@ -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();
}

Expand Down
12 changes: 8 additions & 4 deletions src/widgets/lineedit/lineedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(); };

Expand Down Expand Up @@ -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();
Expand Down
16 changes: 10 additions & 6 deletions src/widgets/textedit/textedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(); };

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e74601e

Please sign in to comment.