Add widget state support.
This commit is contained in:
parent
19091a0e80
commit
8536908eab
19 changed files with 385 additions and 46 deletions
|
@ -25,6 +25,11 @@ public:
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
void setAlpha(float alpha)
|
||||||
|
{
|
||||||
|
mAlpha = static_cast<double>(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const Color& rhs) const
|
bool operator==(const Color& rhs) const
|
||||||
{
|
{
|
||||||
return (mR == rhs.mR)
|
return (mR == rhs.mR)
|
||||||
|
|
|
@ -50,4 +50,14 @@ namespace ntk {
|
||||||
{
|
{
|
||||||
return mBottomLeft;
|
return mBottomLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Rectangle::getRadius() const
|
||||||
|
{
|
||||||
|
return mRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rectangle::setRadius(double radius)
|
||||||
|
{
|
||||||
|
mRadius = radius;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,17 @@ public:
|
||||||
|
|
||||||
Type getType() const override;
|
Type getType() const override;
|
||||||
|
|
||||||
|
double getRadius() const;
|
||||||
|
|
||||||
|
void setRadius(double radius);
|
||||||
|
|
||||||
void sample(SparseGrid<bool>* grid) const override;
|
void sample(SparseGrid<bool>* grid) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mBottomLeft;
|
Point mBottomLeft;
|
||||||
double mWidth{0};
|
double mWidth{0};
|
||||||
double mHeight{0};
|
double mHeight{0};
|
||||||
|
double mRadius{ 0.0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,11 @@ double RectangleNode::getHeight() const
|
||||||
return mHeight;
|
return mHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double RectangleNode::getRadius() const
|
||||||
|
{
|
||||||
|
return mRadius;
|
||||||
|
}
|
||||||
|
|
||||||
void RectangleNode::setWidth(double width)
|
void RectangleNode::setWidth(double width)
|
||||||
{
|
{
|
||||||
if (mWidth != width)
|
if (mWidth != width)
|
||||||
|
@ -51,20 +56,42 @@ void RectangleNode::setHeight(double height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RectangleNode::setRadius(double radius)
|
||||||
|
{
|
||||||
|
if (mRadius != radius)
|
||||||
|
{
|
||||||
|
mGeometryIsDirty = true;
|
||||||
|
mRadius = radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
if (!mBackgroundItem)
|
||||||
{
|
{
|
||||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
|
if (sceneInfo->mSupportsGeometryPrimitives)
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
|
{
|
||||||
|
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
|
||||||
|
rect->setRadius(mRadius);
|
||||||
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
|
||||||
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
|
||||||
|
|
||||||
|
}
|
||||||
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
|
if (sceneInfo->mSupportsGeometryPrimitives)
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
|
{
|
||||||
|
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
|
||||||
|
rect->setRadius(mRadius);
|
||||||
|
mBackgroundItem->updateGeometry(std::move(rect));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RectangleNode::updateTransform()
|
void RectangleNode::updateTransform()
|
||||||
|
|
|
@ -14,15 +14,19 @@ public:
|
||||||
|
|
||||||
double getWidth() const;
|
double getWidth() const;
|
||||||
double getHeight() const;
|
double getHeight() const;
|
||||||
|
double getRadius() const;
|
||||||
|
|
||||||
void setWidth(double width);
|
void setWidth(double width);
|
||||||
void setHeight(double height);
|
void setHeight(double height);
|
||||||
|
void setRadius(double radius);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
||||||
void updateTransform() override;
|
void updateTransform() override;
|
||||||
|
|
||||||
double mWidth{1};
|
double mWidth{1};
|
||||||
double mHeight{1};
|
double mHeight{1};
|
||||||
|
double mRadius{ 0.0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
using RectangleNodePtr = std::unique_ptr<RectangleNode>;
|
using RectangleNodePtr = std::unique_ptr<RectangleNode>;
|
||||||
|
|
|
@ -29,6 +29,15 @@ void MaterialNode::setHasStrokeColor(bool hasStroke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MaterialNode::setHasFillColor(bool hasFill)
|
||||||
|
{
|
||||||
|
if (mHasFillColor != hasFill)
|
||||||
|
{
|
||||||
|
mHasFillColor = hasFill;
|
||||||
|
mMaterialIsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MaterialNode::setFillColor(const Color& color)
|
void MaterialNode::setFillColor(const Color& color)
|
||||||
{
|
{
|
||||||
mHasFillColor = true;
|
mHasFillColor = true;
|
||||||
|
|
|
@ -13,6 +13,7 @@ public:
|
||||||
const Color& getStrokeColor() const;
|
const Color& getStrokeColor() const;
|
||||||
|
|
||||||
void setHasStrokeColor(bool hasStroke);
|
void setHasStrokeColor(bool hasStroke);
|
||||||
|
void setHasFillColor(bool hasFill);
|
||||||
|
|
||||||
void setFillColor(const Color& color);
|
void setFillColor(const Color& color);
|
||||||
void setStrokeColor(const Color& color);
|
void setStrokeColor(const Color& color);
|
||||||
|
|
|
@ -42,22 +42,79 @@ void Button::setLabel(const std::string& text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Button::setState(ButtonData::State state)
|
||||||
|
{
|
||||||
|
if (mStyle.mState != state)
|
||||||
|
{
|
||||||
|
mStyle.mState = state;
|
||||||
|
mStateDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::setEnabled(bool isEnabled)
|
||||||
|
{
|
||||||
|
if (mEnabled != isEnabled)
|
||||||
|
{
|
||||||
|
mEnabled = isEnabled;
|
||||||
|
if (mStyle.mState == ButtonData::State::Disabled)
|
||||||
|
{
|
||||||
|
setState(ButtonData::State::Enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::updateState()
|
||||||
|
{
|
||||||
|
setBackground(mStyle.getContainerColor());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Button::onMyMouseEvent(const MouseEvent* event)
|
void Button::onMyMouseEvent(const MouseEvent* event)
|
||||||
{
|
{
|
||||||
MLOG_INFO("Widget mouse event");
|
if (!mEnabled)
|
||||||
if(event->getAction() == MouseEvent::Action::Pressed)
|
|
||||||
{
|
{
|
||||||
mStyle.mState = ButtonData::State::Pressed;
|
return;
|
||||||
setBackground(mStyle.getContainerColor());
|
}
|
||||||
if(mClickFunc)
|
|
||||||
|
if (event->getAction() == MouseEvent::Action::Pressed)
|
||||||
|
{
|
||||||
|
setState(ButtonData::State::Pressed);
|
||||||
|
}
|
||||||
|
else if (event->getAction() == MouseEvent::Action::Released)
|
||||||
|
{
|
||||||
|
resetState();
|
||||||
|
if (mClickFunc)
|
||||||
{
|
{
|
||||||
mClickFunc(this);
|
mClickFunc(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(event->getAction() == MouseEvent::Action::Released)
|
else if (event->getAction() == MouseEvent::Action::Enter)
|
||||||
{
|
{
|
||||||
mStyle.mState = ButtonData::State::Enabled;
|
resetState();
|
||||||
setBackground(mStyle.getContainerColor());
|
}
|
||||||
|
else if (event->getAction() == MouseEvent::Action::Leave)
|
||||||
|
{
|
||||||
|
resetState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::resetState()
|
||||||
|
{
|
||||||
|
if (mHasFocus)
|
||||||
|
{
|
||||||
|
setState(ButtonData::State::Focused);
|
||||||
|
}
|
||||||
|
else if (mContainsMouse)
|
||||||
|
{
|
||||||
|
setState(ButtonData::State::Hovered);
|
||||||
|
}
|
||||||
|
else if (mEnabled)
|
||||||
|
{
|
||||||
|
setState(ButtonData::State::Enabled);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setState(ButtonData::State::Disabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ public:
|
||||||
|
|
||||||
void setLabel(const std::string& text);
|
void setLabel(const std::string& text);
|
||||||
|
|
||||||
|
void setEnabled(bool isEnabled);
|
||||||
|
|
||||||
void setOnClickFunction(clickFunc func);
|
void setOnClickFunction(clickFunc func);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -34,6 +36,10 @@ protected:
|
||||||
|
|
||||||
void updateLabel(const PaintEvent* event);
|
void updateLabel(const PaintEvent* event);
|
||||||
|
|
||||||
|
void setState(ButtonData::State state);
|
||||||
|
void resetState();
|
||||||
|
void updateState() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ButtonData mStyle;
|
ButtonData mStyle;
|
||||||
|
|
||||||
|
@ -42,6 +48,8 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<TextNode> mTextNode;
|
std::unique_ptr<TextNode> mTextNode;
|
||||||
bool mContentDirty{true};
|
bool mContentDirty{true};
|
||||||
|
|
||||||
|
bool mEnabled{ true };
|
||||||
};
|
};
|
||||||
|
|
||||||
using ButtonUPtr = std::unique_ptr<Button>;
|
using ButtonUPtr = std::unique_ptr<Button>;
|
||||||
|
|
|
@ -11,7 +11,10 @@ public:
|
||||||
enum class Action
|
enum class Action
|
||||||
{
|
{
|
||||||
Pressed,
|
Pressed,
|
||||||
Released
|
Released,
|
||||||
|
Move,
|
||||||
|
Enter,
|
||||||
|
Leave
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -16,7 +16,7 @@ std::unique_ptr<UiEvent> UiEvent::Create()
|
||||||
return std::make_unique<UiEvent>();
|
return std::make_unique<UiEvent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
UiEvent::Type UiEvent::GetType() const
|
UiEvent::Type UiEvent::getType() const
|
||||||
{
|
{
|
||||||
return mType;
|
return mType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,26 +5,38 @@
|
||||||
class UiEvent
|
class UiEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum class Type {
|
||||||
enum class Type{
|
|
||||||
Unknown,
|
Unknown,
|
||||||
Paint,
|
Paint,
|
||||||
Mouse,
|
Mouse,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Resize
|
Resize,
|
||||||
|
Focus
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
|
||||||
UiEvent::Type mType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
UiEvent();
|
UiEvent();
|
||||||
|
|
||||||
virtual ~UiEvent();
|
virtual ~UiEvent();
|
||||||
|
|
||||||
static std::unique_ptr<UiEvent> Create();
|
static std::unique_ptr<UiEvent> Create();
|
||||||
|
|
||||||
Type GetType() const;
|
Type getType() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UiEvent::Type mType;
|
||||||
};
|
};
|
||||||
using UiEventUPtr = std::unique_ptr<UiEvent>;
|
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();
|
return mRootNode.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Widget::setBackground(Theme::Sys::Color token)
|
void Widget::setBackground(Theme::Sys::Color token)
|
||||||
{
|
{
|
||||||
if (mBackground != 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)
|
void Widget::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (mVisible != visible)
|
if (mVisible != visible)
|
||||||
|
@ -92,7 +126,7 @@ void Widget::setVisible(bool visible)
|
||||||
|
|
||||||
bool Widget::isDirty() const
|
bool Widget::isDirty() const
|
||||||
{
|
{
|
||||||
return mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
|
return mStateDirty || mGeometryDirty || mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::needsUpdate() const
|
bool Widget::needsUpdate() const
|
||||||
|
@ -111,6 +145,11 @@ bool Widget::needsUpdate() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::updateState()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::doPaint(const PaintEvent* event)
|
void Widget::doPaint(const PaintEvent* event)
|
||||||
{
|
{
|
||||||
updateBackground(event);
|
updateBackground(event);
|
||||||
|
@ -127,16 +166,19 @@ void Widget::onPaintEvent(const PaintEvent* event)
|
||||||
{
|
{
|
||||||
mRootNode->setName(mName + "_RootNode");
|
mRootNode->setName(mName + "_RootNode");
|
||||||
|
|
||||||
|
if (mStateDirty)
|
||||||
|
{
|
||||||
|
updateState();
|
||||||
|
mStateDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
doPaint(event);
|
doPaint(event);
|
||||||
|
|
||||||
if (mVisibilityDirty)
|
if (mVisibilityDirty)
|
||||||
{
|
{
|
||||||
mRootNode->setIsVisible(mVisible);
|
mRootNode->setIsVisible(mVisible);
|
||||||
}
|
mVisibilityDirty = false;
|
||||||
|
}
|
||||||
mTransformDirty = false;
|
|
||||||
mMaterialDirty = false;
|
|
||||||
mVisibilityDirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto node : mPendingChildNodes)
|
for (auto node : mPendingChildNodes)
|
||||||
|
@ -212,9 +254,96 @@ bool Widget::onMouseEvent(const MouseEvent* event)
|
||||||
return true;
|
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)
|
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)
|
void Widget::updateBackground(const PaintEvent* event)
|
||||||
|
@ -233,16 +362,13 @@ void Widget::updateBackground(const PaintEvent* event)
|
||||||
|
|
||||||
if (mTransformDirty)
|
if (mTransformDirty)
|
||||||
{
|
{
|
||||||
mBackgroundNode->setWidth(deltaX);
|
updateTransform();
|
||||||
mBackgroundNode->setHeight(deltaY);
|
mTransformDirty = false;
|
||||||
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMaterialDirty)
|
if (mMaterialDirty)
|
||||||
{
|
{
|
||||||
mBackgroundNode->setFillColor(event->getThemesManager()->getColor(mBackground));
|
updateMaterial(event);
|
||||||
mBackgroundNode->setStrokeColor(event->getThemesManager()->getColor(mBorder));
|
|
||||||
mBackgroundNode->setStrokeThickness(mBorderThickness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVisibilityDirty)
|
if (mVisibilityDirty)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "ITheme.h"
|
#include "ITheme.h"
|
||||||
#include "WidgetState.h"
|
#include "WidgetState.h"
|
||||||
#include "BoxGeometry.h"
|
#include "BoxGeometry.h"
|
||||||
|
#include "TransformNode.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
class MouseEvent;
|
class MouseEvent;
|
||||||
class KeyboardEvent;
|
class KeyboardEvent;
|
||||||
class PaintEvent;
|
class PaintEvent;
|
||||||
|
class FocusEvent;
|
||||||
|
|
||||||
class AbstractVisualNode;
|
class AbstractVisualNode;
|
||||||
class TransformNode;
|
class TransformNode;
|
||||||
|
@ -47,8 +49,18 @@ public:
|
||||||
|
|
||||||
virtual bool onKeyboardEvent(const KeyboardEvent* event);
|
virtual bool onKeyboardEvent(const KeyboardEvent* event);
|
||||||
|
|
||||||
|
virtual bool onFocusInEvent(const FocusEvent* event);
|
||||||
|
|
||||||
|
void setBackgroundOpacity(float opacity);
|
||||||
|
|
||||||
void setBackground(Theme::Sys::Color token);
|
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 setVisible(bool visible);
|
||||||
|
|
||||||
void setName(const std::string& name);
|
void setName(const std::string& name);
|
||||||
|
@ -60,6 +72,14 @@ protected:
|
||||||
|
|
||||||
virtual void onMyMouseEvent(const MouseEvent* event);
|
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 updateBackground(const PaintEvent* event);
|
||||||
|
|
||||||
virtual void doPaint(const PaintEvent* event);
|
virtual void doPaint(const PaintEvent* event);
|
||||||
|
@ -68,6 +88,8 @@ protected:
|
||||||
|
|
||||||
virtual bool isDirty() const;
|
virtual bool isDirty() const;
|
||||||
|
|
||||||
|
void setFocus(bool hasFocus);
|
||||||
|
|
||||||
void setParent(Widget* parent);
|
void setParent(Widget* parent);
|
||||||
|
|
||||||
Widget* getParent() const;
|
Widget* getParent() const;
|
||||||
|
@ -77,16 +99,26 @@ protected:
|
||||||
std::unique_ptr<TransformNode> mRootNode;
|
std::unique_ptr<TransformNode> mRootNode;
|
||||||
std::vector<std::unique_ptr<Widget> > mChildren;
|
std::vector<std::unique_ptr<Widget> > mChildren;
|
||||||
|
|
||||||
unsigned mBorderThickness{0};
|
|
||||||
Theme::Sys::Color mBackground;
|
|
||||||
Theme::Sys::Color mBorder;
|
Theme::Sys::Color mBorder;
|
||||||
|
double mBorderThickness{0};
|
||||||
|
|
||||||
|
Theme::Sys::Color mBackground;
|
||||||
|
float mBackgroundOpacity{ 1.0 };
|
||||||
|
|
||||||
bool mVisible{true};
|
bool mVisible{true};
|
||||||
|
double mRadius{ 0.0 };
|
||||||
|
|
||||||
std::unique_ptr<RectangleNode> mBackgroundNode;
|
std::unique_ptr<RectangleNode> mBackgroundNode;
|
||||||
|
|
||||||
|
bool mStateDirty{ true };
|
||||||
bool mMaterialDirty{true};
|
bool mMaterialDirty{true};
|
||||||
bool mVisibilityDirty{true};
|
bool mVisibilityDirty{true};
|
||||||
|
bool mGeometryDirty{ true };
|
||||||
|
|
||||||
|
bool mAcceptsFocus{ false };
|
||||||
|
bool mHasFocus{ false };
|
||||||
|
|
||||||
|
bool mContainsMouse{ false };
|
||||||
|
|
||||||
std::string mName;
|
std::string mName;
|
||||||
std::vector<TransformNode*> mPendingChildNodes;
|
std::vector<TransformNode*> mPendingChildNodes;
|
||||||
|
|
|
@ -62,7 +62,7 @@ void DesktopManager::onMouseEvent(const MouseEvent* event)
|
||||||
void DesktopManager::onUiEvent(UiEventUPtr eventUPtr)
|
void DesktopManager::onUiEvent(UiEventUPtr eventUPtr)
|
||||||
{
|
{
|
||||||
const auto event = mEventManager->AddEvent(std::move(eventUPtr));
|
const auto event = mEventManager->AddEvent(std::move(eventUPtr));
|
||||||
switch (event->GetType())
|
switch (event->getType())
|
||||||
{
|
{
|
||||||
case (UiEvent::Type::Paint):
|
case (UiEvent::Type::Paint):
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
add_subdirectory(test_utils)
|
add_subdirectory(test_utils)
|
||||||
|
|
||||||
|
add_subdirectory(ui_controls)
|
||||||
|
|
||||||
file(COPY data/ DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_data)
|
file(COPY data/ DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_data)
|
||||||
|
|
||||||
set(TEST_MODULES
|
set(TEST_MODULES
|
||||||
|
|
|
@ -25,8 +25,6 @@ public:
|
||||||
mDrawingContext = std::make_unique<DrawingContext>(mSurface.get());
|
mDrawingContext = std::make_unique<DrawingContext>(mSurface.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scene* getScene() const
|
Scene* getScene() const
|
||||||
{
|
{
|
||||||
return mSurface->getScene();
|
return mSurface->getScene();
|
||||||
|
|
11
test/ui_controls/CMakeLists.txt
Normal file
11
test/ui_controls/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
set(MODULE_NAME ui_controls)
|
||||||
|
|
||||||
|
list(APPEND UNIT_TEST_FILES
|
||||||
|
TestButton.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(UNIT_TEST_TARGET_NAME ${MODULE_NAME}_unit_tests)
|
||||||
|
|
||||||
|
add_executable(${UNIT_TEST_TARGET_NAME} ${CMAKE_SOURCE_DIR}/test/test_runner.cpp ${UNIT_TEST_FILES})
|
||||||
|
target_link_libraries(${UNIT_TEST_TARGET_NAME} PUBLIC test_utils ui_controls)
|
||||||
|
set_property(TARGET ${UNIT_TEST_TARGET_NAME} PROPERTY FOLDER test/${MODULE_NAME})
|
29
test/ui_controls/TestButton.cpp
Normal file
29
test/ui_controls/TestButton.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include "TestFramework.h"
|
||||||
|
#include "TestUtils.h"
|
||||||
|
#include "TestRenderUtils.h"
|
||||||
|
|
||||||
|
#include "ThemeManager.h"
|
||||||
|
#include "PaintEvent.h"
|
||||||
|
|
||||||
|
#include "Button.h"
|
||||||
|
|
||||||
|
TEST_CASE(TestButton_Elevated, "ui_controls")
|
||||||
|
{
|
||||||
|
auto theme_manager = std::make_unique<ThemeManager>();
|
||||||
|
|
||||||
|
auto paint_event = PaintEvent::Create(theme_manager.get(), nullptr);
|
||||||
|
|
||||||
|
Button button(ButtonData::Component::Elevated);
|
||||||
|
button.setLabel("Enabled");
|
||||||
|
|
||||||
|
button.onPaintEvent(paint_event.get());
|
||||||
|
|
||||||
|
auto node = button.getRootNode();
|
||||||
|
|
||||||
|
TestRenderer renderer;
|
||||||
|
renderer.getScene()->addNode(node);
|
||||||
|
|
||||||
|
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "Elevated_Enabled.svg");
|
||||||
|
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "Elevated_Enabled.png");
|
||||||
|
|
||||||
|
};
|
Loading…
Reference in a new issue