#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 "ThemeManager.h" #include "Window.h" #include "FileLogger.h" #include #include #include Widget::Widget() : BoxGeometry(), mRootNode(std::make_unique()), mChildren(), mBorderThickness(0), mBackground(Theme::Sys::Color::Primary), mBorder(Theme::Sys::Color::Outline), 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)); } void Widget::setName(const std::string& name) { mName = name; } const std::string& Widget::getName() const { return mName; } TransformNode* Widget::getRootNode() const { return mRootNode.get(); } void Widget::setBackground(Theme::Sys::Color token) { if (mBackground != token) { mBackground = token; mMaterialDirty = 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 + "_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::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(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(event->getThemesManager()->getColor(mBackground)); mBackgroundNode->setStrokeColor(event->getThemesManager()->getColor(mBorder)); 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; }