Integration of OCCT 6.5.0 from SVN
[occt.git] / src / TDocStd / TDocStd_MultiTransactionManager.cxx
1 // File:      TDocStd_MultiTransactionManager.cxx
2 // Created:   19.11.02 16:41:50
3 // Author:    Vladimir ANIKIN
4 // Copyright: Open CASCADE 2002
5
6 #include <TDocStd_MultiTransactionManager.ixx>
7 #include <TDocStd_Document.hxx>
8 #include <TDocStd_ApplicationDelta.hxx>
9
10 //=======================================================================
11 //function : TDocStd_MultiTransactionManager
12 //purpose  : Constructor
13 //=======================================================================
14
15 TDocStd_MultiTransactionManager::TDocStd_MultiTransactionManager ()
16 {
17   myUndoLimit = 0;
18   myOpenTransaction = Standard_False;
19   myIsNestedTransactionMode = Standard_False;
20   myOnlyTransactionModification = Standard_False;
21 }
22
23 //=======================================================================
24 //function : SetUndoLimit
25 //purpose  : 
26 //=======================================================================
27
28 void TDocStd_MultiTransactionManager::SetUndoLimit(const Standard_Integer theLimit)
29 {
30   myUndoLimit = theLimit;
31
32   CommitCommand ();
33   
34   Standard_Integer n = myUndos.Length() - myUndoLimit;
35   while (n > 0) {
36     RemoveLastUndo();
37     --n;
38   }
39
40   Standard_Integer i;
41   for(i = myDocuments.Length(); i > 0; i--)
42     myDocuments.Value(i)->SetUndoLimit(myUndoLimit);
43
44 }
45
46 //=======================================================================
47 //function : Undo
48 //purpose  : 
49 //=======================================================================
50
51 void TDocStd_MultiTransactionManager::Undo()
52 {
53   if (myUndos.IsEmpty()) return;
54   const TDocStd_SequenceOfDocument& docs = myUndos.First()->GetDocuments();
55   Standard_Integer i;
56   for (i = docs.Length(); i > 0; i--) {
57     Handle(TDocStd_Document) doc = docs.Value(i);
58     if (doc.IsNull() || doc->GetAvailableUndos() == 0) continue;
59     doc->Undo();
60   }
61   myRedos.Prepend(myUndos.First());
62   myUndos.Remove(1);
63   myOpenTransaction = Standard_False;
64 }
65
66 //=======================================================================
67 //function : Redo
68 //purpose  : 
69 //=======================================================================
70
71 void TDocStd_MultiTransactionManager::Redo() {
72   if (myRedos.IsEmpty()) return;
73   const TDocStd_SequenceOfDocument& docs = myRedos.First()->GetDocuments();
74   Standard_Integer i;
75   for (i = docs.Length(); i > 0; i--) {
76     Handle(TDocStd_Document) doc = docs.Value(i);
77     if (doc.IsNull() || doc->GetAvailableRedos() == 0) continue;
78     doc->Redo();
79   }
80   myUndos.Prepend(myRedos.First());
81   myRedos.Remove(1);
82   myOpenTransaction = Standard_False;
83 }
84
85 //=======================================================================
86 //function : OpenCommand
87 //purpose  : 
88 //=======================================================================
89
90 void TDocStd_MultiTransactionManager::OpenCommand() {
91   if (myOpenTransaction) {
92 #ifdef DEB
93     cout << "TDocStd_MultiTransactionManager::OpenCommand(): "
94             "Can't start new application transaction while a "
95             "previous one is not commited or aborted" << endl;
96 #endif
97     Standard_Failure::Raise("Can't start new application transaction"
98                             "while a previous one is not commited or aborted");
99   }
100   myOpenTransaction = Standard_True;
101   Standard_Integer i;
102   for(i = myDocuments.Length(); i > 0; i--) {
103     while(myDocuments.Value(i)->HasOpenCommand())
104       myDocuments.Value(i)->AbortCommand();
105     myDocuments.Value(i)->OpenCommand();
106   }
107 }
108
109 //=======================================================================
110 //function : AbortCommand
111 //purpose  : 
112 //=======================================================================
113
114 void TDocStd_MultiTransactionManager::AbortCommand() {
115   myOpenTransaction = Standard_False;
116   Standard_Integer i;
117   for(i = myDocuments.Length(); i > 0; i--) {
118     while(myDocuments.Value(i)->HasOpenCommand())
119       myDocuments.Value(i)->AbortCommand();
120   }
121 }
122
123 //=======================================================================
124 //function : CommitCommand
125 //purpose  : 
126 //=======================================================================
127
128 Standard_Boolean TDocStd_MultiTransactionManager::CommitCommand()
129 {
130   Handle(TDocStd_ApplicationDelta) aDelta = new TDocStd_ApplicationDelta;
131   Standard_Boolean isCommited = Standard_False;
132   Standard_Integer i;
133   for(i = myDocuments.Length(); i > 0; i--) {
134     isCommited = Standard_False;
135     while(myDocuments.Value(i)->HasOpenCommand())
136       if (myDocuments.Value(i)->CommitCommand())
137         isCommited = Standard_True;
138     if(isCommited) {
139       aDelta->GetDocuments().Append(myDocuments.Value(i));
140     }
141   }
142   
143   if (aDelta->GetDocuments().Length()) {
144     myUndos.Prepend(aDelta);
145     if (myUndos.Length() > myUndoLimit) {
146       RemoveLastUndo();
147     }
148     myRedos.Clear();
149     isCommited = Standard_True;
150   }
151   myOpenTransaction = Standard_False;
152   return isCommited;
153 }
154
155 //=======================================================================
156 //function : CommitCommand
157 //purpose  : 
158 //=======================================================================
159
160 Standard_Boolean TDocStd_MultiTransactionManager::CommitCommand
161                         (const TCollection_ExtendedString& theName)
162 {
163   Standard_Boolean isCommited = CommitCommand();
164   if (isCommited && myUndos.Length())
165     myUndos.First()->SetName(theName);
166   return isCommited;
167 }
168
169 //=======================================================================
170 //function : DumpTransaction
171 //purpose  : 
172 //=======================================================================
173
174 void TDocStd_MultiTransactionManager::DumpTransaction(Standard_OStream& anOS) const
175 {
176   Standard_Integer i;
177   if(myDocuments.Length() == 0)
178     anOS << "Manager is empty" << endl;
179   else {
180     if(myDocuments.Length() == 1)
181       anOS << "There is one document ( ";
182     else
183       anOS << "There are " << myDocuments.Length() << " documents ( ";
184     for(i = 1; i <= myDocuments.Length(); i++) {
185       Handle(Standard_Transient) aDoc = myDocuments.Value(i);
186       anOS << "\"" << (Standard_Transient*)aDoc;
187       anOS << "\" ";
188     }
189     anOS << ") in the manager "  << endl;
190
191     if(myIsNestedTransactionMode)
192       anOS << "Nested transaction mode is on" << endl;
193     else
194       anOS << "Nested transaction mode is off" << endl;
195
196     anOS << " " << endl;
197   }
198
199   for (i = myUndos.Length(); i > 0; i--) {
200     Handle(TDocStd_ApplicationDelta) delta = myUndos.Value(i);
201     anOS<<" Undo: ";
202     delta->Dump(anOS);
203     if (i == 1) {
204       anOS<<"  < Last action"<<endl;
205     } else {
206       anOS<<endl;
207     }
208   }
209   for (i = 1; i <= myRedos.Length(); i++) {
210     Handle(TDocStd_ApplicationDelta) delta = myRedos.Value(i);
211     anOS<<" Redo: ";
212     delta->Dump(anOS);
213     anOS<<endl;
214   }
215 }
216
217 //=======================================================================
218 //function : RemoveLastUndo
219 //purpose  : 
220 //=======================================================================
221
222 void TDocStd_MultiTransactionManager::RemoveLastUndo()
223 {
224   if(myUndos.Length() == 0) return;
225   const TDocStd_SequenceOfDocument& docs = myUndos.Last()->GetDocuments();
226   Standard_Integer i;
227   for (i = 1; i <= docs.Length(); i++) {
228     docs.Value(i)->RemoveFirstUndo();
229   }
230   myUndos.Remove(myUndos.Length());
231 }
232
233 //=======================================================================
234 //function : AddDocument
235 //purpose  : 
236 //=======================================================================
237
238 void TDocStd_MultiTransactionManager::AddDocument
239   (const Handle(TDocStd_Document)& theDoc)
240 {
241   Standard_Integer i;
242   for(i = myDocuments.Length(); i > 0; i--)
243     if(myDocuments.Value(i) == theDoc)
244       return; // the document is already added to the list
245
246   if(theDoc->IsNestedTransactionMode() !=
247      myIsNestedTransactionMode)
248     theDoc->SetNestedTransactionMode(myIsNestedTransactionMode);
249
250   theDoc->SetModificationMode(myOnlyTransactionModification);
251   
252   myDocuments.Append(theDoc);
253   theDoc->SetUndoLimit(myUndoLimit);
254   if(myOpenTransaction) {
255     if(!theDoc->HasOpenCommand())
256       theDoc->OpenCommand();
257   }
258   else {
259     if(theDoc->HasOpenCommand())
260       theDoc->CommitCommand();
261   }
262   theDoc->ClearUndos();
263   theDoc->ClearRedos();
264 }
265
266 //=======================================================================
267 //function : RemoveDocument
268 //purpose  : 
269 //=======================================================================
270
271 void TDocStd_MultiTransactionManager::RemoveDocument
272   (const Handle(TDocStd_Document)& theDoc)
273 {
274   Standard_Integer i;
275   for(i = myDocuments.Length(); i > 0; i--) {
276     if(myDocuments.Value(i) == theDoc)
277       myDocuments.Remove(i);
278   }
279   for (i = myUndos.Length(); i > 0; i--) {
280     Handle(TDocStd_ApplicationDelta) delta = myUndos.Value(i);
281     TDocStd_SequenceOfDocument& docs = delta->GetDocuments();
282     for(Standard_Integer j = docs.Length(); j > 0; j--) {
283       if(docs.Value(j) == theDoc) {
284         docs.Remove(j);
285         if(docs.Length() == 0)
286           myUndos.Remove(i);
287       }
288     }
289   }
290   for (i = myRedos.Length(); i > 0; i--) {
291     Handle(TDocStd_ApplicationDelta) delta = myRedos.Value(i);
292     TDocStd_SequenceOfDocument& docs = delta->GetDocuments();
293     for(Standard_Integer j = docs.Length(); j > 0; j--) {
294       if(docs.Value(j) == theDoc) {
295         docs.Remove(j);
296         if(docs.Length() == 0)
297           myRedos.Remove(i);
298       }
299     }
300   }
301 }
302
303 //=======================================================================
304 //function : SetNestedTransactionMode
305 //purpose  : 
306 //=======================================================================
307
308 void TDocStd_MultiTransactionManager::SetNestedTransactionMode
309   (const Standard_Boolean isAllowed)
310 {
311   myIsNestedTransactionMode = isAllowed;
312   Standard_Integer i;
313   for(i = myDocuments.Length(); i > 0; i--) {
314     if(myDocuments.Value(i)->IsNestedTransactionMode() != myIsNestedTransactionMode)
315       myDocuments.Value(i)->SetNestedTransactionMode(myIsNestedTransactionMode);
316   }
317 }
318
319 //=======================================================================
320 //function : SetModificationMode
321 //purpose  : if theTransactionOnly is True changes is denied outside transactions
322 //=======================================================================
323
324 void TDocStd_MultiTransactionManager::SetModificationMode
325   (const Standard_Boolean theTransactionOnly)
326 {
327   myOnlyTransactionModification = theTransactionOnly;
328
329   Standard_Integer i;
330   for(i = myDocuments.Length(); i > 0; i--) {
331     myDocuments.Value(i)->SetModificationMode(myOnlyTransactionModification);
332   }
333 }
334
335 //=======================================================================
336 //function : ClearUndos
337 //purpose  : 
338 //=======================================================================
339
340 void TDocStd_MultiTransactionManager::ClearUndos()
341 {
342   AbortCommand();
343
344   myUndos.Clear();
345   Standard_Integer i;
346   for(i = myDocuments.Length(); i > 0; i--) {
347     myDocuments.Value(i)->ClearUndos();
348   }
349 }
350
351 //=======================================================================
352 //function : ClearRedos
353 //purpose  : 
354 //=======================================================================
355
356 void TDocStd_MultiTransactionManager::ClearRedos()
357 {
358   AbortCommand();
359
360   myRedos.Clear();
361   Standard_Integer i;
362   for(i = myDocuments.Length(); i > 0; i--) {
363     myDocuments.Value(i)->ClearRedos();
364   }
365 }
366
367
368