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.
137 lines
2.8 KiB
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
|
|
|