Fork of Tangara with customizations
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
tangara-fw/lib/bindey/include/bindey/property.h

137 lines
2.8 KiB

#pragma once
#include <nod/nod.hpp>
#include <functional>
namespace bindey
{
/**
* Optional always_update policy to notify subscribers everytime the property value is set, not just when it changes
*/
class always_update
{
public:
template <typename T>
bool operator()( const T&, const T& ) const
{
return true;
}
};
template <typename T,
typename UpdatePolicy = std::not_equal_to<T>,
typename Signal = nod::unsafe_signal<void( const T& )>>
class property
{
public:
property()
{
}
property( T&& value )
: mStorage( std::move( value ) )
{
}
property( const property& ) = delete;
property& operator=(const property&) = delete;
/**
* gets the current value
* @return const reference to the value
*/
const T& get() const
{
return mStorage;
}
/**
* gets the current value
* @return mutable reference to the value
*/
T& get()
{
return mStorage;
}
const T& operator()() const
{
return get();
}
T& operator()()
{
return get();
}
/**
* sets the value of the property.
* @param value the new value
* @discussion the value will only be updated if the UpdatePolicy's critera is met.
* if the value is changed, then the @ref changed event will be fired.
*/
void set( const T& value )
{
if ( UpdatePolicy{}( mStorage, value ) )
{
mStorage = value;
changed( mStorage );
}
}
void set( T&& value )
{
if ( UpdatePolicy{}( mStorage, value ) )
{
mStorage = std::move( value );
changed( mStorage );
}
}
void operator()( const T& value )
{
set( value );
}
void operator()( T&& value )
{
set( std::move( value ) );
}
/**
* this signal is invoked whenever the the value changes per the UpdatePolicy
* @discussion nod::unsafe_signal is used here for speed. Take care of your own threading.
*/
Signal changed;
/**
* convience function to attach a change listener to this property
*/
auto onChanged( typename decltype( changed )::slot_type&& c )
{
return changed.connect( std::move( c ) );
}
/**
* convience function to attach a change listener to this property and call it right away
*/
auto onChangedAndNow( typename decltype( changed )::slot_type&& c )
{
auto connection = onChanged( std::move( c ) );
changed( mStorage );
return connection;
}
private:
T mStorage{};
};
/**
* thread safe property type based on nod::signal
*/
template <typename T, typename UpdatePolicy = std::not_equal_to<T>>
using safe_property = property<T, UpdatePolicy, nod::signal<void( const T& )>>;
} // namespace bindey