b311480e |
1 | // Created on: 2004-11-22 |
2 | // Created by: Pavel TELKOV |
973c2be1 |
3 | // Copyright (c) 2004-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
7fd59977 |
16 | // The original implementation Copyright: (C) RINA S.p.A |
17 | |
18 | #include <TObj_Object.hxx> |
19 | |
20 | #include <TObj_Assistant.hxx> |
21 | #include <TObj_LabelIterator.hxx> |
22 | #include <TObj_Model.hxx> |
23 | #include <TObj_ObjectIterator.hxx> |
24 | #include <TObj_OcafObjectIterator.hxx> |
25 | #include <TObj_Persistence.hxx> |
26 | #include <TObj_ReferenceIterator.hxx> |
27 | #include <TObj_SequenceIterator.hxx> |
28 | #include <TDataStd_AsciiString.hxx> |
29 | #include <TObj_TModel.hxx> |
30 | #include <TObj_TNameContainer.hxx> |
31 | #include <TObj_TObject.hxx> |
32 | #include <TObj_TReference.hxx> |
33 | |
34 | #include <TCollection_HAsciiString.hxx> |
35 | #include <TColStd_HArray1OfInteger.hxx> |
36 | #include <TColStd_HArray1OfReal.hxx> |
37 | #include <TColStd_HArray1OfExtendedString.hxx> |
38 | #include <TColStd_SequenceOfInteger.hxx> |
39 | #include <TDF_AttributeIterator.hxx> |
40 | #include <TDF_ChildIDIterator.hxx> |
41 | #include <TDF_ChildIterator.hxx> |
42 | #include <TDF_CopyLabel.hxx> |
43 | #include <TDF_Data.hxx> |
44 | #include <TDF_RelocationTable.hxx> |
45 | #include <TDF_Tool.hxx> |
46 | #include <TDataStd_ExtStringArray.hxx> |
47 | #include <TDataStd_Integer.hxx> |
48 | #include <TDataStd_IntegerArray.hxx> |
49 | #include <TDataStd_Name.hxx> |
50 | #include <TDataStd_Real.hxx> |
51 | #include <TDataStd_RealArray.hxx> |
52 | #include <TDocStd_Document.hxx> |
53 | #include <TDocStd_Owner.hxx> |
ec357c5c |
54 | #include <TDF_TagSource.hxx> |
7fd59977 |
55 | |
56 | |
25e59720 |
57 | IMPLEMENT_STANDARD_RTTIEXT(TObj_Object,Standard_Transient) |
92efcf78 |
58 | |
7fd59977 |
59 | //======================================================================= |
60 | //function : Constructor |
61 | //purpose : |
62 | //======================================================================= |
63 | |
64 | TObj_Object::TObj_Object(const TDF_Label& theLabel, |
65 | const Standard_Boolean theSetName) |
66 | : myLabel(theLabel) |
67 | { |
68 | Handle(TObj_Object) aMe = this; |
69 | TObj_TObject::Set(myLabel, aMe); |
70 | if (theSetName) |
71 | TObj_Model::SetNewName(aMe); |
72 | } |
73 | |
74 | //======================================================================= |
75 | //function : GetModel |
76 | //purpose : |
77 | //======================================================================= |
78 | |
79 | Handle(TObj_Model) TObj_Object::GetModel() const |
80 | { |
81 | Handle(TObj_Model) aModel; |
82 | // if object label is null object is not alive |
83 | if ( myLabel.IsNull() ) |
84 | return aModel; |
85 | |
86 | //TDF_Label aLabel = TDocStd_Document::Get(myLabel)->Main(); |
87 | Handle(TDF_Data) aData = myLabel.Data(); |
88 | if (aData.IsNull()) |
89 | return aModel; |
90 | |
91 | // try get the document from owner attribute manually |
92 | TDF_Label aLabel = aData->Root(); |
93 | Handle(TDocStd_Owner) anOwnerAttr; |
94 | Handle(TDocStd_Document) aTDoc; |
95 | if ( !aLabel.IsNull() && aLabel.FindAttribute( TDocStd_Owner::GetID(), anOwnerAttr ) ) |
96 | aTDoc = anOwnerAttr->GetDocument(); |
97 | if (aTDoc.IsNull()) |
98 | return aModel; |
99 | |
100 | // use main label of the document to find TObj model attribute |
101 | aLabel = aTDoc->Main(); |
102 | Handle(TObj_TModel) aModelAttr; |
103 | if (!aLabel.IsNull() && aLabel.FindAttribute(TObj_TModel::GetID(), aModelAttr)) |
104 | aModel = aModelAttr->Model(); |
105 | |
106 | return aModel; |
107 | } |
108 | |
109 | //======================================================================= |
110 | //function : GetChildren |
111 | //purpose : Returns iterator for the child objects. |
112 | // This method provides tree-like view of the objects hierarchy. |
113 | // The references to other objects are not considered as children. |
114 | // theType narrows a variety of iterated objects |
115 | //======================================================================= |
116 | |
117 | static void addObjToOrderSequence( const Handle(TObj_Object)& theObj, |
118 | const Standard_Integer theOrder, |
119 | Handle(TObj_HSequenceOfObject)& theHSeqOfObj, |
120 | const Standard_Integer theHSeqLength, |
121 | Standard_Integer& theLastIndex, |
122 | Standard_Integer& theLastOrder ) |
123 | { |
124 | if ( theOrder > theLastOrder ) |
125 | { |
126 | while ( theOrder > theLastOrder ) |
127 | { |
128 | // get next object and compare with them |
129 | if ( ++theLastIndex > theHSeqLength ) |
130 | { |
131 | theHSeqOfObj->Append( theObj ); |
132 | theLastIndex = theHSeqLength + 1; |
133 | theLastOrder = theOrder; |
134 | return; |
135 | } |
136 | Handle(TObj_Object) aNext = theHSeqOfObj->Value(theLastIndex); |
137 | theLastOrder = aNext->GetOrder(); |
138 | } |
139 | // add before current position |
140 | theHSeqOfObj->InsertBefore( theLastIndex, theObj ); |
141 | theLastOrder = theOrder; |
142 | } |
143 | else |
144 | { |
145 | while ( theOrder < theLastOrder ) |
146 | { |
147 | if ( --theLastIndex < 1 ) |
148 | { |
149 | theHSeqOfObj->InsertBefore( 1, theObj ); |
150 | theLastIndex = 1; |
151 | theLastOrder = theOrder; |
152 | return; |
153 | } |
154 | // get next object and compare with them |
155 | Handle(TObj_Object) aNext = theHSeqOfObj->Value(theLastIndex); |
156 | theLastOrder = aNext->GetOrder(); |
157 | } |
158 | // add object after current position |
159 | theHSeqOfObj->InsertAfter( theLastIndex, theObj ); |
160 | theLastIndex++; |
161 | theLastOrder = theOrder; |
162 | return; |
163 | } |
164 | } |
165 | |
166 | Handle(TObj_ObjectIterator) TObj_Object::GetChildren |
167 | (const Handle(Standard_Type)& theType) const |
168 | { |
169 | Handle(TObj_ObjectIterator) anItr = |
170 | new TObj_OcafObjectIterator(GetChildLabel(), theType, Standard_True); |
171 | if ( !TestFlags( ObjectState_Ordered ) ) |
172 | return anItr; |
173 | // return object according to their order |
174 | Standard_Integer aLastIndex = 0; |
175 | Standard_Integer aLastOrder = 0; |
176 | Handle(TObj_HSequenceOfObject) aHSeqOfObj = new TObj_HSequenceOfObject(); |
177 | for ( ; anItr->More(); anItr->Next() ) |
178 | { |
179 | Handle(TObj_Object) anObj = anItr->Value(); |
180 | if ( anObj.IsNull() ) |
181 | continue; |
182 | Standard_Integer anOrder = anObj->GetOrder(); |
183 | if ( !aLastIndex ) |
184 | { |
185 | aHSeqOfObj->Append( anObj ); |
186 | aLastIndex = 1; |
187 | aLastOrder = anOrder; |
188 | } |
189 | else |
190 | addObjToOrderSequence( anObj, anOrder, aHSeqOfObj, aHSeqOfObj->Length(), |
191 | aLastIndex, aLastOrder ); |
192 | } |
193 | return new TObj_SequenceIterator( aHSeqOfObj ); |
194 | } |
195 | |
196 | //======================================================================= |
197 | //function : getLabelByRank |
198 | //purpose : Auxiliary function to get a label and attache a name to it |
199 | // Used in debug mode only |
200 | //======================================================================= |
201 | |
202 | #ifdef DFBROWSE |
203 | static TDF_Label getLabelByRank(const TDF_Label& theL, |
204 | const Standard_Integer theRank, |
205 | const Standard_CString theName) |
206 | { |
207 | TDF_Label L = theL.FindChild(theRank,Standard_False); |
208 | if ( L.IsNull() ) |
209 | { |
210 | L = theL.FindChild(theRank,Standard_True); |
211 | TDataStd_Name::Set(L, theName); |
212 | } |
213 | return L; |
214 | } |
215 | #endif |
216 | |
217 | //======================================================================= |
218 | //function : GetChildLabel |
219 | //purpose : |
220 | //======================================================================= |
221 | |
222 | TDF_Label TObj_Object::GetChildLabel() const |
223 | { |
224 | #ifdef DFBROWSE |
225 | return getLabelByRank(GetLabel(),4,"Children"); |
226 | #else |
227 | return GetLabel().FindChild ( 4, Standard_True ); |
228 | #endif |
229 | } |
230 | |
231 | //======================================================================= |
232 | //function : getChildLabel |
233 | //purpose : |
234 | //======================================================================= |
235 | |
236 | TDF_Label TObj_Object::getChildLabel(const Standard_Integer theRank) const |
237 | { |
238 | TDF_Label aLabel = GetChildLabel(); |
239 | if ( theRank > 0 ) |
240 | aLabel = aLabel.FindChild( theRank, Standard_True ); |
241 | return aLabel; |
242 | } |
243 | |
244 | //======================================================================= |
245 | //function : GetLabel |
246 | //purpose : |
247 | //======================================================================= |
248 | |
249 | TDF_Label TObj_Object::GetLabel() const |
250 | { |
251 | return myLabel; |
252 | } |
253 | |
254 | //======================================================================= |
255 | //function : SetName |
256 | //purpose : |
257 | //======================================================================= |
258 | |
259 | Standard_Boolean TObj_Object::SetName(const Handle(TCollection_HExtendedString)& theName) const |
260 | { |
261 | // check if the name is exactly the same |
262 | Handle(TCollection_HExtendedString) anOldName = GetName(); |
263 | if( !anOldName.IsNull() && theName->String().IsEqual(anOldName->String()) ) |
264 | return Standard_True; |
265 | |
266 | // check if name is already registered and do nothing in that case |
267 | const Handle(TObj_TNameContainer) aDictionary = GetDictionary(); |
268 | Handle(TObj_Model) aModel = GetModel(); |
269 | if( aModel->IsRegisteredName( theName, aDictionary ) ) |
270 | return Standard_False; |
271 | |
272 | // change name and update registry |
273 | if (!anOldName.IsNull()) |
274 | aModel->UnRegisterName( anOldName, aDictionary ); |
275 | if ( theName.IsNull() ) |
276 | GetLabel().ForgetAttribute ( TDataStd_Name::GetID() ); |
277 | else |
278 | { |
279 | aModel->RegisterName( theName, GetLabel(), aDictionary ); |
280 | TDataStd_Name::Set(GetLabel(),theName->String()); |
281 | } |
282 | return Standard_True; |
283 | } |
284 | |
285 | //======================================================================= |
286 | //function : SetName |
287 | //purpose : |
288 | //======================================================================= |
289 | |
290 | Standard_Boolean TObj_Object::SetName(const Handle(TCollection_HAsciiString)& theName) const |
291 | { |
292 | return SetName( new TCollection_HExtendedString ( theName ) ); |
293 | } |
294 | |
295 | //======================================================================= |
296 | //function : SetName |
297 | //purpose : |
298 | //======================================================================= |
299 | |
300 | Standard_Boolean TObj_Object::SetName(const Standard_CString theName) const |
301 | { |
302 | return SetName ( new TCollection_HExtendedString ( theName ) ); |
303 | } |
304 | |
305 | //======================================================================= |
306 | //function : GetName |
307 | //purpose : |
308 | //======================================================================= |
309 | |
310 | Handle(TCollection_HExtendedString) TObj_Object::GetName() const |
311 | { |
312 | Handle(TCollection_HExtendedString) aName; |
313 | Handle(TDataStd_Name) A; |
314 | if (GetLabel().FindAttribute (TDataStd_Name::GetID(), A)) |
315 | aName = new TCollection_HExtendedString(A->Get()); |
316 | else aName = new TCollection_HExtendedString(""); |
317 | return aName; |
318 | } |
319 | |
320 | //======================================================================= |
321 | //function : GetName |
322 | //purpose : |
323 | //======================================================================= |
324 | |
325 | Standard_Boolean TObj_Object::GetName(TCollection_ExtendedString& theStr) const |
326 | { |
327 | Handle(TCollection_HExtendedString) aName = GetName(); |
328 | theStr = aName->String(); |
329 | return theStr.Length() != 0; |
330 | } |
331 | |
332 | //======================================================================= |
333 | //function : GetName |
334 | //purpose : |
335 | //======================================================================= |
336 | |
337 | Standard_Boolean TObj_Object::GetName(TCollection_AsciiString& theName) const |
338 | { |
339 | Handle(TCollection_HExtendedString) aName = GetName(); |
340 | if(aName.IsNull()) |
341 | return Standard_False; |
342 | theName = TCollection_AsciiString (aName->String()); |
343 | return theName.Length() != 0; |
344 | } |
345 | |
346 | //======================================================================= |
347 | //function : HasReference |
348 | //purpose : |
349 | //======================================================================= |
350 | |
351 | Standard_Boolean TObj_Object::HasReference |
352 | (const Handle(TObj_Object)& theObject) const |
353 | { |
354 | if ( theObject.IsNull() ) |
355 | return Standard_False; |
356 | Handle(TObj_ObjectIterator) anItr = GetReferences(theObject->DynamicType()); |
357 | if ( anItr.IsNull() || !anItr->More() ) |
358 | return Standard_False; |
359 | for ( ; anItr->More(); anItr->Next() ) |
360 | if ( anItr->Value() == theObject ) |
361 | return Standard_True; |
362 | return Standard_False; |
363 | } |
364 | |
365 | //======================================================================= |
366 | //function : GetReferences |
367 | //purpose : |
368 | //======================================================================= |
369 | |
370 | Handle(TObj_ObjectIterator) TObj_Object::GetReferences |
371 | (const Handle(Standard_Type)& theType) const |
372 | { |
373 | return new TObj_ReferenceIterator(GetReferenceLabel(), theType); |
374 | } |
375 | |
376 | //======================================================================= |
377 | //function : RemoveAllReferences |
378 | //purpose : |
379 | //======================================================================= |
380 | |
381 | void TObj_Object::RemoveAllReferences() |
382 | { |
383 | GetReferenceLabel().ForgetAllAttributes(); |
384 | // other implementation may be get all reference by iterator |
385 | // and replace all of them by null handle with help of ::ReplaceReference |
386 | } |
387 | |
388 | //======================================================================= |
389 | //function : AddBackReference |
390 | //purpose : |
391 | //======================================================================= |
392 | |
393 | void TObj_Object::AddBackReference (const Handle(TObj_Object)& theObject) |
394 | { |
395 | if (myHSeqBackRef.IsNull()) |
396 | myHSeqBackRef = new TObj_HSequenceOfObject; |
397 | |
398 | myHSeqBackRef->Append( theObject ); |
399 | } |
400 | |
401 | //======================================================================= |
402 | //function : RemoveBackReference |
403 | //purpose : |
404 | //======================================================================= |
405 | |
406 | void TObj_Object::RemoveBackReference (const Handle(TObj_Object)& theObject, |
407 | const Standard_Boolean theSingleOnly) |
408 | { |
409 | if (myHSeqBackRef.IsNull()) // to avoid exception. |
410 | return; |
411 | |
412 | for (Standard_Integer i = 1; i <= myHSeqBackRef->Length(); i++) |
413 | { |
414 | if (theObject != myHSeqBackRef->Value(i)) |
415 | continue; |
416 | |
417 | myHSeqBackRef->Remove(i--); |
418 | if (theSingleOnly) |
419 | break; |
420 | } |
421 | if (myHSeqBackRef->Length() < 1) |
422 | myHSeqBackRef.Nullify(); // do not need to store empty sequence. |
423 | } |
424 | //======================================================================= |
425 | //function : GetBackReferences |
426 | //purpose : |
427 | //======================================================================= |
428 | |
429 | Handle(TObj_ObjectIterator) TObj_Object::GetBackReferences |
430 | (const Handle(Standard_Type)& theType) const |
431 | { |
432 | return new TObj_SequenceIterator( myHSeqBackRef, theType ); |
433 | } |
434 | |
435 | //======================================================================= |
436 | //function : ClearBackReferences |
437 | //purpose : |
438 | //======================================================================= |
439 | |
440 | void TObj_Object::ClearBackReferences () |
441 | { |
442 | myHSeqBackRef.Nullify(); |
443 | } |
444 | |
445 | //======================================================================= |
446 | //function : HasBackReferences |
447 | //purpose : |
448 | //======================================================================= |
449 | |
450 | Standard_Boolean TObj_Object::HasBackReferences() const |
451 | { |
452 | Handle(TObj_ObjectIterator) anItr = GetBackReferences(); |
453 | if ( anItr.IsNull() || !anItr->More() ) |
454 | return Standard_False; |
455 | return Standard_True; |
456 | } |
457 | |
458 | //======================================================================= |
459 | //function : CanRemoveReference |
460 | //purpose : |
461 | //======================================================================= |
462 | |
463 | Standard_Boolean TObj_Object::CanRemoveReference |
464 | (const Handle(TObj_Object)& /*theObject*/) const |
465 | { |
466 | return Standard_False; |
467 | } |
468 | |
469 | //======================================================================= |
470 | //function : RemoveReference |
471 | //purpose : |
472 | //======================================================================= |
473 | |
474 | void TObj_Object::RemoveReference (const Handle(TObj_Object)& theObject) |
475 | { |
476 | Handle(TObj_Object) aNullObj; |
477 | ReplaceReference (theObject, aNullObj); |
478 | } |
479 | |
480 | //======================================================================= |
481 | //function : CanDetach |
482 | //purpose : |
483 | //======================================================================= |
484 | Standard_Boolean TObj_Object::CanDetach(const TObj_DeletingMode theMode ) |
485 | { |
486 | if( !IsAlive() ) |
487 | return Standard_False; |
488 | |
489 | Handle(TObj_ObjectIterator) aRefs = GetBackReferences(); |
490 | |
491 | // Free Object can be deleted in any Mode |
492 | if ( aRefs.IsNull() || ! aRefs->More() ) |
493 | return Standard_True; |
494 | |
495 | if( theMode == TObj_FreeOnly ) |
496 | return Standard_False; |
497 | |
498 | if( theMode == TObj_Forced ) |
499 | return Standard_True; |
500 | |
501 | // check the last KeepDepending mode |
502 | Handle(TObj_Object) aMe = this; |
503 | for( ; aRefs->More(); aRefs->Next()) |
504 | { |
505 | Handle(TObj_Object) anObject = aRefs->Value(); |
506 | if (! anObject->CanRemoveReference(aMe) ) |
507 | return Standard_False; // one of objects could not be unlinked |
508 | } |
509 | |
510 | return Standard_True; |
511 | } |
512 | |
513 | //======================================================================= |
514 | //function : Detach |
515 | //purpose : |
516 | //======================================================================= |
517 | |
518 | Standard_Boolean TObj_Object::Detach(const TObj_DeletingMode theMode) |
519 | { |
520 | if( !IsAlive() ) |
521 | return Standard_False; |
522 | |
523 | // if object can not be deleted returns False |
524 | if(!RemoveBackReferences(theMode)) |
525 | return Standard_False; |
526 | |
527 | Handle(TCollection_HExtendedString) anOldName = GetName(); |
528 | |
529 | // detaching childs |
530 | Handle(TObj_ObjectIterator) aChildren = GetChildren(); |
531 | |
532 | for(;aChildren->More(); aChildren->Next()) |
533 | aChildren->Value()->Detach(theMode); |
534 | |
535 | // Clearing its own data |
536 | GetReferenceLabel().ForgetAllAttributes(); |
537 | // clear back references container |
538 | ClearBackReferences(); |
539 | // remove data |
540 | GetDataLabel().ForgetAllAttributes(); |
541 | |
542 | if (!anOldName.IsNull()) |
543 | { |
544 | const Handle(TObj_TNameContainer) aDictionary = GetDictionary(); |
545 | // unregister only it is registered to me. |
546 | if ( !aDictionary.IsNull() && aDictionary->IsRegistered( anOldName ) ) |
547 | { |
548 | TDF_Label aRegisteredLabel = aDictionary->Get().Find( anOldName ); |
549 | if ( !aRegisteredLabel.IsNull() && aRegisteredLabel == GetLabel() ) |
550 | aDictionary->RemoveName( anOldName ); |
551 | } |
552 | } |
553 | GetLabel().ForgetAllAttributes(); |
554 | |
555 | return Standard_True; |
556 | } |
557 | |
558 | //======================================================================= |
559 | //function : Detach |
560 | //purpose : public static method |
561 | //======================================================================= |
562 | |
563 | Standard_Boolean TObj_Object::Detach(const TDF_Label& theLabel, |
564 | const TObj_DeletingMode theMode) |
565 | { |
566 | Handle(TObj_Object) anObject; |
567 | if( GetObj(theLabel, anObject) ) |
568 | return anObject->Detach(theMode); |
569 | return Standard_True; |
570 | } |
571 | |
572 | //======================================================================= |
573 | //function : GetObj |
574 | //purpose : |
575 | //======================================================================= |
576 | |
577 | Standard_Boolean TObj_Object::GetObj(const TDF_Label& theLabel, |
578 | Handle(TObj_Object)& theResult, |
579 | const Standard_Boolean isSuper) |
580 | { |
581 | if(theLabel.IsNull()) |
582 | return Standard_False; |
583 | |
584 | Handle(TObj_TObject) A; |
585 | |
586 | // find on the current label |
587 | if ( theLabel.FindAttribute(TObj_TObject::GetID(), A) ) |
588 | theResult = A->Get(); |
589 | else |
590 | theResult.Nullify(); |
591 | |
592 | if( !theResult.IsNull() ) |
593 | { |
594 | if( !theResult->myLabel.IsNull() ) |
595 | return Standard_True; |
596 | |
597 | // if the object is not allive then it is a wrong data in the Data Model |
598 | theResult.Nullify(); |
599 | } |
600 | else if( isSuper ) |
601 | { |
602 | // try to get object from the father label |
603 | return GetObj(theLabel.Father(),theResult,isSuper); |
604 | } |
605 | |
606 | return Standard_False; |
607 | } |
608 | |
609 | //======================================================================= |
610 | //function : GetFatherObject |
611 | //purpose : Returns the father object, which may be NULL |
612 | // theType gives type of father object to search |
613 | //======================================================================= |
614 | |
615 | Handle(TObj_Object) TObj_Object::GetFatherObject |
616 | (const Handle(Standard_Type)& theType) const |
617 | { |
618 | Handle(TObj_Object) aFather, aSon(this); |
619 | |
620 | while ( aSon->GetObj( aSon->GetLabel().Father(), aFather, Standard_True ) ) |
621 | { |
622 | if (theType.IsNull() || aFather->IsKind( theType )) |
623 | break; |
624 | else |
625 | { |
626 | aSon = aFather; |
627 | aFather.Nullify(); |
628 | } |
629 | } |
630 | |
631 | return aFather; |
632 | } |
633 | |
634 | |
635 | //======================================================================= |
636 | //function : AfterRetrieval |
637 | //purpose : |
638 | //======================================================================= |
639 | |
640 | void TObj_Object::AfterRetrieval() |
641 | { |
642 | // Register the name |
643 | Handle(TObj_Model) aModel = GetModel(); |
644 | if ( !aModel.IsNull() ) |
645 | aModel->RegisterName( GetName(), GetLabel(), GetDictionary() ); |
646 | } |
647 | |
648 | //======================================================================= |
649 | //function : BeforeStoring |
650 | //purpose : base implementation |
651 | //======================================================================= |
652 | |
653 | void TObj_Object::BeforeStoring() |
654 | { |
655 | } |
656 | |
657 | //======================================================================= |
658 | //function : GetReferenceLabel |
659 | //purpose : |
660 | //======================================================================= |
661 | |
662 | TDF_Label TObj_Object::GetReferenceLabel() const |
663 | { |
664 | #ifdef DFBROWSE |
665 | return getLabelByRank(GetLabel(),1,"References"); |
666 | #else |
667 | return GetLabel().FindChild ( 1, Standard_True ); |
668 | #endif |
669 | } |
670 | |
671 | //======================================================================= |
672 | //function : GetDataLabel |
673 | //purpose : |
674 | //======================================================================= |
675 | |
676 | TDF_Label TObj_Object::GetDataLabel() const |
677 | { |
678 | #ifdef DFBROWSE |
679 | return getLabelByRank(GetLabel(),3,"Data"); |
680 | #else |
681 | return GetLabel().FindChild ( 3, Standard_True ); |
682 | #endif |
683 | } |
684 | |
685 | //======================================================================= |
686 | //function : getDataLabel |
687 | //purpose : |
688 | //======================================================================= |
689 | |
690 | TDF_Label TObj_Object::getDataLabel (const Standard_Integer theRank1, |
691 | const Standard_Integer theRank2) const |
692 | { |
693 | TDF_Label aLabel; |
694 | if ( theRank1 > 0 ) // protection |
695 | { |
696 | aLabel = GetDataLabel().FindChild ( theRank1, Standard_True ); |
697 | if ( theRank2 > 0 ) |
698 | aLabel = aLabel.FindChild ( theRank2, Standard_True ); |
699 | } |
700 | return aLabel; |
701 | } |
702 | |
703 | //======================================================================= |
704 | //function : getReferenceLabel |
705 | //purpose : |
706 | //======================================================================= |
707 | |
708 | TDF_Label TObj_Object::getReferenceLabel (const Standard_Integer theRank1, |
709 | const Standard_Integer theRank2) const |
710 | { |
711 | TDF_Label aLabel; |
712 | if ( theRank1 > 0 ) // protection |
713 | { |
714 | aLabel = GetReferenceLabel().FindChild ( theRank1, Standard_True ); |
715 | if ( theRank2 > 0 ) |
716 | aLabel = aLabel.FindChild ( theRank2, Standard_True ); |
717 | } |
718 | return aLabel; |
719 | } |
720 | |
721 | //======================================================================= |
722 | //function : isDataAttribute |
723 | //purpose : Returns True if there is an attribute having theGUID on the |
724 | // theRank2-th sublabel of theRank1-th sublabel of the Data |
725 | // label of the object. |
726 | // If theRank2 is 0 (default), label theRank1 is supposed, not |
727 | // its sublabel |
728 | //======================================================================= |
729 | |
730 | Standard_Boolean TObj_Object::isDataAttribute |
731 | (const Standard_GUID& theGUID, |
732 | const Standard_Integer theRank1, |
733 | const Standard_Integer theRank2) const |
734 | { |
735 | return getDataLabel(theRank1,theRank2).IsAttribute(theGUID); |
736 | } |
737 | |
738 | //======================================================================= |
739 | //function : getReal |
740 | //purpose : |
741 | //======================================================================= |
742 | |
743 | Standard_Real TObj_Object::getReal (const Standard_Integer theRank1, |
744 | const Standard_Integer theRank2) const |
745 | { |
746 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
747 | |
748 | Handle(TDataStd_Real) aReal; |
749 | aLabel.FindAttribute ( TDataStd_Real::GetID(), aReal ); |
750 | return aReal.IsNull() ? 0. : aReal->Get(); |
751 | } |
752 | |
753 | //======================================================================= |
754 | //function : setReal |
755 | //purpose : |
756 | //======================================================================= |
757 | |
758 | Standard_Boolean TObj_Object::setReal (const Standard_Real theValue, |
759 | const Standard_Integer theRank1, |
760 | const Standard_Integer theRank2, |
761 | const Standard_Real theTolerance) const |
762 | { |
763 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
764 | |
765 | // check that value is actually changed |
766 | Handle(TDataStd_Real) A; |
767 | if ( aLabel.FindAttribute(TDataStd_Real::GetID(), A) && |
768 | fabs ( A->Get() - theValue ) <= theTolerance ) return Standard_False; |
769 | |
770 | TDataStd_Real::Set ( aLabel, theValue ); |
771 | return Standard_True; |
772 | } |
773 | |
774 | //======================================================================= |
775 | //function : getExtString |
776 | //purpose : |
777 | //======================================================================= |
778 | |
779 | Handle(TCollection_HExtendedString) TObj_Object::getExtString |
780 | (const Standard_Integer theRank1, |
781 | const Standard_Integer theRank2) const |
782 | { |
783 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
784 | |
785 | Handle(TDataStd_Name) aName; |
786 | aLabel.FindAttribute ( TDataStd_Name::GetID(), aName ); |
787 | return aName.IsNull() ? 0 : new TCollection_HExtendedString(aName->Get()); |
788 | } |
789 | |
790 | //======================================================================= |
791 | //function : setExtString |
792 | //purpose : |
793 | //======================================================================= |
794 | |
795 | void TObj_Object::setExtString |
796 | (const Handle(TCollection_HExtendedString)& theValue, |
797 | const Standard_Integer theRank1, |
798 | const Standard_Integer theRank2) const |
799 | { |
800 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
801 | if ( !theValue.IsNull() ) |
802 | TDataStd_Name::Set ( aLabel, theValue->String() ); |
803 | else |
804 | aLabel.ForgetAttribute( TDataStd_Name::GetID() ); |
805 | } |
806 | |
807 | //======================================================================= |
808 | //function : getAsciiString |
809 | //purpose : |
810 | //======================================================================= |
811 | |
812 | Handle(TCollection_HAsciiString) TObj_Object::getAsciiString |
813 | (const Standard_Integer theRank1, |
814 | const Standard_Integer theRank2) const |
815 | { |
816 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
817 | |
818 | Handle(TDataStd_AsciiString) aStrAttr; |
819 | aLabel.FindAttribute ( TDataStd_AsciiString::GetID(), aStrAttr ); |
820 | return aStrAttr.IsNull() ? 0 : new TCollection_HAsciiString( aStrAttr->Get() ); |
821 | } |
822 | |
823 | //======================================================================= |
824 | //function : setAsciiString |
825 | //purpose : |
826 | //======================================================================= |
827 | |
828 | void TObj_Object::setAsciiString |
829 | (const Handle(TCollection_HAsciiString)& theValue, |
830 | const Standard_Integer theRank1, |
831 | const Standard_Integer theRank2) const |
832 | { |
833 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
834 | if ( !theValue.IsNull() ) |
835 | TDataStd_AsciiString::Set ( aLabel, theValue->String() ); |
836 | else |
837 | aLabel.ForgetAttribute( TDataStd_AsciiString::GetID() ); |
838 | } |
839 | |
840 | //======================================================================= |
841 | //function : getInteger |
842 | //purpose : |
843 | //======================================================================= |
844 | |
845 | Standard_Integer TObj_Object::getInteger (const Standard_Integer theRank1, |
846 | const Standard_Integer theRank2) const |
847 | { |
848 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
849 | |
850 | Handle(TDataStd_Integer) aNum; |
851 | aLabel.FindAttribute ( TDataStd_Integer::GetID(), aNum ); |
852 | return aNum.IsNull() ? 0 : aNum->Get(); |
853 | } |
854 | |
855 | //======================================================================= |
856 | //function : setInteger |
857 | //purpose : |
858 | //======================================================================= |
859 | |
860 | Standard_Boolean TObj_Object::setInteger (const Standard_Integer theValue, |
861 | const Standard_Integer theRank1, |
862 | const Standard_Integer theRank2) const |
863 | { |
864 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
865 | |
866 | // check that value is actually changed |
867 | Handle(TDataStd_Integer) A; |
868 | if ( aLabel.FindAttribute(TDataStd_Integer::GetID(), A) && |
869 | A->Get() == theValue ) return Standard_False; |
870 | |
871 | TDataStd_Integer::Set ( aLabel, theValue ); |
872 | return Standard_True; |
873 | } |
874 | |
875 | //======================================================================= |
876 | //function : getReference |
877 | //purpose : |
878 | //======================================================================= |
879 | |
880 | Handle(TObj_Object) TObj_Object::getReference (const Standard_Integer theRank1, |
881 | const Standard_Integer theRank2) const |
882 | { |
883 | TDF_Label aLabel = getReferenceLabel(theRank1,theRank2); |
884 | |
885 | Handle(TObj_TReference) aRef; |
886 | aLabel.FindAttribute ( TObj_TReference::GetID(), aRef ); |
887 | return aRef.IsNull() ? Handle(TObj_Object)() : aRef->Get(); |
888 | } |
889 | |
890 | //======================================================================= |
891 | //function : setReference |
892 | //purpose : |
893 | //======================================================================= |
894 | |
895 | Standard_Boolean TObj_Object::setReference (const Handle(TObj_Object) & theObject, |
896 | const Standard_Integer theRank1, |
897 | const Standard_Integer theRank2) |
898 | { |
899 | TDF_Label aLabel = getReferenceLabel(theRank1,theRank2); |
900 | |
901 | if ( theObject.IsNull() ) |
902 | return aLabel.ForgetAttribute ( TObj_TReference::GetID() ); |
903 | |
904 | // check that reference is actually changed |
905 | Handle(TObj_TReference) A; |
906 | if ( aLabel.FindAttribute(TObj_TReference::GetID(), A) && |
907 | A->Get() == theObject ) return Standard_False; |
908 | |
909 | // 27.07.05, PTv: remove reference attribute before create new reference (for Undo/Redo) |
910 | aLabel.ForgetAttribute( TObj_TReference::GetID() ); |
911 | |
912 | Handle(TObj_Object) me = this; |
913 | TObj_TReference::Set ( aLabel, theObject, me); |
914 | return Standard_True; |
915 | } |
916 | |
917 | //======================================================================= |
918 | //function : addReference |
919 | //purpose : |
920 | //======================================================================= |
921 | |
922 | TDF_Label TObj_Object::addReference (const Standard_Integer theRank1, |
923 | const Handle(TObj_Object) & theObject) |
924 | { |
925 | TDF_Label aRefLabel = GetReferenceLabel(); |
926 | if ( theRank1 > 0 ) |
927 | aRefLabel = aRefLabel.FindChild ( theRank1, Standard_True ); |
928 | |
929 | TDF_TagSource aTag; |
930 | TDF_Label aLabel = aTag.NewChild(aRefLabel); |
931 | |
932 | Handle(TObj_Object) me = this; |
933 | TObj_TReference::Set ( aLabel, theObject, me); |
934 | return aLabel; |
935 | } |
936 | |
937 | //======================================================================= |
938 | //function : getRealArray |
939 | //purpose : Returns an existing or create a new real array on theRank2-th |
940 | // sublabel of theRank1-th sublabel of the Data label of the object. |
941 | // If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel). |
942 | // A newly created array has 1 and theLength bounds and is initialized |
943 | // with zero |
944 | //WARNING : call setArray() after array contents modification |
945 | // in order to assure Undo work |
946 | //======================================================================= |
947 | |
948 | Handle(TColStd_HArray1OfReal) TObj_Object::getRealArray |
949 | (const Standard_Integer theLength, |
950 | const Standard_Integer theRank1, |
951 | const Standard_Integer theRank2, |
952 | const Standard_Real theInitialValue) const |
953 | { |
954 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
955 | Handle(TDataStd_RealArray) anArrAttribute; |
956 | if (!aLabel.FindAttribute(TDataStd_RealArray::GetID(), anArrAttribute)) |
957 | if ( theLength > 0 ) |
958 | { |
959 | anArrAttribute = TDataStd_RealArray::Set (aLabel, 1, theLength); |
960 | anArrAttribute->Array()->Init( theInitialValue ); |
961 | } |
962 | Handle(TColStd_HArray1OfReal) anArr; |
963 | if ( !anArrAttribute.IsNull() ) |
964 | anArr = anArrAttribute->Array(); |
965 | return anArr; |
966 | } |
967 | |
968 | //======================================================================= |
969 | //function : getIntegerArray |
970 | //purpose : Returns an existing or create a new integer array on theRank2-th |
971 | // sublabel of theRank1-th sublabel of the Data label of the object. |
972 | // If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel). |
973 | // A newly created array has 1 and theLength bounds and is initialized |
974 | // with zero |
975 | //WARNING : call setArray() after array contents modification |
976 | // in order to assure Undo work |
977 | //======================================================================= |
978 | |
979 | Handle(TColStd_HArray1OfInteger) TObj_Object::getIntegerArray |
980 | (const Standard_Integer theLength, |
981 | const Standard_Integer theRank1, |
982 | const Standard_Integer theRank2, |
983 | const Standard_Integer theInitialValue) const |
984 | { |
985 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
986 | Handle(TDataStd_IntegerArray) anArrAttribute; |
987 | if (!aLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anArrAttribute)) |
988 | if ( theLength > 0 ) |
989 | { |
990 | anArrAttribute = TDataStd_IntegerArray::Set (aLabel, 1, theLength); |
991 | anArrAttribute->Array()->Init( theInitialValue ); |
992 | } |
993 | Handle(TColStd_HArray1OfInteger) anArr; |
994 | if ( !anArrAttribute.IsNull() ) |
995 | anArr = anArrAttribute->Array(); |
996 | return anArr; |
997 | } |
998 | |
999 | //======================================================================= |
1000 | //function : getExtStringArray |
1001 | //purpose : Returns an existing or create a new string array on theRank2-th |
1002 | // sublabel of theRank1-th sublabel of the Data label of the object. |
1003 | // If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel). |
1004 | // A newly created array has 1 and theLength bounds |
1005 | // NOTE: new created array is NOT initialized. |
1006 | //WARNING : call setArray() after array contents modification |
1007 | // in order to assure Undo work |
1008 | //======================================================================= |
1009 | |
1010 | Handle(TColStd_HArray1OfExtendedString) TObj_Object::getExtStringArray |
1011 | (const Standard_Integer theLength, |
1012 | const Standard_Integer theRank1, |
1013 | const Standard_Integer theRank2) const |
1014 | { |
1015 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
1016 | Handle(TDataStd_ExtStringArray) anArrAttribute; |
1017 | if (!aLabel.FindAttribute(TDataStd_ExtStringArray::GetID(), anArrAttribute)) |
1018 | if ( theLength > 0 ) |
1019 | anArrAttribute = TDataStd_ExtStringArray::Set (aLabel, 1, theLength); |
1020 | |
1021 | Handle(TColStd_HArray1OfExtendedString) anArr; |
1022 | if ( !anArrAttribute.IsNull() ) |
1023 | anArr = anArrAttribute->Array(); |
1024 | return anArr; |
1025 | } |
1026 | |
1027 | //======================================================================= |
1028 | //function : setArray |
1029 | //purpose : Store theArray on theRank2-th sublabel of theRank1-th sublabel |
1030 | // of the Data label of the object. |
1031 | // If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel). |
1032 | //======================================================================= |
1033 | |
1034 | void TObj_Object::setArray (const Handle(TColStd_HArray1OfReal)& theArray, |
1035 | const Standard_Integer theRank1, |
1036 | const Standard_Integer theRank2) |
1037 | { |
1038 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
1039 | Handle(TDataStd_RealArray) anArrAttribute; |
1040 | if (!aLabel.FindAttribute(TDataStd_RealArray::GetID(), anArrAttribute) && |
1041 | !theArray.IsNull()) |
1042 | anArrAttribute = TDataStd_RealArray::Set (aLabel, 1, 1); |
1043 | |
1044 | if (theArray.IsNull()) { |
1045 | // deletion mode |
1046 | if (!anArrAttribute.IsNull()) |
1047 | aLabel.ForgetAttribute(anArrAttribute); |
1048 | return; |
1049 | } |
1050 | |
1051 | if (anArrAttribute->Array() == theArray) |
1052 | // Backup wont happen but we want it |
1053 | anArrAttribute->Init(1,1); |
1054 | |
1055 | anArrAttribute->ChangeArray( theArray ); |
1056 | } |
1057 | |
1058 | //======================================================================= |
1059 | //function : setArray |
1060 | //purpose : Store theArray on theRank2-th sublabel of theRank1-th sublabel |
1061 | // of the Data label of the object. |
1062 | // If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel). |
1063 | //======================================================================= |
1064 | |
1065 | void TObj_Object::setArray (const Handle(TColStd_HArray1OfInteger)& theArray, |
1066 | const Standard_Integer theRank1, |
1067 | const Standard_Integer theRank2) |
1068 | { |
1069 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
1070 | Handle(TDataStd_IntegerArray) anArrAttribute; |
1071 | if (!aLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anArrAttribute) && |
1072 | !theArray.IsNull()) |
1073 | anArrAttribute = TDataStd_IntegerArray::Set (aLabel, 1, 1); |
1074 | |
1075 | if (theArray.IsNull()) { |
1076 | // deletion mode |
1077 | if (!anArrAttribute.IsNull()) |
1078 | aLabel.ForgetAttribute(anArrAttribute); |
1079 | return; |
1080 | } |
1081 | |
1082 | if (anArrAttribute->Array() == theArray) |
1083 | // Backup wont happen but we want it |
1084 | anArrAttribute->Init(1,1); |
1085 | |
1086 | anArrAttribute->ChangeArray( theArray ); |
1087 | } |
1088 | |
1089 | //======================================================================= |
1090 | //function : setArray |
1091 | //purpose : Store theArray on theRank2-th sublabel of theRank1-th sublabel |
1092 | // of the Data label of the object. |
1093 | // If theRank2 is 0 (default), label theRank1 is supposed (not its sublabel). |
1094 | //======================================================================= |
1095 | |
1096 | void TObj_Object::setArray (const Handle(TColStd_HArray1OfExtendedString)& theArray, |
1097 | const Standard_Integer theRank1, |
1098 | const Standard_Integer theRank2) |
1099 | { |
1100 | TDF_Label aLabel = getDataLabel(theRank1,theRank2); |
1101 | Handle(TDataStd_ExtStringArray) anArrAttribute; |
1102 | if (!aLabel.FindAttribute(TDataStd_ExtStringArray::GetID(), anArrAttribute) && |
1103 | !theArray.IsNull()) |
1104 | anArrAttribute = TDataStd_ExtStringArray::Set (aLabel, 1, 1); |
1105 | |
1106 | if (theArray.IsNull()) { |
1107 | // deletion mode |
1108 | if (!anArrAttribute.IsNull()) |
1109 | aLabel.ForgetAttribute(anArrAttribute); |
1110 | return; |
1111 | } |
1112 | |
1113 | if (anArrAttribute->Array() == theArray) |
1114 | // Backup wont happen but we want it |
1115 | anArrAttribute->Init(1,1); |
1116 | |
1117 | anArrAttribute->ChangeArray( theArray ); |
1118 | } |
1119 | |
c5ec7547 |
1120 | //======================================================================= |
1121 | //function : copyTagSources |
1122 | //purpose : copy TagSource attributes on label and its sublabels |
1123 | //======================================================================= |
1124 | |
1125 | static void copyTagSources (const TDF_Label& theSourceLabel, const TDF_Label& theTargetLabel) |
1126 | { |
1127 | // copy tag source on current label |
1128 | Handle(TDF_Attribute) anAttr; |
1129 | if(theSourceLabel.FindAttribute(TDF_TagSource::GetID(), anAttr)) |
1130 | { |
1131 | Handle(TDF_TagSource) aTagSource = Handle(TDF_TagSource)::DownCast(anAttr); |
1132 | Handle(TDF_TagSource) aTargetTagSource = TDF_TagSource::Set(theTargetLabel); |
1133 | aTargetTagSource->Set(aTagSource->Get()); |
1134 | } |
1135 | |
1136 | // copy recursively to sub-labels; note that iteration is made by target label, |
1137 | // to avoid copying tag sources where data are not copied |
1138 | TDF_ChildIterator aLI(theTargetLabel); |
1139 | for(; aLI.More(); aLI.Next()) |
1140 | { |
1141 | TDF_Label aSourceLabel = theSourceLabel.FindChild(aLI.Value().Tag(), Standard_False); |
1142 | if (! aSourceLabel.IsNull()) |
1143 | copyTagSources (aSourceLabel, aLI.Value()); |
1144 | } |
1145 | } |
1146 | |
7fd59977 |
1147 | //======================================================================= |
1148 | //function : Clone |
c5ec7547 |
1149 | //purpose : |
7fd59977 |
1150 | //======================================================================= |
1151 | |
1152 | Handle(TObj_Object) TObj_Object::Clone |
1153 | (const TDF_Label& theTargetLabel, |
1154 | Handle(TDF_RelocationTable) theRelocTable) |
1155 | { |
1156 | Handle(TDF_RelocationTable) aRelocTable = theRelocTable; |
1157 | if (theRelocTable.IsNull()) |
1158 | aRelocTable = new TDF_RelocationTable; |
1159 | Handle(TObj_Object) aNewObj; |
1160 | // take current model for restoring it after creating object. |
1161 | const Handle(TObj_Model)& aCurrentModel = TObj_Assistant::GetCurrentModel(); |
1162 | |
1163 | // take target model |
1164 | Handle(TObj_Model) aTargetModel; |
1165 | TDF_Label aLabel = TDocStd_Document::Get(theTargetLabel)->Main(); |
1166 | Handle(TObj_TModel) aModelAttr; |
1167 | if (aLabel.FindAttribute(TObj_TModel::GetID(), aModelAttr)) |
1168 | aTargetModel = aModelAttr->Model(); |
1169 | |
1170 | if (aCurrentModel != aTargetModel) |
1171 | TObj_Assistant::SetCurrentModel (aTargetModel); |
1172 | // crete new object |
1173 | aNewObj = TObj_Persistence::CreateNewObject (DynamicType()->Name(), theTargetLabel); |
1174 | |
1175 | if (!aNewObj.IsNull()) |
1176 | { |
1177 | TObj_TObject::Set(theTargetLabel,aNewObj); |
1178 | |
1179 | // adding a record to the reloation table |
1180 | aRelocTable->SetRelocation(GetLabel(), theTargetLabel); |
1181 | |
1182 | // now set name of object. |
1183 | const Handle(TCollection_HExtendedString) aCloneName = GetNameForClone( aNewObj ); |
1184 | if( !aCloneName.IsNull() && !aCloneName->IsEmpty() ) |
1185 | aNewObj->SetName( new TCollection_HExtendedString( aCloneName ) ); |
1186 | |
1187 | // copy the data |
1188 | copyData (aNewObj); |
1189 | |
c5ec7547 |
1190 | // copy children |
7fd59977 |
1191 | TDF_Label aTargetLabel = aNewObj->GetChildLabel(); |
1192 | CopyChildren(aTargetLabel, aRelocTable); |
1193 | |
1194 | // copy TagSource for the children |
c5ec7547 |
1195 | copyTagSources (GetChildLabel(), aTargetLabel); |
7fd59977 |
1196 | |
c5ec7547 |
1197 | // copy the references |
7fd59977 |
1198 | if(theRelocTable.IsNull()) |
1199 | CopyReferences(aNewObj, aRelocTable); |
1200 | } |
1201 | |
1202 | // restore the model for persistence. |
1203 | if (aCurrentModel != aTargetModel) |
1204 | TObj_Assistant::SetCurrentModel (aCurrentModel); |
1205 | |
1206 | return aNewObj; |
1207 | } |
1208 | |
1209 | //======================================================================= |
1210 | //function : copyData |
1211 | //purpose : protected |
1212 | //======================================================================= |
1213 | |
1214 | Standard_Boolean TObj_Object::copyData |
1215 | (const Handle(TObj_Object)& theTargetObject) |
1216 | { |
1217 | Standard_Boolean IsDone = Standard_False; |
1218 | if ( !theTargetObject->DynamicType()->SubType( DynamicType() ) ) |
1219 | return IsDone; |
1220 | // init the copier by labels. |
1221 | TDF_Label aDataLabel = GetDataLabel(); |
1222 | TDF_Label aNewDataLabel = theTargetObject->GetDataLabel(); |
1223 | // check if object has any data. |
1224 | if (aDataLabel.IsNull() || aNewDataLabel.IsNull()) |
1225 | return IsDone; |
1226 | |
1227 | TDF_CopyLabel aCopier(aDataLabel, aNewDataLabel); |
1228 | aCopier.Perform(); |
1229 | |
1230 | return aCopier.IsDone(); |
1231 | } |
1232 | |
1233 | //======================================================================= |
1234 | //function : CopyChildren |
1235 | //purpose : |
1236 | //======================================================================= |
1237 | |
1238 | void TObj_Object::CopyChildren |
1239 | (TDF_Label& theTargetLabel, |
1240 | const Handle(TDF_RelocationTable)& theRelocTable) |
1241 | { |
7fd59977 |
1242 | TDF_Label aSourceChildLabel = GetChildLabel(); |
c5ec7547 |
1243 | Handle(TObj_ObjectIterator) aChildren = // GetChildren(); |
1244 | new TObj_OcafObjectIterator (aSourceChildLabel, NULL, Standard_True); // to support children on sublabels of child label |
7fd59977 |
1245 | for(;aChildren->More(); aChildren->Next()) |
1246 | { |
1247 | Handle(TObj_Object) aChild = aChildren->Value(); |
1248 | if(!aChild.IsNull()) |
1249 | { |
7fd59977 |
1250 | // to support childs on sublabels of sublabel of child label |
1251 | TColStd_SequenceOfInteger aTags; |
1252 | TDF_Label aCurChildLab = aChild->GetLabel(); |
1253 | while ( !aCurChildLab.IsNull() && aCurChildLab != aSourceChildLabel ) |
1254 | { |
1255 | aTags.Append( aCurChildLab.Tag() ); |
1256 | aCurChildLab = aCurChildLab.Father(); |
1257 | } |
1258 | TDF_Label aChildLabel = theTargetLabel; |
1259 | for ( Standard_Integer i = aTags.Length(); i > 0 ; i-- ) |
1260 | aChildLabel = aChildLabel.FindChild( aTags.Value( i ), Standard_True ); |
1261 | |
1262 | aChild->Clone(aChildLabel, theRelocTable); |
1263 | } |
1264 | } |
1265 | } |
1266 | |
1267 | //======================================================================= |
1268 | //function : CopyReferences |
1269 | //purpose : |
1270 | //======================================================================= |
1271 | |
1272 | void TObj_Object::CopyReferences |
1273 | (const Handle(TObj_Object)& theTargetObject, |
1274 | const Handle(TDF_RelocationTable)& theRelocTable) |
1275 | { |
1276 | // recursive copy of references |
1277 | Handle(TObj_ObjectIterator) aSrcChildren = //GetChildren(); |
1278 | // to support childs on sublabels of sublabel of child label |
1279 | new TObj_OcafObjectIterator(GetChildLabel(), NULL, Standard_True); |
1280 | for(; aSrcChildren->More(); aSrcChildren->Next()) |
1281 | { |
a9dde4a3 |
1282 | Handle(TObj_Object) aSrcChild = aSrcChildren->Value(); |
7fd59977 |
1283 | TDF_Label aSrcL = aSrcChild->GetLabel(); |
1284 | TDF_Label aDestLabel; |
1285 | if( !theRelocTable->HasRelocation(aSrcL, aDestLabel) ) |
1286 | continue; |
1287 | Handle(TObj_Object) aDstChild; |
1288 | if ( !TObj_Object::GetObj( aDestLabel, aDstChild ) ) |
1289 | continue; |
1290 | if ( aDstChild.IsNull() || !aDstChild->IsAlive() || aSrcChild->DynamicType() != aDstChild->DynamicType() ) |
1291 | continue; // should not be with relocation table |
1292 | |
1293 | aSrcChild->CopyReferences(aDstChild, theRelocTable); |
1294 | } |
1295 | // copy of my references |
1296 | theTargetObject->GetReferenceLabel().ForgetAllAttributes(Standard_True); |
1297 | |
1298 | TDF_Label aTargetLabel = theTargetObject->GetReferenceLabel(); |
1299 | copyReferences(GetReferenceLabel(), aTargetLabel, theRelocTable); |
1300 | } |
1301 | |
1302 | //======================================================================= |
1303 | //function : copyReferences |
1304 | //purpose : protected |
1305 | //======================================================================= |
1306 | |
1307 | void TObj_Object::copyReferences |
1308 | (const TDF_Label& theSourceLabel, |
1309 | TDF_Label& theTargetLabel, |
1310 | const Handle(TDF_RelocationTable)& theRelocTable) |
1311 | { |
1312 | TDF_AttributeIterator anIter(theSourceLabel); |
1313 | for(; anIter.More(); anIter.Next()) |
1314 | { |
1315 | Handle(TDF_Attribute) anAttr = anIter.Value()->NewEmpty(); |
1316 | theTargetLabel.AddAttribute(anAttr); |
1317 | anIter.Value()->Paste(anAttr, theRelocTable); |
1318 | |
1319 | } |
1320 | TDF_ChildIterator aLI(theSourceLabel); |
1321 | TDF_Label aTargetLabel; |
1322 | for(; aLI.More(); aLI.Next()) |
1323 | { |
1324 | aTargetLabel = theTargetLabel.FindChild(aLI.Value().Tag(), Standard_True); |
1325 | copyReferences(aLI.Value(), aTargetLabel, theRelocTable); |
1326 | } |
1327 | } |
1328 | |
1329 | //======================================================================= |
1330 | //function : ReplaceReference |
1331 | //purpose : |
1332 | //======================================================================= |
1333 | |
1334 | void TObj_Object::ReplaceReference (const Handle(TObj_Object)& theOldObject, |
1335 | const Handle(TObj_Object)& theNewObject) |
1336 | { |
1337 | Handle(TObj_LabelIterator) anItr = |
1338 | Handle(TObj_LabelIterator)::DownCast( GetReferences() ); |
1339 | if (anItr.IsNull()) |
1340 | return; |
1341 | // iterates on references. |
1342 | for (; anItr->More(); anItr->Next() ) |
1343 | { |
1344 | Handle(TObj_Object) anObj = anItr->Value(); |
1345 | if (anObj != theOldObject) |
1346 | continue; |
1347 | |
1348 | TDF_Label aRefLabel = anItr->LabelValue(); |
1349 | // if new object is null then simple remove reference. |
1350 | if (theNewObject.IsNull()) |
1351 | { |
1352 | aRefLabel.ForgetAllAttributes(); |
1353 | break; |
1354 | } |
1355 | // set reference to new object. |
1356 | Handle(TObj_Object) me = this; |
1357 | TObj_TReference::Set ( aRefLabel, theNewObject, me); |
1358 | break; |
1359 | } |
1360 | } |
1361 | |
1362 | //======================================================================= |
1363 | //function : IsAlive |
1364 | //purpose : |
1365 | //======================================================================= |
1366 | |
1367 | Standard_Boolean TObj_Object::IsAlive() const |
1368 | { |
1369 | if (myLabel.IsNull()) |
1370 | return Standard_False; |
1371 | |
1372 | Handle(TObj_Object) anObj; |
1373 | if ( !GetObj( myLabel, anObj ) ) |
1374 | return Standard_False; |
1375 | |
1376 | return Standard_True; |
1377 | } |
1378 | |
1379 | //======================================================================= |
1380 | //function : GetFlags |
1381 | //purpose : |
1382 | //======================================================================= |
1383 | |
1384 | Standard_Integer TObj_Object::GetFlags() const |
1385 | { |
1386 | return getInteger(DataTag_Flags); |
1387 | } |
1388 | |
1389 | //======================================================================= |
1390 | //function : SetFlags |
1391 | //purpose : |
1392 | //======================================================================= |
1393 | |
1394 | void TObj_Object::SetFlags(const Standard_Integer theMask) |
1395 | { |
1396 | Standard_Integer aFlags = getInteger(DataTag_Flags); |
1397 | aFlags = aFlags | theMask; |
1398 | setInteger(aFlags, DataTag_Flags); |
1399 | } |
1400 | |
1401 | //======================================================================= |
1402 | //function : TestFlags |
1403 | //purpose : |
1404 | //======================================================================= |
1405 | |
1406 | Standard_Boolean TObj_Object::TestFlags(const Standard_Integer theMask) const |
1407 | { |
1408 | Standard_Integer aFlags = getInteger(DataTag_Flags); |
dde68833 |
1409 | return (aFlags & theMask) != 0; |
7fd59977 |
1410 | } |
1411 | |
1412 | //======================================================================= |
1413 | //function : ClearFlags |
1414 | //purpose : |
1415 | //======================================================================= |
1416 | |
1417 | void TObj_Object::ClearFlags(const Standard_Integer theMask) |
1418 | { |
1419 | Standard_Integer aFlags = getInteger(DataTag_Flags); |
1420 | aFlags = aFlags & (~theMask); |
1421 | setInteger(aFlags, DataTag_Flags); |
1422 | } |
1423 | |
1424 | //======================================================================= |
1425 | //function : RemoveBackReferences |
1426 | //purpose : |
1427 | //======================================================================= |
1428 | |
1429 | Standard_Boolean TObj_Object::RemoveBackReferences(const TObj_DeletingMode theMode) |
1430 | { |
1431 | Handle(TObj_ObjectIterator) aRefs = GetBackReferences(); |
1432 | |
1433 | // Free Object can be deleted in any Mode |
1434 | if ( aRefs.IsNull() || !aRefs->More()) return Standard_True; |
1435 | |
1436 | if( theMode == TObj_FreeOnly) return Standard_False; |
1437 | |
1438 | // Defining the sequence of objects which are referenced to this one. The |
1439 | // first sequence stores containers the second one object with strong |
1440 | // relation. |
1441 | TObj_SequenceOfObject aContainers; |
1442 | TObj_SequenceOfObject aStrongs; |
1443 | Handle(TObj_Object) aMe = this; |
1444 | |
1445 | // Sorting the referencing objects |
1446 | for( ; aRefs->More() ; aRefs->Next()) |
1447 | { |
1448 | Handle(TObj_Object) anObject = aRefs->Value(); |
1449 | if ( anObject.IsNull() || !anObject->IsAlive() ) |
1450 | continue; |
1451 | if ( anObject->CanRemoveReference(aMe) ) |
1452 | aContainers.Append(anObject); |
1453 | else |
1454 | aStrongs.Append(anObject); |
1455 | } |
1456 | // Can not be removed without deletion of referenced objects mode |
1457 | if( theMode == TObj_KeepDepending && aStrongs.Length() > 0 ) |
1458 | return Standard_False; |
1459 | // Delete or link off the referencing objects |
1460 | Standard_Integer i; |
1461 | Handle(TDF_Data) anOwnData = GetLabel().Data(); |
1462 | for (i = 1; i <= aContainers.Length(); i++) |
1463 | { |
1464 | Handle(TObj_Object) anObj = aContainers(i); |
1465 | if ( anObj.IsNull() || anObj->GetLabel().IsNull() ) |
1466 | continue; // undead object on dead label |
1467 | Handle(TDF_Data) aData = anObj->GetLabel().Data(); |
1468 | Standard_Boolean aModifMode = aData->IsModificationAllowed(); |
1469 | if ( anOwnData != aData ) |
1470 | aData->AllowModification( Standard_True ); |
1471 | anObj->RemoveReference(aMe); |
1472 | if ( anOwnData != aData ) |
1473 | aData->AllowModification( aModifMode ); |
1474 | } |
1475 | /* PTv 21.11.2006 |
1476 | object from other document refers to current object and must be killed |
1477 | when current object become dead for just want to remove references to it |
1478 | if ( theMode != TObj_Forced ) // cause leads to exception when |
1479 | // try to remove objects during close document |
1480 | */ |
1481 | for (i = 1; i <= aStrongs.Length(); i++) |
1482 | { |
1483 | Handle(TObj_Object) anObj = aStrongs(i); |
1484 | if ( anObj.IsNull() || anObj->GetLabel().IsNull() ) |
1485 | continue; // undead object on dead label |
1486 | Handle(TDF_Data) aData = anObj->GetLabel().Data(); |
1487 | Standard_Boolean aModifMode = aData->IsModificationAllowed(); |
1488 | if ( anOwnData != aData ) |
1489 | aData->AllowModification( Standard_True ); |
1490 | anObj->Detach(theMode); |
1491 | if ( anOwnData != aData ) |
1492 | aData->AllowModification( aModifMode ); |
1493 | } |
1494 | |
1495 | return Standard_True; |
1496 | } |
1497 | |
1498 | //======================================================================= |
1499 | //function : RelocateReferences |
1500 | //purpose : Make that each reference pointing to a descendant label of |
1501 | // theFromRoot to point to an equivalent label under theToRoot. |
1502 | // Return False if a resulting reference does not point to |
1503 | // an TObj_Object |
1504 | //Example : |
1505 | // a referred object label = 0:3:24:7:2:7 |
1506 | // theFromRoot = 0:3:24 |
1507 | // theToRoot = 0:2 |
1508 | // a new referred label = 0:2:7:2:7 |
1509 | //======================================================================= |
1510 | |
1511 | Standard_Boolean TObj_Object::RelocateReferences |
1512 | (const TDF_Label& theFromRoot, |
1513 | const TDF_Label& theToRoot, |
1514 | const Standard_Boolean theUpdateBackRefs) |
1515 | { |
1516 | TDF_ChildIDIterator aRefIt (GetReferenceLabel(), |
1517 | TObj_TReference::GetID(), |
1518 | Standard_True ); |
1519 | Handle(TObj_Object) anObj; |
1520 | for ( ; aRefIt.More(); aRefIt.Next() ) |
1521 | { |
1522 | Handle(TObj_TReference) aRef = |
1523 | Handle(TObj_TReference)::DownCast( aRefIt.Value() ); |
1524 | |
1525 | TDF_Label aNewLabel, aLabel = aRef->GetLabel(); |
1526 | if ( aLabel.Data() != theFromRoot.Data() || |
1527 | aLabel.IsDescendant( theToRoot )) |
1528 | continue; // need not to relocate |
1529 | |
1530 | TDF_Tool::RelocateLabel( aLabel, theFromRoot, theToRoot, aNewLabel ); |
1531 | if ( aNewLabel.IsNull() || !TObj_Object::GetObj( aNewLabel, anObj )) |
1532 | return Standard_False; |
1533 | |
1534 | // care of back references |
1535 | if (theUpdateBackRefs) |
1536 | { |
1537 | Handle(TObj_Object) me = this; |
1538 | // a new referred object |
1539 | anObj->AddBackReference( me ); |
1540 | // an old object |
1541 | anObj = aRef->Get(); |
1542 | if (!anObj.IsNull()) |
1543 | anObj->RemoveBackReference( me ); |
1544 | } |
1545 | |
1546 | aRef->Set( aNewLabel, aRef->GetMasterLabel() ); |
1547 | } |
1548 | |
1549 | return Standard_True; |
1550 | } |
1551 | |
1552 | //======================================================================= |
1553 | //function : GetBadReference |
1554 | //purpose : |
1555 | //======================================================================= |
1556 | |
1557 | Standard_Boolean TObj_Object::GetBadReference |
1558 | (const TDF_Label& theRoot, |
1559 | TDF_Label& theBadReference) const |
1560 | { |
1561 | TDF_ChildIDIterator aRefIt (GetReferenceLabel(), |
1562 | TObj_TReference::GetID(), |
1563 | Standard_True ); |
1564 | Handle(TObj_Object) anObj; |
1565 | for ( ; aRefIt.More(); aRefIt.Next() ) |
1566 | { |
1567 | Handle(TObj_TReference) aRef = |
1568 | Handle(TObj_TReference)::DownCast( aRefIt.Value() ); |
1569 | |
1570 | TDF_Label aLabel = aRef->GetLabel(); |
1571 | if ( aLabel.Data() == theRoot.Data() && |
1572 | !aLabel.IsDescendant( theRoot )) |
1573 | { |
1574 | theBadReference = aLabel; |
1575 | return Standard_True; |
1576 | } |
1577 | } |
1578 | |
1579 | return Standard_False; |
1580 | } |
1581 | |
1582 | //======================================================================= |
1583 | //function : TypeFlags |
1584 | //purpose : |
1585 | //======================================================================= |
1586 | |
1587 | Standard_Integer TObj_Object::GetTypeFlags() const |
1588 | { |
1589 | return Visible; |
1590 | } |
1591 | |
1592 | //======================================================================= |
1593 | //function : GetDictionary |
1594 | //purpose : default implementation |
1595 | //======================================================================= |
1596 | |
1597 | Handle(TObj_TNameContainer) TObj_Object::GetDictionary() const |
1598 | { |
1599 | Handle(TObj_Model) aModel = GetModel(); |
1600 | if ( !aModel.IsNull() ) |
1601 | return aModel->GetDictionary(); |
1602 | return NULL; |
1603 | } |
1604 | |
1605 | //======================================================================= |
1606 | //function : SetOrder |
1607 | //purpose : |
1608 | //======================================================================= |
1609 | |
1610 | Standard_Boolean TObj_Object::SetOrder( const Standard_Integer& theIndx ) |
1611 | { |
1612 | setInteger( theIndx, DataTag_Order ); |
1613 | return Standard_True; |
1614 | } |
1615 | |
1616 | //======================================================================= |
1617 | //function : GetOrder |
1618 | //purpose : |
1619 | //======================================================================= |
1620 | |
1621 | Standard_Integer TObj_Object::GetOrder() const |
1622 | { |
1623 | Standard_Integer order = getInteger( DataTag_Order ); |
1624 | if ( !order ) |
1625 | order = GetLabel().Tag(); |
1626 | return order; |
1627 | } |