/*===========================================================================*\ * * * OpenMesh * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * * * * OpenMesh 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. * * * * OpenMesh 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 OpenMesh. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Date$ * * * \*===========================================================================*/ #ifndef PROPERTYMANAGER_HH_ #define PROPERTYMANAGER_HH_ #include namespace OpenMesh { /** * This class is intended to manage the lifecycle of properties. * It also defines convenience operators to access the encapsulated * property's value. * * Usage example: * * \code * TriMesh mesh; * PropertyManager, MeshT> visited(mesh, "visited.plugin-example.i8.informatik.rwth-aachen.de"); * * for (TriMesh::VertexIter vh_it = mesh.begin(); ... ; ...) { * if (!visited[*vh_it]) { * visitComponent(mesh, *vh_it, visited); * } * } * \endcode * */ template class PropertyManager { private: /** * Noncopyable because there aren't not straightforward copy semantics. */ PropertyManager(const PropertyManager&); /** * Noncopyable because there aren't not straightforward copy semantics. */ const PropertyManager& operator=(const PropertyManager&); public: /** * Constructor. * * Throws an \p std::runtime_error if \p existing is true and * no property named \p propname of the appropriate property type * exists. * * @param mesh The mesh on which to create the property. * @param propname The name of the property. * @param existing If false, a new property is created and its lifecycle is managed (i.e. * the property is deleted upon destruction of the PropertyManager instance). If true, * the instance merely acts as a convenience wrapper around an existing property with no * lifecycle management whatsoever. */ PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing) { if (existing) { if (!mesh_->get_property_handle(prop_, propname)) { std::ostringstream oss; oss << "Requested property handle \"" << propname << "\" does not exist."; throw std::runtime_error(oss.str()); } } else { mesh_->add_property(prop_, propname); } } ~PropertyManager() { deleteProperty(); } #if __cplusplus > 199711L or __GXX_EXPERIMENTAL_CXX0X__ /** * Move constructor. Transfers ownership (delete responsibility). */ PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_) { rhs.retain_ = true; } /** * Move assignment. Transfers ownership (delete responsibility). */ PropertyManager &operator=(PropertyManager &&rhs) { deleteProperty(); mesh_ = rhs.mesh_; prop_ = rhs.prop_; retain_ = rhs.retain_; rhs.retain_ = true; return *this; } /** * Create a property manager for the supplied property and mesh. * If the property doesn't exist, it is created. In any case, * lifecycle management is disabled. */ static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) { PROPTYPE dummy_prop; PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname)); pm.retain(); return std::move(pm); } #endif /** * \brief Disable lifecycle management for this property. * * If this method is called, the encapsulated property will not be deleted * upon destruction of the PropertyManager instance. */ inline void retain() { retain_ = true; } /** * Access the encapsulated property. */ inline PROPTYPE &operator* () { return prop_; } /** * Access the encapsulated property. */ inline const PROPTYPE &operator* () const { return prop_; } /** * Enables convenient access to the encapsulated property. * * For a usage example see this class' documentation. * * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.) */ template inline typename PROPTYPE::reference operator[] (const HandleType &handle) { return mesh_->property(prop_, handle); } /** * Enables convenient access to the encapsulated property. * * For a usage example see this class' documentation. * * @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.) */ template inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const { return mesh_->property(prop_, handle); } private: void deleteProperty() { if (!retain_) mesh_->remove_property(prop_); } private: MeshT *mesh_; PROPTYPE prop_; bool retain_; }; } /* namespace OpenMesh */ #endif /* PROPERTYMANAGER_HH_ */