blob: 25e8632f1ce44558526a532d581ae1ddb45d8085 [file] [log] [blame]
#ifndef _RIVE_DATA_BIND_CONTEXT_VALUE_HPP_
#define _RIVE_DATA_BIND_CONTEXT_VALUE_HPP_
#include "rive/viewmodel/viewmodel_instance_value.hpp"
#include "rive/data_bind/converters/data_converter.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/data_values/data_value_number.hpp"
#include "rive/data_bind/context/context_target_value.hpp"
#include <stdio.h>
namespace rive
{
class DataBindContextValue
{
protected:
DataBind* m_dataBind = nullptr;
DataValue* m_dataValue = nullptr;
DataBindContextTargetValue m_targetValue;
bool m_isValid = false;
public:
DataBindContextValue(DataBind* dataBind);
virtual ~DataBindContextValue()
{
if (m_dataValue != nullptr)
{
delete m_dataValue;
}
};
virtual void applyToSource(Core* component,
uint32_t propertyKey,
bool isMainDirection);
virtual void apply(Core* component,
uint32_t propertyKey,
bool isMainDirection) {};
void invalidate() { m_isValid = false; };
virtual bool syncTargetValue(Core* target, uint32_t propertyKey)
{
return false;
};
void syncSourceValue();
DataValue* calculateUntypedDataValue(DataValue* input,
bool isMainDirection,
DataBind* dataBind)
{
auto converter = dataBind->converter();
auto dataValue = converter != nullptr
? isMainDirection
? converter->convert(input, dataBind)
: converter->reverseConvert(input, dataBind)
: input;
return dataValue;
}
template <typename T = DataValue>
DataValue* calculateDataValue(DataValue* input,
bool isMainDirection,
DataBind* dataBind)
{
auto dataValue =
calculateUntypedDataValue(input, isMainDirection, dataBind);
if (dataValue->is<T>())
{
return dataValue;
}
return nullptr;
};
template <typename T = DataValue, typename U>
U calculateValue(DataValue* input, bool isMainDirection, DataBind* dataBind)
{
auto dataValue =
calculateDataValue<T>(input, isMainDirection, dataBind);
if (dataValue && dataValue->template is<T>())
{
return dataValue->template as<T>()->value();
}
return T::defaultValue;
};
template <typename T = DataValue,
typename U,
typename V = ViewModelInstanceValue>
void calculateValueAndApply(bool isMainDirection)
{
// Check if target value changed or binding has been invalidated
if (m_targetValue.syncTargetValue() || !m_isValid)
{
// Calculate new value after converters are applied
auto value = calculateDataValue<T>(m_targetValue.dataValue(),
isMainDirection,
m_dataBind);
if (value)
{
// Apply value to source
m_dataBind->suppressDirt(true);
auto source = m_dataBind->source();
source->as<V>()->applyValue(value->template as<T>());
m_dataBind->suppressDirt(false);
m_isValid = true;
}
}
};
};
} // namespace rive
#endif