Salome HOME
d46b38fa595a4e8e08d96330e24fe582db180707
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_AttributeTreeNode.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20 //  File   : SALOMEDSImpl_AttributeTreeNode.cxx
21 //  Author : Sergey RUIN
22 //  Module : SALOME
23
24
25 #include "SALOMEDSImpl_AttributeTreeNode.hxx"
26 #include <Standard_DomainError.hxx>
27 #include <TDF_Tool.hxx>
28 #include <TDF_Data.hxx>
29 #include <TDF_DataSet.hxx>
30 #include <TDF_RelocationTable.hxx>
31 #include <TCollection_AsciiString.hxx> 
32
33 using namespace std;
34
35 IMPLEMENT_STANDARD_HANDLE( SALOMEDSImpl_AttributeTreeNode, SALOMEDSImpl_GenericAttribute )
36 IMPLEMENT_STANDARD_RTTIEXT( SALOMEDSImpl_AttributeTreeNode, SALOMEDSImpl_GenericAttribute )
37
38 static char* Entry(const TDF_Label& theLabel) 
39 {
40   TCollection_AsciiString anEntry;
41   TDF_Tool::Entry(theLabel, anEntry);
42   return anEntry.ToCString();
43 }  
44
45 const Standard_GUID&  SALOMEDSImpl_AttributeTreeNode::GetDefaultTreeID()
46 {
47   static Standard_GUID TreeNodeID ("0E1C36E6-379B-4d90-AC37-17A14310E648");
48   return TreeNodeID;
49 }    
50
51
52 SALOMEDSImpl_AttributeTreeNode::SALOMEDSImpl_AttributeTreeNode() 
53 :SALOMEDSImpl_GenericAttribute("AttributeTreeNode"), myFather(NULL),  myPrevious(NULL), myNext(NULL), myFirst(NULL) 
54 {}
55
56
57 Handle(SALOMEDSImpl_AttributeTreeNode) SALOMEDSImpl_AttributeTreeNode::Set (const TDF_Label& L, const Standard_GUID& ID) 
58 {
59   Handle(SALOMEDSImpl_AttributeTreeNode) TN;
60
61   if (!L.FindAttribute(ID,TN)) {
62     TN = new SALOMEDSImpl_AttributeTreeNode ();
63     TN->SetTreeID(ID);
64     L.AddAttribute(TN);
65   }
66
67   return TN;    
68 }
69
70 //=======================================================================
71 //TreeNode : ID
72 //purpose  : Returns GUID of the TreeNode
73 //=======================================================================
74 const Standard_GUID& SALOMEDSImpl_AttributeTreeNode::ID() const
75 {
76   return myTreeID;
77 }  
78
79 //=======================================================================
80 //function : Append
81 //purpose  : Add <TN> as last child of me
82 //=======================================================================
83 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::Append (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
84 {
85   CheckLocked();
86
87   if (!(TN->ID() == myTreeID) )
88     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::Append : uncompatible GUID");
89
90   Handle(SALOMEDSImpl_AttributeTreeNode) bid;
91   TN->SetNext(bid); // Deconnects from next.
92
93   // Find the last
94   if (!HasFirst()) {
95     SetFirst(TN);
96     TN->SetPrevious(bid); // Deconnects from previous.
97   }
98   else {
99     Handle(SALOMEDSImpl_AttributeTreeNode) Last = GetFirst();
100     while (Last->HasNext()) {
101       Last = Last->GetNext();
102     }
103     Last->SetNext(TN);
104     TN->SetPrevious(Last);
105   }
106   // Set Father
107   TN->SetFather(this);
108   
109   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
110   
111   return !TN.IsNull();
112 }
113
114 //=======================================================================
115 //function : Prepend
116 //purpose  : Add <TN> as first child of me
117 //=======================================================================
118 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::Prepend (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
119 {
120   CheckLocked();
121
122   if (!(TN->ID() == myTreeID) )
123     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::Prepend : uncompatible GUID");
124
125   Handle(SALOMEDSImpl_AttributeTreeNode) bid;
126   TN->SetPrevious(bid);
127   if (HasFirst()) {
128     TN->SetNext(GetFirst());
129     GetFirst()->SetPrevious(TN);
130   }
131   else {
132     TN->SetNext(bid);
133   }
134   TN->SetFather(this);
135   SetFirst(TN);
136   
137   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
138   
139   return !TN.IsNull();
140 }                     
141
142
143 //=======================================================================
144 //function : InsertBefore
145 //purpose  : Inserts the TreeNode  <TN> before me
146 //=======================================================================
147 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::InsertBefore (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
148 {
149   CheckLocked();
150
151   if (!(TN->ID() == myTreeID) )
152     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::InsertBefore : uncompatible GUID");
153
154   TN->SetFather(GetFather());
155   TN->SetPrevious(GetPrevious());
156   TN->SetNext(this);
157
158   if (!HasPrevious())
159     GetFather()->SetFirst(TN);
160   else
161     GetPrevious()->SetNext(TN);
162
163   SetPrevious(TN);
164   
165   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
166   
167   return !TN.IsNull();
168 }
169
170 //=======================================================================
171 //function : InsertAfter
172 //purpose  : Inserts the TreeNode  <TN> after me
173 //=======================================================================
174 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::InsertAfter (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
175 {
176   CheckLocked();
177
178   if (!(TN->ID() == myTreeID) )
179     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::InsertAfter : uncompatible GUID");
180
181   TN->SetFather(GetFather());
182   TN->SetPrevious(this);
183   TN->SetNext(GetNext());
184
185   if (HasNext()) GetNext()->SetPrevious(TN);
186
187   SetNext(TN);
188   
189   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
190   
191   return !TN.IsNull();
192 }         
193
194 //=======================================================================
195 //function : Remove
196 //purpose  : Removees the function from the function tree
197 //=======================================================================
198 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::Remove ()
199 {
200   CheckLocked();
201
202   if (IsRoot()) return Standard_True;
203
204   Handle(SALOMEDSImpl_AttributeTreeNode) bid;
205   if (!HasPrevious())
206     GetFather()->SetFirst(GetNext());
207   else
208     GetPrevious()->SetNext(GetNext());
209
210   if (HasNext()) {
211     if (HasPrevious()) GetNext()->SetPrevious(GetPrevious());
212     else GetNext()->SetPrevious(bid);
213   }
214   else {
215     if (HasPrevious()) GetPrevious()->SetNext(bid);
216   }
217
218   if (GetFather()->HasFirst()) {
219     if (Handle(SALOMEDSImpl_AttributeTreeNode)::DownCast(this) == GetFather()->GetFirst()) {
220       if (HasNext()) {
221         GetFather()->SetFirst(GetNext());
222       }
223       else GetFather()->SetFirst(bid);
224     }
225   }
226
227   SetFather(bid);
228   SetNext(bid);
229   SetPrevious(bid);
230
231   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
232
233   return Standard_True;
234 }         
235
236 //=======================================================================
237 //function : Depth
238 //purpose  :
239 //=======================================================================
240 Standard_Integer SALOMEDSImpl_AttributeTreeNode::Depth () const
241 {
242   Standard_Integer depth = 0;
243   Handle(SALOMEDSImpl_AttributeTreeNode) current = this;
244   while (current->HasFather()) {
245     depth++;
246     current = current->GetFather();
247   }
248   return depth;
249 }
250
251 //=======================================================================
252 //function : SetTreeID
253 //purpose  : Finds or creates a TreeNode  attribute with explicit ID
254 //         : a driver for it
255 //=======================================================================
256 void SALOMEDSImpl_AttributeTreeNode::SetTreeID (const Standard_GUID& explicitID)
257 {
258   myTreeID = explicitID;
259   
260   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
261 }
262
263
264 //=======================================================================
265 //function : IsAscendant
266 //purpose  :
267 //=======================================================================
268 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsAscendant (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
269 {
270   return ofTN->IsDescendant(this);
271 }                
272
273 //=======================================================================
274 //function : IsDescendant
275 //purpose  :
276 //=======================================================================
277
278 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsDescendant (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
279 {
280   Handle(SALOMEDSImpl_AttributeTreeNode) current = this;
281   while (current->HasFather()) {
282     if (current->GetFather() == ofTN) return Standard_True;
283     current = current->GetFather();
284   }
285   return Standard_False;
286 }
287
288 //=======================================================================
289 //function : IsFather
290 //purpose  :
291 //=======================================================================
292
293 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsFather (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
294 {
295   return (ofTN->GetFather() == this);
296 }
297
298
299 //=======================================================================
300 //function : IsChild
301 //purpose  :
302 //=======================================================================
303
304 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsChild (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
305 {
306   return (myFather == ofTN);
307 }
308
309 //=======================================================================
310 //TreeNode : IsRoot
311 //purpose  : Returns Standard_True if the TreeNode is not attached to a
312 //           TreeNode tree or hasn't an Father.
313 //=======================================================================
314 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsRoot() const
315 {
316   if (myFather.IsNull() &&
317       myPrevious.IsNull() &&
318       myNext.IsNull())
319     return Standard_True;
320   return Standard_False;
321 }
322
323 //=======================================================================
324 //TreeNode : Root
325 //purpose  : Returns the TreeNode which has no Father
326 //=======================================================================
327 Handle(SALOMEDSImpl_AttributeTreeNode) SALOMEDSImpl_AttributeTreeNode::Root() const
328 {
329   Handle(SALOMEDSImpl_AttributeTreeNode) O = this;
330   while (O->HasFather())
331     O = O->GetFather();
332   return O;
333 }       
334
335 //=======================================================================
336 //TreeNode : SetFather
337 //purpose  : Sets the TreeNode F as Father of me
338 //=======================================================================
339 void SALOMEDSImpl_AttributeTreeNode::SetFather(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
340 {
341   CheckLocked();
342   Backup();
343   myFather = F;
344   
345   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
346 }
347
348 //=======================================================================
349 //TreeNode : SetNext
350 //purpose  : Sets the TreeNode F next to me
351 //=======================================================================
352 void SALOMEDSImpl_AttributeTreeNode::SetNext(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
353 {
354   CheckLocked();
355   Backup();
356   myNext = F;
357   
358   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
359 }
360
361
362 //=======================================================================
363 //TreeNode : SetPrevious
364 //purpose  : Sets the TreeNode F previous to me
365 //=======================================================================
366 void SALOMEDSImpl_AttributeTreeNode::SetPrevious(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
367 {
368   CheckLocked();
369   Backup();
370   myPrevious = F;
371   
372   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
373 }
374
375 //=======================================================================
376 //TreeNode : SetFirst
377 //purpose  : Sets the TreeNode F as first in the TreeNode tree
378 //=======================================================================
379 void SALOMEDSImpl_AttributeTreeNode::SetFirst(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
380 {
381   CheckLocked();
382   Backup();
383   myFirst = F;
384   
385   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
386 }         
387
388 //=======================================================================
389 //TreeNode : AfterAddition
390 //purpose  : Connects the TreeNode to the tree.
391 //           Backuped attribute must stay disconnected
392 //=======================================================================
393 void SALOMEDSImpl_AttributeTreeNode::AfterAddition() 
394 {
395   if (!IsBackuped()) {
396     if (!myPrevious.IsNull()) {
397       myPrevious->SetNext(this);
398     }
399     else if (!myFather.IsNull()) {
400       myFather->SetFirst(this);
401     }
402     if (!myNext.IsNull())
403       myNext->SetPrevious(this);
404   }
405 }
406
407 //=======================================================================
408 //TreeNode : BeforeForget
409 //purpose  : Disconnect the TreeNode from the tree.
410 //           Backuped attribute is normaly not concerned by such an operation
411 //=======================================================================
412 void SALOMEDSImpl_AttributeTreeNode::BeforeForget() 
413 {
414   if (!IsBackuped()) {
415     Remove();
416     while (HasFirst()) GetFirst()->Remove();
417   }
418 }
419
420 //=======================================================================
421 //TreeNode : AfterResume
422 //purpose  : Connects the TreeNode to the tree
423 //=======================================================================
424 void SALOMEDSImpl_AttributeTreeNode::AfterResume() 
425 {
426   AfterAddition();
427 }
428
429 //=======================================================================
430 //TreeNode : BeforeUndo
431 //purpose  : Disconnect the TreeNode from the tree.
432 //=======================================================================
433 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
434                                                             const Standard_Boolean forceIt)
435 {
436   if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
437   return Standard_True;
438 }           
439
440 //=======================================================================
441 //TreeNode : AfterUndo
442 //purpose  : Connect the TreeNode from the tree.
443 //=======================================================================
444 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
445                                                            const Standard_Boolean forceIt)
446 {
447   if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
448   return Standard_True;
449 }
450
451 //=======================================================================
452 //TreeNode : Restore
453 //purpose  :
454 //=======================================================================
455 void SALOMEDSImpl_AttributeTreeNode::Restore(const Handle(TDF_Attribute)& other) 
456 {
457   Handle(SALOMEDSImpl_AttributeTreeNode) F =  Handle(SALOMEDSImpl_AttributeTreeNode)::DownCast(other);
458   myFather     = F->myFather;
459   myPrevious   = F->myPrevious;
460   myNext       = F->myNext;
461   myFirst      = F->myFirst;
462   myTreeID     = F->myTreeID;
463 }       
464
465 //=======================================================================
466 //TreeNode : Paste
467 //purpose  : Method for Copy mechanism
468 //=======================================================================
469
470 void SALOMEDSImpl_AttributeTreeNode::Paste(const Handle(TDF_Attribute)& into,
471                                            const Handle(TDF_RelocationTable)& RT) const
472 {
473   Handle(SALOMEDSImpl_AttributeTreeNode) intof = Handle(SALOMEDSImpl_AttributeTreeNode)::DownCast(into);
474   Handle(SALOMEDSImpl_AttributeTreeNode) func;
475   if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
476     func.Nullify();
477   }
478   intof->SetFather(func);
479   if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
480     func.Nullify();
481   }
482   intof->SetNext(func);
483   if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
484     func.Nullify();
485   }
486   intof->SetPrevious(func);
487   if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
488     func.Nullify();
489   }
490
491   intof->SetFirst(func);
492   intof->SetTreeID(myTreeID);
493 }
494
495 //=======================================================================
496 //TreeNode : NewEmpty
497 //purpose  : Returns new empty TreeNode attribute
498 //=======================================================================
499
500 Handle(TDF_Attribute) SALOMEDSImpl_AttributeTreeNode::NewEmpty() const
501 {
502   Handle(SALOMEDSImpl_AttributeTreeNode) T = new SALOMEDSImpl_AttributeTreeNode();
503   T->SetTreeID(myTreeID);
504   return T;
505 }
506
507 //=======================================================================
508 //TreeNode : References
509 //purpose  : Collects the references
510 //=======================================================================
511 void SALOMEDSImpl_AttributeTreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
512 {
513   Handle(SALOMEDSImpl_AttributeTreeNode) fct = myFirst;
514   while (!fct.IsNull()) {
515     aDataSet->AddAttribute(fct);
516     fct = fct->myNext;
517   }
518 }          
519
520 TCollection_AsciiString SALOMEDSImpl_AttributeTreeNode::Type()
521 {
522    char* aNodeName = new char[60];
523    char aGUID[40];
524    ID().ToCString(aGUID);
525    sprintf(aNodeName, "AttributeTreeNodeGUID%s",aGUID);
526    TCollection_AsciiString ret(aNodeName); 
527    delete aNodeName;
528    
529    return ret;                               
530 }
531
532 TCollection_AsciiString SALOMEDSImpl_AttributeTreeNode::Save() 
533 {
534   TCollection_AsciiString aFather, aPrevious, aNext, aFirst;
535
536   if (HasFather()) aFather = Entry(GetFather()->Label()); else aFather = "!";
537   if (HasPrevious()) aPrevious = Entry(GetPrevious()->Label()); else aPrevious = "!";
538   if (HasNext()) aNext = Entry(GetNext()->Label()); else aNext = "!";
539   if (HasFirst()) aFirst = Entry(GetFirst()->Label()); else aFirst = "!";
540
541   int aLength = 4;
542   aLength += aFather.Length() + aPrevious.Length() + aNext.Length() + aFirst.Length();
543   char* aResult = new char[aLength];
544   sprintf(aResult, "%s %s %s %s", aFather.ToCString(), aPrevious.ToCString(), aNext.ToCString(), aFirst.ToCString());
545   TCollection_AsciiString ret(aResult);
546   delete aResult;
547   return ret;
548 }
549
550 void SALOMEDSImpl_AttributeTreeNode::Load(const TCollection_AsciiString& value) 
551 {
552   Handle(TDF_Data) DF = Label().Data();
553   
554   char* aCopy = (char*)value.ToCString();
555   char* adr = strtok(aCopy, " ");
556   
557   TDF_Label aLabel;
558   Handle(SALOMEDSImpl_AttributeTreeNode) aDepNode;
559
560   if (adr && adr[0] != '!') {
561     TDF_Tool::Label(DF, adr, aLabel, 1);
562     if (!aLabel.FindAttribute(ID(), aDepNode)) 
563       aDepNode =  SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
564
565     SetFather(aDepNode);
566   }
567
568   adr = strtok(NULL, " ");
569   if (adr && adr[0] != '!') {
570     TDF_Tool::Label(DF, adr, aLabel, 1);
571     if (!aLabel.FindAttribute(ID(), aDepNode)) 
572       aDepNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
573     SetPrevious(aDepNode);
574   }
575
576   adr = strtok(NULL, " ");
577   if (adr && adr[0] != '!') {
578     TDF_Tool::Label(DF, adr, aLabel, 1);
579     if (!aLabel.FindAttribute(ID(), aDepNode)) 
580       aDepNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
581     SetNext(aDepNode);
582   }
583
584   adr = strtok(NULL, " ");
585   if (adr && adr[0] != '!') {
586     TDF_Tool::Label(DF, adr, aLabel, 1);
587     if (!aLabel.FindAttribute(ID(), aDepNode)) 
588       aDepNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
589     SetFirst(aDepNode);
590   }
591 }
592
593