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