/*
Copyright (C) 2010-2014 Kristian Duske
This file is part of TrenchBroom.
TrenchBroom 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 3 of the License, or
(at your option) any later version.
TrenchBroom 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with TrenchBroom. If not, see .
*/
#ifndef TrenchBroom_AttributableNode
#define TrenchBroom_AttributableNode
#include "Assets/AssetTypes.h"
#include "Assets/EntityDefinition.h"
#include "Model/EntityAttributes.h"
#include "Model/ModelTypes.h"
#include "Model/Node.h"
namespace TrenchBroom {
namespace Model {
class AttributableNode : public Node {
public: // some helper methods
static Assets::EntityDefinition* selectEntityDefinition(const AttributableNodeList& attributables);
static const Assets::AttributeDefinition* selectAttributeDefinition(const AttributeName& name, const AttributableNodeList& attributables);
static AttributeValue selectAttributeValue(const AttributeName& name, const AttributableNodeList& attributables);
protected:
static const String DefaultAttributeValue;
Assets::EntityDefinition* m_definition;
EntityAttributes m_attributes;
AttributableNodeList m_linkSources;
AttributableNodeList m_linkTargets;
AttributableNodeList m_killSources;
AttributableNodeList m_killTargets;
// cache the classname for faster access
AttributeValue m_classname;
public:
virtual ~AttributableNode();
Assets::EntityDefinition* definition() const;
void setDefinition(Assets::EntityDefinition* definition);
public: // attribute management
const Assets::AttributeDefinition* attributeDefinition(const AttributeName& name) const;
const EntityAttribute::List& attributes() const;
void setAttributes(const EntityAttribute::List& attributes);
bool hasAttribute(const AttributeName& name) const;
bool hasAttribute(const AttributeName& name, const AttributeValue& value) const;
bool hasAttributeWithPrefix(const AttributeName& prefix, const AttributeValue& value) const;
bool hasNumberedAttribute(const AttributeName& prefix, const AttributeValue& value) const;
const AttributeValue& attribute(const AttributeName& name, const AttributeValue& defaultValue = DefaultAttributeValue) const;
const AttributeValue& classname(const AttributeValue& defaultClassname = AttributeValues::NoClassname) const;
EntityAttributeSnapshot attributeSnapshot(const AttributeName& name) const;
template
void addOrUpdateAttribute(const AttributeName& name, const T& value) {
addOrUpdateAttribute(name, convertValue(value));
}
template
void addOrUpdateAttribute(const AttributeName& name, const Vec& value) {
addOrUpdateAttribute(name, value.asString());
}
bool canAddOrUpdateAttribute(const AttributeName& name, const AttributeValue& value) const;
void addOrUpdateAttribute(const AttributeName& name, const AttributeValue& value);
bool canRenameAttribute(const AttributeName& name, const AttributeName& newName) const;
void renameAttribute(const AttributeName& name, const AttributeName& newName);
bool canRemoveAttribute(const AttributeName& name) const;
void removeAttribute(const AttributeName& name);
bool isAttributeNameMutable(const AttributeName& name) const;
bool isAttributeValueMutable(const AttributeName& name) const;
private: // attribute management internals
template
AttributeValue convertValue(const T& value) const {
static StringStream str;
str.str("");
str << value;
return str.str();
}
class NotifyAttributeChange {
private:
NotifyNodeChange m_nodeChange;
AttributableNode* m_node;
public:
NotifyAttributeChange(AttributableNode* node);
~NotifyAttributeChange();
};
void attributesWillChange();
void attributesDidChange();
void updateClassname();
private: // search index management
void addAttributesToIndex();
void removeAttributesFromIndex();
void updateAttributeIndex(const EntityAttribute::List& newAttributes);
void addAttributeToIndex(const AttributeName& name, const AttributeValue& value);
void removeAttributeFromIndex(const AttributeName& name, const AttributeValue& value);
void updateAttributeIndex(const AttributeName& oldName, const AttributeValue& oldValue, const AttributeName& newName, const AttributeValue& newValue);
public: // link management
const AttributableNodeList& linkSources() const;
const AttributableNodeList& linkTargets() const;
const AttributableNodeList& killSources() const;
const AttributableNodeList& killTargets() const;
Vec3 linkSourceAnchor() const;
Vec3 linkTargetAnchor() const;
bool hasMissingSources() const;
AttributeNameList findMissingLinkTargets() const;
AttributeNameList findMissingKillTargets() const;
private: // link management internals
void findMissingTargets(const AttributeName& prefix, AttributeNameList& result) const;
void addLinks(const AttributeName& name, const AttributeValue& value);
void removeLinks(const AttributeName& name, const AttributeValue& value);
void updateLinks(const AttributeName& oldName, const AttributeName& oldValue, const AttributeName& newName, const AttributeValue& newValue);
void addLinkTargets(const AttributeValue& targetname);
void addKillTargets(const AttributeValue& targetname);
void removeLinkTargets(const AttributeValue& targetname);
void removeKillTargets(const AttributeValue& targetname);
void addAllLinkSources(const AttributeValue& targetname);
void addAllLinkTargets();
void addAllKillSources(const AttributeValue& targetname);
void addAllKillTargets();
void addLinkTargets(const AttributableNodeList& targets);
void addKillTargets(const AttributableNodeList& targets);
void addLinkSources(const AttributableNodeList& sources);
void addKillSources(const AttributableNodeList& sources);
void removeAllLinkSources();
void removeAllLinkTargets();
void removeAllKillSources();
void removeAllKillTargets();
void removeAllLinks();
void addAllLinks();
void addLinkSource(AttributableNode* attributable);
void addLinkTarget(AttributableNode* attributable);
void addKillSource(AttributableNode* attributable);
void addKillTarget(AttributableNode* attributable);
void removeLinkSource(AttributableNode* attributable);
void removeLinkTarget(AttributableNode* attributable);
void removeKillSource(AttributableNode* attributable);
void removeKillTarget(AttributableNode* attributable);
protected:
AttributableNode();
private: // implemenation of node interface
const String& doGetName() const;
virtual void doAncestorWillChange();
virtual void doAncestorDidChange();
private: // subclassing interface
virtual void doAttributesDidChange() = 0;
virtual bool doIsAttributeNameMutable(const AttributeName& name) const = 0;
virtual bool doIsAttributeValueMutable(const AttributeName& name) const = 0;
virtual Vec3 doGetLinkSourceAnchor() const = 0;
virtual Vec3 doGetLinkTargetAnchor() const = 0;
private: // hide copy constructor and assignment operator
AttributableNode(const AttributableNode&);
AttributableNode& operator=(const AttributableNode&);
};
}
}
#endif /* defined(TrenchBroom_AttributableNode) */