1 // Created on: 1999-06-10
2 // Created by: Vladislav ROMASHKO
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <TDataStd_TreeNode.ixx>
18 #include <TDF_Label.hxx>
19 #include <Standard_DomainError.hxx>
21 // This bug concerns the method IsDescendant():
24 // This bug concerns the method BeforeForget() - Forget/Resume, Undo/Redo behaviour of the attribute
27 //=======================================================================
30 //=======================================================================
32 Standard_Boolean TDataStd_TreeNode::Find(const TDF_Label& L,
33 Handle(TDataStd_TreeNode)& T)
35 return L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), T);
38 //=======================================================================
39 //TreeNode : GetDefaultTreeID
40 //purpose : Static method to get the default ID of a TreeNode
41 //=======================================================================
43 const Standard_GUID& TDataStd_TreeNode::GetDefaultTreeID()
45 static Standard_GUID TDataStd_TreeNodeID ("2a96b621-ec8b-11d0-bee7-080009dc3333");
46 return TDataStd_TreeNodeID;
49 //=======================================================================
51 //purpose : Finds or creates a TreeNode attribute with default ID
52 //=======================================================================
54 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set(const TDF_Label& L)
56 Handle(TDataStd_TreeNode) TN;
57 if (!L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(),TN)) {
58 TN = new TDataStd_TreeNode();
59 TN->SetTreeID(TDataStd_TreeNode::GetDefaultTreeID());
65 //=======================================================================
67 //purpose : Finds or creates a TreeNode attribute with explicit ID
69 //=======================================================================
71 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set (const TDF_Label& L,
72 const Standard_GUID& explicitID)
74 Handle(TDataStd_TreeNode) TN;
75 if (!L.FindAttribute(explicitID,TN)) {
76 TN = new TDataStd_TreeNode ();
77 TN->SetTreeID(explicitID);
83 //=======================================================================
85 //purpose : Returns GUID of the TreeNode
86 //=======================================================================
88 const Standard_GUID& TDataStd_TreeNode::ID() const
93 //=======================================================================
94 //TreeNode : TDataStd_TreeNode
95 //purpose : Constructor
96 //=======================================================================
98 TDataStd_TreeNode::TDataStd_TreeNode () :
99 myFather(NULL), myPrevious(NULL), myNext(NULL), myFirst(NULL), myLast(NULL)
103 //=======================================================================
105 //purpose : Add <TN> as last child of me
106 //=======================================================================
108 Standard_Boolean TDataStd_TreeNode::Append (const Handle(TDataStd_TreeNode)& TN)
110 if (!(TN->ID() == myTreeID) )
111 Standard_DomainError::Raise("TDataStd_TreeNode::Append : uncompatible GUID");
113 Handle(TDataStd_TreeNode) bid;
114 TN->SetNext(bid); // Deconnects from next.
119 TN->SetPrevious(bid); // Deconnects from previous.
123 Handle(TDataStd_TreeNode) L = Last();
129 myLast=TN.operator->();
133 //=======================================================================
135 //purpose : Add <TN> as first child of me
136 //=======================================================================
138 Standard_Boolean TDataStd_TreeNode::Prepend (const Handle(TDataStd_TreeNode)& TN)
140 if (!(TN->ID() == myTreeID) )
141 Standard_DomainError::Raise("TDataStd_TreeNode::Prepend : uncompatible GUID");
143 Handle(TDataStd_TreeNode) bid;
144 TN->SetPrevious(bid);
146 TN->SetNext(First());
147 First()->SetPrevious(TN);
158 //=======================================================================
159 //function : InsertBefore
160 //purpose : Inserts the TreeNode <TN> before me
161 //=======================================================================
163 Standard_Boolean TDataStd_TreeNode::InsertBefore (const Handle(TDataStd_TreeNode)& TN)
165 if (!(TN->ID() == myTreeID) )
166 Standard_DomainError::Raise("TDataStd_TreeNode::InsertBefore : uncompatible GUID");
168 TN->SetFather(Father());
169 TN->SetPrevious(Previous());
173 Father()->SetFirst(TN);
175 Previous()->SetNext(TN);
181 //=======================================================================
182 //function : InsertAfter
183 //purpose : Inserts the TreeNode <TN> after me
184 //=======================================================================
186 Standard_Boolean TDataStd_TreeNode::InsertAfter (const Handle(TDataStd_TreeNode)& TN)
188 if (!(TN->ID() == myTreeID) )
189 Standard_DomainError::Raise("TDataStd_TreeNode::InsertAfter : uncompatible GUID");
191 if (HasFather() && !HasNext())
192 Father()->SetLast(TN);
194 TN->SetFather(Father());
195 TN->SetPrevious(this);
199 Next()->SetPrevious(TN);
205 //=======================================================================
207 //purpose : Removees the function from the function tree
208 //=======================================================================
210 Standard_Boolean TDataStd_TreeNode::Remove ()
212 if (IsRoot()) return Standard_True;
214 Handle(TDataStd_TreeNode) bid;
216 Father()->SetFirst(Next());
218 Previous()->SetNext(Next());
221 if (HasPrevious()) Next()->SetPrevious(Previous());
222 else Next()->SetPrevious(bid);
225 if (HasPrevious()) Previous()->SetNext(bid);
228 if (Father()->HasFirst()) {
229 if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->First()) {
231 Father()->SetFirst(Next());
233 else Father()->SetFirst(bid);
237 if(Father()->HasLast()) {
238 if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->Last()) {
240 Father()->SetLast(Previous());
242 else Father()->SetLast(bid);
249 return Standard_True;
253 //=======================================================================
256 //=======================================================================
258 Standard_Integer TDataStd_TreeNode::Depth () const
260 Standard_Integer depth = 0;
262 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
263 while (O->myFather != NULL)
272 //=======================================================================
273 //function : NbChildren
274 //purpose : Returns the number of child nodes.
275 // If <allLevels> is true, the method counts children of all levels
276 // (children of children ...)
277 //=======================================================================
278 Standard_Integer TDataStd_TreeNode::NbChildren(const Standard_Boolean allLevels) const
280 Standard_Integer nb = 0;
281 TDataStd_TreeNode* C = myFirst;
287 nb += C->NbChildren(allLevels);
295 //=======================================================================
296 //function : SetTreeID
297 //purpose : Finds or creates a TreeNode attribute with explicit ID
299 //=======================================================================
301 void TDataStd_TreeNode::SetTreeID (const Standard_GUID& explicitID)
303 myTreeID = explicitID;
307 //=======================================================================
308 //function : IsAscendant
310 //=======================================================================
312 Standard_Boolean TDataStd_TreeNode::IsAscendant (const Handle(TDataStd_TreeNode)& ofTN) const
314 return ofTN->IsDescendant(this);
318 //=======================================================================
319 //function : IsDescendant
321 //=======================================================================
323 Standard_Boolean TDataStd_TreeNode::IsDescendant (const Handle(TDataStd_TreeNode)& ofTN) const
327 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
328 while (O->myFather != NULL)
330 if (O->myFather == ofTN)
331 return Standard_True;
336 Handle(TDataStd_TreeNode) current;
337 for (current = this; current = current->Father(); current->HasFather()) {
338 if (current == ofTN) return Standard_True;
341 return Standard_False;
344 //=======================================================================
345 //function : IsFather
347 //=======================================================================
349 Standard_Boolean TDataStd_TreeNode::IsFather (const Handle(TDataStd_TreeNode)& ofTN) const
351 return (ofTN->Father() == this);
355 //=======================================================================
358 //=======================================================================
360 Standard_Boolean TDataStd_TreeNode::IsChild (const Handle(TDataStd_TreeNode)& ofTN) const
362 return (myFather == ofTN.operator->());
366 //=======================================================================
368 //purpose : Returns the Father of the TreeNode
369 //=======================================================================
371 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Father() const
373 Handle(TDataStd_TreeNode) O = myFather;
377 //=======================================================================
379 //purpose : Returns Standard_True if the TreeNode is not attached to a
380 // TreeNode tree or hasn't an Father.
381 //=======================================================================
383 Standard_Boolean TDataStd_TreeNode::IsRoot() const
385 if (myFather == NULL &&
386 myPrevious == NULL &&
388 return Standard_True;
389 return Standard_False;
392 //=======================================================================
394 //purpose : Returns the TreeNode which has no Father
395 //=======================================================================
397 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Root() const
399 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
400 while (O->myFather != NULL)
407 //=======================================================================
409 //purpose : Returns next (in the TreeNode tree) TreeNode
410 //=======================================================================
412 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Next() const
414 Handle(TDataStd_TreeNode) O = myNext;
418 //=======================================================================
419 //TreeNode : Previous
420 //purpose : Returns previous (in the TreeNode tree) TreeNode
421 //=======================================================================
423 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Previous() const
425 Handle(TDataStd_TreeNode) O = myPrevious;
429 //=======================================================================
431 //purpose : Returns first child
432 //=======================================================================
434 Handle(TDataStd_TreeNode) TDataStd_TreeNode::First () const
436 Handle(TDataStd_TreeNode) O = myFirst;
440 //=======================================================================
442 //purpose : Returns last child
443 // Optimize an Append operation if it is called in a circle
444 //=======================================================================
446 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Last ()
448 if(myLast && !myLast->IsChild(this))
457 //=======================================================================
458 //TreeNode : FindLast
459 //purpose : Returns last child
460 // Optimizes an Append operation if it is called in a circle
461 //=======================================================================
462 Handle(TDataStd_TreeNode) TDataStd_TreeNode::FindLast ()
466 TDataStd_TreeNode* L = myFirst;
467 while (L->myNext != NULL)
474 //=======================================================================
475 //TreeNode : SetFather
476 //purpose : Sets the TreeNode F as Father of me
477 //=======================================================================
479 void TDataStd_TreeNode::SetFather(const Handle(TDataStd_TreeNode)& F)
482 if (F.IsNull()) myFather = NULL;
483 else myFather = F.operator->();
487 //=======================================================================
489 //purpose : Sets the TreeNode F next to me
490 //=======================================================================
492 void TDataStd_TreeNode::SetNext(const Handle(TDataStd_TreeNode)& F)
495 if (F.IsNull()) myNext = NULL;
496 else myNext = F.operator->();
501 //=======================================================================
502 //TreeNode : SetPrevious
503 //purpose : Sets the TreeNode F previous to me
504 //=======================================================================
506 void TDataStd_TreeNode::SetPrevious(const Handle(TDataStd_TreeNode)& F)
509 if (F.IsNull()) myPrevious = NULL;
510 else myPrevious = F.operator->();
514 //=======================================================================
515 //TreeNode : SetFirst
516 //purpose : Sets the TreeNode F as first in the TreeNode tree
517 //=======================================================================
519 void TDataStd_TreeNode::SetFirst(const Handle(TDataStd_TreeNode)& F)
522 if (F.IsNull()) myFirst = NULL;
523 else myFirst = F.operator->();
527 //=======================================================================
529 //purpose : Sets the TreeNode F as last in the TreeNode tree
530 //=======================================================================
532 void TDataStd_TreeNode::SetLast(const Handle(TDataStd_TreeNode)& F)
535 if (F.IsNull()) myLast = NULL;
536 else myLast = F.operator->();
539 //=======================================================================
540 //TreeNode : AfterAddition
541 //purpose : Connects the TreeNode to the tree.
542 // Backuped attribute must stay disconnected
543 //=======================================================================
545 void TDataStd_TreeNode::AfterAddition() {
548 myPrevious->SetNext(this);
550 myFather->SetFirst(this);
552 myNext->SetPrevious(this);
556 //=======================================================================
557 //TreeNode : BeforeForget
558 //purpose : Disconnect the TreeNode from the tree.
559 // Backuped attribute is normaly not concerned by such an operation
560 //=======================================================================
562 void TDataStd_TreeNode::BeforeForget() {
566 while (HasFirst()) First()->Remove();
569 if (!IsBackuped()) Remove();
573 //=======================================================================
574 //TreeNode : AfterResume
575 //purpose : Connects the TreeNode to the tree
576 //=======================================================================
578 void TDataStd_TreeNode::AfterResume() {
582 //=======================================================================
583 //TreeNode : BeforeUndo
584 //purpose : Disconnect the TreeNode from the tree.
585 //=======================================================================
587 Standard_Boolean TDataStd_TreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
588 const Standard_Boolean /*forceIt*/)
590 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
591 return Standard_True;
594 //=======================================================================
595 //TreeNode : AfterUndo
596 //purpose : Connect the TreeNode from the tree.
597 //=======================================================================
599 Standard_Boolean TDataStd_TreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
600 const Standard_Boolean /*forceIt*/)
602 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
603 return Standard_True;
606 //=======================================================================
609 //=======================================================================
611 void TDataStd_TreeNode::Restore(const Handle(TDF_Attribute)& other) {
612 Handle(TDataStd_TreeNode) F = Handle(TDataStd_TreeNode)::DownCast(other);
613 myFather = F->myFather;
614 myPrevious = F->myPrevious;
616 myFirst = F->myFirst;
617 myTreeID = F->myTreeID;
621 //=======================================================================
623 //purpose : Method for Copy mechanism
624 //=======================================================================
626 void TDataStd_TreeNode::Paste(const Handle(TDF_Attribute)& into,
627 const Handle(TDF_RelocationTable)& RT) const
629 Handle(TDataStd_TreeNode) intof = Handle(TDataStd_TreeNode)::DownCast(into);
630 Handle(TDataStd_TreeNode) func;
631 if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
634 intof->SetFather(func);
635 if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
638 intof->SetNext(func);
639 if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
642 intof->SetPrevious(func);
643 if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
647 intof->SetFirst(func);
648 intof->SetTreeID(myTreeID);
651 //=======================================================================
652 //TreeNode : NewEmpty
653 //purpose : Returns new empty TreeNode attribute
654 //=======================================================================
656 Handle(TDF_Attribute) TDataStd_TreeNode::NewEmpty() const
658 Handle(TDataStd_TreeNode) T = new TDataStd_TreeNode();
659 T->SetTreeID(myTreeID);
663 //=======================================================================
664 //TreeNode : References
665 //purpose : Collects the references
666 //=======================================================================
668 void TDataStd_TreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
670 TDataStd_TreeNode* fct = myFirst;
671 while (fct != NULL) {
672 aDataSet->AddAttribute(fct);
677 //=======================================================================
679 //purpose : Dump of the TreeNode
680 //=======================================================================
682 Standard_OStream& TDataStd_TreeNode::Dump (Standard_OStream& anOS) const
684 TDF_Attribute::Dump (anOS);
687 if (!myFather->Label().IsNull()) myFather->Label().EntryDump(anOS);
691 if (!myPrevious->Label().IsNull()) myPrevious->Label().EntryDump(anOS);
695 if (!myNext->Label().IsNull()) myNext->Label().EntryDump(anOS);
699 if (!myFirst->Label().IsNull()) myFirst->Label().EntryDump(anOS);