Enable Property to have multiple callbacks

This commit is contained in:
Alexander Bock
2017-07-11 14:23:17 -04:00
parent 9258c9f858
commit 314c6c0848
2 changed files with 62 additions and 11 deletions

View File

@@ -73,6 +73,14 @@ public:
User = 0 ///< Visible in User mode
};
/// An OnChangeHandle is returned by the onChange method to uniquely identify an
/// onChange callback
using OnChangeHandle = uint32_t;
/// This OnChangeHandle can be used to remove all onChange callbacks from this
/// Property
static OnChangeHandle OnChangeHandleAll;
/**
* The constructor for the property. The <code>identifier</code> needs to be unique
* for each PropertyOwner. The <code>guiName</code> will be stored in the metaData
@@ -92,7 +100,7 @@ public:
* The destructor taking care of deallocating all unused memory. This method will not
* remove the Property from the PropertyOwner.
*/
virtual ~Property();
virtual ~Property() = default;
/**
* This method returns the class name of the Property. The method is used by the
@@ -191,12 +199,25 @@ public:
* This method registers a <code>callback</code> function that will be called every
* time if either Property:set or Property::setLuaValue was called with a value that
* is different from the previously stored value. The callback can be removed by
* passing an empty <code>std::function<void()></code> object.
* calling the removeOnChange method with the OnChangeHandle that was returned here.
* \param callback The callback function that is called when the encapsulated type has
* been successfully changed by either the Property::set or Property::setLuaValue
* methods.
* \pre The callback must not be empty
* \return An OnChangeHandle that can be used in subsequent calls to remove a callback
*/
virtual void onChange(std::function<void()> callback);
OnChangeHandle onChange(std::function<void()> callback);
/**
* This method deregisters a callback that was previously registered with the onChange
* method. If OnChangeHandleAll is passed to this function, all registered callbacks
* are removed.
* \param handle An OnChangeHandle that was returned from a previous call to onChange
* by this property or OnChangeHandleAll if all callbacks should be removed.
* \pre handle must refer to a callback that has been previously registred
* \pre handle must refer to a callback that has not been removed previously
*/
void removeOnChange(OnChangeHandle handle);
/**
* This method returns the unique identifier of this Property.
@@ -389,8 +410,11 @@ protected:
/// The Dictionary containing all meta data necessary for external applications
ghoul::Dictionary _metaData;
/// The callback function that will be invoked whenever the encapsulated value changes
std::function<void()> _onChangeCallback;
/// The callback function sthat will be invoked whenever the value changes
std::vector<std::pair<OnChangeHandle, std::function<void()>>> _onChangeCallbacks;
private:
OnChangeHandle _currentHandleValue;
};
} // namespace properties

View File

@@ -40,6 +40,9 @@ namespace {
const char* _metaDataKeyViewPrefix = "view.";
}
Property::OnChangeHandle Property::OnChangeHandleAll =
std::numeric_limits<OnChangeHandle>::max();
const char* Property::ViewOptions::Color = "color";
const char* Property::ViewOptions::LightPosition = "lightPosition";
@@ -51,6 +54,7 @@ const char* Property::MetaDataKey = "MetaData";
Property::Property(std::string identifier, std::string guiName, Visibility visibility)
: _owner(nullptr)
, _identifier(std::move(identifier))
, _currentHandleValue(0)
{
ghoul_assert(!_identifier.empty(), "Identifier must not be empty");
ghoul_assert(!guiName.empty(), "guiName must not be empty");
@@ -59,8 +63,6 @@ Property::Property(std::string identifier, std::string guiName, Visibility visib
_metaData.setValue(MetaDataKeyGuiName, std::move(guiName));
}
Property::~Property() {}
const std::string& Property::identifier() const {
return _identifier;
}
@@ -163,8 +165,33 @@ const ghoul::Dictionary& Property::metaData() const {
return _metaData;
}
void Property::onChange(std::function<void()> callback) {
_onChangeCallback = std::move(callback);
Property::OnChangeHandle Property::onChange(std::function<void()> callback) {
ghoul_assert(callback, "The callback must not be empty");
OnChangeHandle handle = _currentHandleValue++;
_onChangeCallbacks.emplace_back(handle, std::move(callback));
return handle;
}
void Property::removeOnChange(OnChangeHandle handle) {
if (handle == OnChangeHandleAll) {
_onChangeCallbacks.clear();
}
else {
auto it = std::find_if(
_onChangeCallbacks.begin(),
_onChangeCallbacks.end(),
[handle](const std::pair<OnChangeHandle, std::function<void()>>& p) {
return p.first == handle;
}
);
ghoul_assert(
it != _onChangeCallbacks.end(),
"handle must be a valid callback handle"
);
_onChangeCallbacks.erase(it);
}
}
PropertyOwner* Property::owner() const {
@@ -176,8 +203,8 @@ void Property::setPropertyOwner(PropertyOwner* owner) {
}
void Property::notifyListener() {
if (_onChangeCallback) {
_onChangeCallback();
for (const std::pair<OnChangeHandle, std::function<void()>>& p : _onChangeCallbacks) {
p.second();
}
}