Add widget state support.

This commit is contained in:
jmsgrogan 2023-01-18 13:29:31 +00:00
parent 19091a0e80
commit 8536908eab
19 changed files with 385 additions and 46 deletions

View file

@ -11,7 +11,10 @@ public:
enum class Action
{
Pressed,
Released
Released,
Move,
Enter,
Leave
};
public:

View file

@ -16,7 +16,7 @@ std::unique_ptr<UiEvent> UiEvent::Create()
return std::make_unique<UiEvent>();
}
UiEvent::Type UiEvent::GetType() const
UiEvent::Type UiEvent::getType() const
{
return mType;
}

View file

@ -5,26 +5,38 @@
class UiEvent
{
public:
enum class Type{
enum class Type {
Unknown,
Paint,
Mouse,
Keyboard,
Resize
Resize,
Focus
};
protected:
UiEvent::Type mType;
public:
UiEvent();
virtual ~UiEvent();
static std::unique_ptr<UiEvent> Create();
Type GetType() const;
Type getType() const;
protected:
UiEvent::Type mType;
};
using UiEventUPtr = std::unique_ptr<UiEvent>;
class FocusEvent : public UiEvent
{
public:
FocusEvent()
: UiEvent()
{
};
virtual ~FocusEvent() = default;
};

View file

@ -64,8 +64,6 @@ TransformNode* Widget::getRootNode() const
return mRootNode.get();
}
void Widget::setBackground(Theme::Sys::Color token)
{
if (mBackground != token)
@ -75,6 +73,42 @@ void Widget::setBackground(Theme::Sys::Color token)
}
}
void Widget::setBackgroundOpacity(float opacity)
{
if (mBackgroundOpacity != opacity)
{
mBackgroundOpacity = opacity;
mMaterialDirty = true;
}
}
void Widget::setOutlineThickness(double thickness)
{
if (mBorderThickness != thickness)
{
mBorderThickness = thickness;
mMaterialDirty = true;
}
}
void Widget::setOutline(Theme::Sys::Color token)
{
if (mBorder != token)
{
mBorder = token;
mMaterialDirty = true;
}
}
void Widget::setRadius(double radius)
{
if (mRadius != radius)
{
mRadius = radius;
mGeometryDirty = true;
}
}
void Widget::setVisible(bool visible)
{
if (mVisible != visible)
@ -92,7 +126,7 @@ void Widget::setVisible(bool visible)
bool Widget::isDirty() const
{
return mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
return mStateDirty || mGeometryDirty || mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
}
bool Widget::needsUpdate() const
@ -111,6 +145,11 @@ bool Widget::needsUpdate() const
return false;
}
void Widget::updateState()
{
}
void Widget::doPaint(const PaintEvent* event)
{
updateBackground(event);
@ -127,16 +166,19 @@ void Widget::onPaintEvent(const PaintEvent* event)
{
mRootNode->setName(mName + "_RootNode");
if (mStateDirty)
{
updateState();
mStateDirty = false;
}
doPaint(event);
if (mVisibilityDirty)
{
mRootNode->setIsVisible(mVisible);
}
mTransformDirty = false;
mMaterialDirty = false;
mVisibilityDirty = false;
mVisibilityDirty = false;
}
}
for (auto node : mPendingChildNodes)
@ -212,9 +254,96 @@ bool Widget::onMouseEvent(const MouseEvent* event)
return true;
}
bool Widget::onFocusInEvent(const FocusEvent* event)
{
bool inChild = false;
for (const auto& child : mChildren)
{
if (child->onFocusInEvent(event))
{
inChild = true;
break;
}
}
if (inChild)
{
return true;
}
else if (mAcceptsFocus)
{
setFocus(true);
return true;
}
return false;
}
void Widget::setFocus(bool hasFocus)
{
if (mHasFocus != hasFocus)
{
mHasFocus = hasFocus;
mStateDirty = true;
}
}
void Widget::onMyMouseEvent(const MouseEvent* event)
{
MLOG_INFO("Widget mouse event");
}
void Widget::createOrUpdateGeometry()
{
if (!mBackgroundNode)
{
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;
mBackgroundNode = std::make_unique<RectangleNode>(DiscretePoint(locX, locY), deltaX, deltaY);
mBackgroundNode->setName(mName + "_BackgroundNode");
mRootNode->addChild(mBackgroundNode.get());
}
else
{
mBackgroundNode->setRadius(mRadius);
}
}
void Widget::updateTransform()
{
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;
mBackgroundNode->setWidth(deltaX);
mBackgroundNode->setHeight(deltaY);
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
}
void Widget::updateMaterial(const PaintEvent* event)
{
if (mBackground != Theme::Sys::Color::None)
{
auto background_color = event->getThemesManager()->getColor(mBackground);
background_color.setAlpha(mBackgroundOpacity);
mBackgroundNode->setFillColor(background_color);
}
else
{
mBackgroundNode->setHasFillColor(false);
}
if (mBorder != Theme::Sys::Color::None)
{
mBackgroundNode->setStrokeColor(event->getThemesManager()->getColor(mBorder));
mBackgroundNode->setStrokeThickness(mBorderThickness);
}
else
{
mBackgroundNode->setHasStrokeColor(false);
}
}
void Widget::updateBackground(const PaintEvent* event)
@ -233,16 +362,13 @@ void Widget::updateBackground(const PaintEvent* event)
if (mTransformDirty)
{
mBackgroundNode->setWidth(deltaX);
mBackgroundNode->setHeight(deltaY);
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
updateTransform();
mTransformDirty = false;
}
if (mMaterialDirty)
{
mBackgroundNode->setFillColor(event->getThemesManager()->getColor(mBackground));
mBackgroundNode->setStrokeColor(event->getThemesManager()->getColor(mBorder));
mBackgroundNode->setStrokeThickness(mBorderThickness);
updateMaterial(event);
}
if (mVisibilityDirty)

