blob: d48db963aeee1b2b70dca942ee0df2a46051863a [file]
/*
* Copyright 2024 Rive
*/
#include "rive/input/focus_node.hpp"
#include "rive/input/focus_manager.hpp"
#include <algorithm>
#include <cstddef>
namespace rive
{
FocusNode::~FocusNode()
{
// A child held elsewhere via rcp (a NestedArtboard's persistent focus
// scope, an ArtboardComponentList row) can outlive this node, so clear its
// back-pointer to keep m_parent from dangling.
for (const auto& child : m_children)
{
child->m_parent = nullptr;
}
}
void FocusNode::addChild(rcp<FocusNode> child)
{
insertChild(m_children.size(), std::move(child));
}
void FocusNode::insertChild(size_t index, rcp<FocusNode> child)
{
if (!child)
{
return;
}
child->removeFromParent();
child->m_parent = this;
if (index > m_children.size())
{
index = m_children.size();
}
m_children.insert(m_children.begin() + static_cast<ptrdiff_t>(index),
std::move(child));
invalidateFocusableContent();
}
void FocusNode::removeChild(rcp<FocusNode> child)
{
if (!child || child->m_parent != this)
{
return;
}
child->m_parent = nullptr;
auto it = std::find(m_children.begin(), m_children.end(), child);
if (it != m_children.end())
{
m_children.erase(it);
}
invalidateFocusableContent();
}
void FocusNode::invalidateFocusableContent()
{
if (m_manager != nullptr)
{
m_manager->markFocusableContentDirty();
}
}
void FocusNode::removeFromParent()
{
if (m_parent)
{
m_parent->removeChild(ref_rcp(this));
}
}
} // namespace rive