#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 #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) { 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) { } void Widget::updateBackground(const PaintEvent* event) { unsigned locX = mLocation.getX() + mMargin.mLeft; unsigned locY = mLocation.getX() + 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); } } 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; }