#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 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::setBackgroundTone(Theme::Sys::Color token) { if (mBackgroundTone != token) { mBackgroundTone = token; mMaterialDirty = true; } } void Widget::setElevation(Theme::Sys::Elevation elevation) { if (mElevation != elevation) { mElevation = elevation; mMaterialDirty = true; } } 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) { if (mVisible != visible) { mVisibilityDirty = true; mVisible = visible; for (auto& child : mChildren) { child->setVisible(mVisible); } } } bool Widget::isDirty() const { return mStateDirty || mGeometryDirty || 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::updateState() { } void Widget::doPaint(const PaintEvent* event) { updateBackground(event); } void Widget::onPaintEvent(const PaintEvent* event) { if (!needsUpdate()) { return; } if (isDirty()) { mRootNode->setName(mName + "_RootNode"); if (mStateDirty) { updateState(); mStateDirty = false; } doPaint(event); mGeometryDirty = false; mMaterialDirty = false; mTransformDirty = false; if (mVisibilityDirty) { mRootNode->setIsVisible(mVisible); 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; } 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::createOrUpdateGeometry() { const auto deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight; const auto deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom; if (!mBackgroundNode) { const auto locX = mLocation.getX() + mMargin.mLeft; const auto locY = mLocation.getY() + mMargin.mTop; mBackgroundNode = std::make_unique(DiscretePoint(locX, locY), deltaX, deltaY); mBackgroundNode->setRadius(mRadius); mBackgroundNode->setName(mName + "_BackgroundNode"); mRootNode->addChild(mBackgroundNode.get()); } else { mBackgroundNode->setWidth(deltaX); mBackgroundNode->setHeight(deltaY); mBackgroundNode->setRadius(mRadius); } } void Widget::updateTransform() { const auto locX = mLocation.getX() + mMargin.mLeft; const auto locY = mLocation.getY() + mMargin.mTop; mBackgroundNode->setLocation(DiscretePoint(locX, locY)); } void Widget::updateMaterial(const PaintEvent* event) { if (mBackground != Theme::Sys::Color::None) { //if (mBackgroundTone == Theme::Sys::Color::None || mElevation == Theme::Sys::Elevation::Level_0) //{ auto background_color = event->getThemesManager()->getColor(mBackground); background_color.setAlpha(mBackgroundOpacity); mBackgroundNode->setFillColor(background_color); //} //else //{ //event->getThemesManager()->getColor(mBackground); //} } 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) { if (mGeometryDirty) { createOrUpdateGeometry(); } if (mTransformDirty) { updateTransform(); } if (mMaterialDirty) { updateMaterial(event); } 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; }