traverselib.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #if !defined (INCLUDED_TRAVERSELIB_H)
00023 #define INCLUDED_TRAVERSELIB_H
00024 
00025 #include "debugging/debugging.h"
00026 
00027 #include "scenelib.h"
00028 #include "undolib.h"
00029 #include "container/container.h"
00030 
00031 #include <list>
00032 #include <vector>
00033 #include <algorithm>
00034 #include <cassert>
00035 
00036 class TraversableObserverInsertOutputIterator
00037 {
00038     protected:
00039         scene::Traversable::Observer* m_observer;
00040     public:
00041         typedef std::output_iterator_tag iterator_category;
00042         typedef void difference_type;
00043         typedef void value_type;
00044         typedef void pointer;
00045         typedef void reference;
00046 
00047         TraversableObserverInsertOutputIterator (scene::Traversable::Observer* observer) :
00048             m_observer(observer)
00049         {
00050         }
00051         TraversableObserverInsertOutputIterator& operator= (const NodeReference& node)
00052         {
00053             m_observer->insert(node);
00054             return *this;
00055         }
00056         TraversableObserverInsertOutputIterator& operator= (const NodeSmartReference& node)
00057         {
00058             m_observer->insert(node);
00059             return *this;
00060         }
00061         TraversableObserverInsertOutputIterator& operator* ()
00062         {
00063             return *this;
00064         }
00065         TraversableObserverInsertOutputIterator& operator++ ()
00066         {
00067             return *this;
00068         }
00069         TraversableObserverInsertOutputIterator& operator++ (int)
00070         {
00071             return *this;
00072         }
00073 };
00074 
00075 class TraversableObserverEraseOutputIterator
00076 {
00077     protected:
00078         scene::Traversable::Observer* m_observer;
00079     public:
00080         typedef std::output_iterator_tag iterator_category;
00081         typedef void difference_type;
00082         typedef void value_type;
00083         typedef void pointer;
00084         typedef void reference;
00085 
00086         TraversableObserverEraseOutputIterator (scene::Traversable::Observer* observer) :
00087             m_observer(observer)
00088         {
00089         }
00090         TraversableObserverEraseOutputIterator& operator= (const NodeReference& node)
00091         {
00092             m_observer->erase(node);
00093             return *this;
00094         }
00095         TraversableObserverEraseOutputIterator& operator= (const NodeSmartReference& node)
00096         {
00097             m_observer->erase(node);
00098             return *this;
00099         }
00100         TraversableObserverEraseOutputIterator& operator* ()
00101         {
00102             return *this;
00103         }
00104         TraversableObserverEraseOutputIterator& operator++ ()
00105         {
00106             return *this;
00107         }
00108         TraversableObserverEraseOutputIterator& operator++ (int)
00109         {
00110             return *this;
00111         }
00112 };
00113 typedef UnsortedSet<NodeSmartReference> UnsortedNodeSet;
00114 
00116 inline void nodeset_diff (const UnsortedNodeSet& self, const UnsortedNodeSet& other,
00117         scene::Traversable::Observer* observer)
00118 {
00119     std::vector<NodeSmartReference> sorted(self.begin(), self.end());
00120     std::vector<NodeSmartReference> other_sorted(other.begin(), other.end());
00121 
00122     std::sort(sorted.begin(), sorted.end());
00123     std::sort(other_sorted.begin(), other_sorted.end());
00124 
00125     std::set_difference(sorted.begin(), sorted.end(), other_sorted.begin(), other_sorted.end(),
00126             TraversableObserverEraseOutputIterator(observer));
00127     std::set_difference(other_sorted.begin(), other_sorted.end(), sorted.begin(), sorted.end(),
00128             TraversableObserverInsertOutputIterator(observer));
00129 }
00130 
00132 class TraversableNodeSet: public scene::Traversable
00133 {
00134         UnsortedNodeSet m_children;
00135         UndoableObject<TraversableNodeSet> m_undo;
00136         Observer* m_observer;
00137 
00138         void copy (const TraversableNodeSet& other)
00139         {
00140             m_children = other.m_children;
00141         }
00142         void notifyInsertAll ()
00143         {
00144             if (m_observer) {
00145                 for (UnsortedNodeSet::iterator i = m_children.begin(); i != m_children.end(); ++i) {
00146                     m_observer->insert(*i);
00147                 }
00148             }
00149         }
00150         void notifyEraseAll ()
00151         {
00152             if (m_observer) {
00153                 for (UnsortedNodeSet::iterator i = m_children.begin(); i != m_children.end(); ++i) {
00154                     m_observer->erase(*i);
00155                 }
00156             }
00157         }
00158     public:
00159         TraversableNodeSet () :
00160             m_undo(*this), m_observer(0)
00161         {
00162         }
00163         TraversableNodeSet (const TraversableNodeSet& other) :
00164             scene::Traversable(other), m_undo(*this), m_observer(0)
00165         {
00166             copy(other);
00167             notifyInsertAll();
00168         }
00169         ~TraversableNodeSet ()
00170         {
00171             notifyEraseAll();
00172         }
00173         TraversableNodeSet& operator= (const TraversableNodeSet& other)
00174         {
00175             // optimised change-tracking using diff algorithm
00176             if (m_observer) {
00177                 nodeset_diff(m_children, other.m_children, m_observer);
00178             }
00179             copy(other);
00180             return *this;
00181         }
00182         void swap (TraversableNodeSet& other)
00183         {
00184             std::swap(m_children, other.m_children);
00185             std::swap(m_observer, other.m_observer);
00186         }
00187 
00188         void attach (Observer* observer)
00189         {
00190             ASSERT_MESSAGE(m_observer == 0, "TraversableNodeSet::attach: observer cannot be attached");
00191             m_observer = observer;
00192             notifyInsertAll();
00193         }
00194         void detach (Observer* observer)
00195         {
00196             ASSERT_MESSAGE(m_observer == observer, "TraversableNodeSet::detach: observer cannot be detached");
00197             notifyEraseAll();
00198             m_observer = 0;
00199         }
00201         void insert (scene::Node& node)
00202         {
00203             ASSERT_MESSAGE(&node != 0, "TraversableNodeSet::insert: sanity check failed");
00204             m_undo.save();
00205 
00206             ASSERT_MESSAGE(m_children.find(NodeSmartReference(node)) == m_children.end(), "TraversableNodeSet::insert - element already exists");
00207 
00208             m_children.insert(NodeSmartReference(node));
00209 
00210             if (m_observer) {
00211                 m_observer->insert(node);
00212             }
00213         }
00215         void erase (scene::Node& node)
00216         {
00217             ASSERT_MESSAGE(&node != 0, "TraversableNodeSet::erase: sanity check failed");
00218             m_undo.save();
00219 
00220             ASSERT_MESSAGE(m_children.find(NodeSmartReference(node)) != m_children.end(), "TraversableNodeSet::erase - failed to find element");
00221 
00222             if (m_observer) {
00223                 m_observer->erase(node);
00224             }
00225 
00226             m_children.erase(NodeSmartReference(node));
00227         }
00229         void traverse (const Walker& walker)
00230         {
00231             UnsortedNodeSet::iterator i = m_children.begin();
00232             while (i != m_children.end()) {
00233                 // post-increment the iterator
00234                 Node_traverseSubgraph(*i++, walker);
00235                 // the Walker can safely remove the current node from
00236                 // this container without invalidating the iterator
00237             }
00238         }
00240         bool empty () const
00241         {
00242             return m_children.empty();
00243         }
00244 
00245         void instanceAttach (MapFile* map)
00246         {
00247             m_undo.instanceAttach(map);
00248         }
00249         void instanceDetach (MapFile* map)
00250         {
00251             m_undo.instanceDetach(map);
00252         }
00253 };
00254 
00255 namespace std
00256 {
00259     inline void swap (TraversableNodeSet& self, TraversableNodeSet& other)
00260     {
00261         self.swap(other);
00262     }
00263 }
00264 
00266 class TraversableNode: public scene::Traversable
00267 {
00268     public:
00269         TraversableNode () :
00270             m_node(0), m_observer(0)
00271         {
00272         }
00273 
00274         // traverse
00275         void attach (Observer* observer)
00276         {
00277             ASSERT_MESSAGE(m_observer == 0, "TraversableNode::attach - cannot attach observer");
00278             m_observer = observer;
00279             if (m_node != 0) {
00280                 m_observer->insert(*m_node);
00281             }
00282         }
00283         void detach (Observer* observer)
00284         {
00285             ASSERT_MESSAGE(m_observer == observer, "TraversableNode::detach - cannot detach observer");
00286             if (m_node != 0) {
00287                 m_observer->erase(*m_node);
00288             }
00289             m_observer = 0;
00290         }
00292         void insert (scene::Node& node)
00293         {
00294             // Throw an exception if there is already a contained node
00295             assert(m_node == 0);
00296 
00297             m_node = &node;
00298             node.IncRef();
00299 
00300             if (m_observer != 0) {
00301                 m_observer->insert(node);
00302             }
00303         }
00304         void erase (scene::Node& node)
00305         {
00306             assert(m_node == &node);
00307 
00308             if (m_observer != 0) {
00309                 m_observer->erase(node);
00310             }
00311 
00312             m_node = 0;
00313             node.DecRef();
00314         }
00315         void traverse (const scene::Traversable::Walker& walker)
00316         {
00317             if (m_node != 0) {
00318                 Node_traverseSubgraph(*m_node, walker);
00319             }
00320         }
00321         bool empty () const
00322         {
00323             return m_node != 0;
00324         }
00325 
00326         scene::Node& get ()
00327         {
00328             return *m_node;
00329         }
00330 
00331     private:
00332         scene::Node* m_node;
00333         Observer* m_observer;
00334 };
00335 
00336 class TraversableObserverInsert
00337 {
00338         scene::Node& node;
00339     public:
00340         TraversableObserverInsert (scene::Node& node) :
00341             node(node)
00342         {
00343         }
00344         void operator() (scene::Traversable::Observer& observer) const
00345         {
00346             observer.insert(node);
00347         }
00348 };
00349 
00350 class TraversableObserverErase
00351 {
00352         scene::Node& node;
00353     public:
00354         TraversableObserverErase (scene::Node& node) :
00355             node(node)
00356         {
00357         }
00358         void operator() (scene::Traversable::Observer& observer) const
00359         {
00360             observer.erase(node);
00361         }
00362 };
00363 
00364 class TraversableObserverPairRelay: public ReferencePair<scene::Traversable::Observer> ,
00365         public scene::Traversable::Observer
00366 {
00367     public:
00368         void insert (scene::Node& node)
00369         {
00370             forEach(TraversableObserverInsert(node));
00371         }
00372         void erase (scene::Node& node)
00373         {
00374             forEach(TraversableObserverErase(node));
00375         }
00376 };
00377 
00378 template<typename Type>
00379 class ReferenceSet
00380 {
00381         typedef UniqueSet<Type*> Values;
00382         Values m_values;
00383     public:
00384         void attach (Type& t)
00385         {
00386             m_values.insert(&t);
00387         }
00388         void detach (Type& t)
00389         {
00390             m_values.erase(&t);
00391         }
00392         template<typename Functor>
00393         void forEach (const Functor& functor)
00394         {
00395             for (typename Values::iterator i = m_values.begin(); i != m_values.end(); ++i) {
00396                 functor(*(*i));
00397             }
00398         }
00399 };
00400 
00401 class TraversableObserverRelay: public ReferenceSet<scene::Traversable::Observer> , public scene::Traversable::Observer
00402 {
00403     public:
00404         TraversableObserverRelay ()
00405         {
00406         }
00407         ~TraversableObserverRelay ()
00408         {
00409         }
00410 
00411         void insert (scene::Node& node)
00412         {
00413             forEach(TraversableObserverInsert(node));
00414         }
00415         void erase (scene::Node& node)
00416         {
00417             forEach(TraversableObserverErase(node));
00418         }
00419 };
00420 
00421 #endif

Generated by  doxygen 1.6.2