1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef TrenchBroom_NodeVisitor 21 #define TrenchBroom_NodeVisitor 22 23 #include "Model/ModelTypes.h" 24 25 namespace TrenchBroom { 26 namespace Model { 27 class BaseNodeVisitor { 28 private: 29 bool m_cancelled; 30 bool m_recursionStopped; 31 protected: 32 BaseNodeVisitor(); 33 public: 34 virtual ~BaseNodeVisitor(); 35 bool cancelled() const; 36 bool recursionStopped(); 37 protected: 38 void cancel(); 39 void stopRecursion(); 40 }; 41 42 class NodeVisitor : public BaseNodeVisitor { 43 protected: 44 NodeVisitor(); 45 public: 46 virtual ~NodeVisitor(); 47 48 virtual void visit(World* world); 49 virtual void visit(Layer* layer); 50 virtual void visit(Group* group); 51 virtual void visit(Entity* entity); 52 virtual void visit(Brush* brush); 53 private: 54 virtual void doVisit(World* world) = 0; 55 virtual void doVisit(Layer* layer) = 0; 56 virtual void doVisit(Group* group) = 0; 57 virtual void doVisit(Entity* entity) = 0; 58 virtual void doVisit(Brush* brush) = 0; 59 }; 60 61 class ConstNodeVisitor : public BaseNodeVisitor { 62 protected: 63 ConstNodeVisitor(); 64 public: 65 virtual ~ConstNodeVisitor(); 66 67 virtual void visit(const World* world); 68 virtual void visit(const Layer* layer); 69 virtual void visit(const Group* group); 70 virtual void visit(const Entity* entity); 71 virtual void visit(const Brush* brush); 72 private: 73 virtual void doVisit(const World* world) = 0; 74 virtual void doVisit(const Layer* layer) = 0; 75 virtual void doVisit(const Group* group) = 0; 76 virtual void doVisit(const Entity* entity) = 0; 77 virtual void doVisit(const Brush* brush) = 0; 78 }; 79 80 81 struct NeverStopRecursion { 82 bool operator()(const Node* node, bool matched) const; 83 }; 84 85 struct StopRecursionIfMatched { 86 bool operator()(const Node* node, bool matched) const; 87 }; 88 89 template <class P, class S = NeverStopRecursion> 90 class MatchingNodeVisitor : public NodeVisitor { 91 private: 92 P m_p; 93 S m_s; 94 protected: m_p(p)95 MatchingNodeVisitor(const P& p = P(), const S& s = S()) : m_p(p), m_s(s) {} 96 public: ~MatchingNodeVisitor()97 virtual ~MatchingNodeVisitor() {} 98 visit(World * world)99 void visit(World* world) { 100 const bool match = m_p(world); 101 if (match) NodeVisitor::visit(world); 102 if (m_s(world, match)) stopRecursion(); 103 } 104 visit(Layer * layer)105 void visit(Layer* layer) { 106 const bool match = m_p(layer); 107 if (match) NodeVisitor::visit(layer); 108 if (m_s(layer, match)) stopRecursion(); 109 } 110 visit(Group * group)111 void visit(Group* group) { 112 const bool match = m_p(group); 113 if (match) NodeVisitor::visit(group); 114 if (m_s(group, match)) stopRecursion(); 115 } 116 visit(Entity * entity)117 void visit(Entity* entity) { 118 const bool match = m_p(entity); 119 if (match) NodeVisitor::visit(entity); 120 if (m_s(entity, match)) stopRecursion(); 121 } 122 visit(Brush * brush)123 void visit(Brush* brush) { 124 const bool match = m_p(brush); 125 if (match) NodeVisitor::visit(brush); 126 if (m_s(brush, match)) stopRecursion(); 127 } 128 }; 129 130 template <class P, class S = NeverStopRecursion> 131 class ConstMatchingNodeVisitor : public ConstNodeVisitor { 132 private: 133 P m_p; 134 S m_s; 135 protected: m_p(p)136 ConstMatchingNodeVisitor(const P& p = P(), const S& s = S()) : m_p(p), m_s(s) {} 137 public: ~ConstMatchingNodeVisitor()138 virtual ~ConstMatchingNodeVisitor() {} 139 visit(const World * world)140 void visit(const World* world) { 141 const bool match = m_p(world); 142 if (match) ConstNodeVisitor::visit(world); 143 if (m_s(world, match)) stopRecursion(); 144 } 145 visit(const Layer * layer)146 void visit(const Layer* layer) { 147 const bool match = m_p(layer); 148 if (match) ConstNodeVisitor::visit(layer); 149 if (m_s(layer, match)) stopRecursion(); 150 } 151 visit(const Group * group)152 void visit(const Group* group) { 153 const bool match = m_p(group); 154 if (match) ConstNodeVisitor::visit(group); 155 if (m_s(group, match)) stopRecursion(); 156 } 157 visit(const Entity * entity)158 void visit(const Entity* entity) { 159 const bool match = m_p(entity); 160 if (match) ConstNodeVisitor::visit(entity); 161 if (m_s(entity, match)) stopRecursion(); 162 } 163 visit(const Brush * brush)164 void visit(const Brush* brush) { 165 const bool match = m_p(brush); 166 if (match) ConstNodeVisitor::visit(brush); 167 if (m_s(brush, match)) stopRecursion(); 168 } 169 }; 170 171 template <typename T> 172 class NodeQuery { 173 private: 174 bool m_hasResult; 175 T m_result; 176 public: 177 NodeQuery(const T& defaultResult = T()) : m_hasResult(false)178 m_hasResult(false), 179 m_result(defaultResult) {} 180 ~NodeQuery()181 virtual ~NodeQuery() {} 182 hasResult()183 bool hasResult() const { 184 return m_hasResult; 185 } 186 result()187 T result() const { 188 assert(hasResult()); 189 return m_result; 190 } 191 protected: setResult(T result)192 void setResult(T result) { 193 if (!m_hasResult) { 194 m_result = result; 195 m_hasResult = true; 196 } else { 197 m_result = doCombineResults(m_result, result); 198 } 199 } 200 private: doCombineResults(T oldResult,T newResult)201 virtual T doCombineResults(T oldResult, T newResult) const { return newResult; } 202 }; 203 } 204 } 205 206 #endif /* defined(TrenchBroom_NodeVisitor) */ 207