blob: 7299ad4a80b45e9df40d24751a9e36a514b78103 [file] [log] [blame]
#include "rive/data_bind/data_context.hpp"
#include "rive/data_bind/data_bind_path.hpp"
#include "rive/file.hpp"
#include "rive/viewmodel/viewmodel_instance.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/viewmodel/viewmodel_instance_viewmodel.hpp"
using namespace rive;
DataContext::DataContext(rcp<ViewModelInstance> viewModelInstance) :
m_ViewModelInstance(viewModelInstance)
{}
void DataContext::viewModelInstance(rcp<ViewModelInstance> value)
{
m_ViewModelInstance = value;
}
void DataContext::advanced() { m_ViewModelInstance->advanced(); }
ViewModelInstanceValue* DataContext::getViewModelProperty(
const std::vector<uint32_t> path) const
{
std::vector<uint32_t>::const_iterator it;
if (path.size() == 0)
{
return nullptr;
}
if (m_ViewModelInstance != nullptr &&
m_ViewModelInstance->viewModelId() == path[0])
{
rcp<ViewModelInstance> instance = m_ViewModelInstance;
for (it = path.begin() + 1; it != path.end() - 1; it++)
{
auto viewModelInstanceValue = instance->propertyValue(*it);
if (viewModelInstanceValue != nullptr &&
viewModelInstanceValue->is<ViewModelInstanceViewModel>())
{
instance =
viewModelInstanceValue->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance();
}
else
{
goto skip_path;
}
}
ViewModelInstanceValue* value = instance->propertyValue(*it++);
return value;
}
skip_path:
if (m_Parent != nullptr)
{
return m_Parent->getViewModelProperty(path);
}
return nullptr;
}
ViewModelInstanceValue* DataContext::getRelativeViewModelProperty(
const std::vector<uint32_t> path,
DataResolver* resolver) const
{
std::vector<uint32_t>::const_iterator it;
if (path.size() == 0 || !resolver)
{
return nullptr;
}
{
rcp<ViewModelInstance> instance = m_ViewModelInstance;
for (it = path.begin(); it != path.end() - 1; it++)
{
auto viewModelInstanceValue =
instance->propertyValue(resolver->resolveName(*it));
if (viewModelInstanceValue != nullptr &&
viewModelInstanceValue->is<ViewModelInstanceViewModel>())
{
instance =
viewModelInstanceValue->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance();
}
else
{
goto skip_relative_path;
}
}
ViewModelInstanceValue* propertyValue =
instance->propertyValue(resolver->resolveName(*it++));
if (propertyValue)
{
return propertyValue;
}
}
skip_relative_path:
if (m_Parent != nullptr)
{
return m_Parent->getRelativeViewModelProperty(path, resolver);
}
return nullptr;
}
rcp<ViewModelInstance> DataContext::getViewModelInstance(
const std::vector<uint32_t> path) const
{
if (path.size() == 0)
{
return nullptr;
}
std::vector<uint32_t>::const_iterator it;
if (m_ViewModelInstance != nullptr &&
m_ViewModelInstance->viewModelId() == path[0])
{
rcp<ViewModelInstance> instance = m_ViewModelInstance;
for (it = path.begin() + 1; it != path.end(); it++)
{
auto viewModelInstanceValue = instance->propertyValue(*it);
if (viewModelInstanceValue != nullptr &&
viewModelInstanceValue->is<ViewModelInstanceViewModel>())
{
instance =
viewModelInstanceValue->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance();
}
else
{
instance = nullptr;
}
if (instance == nullptr)
{
goto skip_path;
}
}
return instance;
}
skip_path:
if (m_Parent != nullptr)
{
return m_Parent->getViewModelInstance(path);
}
return nullptr;
}
rcp<ViewModelInstance> DataContext::getRelativeViewModelInstance(
const std::vector<uint32_t> path,
DataResolver* resolver) const
{
if (path.size() == 0 || !resolver)
{
return nullptr;
}
std::vector<uint32_t>::const_iterator it;
if (m_ViewModelInstance != nullptr)
{
rcp<ViewModelInstance> instance = m_ViewModelInstance;
for (it = path.begin(); it != path.end(); it++)
{
auto viewModelInstanceValue =
instance->propertyValue(resolver->resolveName(*it));
if (viewModelInstanceValue != nullptr &&
viewModelInstanceValue->is<ViewModelInstanceViewModel>())
{
instance =
viewModelInstanceValue->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance();
}
else
{
instance = nullptr;
}
if (instance == nullptr)
{
goto skip_path_relative;
}
}
return instance;
}
skip_path_relative:
if (m_Parent != nullptr)
{
return m_Parent->getRelativeViewModelInstance(path, resolver);
}
return nullptr;
}
rcp<ViewModelInstance> DataContext::getViewModelInstance(
DataBindPath* dataBindPath) const
{
if (!dataBindPath)
{
return nullptr;
}
if (dataBindPath->isRelative())
{
auto file = dataBindPath->file();
if (file)
{
auto resolver = file->dataResolver();
if (resolver)
{
return getRelativeViewModelInstance(
dataBindPath->resolvedPath(),
resolver);
}
}
return nullptr;
}
else
{
return getViewModelInstance(dataBindPath->resolvedPath());
}
}