Set up stacked widget.

This commit is contained in:
jmsgrogan 2020-06-27 10:47:30 +01:00
parent 4e85edacc8
commit ee51f3ee09
51 changed files with 808 additions and 195 deletions

View file

@ -11,6 +11,7 @@ list(APPEND ui_elements_LIB_INCLUDES
widgets/Label.cpp
widgets/HorizontalSpacer.cpp
widgets/VerticalSpacer.cpp
widgets/StackWidget.cpp
widgets/TextBox.cpp
widgets/elements/GeometryElement.cpp
widgets/elements/RectangleElement.cpp

View file

@ -37,7 +37,7 @@ void Window::OnKeyboardEvent(const KeyboardEvent* event)
void Window::OnPaint(const PaintEvent* event)
{
mLayers.clear();
mWidget->SetSize(mWidth, mHeight);
mWidget->SetBounds(mWidth, mHeight);
mWidget->OnPaintEvent(event);
auto layers = mWidget->GetLayers();

View file

@ -4,9 +4,10 @@
Button::Button()
: Widget(),
mLabel(),
mCachedColor(255, 255, 255),
mClickFunc()
{
mClickedColor = Color::Create(180, 180, 180);
}
std::unique_ptr<Button> Button::Create()
@ -28,15 +29,16 @@ void Button::OnMyMouseEvent(const MouseEvent* event)
{
if(event->GetAction() == MouseEvent::Action::Pressed)
{
SetBackgroundColor(Color::Create(0, 255, 0));
mCachedColor = *mBackgroundColor;
SetBackgroundColor(Color::Create(*mClickedColor));
if(mClickFunc)
{
mClickFunc();
mClickFunc(this);
}
}
else if(event->GetAction() == MouseEvent::Action::Released)
{
SetBackgroundColor(Color::Create(0, 255, 255));
SetBackgroundColor(Color::Create(mCachedColor));
}
}
@ -46,10 +48,13 @@ void Button::OnPaintEvent(const PaintEvent* event)
AddBackground(event);
if(!mLabel.empty())
{
auto middle = DiscretePoint(mLocation.GetX() + mWidth/2,
mLocation.GetY() + mHeight/2);
unsigned fontOffset = mLabel.size() * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset,
mLocation.GetY() + mSize.mHeight/2 + 4);
auto textLayer = VisualLayer::Create();
textLayer->SetText(TextElement::Create(mLabel, middle));
auto textElement = TextElement::Create(mLabel, middle);
textElement->SetFillColor(Color::Create(*mBackgroundColor));
textLayer->SetText(std::move(textElement));
mMyLayers.push_back(std::move(textLayer));
}
CopyMyLayers();

View file

@ -6,9 +6,11 @@
class Button : public Widget
{
private:
using clickFunc = std::function<void()>;
using clickFunc = std::function<void(Widget* self)>;
std::string mLabel;
clickFunc mClickFunc;
Color mCachedColor;
ColorUPtr mClickedColor;
public:
Button();

View file

@ -31,21 +31,22 @@ void HorizontalSpacer::AddChildLayers(const PaintEvent* event)
mLayers.clear();
double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0);
double offset = 0;
double height = mHeight;
if (mMaxHeight > 0 && height > mMaxHeight)
double height = mSize.mHeight;
if (mSize.mMaxHeight > 0 && height > mSize.mMaxHeight)
{
height = mMaxHeight;
height = mSize.mMaxHeight;
}
for(std::size_t idx=0; idx<mChildren.size(); idx++)
{
auto& child = mChildren[idx];
double scale = mScales[idx];
double delta = height * (scale/scaleSum);
if (child->GetMaxHeight() > 0 && delta > child->GetMaxHeight())
auto size = child->GetSize();
if (size.mMaxHeight > 0 && delta > size.mMaxHeight)
{
delta = child->GetMaxHeight();
delta = size.mMaxHeight;
}
child->SetSize(mWidth, delta);
child->SetBounds(mSize.mWidth, delta);
child->SetLocation(DiscretePoint(mLocation.GetX(), mLocation.GetY() + offset));
child->OnPaintEvent(event);
auto layers = child->GetLayers();

View file

@ -25,10 +25,13 @@ void Label::OnPaintEvent(const PaintEvent* event)
if(!mLabel.empty())
{
auto middle = DiscretePoint(mLocation.GetX() + mWidth/2,
mLocation.GetY() + mHeight/2);
unsigned fontOffset = mLabel.size() * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset,
mLocation.GetY() + mSize.mHeight/2 + 4);
auto textLayer = VisualLayer::Create();
textLayer->SetText(TextElement::Create(mLabel, middle));
auto textElement = TextElement::Create(mLabel, middle);
textElement->SetFillColor(Color::Create(*mBackgroundColor));
textLayer->SetText(std::move(textElement));
mMyLayers.push_back(std::move(textLayer));
}
CopyMyLayers();

View file

@ -0,0 +1,26 @@
#include "StackWidget.h"
StackWidget::StackWidget()
{
}
std::unique_ptr<StackWidget> StackWidget::Create()
{
return std::make_unique<StackWidget>();
}
void StackWidget::ShowChild(Widget* target)
{
for(auto& child : mChildren)
{
if(child.get() == target)
{
child->SetVisible(true);
}
else
{
child->SetVisible(false);
}
}
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "Widget.h"
class StackWidget : public Widget
{
public:
StackWidget();
static std::unique_ptr<StackWidget> Create();
void ShowChild(Widget* child);
};
using StackWidgetUPtr = std::unique_ptr<StackWidget>;

View file

@ -8,7 +8,8 @@ TextBox::TextBox()
mContent(),
mCaps(false)
{
mBackgroundColor = Color::Create(240, 240, 220);
mBackgroundColor = Color::Create(250, 250, 250);
mPadding = {10, 0, 10, 0};
}
std::unique_ptr<TextBox> TextBox::Create()
@ -64,7 +65,6 @@ bool TextBox::OnMyKeyboardEvent(const KeyboardEvent* event)
AppendContent(keyString);
}
}
return true;
}
@ -85,12 +85,14 @@ void TextBox::OnPaintEvent(const PaintEvent* event)
}
for(const auto& line : seglist)
{
auto loc = DiscretePoint(mLocation.GetX() + mWidth/10,
mLocation.GetY() + mHeight/10 + offset);
auto loc = DiscretePoint(mLocation.GetX() + mPadding.mLeft,
mLocation.GetY() + mPadding.mTop + offset);
auto textLayer = VisualLayer::Create();
textLayer->SetText(TextElement::Create(line, loc));
auto textElement = TextElement::Create(line, loc);
textElement->SetFillColor(Color::Create(*mBackgroundColor));
textLayer->SetText(std::move(textElement));
mMyLayers.push_back(std::move(textLayer));
offset += 15;
offset += 20;
}
}
CopyMyLayers();

