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 #include "AttributableNode.h" 21 22 #include "Assets/AttributeDefinition.h" 23 24 namespace TrenchBroom { 25 namespace Model { selectEntityDefinition(const AttributableNodeList & attributables)26 Assets::EntityDefinition* AttributableNode::selectEntityDefinition(const AttributableNodeList& attributables) { 27 Assets::EntityDefinition* definition = NULL; 28 29 AttributableNodeList::const_iterator it, end; 30 for (it = attributables.begin(), end = attributables.end(); it != end; ++it) { 31 AttributableNode* attributable = *it; 32 if (definition == NULL) { 33 definition = attributable->definition(); 34 } else if (definition != attributable->definition()) { 35 definition = NULL; 36 break; 37 } 38 } 39 40 return definition; 41 } 42 selectAttributeDefinition(const AttributeName & name,const AttributableNodeList & attributables)43 const Assets::AttributeDefinition* AttributableNode::selectAttributeDefinition(const AttributeName& name, const AttributableNodeList& attributables) { 44 AttributableNodeList::const_iterator it = attributables.begin(); 45 AttributableNodeList::const_iterator end = attributables.end(); 46 if (it == end) 47 return NULL; 48 49 const AttributableNode* attributable = *it; 50 const Assets::AttributeDefinition* definition = attributable->attributeDefinition(name); 51 if (definition == NULL) 52 return NULL; 53 54 while (++it != end) { 55 attributable = *it; 56 const Assets::AttributeDefinition* currentDefinition = attributable->attributeDefinition(name); 57 if (currentDefinition == NULL) 58 return NULL; 59 60 if (!definition->equals(currentDefinition)) 61 return NULL; 62 } 63 64 return definition; 65 } 66 selectAttributeValue(const AttributeName & name,const AttributableNodeList & attributables)67 AttributeValue AttributableNode::selectAttributeValue(const AttributeName& name, const AttributableNodeList& attributables) { 68 AttributableNodeList::const_iterator it = attributables.begin(); 69 AttributableNodeList::const_iterator end = attributables.end(); 70 if (it == end) 71 return ""; 72 73 const AttributableNode* attributable = *it; 74 if (!attributable->hasAttribute(name)) 75 return ""; 76 77 const AttributeValue& value = attributable->attribute(name); 78 while (++it != end) { 79 attributable = *it; 80 if (!attributable->hasAttribute(name)) 81 return ""; 82 if (value != attributable->attribute(name)) 83 return ""; 84 } 85 return value; 86 } 87 88 const String AttributableNode::DefaultAttributeValue(""); 89 ~AttributableNode()90 AttributableNode::~AttributableNode() { 91 m_definition = NULL; 92 } 93 definition() const94 Assets::EntityDefinition* AttributableNode::definition() const { 95 return m_definition; 96 } 97 setDefinition(Assets::EntityDefinition * definition)98 void AttributableNode::setDefinition(Assets::EntityDefinition* definition) { 99 if (m_definition == definition) 100 return; 101 102 const NotifyAttributeChange notifyChange(this); 103 if (m_definition != NULL) 104 m_definition->decUsageCount(); 105 m_definition = definition; 106 m_attributes.updateDefinitions(m_definition); 107 if (m_definition != NULL) 108 m_definition->incUsageCount(); 109 } 110 attributeDefinition(const AttributeName & name) const111 const Assets::AttributeDefinition* AttributableNode::attributeDefinition(const AttributeName& name) const { 112 return m_definition == NULL ? NULL : m_definition->attributeDefinition(name); 113 } 114 attributes() const115 const EntityAttribute::List& AttributableNode::attributes() const { 116 return m_attributes.attributes(); 117 } 118 setAttributes(const EntityAttribute::List & attributes)119 void AttributableNode::setAttributes(const EntityAttribute::List& attributes) { 120 const NotifyAttributeChange notifyChange(this); 121 updateAttributeIndex(attributes); 122 m_attributes.setAttributes(attributes); 123 m_attributes.updateDefinitions(m_definition); 124 } 125 hasAttribute(const AttributeName & name) const126 bool AttributableNode::hasAttribute(const AttributeName& name) const { 127 return m_attributes.hasAttribute(name); 128 } 129 hasAttribute(const AttributeName & name,const AttributeValue & value) const130 bool AttributableNode::hasAttribute(const AttributeName& name, const AttributeValue& value) const { 131 return m_attributes.hasAttribute(name, value); 132 } 133 hasAttributeWithPrefix(const AttributeName & prefix,const AttributeValue & value) const134 bool AttributableNode::hasAttributeWithPrefix(const AttributeName& prefix, const AttributeValue& value) const { 135 return m_attributes.hasAttributeWithPrefix(prefix, value); 136 } 137 hasNumberedAttribute(const AttributeName & prefix,const AttributeValue & value) const138 bool AttributableNode::hasNumberedAttribute(const AttributeName& prefix, const AttributeValue& value) const { 139 return m_attributes.hasNumberedAttribute(prefix, value); 140 } 141 attribute(const AttributeName & name,const AttributeValue & defaultValue) const142 const AttributeValue& AttributableNode::attribute(const AttributeName& name, const AttributeValue& defaultValue) const { 143 const AttributeValue* value = m_attributes.attribute(name); 144 if (value == NULL) 145 return defaultValue; 146 return *value; 147 } 148 classname(const AttributeValue & defaultClassname) const149 const AttributeValue& AttributableNode::classname(const AttributeValue& defaultClassname) const { 150 return m_classname.empty() ? defaultClassname : m_classname; 151 } 152 attributeSnapshot(const AttributeName & name) const153 EntityAttributeSnapshot AttributableNode::attributeSnapshot(const AttributeName& name) const { 154 return m_attributes.snapshot(name); 155 } 156 canAddOrUpdateAttribute(const AttributeName & name,const AttributeValue & value) const157 bool AttributableNode::canAddOrUpdateAttribute(const AttributeName& name, const AttributeValue& value) const { 158 return isAttributeValueMutable(name); 159 } 160 addOrUpdateAttribute(const AttributeName & name,const AttributeValue & value)161 void AttributableNode::addOrUpdateAttribute(const AttributeName& name, const AttributeValue& value) { 162 const NotifyAttributeChange notifyChange(this); 163 164 const Assets::AttributeDefinition* definition = Assets::EntityDefinition::safeGetAttributeDefinition(m_definition, name); 165 const AttributeValue* oldValue = m_attributes.attribute(name); 166 if (oldValue != NULL) { 167 removeAttributeFromIndex(name, *oldValue); 168 removeLinks(name, *oldValue); 169 } 170 171 m_attributes.addOrUpdateAttribute(name, value, definition); 172 addAttributeToIndex(name, value); 173 addLinks(name, value); 174 } 175 canRenameAttribute(const AttributeName & name,const AttributeName & newName) const176 bool AttributableNode::canRenameAttribute(const AttributeName& name, const AttributeName& newName) const { 177 return isAttributeNameMutable(name) && isAttributeNameMutable(newName); 178 } 179 renameAttribute(const AttributeName & name,const AttributeName & newName)180 void AttributableNode::renameAttribute(const AttributeName& name, const AttributeName& newName) { 181 if (name == newName) 182 return; 183 184 const AttributeValue* valuePtr = m_attributes.attribute(name); 185 if (valuePtr == NULL) 186 return; 187 188 const NotifyAttributeChange notifyChange(this); 189 190 const Assets::AttributeDefinition* newDefinition = Assets::EntityDefinition::safeGetAttributeDefinition(m_definition, newName); 191 m_attributes.renameAttribute(name, newName, newDefinition); 192 193 const AttributeValue value = *valuePtr; 194 updateAttributeIndex(name, value, newName, value); 195 updateLinks(name, value, newName, value); 196 } 197 canRemoveAttribute(const AttributeName & name) const198 bool AttributableNode::canRemoveAttribute(const AttributeName& name) const { 199 return isAttributeNameMutable(name) && isAttributeValueMutable(name); 200 } 201 removeAttribute(const AttributeName & name)202 void AttributableNode::removeAttribute(const AttributeName& name) { 203 const AttributeValue* valuePtr = m_attributes.attribute(name); 204 if (valuePtr == NULL) 205 return; 206 207 const NotifyAttributeChange notifyChange(this); 208 209 const AttributeValue value = *valuePtr; 210 m_attributes.removeAttribute(name); 211 212 removeAttributeFromIndex(name, value); 213 removeLinks(name, value); 214 } 215 isAttributeNameMutable(const AttributeName & name) const216 bool AttributableNode::isAttributeNameMutable(const AttributeName& name) const { 217 return doIsAttributeNameMutable(name); 218 } 219 isAttributeValueMutable(const AttributeName & name) const220 bool AttributableNode::isAttributeValueMutable(const AttributeName& name) const { 221 return doIsAttributeValueMutable(name); 222 } 223 NotifyAttributeChange(AttributableNode * node)224 AttributableNode::NotifyAttributeChange::NotifyAttributeChange(AttributableNode* node) : 225 m_nodeChange(node), 226 m_node(node) { 227 assert(m_node != NULL); 228 m_node->attributesWillChange(); 229 } 230 ~NotifyAttributeChange()231 AttributableNode::NotifyAttributeChange::~NotifyAttributeChange() { 232 m_node->attributesDidChange(); 233 } 234 attributesWillChange()235 void AttributableNode::attributesWillChange() {} 236 attributesDidChange()237 void AttributableNode::attributesDidChange() { 238 updateClassname(); 239 doAttributesDidChange(); 240 } 241 updateClassname()242 void AttributableNode::updateClassname() { 243 m_classname = attribute(AttributeNames::Classname); 244 } 245 addAttributesToIndex()246 void AttributableNode::addAttributesToIndex() { 247 const EntityAttribute::List& attributes = m_attributes.attributes(); 248 EntityAttribute::List::const_iterator it, end; 249 for (it = attributes.begin(), end = attributes.end(); it != end; ++it) { 250 const EntityAttribute& attribute = *it; 251 addAttributeToIndex(attribute.name(), attribute.value()); 252 } 253 } 254 removeAttributesFromIndex()255 void AttributableNode::removeAttributesFromIndex() { 256 const EntityAttribute::List& attributes = m_attributes.attributes(); 257 EntityAttribute::List::const_iterator it, end; 258 for (it = attributes.begin(), end = attributes.end(); it != end; ++it) { 259 const EntityAttribute& attribute = *it; 260 removeAttributeFromIndex(attribute.name(), attribute.value()); 261 } 262 } 263 updateAttributeIndex(const EntityAttribute::List & newAttributes)264 void AttributableNode::updateAttributeIndex(const EntityAttribute::List& newAttributes) { 265 EntityAttribute::List oldSorted = m_attributes.attributes(); 266 EntityAttribute::List newSorted = newAttributes; 267 268 oldSorted.sort(); 269 newSorted.sort(); 270 271 EntityAttribute::List::const_iterator oldIt = oldSorted.begin(); 272 EntityAttribute::List::const_iterator oldEnd = oldSorted.end(); 273 EntityAttribute::List::const_iterator newIt = newSorted.begin(); 274 EntityAttribute::List::const_iterator newEnd = newSorted.end(); 275 276 while (oldIt != oldEnd && newIt != newEnd) { 277 const EntityAttribute& oldAttr = *oldIt; 278 const EntityAttribute& newAttr = *newIt; 279 280 const int cmp = oldAttr.compare(newAttr); 281 if (cmp < 0) { 282 removeAttributeFromIndex(oldAttr.name(), oldAttr.value()); 283 ++oldIt; 284 } else if (cmp > 0) { 285 addAttributeToIndex(newAttr.name(), newAttr.value()); 286 ++newIt; 287 } else { 288 updateAttributeIndex(oldAttr.name(), oldAttr.value(), newAttr.name(), newAttr.value()); 289 ++oldIt; ++newIt; 290 } 291 } 292 293 while (oldIt != oldEnd) { 294 const EntityAttribute& oldAttr = *oldIt; 295 removeAttributeFromIndex(oldAttr.name(), oldAttr.value()); 296 ++oldIt; 297 } 298 299 while (newIt != newEnd) { 300 const EntityAttribute& newAttr = *newIt; 301 addAttributeToIndex(newAttr.name(), newAttr.value()); 302 ++newIt; 303 } 304 } 305 addAttributeToIndex(const AttributeName & name,const AttributeValue & value)306 void AttributableNode::addAttributeToIndex(const AttributeName& name, const AttributeValue& value) { 307 addToIndex(this, name, value); 308 } 309 removeAttributeFromIndex(const AttributeName & name,const AttributeValue & value)310 void AttributableNode::removeAttributeFromIndex(const AttributeName& name, const AttributeValue& value) { 311 removeFromIndex(this, name, value); 312 } 313 updateAttributeIndex(const AttributeName & oldName,const AttributeValue & oldValue,const AttributeName & newName,const AttributeValue & newValue)314 void AttributableNode::updateAttributeIndex(const AttributeName& oldName, const AttributeValue& oldValue, const AttributeName& newName, const AttributeValue& newValue) { 315 removeFromIndex(this, oldName, oldValue); 316 addToIndex(this, newName, newValue); 317 } 318 linkSources() const319 const AttributableNodeList& AttributableNode::linkSources() const { 320 return m_linkSources; 321 } 322 linkTargets() const323 const AttributableNodeList& AttributableNode::linkTargets() const { 324 return m_linkTargets; 325 } 326 killSources() const327 const AttributableNodeList& AttributableNode::killSources() const { 328 return m_killSources; 329 } 330 killTargets() const331 const AttributableNodeList& AttributableNode::killTargets() const { 332 return m_killTargets; 333 } 334 linkSourceAnchor() const335 Vec3 AttributableNode::linkSourceAnchor() const { 336 return doGetLinkSourceAnchor(); 337 } 338 linkTargetAnchor() const339 Vec3 AttributableNode::linkTargetAnchor() const { 340 return doGetLinkTargetAnchor(); 341 } 342 hasMissingSources() const343 bool AttributableNode::hasMissingSources() const { 344 return (m_linkSources.empty() && 345 m_killSources.empty() && 346 hasAttribute(AttributeNames::Targetname)); 347 } 348 findMissingLinkTargets() const349 AttributeNameList AttributableNode::findMissingLinkTargets() const { 350 AttributeNameList result; 351 findMissingTargets(AttributeNames::Target, result); 352 return result; 353 } 354 findMissingKillTargets() const355 AttributeNameList AttributableNode::findMissingKillTargets() const { 356 AttributeNameList result; 357 findMissingTargets(AttributeNames::Killtarget, result); 358 return result; 359 } 360 findMissingTargets(const AttributeName & prefix,AttributeNameList & result) const361 void AttributableNode::findMissingTargets(const AttributeName& prefix, AttributeNameList& result) const { 362 const EntityAttribute::List attributes = m_attributes.numberedAttributes(prefix); 363 EntityAttribute::List::const_iterator aIt, aEnd; 364 for (aIt = attributes.begin(), aEnd = attributes.end(); aIt != aEnd; ++aIt) { 365 const EntityAttribute& attribute = *aIt; 366 const AttributeValue& targetname = attribute.value(); 367 if (targetname.empty()) { 368 result.push_back(attribute.name()); 369 } else { 370 AttributableNodeList linkTargets; 371 findAttributableNodesWithAttribute(AttributeNames::Targetname, targetname, linkTargets); 372 if (linkTargets.empty()) 373 result.push_back(attribute.name()); 374 } 375 } 376 } 377 addLinks(const AttributeName & name,const AttributeValue & value)378 void AttributableNode::addLinks(const AttributeName& name, const AttributeValue& value) { 379 if (isNumberedAttribute(AttributeNames::Target, name)) { 380 addLinkTargets(value); 381 } else if (isNumberedAttribute(AttributeNames::Killtarget, name)) { 382 addKillTargets(value); 383 } else if (name == AttributeNames::Targetname) { 384 addAllLinkSources(value); 385 addAllKillSources(value); 386 } 387 } 388 removeLinks(const AttributeName & name,const AttributeValue & value)389 void AttributableNode::removeLinks(const AttributeName& name, const AttributeValue& value) { 390 if (isNumberedAttribute(AttributeNames::Target, name)) { 391 removeLinkTargets(value); 392 } else if (isNumberedAttribute(AttributeNames::Killtarget, name)) { 393 removeKillTargets(value); 394 } else if (name == AttributeNames::Targetname) { 395 removeAllLinkSources(); 396 removeAllKillSources(); 397 } 398 } 399 updateLinks(const AttributeName & oldName,const AttributeName & oldValue,const AttributeName & newName,const AttributeValue & newValue)400 void AttributableNode::updateLinks(const AttributeName& oldName, const AttributeName& oldValue, const AttributeName& newName, const AttributeValue& newValue) { 401 removeLinks(oldName, oldValue); 402 addLinks(newName, newValue); 403 } 404 addLinkTargets(const AttributeValue & targetname)405 void AttributableNode::addLinkTargets(const AttributeValue& targetname) { 406 if (!targetname.empty()) { 407 AttributableNodeList targets; 408 findAttributableNodesWithAttribute(AttributeNames::Targetname, targetname, targets); 409 addLinkTargets(targets); 410 } 411 } 412 addKillTargets(const AttributeValue & targetname)413 void AttributableNode::addKillTargets(const AttributeValue& targetname) { 414 if (!targetname.empty()) { 415 AttributableNodeList targets; 416 findAttributableNodesWithAttribute(AttributeNames::Targetname, targetname, targets); 417 addKillTargets(targets); 418 } 419 } 420 removeLinkTargets(const AttributeValue & targetname)421 void AttributableNode::removeLinkTargets(const AttributeValue& targetname) { 422 if (!targetname.empty()) { 423 AttributableNodeList::iterator rem = m_linkTargets.end(); 424 AttributableNodeList::iterator it = m_linkTargets.begin(); 425 while (it != rem) { 426 AttributableNode* target = *it; 427 const AttributeValue& targetTargetname = target->attribute(AttributeNames::Targetname); 428 if (targetTargetname == targetname) { 429 target->removeLinkSource(this); 430 --rem; 431 std::iter_swap(it, rem); 432 } else { 433 ++it; 434 } 435 } 436 m_linkTargets.erase(rem, m_linkTargets.end()); 437 } 438 } 439 removeKillTargets(const AttributeValue & targetname)440 void AttributableNode::removeKillTargets(const AttributeValue& targetname) { 441 if (!targetname.empty()) { 442 AttributableNodeList::iterator rem = m_killTargets.end(); 443 AttributableNodeList::iterator it = m_killTargets.begin(); 444 while (it != rem) { 445 AttributableNode* target = *it; 446 const AttributeValue& targetTargetname = target->attribute(AttributeNames::Targetname); 447 if (targetTargetname == targetname) { 448 target->removeKillSource(this); 449 --rem; 450 std::iter_swap(it, rem); 451 } else { 452 ++it; 453 } 454 } 455 m_killTargets.erase(rem, m_killTargets.end()); 456 } 457 } 458 addAllLinkSources(const AttributeValue & targetname)459 void AttributableNode::addAllLinkSources(const AttributeValue& targetname) { 460 if (!targetname.empty()) { 461 AttributableNodeList linkSources; 462 findAttributableNodesWithNumberedAttribute(AttributeNames::Target, targetname, linkSources); 463 addLinkSources(linkSources); 464 } 465 } 466 addAllLinkTargets()467 void AttributableNode::addAllLinkTargets() { 468 const EntityAttribute::List attributes = m_attributes.numberedAttributes(AttributeNames::Target); 469 EntityAttribute::List::const_iterator aIt, aEnd; 470 for (aIt = attributes.begin(), aEnd = attributes.end(); aIt != aEnd; ++aIt) { 471 const EntityAttribute& attribute = *aIt; 472 const String& targetname = attribute.value(); 473 if (!targetname.empty()) { 474 AttributableNodeList linkTargets; 475 findAttributableNodesWithAttribute(AttributeNames::Targetname, targetname, linkTargets); 476 addLinkTargets(linkTargets); 477 } 478 } 479 } 480 addAllKillSources(const AttributeValue & targetname)481 void AttributableNode::addAllKillSources(const AttributeValue& targetname) { 482 if (!targetname.empty()) { 483 AttributableNodeList killSources; 484 findAttributableNodesWithNumberedAttribute(AttributeNames::Killtarget, targetname, killSources); 485 addKillSources(killSources); 486 } 487 } 488 addAllKillTargets()489 void AttributableNode::addAllKillTargets() { 490 const EntityAttribute::List attributes = m_attributes.numberedAttributes(AttributeNames::Killtarget); 491 EntityAttribute::List::const_iterator aIt, aEnd; 492 for (aIt = attributes.begin(), aEnd = attributes.end(); aIt != aEnd; ++aIt) { 493 const EntityAttribute& attribute = *aIt; 494 const String& targetname = attribute.value(); 495 if (!targetname.empty()) { 496 AttributableNodeList killTargets; 497 findAttributableNodesWithAttribute(AttributeNames::Targetname, targetname, killTargets); 498 addKillTargets(killTargets); 499 } 500 } 501 } 502 addLinkTargets(const AttributableNodeList & targets)503 void AttributableNode::addLinkTargets(const AttributableNodeList& targets) { 504 m_linkTargets.reserve(m_linkTargets.size() + targets.size()); 505 506 AttributableNodeList::const_iterator it, end; 507 for (it = targets.begin(), end = targets.end(); it != end; ++it) { 508 AttributableNode* target = *it; 509 target->addLinkSource(this); 510 m_linkTargets.push_back(target); 511 } 512 invalidateIssues(); 513 } 514 addKillTargets(const AttributableNodeList & targets)515 void AttributableNode::addKillTargets(const AttributableNodeList& targets) { 516 m_killTargets.reserve(m_killTargets.size() + targets.size()); 517 518 AttributableNodeList::const_iterator it, end; 519 for (it = targets.begin(), end = targets.end(); it != end; ++it) { 520 AttributableNode* target = *it; 521 target->addKillSource(this); 522 m_killTargets.push_back(target); 523 } 524 invalidateIssues(); 525 } 526 addLinkSources(const AttributableNodeList & sources)527 void AttributableNode::addLinkSources(const AttributableNodeList& sources) { 528 m_linkSources.reserve(m_linkSources.size() + sources.size()); 529 530 AttributableNodeList::const_iterator it, end; 531 for (it = sources.begin(), end = sources.end(); it != end; ++it) { 532 AttributableNode* linkSource = *it; 533 linkSource->addLinkTarget(this); 534 m_linkSources.push_back(linkSource); 535 } 536 invalidateIssues(); 537 } 538 addKillSources(const AttributableNodeList & sources)539 void AttributableNode::addKillSources(const AttributableNodeList& sources) { 540 m_killSources.reserve(m_killSources.size() + sources.size()); 541 542 AttributableNodeList::const_iterator it, end; 543 for (it = sources.begin(), end = sources.end(); it != end; ++it) { 544 AttributableNode* killSource = *it; 545 killSource->addKillTarget(this); 546 m_killSources.push_back(killSource); 547 } 548 invalidateIssues(); 549 } 550 removeAllLinkSources()551 void AttributableNode::removeAllLinkSources() { 552 AttributableNodeList::const_iterator it, end; 553 for (it = m_linkSources.begin(), end = m_linkSources.end(); it != end; ++it) { 554 AttributableNode* linkSource = *it; 555 linkSource->removeLinkTarget(this); 556 } 557 m_linkSources.clear(); 558 invalidateIssues(); 559 } 560 removeAllLinkTargets()561 void AttributableNode::removeAllLinkTargets() { 562 AttributableNodeList::const_iterator it, end; 563 for (it = m_linkTargets.begin(), end = m_linkTargets.end(); it != end; ++it) { 564 AttributableNode* linkTarget = *it; 565 linkTarget->removeLinkSource(this); 566 } 567 m_linkTargets.clear(); 568 invalidateIssues(); 569 } 570 removeAllKillSources()571 void AttributableNode::removeAllKillSources() { 572 AttributableNodeList::const_iterator it, end; 573 for (it = m_killSources.begin(), end = m_killSources.end(); it != end; ++it) { 574 AttributableNode* killSource = *it; 575 killSource->removeKillTarget(this); 576 } 577 m_killSources.clear(); 578 invalidateIssues(); 579 } 580 removeAllKillTargets()581 void AttributableNode::removeAllKillTargets() { 582 AttributableNodeList::const_iterator it, end; 583 for (it = m_killTargets.begin(), end = m_killTargets.end(); it != end; ++it) { 584 AttributableNode* killTarget = *it; 585 killTarget->removeKillSource(this); 586 } 587 m_killTargets.clear(); 588 invalidateIssues(); 589 } 590 removeAllLinks()591 void AttributableNode::removeAllLinks() { 592 removeAllLinkSources(); 593 removeAllLinkTargets(); 594 removeAllKillSources(); 595 removeAllKillTargets(); 596 } 597 addAllLinks()598 void AttributableNode::addAllLinks() { 599 addAllLinkTargets(); 600 addAllKillTargets(); 601 602 const AttributeValue* targetname = m_attributes.attribute(AttributeNames::Targetname); 603 if (targetname != NULL && !targetname->empty()) { 604 addAllLinkSources(*targetname); 605 addAllKillSources(*targetname); 606 } 607 } 608 doAncestorWillChange()609 void AttributableNode::doAncestorWillChange() { 610 removeAllLinks(); 611 removeAttributesFromIndex(); 612 } 613 doAncestorDidChange()614 void AttributableNode::doAncestorDidChange() { 615 addAttributesToIndex(); 616 addAllLinks(); 617 } 618 addLinkSource(AttributableNode * attributable)619 void AttributableNode::addLinkSource(AttributableNode* attributable) { 620 assert(attributable != NULL); 621 m_linkSources.push_back(attributable); 622 invalidateIssues(); 623 } 624 addLinkTarget(AttributableNode * attributable)625 void AttributableNode::addLinkTarget(AttributableNode* attributable) { 626 assert(attributable != NULL); 627 m_linkTargets.push_back(attributable); 628 invalidateIssues(); 629 } 630 addKillSource(AttributableNode * attributable)631 void AttributableNode::addKillSource(AttributableNode* attributable) { 632 assert(attributable != NULL); 633 m_killSources.push_back(attributable); 634 invalidateIssues(); 635 } 636 addKillTarget(AttributableNode * attributable)637 void AttributableNode::addKillTarget(AttributableNode* attributable) { 638 assert(attributable != NULL); 639 m_killTargets.push_back(attributable); 640 invalidateIssues(); 641 } 642 removeLinkSource(AttributableNode * attributable)643 void AttributableNode::removeLinkSource(AttributableNode* attributable) { 644 assert(attributable != NULL); 645 VectorUtils::erase(m_linkSources, attributable); 646 invalidateIssues(); 647 } 648 removeLinkTarget(AttributableNode * attributable)649 void AttributableNode::removeLinkTarget(AttributableNode* attributable) { 650 assert(attributable != NULL); 651 VectorUtils::erase(m_linkTargets, attributable); 652 invalidateIssues(); 653 } 654 removeKillSource(AttributableNode * attributable)655 void AttributableNode::removeKillSource(AttributableNode* attributable) { 656 assert(attributable != NULL); 657 VectorUtils::erase(m_killSources, attributable); 658 invalidateIssues(); 659 } 660 AttributableNode()661 AttributableNode::AttributableNode() : 662 Node(), 663 m_definition(NULL) {} 664 doGetName() const665 const String& AttributableNode::doGetName() const { 666 static const String defaultName("<missing classname>"); 667 return classname(defaultName); 668 } 669 removeKillTarget(AttributableNode * attributable)670 void AttributableNode::removeKillTarget(AttributableNode* attributable) { 671 assert(attributable != NULL); 672 VectorUtils::erase(m_killTargets, attributable); 673 } 674 } 675 } 676