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