Commit 8186e6b5 authored by Jan Möbius's avatar Jan Möbius
Browse files

Missing files

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@13054 383ad7c9-94d9-4d36-a494-682f7c89f535
parent ca8c4c24
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision: 10745 $ *
* $LastChangedBy: moebius $ *
* $Date: 2011-01-26 10:23:50 +0100 (Mi, 26. Jan 2011) $ *
* *
\*===========================================================================*/
#include "Properties.hh"
using namespace std;
Properties::BaseProperty::BaseProperty()
{
}
Properties::BaseProperty::~BaseProperty()
{
}
Properties::Properties()
{
size_ = 0;
}
Properties::~Properties()
{
clear_properties();
}
/**
* @brief While preserving the properties themself, all values in the property are deleted
*
* This method preserves the properties, the property handles remain valid. Call this method
* if all objects in the derived class are deleted, so there is no object left that has properties
* attached to it. Notice the difference to Properties::clear_properties.
*/
void Properties::clean_properties()
{
for(vector<BaseProperty*>::iterator it = properties_.begin(); it != properties_.end(); ++it)
if((*it) != 0)
(*it)->clear();
size_ = 0;
}
/**
* @brief Deletes all properties, including their values
*
* Notice the difference to Properties::clean_properties, which preserves the properties and only
* deletes the values inside them.
*/
void Properties::clear_properties()
{
for(vector<BaseProperty*>::iterator it = properties_.begin(); it != properties_.end(); ++it)
if((*it) != 0)
delete *it;
properties_.clear();
property_names_.clear();
size_ = 0;
}
/**
* @brief Inserts a property for a new object at the given index
*
* If the derived class inserts a new object at the given index, the properties have to insert a new
* property, to keep it in sync. This is done by calling this method. To append at the end simply
* give the size of the vector holding the objects as parameter.
*
* @param _index Index of the new object, all the property indices for objects with index >= _index
* are increased by one
*/
void Properties::insert_property_at(int _index)
{
size_ += 1;
for(vector<BaseProperty*>::iterator it = properties_.begin(); it != properties_.end(); ++it)
if(*it != 0)
(*it)->insert_at(_index);
}
/**
* @brief Removes a property for an object that is being deleted from the derived class
*
* The same as for Properties::insert_property_at, just the other way around.
*
* @param _index Index of the new object, all the property indices for objects with index >= _index
* are decremented by one
*/
void Properties::remove_property_at(int _index)
{
size_ -= 1;
for(vector<BaseProperty*>::iterator it = properties_.begin(); it != properties_.end(); ++it)
if(*it != 0)
(*it)->remove_at(_index);
}
/**
* @brief Returns true if a property with the given name exists
*
* @param _name The properties name
* @return true if the property exists, false otherwise
*/
bool Properties::has_property(std::string _name)
{
if(property_names_.find(_name) == property_names_.end())
return false;
return true;
}
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision: 10745 $ *
* $LastChangedBy: moebius $ *
* $Date: 2011-01-26 10:23:50 +0100 (Mi, 26 Jan 2011) $ *
* *
\*===========================================================================*/
#ifndef PROPERTIES_HH
#define PROPERTIES_HH
/**
* @file Properties.hh
* @brief The header for the properties, one file for all objects
*
* All methods that are declared inside of template classes go into PropertiesT.cc, all other methods
* (those that are declared in normal classes) go into Properties.cc. Otherwise including the .cc
* (see end of this header) results in linker problems.
*/
#include <vector>
#include <map>
#include <string>
#include <OpenFlipper/common/GlobalDefines.hh>
/**
* @brief The property handle, use it to access the properties
*
* The template parameter corresponds to the type stored by this property.
*/
template<typename T>
class PropertyHandleT
{
friend class Properties;
protected:
typedef T value_type;
public:
PropertyHandleT(int _idx = -1);
virtual ~PropertyHandleT();
inline bool isValid();
protected:
int idx_; ///< The properties index
};
/**
* @brief The properties storage class
*
* This class is equipped with all methods you need to access the properties. Derive your class from it,
* then call the Properties::insert_property_at and Properties::remove_property_at members, whenever the
* vector holding the objects this property class refers to changes. The properties are bound to objects
* by their integer based index.
*/
class DLLEXPORT Properties
{
protected:
/**
* @brief The base class for all property template instances
*
* This class is used as an abstraction layer for the numerous instances of the PropertyT template.
* Its easier to store them in a vector this way.
*/
class DLLEXPORT BaseProperty
{
friend class Properties;
public:
BaseProperty();
virtual ~BaseProperty();
protected:
/**
* @name Synchronization
* Called by the Properties container to keep the indices in sync.
*/
//@{
virtual void insert_at(int _index) = 0; ///< Called by Properties as new objects are inserted in the derived class
virtual void remove_at(int _index) = 0; ///< Called by Properties as objects are deleted in the derived class
virtual void clear() = 0; ///< Called if all values have to be erased from this property
//@}
};
/**
* @brief A container storing a single property for all objects
*
* The template type is determined by the property handle PropertyHandleT used to add it to the
* Properties container.
*/
template<typename T>
class PropertyT : public BaseProperty
{
friend class Properties;
public:
PropertyT(unsigned long _size = 0);
virtual ~PropertyT();
public:
inline T &operator[](int _index);
protected:
/**
* @name Synchronization
* Called by the Properties container to keep the indices in sync.
*/
//@{
void insert_at(int _index);
void remove_at(int _index);
void clear();
//@}
protected:
std::vector<T> values_; ///< Stores a property for every object in the class derived from the Properties class. Access by index.
};
public:
Properties();
virtual ~Properties();
public:
/**
* @name Property management
* Use these to edit the properties themself, not their values.
*/
//@{
template<typename T> bool add_property(PropertyHandleT<T> &_hProp, std::string _name);
template<typename T> bool get_property(PropertyHandleT<T> &_hProp, std::string _name);
bool has_property(std::string _name);
template<typename T> bool remove_property(PropertyHandleT<T> &_hProp);
void clear_properties();
//@}
/**
* @name Property access
* Edit the properties values.
*/
//@{
template<typename T> T &property(PropertyHandleT<T> &_hProp, int _index);
//@}
protected:
/**
* @name Synchronization
* Call these methods to keep the property indices in sync with the objects they are bound to.
*/
//@{
void insert_property_at(int _index);
void remove_property_at(int _index);
void clean_properties();
//@}
protected:
std::map<std::string, int> property_names_; ///< The property names, key holding the name, value the properties index in Properties::properties_.
std::vector<BaseProperty*> properties_;
unsigned long size_; ///< The number of fields in each property, used when new properties have to be created.
};
/**
* @var Properties::properties_
* @brief A vector holding the properties.
*
* Access them using a property handle, that in turn is storing a index derived from
* Properties::property_names_. If a property is deleted its position in the vector is deleted and
* set to zero. If a new property is added it will either take a place in the vector that is zero
* or append itself to the end. This way the property handles stay valid all the time.
*/
//=============================================================================
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(PROPERTIES_C)
#define PROPERTIES_TEMPLATES
#include "PropertiesT.cc"
#endif
//=============================================================================
#endif // PROPERTIES_HH defined
//=============================================================================
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
#define PROPERTIES_C
#include <assert.h>
#include <iostream>
using namespace std;
//-----------------------------------------------------------------------------
/**
* @brief Adds a new property
*
* Give the property type as template parameter of the property handle. Assign a unique name to the property,
* to be able to access it later. The property is created an the property handle is updated. After this call
* it is directly ready for use. Returns false if a property with this name already exists. In that case
* the property handle will point to that property.
*
* @param _hProp A new unused property handle. When the method returns it will always point to a property.
* @param _name The properties name, has to be unique.
* @return true if a new property was created, false if an existing is returned.
*/
template<typename T>
bool Properties::add_property(PropertyHandleT<T> &_hProp, std::string _name)
{
// return the property if it exists
if(get_property(_hProp, _name))
return false;
// create it if not
// find the first free entry
vector<BaseProperty*>::iterator it;
for(it = properties_.begin(); it != properties_.end(); ++it)
if(*it == 0)
break;
if(it == properties_.end()) // found a free entry?
{
// append at the end
_hProp.idx_ = properties_.size();
property_names_.insert( pair<string, int>(_name, properties_.size()) );
properties_.push_back(dynamic_cast<BaseProperty*>(new PropertyT<T>(size_))); // the new one needs to have the same number of entries, to keep the correspondence
}else{
// insert in the free spot
_hProp.idx_ = it - properties_.begin();
property_names_.insert( pair<string, int>(_name, _hProp.idx_) );
*it = new PropertyT<T>(size_);
}
return true;
}
//-----------------------------------------------------------------------------
/**
* @brief Initiates the property handle
*
* If this call is successful and there is a property with the given name, the property handle will point to
* it. If not, this method returns false.
*
* @param _hProp A new, unused property handle
* @param _name The properties name
* @return true if the property exists and _hProp is now valid, false otherwise
*/
template<typename T>
bool Properties::get_property(PropertyHandleT<T> &_hProp, std::string _name)
{
// find the name
map<string, int>::iterator f = property_names_.find(_name);
if(f == property_names_.end())
return false;
// return the index
_hProp.idx_ = f->second;
assert(properties_[_hProp.idx_] != 0);
return true;
}
//-----------------------------------------------------------------------------
/**
* @brief Deletes a property including all values
*
* Call this method to remove the property identified by the handle.
*
* @param _hProp A valid property handle pointing to a property
* @return true if the handle was valid and a property was deleted, false otherwise
*/
template<typename T>
bool Properties::remove_property(PropertyHandleT<T> &_hProp)
{
if(!_hProp.isValid())
return false;
assert(_hProp.idx_ < (int)properties_.size());
assert(properties_[_hProp.idx_] != 0);
// delete the property
delete properties_[_hProp.idx_];
properties_[_hProp.idx_] = 0;
// find the names entry and delete it
for(map<string, int>::iterator it = property_names_.begin(); it != property_names_.end(); ++it)
{
if(it->second == _hProp.idx_)
{
property_names_.erase(it);
break;
}
}
// invalidate the handle
_hProp.idx_ = -1;
return true;
}
//-----------------------------------------------------------------------------
/**
* @brief Direct access to the properties values
*
* Access the property by using the same index as you use for the corresponding object in the derived class.
* This method returns a reference to the type given by the property handle. Make sure you use the right
* template parameter, otherwise the result is undefined (most likely a zero-reference).
*
* @param _hProp A valid handle to a property
* @param _index The index of the property, corresponds to the index of the object in the derived class
* this property refers to
*/
template<typename T>
T &Properties::property(PropertyHandleT<T> &_hProp, int _index)
{
assert(_hProp.idx_ >= 0 && _hProp.idx_ < (int)properties_.size());
assert(properties_[_hProp.idx_] != 0);
assert(reinterpret_cast< PropertyT<T>* >(properties_[_hProp.idx_]) != 0);
return (*reinterpret_cast< PropertyT<T>* >(properties_[_hProp.idx_]))[_index];
}
//-----------------------------------------------------------------------------
// PropertyHandleT
//-----------------------------------------------------------------------------
/**
* @brief Constructs a new property handle
*
* Do not use the index parameter, unless you really know what you do. Rather pass 0 and then
* use Properties::get_property.
*
* @param _idx The properties internal index, use with caution (or better, don't use at all)
*/
template<typename T>
PropertyHandleT<T>::PropertyHandleT(int _idx) :
idx_(_idx)
{
}
//-----------------------------------------------------------------------------
/**
* @brief Destructor
*/
template<typename T>
PropertyHandleT<T>::~PropertyHandleT()
{
}
//-----------------------------------------------------------------------------
/**
* @brief Returns true if the handle is valid, false otherwise
*
* This method does not test if there is a property with that index, so make sure you don't use
* handles after their property was deleted or use invalid values in the constructor.
*/
template<typename T>
bool PropertyHandleT<T>::isValid()
{
return idx_ >= 0;
}
//-----------------------------------------------------------------------------
// PropertyT
//-----------------------------------------------------------------------------
/**
* @brief Creates a new property with the given size
*
* If a property is created when the derived class is already holding objects, it is of course not in sync
* with regard to the number of stored values (e.g. see Properties::PropertyT::insert_at). The \e _size
* parameter allocates the memory to get the new property in sync.
*/
template<typename T>
Properties::PropertyT<T>::PropertyT(unsigned long _size)
{
for(unsigned long i = 0; i < _size; ++i)
values_.push_back(T());
}
//-----------------------------------------------------------------------------
/**
* @brief Destructor
*/
template<typename T>
Properties::PropertyT<T>::~PropertyT()
{
}
//-----------------------------------------------------------------------------
/**
* @brief Direct access to the value with the given index
*
* This method is used by the Properties class to gain access to the Properties values
*/
template<typename T>
T &Properties::PropertyT<T>::operator[](int _index)
{
assert(_index >= 0 && _index < (int)values_.size());