Files
Nuake-custom/Nuake/src/UI/Nodes/Canvas.cpp

203 lines
3.5 KiB
C++

#include "Canvas.h"
#include "src/UI/Renderer.h"
#include "src/FileSystem/File.h"
#include "Node.h"
#include <yoga/Yoga.h>
#include <yoga/YGConfig.h>
namespace NuakeUI
{
CanvasPtr Canvas::New()
{
return std::make_shared<Canvas>();
}
Canvas::Canvas() : mInputManager(nullptr), mDirty(false)
{
mYogaConfig = YGConfigNew();
}
Canvas::~Canvas()
{
YGConfigFree(mYogaConfig);
if (mRootNode)
{
YGNodeFreeRecursive(mRootNode->GetYogaNode());
}
}
void Canvas::Tick()
{
if (!mRootNode)
return;
mRootNode->UpdateInput(mInputManager);
mRootNode->Tick(mInputManager);
mInputManager->ScrollX = 0.f;
mInputManager->ScrollY = 0.f;
}
void Canvas::Draw()
{
if (!mRootNode)
return;
Renderer::Get().BeginDraw();
Renderer::Get().DrawNode(mRootNode, 0);
mRootNode->Draw(0);
}
void Canvas::ComputeLayout(Vector2 size)
{
if (!mRootNode)
return;
Renderer::Get().SetViewportSize(size);
float x, y;
x = mInputManager->GetMouseX();
y = mInputManager->GetMouseY();
auto root = mRootNode->GetYogaNode();
// Recompute the node tree.
if (mDirty)
ComputeStyle(mRootNode);
mRootNode->Calculate();
if (root)
YGNodeCalculateLayout(root, size.x, size.y, YGDirectionLTR);
}
void Canvas::ComputeStyle(NodePtr node)
{
for (auto& s : node->GetDataModelOperations())
{
if (s->Type != OperationType::IfClass)
continue;
if (auto dataModel = node->GetDataModel(); s->Compare(dataModel))
{
node->AddClass(s->ClassName);
}
else
{
node->RemoveClass(s->ClassName);
}
}
for (auto& rule : mStyleSheet->Rules)
{
bool respectSelector = true;
for (StyleSelector& selector : rule.Selector)
{
bool foundSelector = false;
switch (selector.Type)
{
case StyleSelectorType::Class:
{
for (auto& c : node->Classes)
{
if (c == selector.Value)
foundSelector = true;
}
break;
}
case StyleSelectorType::Pseudo:
{
const bool isHover = selector.Value == "hover" && node->State == NodeState::Hover;
const bool isActive = selector.Value == "active" && node->State == NodeState::Clicked;
if (isHover || isActive)
{
foundSelector = true;
}
break;
}
case StyleSelectorType::Id:
{
if (selector.Value == node->GetID())
{
foundSelector = true;
}
break;
}
case StyleSelectorType::Tag:
{
if (selector.Value == node->GetType())
{
foundSelector = true;
}
break;
}
}
if (!foundSelector)
{
respectSelector = false;
}
}
if (respectSelector)
node->ApplyStyleProperties(rule.Properties);
}
for (auto& c : node->GetChildrens())
{
ComputeStyle(c);
}
}
// Getters & Setters
NodePtr Canvas::GetRoot() const
{
return mRootNode;
}
void Canvas::SetRoot(NodePtr root)
{
mRootNode = root;
root->canvasOwner = this;
}
void Canvas::SetInputManager(InputManager* inputManager)
{
mInputManager = inputManager;
}
StyleSheetPtr Canvas::GetStyleSheet() const
{
return mStyleSheet;
}
void Canvas::SetStyleSheet(StyleSheetPtr styleSheet)
{
mDirty = true;
mStyleSheet = styleSheet;
}
Ref<Node> Canvas::GetNodeByUUID(const UUID& uuid)
{
if (!nodeCache.contains(uuid))
{
return nullptr;
}
return nodeCache[uuid];
}
void Canvas::AddSourceFile(Ref<File> file)
{
sourceFiles.push_back(file);
}
std::vector<Ref<File>> Canvas::GetSourceFiles() const
{
return sourceFiles;
}
}