Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit d9a8d2fa authored by schultezub's avatar schultezub
Browse files

* added PropertyCollection

 * extended Observer pattern implementation
 * added AbstractProperty
 * added InvalidationLevel

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@174 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 87824f71
......@@ -6,15 +6,17 @@ MESSAGE(STATUS "Configuring TUMVis Core")
FILE(GLOB TUMVIS_CORE_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
datastructures/*.cpp
eventhandler/*.cpp
eventhandlers/*.cpp
pipeline/*.cpp
properties/*.cpp
tools/*.cpp
)
FILE(GLOB TUMVIS_CORE_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
datastructures/*.h
eventhandler/*.h
eventhandlers/*.h
pipeline/*.h
properties/*.h
tools/*.h
)
......
......@@ -16,4 +16,8 @@ namespace TUMVis {
void AbstractPipeline::setCanvas(tgt::GLCanvas* canvas) {
_canvas = canvas;
}
PropertyCollection& AbstractPipeline::getPropertyCollection() {
return _properties;
}
}
......@@ -5,7 +5,8 @@
#include "tgt/logmanager.h"
#include "tgt/event/eventlistener.h"
#include "core/datastructures/datacontainer.h"
#include "core/eventhandler/abstracteventhandler.h"
#include "core/eventhandlers/abstracteventhandler.h"
#include "core/properties/propertycollection.h"
#include <vector>
......@@ -46,11 +47,18 @@ namespace TUMVis {
*/
void setCanvas(tgt::GLCanvas* canvas);
/**
* Returns the PropertyCollection of this processor.
* \return _properties
*/
PropertyCollection& getPropertyCollection();
protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
tgt::GLCanvas* _canvas; ///< Target canvas for rendering
std::vector<AbstractEventHandler*> _eventHandlers; ///< List of registered event handlers for the pipeline
PropertyCollection _properties; ///< PropertyCollection of this pipeline
static const std::string loggerCat_;
};
......
......@@ -21,16 +21,24 @@ namespace TUMVis {
return _data;
}
int AbstractProcessor::getInvalidationLevel() const {
const InvalidationLevel& AbstractProcessor::getInvalidationLevel() const {
return _invalidationLevel;
}
void AbstractProcessor::setInvalidationLevel(InvalidationLevel il) {
if (il == VALID) {
_invalidationLevel = static_cast<int>(VALID);
void AbstractProcessor::applyInvalidationLevel(InvalidationLevel::NamedLevels nl) {
_invalidationLevel.setLevel(nl);
}
void AbstractProcessor::onNotify(const PropertyObserverArgs& poa) {
_invalidationLevel.setLevel(poa._invalidationLevel);
// If processor is no longer valid, notify observers
if (! _invalidationLevel.isValid()) {
notifyObservers(ProcessorObserverArgs(this, _invalidationLevel));
}
else {
_invalidationLevel |= static_cast<int>(il);
}
}
PropertyCollection& AbstractProcessor::getPropertyCollection() {
return _properties;
}
}
......@@ -2,22 +2,42 @@
#define PROCESSOR_H__
#include "tgt/logmanager.h"
#include "core/tools/invalidationlevel.h"
#include "core/datastructures/datacontainer.h"
#include "core/properties/abstractproperty.h"
#include "core/properties/propertycollection.h"
#include <string>
#include <vector>
namespace TUMVis {
class AbstractProcessor;
/**
* Observer Arguments for Property observers.
*/
struct ProcessorObserverArgs : public GenericObserverArgs<AbstractProcessor> {
/**
* Creates new PropertyObserverArgs.
* \param subject Subject that emits the notification
* \param invalidationLevel Invalidation level of that property
*/
ProcessorObserverArgs(const AbstractProcessor* subject, InvalidationLevel invalidationLevel)
: GenericObserverArgs<AbstractProcessor>(subject)
, _invalidationLevel(invalidationLevel)
{}
InvalidationLevel _invalidationLevel; ///< Invalidation level of that processor
};
/**
* Abstract base class for TUMVis Processors.
*
* \sa AbstractPipeline
*/
class AbstractProcessor {
class AbstractProcessor : GenericObserver<PropertyObserverArgs>, public GenericObservable<ProcessorObserverArgs> {
public:
enum InvalidationLevel {
VALID = 0,
INVALID_RESULT = 1 << 0,
INVALID_SHADER = 1 << 1,
};
/**
* Creates a AbstractProcessor.
......@@ -52,22 +72,39 @@ namespace TUMVis {
/**
* Returns the invalidation level of this processor.
* Remind, that this is internally handled as a integer bit-set, so make sure to test via logic or.
* \return Integer representation of _invalidationLevel
* \return _invalidationLevel
*/
int getInvalidationLevel() const;
const InvalidationLevel& getInvalidationLevel() const;
/**
* Update the processor's invalidation level by \a il.
* If \a il is VALID, the processor's invalidation level will be set to VALID.
* If \a il is one of the INVALID_X state, the processor's corresponding flag will be set.
* \param il Invalidation level to set.
* Returns the PropertyCollection of this processor.
* \return _properties
*/
void setInvalidationLevel(InvalidationLevel il);
PropertyCollection& getPropertyCollection();
/**
* Update the processor's invalidation level by \a nl.
* If \a nl is VALID, the processor's invalidation level will be set to VALID.
* If \a nl is one of the INVALID_X state, the processor's corresponding flag will be set.
* \param nl Invalidation level to apply.
*/
void applyInvalidationLevel(InvalidationLevel::NamedLevels nl);
/**
* Gets called when one of the observed properties changed notifies its observers.
* \sa GenericObserver::onNotify, AbstractProperty
* \param poa PropertyObserverArgs ObserverArgument struct containing the emitting property and its InvalidationLevel
*/
virtual void onNotify(const PropertyObserverArgs& poa);
protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Processor
int _invalidationLevel; ///< Invalidation level of this processor
DataContainer _data; ///< DataContainer containing local working set of data for this Processor
InvalidationLevel _invalidationLevel; ///< current invalidation level of this processor
PropertyCollection _properties; ///< PropertyCollection of this processor
static const std::string loggerCat_;
};
......
#include "abstractproperty.h"
namespace TUMVis {
const std::string AbstractProperty::loggerCat_ = "TUMVis.core.datastructures.AbstractProperty";
AbstractProperty::AbstractProperty(const std::string& name, const std::string& title, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: _name(name)
, _title(title)
, _invalidationLevel(il)
{
}
AbstractProperty::~AbstractProperty() {
}
const std::string& AbstractProperty::getName() {
return _name;
}
const std::string& AbstractProperty::getTitle() {
return _title;
}
const InvalidationLevel& AbstractProperty::getInvalidationLevel() const {
return _invalidationLevel;
}
void AbstractProperty::setInvalidationLevel(const InvalidationLevel& il) {
_invalidationLevel = il;
}
}
#ifndef ABSTRACTPROPERTY_H__
#define ABSTRACTPROPERTY_H__
#include "tgt/logmanager.h"
#include "core/tools/invalidationlevel.h"
#include "core/tools/observer.h"
#include <string>
#include <vector>
namespace TUMVis {
// TODO: Hopefully this forward declaration works for the template definition.
// But as its only used as pointer within the template, it should be okay.
class AbstractProperty;
/**
* Observer Arguments for Property observers.
*/
struct PropertyObserverArgs : public GenericObserverArgs<AbstractProperty> {
/**
* Creates new PropertyObserverArgs.
* \param subject Subject that emits the notification
* \param invalidationLevel Invalidation level of that property
*/
PropertyObserverArgs(const AbstractProperty* subject, InvalidationLevel invalidationLevel)
: GenericObserverArgs<AbstractProperty>(subject)
, _invalidationLevel(invalidationLevel)
{}
InvalidationLevel _invalidationLevel; ///< Invalidation level of that property
};
/**
* Abstract base class for TUMVis Property.
*
* \todo Add PropertyWidgets, add clone()?
*/
class AbstractProperty : public GenericObservable<PropertyObserverArgs> {
public:
/**
* Creates a new AbstractProperty
* \param name Property name (unchangable!)
* \param title Property title (e.g. used for GUI)
* \param il Invalidation level that this property triggers
*/
AbstractProperty(const std::string& name, const std::string& title, InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
/**
* Virtual Destructor
**/
virtual ~AbstractProperty();
/**
* Returns the property name.
* \return _name
*/
const std::string& getName();
/**
* Returns the property title (e.g. used for GUI).
* \return _title
*/
const std::string& getTitle();
/**
* Returns the invalidation level that this property triggers.
* \return _invalidationLevel
*/
const InvalidationLevel& getInvalidationLevel() const;
/**
* Sets the invalidation level that this property triggers.
* \param il New invalidation level that this property triggers.
*/
void setInvalidationLevel(const InvalidationLevel& il);
protected:
// DO NOT REMOVE THE CONSTNESS OF _name. PropertyCollection relies on it!
const std::string _name; ///< Property name (unchangable on purpose!)
std::string _title; ///< Property title (e.g. used for GUI)
InvalidationLevel _invalidationLevel; ///< Invalidation level that this property triggers
static const std::string loggerCat_;
};
}
#endif // ABSTRACTPROPERTY_H__
#include "abstractproperty.h"
namespace TUMVis {
const std::string GenericProperty::loggerCat_ = "TUMVis.core.datastructures.GenericProperty";
}
......@@ -2,25 +2,31 @@
#define GENERICPROPERTY_H__
#include "tgt/logmanager.h"
#include "core/tools/observer.h"
#include <string>
#include <vector>
#include "core/properties/abstractproperty.h"
namespace TUMVis {
/**
* Abstract base class for TUMVis Property.
*
* Generic class for value-based properties.
*
* \tparam T Base type of the property's value.
* \todo Add PropertyWidgets
*/
template<typename T>
class GenericProperty : public Observable {
class GenericProperty : public AbstractProperty {
public:
/**
* Creates an GenericProperty.
* Creates a new GenericProperty.
* \param name Property name
* \param title Property title (e.g. used for GUI)
* \param value Initial value of the property
* \param il Invalidation level that this property triggers
*/
GenericProperty();
GenericProperty(
const std::string& name,
const std::string& title,
const T& value,
InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
/**
* Virtual Destructor
......@@ -28,35 +34,51 @@ namespace TUMVis {
virtual ~GenericProperty();
const std::string& getName() {
return _name;
}
/**
* Returns the current value of this property.
* \return _value
*/
const T getValue() const;
const std::string& getTitle() {
return _title;
}
/**
* Sets the property value to \a value and notifies all observers.
* \param value New value for this property.
*/
void setValue(const T& value);
const T getValue() const {
return _value;
}
void setValue(const T& value) {
_value = value;
notifyObservers();
}
protected:
T _value; ///< value of the property
static const std::string loggerCat_;
};
// - template implementation ----------------------------------------------------------------------
template<typename T>
TUMVis::GenericProperty<T>::GenericProperty(const std::string& name, const std::string& title, const T& value, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: AbstractProperty(name, title, il)
, _value(value)
{
}
protected:
template<typename T>
TUMVis::GenericProperty<T>::~GenericProperty() {
std::string _name;
std::string _title;
}
T _value;
template<typename T>
const T TUMVis::GenericProperty<T>::getValue() const {
return _value;
}
static const std::string loggerCat_;
};
template<typename T>
void TUMVis::GenericProperty<T>::setValue(const T& value) {
_value = value;
notifyObservers(PropertyObserverArgs(this, _invalidationLevel));
}
template<typename T>
const std::string TUMVis::GenericProperty<T>::loggerCat_ = "TUMVis.core.datastructures.GenericProperty";
}
#endif // GENERICPROPERTY_H__
#include "propertycollection.h"
namespace TUMVis {
PropertyCollection::PropertyCollection() {
}
void PropertyCollection::addProperty(AbstractProperty* prop) {
tgtAssert(prop != 0, "Property must not be 0!");
std::vector<AbstractProperty*>::iterator it = findProperty(prop->getName());
if (it != _properties.end()) {
*it = prop;
}
else {
_properties.push_back(prop);
}
}
void PropertyCollection::removeProperty(AbstractProperty* prop) {
tgtAssert(prop != 0, "Property must not be 0!");
std::vector<AbstractProperty*>::iterator it = findProperty(prop->getName());
if (it != _properties.end())
_properties.erase(it);
}
AbstractProperty* PropertyCollection::getProperty(const std::string& name) const {
std::vector<AbstractProperty*>::const_iterator it = findProperty(name);
if (it != _properties.end())
return *it;
return 0;
}
const std::vector<AbstractProperty*>& PropertyCollection::getProperties() const {
return _properties;
}
std::vector<AbstractProperty*>::iterator PropertyCollection::findProperty(const std::string& name) {
// using std::find would be more elegant, but also need more LOC...
for (std::vector<AbstractProperty*>::iterator it = _properties.begin(); it != _properties.end(); ++it) {
if ((*it)->getName() == name)
return it;
}
return _properties.end();
}
std::vector<AbstractProperty*>::const_iterator PropertyCollection::findProperty(const std::string& name) const {
// using std::find would be more elegant, but also need more LOC...
for (std::vector<AbstractProperty*>::const_iterator it = _properties.begin(); it != _properties.end(); ++it) {
if ((*it)->getName() == name)
return it;
}
return _properties.end();
}
}
\ No newline at end of file
#ifndef PROPERTYCOLLECTION_H__
#define PROPERTYCOLLECTION_H__
#include "core/properties/abstractproperty.h"
#include <vector>
#include <string>
namespace TUMVis {
/**
* Wrapper for a vector of Properties.
* Properties can be registered and then accessed via their names.
*/
class PropertyCollection {
public:
PropertyCollection();
/**
* Registers \a prop as property of this processor. Registered properties can be accessed from
* the outside, e.g. via getProperty(). An already existing property with the same name will
* be replaced.
* \note Processor does _not_ take ownership of the property. Hence, make sure to
* unregister the property before destroying/deleting it.
* \param prop Property to register
*/
void addProperty(AbstractProperty* prop);
/**
* Unregisters \a prop from this processor.
* \sa AbstractProcessor::addProperty
* \param prop Property to unregister.
*/
void removeProperty(AbstractProperty* prop);
/**
* Returns the property with the given name \a name.
* If no such property exists, the result will be 0.
* \param name Name of the property to return.
* \return The property named \a name, 0 if no such property exists.
*/
AbstractProperty* getProperty(const std::string& name) const;
/**
* Returns the list of all registered properties.
* \note Please do not mess with the non-const pointers in the vector.
* \return _properties
*/
const std::vector<AbstractProperty*>& getProperties() const;
private:
/**
* Searches _properties for a property named \a name.
* \param name Property name to search for.
* \return An iterator to the search result, _properties.end() if no such property was found.
*/
std::vector<AbstractProperty*>::iterator findProperty(const std::string& name);
/**
* Searches _properties for a property named \a name.
* \param name Property name to search for.
* \return An iterator to the search result, _properties.end() if no such property was found.
*/
std::vector<AbstractProperty*>::const_iterator findProperty(const std::string& name) const;
std::vector<AbstractProperty*> _properties; ///< list of all registered properties
};
}
#endif // PROPERTYCOLLECTION_H__
#ifndef INVALIDATIONLEVEL_H__
#define INVALIDATIONLEVEL_H__
namespace TUMVis {
/**
* Wrapper class for enum-int-based invalidation levels
* Invalidation Level will internally be stored in an integer, the named levels define the bit mask.
* All Accessor methods correctly apply the bitmasks.
*/
struct InvalidationLevel {
public:
/**
* Available invalidation levels
*/
enum NamedLevels {
VALID = 0,
INVALID_RESULT = 1 << 0,
INVALID_SHADER = 1 << 1,
};
/**
* Creates a new invalidation level.
* \param defaultLevel Initial invalidation level
*/
InvalidationLevel(int defaultLevel = VALID) {
_level = static_cast<int>(defaultLevel);
}
/**
* Returns the invalidation level
* \return _level
*/
int getLevel() const {
return _level;
}
/**
* Returns wheter the invalidation level is valid.
* \return _level == VALID
*/
bool isValid() const {
return _level == static_cast<int>(VALID);
}