mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 19:50:03 -06:00
Enable Property to have multiple callbacks
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user