View file

@ -4,6 +4,7 @@
#include "ITheme.h"
#include "WidgetState.h"
#include "BoxGeometry.h"
#include "TransformNode.h"
#include <memory>
#include <vector>
@ -12,6 +13,7 @@
class MouseEvent;
class KeyboardEvent;
class PaintEvent;
class FocusEvent;
class AbstractVisualNode;
class TransformNode;
@ -47,8 +49,18 @@ public:
virtual bool onKeyboardEvent(const KeyboardEvent* event);
virtual bool onFocusInEvent(const FocusEvent* event);
void setBackgroundOpacity(float opacity);
void setBackground(Theme::Sys::Color token);
void setOutlineThickness(double thickness);
void setOutline(Theme::Sys::Color token);
void setRadius(double radius);
void setVisible(bool visible);
void setName(const std::string& name);
@ -60,6 +72,14 @@ protected:
virtual void onMyMouseEvent(const MouseEvent* event);
virtual void createOrUpdateGeometry();
virtual void updateMaterial(const PaintEvent* event);
virtual void updateTransform();
virtual void updateState();
virtual void updateBackground(const PaintEvent* event);
virtual void doPaint(const PaintEvent* event);
@ -68,6 +88,8 @@ protected:
virtual bool isDirty() const;
void setFocus(bool hasFocus);
void setParent(Widget* parent);
Widget* getParent() const;
@ -77,16 +99,26 @@ protected:
std::unique_ptr<TransformNode> mRootNode;
std::vector<std::unique_ptr<Widget> > mChildren;
unsigned mBorderThickness{0};
Theme::Sys::Color mBackground;
Theme::Sys::Color mBorder;
double mBorderThickness{0};
Theme::Sys::Color mBackground;
float mBackgroundOpacity{ 1.0 };
bool mVisible{true};
double mRadius{ 0.0 };
std::unique_ptr<RectangleNode> mBackgroundNode;
bool mStateDirty{ true };
bool mMaterialDirty{true};
bool mVisibilityDirty{true};
bool mGeometryDirty{ true };
bool mAcceptsFocus{ false };
bool mHasFocus{ false };
bool mContainsMouse{ false };
std::string mName;
std::vector<TransformNode*> mPendingChildNodes;