Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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);
}