Add widget state support.
This commit is contained in:
parent
19091a0e80
commit
8536908eab
19 changed files with 385 additions and 46 deletions
|
@ -11,7 +11,10 @@ public:
|
|||
enum class Action
|
||||
{
|
||||
Pressed,
|
||||
Released
|
||||
Released,
|
||||
Move,
|
||||
Enter,
|
||||
Leave
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue