1 // File: TFunction_Function.cxx
2 // Created: Thu Jun 10 19:39:27 1999
3 // Author: Vladislav ROMASHKO
4 // <vro@flox.nnov.matra-dtv.fr>
7 #include <TDataStd_TreeNode.ixx>
8 #include <TDF_Label.hxx>
9 #include <Standard_DomainError.hxx>
11 // This bug concerns the method IsDescendant():
14 // This bug concerns the method BeforeForget() - Forget/Resume, Undo/Redo behaviour of the attribute
17 //=======================================================================
20 //=======================================================================
22 Standard_Boolean TDataStd_TreeNode::Find(const TDF_Label& L,
23 Handle(TDataStd_TreeNode)& T)
25 return L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), T);
28 //=======================================================================
29 //TreeNode : GetDefaultTreeID
30 //purpose : Static method to get the default ID of a TreeNode
31 //=======================================================================
33 const Standard_GUID& TDataStd_TreeNode::GetDefaultTreeID()
35 static Standard_GUID TDataStd_TreeNodeID ("2a96b621-ec8b-11d0-bee7-080009dc3333");
36 return TDataStd_TreeNodeID;
39 //=======================================================================
41 //purpose : Finds or creates a TreeNode attribute with default ID
42 //=======================================================================
44 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set(const TDF_Label& L)
46 Handle(TDataStd_TreeNode) TN;
47 if (!L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(),TN)) {
48 TN = new TDataStd_TreeNode();
49 TN->SetTreeID(TDataStd_TreeNode::GetDefaultTreeID());
55 //=======================================================================
57 //purpose : Finds or creates a TreeNode attribute with explicit ID
59 //=======================================================================
61 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set (const TDF_Label& L,
62 const Standard_GUID& explicitID)
64 Handle(TDataStd_TreeNode) TN;
65 if (!L.FindAttribute(explicitID,TN)) {
66 TN = new TDataStd_TreeNode ();
67 TN->SetTreeID(explicitID);
73 //=======================================================================
75 //purpose : Returns GUID of the TreeNode
76 //=======================================================================
78 const Standard_GUID& TDataStd_TreeNode::ID() const
83 //=======================================================================
84 //TreeNode : TDataStd_TreeNode
85 //purpose : Constructor
86 //=======================================================================
88 TDataStd_TreeNode::TDataStd_TreeNode () :
89 myFather(NULL), myPrevious(NULL), myNext(NULL), myFirst(NULL), myLast(NULL)
93 //=======================================================================
95 //purpose : Add <TN> as last child of me
96 //=======================================================================
98 Standard_Boolean TDataStd_TreeNode::Append (const Handle(TDataStd_TreeNode)& TN)
100 if (!(TN->ID() == myTreeID) )
101 Standard_DomainError::Raise("TDataStd_TreeNode::Append : uncompatible GUID");
103 Handle(TDataStd_TreeNode) bid;
104 TN->SetNext(bid); // Deconnects from next.
109 TN->SetPrevious(bid); // Deconnects from previous.
113 Handle(TDataStd_TreeNode) L = Last();
119 myLast=TN.operator->();
123 //=======================================================================
125 //purpose : Add <TN> as first child of me
126 //=======================================================================
128 Standard_Boolean TDataStd_TreeNode::Prepend (const Handle(TDataStd_TreeNode)& TN)
130 if (!(TN->ID() == myTreeID) )
131 Standard_DomainError::Raise("TDataStd_TreeNode::Prepend : uncompatible GUID");
133 Handle(TDataStd_TreeNode) bid;
134 TN->SetPrevious(bid);
136 TN->SetNext(First());
137 First()->SetPrevious(TN);
148 //=======================================================================
149 //function : InsertBefore
150 //purpose : Inserts the TreeNode <TN> before me
151 //=======================================================================
153 Standard_Boolean TDataStd_TreeNode::InsertBefore (const Handle(TDataStd_TreeNode)& TN)
155 if (!(TN->ID() == myTreeID) )
156 Standard_DomainError::Raise("TDataStd_TreeNode::InsertBefore : uncompatible GUID");
158 TN->SetFather(Father());
159 TN->SetPrevious(Previous());
163 Father()->SetFirst(TN);
165 Previous()->SetNext(TN);
171 //=======================================================================
172 //function : InsertAfter
173 //purpose : Inserts the TreeNode <TN> after me
174 //=======================================================================
176 Standard_Boolean TDataStd_TreeNode::InsertAfter (const Handle(TDataStd_TreeNode)& TN)
178 if (!(TN->ID() == myTreeID) )
179 Standard_DomainError::Raise("TDataStd_TreeNode::InsertAfter : uncompatible GUID");
181 if (HasFather() && !HasNext())
182 Father()->SetLast(TN);
184 TN->SetFather(Father());
185 TN->SetPrevious(this);
189 Next()->SetPrevious(TN);
195 //=======================================================================
197 //purpose : Removees the function from the function tree
198 //=======================================================================
200 Standard_Boolean TDataStd_TreeNode::Remove ()
202 if (IsRoot()) return Standard_True;
204 Handle(TDataStd_TreeNode) bid;
206 Father()->SetFirst(Next());
208 Previous()->SetNext(Next());
211 if (HasPrevious()) Next()->SetPrevious(Previous());
212 else Next()->SetPrevious(bid);
215 if (HasPrevious()) Previous()->SetNext(bid);
218 if (Father()->HasFirst()) {
219 if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->First()) {
221 Father()->SetFirst(Next());
223 else Father()->SetFirst(bid);
227 if(Father()->HasLast()) {
228 if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->Last()) {
230 Father()->SetLast(Previous());
232 else Father()->SetLast(bid);
239 return Standard_True;
243 //=======================================================================
246 //=======================================================================
248 Standard_Integer TDataStd_TreeNode::Depth () const
250 Standard_Integer depth = 0;
252 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
253 while (O->myFather != NULL)
262 //=======================================================================
263 //function : NbChildren
264 //purpose : Returns the number of child nodes.
265 // If <allLevels> is true, the method counts children of all levels
266 // (children of children ...)
267 //=======================================================================
268 Standard_Integer TDataStd_TreeNode::NbChildren(const Standard_Boolean allLevels) const
270 Standard_Integer nb = 0;
271 TDataStd_TreeNode* C = myFirst;
277 nb += C->NbChildren(allLevels);
285 //=======================================================================
286 //function : SetTreeID
287 //purpose : Finds or creates a TreeNode attribute with explicit ID
289 //=======================================================================
291 void TDataStd_TreeNode::SetTreeID (const Standard_GUID& explicitID)
293 myTreeID = explicitID;
297 //=======================================================================
298 //function : IsAscendant
300 //=======================================================================
302 Standard_Boolean TDataStd_TreeNode::IsAscendant (const Handle(TDataStd_TreeNode)& ofTN) const
304 return ofTN->IsDescendant(this);
308 //=======================================================================
309 //function : IsDescendant
311 //=======================================================================
313 Standard_Boolean TDataStd_TreeNode::IsDescendant (const Handle(TDataStd_TreeNode)& ofTN) const
317 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
318 while (O->myFather != NULL)
320 if (O->myFather == ofTN)
321 return Standard_True;
326 Handle(TDataStd_TreeNode) current;
327 for (current = this; current = current->Father(); current->HasFather()) {
328 if (current == ofTN) return Standard_True;
331 return Standard_False;
334 //=======================================================================
335 //function : IsFather
337 //=======================================================================
339 Standard_Boolean TDataStd_TreeNode::IsFather (const Handle(TDataStd_TreeNode)& ofTN) const
341 return (ofTN->Father() == this);
345 //=======================================================================
348 //=======================================================================
350 Standard_Boolean TDataStd_TreeNode::IsChild (const Handle(TDataStd_TreeNode)& ofTN) const
352 return (myFather == ofTN.operator->());
356 //=======================================================================
358 //purpose : Returns the Father of the TreeNode
359 //=======================================================================
361 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Father() const
363 Handle(TDataStd_TreeNode) O = myFather;
367 //=======================================================================
369 //purpose : Returns Standard_True if the TreeNode is not attached to a
370 // TreeNode tree or hasn't an Father.
371 //=======================================================================
373 Standard_Boolean TDataStd_TreeNode::IsRoot() const
375 if (myFather == NULL &&
376 myPrevious == NULL &&
378 return Standard_True;
379 return Standard_False;
382 //=======================================================================
384 //purpose : Returns the TreeNode which has no Father
385 //=======================================================================
387 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Root() const
389 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
390 while (O->myFather != NULL)
397 //=======================================================================
399 //purpose : Returns next (in the TreeNode tree) TreeNode
400 //=======================================================================
402 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Next() const
404 Handle(TDataStd_TreeNode) O = myNext;
408 //=======================================================================
409 //TreeNode : Previous
410 //purpose : Returns previous (in the TreeNode tree) TreeNode
411 //=======================================================================
413 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Previous() const
415 Handle(TDataStd_TreeNode) O = myPrevious;
419 //=======================================================================
421 //purpose : Returns first child
422 //=======================================================================
424 Handle(TDataStd_TreeNode) TDataStd_TreeNode::First () const
426 Handle(TDataStd_TreeNode) O = myFirst;
430 //=======================================================================
432 //purpose : Returns last child
433 // Optimize an Append operation if it is called in a circle
434 //=======================================================================
436 Handle(TDataStd_TreeNode) TDataStd_TreeNode::Last ()
438 if(myLast && !myLast->IsChild(this))
447 //=======================================================================
448 //TreeNode : FindLast
449 //purpose : Returns last child
450 // Optimizes an Append operation if it is called in a circle
451 //=======================================================================
452 Handle(TDataStd_TreeNode) TDataStd_TreeNode::FindLast ()
456 TDataStd_TreeNode* L = myFirst;
457 while (L->myNext != NULL)
464 //=======================================================================
465 //TreeNode : SetFather
466 //purpose : Sets the TreeNode F as Father of me
467 //=======================================================================
469 void TDataStd_TreeNode::SetFather(const Handle(TDataStd_TreeNode)& F)
472 if (F.IsNull()) myFather = NULL;
473 else myFather = F.operator->();
477 //=======================================================================
479 //purpose : Sets the TreeNode F next to me
480 //=======================================================================
482 void TDataStd_TreeNode::SetNext(const Handle(TDataStd_TreeNode)& F)
485 if (F.IsNull()) myNext = NULL;
486 else myNext = F.operator->();
491 //=======================================================================
492 //TreeNode : SetPrevious
493 //purpose : Sets the TreeNode F previous to me
494 //=======================================================================
496 void TDataStd_TreeNode::SetPrevious(const Handle(TDataStd_TreeNode)& F)
499 if (F.IsNull()) myPrevious = NULL;
500 else myPrevious = F.operator->();
504 //=======================================================================
505 //TreeNode : SetFirst
506 //purpose : Sets the TreeNode F as first in the TreeNode tree
507 //=======================================================================
509 void TDataStd_TreeNode::SetFirst(const Handle(TDataStd_TreeNode)& F)
512 if (F.IsNull()) myFirst = NULL;
513 else myFirst = F.operator->();
517 //=======================================================================
519 //purpose : Sets the TreeNode F as last in the TreeNode tree
520 //=======================================================================
522 void TDataStd_TreeNode::SetLast(const Handle(TDataStd_TreeNode)& F)
525 if (F.IsNull()) myLast = NULL;
526 else myLast = F.operator->();
529 //=======================================================================
530 //TreeNode : AfterAddition
531 //purpose : Connects the TreeNode to the tree.
532 // Backuped attribute must stay disconnected
533 //=======================================================================
535 void TDataStd_TreeNode::AfterAddition() {
538 myPrevious->SetNext(this);
540 myFather->SetFirst(this);
542 myNext->SetPrevious(this);
546 //=======================================================================
547 //TreeNode : BeforeForget
548 //purpose : Disconnect the TreeNode from the tree.
549 // Backuped attribute is normaly not concerned by such an operation
550 //=======================================================================
552 void TDataStd_TreeNode::BeforeForget() {
556 while (HasFirst()) First()->Remove();
559 if (!IsBackuped()) Remove();
563 //=======================================================================
564 //TreeNode : AfterResume
565 //purpose : Connects the TreeNode to the tree
566 //=======================================================================
568 void TDataStd_TreeNode::AfterResume() {
572 //=======================================================================
573 //TreeNode : BeforeUndo
574 //purpose : Disconnect the TreeNode from the tree.
575 //=======================================================================
577 Standard_Boolean TDataStd_TreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
578 const Standard_Boolean forceIt)
580 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
581 return Standard_True;
584 //=======================================================================
585 //TreeNode : AfterUndo
586 //purpose : Connect the TreeNode from the tree.
587 //=======================================================================
589 Standard_Boolean TDataStd_TreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
590 const Standard_Boolean forceIt)
592 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
593 return Standard_True;
596 //=======================================================================
599 //=======================================================================
601 void TDataStd_TreeNode::Restore(const Handle(TDF_Attribute)& other) {
602 Handle(TDataStd_TreeNode) F = Handle(TDataStd_TreeNode)::DownCast(other);
603 myFather = F->myFather;
604 myPrevious = F->myPrevious;
606 myFirst = F->myFirst;
607 myTreeID = F->myTreeID;
611 //=======================================================================
613 //purpose : Method for Copy mechanism
614 //=======================================================================
616 void TDataStd_TreeNode::Paste(const Handle(TDF_Attribute)& into,
617 const Handle(TDF_RelocationTable)& RT) const
619 Handle(TDataStd_TreeNode) intof = Handle(TDataStd_TreeNode)::DownCast(into);
620 Handle(TDataStd_TreeNode) func;
621 if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
624 intof->SetFather(func);
625 if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
628 intof->SetNext(func);
629 if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
632 intof->SetPrevious(func);
633 if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
637 intof->SetFirst(func);
638 intof->SetTreeID(myTreeID);
641 //=======================================================================
642 //TreeNode : NewEmpty
643 //purpose : Returns new empty TreeNode attribute
644 //=======================================================================
646 Handle(TDF_Attribute) TDataStd_TreeNode::NewEmpty() const
648 Handle(TDataStd_TreeNode) T = new TDataStd_TreeNode();
649 T->SetTreeID(myTreeID);
653 //=======================================================================
654 //TreeNode : References
655 //purpose : Collects the references
656 //=======================================================================
658 void TDataStd_TreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
660 TDataStd_TreeNode* fct = myFirst;
661 while (fct != NULL) {
662 aDataSet->AddAttribute(fct);
667 //=======================================================================
669 //purpose : Dump of the TreeNode
670 //=======================================================================
672 Standard_OStream& TDataStd_TreeNode::Dump (Standard_OStream& anOS) const
674 TDF_Attribute::Dump (anOS);
677 if (!myFather->Label().IsNull()) myFather->Label().EntryDump(anOS);
681 if (!myPrevious->Label().IsNull()) myPrevious->Label().EntryDump(anOS);
685 if (!myNext->Label().IsNull()) myNext->Label().EntryDump(anOS);
689 if (!myFirst->Label().IsNull()) myFirst->Label().EntryDump(anOS);