0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / TDocStd / TDocStd_Document.cxx
1 // Copyright (c) 2006-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <TDocStd_Document.hxx>
15
16 #include <CDM_Document.hxx>
17 #include <CDM_MetaData.hxx>
18 #include <Standard_Dump.hxx>
19 #include <Standard_Type.hxx>
20 #include <TCollection_AsciiString.hxx>
21 #include <TCollection_ExtendedString.hxx>
22 #include <TDF_AttributeDelta.hxx>
23 #include <TDF_AttributeDeltaList.hxx>
24 #include <TDF_AttributeIterator.hxx>
25 #include <TDF_AttributeList.hxx>
26 #include <TDF_Data.hxx>
27 #include <TDF_Delta.hxx>
28 #include <TDF_IDMap.hxx>
29 #include <TDF_Label.hxx>
30 #include <TDF_ListIteratorOfAttributeDeltaList.hxx>
31 #include <TDF_ListIteratorOfAttributeList.hxx>
32 #include <TDF_ListIteratorOfDeltaList.hxx>
33 #include <TDF_Reference.hxx>
34 #include <TDocStd.hxx>
35 #include <TDocStd_Application.hxx>
36 #include <TDocStd_CompoundDelta.hxx>
37 #include <TDocStd_Context.hxx>
38 #include <TDocStd_LabelIDMapDataMap.hxx>
39 #include <TDocStd_Modified.hxx>
40 #include <TDocStd_Owner.hxx>
41 #include <TDocStd_XLink.hxx>
42 #include <TDocStd_XLinkIterator.hxx>
43
44 IMPLEMENT_STANDARD_RTTIEXT(TDocStd_Document,CDM_Document)
45
46 // List should have a RemoveLast...
47 #define TDocStd_List_RemoveLast(theList) \
48 TDF_ListIteratorOfDeltaList it(theList); \
49 Standard_Integer i,n = theList.Extent(); \
50 for (i = 1; i < n; i++) it.Next(); \
51 theList.Remove(it);
52
53 #undef DEB_TRANS
54
55 #undef DEB_DELTA
56
57 #define SRN_DELTA_COMPACT
58
59 //=======================================================================
60 //function : Get
61 //purpose  : 
62 //=======================================================================
63
64 Handle(TDocStd_Document) TDocStd_Document::Get (const TDF_Label& acces)
65 {
66   // avoid creation of Handle(TDF_Data) during TDF_Data destruction
67   if (acces.Root().HasAttribute()) {
68     return TDocStd_Owner::GetDocument(acces.Data());
69   }
70   return Handle(TDocStd_Document)();
71 }
72
73 //=======================================================================
74 //function : TDocStd_Document
75 //purpose  : 
76 //=======================================================================
77
78
79 TDocStd_Document::TDocStd_Document(const TCollection_ExtendedString& aStorageFormat) :
80 myStorageFormat(aStorageFormat),
81 myData (new TDF_Data()),
82 myUndoLimit(0),
83 myUndoTransaction ("UNDO"),
84 mySaveTime(0),
85 myIsNestedTransactionMode(0),
86 mySaveEmptyLabels(Standard_False)
87 {
88   myUndoTransaction.Initialize (myData);
89   TDocStd_Owner::SetDocument(myData,this);
90
91 #ifdef SRN_DELTA_COMPACT
92   myFromUndo.Nullify();
93   myFromRedo.Nullify();
94 #endif
95 }
96
97
98 //=======================================================================
99 //function : IsSaved
100 //purpose  : 
101 //=======================================================================
102
103 Standard_Boolean TDocStd_Document::IsSaved() const
104 {
105   return CDM_Document::IsStored();
106 }
107
108
109 //=======================================================================
110 //function : GetName
111 //purpose  : 
112 //=======================================================================
113
114 TCollection_ExtendedString TDocStd_Document::GetName () const
115 {
116   return CDM_Document::MetaData()->Name();
117 }
118
119 //=======================================================================
120 //function : GetPath
121 //purpose  : 
122 //=======================================================================
123
124 TCollection_ExtendedString TDocStd_Document::GetPath () const
125 {
126   return CDM_Document::MetaData()->Path();
127 }
128
129
130 //=======================================================================
131 //function : SetData
132 //purpose  : 
133 //=======================================================================
134
135 void TDocStd_Document::SetData (const Handle(TDF_Data)& D)
136 {
137   myData = D;
138   myUndoTransaction.Initialize (myData);
139 }
140
141 //=======================================================================
142 //function : GetData
143 //purpose  : 
144 //=======================================================================
145
146 Handle(TDF_Data) TDocStd_Document::GetData () const
147 {
148   return myData;
149 }
150
151 //=======================================================================
152 //function : Main
153 //purpose  : 
154 //=======================================================================
155
156 TDF_Label TDocStd_Document::Main () const
157
158   return  myData->Root().FindChild(1,Standard_True);
159 }
160
161 //=======================================================================
162 //function : IsEmpty
163 //purpose  : 
164 //=======================================================================
165
166 Standard_Boolean TDocStd_Document::IsEmpty() const
167 {
168   TDF_AttributeIterator It (Main());
169   return !It.More();
170 }
171
172 //=======================================================================
173 //function : IsValid
174 //purpose  : 
175 //=======================================================================
176
177 Standard_Boolean TDocStd_Document::IsValid() const
178 {
179   return TDocStd_Modified::IsEmpty(Main());
180 }
181
182 //=======================================================================
183 //function : SetModified
184 //purpose  : 
185 //=======================================================================
186
187 void TDocStd_Document::SetModified (const TDF_Label& L)                                  
188 {  
189   TDocStd_Modified::Add(L);
190 }
191
192 //=======================================================================
193 //function : IsModified
194 //purpose  : 
195 //=======================================================================
196 //Standard_Boolean TDocStd_Document::IsModified (const TDF_Label& L) const                                 
197 //{  
198 //  return TDocStd_Modified::Contains(L);
199 //}
200
201 //=======================================================================
202 //function : PurgeModified
203 //purpose  : 
204 //=======================================================================
205
206 void TDocStd_Document::PurgeModified()
207 {   
208   TDocStd_Modified::Clear(Main()); 
209 }
210
211 //=======================================================================
212 //function : GetModified
213 //purpose  : 
214 //=======================================================================
215
216 const TDF_LabelMap&  TDocStd_Document::GetModified() const
217 {  
218   return TDocStd_Modified::Get(Main());  
219 }
220
221
222
223 //=======================================================================
224 //function : Update
225 //purpose  : 
226 //=======================================================================
227
228 void TDocStd_Document::Update(const Handle(CDM_Document)& /*aToDocument*/,
229                                const Standard_Integer aReferenceIdentifier,
230                                const Standard_Address aModifContext) 
231 {
232   const TDocStd_Context* CC = static_cast<TDocStd_Context*> (aModifContext);
233   if (CC->ModifiedReferences() || !IsUpToDate(aReferenceIdentifier)) {
234     TCollection_AsciiString aDocEntry(aReferenceIdentifier);
235     UpdateReferences(aDocEntry);
236     SetIsUpToDate(aReferenceIdentifier);
237   }
238 }
239
240 //=======================================================================
241 //function : NewCommand
242 //purpose  : 
243 //=======================================================================
244
245 void TDocStd_Document::NewCommand()
246 {
247 #ifdef OCCT_DEBUG_TRANS
248   if (myUndoTransaction.IsOpen() && myData->Transaction() > 1) {
249     throw Standard_DomainError("NewCommand : many open transactions");
250   }
251 #endif
252
253   CommitTransaction();
254   OpenTransaction();
255
256 #ifdef OCCT_DEBUG_TRANS
257   std::cout<<"End NewCommand"<<std::endl;
258 #endif
259 }
260
261
262 //=======================================================================
263 //function : HasOpenCommand
264 //purpose  : 
265 //=======================================================================
266 Standard_Boolean TDocStd_Document::HasOpenCommand() const
267 {
268   return myUndoTransaction.IsOpen();
269 }
270
271 //=======================================================================
272 //function : OpenCommand
273 //purpose  : 
274 //=======================================================================
275
276 void TDocStd_Document::OpenCommand ()
277 {
278   if (!myIsNestedTransactionMode && myUndoTransaction.IsOpen()) {
279     throw Standard_DomainError("TDocStd_Document::OpenCommand : already open");
280   }
281   OpenTransaction();
282 //  if (myUndoLimit != 0) myUndoTransaction.Open();
283 }
284
285 //=======================================================================
286 //function : CommitCommand
287 //purpose  : 
288 //=======================================================================
289
290 Standard_Boolean TDocStd_Document::CommitCommand ()
291 {
292   return CommitTransaction();
293 }
294
295
296 //=======================================================================
297 //function : AbortCommand
298 //purpose  : 
299 //=======================================================================
300
301 void TDocStd_Document::AbortCommand ()
302
303   AbortTransaction();
304 }
305
306
307 //=======================================================================
308 //function : CommitTransaction
309 //purpose  : Private method.
310 //=======================================================================
311
312 Standard_Boolean TDocStd_Document::CommitTransaction()
313 {
314   myData->AllowModification(Standard_True);
315
316   Standard_Boolean isDone = Standard_False;
317   // nested transaction mode
318   if (myIsNestedTransactionMode && myUndoTransaction.IsOpen()) {
319
320     Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
321     Handle(TDocStd_CompoundDelta) aCompDelta =
322       Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
323     AppendDeltaToTheFirst(aCompDelta, D);
324     D = aCompDelta;
325     myUndoFILO.RemoveFirst();
326     if(myUndoFILO.Extent()) {
327       aCompDelta = Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
328       AppendDeltaToTheFirst(aCompDelta, D);
329       myUndoTransaction.Open();
330     }
331     else {
332       if(!D->IsEmpty()) {
333         myUndos.Append(D);
334         myRedos.Clear(); // if we push an Undo we clear the redos
335         isDone = Standard_True;
336       }
337     }
338
339     // deny modifications if the transaction is not opened
340     if(myOnlyTransactionModification) {
341       myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
342                                 ? Standard_True :Standard_False);
343     }
344
345   } else {
346
347   // are we undoing...
348     if (myUndoLimit != 0 && myUndoTransaction.IsOpen()) {
349
350       Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
351       if (!(D.IsNull() || D->IsEmpty())) {
352         isDone = Standard_True;
353
354         myRedos.Clear(); // if we push an Undo we clear the redos
355         myUndos.Append(D); // New undos are at the end of the list
356         // Check  the limit to remove the oldest one
357         if (myUndos.Extent() > myUndoLimit) {
358 #ifdef SRN_DELTA_COMPACT
359           Handle(TDF_Delta) aDelta = myUndos.First();
360 #endif
361           myUndos.RemoveFirst();
362 #ifdef SRN_DELTA_COMPACT
363           if(myFromUndo == aDelta) {
364             //The oldest Undo delta coincides with `from` delta
365             if(myUndos.Extent() == 1) {   //There is the only Undo
366               myFromUndo.Nullify();
367               myFromRedo.Nullify();
368             }
369             else
370               myFromUndo = myUndos.First();
371           }
372 #endif
373         }
374       }
375
376     }
377
378     // deny or allow modifications acording to transaction state
379     if(myOnlyTransactionModification) {
380       myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
381                                  ? Standard_True :Standard_False);
382     }
383   }
384   // Notify CDM_Application of the successful commit
385   if (isDone && IsOpened()) {
386     const Handle(TDocStd_Application) anAppli =
387       Handle(TDocStd_Application)::DownCast(Application());
388     if (!anAppli.IsNull())
389       anAppli -> OnCommitTransaction (this);
390   }
391   return isDone;
392 }
393
394
395 //=======================================================================
396 //function : AbortTransaction
397 //purpose  : Private method.
398 //=======================================================================
399
400 void TDocStd_Document::AbortTransaction()
401 {
402   myData->AllowModification(Standard_True);
403   
404   if (myUndoTransaction.IsOpen())
405     if (myUndoLimit != 0)
406       myUndoTransaction.Abort();
407
408   if (myIsNestedTransactionMode && myUndoFILO.Extent()) {
409     if (!myUndoFILO.First()->IsEmpty())
410       myData->Undo(myUndoFILO.First(),Standard_True);
411     myUndoFILO.RemoveFirst();
412     if (myUndoFILO.Extent())
413       myUndoTransaction.Open();
414   }
415   // deny or allow modifications acording to transaction state
416   if (myOnlyTransactionModification) {
417     myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
418                                ? Standard_True :Standard_False);
419   }
420   // Notify CDM_Application of the event
421   if (IsOpened()) {
422     const Handle(TDocStd_Application) anAppli =
423       Handle(TDocStd_Application)::DownCast(Application());
424     if (!anAppli.IsNull())
425       anAppli -> OnAbortTransaction (this);
426   }
427 }
428
429
430 //=======================================================================
431 //function :OpenTransaction
432 //purpose  : Private method.
433 //=======================================================================
434
435 void TDocStd_Document::OpenTransaction()
436 {
437   myData->AllowModification(Standard_True);
438
439   // nested transaction mode
440   if (myIsNestedTransactionMode) {
441
442     if (myUndoTransaction.IsOpen()) {
443       Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
444       Handle(TDocStd_CompoundDelta) aCompDelta =
445         Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
446       AppendDeltaToTheFirst(aCompDelta, D);
447     }
448     Standard_Integer aLastTime = myData->Time();
449     if (myUndoFILO.Extent())
450       aLastTime = myUndoFILO.First()->EndTime();
451     Handle(TDocStd_CompoundDelta) aCompoundDelta =
452       new TDocStd_CompoundDelta;
453     aCompoundDelta->Validity(aLastTime, aLastTime);
454     myUndoFILO.Prepend(aCompoundDelta);
455   } 
456
457   if (myUndoLimit != 0) myUndoTransaction.Open();
458
459   // deny or allow modifications acording to transaction state
460   if (myOnlyTransactionModification) {
461     myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
462                                ? Standard_True :Standard_False);
463   }
464   // Notify CDM_Application of the event
465   if (IsOpened()) {
466     const Handle(TDocStd_Application) anAppli =
467       Handle(TDocStd_Application)::DownCast(Application());
468     if (!anAppli.IsNull())
469       anAppli -> OnOpenTransaction (this);
470   }
471 }
472
473 //=======================================================================
474 //function : SetUndoLimit
475 //purpose  : 
476 //=======================================================================
477
478 void TDocStd_Document::SetUndoLimit(const Standard_Integer L)
479 {  
480 #ifdef SRN_DELTA_COMPACT
481   myFromUndo.Nullify();  //Compaction has to aborted
482   myFromRedo.Nullify();
483 #endif
484
485   CommitTransaction ();
486   myUndoLimit = (L > 0) ? L : 0;
487   Standard_Integer n = myUndos.Extent() - myUndoLimit;
488   while (n > 0) {
489     myUndos.RemoveFirst();
490     --n;
491   }
492   // deny or allow modifications acording to transaction state
493   if(myOnlyTransactionModification) {
494     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
495                               ? Standard_True :Standard_False);
496   }
497   //OpenTransaction(); dp 15/10/99
498 }
499
500 //=======================================================================
501 //function : GetUndoLimit
502 //purpose  : 
503 //=======================================================================
504
505 Standard_Integer TDocStd_Document::GetUndoLimit() const
506 {
507   return myUndoLimit;
508 }
509
510 //=======================================================================
511 //function : Undos
512 //purpose  : 
513 //=======================================================================
514
515 Standard_Integer TDocStd_Document::GetAvailableUndos() const
516 {
517   return myUndos.Extent();
518 }
519
520 //=======================================================================
521 //function : ClearUndos
522 //purpose  : 
523 //=======================================================================
524
525 void TDocStd_Document::ClearUndos()
526 {
527   myUndos.Clear();
528   myRedos.Clear();
529 #ifdef SRN_DELTA_COMPACT
530   myFromRedo.Nullify();
531   myFromUndo.Nullify();
532 #endif
533 }
534
535 //=======================================================================
536 //function : ClearRedos
537 //purpose  : 
538 //=======================================================================
539
540 void TDocStd_Document::ClearRedos()
541 {
542   myRedos.Clear();
543 #ifdef SRN_DELTA_COMPACT
544   myFromRedo.Nullify();
545 #endif
546 }
547
548 //=======================================================================
549 //function : Undo
550 //purpose  : 
551 // Some importante notice:
552 // 1) The most recent undo delta is at the end of the list.
553 // 2) Removing the LAST item of a list is tedious, but it is done only on
554 //    Undo. Remove first is done at each command if the limit is reached!
555 // 3) To make fun, the redos are not like the undos: the most recent delta
556 //    is at the beginning! Like this, it is easier to remove it after use.
557 //=======================================================================
558 Standard_Boolean TDocStd_Document::Undo() 
559 {
560   // Don't call NewCommand(), because it may commit Interactive Attributes
561   // and generate a undesirable Delta!
562
563   Standard_Boolean isOpened = myUndoTransaction.IsOpen();
564   Standard_Boolean undoDone = Standard_False;
565   //TDF_Label currentObjectLabel = CurrentLabel (); //Sauve pour usage ulterieur.
566
567   if (!myUndos.IsEmpty()) {
568     // Reset the transaction
569     AbortTransaction();
570
571     // only for nested transaction mode
572     while(myIsNestedTransactionMode && myUndoFILO.Extent())
573       AbortTransaction();
574
575     // allow modifications
576     myData->AllowModification(Standard_True);
577
578     // Apply the Undo
579     // should test the applicability before.
580 #ifdef OCCT_DEBUG_DELTA
581     std::cout<<"DF before Undo =================================="<<std::endl; TDF_Tool::DeepDump(std::cout,myData);
582 #endif
583     Handle(TDF_Delta) D = myData->Undo(myUndos.Last(),Standard_True);
584     D->SetName(myUndos.Last()->Name());
585 #ifdef OCCT_DEBUG_DELTA
586     std::cout<<"DF after Undo =================================="<<std::endl; TDF_Tool::DeepDump(std::cout,myData);
587 #endif
588     // Push the redo
589     myRedos.Prepend(D);
590     // Remove the last Undo
591     TDocStd_List_RemoveLast(myUndos);
592     undoDone = Standard_True;
593   }
594
595   if (isOpened && undoDone) OpenTransaction();
596
597   // deny or allow modifications acording to transaction state
598   if(myOnlyTransactionModification) {
599     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
600                               ? Standard_True :Standard_False);
601   }
602   
603   return undoDone;
604 }
605
606 //=======================================================================
607 //function : GetAvailableRedos
608 //purpose  : 
609 //=======================================================================
610
611 Standard_Integer TDocStd_Document:: GetAvailableRedos() const
612 {
613   // should test the applicability before.
614   return myRedos.Extent();
615 }
616
617 //=======================================================================
618 //function : Redo
619 //purpose  : 
620 //=======================================================================
621 Standard_Boolean TDocStd_Document::Redo() 
622 {
623   Standard_Boolean isOpened = myUndoTransaction.IsOpen();
624   Standard_Boolean undoDone = Standard_False;
625   // TDF_Label currentObjectLabel = CurrentLabel();//Sauve pour usage ulterieur.
626   if (!myRedos.IsEmpty()) {
627     // should test the applicability before.
628     // Reset the transaction
629     AbortTransaction();
630
631     // only for nested transaction mode
632     while(myIsNestedTransactionMode && myUndoFILO.Extent())
633       AbortTransaction();
634
635     // allow modifications
636     myData->AllowModification(Standard_True);
637
638     // Apply the Redo
639 #ifdef OCCT_DEBUG_DELTA
640     std::cout<<"DF before Redo =================================="<<std::endl; TDF_Tool::DeepDump(std::cout,myData);
641 #endif
642     Handle(TDF_Delta) D = myData->Undo(myRedos.First(),Standard_True);
643     D->SetName(myRedos.First()->Name());
644 #ifdef OCCT_DEBUG_DELTA
645     std::cout<<"DF after Redo =================================="<<std::endl; TDF_Tool::DeepDump(std::cout,myData);
646 #endif
647     // Push the redo of the redo as an undo (got it !)
648     myUndos.Append(D);
649     // remove the Redo from the head
650     myRedos.RemoveFirst();
651     undoDone = Standard_True;
652   }
653   
654   if (isOpened && undoDone) OpenTransaction();
655
656   // deny or allow modifications acording to transaction state
657   if(myOnlyTransactionModification) {
658     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
659                               ? Standard_True :Standard_False);
660   }
661
662   return undoDone;
663 }
664
665 //=======================================================================
666 //function : UpdateReferences
667 //purpose  : 
668 //=======================================================================
669
670 void TDocStd_Document::UpdateReferences(const TCollection_AsciiString& aDocEntry) 
671 {
672
673   TDF_AttributeList aRefList;
674   TDocStd_XLink* xRefPtr;
675   for (TDocStd_XLinkIterator xItr (this); xItr.More(); xItr.Next()) {
676     xRefPtr = xItr.Value();
677     if (xRefPtr->DocumentEntry() == aDocEntry) {
678       aRefList.Append(xRefPtr->Update());
679     }
680   }
681   TDF_ListIteratorOfAttributeList It(aRefList);
682   for (;It.More();It.Next()) {
683     //     // mise a jour import
684     SetModified(It.Value()->Label());
685   }
686 }
687
688
689 //=======================================================================
690 //function : GetUndos
691 //purpose  : 
692 //=======================================================================
693
694 const TDF_DeltaList& TDocStd_Document::GetUndos() const 
695 {
696   return myUndos;
697 }
698
699
700 //=======================================================================
701 //function : GetRedos
702 //purpose  : 
703 //=======================================================================
704
705 const TDF_DeltaList& TDocStd_Document::GetRedos() const 
706 {
707   return myRedos;
708 }
709
710 //=======================================================================
711 //function : InitDeltaCompaction
712 //purpose  : 
713 //=======================================================================
714
715 Standard_Boolean TDocStd_Document::InitDeltaCompaction()
716 {
717 #ifdef SRN_DELTA_COMPACT
718   if (myUndoLimit == 0 || myUndos.Extent() == 0) {
719     myFromRedo.Nullify();
720     myFromUndo.Nullify();
721     return Standard_False; //No Undos to compact
722   }
723
724   myFromRedo.Nullify();
725
726   myFromUndo = myUndos.Last();
727   if(myRedos.Extent() > 0) myFromRedo = myRedos.First();
728 #endif
729   return Standard_True;
730 }
731
732 //=======================================================================
733 //function : PerformDeltaCompaction
734 //purpose  : 
735 //=======================================================================
736
737 Standard_Boolean TDocStd_Document::PerformDeltaCompaction()  
738
739 #ifdef SRN_DELTA_COMPACT
740   if(myFromUndo.IsNull()) return Standard_False;  //Redo can be Null for this operation 
741
742   TDF_DeltaList aList; 
743   Handle(TDocStd_CompoundDelta) aCompoundDelta = new TDocStd_CompoundDelta; 
744   TDF_ListIteratorOfDeltaList anIterator(myUndos); 
745   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator;
746   TDocStd_LabelIDMapDataMap aMap; 
747   Standard_Boolean isFound = Standard_False, isTimeSet = Standard_False; 
748
749   //Process Undos
750
751   for(; anIterator.More(); anIterator.Next()) { 
752     if(!isFound) { 
753       if(myFromUndo == anIterator.Value()) isFound = Standard_True; 
754       aList.Append(anIterator.Value());  //Fill the list of deltas that precede compound delta 
755       continue;
756     } 
757
758     if(!isTimeSet) {  //Set begin and end time when the compound delta is valid
759       aCompoundDelta->Validity(anIterator.Value()->BeginTime(), myUndos.Last()->EndTime());
760       isTimeSet = Standard_True;
761     } 
762     
763     aDeltasIterator.Initialize(anIterator.Value()->AttributeDeltas());
764     for(; aDeltasIterator.More(); aDeltasIterator.Next()) {   
765       if(!aMap.IsBound(aDeltasIterator.Value()->Label())) {
766         TDF_IDMap* pIDMap = new TDF_IDMap();
767         aMap.Bind(aDeltasIterator.Value()->Label(), *pIDMap);
768         delete pIDMap;
769         }
770       if(aMap(aDeltasIterator.Value()->Label()).Add(aDeltasIterator.Value()->ID())) //The attribute is not 
771         aCompoundDelta->AddAttributeDelta(aDeltasIterator.Value());                 //already in the delta
772     }
773   } 
774
775   myUndos.Clear(); 
776   myUndos.Assign(aList); 
777   myUndos.Append(aCompoundDelta); 
778
779   //Process Redos
780
781   if(myFromRedo.IsNull()) {
782     myRedos.Clear();
783     return Standard_True;
784   }
785
786   aList.Clear();
787
788   for(anIterator.Initialize(myRedos); anIterator.More(); anIterator.Next()) { 
789     aList.Append(anIterator.Value()); 
790     if(anIterator.Value() == myFromRedo) break;
791   }
792
793   myRedos.Clear();
794   myRedos.Assign(aList); 
795 #endif
796   return Standard_True; 
797
798
799
800 //=======================================================================
801 //function : StorageFormat
802 //purpose  : 
803 //=======================================================================
804
805 TCollection_ExtendedString TDocStd_Document::StorageFormat() const 
806 {
807   return myStorageFormat;
808 }
809
810
811 //=======================================================================
812 //function : ChangeStorageFormat
813 //purpose  : 
814 //=======================================================================
815
816 void TDocStd_Document::ChangeStorageFormat (const TCollection_ExtendedString& newStorageFormat) 
817 {
818   if (newStorageFormat != myStorageFormat) {
819     myStorageFormat = newStorageFormat;
820     myResourcesAreLoaded = Standard_False;
821     CDM_Document::LoadResources ();
822   }
823 }
824
825
826
827
828 //=======================================================================
829 //function : Recompute
830 //purpose  : 
831 //=======================================================================
832
833 void TDocStd_Document::Recompute ()
834 {
835   if (IsValid()) return;
836   // find the top function and execute it
837   //  Handle(TDesign_Function) F;
838   //  if (Main().FindAttribute(TDesign_Function::GetID(),F)) {
839   // TFunction_Solver slv;
840   // slv.SetTouched(GetModified());
841   // slv.ExecuteFrom(F);
842   PurgeModified();
843 }
844
845 //=======================================================================
846 //function : AppendDeltaToTheFirst
847 //purpose  : Appends delta to the first delta in the myUndoFILO
848 //=======================================================================
849
850 void TDocStd_Document::AppendDeltaToTheFirst
851   (const Handle(TDocStd_CompoundDelta)& theDelta1,
852    const Handle(TDF_Delta)& theDelta2)
853 {
854   if(theDelta2->IsEmpty()) return;
855   TDocStd_LabelIDMapDataMap aMap; 
856     
857   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator1
858     (theDelta1->AttributeDeltas());
859   for(; aDeltasIterator1.More(); aDeltasIterator1.Next()) {   
860     TDF_Label aLabel = aDeltasIterator1.Value()->Label();
861     if(!aMap.IsBound(aLabel)) {
862       TDF_IDMap aTmpIDMap;
863       aMap.Bind(aLabel, aTmpIDMap);
864     }
865     Standard_GUID anID = aDeltasIterator1.Value()->ID();
866     TDF_IDMap& anIDMap = aMap.ChangeFind(aLabel);
867     anIDMap.Add(anID);
868   }
869   
870   theDelta1->Validity(theDelta1->BeginTime(), theDelta2->EndTime());
871   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator2
872     (theDelta2->AttributeDeltas());
873   for(; aDeltasIterator2.More(); aDeltasIterator2.Next()) {   
874     TDF_Label aLabel = aDeltasIterator2.Value()->Label();
875     Standard_GUID anID = aDeltasIterator2.Value()->ID();
876     if(aMap.IsBound(aLabel)) {
877       const TDF_IDMap& anIDMap = aMap.Find(aLabel);
878       if(anIDMap.Contains(anID)) continue;
879     }
880     theDelta1->AddAttributeDelta(aDeltasIterator2.Value());
881   }
882 }
883
884 //=======================================================================
885 //function : RemoveFirstUndo
886 //purpose  : 
887 //=======================================================================
888 void TDocStd_Document::RemoveFirstUndo() {
889   if (myUndos.IsEmpty()) return;
890   myUndos.RemoveFirst();
891 }
892
893 //=======================================================================
894 //function : BeforeClose
895 //purpose  : 
896 //=======================================================================
897 void TDocStd_Document::BeforeClose() 
898 {
899   SetModificationMode(Standard_False);
900   AbortTransaction();
901   if(myIsNestedTransactionMode)
902          myUndoFILO.Clear();
903   ClearUndos();
904 }
905
906 //=======================================================================
907 //function : DumpJson
908 //purpose  : 
909 //=======================================================================
910 void TDocStd_Document::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
911 {
912   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
913
914   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, CDM_Document)
915   
916   OCCT_DUMP_FIELD_VALUE_STRING (theOStream, myStorageFormat)
917
918   for (TDF_DeltaList::Iterator anUndoIt (myUndos); anUndoIt.More(); anUndoIt.Next())
919   {
920     const Handle(TDF_Delta)& anUndo = anUndoIt.Value();
921     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anUndo.get())
922   }
923
924   for (TDF_DeltaList::Iterator aRedoIt (myRedos); aRedoIt.More(); aRedoIt.Next())
925   {
926     const Handle(TDF_Delta)& aRedo = aRedoIt.Value();
927     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aRedo.get())
928   }
929
930   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myData.get())
931   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myUndoLimit)
932   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myUndoTransaction)
933   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myFromUndo.get())
934   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myFromRedo.get())
935   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySaveTime)
936   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsNestedTransactionMode)
937
938   for (TDF_DeltaList::Iterator anUndoFILOIt (myUndoFILO); anUndoFILOIt.More(); anUndoFILOIt.Next())
939   {
940     const Handle(TDF_Delta)& anUndoFILO = anUndoFILOIt.Value();
941     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anUndoFILO.get())
942   }
943
944   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myOnlyTransactionModification)
945   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySaveEmptyLabels)
946 }