#pragma once
#include "SignalSlot.h"
#include "Common.h"
BEGIN_NAMESPACE
template <class T>
class PropertyInterface : public InterfaceBase
{
public:
virtual T const & get() const = 0;
virtual void set(T a_newValue) = 0;
// implementing cast and assignment operators is not the more C++ way?
//virtual T const & operator()(void) const
//virtual operator=(T const &) const
};
// This class is an abstract base class for a property
// The main thing to note is that it doesn't contain the
// variable backing this property which allows the value
// to come from any source or be held say inside of the
// library code or an engine, this API then exposes that
// through this interface. The only issue is that it
// requires that the library or engine code must call
// setValue when the value has changed to notify interested
// parties. The T type of this property however can be large
// or arbitary. The set re-implementation can also be made
// to be ref-count aware or implement something like a swap
// as is done in certain cases for assignment operators.
template <class T>
class AbstractProperty : public PropertyInterface<T>
{
public:
AbstractProperty<T>& operator=(T const & a_newValue)
{
//Variant v = a_newValue;
//setValue(v);
setValue(a_newValue);
return *this;
}
T const & operator()(void) const
{
return value();
}
void setValue(const T& a_newValue)
{
set(a_newValue);
valueChanged(a_newValue);
}
/*
void setValue(Variant& a_newValue)
{
set(a_newValue.variant_cast<T>());
valueChanged(a_newValue);
}
*/
T const & value() const
{
return get();
}
//Signal valueChanged;
Action<T> valueChanged;
protected:
virtual T const & get() const = 0;
virtual void set(T a_newValue) = 0;
};
// This is an implementation of the AbstractProperty interface
// which actually holds and backs the property with a variable
// of the given type.
// This is good for simple types where the declaration of the
// property also is intended to create the variable associated
// with it.
// In the case of a widget which manipulates a value, consider
// the widget instead passing and storing a AbstractProperty
// to it instead of a concrete value in a Property.
template <class T>
class Property : public AbstractProperty<T>
{
public:
Property() {}
Property(const T& val) : m_value(val) {}
Property(const Property<T>& other) : m_value(other.m_value) {}
Property<T>& operator=(T const & a_newValue)
{
//Variant v = a_newValue;
//AbstractProperty<T>::setValue(v);
AbstractProperty<T>::setValue(a_newValue);
return *this;
}
protected:
T const & get() const { return m_value; }
void set(T a_newValue) { m_value = a_newValue; }
private:
T m_value;
};
END_NAMESPACE