1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 // INCLUDE --------------------------------------------------------------- 30 31 #include <vcl/virdev.hxx> 32 33 #include "undobase.hxx" 34 #include "refundo.hxx" 35 #include "docsh.hxx" 36 #include "tabvwsh.hxx" 37 #include "undoolk.hxx" 38 #include "undodraw.hxx" 39 #include "dbcolect.hxx" 40 #include "attrib.hxx" 41 #include "queryparam.hxx" 42 #include "globstr.hrc" 43 44 // STATIC DATA ----------------------------------------------------------- 45 46 TYPEINIT1(ScSimpleUndo, SfxUndoAction); 47 TYPEINIT1(ScBlockUndo, ScSimpleUndo); 48 TYPEINIT1(ScMoveUndo, ScSimpleUndo); 49 TYPEINIT1(ScDBFuncUndo, ScSimpleUndo); 50 TYPEINIT1(ScUndoWrapper, SfxUndoAction); 51 52 // ----------------------------------------------------------------------- 53 54 ScSimpleUndo::ScSimpleUndo( ScDocShell* pDocSh ) : 55 pDocShell( pDocSh ), 56 pDetectiveUndo( NULL ) 57 { 58 } 59 60 __EXPORT ScSimpleUndo::~ScSimpleUndo() 61 { 62 delete pDetectiveUndo; 63 } 64 65 bool ScSimpleUndo::SetViewMarkData( const ScMarkData& rMarkData ) 66 { 67 if ( IsPaintLocked() ) 68 return false; 69 70 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 71 if ( !pViewShell ) 72 return false; 73 74 pViewShell->SetMarkData( rMarkData ); 75 return true; 76 } 77 78 sal_Bool __EXPORT ScSimpleUndo::Merge( SfxUndoAction *pNextAction ) 79 { 80 // Zu jeder Undo-Action kann eine SdrUndoGroup fuer das Aktualisieren 81 // der Detektiv-Pfeile gehoeren. 82 // DetectiveRefresh kommt immer hinterher, die SdrUndoGroup ist in 83 // eine ScUndoDraw Action verpackt. 84 // Nur beim automatischen Aktualisieren wird AddUndoAction mit 85 // bTryMerg=sal_True gerufen. 86 87 if ( !pDetectiveUndo && pNextAction->ISA(ScUndoDraw) ) 88 { 89 // SdrUndoAction aus der ScUndoDraw Action uebernehmen, 90 // ScUndoDraw wird dann vom UndoManager geloescht 91 92 ScUndoDraw* pCalcUndo = (ScUndoDraw*)pNextAction; 93 pDetectiveUndo = pCalcUndo->GetDrawUndo(); 94 pCalcUndo->ForgetDrawUndo(); 95 return sal_True; 96 } 97 98 return sal_False; 99 } 100 101 void ScSimpleUndo::BeginUndo() 102 { 103 pDocShell->SetInUndo( sal_True ); 104 105 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 106 if (pViewShell) 107 pViewShell->HideAllCursors(); // z.B. wegen zusammengefassten Zellen 108 109 // detective updates happened last, must be undone first 110 if (pDetectiveUndo) 111 pDetectiveUndo->Undo(); 112 } 113 114 void ScSimpleUndo::EndUndo() 115 { 116 pDocShell->SetDocumentModified(); 117 118 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 119 if (pViewShell) 120 { 121 pViewShell->UpdateAutoFillMark(); 122 pViewShell->UpdateInputHandler(); 123 pViewShell->ShowAllCursors(); 124 } 125 126 pDocShell->SetInUndo( sal_False ); 127 } 128 129 void ScSimpleUndo::BeginRedo() 130 { 131 pDocShell->SetInUndo( sal_True ); //! eigenes Flag fuer Redo? 132 133 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 134 if (pViewShell) 135 pViewShell->HideAllCursors(); // z.B. wegen zusammengefassten Zellen 136 } 137 138 void ScSimpleUndo::EndRedo() 139 { 140 if (pDetectiveUndo) 141 pDetectiveUndo->Redo(); 142 143 pDocShell->SetDocumentModified(); 144 145 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 146 if (pViewShell) 147 { 148 pViewShell->UpdateAutoFillMark(); 149 pViewShell->UpdateInputHandler(); 150 pViewShell->ShowAllCursors(); 151 } 152 153 pDocShell->SetInUndo( sal_False ); 154 } 155 156 void ScSimpleUndo::ShowTable( SCTAB nTab ) // static 157 { 158 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 159 if (pViewShell) 160 pViewShell->SetTabNo( nTab ); 161 } 162 163 void ScSimpleUndo::ShowTable( const ScRange& rRange ) // static 164 { 165 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 166 if (pViewShell) 167 { 168 SCTAB nStart = rRange.aStart.Tab(); 169 SCTAB nEnd = rRange.aEnd.Tab(); 170 SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); 171 if ( nTab < nStart || nTab > nEnd ) // wenn nicht im Bereich: 172 pViewShell->SetTabNo( nStart ); // auf erste des Bereiches 173 } 174 } 175 176 177 // ----------------------------------------------------------------------- 178 179 ScBlockUndo::ScBlockUndo( ScDocShell* pDocSh, const ScRange& rRange, 180 ScBlockUndoMode eBlockMode ) : 181 ScSimpleUndo( pDocSh ), 182 aBlockRange( rRange ), 183 eMode( eBlockMode ) 184 { 185 pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); 186 } 187 188 __EXPORT ScBlockUndo::~ScBlockUndo() 189 { 190 DeleteSdrUndoAction( pDrawUndo ); 191 } 192 193 void ScBlockUndo::BeginUndo() 194 { 195 ScSimpleUndo::BeginUndo(); 196 EnableDrawAdjust( pDocShell->GetDocument(), sal_False ); 197 } 198 199 void ScBlockUndo::EndUndo() 200 { 201 if (eMode == SC_UNDO_AUTOHEIGHT) 202 AdjustHeight(); 203 204 EnableDrawAdjust( pDocShell->GetDocument(), sal_True ); 205 DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); 206 207 ShowBlock(); 208 ScSimpleUndo::EndUndo(); 209 } 210 211 /* 212 void ScBlockUndo::BeginRedo() 213 { 214 ScSimpleUndo::BeginRedo(); 215 } 216 */ 217 218 void ScBlockUndo::EndRedo() 219 { 220 if (eMode == SC_UNDO_AUTOHEIGHT) 221 AdjustHeight(); 222 223 ShowBlock(); 224 ScSimpleUndo::EndRedo(); 225 } 226 227 sal_Bool ScBlockUndo::AdjustHeight() 228 { 229 ScDocument* pDoc = pDocShell->GetDocument(); 230 231 VirtualDevice aVirtDev; 232 Fraction aZoomX( 1, 1 ); 233 Fraction aZoomY = aZoomX; 234 double nPPTX, nPPTY; 235 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 236 if (pViewShell) 237 { 238 ScViewData* pData = pViewShell->GetViewData(); 239 nPPTX = pData->GetPPTX(); 240 nPPTY = pData->GetPPTY(); 241 aZoomX = pData->GetZoomX(); 242 aZoomY = pData->GetZoomY(); 243 } 244 else 245 { 246 // Zoom auf 100 lassen 247 nPPTX = ScGlobal::nScreenPPTX; 248 nPPTY = ScGlobal::nScreenPPTY; 249 } 250 251 sal_Bool bRet = pDoc->SetOptimalHeight( aBlockRange.aStart.Row(), aBlockRange.aEnd.Row(), 252 /*!*/ aBlockRange.aStart.Tab(), 0, &aVirtDev, 253 nPPTX, nPPTY, aZoomX, aZoomY, sal_False ); 254 255 if (bRet) 256 pDocShell->PostPaint( 0, aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(), 257 MAXCOL, MAXROW, aBlockRange.aEnd.Tab(), 258 PAINT_GRID | PAINT_LEFT ); 259 260 return bRet; 261 } 262 263 void ScBlockUndo::ShowBlock() 264 { 265 if ( IsPaintLocked() ) 266 return; 267 268 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); 269 if (pViewShell) 270 { 271 ShowTable( aBlockRange ); // bei mehreren Tabs im Range ist jede davon gut 272 pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), 273 SC_FOLLOW_JUMP, sal_False, sal_False ); 274 SCTAB nTab = pViewShell->GetViewData()->GetTabNo(); 275 ScRange aRange = aBlockRange; 276 aRange.aStart.SetTab( nTab ); 277 aRange.aEnd.SetTab( nTab ); 278 pViewShell->MarkRange( aRange ); 279 280 // nicht per SetMarkArea an MarkData, wegen evtl. fehlendem Paint 281 } 282 } 283 284 285 // ----------------------------------------------------------------------- 286 287 ScMoveUndo::ScMoveUndo( ScDocShell* pDocSh, ScDocument* pRefDoc, ScRefUndoData* pRefData, 288 ScMoveUndoMode eRefMode ) : 289 ScSimpleUndo( pDocSh ), 290 pRefUndoDoc( pRefDoc ), 291 pRefUndoData( pRefData ), 292 eMode( eRefMode ) 293 { 294 ScDocument* pDoc = pDocShell->GetDocument(); 295 if (pRefUndoData) 296 pRefUndoData->DeleteUnchanged(pDoc); 297 pDrawUndo = GetSdrUndoAction( pDoc ); 298 } 299 300 __EXPORT ScMoveUndo::~ScMoveUndo() 301 { 302 delete pRefUndoData; 303 delete pRefUndoDoc; 304 DeleteSdrUndoAction( pDrawUndo ); 305 } 306 307 void ScMoveUndo::UndoRef() 308 { 309 ScDocument* pDoc = pDocShell->GetDocument(); 310 ScRange aRange(0,0,0, MAXCOL,MAXROW,pRefUndoDoc->GetTableCount()-1); 311 pRefUndoDoc->CopyToDocument( aRange, IDF_FORMULA, sal_False, pDoc, NULL, sal_False ); 312 if (pRefUndoData) 313 pRefUndoData->DoUndo( pDoc, (eMode == SC_UNDO_REFFIRST) ); 314 // #65055# HACK: ScDragDropUndo ist der einzige mit REFFIRST. 315 // Falls nicht, resultiert daraus evtl. ein zu haeufiges Anpassen 316 // der ChartRefs, nicht schoen, aber auch nicht schlecht.. 317 } 318 319 void ScMoveUndo::BeginUndo() 320 { 321 ScSimpleUndo::BeginUndo(); 322 323 EnableDrawAdjust( pDocShell->GetDocument(), sal_False ); 324 325 if (pRefUndoDoc && eMode == SC_UNDO_REFFIRST) 326 UndoRef(); 327 } 328 329 void ScMoveUndo::EndUndo() 330 { 331 //@17.12.97 Reihenfolge der Fkt.s geaendert 332 DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() ); // #125875# must also be called when pointer is null 333 334 if (pRefUndoDoc && eMode == SC_UNDO_REFLAST) 335 UndoRef(); 336 337 EnableDrawAdjust( pDocShell->GetDocument(), sal_True ); 338 339 ScSimpleUndo::EndUndo(); 340 } 341 342 /* 343 void ScMoveUndo::BeginRedo() 344 { 345 ScSimpleUndo::BeginRedo(); 346 } 347 */ 348 349 /* 350 void ScMoveUndo::EndRedo() 351 { 352 ScSimpleUndo::EndRedo(); 353 } 354 */ 355 356 // ----------------------------------------------------------------------- 357 358 ScDBFuncUndo::ScDBFuncUndo( ScDocShell* pDocSh, const ScRange& rOriginal, SdrUndoAction* pDrawUndo ) : 359 ScSimpleUndo( pDocSh ), 360 aOriginalRange( rOriginal ), 361 mpDrawUndo( pDrawUndo ) 362 { 363 pAutoDBRange = pDocSh->GetOldAutoDBRange(); 364 } 365 366 ScDBFuncUndo::~ScDBFuncUndo() 367 { 368 DeleteSdrUndoAction( mpDrawUndo ); 369 delete pAutoDBRange; 370 } 371 372 void ScDBFuncUndo::SetDrawUndoAction( SdrUndoAction* pDrawUndo ) 373 { 374 DeleteSdrUndoAction( mpDrawUndo ); 375 mpDrawUndo = pDrawUndo; 376 } 377 378 void ScDBFuncUndo::BeginUndo() 379 { 380 ScSimpleUndo::BeginUndo(); 381 DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() ); 382 } 383 384 void ScDBFuncUndo::EndUndo() 385 { 386 ScSimpleUndo::EndUndo(); 387 388 if ( pAutoDBRange ) 389 { 390 sal_uInt16 nNoNameIndex; 391 ScDocument* pDoc = pDocShell->GetDocument(); 392 ScDBCollection* pColl = pDoc->GetDBCollection(); 393 if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) ) 394 { 395 ScDBData* pNoNameData = (*pColl)[nNoNameIndex]; 396 397 SCCOL nRangeX1; 398 SCROW nRangeY1; 399 SCCOL nRangeX2; 400 SCROW nRangeY2; 401 SCTAB nRangeTab; 402 pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); 403 pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); 404 405 *pNoNameData = *pAutoDBRange; 406 407 if ( pAutoDBRange->HasAutoFilter() ) 408 { 409 // restore AutoFilter buttons 410 pAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); 411 pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO ); 412 pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID ); 413 } 414 } 415 } 416 } 417 418 void ScDBFuncUndo::BeginRedo() 419 { 420 RedoSdrUndoAction( mpDrawUndo ); 421 if ( pAutoDBRange ) 422 { 423 // move the database range to this function's position again (see ScDocShell::GetDBData) 424 425 sal_uInt16 nNoNameIndex; 426 ScDocument* pDoc = pDocShell->GetDocument(); 427 ScDBCollection* pColl = pDoc->GetDBCollection(); 428 if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) ) 429 { 430 ScDBData* pNoNameData = (*pColl)[nNoNameIndex]; 431 432 SCCOL nRangeX1; 433 SCROW nRangeY1; 434 SCCOL nRangeX2; 435 SCROW nRangeY2; 436 SCTAB nRangeTab; 437 pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); 438 pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); 439 440 pNoNameData->SetSortParam( ScSortParam() ); 441 pNoNameData->SetQueryParam( ScQueryParam() ); 442 pNoNameData->SetSubTotalParam( ScSubTotalParam() ); 443 444 pNoNameData->SetArea( aOriginalRange.aStart.Tab(), 445 aOriginalRange.aStart.Col(), aOriginalRange.aStart.Row(), 446 aOriginalRange.aEnd.Col(), aOriginalRange.aEnd.Row() ); 447 448 pNoNameData->SetByRow( sal_True ); 449 pNoNameData->SetAutoFilter( sal_False ); 450 // header is always set with the operation in redo 451 } 452 } 453 454 ScSimpleUndo::BeginRedo(); 455 } 456 457 void ScDBFuncUndo::EndRedo() 458 { 459 ScSimpleUndo::EndRedo(); 460 } 461 462 // ----------------------------------------------------------------------- 463 464 ScUndoWrapper::ScUndoWrapper( SfxUndoAction* pUndo ) : 465 pWrappedUndo( pUndo ) 466 { 467 } 468 469 ScUndoWrapper::~ScUndoWrapper() 470 { 471 delete pWrappedUndo; 472 } 473 474 void ScUndoWrapper::ForgetWrappedUndo() 475 { 476 pWrappedUndo = NULL; // don't delete in dtor - pointer must be stored outside 477 } 478 479 String ScUndoWrapper::GetComment() const 480 { 481 if (pWrappedUndo) 482 return pWrappedUndo->GetComment(); 483 else 484 return String(); 485 } 486 487 String ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const 488 { 489 if (pWrappedUndo) 490 return pWrappedUndo->GetRepeatComment(rTarget); 491 else 492 return String(); 493 } 494 495 sal_uInt16 ScUndoWrapper::GetId() const 496 { 497 if (pWrappedUndo) 498 return pWrappedUndo->GetId(); 499 else 500 return 0; 501 } 502 503 sal_Bool ScUndoWrapper::IsLinked() 504 { 505 if (pWrappedUndo) 506 return pWrappedUndo->IsLinked(); 507 else 508 return sal_False; 509 } 510 511 void ScUndoWrapper::SetLinked( sal_Bool bIsLinked ) 512 { 513 if (pWrappedUndo) 514 pWrappedUndo->SetLinked(bIsLinked); 515 } 516 517 sal_Bool ScUndoWrapper::Merge( SfxUndoAction* pNextAction ) 518 { 519 if (pWrappedUndo) 520 return pWrappedUndo->Merge(pNextAction); 521 else 522 return sal_False; 523 } 524 525 void ScUndoWrapper::Undo() 526 { 527 if (pWrappedUndo) 528 pWrappedUndo->Undo(); 529 } 530 531 void ScUndoWrapper::Redo() 532 { 533 if (pWrappedUndo) 534 pWrappedUndo->Redo(); 535 } 536 537 void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget) 538 { 539 if (pWrappedUndo) 540 pWrappedUndo->Repeat(rTarget); 541 } 542 543 sal_Bool ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const 544 { 545 if (pWrappedUndo) 546 return pWrappedUndo->CanRepeat(rTarget); 547 else 548 return sal_False; 549 } 550 551 552