#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 #include #include Widget::Widget() : mLocation(DiscretePoint(0, 0)), mSize({100, 0, 0, 100, 0, 0}), mPadding(), mMargin(), mRootNode(std::make_unique()), mChildren(), mBorderThickness(0), mBackgroundColor(Color(255, 255, 255)), mBorderColor(Color(0, 0, 0)), mVisible(true) { mName = "Widget"; } Widget::~Widget() { } std::unique_ptr Widget::Create() { return std::make_unique(); } void Widget::addWidget(WidgetUPtr widget) { 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 (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::doPaint(const PaintEvent* event) { updateBackground(event); } void Widget::onPaintEvent(const PaintEvent* event) { if (!needsUpdate()) { return; } if (isDirty()) { mRootNode->setName(mName); doPaint(event); 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); child->setVisible(mVisible); } } 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) { } 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(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); } if (mVisibilityDirty) { mBackgroundNode->setIsVisible(mVisible); } }