Clean project structure.
This commit is contained in:
parent
78a4fa99ff
commit
947bf937fd
496 changed files with 206 additions and 137 deletions
395
src/ui/ui_elements/widgets/Widget.cpp
Normal file
395
src/ui/ui_elements/widgets/Widget.cpp
Normal file
|
@ -0,0 +1,395 @@
|
|||
#include "Widget.h"
|
||||
|
||||
#include "RectangleNode.h"
|
||||
#include "MouseEvent.h"
|
||||
#include "KeyboardEvent.h"
|
||||
#include "PaintEvent.h"
|
||||
|
||||
#include "AbstractVisualNode.h"
|
||||
#include "TextNode.h"
|
||||
#include "TransformNode.h"
|
||||
#include "RootNode.h"
|
||||
|
||||
#include "Window.h"
|
||||
#include "FileLogger.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
|
||||
Widget::Widget()
|
||||
: mLocation(DiscretePoint(0, 0)),
|
||||
mSize({100, 0, 0, 100, 0, 0}),
|
||||
mPadding(),
|
||||
mMargin(),
|
||||
mRootNode(std::make_unique<TransformNode>()),
|
||||
mChildren(),
|
||||
mBorderThickness(0),
|
||||
mBackgroundColor(Color(255, 255, 255)),
|
||||
mBorderColor(Color(0, 0, 0)),
|
||||
mVisible(true)
|
||||
{
|
||||
mName = "Widget";
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<Widget> Widget::Create()
|
||||
{
|
||||
return std::make_unique<Widget>();
|
||||
}
|
||||
|
||||
void Widget::addWidget(WidgetUPtr widget)
|
||||
{
|
||||
widget->setParent(this);
|
||||
|
||||
mPendingChildNodes.push_back(widget->getRootNode());
|
||||
mChildren.push_back(std::move(widget));
|
||||
}
|
||||
|
||||
Widget::BoundedSize Widget::getSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
const DiscretePoint& Widget::getLocation() const
|
||||
{
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
TransformNode* Widget::getRootNode() const
|
||||
{
|
||||
return mRootNode.get();
|
||||
}
|
||||
|
||||
void Widget::setSize(const BoundedSize& size)
|
||||
{
|
||||
if (size != mSize)
|
||||
{
|
||||
mSize = size;
|
||||
mTransformDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setMargin(unsigned margin)
|
||||
{
|
||||
setMargin({margin, margin, margin, margin});
|
||||
}
|
||||
|
||||
void Widget::setMargin(const BoundaryOffset& margin)
|
||||
{
|
||||
if (margin != mMargin)
|
||||
{
|
||||
mMargin = margin;
|
||||
mTransformDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setPadding(unsigned padding)
|
||||
{
|
||||
setPadding({padding, padding, padding, padding});
|
||||
}
|
||||
|
||||
void Widget::setPadding(const BoundaryOffset& padding)
|
||||
{
|
||||
if (padding != mPadding)
|
||||
{
|
||||
mPadding = padding;
|
||||
mTransformDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setBounds(unsigned width, unsigned height)
|
||||
{
|
||||
if (mSize.mMaxWidth > 0 && width > mSize.mMaxWidth)
|
||||
{
|
||||
width = mSize.mMaxWidth;
|
||||
}
|
||||
|
||||
if (mSize.mMaxHeight > 0 && height > mSize.mMaxHeight)
|
||||
{
|
||||
height = mSize.mMaxHeight;
|
||||
}
|
||||
|
||||
if (width != mSize.mWidth || height != mSize.mHeight)
|
||||
{
|
||||
mTransformDirty = true;
|
||||
mSize.mWidth = width;
|
||||
mSize.mHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setBackgroundColor(const Color& color)
|
||||
{
|
||||
if (mBackgroundColor != color)
|
||||
{
|
||||
mBackgroundColor = color;
|
||||
mMaterialDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setLocation(const DiscretePoint& loc)
|
||||
{
|
||||
if (mLocation != loc)
|
||||
{
|
||||
mLocation = loc;
|
||||
mTransformDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setVisible(bool visible)
|
||||
{
|
||||
if (mVisible != visible)
|
||||
{
|
||||
mVisibilityDirty = true;
|
||||
|
||||
mVisible = visible;
|
||||
|
||||
for (auto& child : mChildren)
|
||||
{
|
||||
child->setVisible(mVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::isDirty() const
|
||||
{
|
||||
return mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
|
||||
}
|
||||
|
||||
bool Widget::needsUpdate() const
|
||||
{
|
||||
if (isDirty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for(auto& child: mChildren)
|
||||
{
|
||||
if (child->needsUpdate())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Widget::setMaxWidth(unsigned maxWidth)
|
||||
{
|
||||
if (mSize.mMaxWidth != maxWidth)
|
||||
{
|
||||
mTransformDirty = true;
|
||||
mSize.mMaxWidth = maxWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::doPaint(const PaintEvent* event)
|
||||
{
|
||||
updateBackground(event);
|
||||
}
|
||||
|
||||
void Widget::onPaintEvent(const PaintEvent* event)
|
||||
{
|
||||
if (!needsUpdate())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDirty())
|
||||
{
|
||||
mRootNode->setName(mName + "_RootNode");
|
||||
|
||||
doPaint(event);
|
||||
|
||||
if (mVisibilityDirty)
|
||||
{
|
||||
mRootNode->setIsVisible(mVisible);
|
||||
}
|
||||
|
||||
mTransformDirty = false;
|
||||
mMaterialDirty = false;
|
||||
mVisibilityDirty = false;
|
||||
}
|
||||
|
||||
for (auto node : mPendingChildNodes)
|
||||
{
|
||||
mRootNode->addChild(node);
|
||||
}
|
||||
mPendingChildNodes.clear();
|
||||
|
||||
updateChildLocations();
|
||||
|
||||
for(auto& child: mChildren)
|
||||
{
|
||||
child->onPaintEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::updateChildLocations()
|
||||
{
|
||||
for(auto& child: mChildren)
|
||||
{
|
||||
child->setBounds(mSize.mWidth, mSize.mHeight);
|
||||
child->setLocation(mLocation);
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::contains(const DiscretePoint& loc) const
|
||||
{
|
||||
if(loc.getX() < mLocation.getX())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool Widget::onKeyboardEvent(const KeyboardEvent* event)
|
||||
{
|
||||
bool inChild = false;
|
||||
for(const auto& child : mChildren)
|
||||
{
|
||||
if(child->onKeyboardEvent(event))
|
||||
{
|
||||
inChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!inChild)
|
||||
{
|
||||
return onMyKeyboardEvent(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Widget::onMyKeyboardEvent(const KeyboardEvent* event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::onMouseEvent(const MouseEvent* event)
|
||||
{
|
||||
bool inChild = false;
|
||||
for(const auto& child : mChildren)
|
||||
{
|
||||
if(child->onMouseEvent(event))
|
||||
{
|
||||
inChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!inChild)
|
||||
{
|
||||
if(mVisible && contains(event->getClientLocation()))
|
||||
{
|
||||
onMyMouseEvent(event);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Widget::onMyMouseEvent(const MouseEvent* event)
|
||||
{
|
||||
MLOG_INFO("Widget mouse event");
|
||||
}
|
||||
|
||||
void Widget::updateBackground(const PaintEvent* event)
|
||||
{
|
||||
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;
|
||||
|
||||
if (!mBackgroundNode)
|
||||
{
|
||||
mBackgroundNode = std::make_unique<RectangleNode>(DiscretePoint(locX, locY), deltaX, deltaY);
|
||||
mBackgroundNode->setName(mName + "_BackgroundNode");
|
||||
mRootNode->addChild(mBackgroundNode.get());
|
||||
}
|
||||
|
||||
if (mTransformDirty)
|
||||
{
|
||||
mBackgroundNode->setWidth(deltaX);
|
||||
mBackgroundNode->setHeight(deltaY);
|
||||
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
|
||||
}
|
||||
|
||||
if (mMaterialDirty)
|
||||
{
|
||||
mBackgroundNode->setFillColor(mBackgroundColor);
|
||||
mBackgroundNode->setStrokeColor(mBorderColor);
|
||||
mBackgroundNode->setStrokeThickness(mBorderThickness);
|
||||
}
|
||||
|
||||
if (mVisibilityDirty)
|
||||
{
|
||||
mBackgroundNode->setIsVisible(mVisible);
|
||||
}
|
||||
}
|
||||
|
||||
mt::Window* Widget::getTopLevelWindow() const
|
||||
{
|
||||
if(mWindow)
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
std::cout << "I am " << getName() << std::endl;
|
||||
|
||||
auto lastParent = mParent;
|
||||
auto nextParent = mParent;
|
||||
while(nextParent)
|
||||
{
|
||||
lastParent = nextParent;
|
||||
nextParent = lastParent->getParent();
|
||||
std::cout << "Checking if " << lastParent->getName() << std::endl;
|
||||
if (nextParent)
|
||||
{
|
||||
std::cout << "Next is " << nextParent->getName() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "no next" << std::endl;
|
||||
}
|
||||
}
|
||||
return lastParent->getTopLevelWindow();
|
||||
}
|
||||
|
||||
Widget* Widget::getParent() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
mt::Window* Widget::getWindow() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
void Widget::setParent(Widget* parent)
|
||||
{
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
void Widget::setWindow(mt::Window* window)
|
||||
{
|
||||
mWindow = window;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue