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