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 "scitems.hxx" 32 #include <editeng/eeitem.hxx> 33 34 35 #include <vcl/timer.hxx> 36 #include <vcl/msgbox.hxx> 37 #include <sfx2/app.hxx> 38 #include <sfx2/viewfrm.hxx> 39 #include <sfx2/bindings.hxx> 40 #include <sfx2/childwin.hxx> 41 42 #include "attrib.hxx" 43 #include "pagedata.hxx" 44 #include "tabview.hxx" 45 #include "tabvwsh.hxx" 46 #include "printfun.hxx" 47 #include "stlpool.hxx" 48 #include "docsh.hxx" 49 #include "gridwin.hxx" 50 #include "olinewin.hxx" 51 #include "uiitems.hxx" 52 #include "sc.hrc" 53 #include "viewutil.hxx" 54 #include "colrowba.hxx" 55 #include "waitoff.hxx" 56 #include "globstr.hrc" 57 #include "scmod.hxx" 58 59 #define SC_BLOCKMODE_NONE 0 60 #define SC_BLOCKMODE_NORMAL 1 61 #define SC_BLOCKMODE_OWN 2 62 63 64 65 // 66 // Markier - Funktionen 67 // 68 69 void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) 70 { 71 if (!ValidCol(nStartCol)) nStartCol = MAXCOL; 72 if (!ValidRow(nStartRow)) nStartRow = MAXROW; 73 if (!ValidCol(nEndCol)) nEndCol = MAXCOL; 74 if (!ValidRow(nEndRow)) nEndRow = MAXROW; 75 76 sal_Bool bLeft = (nStartCol==0 && nEndCol==MAXCOL); 77 sal_Bool bTop = (nStartRow==0 && nEndRow==MAXROW); 78 79 if (bLeft) 80 PaintLeftArea( nStartRow, nEndRow ); 81 if (bTop) 82 PaintTopArea( nStartCol, nEndCol ); 83 84 aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, 85 aViewData.GetTabNo() ); 86 PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS ); 87 } 88 89 sal_Bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 90 { 91 return bIsBlockMode 92 && nBlockStartX == nCol 93 && nBlockStartY == nRow 94 && nBlockStartZ == nTab; 95 } 96 97 void ScTabView::InitOwnBlockMode() 98 { 99 if (!bIsBlockMode) 100 { 101 // Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen: 102 103 ScMarkData& rMark = aViewData.GetMarkData(); 104 if (!rMark.IsMarked() && !rMark.IsMultiMarked()) 105 GetSelEngine()->CursorPosChanging( sal_False, sal_False ); 106 107 // bIsBlockMode = sal_True; 108 bIsBlockMode = SC_BLOCKMODE_OWN; //! Variable umbenennen! 109 nBlockStartX = 0; 110 nBlockStartY = 0; 111 nBlockStartZ = 0; 112 nBlockEndX = 0; 113 nBlockEndY = 0; 114 nBlockEndZ = 0; 115 116 SelectionChanged(); // Status wird mit gesetzer Markierung abgefragt 117 } 118 } 119 120 void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, 121 sal_Bool bTestNeg, sal_Bool bCols, sal_Bool bRows ) 122 { 123 if (!bIsBlockMode) 124 { 125 if (!ValidCol(nCurX)) nCurX = MAXCOL; 126 if (!ValidRow(nCurY)) nCurY = MAXROW; 127 128 ScMarkData& rMark = aViewData.GetMarkData(); 129 SCTAB nTab = aViewData.GetTabNo(); 130 131 // Teil von Markierung aufheben? 132 if (bTestNeg) 133 { 134 if ( bCols ) 135 bBlockNeg = rMark.IsColumnMarked( nCurX ); 136 else if ( bRows ) 137 bBlockNeg = rMark.IsRowMarked( nCurY ); 138 else 139 bBlockNeg = rMark.IsCellMarked( nCurX, nCurY ); 140 } 141 else 142 bBlockNeg = sal_False; 143 rMark.SetMarkNegative(bBlockNeg); 144 145 // bIsBlockMode = sal_True; 146 bIsBlockMode = SC_BLOCKMODE_NORMAL; //! Variable umbenennen! 147 bBlockCols = bCols; 148 bBlockRows = bRows; 149 nBlockStartX = nBlockStartXOrig = nCurX; 150 nBlockStartY = nBlockStartYOrig = nCurY; 151 nBlockStartZ = nCurZ; 152 nBlockEndX = nOldCurX = nBlockStartX; 153 nBlockEndY = nOldCurY = nBlockStartY; 154 nBlockEndZ = nBlockStartZ; 155 156 if (bBlockCols) 157 { 158 nBlockStartY = nBlockStartYOrig = 0; 159 nBlockEndY = MAXROW; 160 } 161 162 if (bBlockRows) 163 { 164 nBlockStartX = nBlockStartXOrig = 0; 165 nBlockEndX = MAXCOL; 166 } 167 168 rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) ); 169 170 #ifdef OLD_SELECTION_PAINT 171 InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY ); 172 #endif 173 UpdateSelectionOverlay(); 174 175 bNewStartIfMarking = sal_False; // use only once 176 } 177 } 178 179 void ScTabView::SetNewStartIfMarking() 180 { 181 bNewStartIfMarking = sal_True; 182 } 183 184 void ScTabView::DoneBlockMode( sal_Bool bContinue ) // Default FALSE 185 { 186 // Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird, 187 // wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat. 188 // Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird. 189 190 if (bIsBlockMode && !bMoveIsShift) 191 { 192 ScMarkData& rMark = aViewData.GetMarkData(); 193 sal_Bool bFlag = rMark.GetMarkingFlag(); 194 rMark.SetMarking(sal_False); 195 196 if (bBlockNeg && !bContinue) 197 rMark.MarkToMulti(); 198 199 if (bContinue) 200 rMark.MarkToMulti(); 201 else 202 { 203 // Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode 204 // aus SetTabNo aufgerufen wird 205 // (z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird) 206 207 SCTAB nTab = aViewData.GetTabNo(); 208 ScDocument* pDoc = aViewData.GetDocument(); 209 if ( pDoc->HasTable(nTab) ) 210 PaintBlock( sal_True ); // sal_True -> Block loeschen 211 else 212 rMark.ResetMark(); 213 } 214 // bIsBlockMode = sal_False; 215 bIsBlockMode = SC_BLOCKMODE_NONE; //! Variable umbenennen! 216 217 rMark.SetMarking(bFlag); 218 rMark.SetMarkNegative(sal_False); 219 } 220 } 221 222 void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, 223 sal_Bool bCols, sal_Bool bRows, sal_Bool bCellSelection ) 224 { 225 if (!ValidCol(nCurX)) nCurX = MAXCOL; 226 if (!ValidRow(nCurY)) nCurY = MAXROW; 227 228 if (!bIsBlockMode) 229 { 230 DBG_ERROR( "MarkCursor nicht im BlockMode" ); 231 InitBlockMode( nCurX, nCurY, nCurZ, sal_False, bCols, bRows ); 232 } 233 234 if (bCols) 235 nCurY = MAXROW; 236 if (bRows) 237 nCurX = MAXCOL; 238 239 ScMarkData& rMark = aViewData.GetMarkData(); 240 DBG_ASSERT(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()"); 241 ScRange aMarkRange; 242 rMark.GetMarkArea(aMarkRange); 243 if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) || 244 ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) || 245 ( bIsBlockMode == SC_BLOCKMODE_OWN )) 246 { 247 // Markierung ist veraendert worden 248 // (z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde) 249 // oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert... 250 251 sal_Bool bOldShift = bMoveIsShift; 252 bMoveIsShift = sal_False; // wirklich umsetzen 253 DoneBlockMode(sal_False); //! direkt Variablen setzen? (-> kein Geflacker) 254 bMoveIsShift = bOldShift; 255 256 InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), 257 nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows ); 258 } 259 260 SCCOL nOldBlockEndX = nBlockEndX; 261 SCROW nOldBlockEndY = nBlockEndY; 262 263 if ( nCurX != nOldCurX || nCurY != nOldCurY ) 264 { 265 // Current cursor has moved 266 267 SCTAB nTab = nCurZ; 268 269 #ifdef OLD_SELECTION_PAINT 270 SCCOL nDrawStartCol; 271 SCROW nDrawStartRow; 272 SCCOL nDrawEndCol; 273 SCROW nDrawEndRow; 274 #endif 275 276 // Set old selection area 277 ScUpdateRect aRect( nBlockStartX, nBlockStartY, nOldBlockEndX, nOldBlockEndY ); 278 279 if ( bCellSelection ) 280 { 281 // Expand selection area accordingly when the current selection ends 282 // with a merged cell. 283 SCsCOL nCurXOffset = 0; 284 SCsCOL nBlockStartXOffset = 0; 285 SCsROW nCurYOffset = 0; 286 SCsROW nBlockStartYOffset = 0; 287 sal_Bool bBlockStartMerged = sal_False; 288 const ScMergeAttr* pMergeAttr = NULL; 289 ScDocument* pDocument = aViewData.GetDocument(); 290 291 // The following block checks whether or not the "BlockStart" (anchor) 292 // cell is merged. If it's merged, it'll then move the position of the 293 // anchor cell to the corner that's diagonally opposite of the 294 // direction of a current selection area. For instance, if a current 295 // selection is moving in the upperleft direction, the anchor cell will 296 // move to the lower-right corner of the merged anchor cell, and so on. 297 298 pMergeAttr = static_cast<const ScMergeAttr*>( 299 pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) ); 300 if ( pMergeAttr->IsMerged() ) 301 { 302 SCsCOL nColSpan = pMergeAttr->GetColMerge(); 303 SCsROW nRowSpan = pMergeAttr->GetRowMerge(); 304 305 if ( !( nCurX >= nBlockStartXOrig + nColSpan - 1 && nCurY >= nBlockStartYOrig + nRowSpan - 1 ) ) 306 { 307 nBlockStartX = nCurX >= nBlockStartXOrig ? nBlockStartXOrig : nBlockStartXOrig + nColSpan - 1; 308 nBlockStartY = nCurY >= nBlockStartYOrig ? nBlockStartYOrig : nBlockStartYOrig + nRowSpan - 1; 309 nCurXOffset = nCurX >= nBlockStartXOrig && nCurX < nBlockStartXOrig + nColSpan - 1 ? 310 nBlockStartXOrig - nCurX + nColSpan - 1 : 0; 311 nCurYOffset = nCurY >= nBlockStartYOrig && nCurY < nBlockStartYOrig + nRowSpan - 1 ? 312 nBlockStartYOrig - nCurY + nRowSpan - 1 : 0; 313 bBlockStartMerged = sal_True; 314 } 315 } 316 317 // The following block checks whether or not the current cell is 318 // merged. If it is, it'll then set the appropriate X & Y offset 319 // values (nCurXOffset & nCurYOffset) such that the selection area will 320 // grow by those specified offset amounts. Note that the values of 321 // nCurXOffset/nCurYOffset may also be specified in the previous code 322 // block, in which case whichever value is greater will take on. 323 324 pMergeAttr = static_cast<const ScMergeAttr*>( 325 pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) ); 326 if ( pMergeAttr->IsMerged() ) 327 { 328 SCsCOL nColSpan = pMergeAttr->GetColMerge(); 329 SCsROW nRowSpan = pMergeAttr->GetRowMerge(); 330 331 if ( !( nBlockStartX >= nCurX + nColSpan - 1 && nBlockStartY >= nCurY + nRowSpan - 1 ) ) 332 { 333 if ( nBlockStartX <= nCurX + nColSpan - 1 ) 334 { 335 SCsCOL nCurXOffsetTemp = nCurX < nCurX + nColSpan - 1 ? nColSpan - 1 : 0; 336 nCurXOffset = nCurXOffset > nCurXOffsetTemp ? nCurXOffset : nCurXOffsetTemp; 337 } 338 if ( nBlockStartY <= nCurY + nRowSpan - 1 ) 339 { 340 SCsROW nCurYOffsetTemp = nCurY < nCurY + nRowSpan - 1 ? nRowSpan - 1 : 0; 341 nCurYOffset = nCurYOffset > nCurYOffsetTemp ? nCurYOffset : nCurYOffsetTemp; 342 } 343 if ( !( nBlockStartX <= nCurX && nBlockStartY <= nCurY ) && 344 !( nBlockStartX > nCurX + nColSpan - 1 && nBlockStartY > nCurY + nRowSpan - 1 ) ) 345 { 346 nBlockStartXOffset = nBlockStartX > nCurX && nBlockStartX <= nCurX + nColSpan - 1 ? nCurX - nBlockStartX : 0; 347 nBlockStartYOffset = nBlockStartY > nCurY && nBlockStartY <= nCurY + nRowSpan - 1 ? nCurY - nBlockStartY : 0; 348 } 349 } 350 } 351 else 352 { 353 // The current cell is not merged. Move the anchor cell to its 354 // original position. 355 if ( !bBlockStartMerged ) 356 { 357 nBlockStartX = nBlockStartXOrig; 358 nBlockStartY = nBlockStartYOrig; 359 } 360 } 361 362 nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0; 363 nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0; 364 nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset; 365 nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset; 366 } 367 else 368 { 369 nBlockEndX = nCurX; 370 nBlockEndY = nCurY; 371 } 372 // end of "if ( bCellSelection )" 373 374 // Set new selection area 375 aRect.SetNew( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); 376 rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) ); 377 378 #ifdef OLD_SELECTION_PAINT 379 sal_Bool bCont; 380 sal_Bool bDraw = aRect.GetXorDiff( nDrawStartCol, nDrawStartRow, 381 nDrawEndCol, nDrawEndRow, bCont ); 382 if ( bDraw ) 383 { 384 //? PutInOrder( nDrawStartCol, nDrawEndCol ); 385 //? PutInOrder( nDrawStartRow, nDrawEndRow ); 386 387 HideAllCursors(); 388 InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); 389 if (bCont) 390 { 391 aRect.GetContDiff( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); 392 InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); 393 } 394 ShowAllCursors(); 395 } 396 #endif 397 UpdateSelectionOverlay(); 398 399 nOldCurX = nCurX; 400 nOldCurY = nCurY; 401 402 aViewData.GetViewShell()->UpdateInputHandler(); 403 // InvalidateAttribs(); 404 } 405 406 if ( !bCols && !bRows ) 407 aHdrFunc.SetAnchorFlag( sal_False ); 408 } 409 410 void ScTabView::UpdateSelectionOverlay() 411 { 412 for (sal_uInt16 i=0; i<4; i++) 413 if ( pGridWin[i] && pGridWin[i]->IsVisible() ) 414 pGridWin[i]->UpdateSelectionOverlay(); 415 } 416 417 void ScTabView::UpdateShrinkOverlay() 418 { 419 for (sal_uInt16 i=0; i<4; i++) 420 if ( pGridWin[i] && pGridWin[i]->IsVisible() ) 421 pGridWin[i]->UpdateShrinkOverlay(); 422 } 423 424 void ScTabView::UpdateAllOverlays() 425 { 426 for (sal_uInt16 i=0; i<4; i++) 427 if ( pGridWin[i] && pGridWin[i]->IsVisible() ) 428 pGridWin[i]->UpdateAllOverlays(); 429 } 430 431 //! 432 //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae. 433 //! 434 435 void ScTabView::PaintBlock( sal_Bool bReset ) 436 { 437 ScDocument* pDoc = aViewData.GetDocument(); 438 ScMarkData& rMark = aViewData.GetMarkData(); 439 SCTAB nTab = aViewData.GetTabNo(); 440 sal_Bool bMark = rMark.IsMarked(); 441 sal_Bool bMulti = rMark.IsMultiMarked(); 442 if (bMark || bMulti) 443 { 444 ScRange aMarkRange; 445 HideAllCursors(); 446 if (bMulti) 447 { 448 sal_Bool bFlag = rMark.GetMarkingFlag(); 449 rMark.SetMarking(sal_False); 450 rMark.MarkToMulti(); 451 rMark.GetMultiMarkArea(aMarkRange); 452 rMark.MarkToSimple(); 453 rMark.SetMarking(bFlag); 454 455 bMark = rMark.IsMarked(); 456 bMulti = rMark.IsMultiMarked(); 457 } 458 else 459 rMark.GetMarkArea(aMarkRange); 460 461 nBlockStartX = aMarkRange.aStart.Col(); 462 nBlockStartY = aMarkRange.aStart.Row(); 463 nBlockStartZ = aMarkRange.aStart.Tab(); 464 nBlockEndX = aMarkRange.aEnd.Col(); 465 nBlockEndY = aMarkRange.aEnd.Row(); 466 nBlockEndZ = aMarkRange.aEnd.Tab(); 467 468 sal_Bool bDidReset = sal_False; 469 470 if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ ) 471 { 472 if ( bReset ) 473 { 474 // Invertieren beim Loeschen nur auf aktiver View 475 if ( aViewData.IsActive() ) 476 { 477 sal_uInt16 i; 478 if ( bMulti ) 479 { 480 #ifdef OLD_SELECTION_PAINT 481 for (i=0; i<4; i++) 482 if (pGridWin[i] && pGridWin[i]->IsVisible()) 483 pGridWin[i]->InvertSimple( nBlockStartX, nBlockStartY, 484 nBlockEndX, nBlockEndY, 485 sal_True, sal_True ); 486 #endif 487 rMark.ResetMark(); 488 UpdateSelectionOverlay(); 489 bDidReset = sal_True; 490 } 491 else 492 { 493 #ifdef OLD_SELECTION_PAINT 494 // (mis)use InvertBlockMark to remove all of the selection 495 // -> set bBlockNeg (like when removing parts of a selection) 496 // and convert everything to Multi 497 498 rMark.MarkToMulti(); 499 sal_Bool bOld = bBlockNeg; 500 bBlockNeg = sal_True; 501 // #73130# (negative) MarkArea must be set in case of repaint 502 rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, 503 nBlockEndX,nBlockEndY, nTab ) ); 504 505 InvertBlockMark( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); 506 507 bBlockNeg = bOld; 508 #endif 509 rMark.ResetMark(); 510 UpdateSelectionOverlay(); 511 bDidReset = sal_True; 512 } 513 514 // repaint if controls are touched (#69680# in both cases) 515 // #i74768# Forms are rendered by DrawingLayer's EndDrawLayers() 516 static bool bSuppressControlExtraStuff(true); 517 518 if(!bSuppressControlExtraStuff) 519 { 520 Rectangle aMMRect = pDoc->GetMMRect(nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY, nTab); 521 if (pDoc->HasControl( nTab, aMMRect )) 522 { 523 for (i=0; i<4; i++) 524 { 525 if (pGridWin[i] && pGridWin[i]->IsVisible()) 526 { 527 // MapMode muss logischer (1/100mm) sein !!! 528 pDoc->InvalidateControls( pGridWin[i], nTab, aMMRect ); 529 pGridWin[i]->Update(); 530 } 531 } 532 } 533 } 534 } 535 } 536 else 537 PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); 538 } 539 540 if ( bReset && !bDidReset ) 541 rMark.ResetMark(); 542 543 ShowAllCursors(); 544 } 545 } 546 547 void ScTabView::SelectAll( sal_Bool bContinue ) 548 { 549 ScMarkData& rMark = aViewData.GetMarkData(); 550 SCTAB nTab = aViewData.GetTabNo(); 551 552 if (rMark.IsMarked()) 553 { 554 ScRange aMarkRange; 555 rMark.GetMarkArea( aMarkRange ); 556 if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) ) 557 return; 558 } 559 560 DoneBlockMode( bContinue ); 561 InitBlockMode( 0,0,nTab ); 562 MarkCursor( MAXCOL,MAXROW,nTab ); 563 564 SelectionChanged(); 565 } 566 567 void ScTabView::SelectAllTables() 568 { 569 ScDocument* pDoc = aViewData.GetDocument(); 570 ScMarkData& rMark = aViewData.GetMarkData(); 571 // SCTAB nTab = aViewData.GetTabNo(); 572 SCTAB nCount = pDoc->GetTableCount(); 573 574 if (nCount>1) 575 { 576 for (SCTAB i=0; i<nCount; i++) 577 rMark.SelectTable( i, sal_True ); 578 579 // Markierungen werden per Default nicht pro Tabelle gehalten 580 // pDoc->ExtendMarksFromTable( nTab ); 581 582 aViewData.GetDocShell()->PostPaintExtras(); 583 SfxBindings& rBind = aViewData.GetBindings(); 584 rBind.Invalidate( FID_FILL_TAB ); 585 rBind.Invalidate( FID_TAB_DESELECTALL ); 586 } 587 } 588 589 void ScTabView::DeselectAllTables() 590 { 591 ScDocument* pDoc = aViewData.GetDocument(); 592 ScMarkData& rMark = aViewData.GetMarkData(); 593 SCTAB nTab = aViewData.GetTabNo(); 594 SCTAB nCount = pDoc->GetTableCount(); 595 596 for (SCTAB i=0; i<nCount; i++) 597 rMark.SelectTable( i, ( i == nTab ) ); 598 599 aViewData.GetDocShell()->PostPaintExtras(); 600 SfxBindings& rBind = aViewData.GetBindings(); 601 rBind.Invalidate( FID_FILL_TAB ); 602 rBind.Invalidate( FID_TAB_DESELECTALL ); 603 } 604 605 sal_Bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom, 606 long nWindowX, long nWindowY, ScDocument* pDoc, SCTAB nTab, 607 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 608 SCCOL nFixPosX, SCROW nFixPosY ) 609 { 610 double fZoomFactor = (double)Fraction(nZoom,100); 611 fScaleX *= fZoomFactor; 612 fScaleY *= fZoomFactor; 613 614 long nBlockX = 0; 615 SCCOL nCol; 616 for (nCol=0; nCol<nFixPosX; nCol++) 617 { 618 // for frozen panes, add both parts 619 sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab ); 620 if (nColTwips) 621 { 622 nBlockX += (long)(nColTwips * fScaleX); 623 if (nBlockX > nWindowX) 624 return sal_False; 625 } 626 } 627 for (nCol=nStartCol; nCol<=nEndCol; nCol++) 628 { 629 sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab ); 630 if (nColTwips) 631 { 632 nBlockX += (long)(nColTwips * fScaleX); 633 if (nBlockX > nWindowX) 634 return sal_False; 635 } 636 } 637 638 long nBlockY = 0; 639 for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow) 640 { 641 if (pDoc->RowHidden(nRow, nTab)) 642 continue; 643 644 // for frozen panes, add both parts 645 sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab); 646 if (nRowTwips) 647 { 648 nBlockY += (long)(nRowTwips * fScaleY); 649 if (nBlockY > nWindowY) 650 return sal_False; 651 } 652 } 653 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) 654 { 655 sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab); 656 if (nRowTwips) 657 { 658 nBlockY += (long)(nRowTwips * fScaleY); 659 if (nBlockY > nWindowY) 660 return sal_False; 661 } 662 } 663 664 return sal_True; 665 } 666 667 sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom ) 668 { 669 sal_uInt16 nZoom = 0; // Ergebnis 670 671 switch ( eType ) 672 { 673 case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert 674 nZoom = nOldZoom; 675 break; 676 677 case SVX_ZOOM_OPTIMAL: // nZoom entspricht der optimalen Gr"o\se 678 { 679 ScMarkData& rMark = aViewData.GetMarkData(); 680 ScDocument* pDoc = aViewData.GetDocument(); 681 682 if (!rMark.IsMarked() && !rMark.IsMultiMarked()) 683 nZoom = 100; // nothing selected 684 else 685 { 686 SCTAB nTab = aViewData.GetTabNo(); 687 ScRange aMarkRange; 688 if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE ) 689 rMark.GetMultiMarkArea( aMarkRange ); 690 691 SCCOL nStartCol = aMarkRange.aStart.Col(); 692 SCROW nStartRow = aMarkRange.aStart.Row(); 693 SCTAB nStartTab = aMarkRange.aStart.Tab(); 694 SCCOL nEndCol = aMarkRange.aEnd.Col(); 695 SCROW nEndRow = aMarkRange.aEnd.Row(); 696 SCTAB nEndTab = aMarkRange.aEnd.Tab(); 697 698 if ( nTab < nStartTab && nTab > nEndTab ) 699 nTab = nStartTab; 700 701 ScSplitPos eUsedPart = aViewData.GetActivePart(); 702 703 SCCOL nFixPosX = 0; 704 SCROW nFixPosY = 0; 705 if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) 706 { 707 // use right part 708 eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT; 709 nFixPosX = aViewData.GetFixPosX(); 710 if ( nStartCol < nFixPosX ) 711 nStartCol = nFixPosX; 712 } 713 if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) 714 { 715 // use bottom part 716 eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; 717 nFixPosY = aViewData.GetFixPosY(); 718 if ( nStartRow < nFixPosY ) 719 nStartRow = nFixPosY; 720 } 721 722 if (pGridWin[eUsedPart]) 723 { 724 // Because scale is rounded to pixels, the only reliable way to find 725 // the right scale is to check if a zoom fits 726 727 Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel(); 728 729 // for frozen panes, use sum of both parts for calculation 730 731 if ( nFixPosX != 0 ) 732 aWinSize.Width() += GetGridWidth( SC_SPLIT_LEFT ); 733 if ( nFixPosY != 0 ) 734 aWinSize.Height() += GetGridHeight( SC_SPLIT_TOP ); 735 736 ScDocShell* pDocSh = aViewData.GetDocShell(); 737 double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor(); 738 double nPPTY = ScGlobal::nScreenPPTY; 739 740 sal_uInt16 nMin = MINZOOM; 741 sal_uInt16 nMax = MAXZOOM; 742 while ( nMax > nMin ) 743 { 744 sal_uInt16 nTest = (nMin+nMax+1)/2; 745 if ( lcl_FitsInWindow( 746 nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(), 747 pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow, 748 nFixPosX, nFixPosY ) ) 749 nMin = nTest; 750 else 751 nMax = nTest-1; 752 } 753 DBG_ASSERT( nMin == nMax, "Schachtelung ist falsch" ); 754 nZoom = nMin; 755 756 if ( nZoom != nOldZoom ) 757 { 758 // scroll to block only in active split part 759 // (the part for which the size was calculated) 760 761 if ( nStartCol <= nEndCol ) 762 aViewData.SetPosX( WhichH(eUsedPart), nStartCol ); 763 if ( nStartRow <= nEndRow ) 764 aViewData.SetPosY( WhichV(eUsedPart), nStartRow ); 765 } 766 } 767 } 768 } 769 break; 770 771 case SVX_ZOOM_WHOLEPAGE: // nZoom entspricht der ganzen Seite oder 772 case SVX_ZOOM_PAGEWIDTH: // nZoom entspricht der Seitenbreite 773 { 774 SCTAB nCurTab = aViewData.GetTabNo(); 775 ScDocument* pDoc = aViewData.GetDocument(); 776 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); 777 SfxStyleSheetBase* pStyleSheet = 778 pStylePool->Find( pDoc->GetPageStyle( nCurTab ), 779 SFX_STYLE_FAMILY_PAGE ); 780 781 DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" ); 782 783 if ( pStyleSheet ) 784 { 785 ScPrintFunc aPrintFunc( aViewData.GetDocShell(), 786 aViewData.GetViewShell()->GetPrinter(sal_True), 787 nCurTab ); 788 789 Size aPageSize = aPrintFunc.GetDataSize(); 790 791 // use the size of the largest GridWin for normal split, 792 // or both combined for frozen panes, with the (document) size 793 // of the frozen part added to the page size 794 // (with frozen panes, the size of the individual parts 795 // depends on the scale that is to be calculated) 796 797 if ( !pGridWin[SC_SPLIT_BOTTOMLEFT] ) return 0; 798 Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel(); 799 ScSplitMode eHMode = aViewData.GetHSplitMode(); 800 if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] ) 801 { 802 long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]-> 803 GetOutputSizePixel().Width(); 804 if ( eHMode == SC_SPLIT_FIX ) 805 { 806 aWinSize.Width() += nOtherWidth; 807 for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT); 808 nCol < aViewData.GetFixPosX(); nCol++ ) 809 aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab ); 810 } 811 else if ( nOtherWidth > aWinSize.Width() ) 812 aWinSize.Width() = nOtherWidth; 813 } 814 ScSplitMode eVMode = aViewData.GetVSplitMode(); 815 if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] ) 816 { 817 long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]-> 818 GetOutputSizePixel().Height(); 819 if ( eVMode == SC_SPLIT_FIX ) 820 { 821 aWinSize.Height() += nOtherHeight; 822 aPageSize.Height() += pDoc->GetRowHeight( 823 aViewData.GetPosY(SC_SPLIT_TOP), 824 aViewData.GetFixPosY()-1, nCurTab); 825 } 826 else if ( nOtherHeight > aWinSize.Height() ) 827 aWinSize.Height() = nOtherHeight; 828 } 829 830 double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor(); 831 double nPPTY = ScGlobal::nScreenPPTY; 832 833 long nZoomX = (long) ( aWinSize.Width() * 100 / 834 ( aPageSize.Width() * nPPTX ) ); 835 long nZoomY = (long) ( aWinSize.Height() * 100 / 836 ( aPageSize.Height() * nPPTY ) ); 837 long nNew = nZoomX; 838 839 if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew) 840 nNew = nZoomY; 841 842 nZoom = (sal_uInt16) nNew; 843 } 844 } 845 break; 846 847 default: 848 DBG_ERROR("Unknown Zoom-Revision"); 849 nZoom = 0; 850 } 851 852 return nZoom; 853 } 854 855 // wird z.B. gerufen, wenn sich das View-Fenster verschiebt: 856 857 void ScTabView::StopMarking() 858 { 859 ScSplitPos eActive = aViewData.GetActivePart(); 860 if (pGridWin[eActive]) 861 pGridWin[eActive]->StopMarking(); 862 863 ScHSplitPos eH = WhichH(eActive); 864 if (pColBar[eH]) 865 pColBar[eH]->StopMarking(); 866 867 ScVSplitPos eV = WhichV(eActive); 868 if (pRowBar[eV]) 869 pRowBar[eV]->StopMarking(); 870 } 871 872 void ScTabView::HideNoteMarker() 873 { 874 for (sal_uInt16 i=0; i<4; i++) 875 if (pGridWin[i] && pGridWin[i]->IsVisible()) 876 pGridWin[i]->HideNoteMarker(); 877 } 878 879 void ScTabView::MakeDrawLayer() 880 { 881 if (!pDrawView) 882 { 883 aViewData.GetDocShell()->MakeDrawLayer(); 884 885 // pDrawView wird per Notify gesetzt 886 DBG_ASSERT(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht"); 887 888 // #114409# 889 for(sal_uInt16 a(0); a < 4; a++) 890 { 891 if(pGridWin[a]) 892 { 893 pGridWin[a]->DrawLayerCreated(); 894 } 895 } 896 } 897 } 898 899 void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId ) 900 { 901 if ( SC_MOD()->IsInExecuteDrop() ) 902 { 903 // #i28468# don't show error message when called from Drag&Drop, silently abort instead 904 return; 905 } 906 907 StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen 908 909 Window* pParent = aViewData.GetDialogParent(); 910 ScWaitCursorOff aWaitOff( pParent ); 911 sal_Bool bFocus = pParent && pParent->HasFocus(); 912 913 if(nGlobStrId==STR_PROTECTIONERR) 914 { 915 if(aViewData.GetDocShell()->IsReadOnly()) 916 { 917 nGlobStrId=STR_READONLYERR; 918 } 919 } 920 921 InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) ); 922 aBox.Execute(); 923 if (bFocus) 924 pParent->GrabFocus(); 925 } 926 927 Window* ScTabView::GetParentOrChild( sal_uInt16 nChildId ) 928 { 929 SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame(); 930 931 if ( pViewFrm->HasChildWindow(nChildId) ) 932 { 933 SfxChildWindow* pChild = pViewFrm->GetChildWindow(nChildId); 934 if (pChild) 935 { 936 Window* pWin = pChild->GetWindow(); 937 if (pWin && pWin->IsVisible()) 938 return pWin; 939 } 940 } 941 942 return aViewData.GetDialogParent(); 943 } 944 945 void ScTabView::UpdatePageBreakData( sal_Bool bForcePaint ) 946 { 947 ScPageBreakData* pNewData = NULL; 948 949 if (aViewData.IsPagebreakMode()) 950 { 951 ScDocShell* pDocSh = aViewData.GetDocShell(); 952 ScDocument* pDoc = pDocSh->GetDocument(); 953 SCTAB nTab = aViewData.GetTabNo(); 954 955 sal_uInt16 nCount = pDoc->GetPrintRangeCount(nTab); 956 if (!nCount) 957 nCount = 1; 958 pNewData = new ScPageBreakData(nCount); 959 960 ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData ); 961 // ScPrintFunc fuellt im ctor die PageBreakData 962 if ( nCount > 1 ) 963 { 964 aPrintFunc.ResetBreaks(nTab); 965 pNewData->AddPages(); 966 } 967 968 // Druckbereiche veraendert? 969 if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) ) 970 PaintGrid(); 971 } 972 973 delete pPageBreakData; 974 pPageBreakData = pNewData; 975 } 976 977 978 979