From f723c5f20a3fd9a9b6b0af16cbdb69424ebe654b Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 1 Mar 2023 06:41:14 -0800 Subject: [PATCH] Added teardown styled use effect --- src/dawn/state/State.hpp | 35 +++++++++++++++++++++++++++++--- src/dawn/state/StateEvent.hpp | 1 + src/dawn/state/StateProperty.hpp | 18 ++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/dawn/state/State.hpp b/src/dawn/state/State.hpp index adac24cd..e9161229 100644 --- a/src/dawn/state/State.hpp +++ b/src/dawn/state/State.hpp @@ -36,12 +36,14 @@ namespace Dawn { * * @param fn The callback to be invoked when the state value changes. * @param property Property to listen for affect changees to. + * @return Returns callback that invokes the provided FN immediately. */ - void useEffect( + std::function useEffect( const std::function &fn, IStateProperty &property ) { property._effectListners.push_back(fn); + return fn; } /** @@ -50,8 +52,9 @@ namespace Dawn { * * @param fn The callback to be invoked when the state value changes. * @param property Vector list of properties to listen for changes to. + * @return Returns callback that invokes the provided FN immediately. */ - void useEffect( + std::function useEffect( const std::function &fn, std::vector props ) { @@ -60,6 +63,31 @@ namespace Dawn { (*itProp)->_effectListners.push_back(fn); ++itProp; } + return fn; + } + + /** + * Listen for changes to a state property and invoke the provided callback + * also, when state is changed this will run the returned teardown + * callback. + * + * @param fn The callback to be invoked when the state value changes. + * @param property Vector list of properties to listen for changes to. + * @return Returns callback that invokes the provided FN immediately. + */ + std::function useEffectWithTeardown( + const std::function()> &fn, + IStateProperty &property + ) { + property._effectListnersWithTeardown.push_back(fn); + + return std::bind([&]( + std::function()> &callback, + IStateProperty *prop + ) { + auto teardown = callback(); + prop->_effectTeardowns.push_back(teardown); + }, fn, &property); } /** @@ -74,7 +102,6 @@ namespace Dawn { */ template std::function useEvent(F fn, StateEvent &event) { - // Create a listener structure struct StateEventListener listener; listener.listener = fn; @@ -99,6 +126,8 @@ namespace Dawn { return listener.unsub; } + + virtual ~StateOwner() { auto it = this->eventsSubscribed.begin(); diff --git a/src/dawn/state/StateEvent.hpp b/src/dawn/state/StateEvent.hpp index 79b5318a..12a0ddd2 100644 --- a/src/dawn/state/StateEvent.hpp +++ b/src/dawn/state/StateEvent.hpp @@ -5,6 +5,7 @@ #pragma once #include "assert/assert.hpp" +#include "event/Event.hpp" namespace Dawn { /** Forwarders / Fake Virtuals for other methods. */ diff --git a/src/dawn/state/StateProperty.hpp b/src/dawn/state/StateProperty.hpp index 15ab7a54..f34ecea4 100644 --- a/src/dawn/state/StateProperty.hpp +++ b/src/dawn/state/StateProperty.hpp @@ -10,6 +10,8 @@ namespace Dawn { class IStateProperty { public: std::vector> _effectListners; + std::vector()>> _effectListnersWithTeardown; + std::vector> _effectTeardowns; }; template @@ -26,12 +28,28 @@ namespace Dawn { this->previous = this->_realValue; this->_realValue = val; + // Run the teardowns + auto itTeardown = this->_effectTeardowns.begin(); + while(itTeardown != this->_effectTeardowns.end()) { + (*itTeardown)(); + ++itTeardown; + } + this->_effectTeardowns.clear(); + // Notify the effect listeners auto itEffect = this->_effectListners.begin(); while(itEffect != this->_effectListners.end()) { (*itEffect)(); ++itEffect; } + + // Notify the teardown effect listeners + auto itWithTeardown = this->_effectListnersWithTeardown.begin(); + while(itWithTeardown != this->_effectListnersWithTeardown.end()) { + auto teardown = (*itWithTeardown)(); + this->_effectTeardowns.push_back(teardown); + ++itWithTeardown; + } } public: