Modules/WidgetsNew/private/RootWidget.cpp
2024-10-14 20:20:21 +03:00

122 lines
No EOL
2.7 KiB
C++

#include "RootWidget.hpp"
#include "BasicLayout.hpp"
#include <algorithm>
using namespace tp;
WidgetLayout* WidgetManagerInterface::defaultLayout(Widget* widget) {
return new BasicLayout(widget);
}
RootWidget::RootWidget() {
setDebug("root", RGBA(1));
}
void RootWidget::setRootWidget(Widget* widget) {
mRoot = widget;
widget->mParent = this;
}
void RootWidget::processFrame(EventHandler* events, const RectF& screenArea) {
mRoot->setArea(screenArea);
if (!mDebugManager.update(this, *events)) return;
// construct hierarchy tree of widgets to process
mUpdateManager.updateTreeToProcess(mRoot);
updateAnimations();
updateAreaCache(mRoot, true);
// update all events and call all event processing callbacks
mUpdateManager.processWidgets(mRoot, *events);
updateAreaCache(mRoot, true);
// update widget sizes base on individual size policies
mLayoutManager.adjust(mRoot);
updateAreaCache(mRoot, false);
// trigger some widgets by moise pointer
mUpdateManager.handleFocusChanges(mRoot, *events);
// check triggered widgets for removal
mUpdateManager.clean();
}
bool RootWidget::needsUpdate() const {
if (mDebugManager.isRedrawAlways()) return true;
return mUpdateManager.isPendingUpdates();
}
void RootWidget::drawFrame(Canvas& canvas) {
canvas.rect(mRoot->getAreaT(), RGBA(0, 0, 0, 1));
drawRecursion(canvas, mRoot, { 0, 0 });
mDebugManager.drawDebug(this, canvas);
}
void RootWidget::drawRecursion(Canvas& canvas, Widget* active, const Vec2F& pos) {
if (!active->mFlags.get(ENABLED)) return;
canvas.setOrigin(pos);
canvas.pushClamp({ pos, active->getArea().size });
active->draw(canvas);
for (auto child = active->mDepthOrder.lastNode(); child; child = child->prev) {
drawRecursion(canvas, child->data, pos + child->data->getArea().pos);
}
canvas.setOrigin(pos);
canvas.popClamp();
active->drawOverlay(canvas);
}
void RootWidget::setWidgetArea(Widget& widget, const RectF& rect) {
widget.mArea.setTargetRect(rect);
widget.mArea.endAnimation();
}
void RootWidget::updateAnimations() {
dfs(mRoot, [](Widget* widget) {
widget->updateAnimations();
});
}
void RootWidget::updateWidget(Widget* widget, const char* reason) {
DEBUG_ASSERT(reason)
mUpdateManager.scheduleUpdate(widget, reason);
}
void RootWidget::updateAreaCache(Widget* iter, bool read) {
if (!iter || !iter->isUpdate()) return;
if (read) {
iter->mAreaCache = iter->getAreaT();
} else {
iter->setArea(iter->mAreaCache);
iter->mArea.updateCurrentRect();
}
for (auto child : iter->mChildren) {
if (read) {
child->mAreaCache = child->getAreaT();
} else {
child->setArea(child->mAreaCache);
child->mArea.updateCurrentRect();
}
}
for (auto child : iter->mDepthOrder) {
updateAreaCache(child.data(), read);
}
}