0024023: Revamp the OCCT Handle -- general
[occt.git] / src / TDocStd / TDocStd_MultiTransactionManager.cxx
CommitLineData
b311480e 1// Created on: 2002-11-19
2// Created by: Vladimir ANIKIN
973c2be1 3// Copyright (c) 2002-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.
7fd59977 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
25TDocStd_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
38void 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
61void 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
81void 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
100void TDocStd_MultiTransactionManager::OpenCommand() {
101 if (myOpenTransaction) {
0797d9d3 102#ifdef OCCT_DEBUG
7fd59977 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
124void 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
138Standard_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
170Standard_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
184void 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);
c04c30b3 196 anOS << "\"" << aDoc.get();
7fd59977 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
232void 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
248void 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
281void 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
318void 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
334void 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
350void 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
366void 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