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 (this == Father()->First().operator->()) {
231 Father()->SetFirst(Next());
233 else Father()->SetFirst(bid);
237 if(Father()->HasLast()) {
238 Father()->SetLast(bid);
244 return Standard_True;
248 //=======================================================================
251 //=======================================================================
253 Standard_Integer TDataStd_TreeNode::Depth () const
255 Standard_Integer depth = 0;
257 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
258 while (O->myFather != NULL)
267 //=======================================================================
268 //function : NbChildren
269 //purpose : Returns the number of child nodes.
270 // If <allLevels> is true, the method counts children of all levels
271 // (children of children ...)
272 //=======================================================================
273 Standard_Integer TDataStd_TreeNode::NbChildren(const Standard_Boolean allLevels) const
275 Standard_Integer nb = 0;
276 TDataStd_TreeNode* C = myFirst;
282 nb += C->NbChildren(allLevels);
290 //=======================================================================
291 //function : SetTreeID
292 //purpose : Finds or creates a TreeNode attribute with explicit ID
294 //=======================================================================
296 void TDataStd_TreeNode::SetTreeID (const Standard_GUID& explicitID)
298 myTreeID = explicitID;
302 //=======================================================================
303 //function : IsAscendant
305 //=======================================================================
307 Standard_Boolean TDataStd_TreeNode::IsAscendant (const Handle(TDataStd_TreeNode)& ofTN) const
309 return ofTN->IsDescendant(this);
313 //=======================================================================
314 //function : IsDescendant
316 //=======================================================================
318 Standard_Boolean TDataStd_TreeNode::IsDescendant (const Handle(TDataStd_TreeNode)& ofTN) const
322 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
323 while (O->myFather != NULL)
325 if (O->myFather == ofTN)
326 return Standard_True;
331 Handle(TDataStd_TreeNode) current;
332 for (current = this; current = current->Father(); current->HasFather()) {
333 if (current == ofTN) return Standard_True;
336 return Standard_False;
339 //=======================================================================
340 //function : IsFather
342 //=======================================================================
344 Standard_Boolean TDataStd_TreeNode::IsFather (const Handle(TDataStd_TreeNode)& ofTN) const
346 return (ofTN->Father() == this);
350 //=======================================================================
353 //=======================================================================
355 Standard_Boolean TDataStd_TreeNode::IsChild (const Handle(TDataStd_TreeNode)& ofTN) const
357 return (myFather == ofTN.operator->());
361 //=======================================================================
363 //purpose : Returns the Father of the TreeNode
364 //=======================================================================
366 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Father() const
368 Handle(TDataStd_TreeNode) O = myFather;
372 //=======================================================================
374 //purpose : Returns Standard_True if the TreeNode is not attached to a
375 // TreeNode tree or hasn't an Father.
376 //=======================================================================
378 Standard_Boolean TDataStd_TreeNode::IsRoot() const
380 if (myFather == NULL &&
381 myPrevious == NULL &&
383 return Standard_True;
384 return Standard_False;
387 //=======================================================================
389 //purpose : Returns the TreeNode which has no Father
390 //=======================================================================
392 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Root() const
394 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
395 while (O->myFather != NULL)
402 //=======================================================================
404 //purpose : Returns next (in the TreeNode tree) TreeNode
405 //=======================================================================
407 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Next() const
409 Handle(TDataStd_TreeNode) O = myNext;
413 //=======================================================================
414 //TreeNode : Previous
415 //purpose : Returns previous (in the TreeNode tree) TreeNode
416 //=======================================================================
418 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Previous() const
420 Handle(TDataStd_TreeNode) O = myPrevious;
424 //=======================================================================
426 //purpose : Returns first child
427 //=======================================================================
429 Handle(TDataStd_TreeNode) TDataStd_TreeNode::First () const
431 Handle(TDataStd_TreeNode) O = myFirst;
435 //=======================================================================
437 //purpose : Returns last child
438 // Optimize an Append operation if it is called in a circle
439 //=======================================================================
441 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Last ()
443 if(myLast && !myLast->IsChild(this))
452 //=======================================================================
453 //TreeNode : FindLast
454 //purpose : Returns last child
455 // Optimizes an Append operation if it is called in a circle
456 //=======================================================================
457 Handle(TDataStd_TreeNode) TDataStd_TreeNode::FindLast ()
461 TDataStd_TreeNode* L = myFirst;
462 while (L->myNext != NULL)
469 //=======================================================================
470 //TreeNode : SetFather
471 //purpose : Sets the TreeNode F as Father of me
472 //=======================================================================
474 void TDataStd_TreeNode::SetFather(const Handle(TDataStd_TreeNode)& F)
477 if (F.IsNull()) myFather = NULL;
478 else myFather = F.operator->();
482 //=======================================================================
484 //purpose : Sets the TreeNode F next to me
485 //=======================================================================
487 void TDataStd_TreeNode::SetNext(const Handle(TDataStd_TreeNode)& F)
490 if (F.IsNull()) myNext = NULL;
491 else myNext = F.operator->();
496 //=======================================================================
497 //TreeNode : SetPrevious
498 //purpose : Sets the TreeNode F previous to me
499 //=======================================================================
501 void TDataStd_TreeNode::SetPrevious(const Handle(TDataStd_TreeNode)& F)
504 if (F.IsNull()) myPrevious = NULL;
505 else myPrevious = F.operator->();
509 //=======================================================================
510 //TreeNode : SetFirst
511 //purpose : Sets the TreeNode F as first in the TreeNode tree
512 //=======================================================================
514 void TDataStd_TreeNode::SetFirst(const Handle(TDataStd_TreeNode)& F)
517 if (F.IsNull()) myFirst = NULL;
518 else myFirst = F.operator->();
522 //=======================================================================
524 //purpose : Sets the TreeNode F as last in the TreeNode tree
525 //=======================================================================
527 void TDataStd_TreeNode::SetLast(const Handle(TDataStd_TreeNode)& F)
530 if (F.IsNull()) myLast = NULL;
531 else myLast = F.operator->();
534 //=======================================================================
535 //TreeNode : AfterAddition
536 //purpose : Connects the TreeNode to the tree.
537 // Backuped attribute must stay disconnected
538 //=======================================================================
540 void TDataStd_TreeNode::AfterAddition() {
543 myPrevious->SetNext(this);
545 myFather->SetFirst(this);
547 myNext->SetPrevious(this);
551 //=======================================================================
552 //TreeNode : BeforeForget
553 //purpose : Disconnect the TreeNode from the tree.
554 // Backuped attribute is normaly not concerned by such an operation
555 //=======================================================================
557 void TDataStd_TreeNode::BeforeForget() {
561 while (HasFirst()) First()->Remove();
564 if (!IsBackuped()) Remove();
568 //=======================================================================
569 //TreeNode : AfterResume
570 //purpose : Connects the TreeNode to the tree
571 //=======================================================================
573 void TDataStd_TreeNode::AfterResume() {
577 //=======================================================================
578 //TreeNode : BeforeUndo
579 //purpose : Disconnect the TreeNode from the tree.
580 //=======================================================================
582 Standard_Boolean TDataStd_TreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
583 const Standard_Boolean /*forceIt*/)
585 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
586 return Standard_True;
589 //=======================================================================
590 //TreeNode : AfterUndo
591 //purpose : Connect the TreeNode from the tree.
592 //=======================================================================
594 Standard_Boolean TDataStd_TreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
595 const Standard_Boolean /*forceIt*/)
597 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
598 return Standard_True;
601 //=======================================================================
604 //=======================================================================
606 void TDataStd_TreeNode::Restore(const Handle(TDF_Attribute)& other) {
607 Handle(TDataStd_TreeNode) F = Handle(TDataStd_TreeNode)::DownCast(other);
608 myFather = F->myFather;
609 myPrevious = F->myPrevious;
611 myFirst = F->myFirst;
612 myTreeID = F->myTreeID;
616 //=======================================================================
618 //purpose : Method for Copy mechanism
619 //=======================================================================
621 void TDataStd_TreeNode::Paste(const Handle(TDF_Attribute)& into,
622 const Handle(TDF_RelocationTable)& RT) const
624 Handle(TDataStd_TreeNode) intof = Handle(TDataStd_TreeNode)::DownCast(into);
625 Handle(TDataStd_TreeNode) func;
626 if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
629 intof->SetFather(func);
630 if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
633 intof->SetNext(func);
634 if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
637 intof->SetPrevious(func);
638 if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
642 intof->SetFirst(func);
643 intof->SetTreeID(myTreeID);
646 //=======================================================================
647 //TreeNode : NewEmpty
648 //purpose : Returns new empty TreeNode attribute
649 //=======================================================================
651 Handle(TDF_Attribute) TDataStd_TreeNode::NewEmpty() const
653 Handle(TDataStd_TreeNode) T = new TDataStd_TreeNode();
654 T->SetTreeID(myTreeID);
658 //=======================================================================
659 //TreeNode : References
660 //purpose : Collects the references
661 //=======================================================================
663 void TDataStd_TreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
665 TDataStd_TreeNode* fct = myFirst;
666 while (fct != NULL) {
667 aDataSet->AddAttribute(fct);
672 //=======================================================================
674 //purpose : Dump of the TreeNode
675 //=======================================================================
677 Standard_OStream& TDataStd_TreeNode::Dump (Standard_OStream& anOS) const
679 TDF_Attribute::Dump (anOS);
682 if (!myFather->Label().IsNull()) myFather->Label().EntryDump(anOS);
686 if (!myPrevious->Label().IsNull()) myPrevious->Label().EntryDump(anOS);
690 if (!myNext->Label().IsNull()) myNext->Label().EntryDump(anOS);
694 if (!myFirst->Label().IsNull()) myFirst->Label().EntryDump(anOS);
698 if (!myLast->Label().IsNull()) myLast->Label().EntryDump(anOS);