31#pragma warning (disable: 4702 )
36 template <
typename T,
typename Category,
class Context,
typename Calculator>
39 template <
typename T,
typename Category,
class Context,
typename Calculator>
47 transition{ aAnimator, aEasingFunction, aDuration, aEnabled },
48 iProperty{ aProperty }
54 if (iProperty.iPreviousValue != std::nullopt)
56 bool alreadyActive =
active();
65 return iFrom != std::nullopt;
81 return iUpdatingProperty;
111 return iFrom == std::nullopt;
116 iFrom = std::nullopt;
120 void sync(
bool aIgnorePrevious =
false) final
122 iFrom = aIgnorePrevious ? iProperty.iValue : iProperty.iPreviousValue;
123 iTo = iProperty.iValue;
127 std::optional<value_type> iFrom;
128 std::optional<value_type> iTo;
129 std::optional<value_type> iMix;
130 bool iUpdatingProperty =
false;
133 template <
typename T,
typename Category,
class Context,
typename Calculator = T(*)()>
137 template <
typename,
typename,
class,
typename>
154 template <
typename ParentType>
164 template <
typename SFINAE = neolib::optional_t<T>>
165 operator const typename std::enable_if<neolib::is_optional_v<T>, SFINAE>
::type&()
const
167 return *iParent.value();
169 template <
typename T2,
typename SFINAE = optional_proxy<parent_type>>
170 typename std::enable_if<!std::is_const<parent_type>::value, SFINAE>
::type&
operator=(
const T2& aValue)
172 iParent.assign(aValue);
175 template <
typename SFINAE = const neolib::optional_t<T>*>
178 return &*iParent.value();
192 property(
i_property_owner& aOwner, std::string
const& aName,
const T& aValue) : iOwner{ aOwner }, iName{ aName }, iValue { aValue }
211 const string&
name() const final
215 const std::type_info&
type() const final
231 if (
value() != std::nullopt)
241 std::visit([
this](
auto&& arg)
243 if constexpr (std::is_same_v<std::decay_t<
decltype(arg)>, std::monostate>)
246 *
this = std::forward<decltype(arg)>(arg);
255 iReadOnly = aReadOnly;
259 return iTransition !=
nullptr;
263 if (iTransition !=
nullptr)
265 throw std::logic_error(
"neogfx::property: no transition!" );
269 iTransition = std::make_unique<transition_type>(aAnimator, *
this, aEasingFunction, aDuration, aEnabled);
273 iTransition =
nullptr;
277 return iTransitionSuppressed;
281 iTransitionSuppressed = aSuppress;
290 return iDelegate !=
nullptr;
304 iDelegate = &aDelegate;
315 std::visit([
this](
auto&& arg)
317 typedef std::decay_t<
decltype(arg)> try_type;
318 if constexpr (std::is_same_v<try_type, value_type>)
320 else if constexpr (std::is_same_v<try_type, custom_type>)
327 else if constexpr (std::is_same_v<try_type, neolib::none_t> || std::is_same_v<try_type, std::monostate>)
332 iValue = std::nullopt;
350 template <
typename T2>
351 self_type&
assign(T2&& aValue,
bool aOwnerNotify =
true,
bool aDiscardPreviousValue =
false)
353 typedef std::decay_t<
decltype(aValue)> try_type;
354 if constexpr (std::is_same_v<try_type, value_type> || std::is_same_v<neolib::optional<try_type>,
value_type>)
355 return do_assign(std::forward<T2>(aValue), aOwnerNotify, aDiscardPreviousValue);
356 else if constexpr (std::is_same_v<try_type, custom_type>)
358 else if constexpr (std::is_same_v<try_type, neolib::none_t> || std::is_same_v<try_type, std::monostate>)
359 return do_assign(
value_type{}, aOwnerNotify, aDiscardPreviousValue);
360 else if constexpr (std::is_arithmetic_v<value_type> && std::is_convertible_v<try_type, value_type> && std::is_integral_v<try_type> == std::is_integral_v<value_type>)
361 return do_assign(
static_cast<value_type>(std::forward<T2>(aValue)), aOwnerNotify, aDiscardPreviousValue);
370 template <
typename T2>
373 return assign(std::forward<T2>(aValue));
379 template <
typename SFINAE = optional_proxy<const self_type>>
380 const typename std::enable_if<neolib::is_optional_v<T>, SFINAE>
::type operator*()
const
384 template <
typename SFINAE = optional_proxy<self_type>>
389 template <
typename SFINAE = optional_proxy<const self_type>>
394 template <
typename SFINAE = optional_proxy<self_type>>
399 template <
typename T>
402 return value() == aRhs;
404 template <
typename T>
407 return value() != aRhs;
409 template <
typename T>
412 return value() == aRhs;
414 template <
typename T>
417 return value() != aRhs;
430 return &mutable_value();
437 if (iCalculator !=
nullptr)
438 return reinterpret_cast<void*const*
>(&iCalculator);
444 return const_cast<value_type&
>(to_const(*this).value());
446 template <
typename T2>
447 self_type& do_assign(T2&& aValue,
bool aOwnerNotify =
true,
bool aDiscardPreviousValue =
false)
457 if (mutable_value() != aValue)
461 iPreviousValue = !aDiscardPreviousValue ?
value() : aValue;
462 mutable_value() = aValue;
466 mutable_value() = aValue;
471 mutable_value() = aValue;
477 update(aOwnerNotify);
482 void update(
bool aOwnerNotify =
true)
495 bool discardChangedFromTo =
false;
508 if (!discardChangedFromTo &&
event_consumed(ChangedFromTo.trigger(*iPreviousValue,
value())))
514 i_property_owner& iOwner;
518 std::optional<value_type> iPreviousValue;
519 bool iReadOnly =
false;
520 std::unique_ptr<transition_type> iTransition;
521 bool iTransitionSuppressed =
false;
522 i_property_delegate* iDelegate =
nullptr;
525 namespace property_category
527 struct soft_geometry {};
528 struct hard_geometry {};
531 struct other_appearance {};
532 struct interaction {};
536 #define define_property( category, type, name, calculator, ... ) neogfx::property<type, category, property_context_type, decltype(&property_context_type::##calculator)> name = { *this, #name ##s, &property_context_type::##calculator, __VA_ARGS__ };
virtual void register_property(i_property &aProperty)=0
virtual property_variant get(const i_property &aProperty) const =0
virtual const void * data() const =0
virtual const i_properties & properties() const =0
virtual void property_changed(i_property &aProperty)=0
std::enable_if<!std::is_const< parent_type >::value, SFINAE >::type & operator=(const T2 &aValue)
const std::enable_if< neolib::is_optional_v< T >, SFINAE >::type operator->() const
optional_proxy(parent_type &aParent)
bool updating_property() const
bool property_transition::can_apply() const final
value_type const & mix() const
bool finished() const final
void sync(bool aIgnorePrevious=false) final
property_transition(i_animator &aAnimator, property_type &aProperty, easing aEasingFunction, double aDuration, bool aEnabled=true)
property< T, Category, Context, Calculator > property_type
value_type const & from() const
value_type const & to() const
std::enable_if< neolib::is_optional_v< T >, SFINAE >::type operator->()
void clear_transition() final
const std::enable_if< neolib::is_optional_v< T >, SFINAE >::type operator*() const
bool optional() const final
property(i_property_owner &aOwner, std::string const &aName, calculator_function_type aCalculator)
property_variant get(const i_property &aProperty) const final
const string & name() const final
self_type & assign(T2 &&aValue, bool aOwnerNotify=true, bool aDiscardPreviousValue=false)
const std::type_info & type() const final
bool transition_suppressed() const final
bool transition_set() const final
void set_transition(i_animator &aAnimator, easing aEasingFunction, double aDuration, bool aEnabled=true) final
i_property_delegate & delegate() final
self_type & operator=(T2 &&aValue)
const void * data() const final
bool operator!=(const neolib::optional< T > &aRhs) const
const std::type_info & category() const final
property(i_property_owner &aOwner, std::string const &aName)
i_property_delegate const & delegate() const final
void set_delegate(i_property_delegate &aDelegate) final
value_type const & effective_value() const
void unset_delegate() final
Calculator calculator_function_type
bool operator==(const neolib::optional< T > &aRhs) const
property_transition< T, Category, Context, Calculator > transition_type
bool operator!=(const T &aRhs) const
property(i_property_owner &aOwner, std::string const &aName, const T &aValue)
transition_type & transition() const final
define_declared_event(PropertyChanged, property_changed, const property_variant &) define_declared_event(PropertyChangedFromTo
value_type const & value() const
property_variant get_as_variant() const final
std::enable_if< neolib::is_optional_v< T >, SFINAE >::type operator*()
property(i_property_owner &aOwner, std::string const &aName, calculator_function_type aCalculator, const T &aValue)
void *const * calculator_function() const final
void suppress_transition(bool aSuppress) final
bool read_only() const final
void set_read_only(bool aReadOnly) final
i_property_owner & owner() const final
bool has_delegate() const final
const std::enable_if< neolib::is_optional_v< T >, SFINAE >::type operator->() const
void set_from_variant(const property_variant &aValue) final
const property_variant const property_variant changed_from_to
bool operator==(const T &aRhs) const
bool animation_finished() const override
easing easing_function() const override
bool active() const override
bool enabled() const override
double mix_value() const override
bool disable_when_finished() const override
bool paused() const override
void reset(bool aEnable=true, bool aDisableWhenFinished=false, bool aResetStartTime=true) override
neolib::destroyed_flag destroyed_flag
neolib::variant< void *, bool, char, int32_t, uint32_t, int64_t, uint64_t, float, double, string, mat33, size, point, rect, box_areas, custom_type > property_variant
point mix(const point &aLhs, const point &aRhs, double aMixValue)
ref_ptr< ConcreteType > make_ref(Args &&... args)
bool event_consumed(trigger_result aTriggerResult)
auto destroyed(Object &aObject, const Handler aHandler)
#define define_event(name, declName,...)
#define define_declared_event(name, declName,...)