View file

@ -31,13 +31,13 @@ void VerticalSpacer::AddChildLayers(const PaintEvent* event)
mLayers.clear();
double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0);
double offset = 0;
unsigned delta = mWidth / mChildren.size();
unsigned delta = mSize.mWidth / mChildren.size();
for(std::size_t idx=0; idx<mChildren.size(); idx++)
{
auto& child = mChildren[idx];
double scale = mScales[idx];
double delta = mWidth * (scale/scaleSum);
child->SetSize(delta, mHeight);
double delta = mSize.mWidth * (scale/scaleSum);
child->SetBounds(delta, mSize.mHeight);
child->SetLocation(DiscretePoint(mLocation.GetX() + offset, mLocation.GetY()));
child->OnPaintEvent(event);
auto layers = child->GetLayers();

View file

@ -5,13 +5,16 @@
Widget::Widget()
: mLocation(DiscretePoint(0, 0)),
mWidth(100),
mHeight(100),
mMaxHeight(0),
mSize({100, 0, 0, 100, 0, 0}),
mPadding(),
mMargin(),
mMyLayers(),
mLayers(),
mChildren(),
mBackgroundColor(Color::Create(200, 0, 0))
mBorderThickness(0),
mBackgroundColor(Color::Create(255, 255, 255)),
mBorderColor(Color::Create(0, 0, 0)),
mVisible(true)
{
}
@ -31,14 +34,9 @@ void Widget::AddWidget(WidgetUPtr widget)
mChildren.push_back(std::move(widget));
}
unsigned Widget::GetWidth() const
Widget::BoundedSize Widget::GetSize() const
{
return mWidth;
}
unsigned Widget::GetHeight() const
{
return mHeight;
return mSize;
}
DiscretePoint Widget::GetLocation() const
@ -51,14 +49,29 @@ std::vector<VisualLayer*> Widget::GetLayers() const
return mLayers;
}
unsigned Widget::GetMaxHeight() const
void Widget::SetSize(const BoundedSize& size)
{
return mMaxHeight;
mSize = size;
}
void Widget::SetMaxHeight(unsigned maxHeight)
void Widget::SetMargin(unsigned margin)
{
mMaxHeight = maxHeight;
mMargin = {margin, margin, margin, margin};
}
void Widget::SetMargin(const BoundaryOffset& margin)
{
mMargin = margin;
}
void Widget::SetPadding(unsigned padding)
{
mPadding = {padding, padding, padding, padding};
}
void Widget::SetPadding(const BoundaryOffset& padding)
{
mPadding = padding;
}
void Widget::CopyMyLayers()
@ -69,11 +82,17 @@ void Widget::CopyMyLayers()
std::transform(mMyLayers.begin(), mMyLayers.end(), std::back_inserter(mLayers), getRaw);
}
void Widget::SetBounds(unsigned width, unsigned height)
{
mSize.mWidth = width;
mSize.mHeight = height;
}
void Widget::AddChildLayers(const PaintEvent* event)
{
for(auto& child: mChildren)
{
child->SetSize(mWidth, mHeight);
child->SetBounds(mSize.mWidth, mSize.mHeight);
child->SetLocation(mLocation);
child->OnPaintEvent(event);
const auto layers = child->GetLayers();
@ -84,6 +103,9 @@ void Widget::AddChildLayers(const PaintEvent* event)
void Widget::OnPaintEvent(const PaintEvent* event)
{
mMyLayers.clear();
mLayers.clear();
if(!mVisible)return;
AddBackground(event);
CopyMyLayers();
AddChildLayers(event);
@ -92,8 +114,8 @@ void Widget::OnPaintEvent(const PaintEvent* event)
bool Widget::Contains(const DiscretePoint& loc) const
{
if(loc.GetX() < mLocation.GetX()) return false;
if(loc.GetX() > mLocation.GetX() + mWidth) return false;
if(loc.GetY() > mLocation.GetY() + mHeight) return false;
if(loc.GetX() > mLocation.GetX() + mSize.mWidth) return false;
if(loc.GetY() > mLocation.GetY() + mSize.mHeight) return false;
if(loc.GetY() < mLocation.GetY()) return false;
return true;
}
@ -154,7 +176,12 @@ void Widget::OnMyMouseEvent(const MouseEvent* event)
void Widget::AddBackground(const PaintEvent* event)
{
auto shape = RectangleElement::Create(mLocation, mWidth, mHeight);
unsigned locX = mLocation.GetX() + mMargin.mLeft;
unsigned locY = mLocation.GetY() + mMargin.mTop;
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
auto shape = RectangleElement::Create(DiscretePoint(locX, locY),
deltaX, deltaY);
shape->SetFillColor(Color::Create(*mBackgroundColor));
auto shapeLayer = VisualLayer::Create();
shapeLayer->SetShape(std::move(shape));
@ -171,8 +198,7 @@ void Widget::SetLocation(const DiscretePoint& loc)
mLocation = loc;
}
void Widget::SetSize(unsigned width, unsigned height)
void Widget::SetVisible(bool visible)
{
mWidth = width;
mHeight = height;
mVisible = visible;
}

View file

@ -12,16 +12,35 @@
class Widget
{
protected:
public:
struct BoundaryOffset{
unsigned mLeft = 0;
unsigned mRight = 0;
unsigned mTop = 0;
unsigned mBottom = 0;
};
struct BoundedSize{
unsigned mWidth = 0;
unsigned mMaxWidth = 0;
unsigned mMinWidth = 0;
unsigned mHeight = 0;
unsigned mMaxHeight = 0;
unsigned mMinHeight = 0;
};
protected:
DiscretePoint mLocation;
unsigned mWidth;
unsigned mHeight;
unsigned mMaxHeight;
BoundedSize mSize;
BoundaryOffset mPadding;
BoundaryOffset mMargin;
std::vector<VisualLayerUPtr> mMyLayers;
std::vector<VisualLayer*> mLayers;
std::vector<std::unique_ptr<Widget> > mChildren;
unsigned mBorderThickness;
ColorUPtr mBackgroundColor;
ColorUPtr mBorderColor;
bool mVisible;
public:
@ -33,11 +52,7 @@ public:
virtual void AddWidget(std::unique_ptr<Widget> widget);
unsigned GetWidth() const;
unsigned GetHeight() const;
unsigned GetMaxHeight() const;
BoundedSize GetSize() const;
std::vector<VisualLayer*> GetLayers() const;
@ -53,11 +68,21 @@ public:
void SetBackgroundColor(ColorUPtr color);
void SetSize(unsigned mWidth, unsigned mHeight);
void SetBounds(unsigned width, unsigned height);
void SetSize(const BoundedSize& size);
void SetMargin(unsigned margin);
void SetMargin(const BoundaryOffset& margin);
void SetPadding(unsigned padding);
void SetPadding(const BoundaryOffset& padding);
void SetLocation(const DiscretePoint& loc);
void SetMaxHeight(unsigned maxHeight);
void SetVisible(bool visible);
protected:

View file

@ -3,7 +3,9 @@
TextElement::TextElement(const std::string& content, const DiscretePoint& loc)
: mContent(content),
mLocation(loc),
mFontLabel("7x14")
mFontLabel("7x14"),
mFillColor(Color::Create(255, 255, 255)),
mStrokeColor(Color::Create(0, 0, 0))
{
// https://en.wikipedia.org/wiki/Fixed_(typeface)#:~:text=misc%2Dfixed%20is%20a%20collection,to%20a%20single%20font%20family.
}
@ -18,6 +20,15 @@ std::unique_ptr<TextElement> TextElement::Create(const std::string& content, con
return std::make_unique<TextElement>(content, loc);
}
Color* TextElement::GetFillColor() const
{
return mFillColor.get();
}
Color* TextElement::GetStrokeColor() const
{
return mStrokeColor.get();
}
DiscretePoint TextElement::GetLocation() const
{
return mLocation;
@ -37,3 +48,13 @@ void TextElement::SetContent(const std::string& content)
{
mContent = content;
}
void TextElement::SetFillColor(ColorUPtr color)
{
mFillColor = std::move(color);
}
void TextElement::SetStrokeColor(ColorUPtr color)
{
mStrokeColor = std::move(color);
}

View file

@ -4,12 +4,15 @@
#include <string>
#include "DiscretePoint.h"
#include "Color.h"
class TextElement
{
std::string mContent;
DiscretePoint mLocation;
std::string mFontLabel;
ColorUPtr mFillColor;
ColorUPtr mStrokeColor;
public:
@ -19,13 +22,15 @@ public:
static std::unique_ptr<TextElement> Create(const std::string& content, const DiscretePoint& loc);
Color* GetFillColor() const;
Color* GetStrokeColor() const;
DiscretePoint GetLocation() const;
std::string GetContent() const;
std::string GetFontLabel() const;
void SetContent(const std::string& content);
void SetFillColor(ColorUPtr color);
void SetStrokeColor(ColorUPtr color);
};
using TextElementUPtr = std::unique_ptr<TextElement>;