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