//-*-c++-*- /** Authors: David Auber, Patrick Mary, Morgan Mathiaut from the LaBRI Visualization Team Email : auber@tulip-software.org Last modification : 22/01/2009 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #ifndef TULIP_PROPERTIESPROXY_H #define TULIP_PROPERTIESPROXY_H #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "tulip/Observable.h" #include "tulip/ObservableProperty.h" #include "tulip/Iterator.h" #include "tulip/Types.h" #include "tulip/PropertyAlgorithm.h" #include "tulip/MutableContainer.h" #include "tulip/ReturnType.h" #include "tulip/tulipconf.h" #include "tulip/TemplateFactory.h" namespace tlp { /** * \defgroup properties */ /*@{*/ //============================================================= class TLP_SCOPE PropertyInterface: public Observable, public ObservableProperty { public: virtual ~PropertyInterface(); virtual void erase(const node) =0; virtual void erase(const edge) =0; virtual void copy(const node, const node, PropertyInterface *) =0; virtual void copy(const edge, const edge, PropertyInterface *) =0; virtual PropertyInterface* clonePrototype(Graph *, std::string) =0; //================================================================================= // Returns a string describing the type of the property. // i.e. "graph", "double", "layout", "string", "integer", "color", "size", ... virtual std::string getTypename() = 0; static std::string getTypename( PropertyInterface * ); // Untyped accessors virtual std::string getNodeDefaultStringValue() = 0; virtual std::string getEdgeDefaultStringValue() = 0; virtual std::string getNodeStringValue( const node n ) = 0; virtual std::string getEdgeStringValue( const edge e ) = 0; virtual bool setNodeStringValue( const node n, const std::string & v ) = 0; virtual bool setEdgeStringValue( const edge e, const std::string & v ) = 0; virtual bool setAllNodeStringValue( const std::string & v ) = 0; virtual bool setAllEdgeStringValue( const std::string & v ) = 0; virtual Iterator<node>* getNonDefaultValuatedNodes()=0; virtual Iterator<edge>* getNonDefaultValuatedEdges()=0; protected: // redefinitions of ObservableProperty methods void notifyAfterSetNodeValue(PropertyInterface*,const node n); void notifyAfterSetEdgeValue(PropertyInterface*,const edge e); void notifyAfterSetAllNodeValue(PropertyInterface*); void notifyAfterSetAllEdgeValue(PropertyInterface*); void notifyDestroy(PropertyInterface*); }; /** * This class is used to store a property of a graph. * A property is a couple of two functions: * - One from the set of nodes to a set of Tnode value * - One from the set of edges to a set of Tedge value * * A AbstractProperty can be connected or not to a PropertyAlgorithm. * In the first case it can be seen as buffer beetween the property and the user. * In the second case it is only a memory area for storing data. * A AbstractProperty is an observable, so it can be observed by others objects. */ template <class Tnode, class Tedge, class TPROPERTY = PropertyAlgorithm > class TLP_SCOPE AbstractProperty : public PropertyInterface { friend class GraphView; public: static TLP_SCOPE TemplateFactory< PropertyFactory<TPROPERTY>, TPROPERTY, PropertyContext > *factory; static void initFactory() { if (!factory) { factory = new TemplateFactory< PropertyFactory<TPROPERTY>, TPROPERTY, PropertyContext >; } } AbstractProperty(Graph *); /** * Returns the node default value of the property proxy * warnning: If the type is a pointer it can produce big memory * leak if the user doesn't manage the memory himself */ typename Tnode::RealType getNodeDefaultValue(); /** * Returns the edge default value of the property proxy * warnning: If the type is a pointer it can produce big memory * leak if the user doesn't manage the memory himself */ typename Tedge::RealType getEdgeDefaultValue(); /** * Returns the value associated to the node n in this property. * If the value is already fixed it is done in constant time. * else if it is a computed property (plug-in), it calls the associated property * If there is no value and no algorithms it returns the default value * depending of the type. */ typename ReturnType<typename Tnode::RealType>::Value getNodeValue(const node n ); /** * Returns the value associated to the node n in this property. * If the value is already fixed it is done in constant time. * else if it is a computed property (plug-in), it calls the associated property * If there is no value and no algorithms it returns the default value * depending of the type. */ typename ReturnType<typename Tedge::RealType>::Value getEdgeValue(const edge e); /** * Set the value of a node n and notify the observers of a modification. * Warning : When using computed property (plug-in), if one sets the value of * a node n, the plug-in won't be call for n. */ void setNodeValue(const node n, const typename Tnode::RealType &v); /** * Set the value of an edge and notify the observers of a modification. * Warning : When using computed property (plug-in), if one sets the value of * a edge e, the plug-in won't be call for e. */ void setEdgeValue(const edge e, const typename Tedge::RealType &v); /** * Set the value of all nodes and notify the observers */ void setAllNodeValue(const typename Tnode::RealType &v); /** * Set the value of all edges and notify the observers */ void setAllEdgeValue(const typename Tedge::RealType &v); //================================================================================= virtual void erase(const node n); //================================================================================= virtual void erase(const edge e); //================================================================================= // Because of compilation pb on Windows platform (g++ bug ???) // we include the code of the method below instead of having it // included in AbstractProperty.cpp virtual AbstractProperty<Tnode,Tedge,TPROPERTY>& operator =(AbstractProperty<Tnode,Tedge,TPROPERTY> &prop) { if (this!= &prop) { //============================================================= //The backup is necessary, if a proxy is a function which use the value of "*this" //Future implementation should take into account : recursive or not //It will enable to presserve the backup cost in a lot of case. //============================================================= if (graph == 0) graph = prop.graph; if (graph == prop.graph) { setAllNodeValue(prop.getNodeDefaultValue()); setAllEdgeValue(prop.getEdgeDefaultValue()); Iterator<node> *itN = prop.getNonDefaultValuatedNodes(); while (itN->hasNext()) { node itn = itN->next(); setNodeValue(itn, prop.getNodeValue(itn)); } delete itN; Iterator<edge> *itE = prop.getNonDefaultValuatedEdges(); while (itE->hasNext()) { edge ite = itE->next(); setEdgeValue(ite, prop.getEdgeValue(ite)); } delete itE; } else { MutableContainer<typename Tnode::RealType> backupNode; MutableContainer<typename Tedge::RealType> backupEdge; backupNode.setAll(prop.nodeDefaultValue); backupEdge.setAll(prop.edgeDefaultValue); Iterator<node> *itN=graph->getNodes(); while (itN->hasNext()) { node itn=itN->next(); if (prop.graph->isElement(itn)) backupNode.set(itn.id,prop.getNodeValue(itn)); } delete itN; Iterator<edge> *itE=graph->getEdges(); while (itE->hasNext()) { edge ite=itE->next(); if (prop.graph->isElement(ite)) backupEdge.set(ite.id,prop.getEdgeValue(ite)); } delete itE; //==============================================================* itN=graph->getNodes(); while (itN->hasNext()) { node itn=itN->next(); if (prop.graph->isElement(itn)) setNodeValue(itn,backupNode.get(itn.id)); } delete itN; itE=graph->getEdges(); while (itE->hasNext()) { edge ite=itE->next(); if (prop.graph->isElement(ite)) setEdgeValue(ite,backupEdge.get(ite.id)); } delete itE; } clone_handler(prop); } return *this; } //================================================================================= bool compute(const std::string &algorithm, std::string &msg, const PropertyContext&); //================================================================================= virtual std::string getTypename(); // Untyped accessors virtual std::string getNodeDefaultStringValue(); virtual std::string getEdgeDefaultStringValue(); virtual std::string getNodeStringValue( const node n ); virtual std::string getEdgeStringValue( const edge e ); virtual bool setNodeStringValue( const node n, const std::string & v ); virtual bool setEdgeStringValue( const edge e, const std::string & v ); virtual bool setAllNodeStringValue( const std::string & v ); virtual bool setAllEdgeStringValue( const std::string & v ); // returns an iterator on all nodes whose value is different // from the default value virtual Iterator<node>* getNonDefaultValuatedNodes(); // returns an iterator on all edges whose value is different // from the default value virtual Iterator<edge>* getNonDefaultValuatedEdges(); protected: //================================================================================= ///Enable to clone part of sub_class virtual void clone_handler(AbstractProperty<Tnode,Tedge,TPROPERTY> &){}; protected: MutableContainer<typename Tnode::RealType> nodeProperties; MutableContainer<typename Tedge::RealType> edgeProperties; Graph *graph; bool circularCall; typename Tnode::RealType nodeDefaultValue; typename Tedge::RealType edgeDefaultValue; }; /*@}*/ } #include "./cxx/AbstractProperty.cxx" #endif