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