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_AttributableNode
21 #define TrenchBroom_AttributableNode
22 
23 #include "Assets/AssetTypes.h"
24 #include "Assets/EntityDefinition.h"
25 #include "Model/EntityAttributes.h"
26 #include "Model/ModelTypes.h"
27 #include "Model/Node.h"
28 
29 namespace TrenchBroom {
30     namespace Model {
31         class AttributableNode : public Node {
32         public: // some helper methods
33             static Assets::EntityDefinition* selectEntityDefinition(const AttributableNodeList& attributables);
34             static const Assets::AttributeDefinition* selectAttributeDefinition(const AttributeName& name, const AttributableNodeList& attributables);
35             static AttributeValue selectAttributeValue(const AttributeName& name, const AttributableNodeList& attributables);
36         protected:
37             static const String DefaultAttributeValue;
38 
39             Assets::EntityDefinition* m_definition;
40             EntityAttributes m_attributes;
41 
42             AttributableNodeList m_linkSources;
43             AttributableNodeList m_linkTargets;
44             AttributableNodeList m_killSources;
45             AttributableNodeList m_killTargets;
46 
47             // cache the classname for faster access
48             AttributeValue m_classname;
49         public:
50             virtual ~AttributableNode();
51 
52             Assets::EntityDefinition* definition() const;
53             void setDefinition(Assets::EntityDefinition* definition);
54         public: // attribute management
55             const Assets::AttributeDefinition* attributeDefinition(const AttributeName& name) const;
56 
57             const EntityAttribute::List& attributes() const;
58             void setAttributes(const EntityAttribute::List& attributes);
59 
60             bool hasAttribute(const AttributeName& name) const;
61             bool hasAttribute(const AttributeName& name, const AttributeValue& value) const;
62             bool hasAttributeWithPrefix(const AttributeName& prefix, const AttributeValue& value) const;
63             bool hasNumberedAttribute(const AttributeName& prefix, const AttributeValue& value) const;
64 
65             const AttributeValue& attribute(const AttributeName& name, const AttributeValue& defaultValue = DefaultAttributeValue) const;
66             const AttributeValue& classname(const AttributeValue& defaultClassname = AttributeValues::NoClassname) const;
67 
68             EntityAttributeSnapshot attributeSnapshot(const AttributeName& name) const;
69 
70             template <typename T>
addOrUpdateAttribute(const AttributeName & name,const T & value)71             void addOrUpdateAttribute(const AttributeName& name, const T& value) {
72                 addOrUpdateAttribute(name, convertValue(value));
73             }
74 
75             template <typename T, size_t S>
addOrUpdateAttribute(const AttributeName & name,const Vec<T,S> & value)76             void addOrUpdateAttribute(const AttributeName& name, const Vec<T,S>& value) {
77                 addOrUpdateAttribute(name, value.asString());
78             }
79 
80             bool canAddOrUpdateAttribute(const AttributeName& name, const AttributeValue& value) const;
81             void addOrUpdateAttribute(const AttributeName& name, const AttributeValue& value);
82 
83             bool canRenameAttribute(const AttributeName& name, const AttributeName& newName) const;
84             void renameAttribute(const AttributeName& name, const AttributeName& newName);
85 
86             bool canRemoveAttribute(const AttributeName& name) const;
87             void removeAttribute(const AttributeName& name);
88 
89             bool isAttributeNameMutable(const AttributeName& name) const;
90             bool isAttributeValueMutable(const AttributeName& name) const;
91         private: // attribute management internals
92             template <typename T>
convertValue(const T & value)93             AttributeValue convertValue(const T& value) const {
94                 static StringStream str;
95                 str.str("");
96                 str << value;
97                 return str.str();
98             }
99 
100             class NotifyAttributeChange {
101             private:
102                 NotifyNodeChange m_nodeChange;
103                 AttributableNode* m_node;
104             public:
105                 NotifyAttributeChange(AttributableNode* node);
106                 ~NotifyAttributeChange();
107             };
108 
109             void attributesWillChange();
110             void attributesDidChange();
111 
112             void updateClassname();
113         private: // search index management
114             void addAttributesToIndex();
115             void removeAttributesFromIndex();
116             void updateAttributeIndex(const EntityAttribute::List& newAttributes);
117 
118             void addAttributeToIndex(const AttributeName& name, const AttributeValue& value);
119             void removeAttributeFromIndex(const AttributeName& name, const AttributeValue& value);
120             void updateAttributeIndex(const AttributeName& oldName, const AttributeValue& oldValue, const AttributeName& newName, const AttributeValue& newValue);
121         public: // link management
122             const AttributableNodeList& linkSources() const;
123             const AttributableNodeList& linkTargets() const;
124             const AttributableNodeList& killSources() const;
125             const AttributableNodeList& killTargets() const;
126 
127             Vec3 linkSourceAnchor() const;
128             Vec3 linkTargetAnchor() const;
129 
130             bool hasMissingSources() const;
131             AttributeNameList findMissingLinkTargets() const;
132             AttributeNameList findMissingKillTargets() const;
133         private: // link management internals
134             void findMissingTargets(const AttributeName& prefix, AttributeNameList& result) const;
135 
136             void addLinks(const AttributeName& name, const AttributeValue& value);
137             void removeLinks(const AttributeName& name, const AttributeValue& value);
138             void updateLinks(const AttributeName& oldName, const AttributeName& oldValue, const AttributeName& newName, const AttributeValue& newValue);
139 
140             void addLinkTargets(const AttributeValue& targetname);
141             void addKillTargets(const AttributeValue& targetname);
142 
143             void removeLinkTargets(const AttributeValue& targetname);
144             void removeKillTargets(const AttributeValue& targetname);
145 
146             void addAllLinkSources(const AttributeValue& targetname);
147             void addAllLinkTargets();
148             void addAllKillSources(const AttributeValue& targetname);
149             void addAllKillTargets();
150 
151             void addLinkTargets(const AttributableNodeList& targets);
152             void addKillTargets(const AttributableNodeList& targets);
153             void addLinkSources(const AttributableNodeList& sources);
154             void addKillSources(const AttributableNodeList& sources);
155 
156             void removeAllLinkSources();
157             void removeAllLinkTargets();
158             void removeAllKillSources();
159             void removeAllKillTargets();
160 
161             void removeAllLinks();
162             void addAllLinks();
163 
164             void addLinkSource(AttributableNode* attributable);
165             void addLinkTarget(AttributableNode* attributable);
166             void addKillSource(AttributableNode* attributable);
167             void addKillTarget(AttributableNode* attributable);
168 
169             void removeLinkSource(AttributableNode* attributable);
170             void removeLinkTarget(AttributableNode* attributable);
171             void removeKillSource(AttributableNode* attributable);
172             void removeKillTarget(AttributableNode* attributable);
173         protected:
174             AttributableNode();
175         private: // implemenation of node interface
176             const String& doGetName() const;
177             virtual void doAncestorWillChange();
178             virtual void doAncestorDidChange();
179         private: // subclassing interface
180             virtual void doAttributesDidChange() = 0;
181             virtual bool doIsAttributeNameMutable(const AttributeName& name) const = 0;
182             virtual bool doIsAttributeValueMutable(const AttributeName& name) const = 0;
183             virtual Vec3 doGetLinkSourceAnchor() const = 0;
184             virtual Vec3 doGetLinkTargetAnchor() const = 0;
185         private: // hide copy constructor and assignment operator
186             AttributableNode(const AttributableNode&);
187             AttributableNode& operator=(const AttributableNode&);
188         };
189     }
190 }
191 
192 #endif /* defined(TrenchBroom_AttributableNode) */
193