| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| |
| |
| // INCLUDE --------------------------------------------------------------- |
| |
| #include "scitems.hxx" |
| #include <editeng/eeitem.hxx> |
| |
| |
| #include <vcl/timer.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <sfx2/app.hxx> |
| #include <sfx2/viewfrm.hxx> |
| #include <sfx2/bindings.hxx> |
| #include <sfx2/childwin.hxx> |
| |
| #include "attrib.hxx" |
| #include "pagedata.hxx" |
| #include "tabview.hxx" |
| #include "tabvwsh.hxx" |
| #include "printfun.hxx" |
| #include "stlpool.hxx" |
| #include "docsh.hxx" |
| #include "gridwin.hxx" |
| #include "olinewin.hxx" |
| #include "uiitems.hxx" |
| #include "sc.hrc" |
| #include "viewutil.hxx" |
| #include "colrowba.hxx" |
| #include "waitoff.hxx" |
| #include "globstr.hrc" |
| #include "scmod.hxx" |
| |
| #define SC_BLOCKMODE_NONE 0 |
| #define SC_BLOCKMODE_NORMAL 1 |
| #define SC_BLOCKMODE_OWN 2 |
| |
| |
| |
| // |
| // Markier - Funktionen |
| // |
| |
| void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) |
| { |
| if (!ValidCol(nStartCol)) nStartCol = MAXCOL; |
| if (!ValidRow(nStartRow)) nStartRow = MAXROW; |
| if (!ValidCol(nEndCol)) nEndCol = MAXCOL; |
| if (!ValidRow(nEndRow)) nEndRow = MAXROW; |
| |
| sal_Bool bLeft = (nStartCol==0 && nEndCol==MAXCOL); |
| sal_Bool bTop = (nStartRow==0 && nEndRow==MAXROW); |
| |
| if (bLeft) |
| PaintLeftArea( nStartRow, nEndRow ); |
| if (bTop) |
| PaintTopArea( nStartCol, nEndCol ); |
| |
| aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, |
| aViewData.GetTabNo() ); |
| PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS ); |
| } |
| |
| sal_Bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const |
| { |
| return bIsBlockMode |
| && nBlockStartX == nCol |
| && nBlockStartY == nRow |
| && nBlockStartZ == nTab; |
| } |
| |
| void ScTabView::InitOwnBlockMode() |
| { |
| if (!bIsBlockMode) |
| { |
| // Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen: |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| if (!rMark.IsMarked() && !rMark.IsMultiMarked()) |
| GetSelEngine()->CursorPosChanging( sal_False, sal_False ); |
| |
| // bIsBlockMode = sal_True; |
| bIsBlockMode = SC_BLOCKMODE_OWN; //! Variable umbenennen! |
| nBlockStartX = 0; |
| nBlockStartY = 0; |
| nBlockStartZ = 0; |
| nBlockEndX = 0; |
| nBlockEndY = 0; |
| nBlockEndZ = 0; |
| |
| SelectionChanged(); // Status wird mit gesetzer Markierung abgefragt |
| } |
| } |
| |
| void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, |
| sal_Bool bTestNeg, sal_Bool bCols, sal_Bool bRows, sal_Bool bForceNeg ) |
| { |
| if (!bIsBlockMode) |
| { |
| if (!ValidCol(nCurX)) nCurX = MAXCOL; |
| if (!ValidRow(nCurY)) nCurY = MAXROW; |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| // Teil von Markierung aufheben? |
| //IAccessibility2 Implementation 2009----- |
| if (bForceNeg) |
| bBlockNeg = sal_True; |
| //-----IAccessibility2 Implementation 2009 |
| else if (bTestNeg) |
| { |
| if ( bCols ) |
| bBlockNeg = rMark.IsColumnMarked( nCurX ); |
| else if ( bRows ) |
| bBlockNeg = rMark.IsRowMarked( nCurY ); |
| else |
| bBlockNeg = rMark.IsCellMarked( nCurX, nCurY ); |
| } |
| else |
| bBlockNeg = sal_False; |
| rMark.SetMarkNegative(bBlockNeg); |
| |
| // bIsBlockMode = sal_True; |
| bIsBlockMode = SC_BLOCKMODE_NORMAL; //! Variable umbenennen! |
| bBlockCols = bCols; |
| bBlockRows = bRows; |
| nBlockStartX = nBlockStartXOrig = nCurX; |
| nBlockStartY = nBlockStartYOrig = nCurY; |
| nBlockStartZ = nCurZ; |
| nBlockEndX = nOldCurX = nBlockStartX; |
| nBlockEndY = nOldCurY = nBlockStartY; |
| nBlockEndZ = nBlockStartZ; |
| |
| if (bBlockCols) |
| { |
| nBlockStartY = nBlockStartYOrig = 0; |
| nBlockEndY = MAXROW; |
| } |
| |
| if (bBlockRows) |
| { |
| nBlockStartX = nBlockStartXOrig = 0; |
| nBlockEndX = MAXCOL; |
| } |
| |
| rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) ); |
| |
| #ifdef OLD_SELECTION_PAINT |
| InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY ); |
| #endif |
| UpdateSelectionOverlay(); |
| |
| bNewStartIfMarking = sal_False; // use only once |
| } |
| } |
| |
| void ScTabView::SetNewStartIfMarking() |
| { |
| bNewStartIfMarking = sal_True; |
| } |
| |
| void ScTabView::DoneBlockMode( sal_Bool bContinue ) // Default FALSE |
| { |
| // Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird, |
| // wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat. |
| // Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird. |
| |
| if (bIsBlockMode && !bMoveIsShift) |
| { |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| sal_Bool bFlag = rMark.GetMarkingFlag(); |
| rMark.SetMarking(sal_False); |
| |
| if (bBlockNeg && !bContinue) |
| rMark.MarkToMulti(); |
| |
| if (bContinue) |
| rMark.MarkToMulti(); |
| else |
| { |
| // Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode |
| // aus SetTabNo aufgerufen wird |
| // (z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird) |
| |
| SCTAB nTab = aViewData.GetTabNo(); |
| ScDocument* pDoc = aViewData.GetDocument(); |
| if ( pDoc->HasTable(nTab) ) |
| PaintBlock( sal_True ); // sal_True -> Block loeschen |
| else |
| rMark.ResetMark(); |
| } |
| // bIsBlockMode = sal_False; |
| bIsBlockMode = SC_BLOCKMODE_NONE; //! Variable umbenennen! |
| |
| rMark.SetMarking(bFlag); |
| rMark.SetMarkNegative(sal_False); |
| } |
| } |
| |
| void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, |
| sal_Bool bCols, sal_Bool bRows, sal_Bool bCellSelection ) |
| { |
| if (!ValidCol(nCurX)) nCurX = MAXCOL; |
| if (!ValidRow(nCurY)) nCurY = MAXROW; |
| |
| if (!bIsBlockMode) |
| { |
| DBG_ERROR( "MarkCursor nicht im BlockMode" ); |
| InitBlockMode( nCurX, nCurY, nCurZ, sal_False, bCols, bRows ); |
| } |
| |
| if (bCols) |
| nCurY = MAXROW; |
| if (bRows) |
| nCurX = MAXCOL; |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| DBG_ASSERT(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()"); |
| ScRange aMarkRange; |
| rMark.GetMarkArea(aMarkRange); |
| if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) || |
| ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) || |
| ( bIsBlockMode == SC_BLOCKMODE_OWN )) |
| { |
| // Markierung ist veraendert worden |
| // (z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde) |
| // oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert... |
| |
| sal_Bool bOldShift = bMoveIsShift; |
| bMoveIsShift = sal_False; // wirklich umsetzen |
| DoneBlockMode(sal_False); //! direkt Variablen setzen? (-> kein Geflacker) |
| bMoveIsShift = bOldShift; |
| |
| InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), |
| nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows ); |
| } |
| |
| SCCOL nOldBlockEndX = nBlockEndX; |
| SCROW nOldBlockEndY = nBlockEndY; |
| |
| if ( nCurX != nOldCurX || nCurY != nOldCurY ) |
| { |
| // Current cursor has moved |
| |
| SCTAB nTab = nCurZ; |
| |
| #ifdef OLD_SELECTION_PAINT |
| SCCOL nDrawStartCol; |
| SCROW nDrawStartRow; |
| SCCOL nDrawEndCol; |
| SCROW nDrawEndRow; |
| #endif |
| |
| // Set old selection area |
| ScUpdateRect aRect( nBlockStartX, nBlockStartY, nOldBlockEndX, nOldBlockEndY ); |
| |
| if ( bCellSelection ) |
| { |
| // Expand selection area accordingly when the current selection ends |
| // with a merged cell. |
| SCsCOL nCurXOffset = 0; |
| SCsCOL nBlockStartXOffset = 0; |
| SCsROW nCurYOffset = 0; |
| SCsROW nBlockStartYOffset = 0; |
| sal_Bool bBlockStartMerged = sal_False; |
| const ScMergeAttr* pMergeAttr = NULL; |
| ScDocument* pDocument = aViewData.GetDocument(); |
| |
| // The following block checks whether or not the "BlockStart" (anchor) |
| // cell is merged. If it's merged, it'll then move the position of the |
| // anchor cell to the corner that's diagonally opposite of the |
| // direction of a current selection area. For instance, if a current |
| // selection is moving in the upperleft direction, the anchor cell will |
| // move to the lower-right corner of the merged anchor cell, and so on. |
| |
| pMergeAttr = static_cast<const ScMergeAttr*>( |
| pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) ); |
| if ( pMergeAttr->IsMerged() ) |
| { |
| SCsCOL nColSpan = pMergeAttr->GetColMerge(); |
| SCsROW nRowSpan = pMergeAttr->GetRowMerge(); |
| |
| if ( !( nCurX >= nBlockStartXOrig + nColSpan - 1 && nCurY >= nBlockStartYOrig + nRowSpan - 1 ) ) |
| { |
| nBlockStartX = nCurX >= nBlockStartXOrig ? nBlockStartXOrig : nBlockStartXOrig + nColSpan - 1; |
| nBlockStartY = nCurY >= nBlockStartYOrig ? nBlockStartYOrig : nBlockStartYOrig + nRowSpan - 1; |
| nCurXOffset = nCurX >= nBlockStartXOrig && nCurX < nBlockStartXOrig + nColSpan - 1 ? |
| nBlockStartXOrig - nCurX + nColSpan - 1 : 0; |
| nCurYOffset = nCurY >= nBlockStartYOrig && nCurY < nBlockStartYOrig + nRowSpan - 1 ? |
| nBlockStartYOrig - nCurY + nRowSpan - 1 : 0; |
| bBlockStartMerged = sal_True; |
| } |
| } |
| |
| // The following block checks whether or not the current cell is |
| // merged. If it is, it'll then set the appropriate X & Y offset |
| // values (nCurXOffset & nCurYOffset) such that the selection area will |
| // grow by those specified offset amounts. Note that the values of |
| // nCurXOffset/nCurYOffset may also be specified in the previous code |
| // block, in which case whichever value is greater will take on. |
| |
| pMergeAttr = static_cast<const ScMergeAttr*>( |
| pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) ); |
| if ( pMergeAttr->IsMerged() ) |
| { |
| SCsCOL nColSpan = pMergeAttr->GetColMerge(); |
| SCsROW nRowSpan = pMergeAttr->GetRowMerge(); |
| |
| if ( !( nBlockStartX >= nCurX + nColSpan - 1 && nBlockStartY >= nCurY + nRowSpan - 1 ) ) |
| { |
| if ( nBlockStartX <= nCurX + nColSpan - 1 ) |
| { |
| SCsCOL nCurXOffsetTemp = nCurX < nCurX + nColSpan - 1 ? nColSpan - 1 : 0; |
| nCurXOffset = nCurXOffset > nCurXOffsetTemp ? nCurXOffset : nCurXOffsetTemp; |
| } |
| if ( nBlockStartY <= nCurY + nRowSpan - 1 ) |
| { |
| SCsROW nCurYOffsetTemp = nCurY < nCurY + nRowSpan - 1 ? nRowSpan - 1 : 0; |
| nCurYOffset = nCurYOffset > nCurYOffsetTemp ? nCurYOffset : nCurYOffsetTemp; |
| } |
| if ( !( nBlockStartX <= nCurX && nBlockStartY <= nCurY ) && |
| !( nBlockStartX > nCurX + nColSpan - 1 && nBlockStartY > nCurY + nRowSpan - 1 ) ) |
| { |
| nBlockStartXOffset = nBlockStartX > nCurX && nBlockStartX <= nCurX + nColSpan - 1 ? nCurX - nBlockStartX : 0; |
| nBlockStartYOffset = nBlockStartY > nCurY && nBlockStartY <= nCurY + nRowSpan - 1 ? nCurY - nBlockStartY : 0; |
| } |
| } |
| } |
| else |
| { |
| // The current cell is not merged. Move the anchor cell to its |
| // original position. |
| if ( !bBlockStartMerged ) |
| { |
| nBlockStartX = nBlockStartXOrig; |
| nBlockStartY = nBlockStartYOrig; |
| } |
| } |
| |
| nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0; |
| nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0; |
| nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset; |
| nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset; |
| } |
| else |
| { |
| nBlockEndX = nCurX; |
| nBlockEndY = nCurY; |
| } |
| // end of "if ( bCellSelection )" |
| |
| // Set new selection area |
| aRect.SetNew( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); |
| rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) ); |
| |
| #ifdef OLD_SELECTION_PAINT |
| sal_Bool bCont; |
| sal_Bool bDraw = aRect.GetXorDiff( nDrawStartCol, nDrawStartRow, |
| nDrawEndCol, nDrawEndRow, bCont ); |
| if ( bDraw ) |
| { |
| //? PutInOrder( nDrawStartCol, nDrawEndCol ); |
| //? PutInOrder( nDrawStartRow, nDrawEndRow ); |
| |
| HideAllCursors(); |
| InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); |
| if (bCont) |
| { |
| aRect.GetContDiff( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); |
| InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); |
| } |
| ShowAllCursors(); |
| } |
| #endif |
| UpdateSelectionOverlay(); |
| |
| nOldCurX = nCurX; |
| nOldCurY = nCurY; |
| |
| aViewData.GetViewShell()->UpdateInputHandler(); |
| // InvalidateAttribs(); |
| } |
| |
| if ( !bCols && !bRows ) |
| aHdrFunc.SetAnchorFlag( sal_False ); |
| } |
| |
| void ScTabView::UpdateSelectionOverlay() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if ( pGridWin[i] && pGridWin[i]->IsVisible() ) |
| pGridWin[i]->UpdateSelectionOverlay(); |
| } |
| |
| void ScTabView::UpdateShrinkOverlay() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if ( pGridWin[i] && pGridWin[i]->IsVisible() ) |
| pGridWin[i]->UpdateShrinkOverlay(); |
| } |
| |
| void ScTabView::UpdateAllOverlays() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if ( pGridWin[i] && pGridWin[i]->IsVisible() ) |
| pGridWin[i]->UpdateAllOverlays(); |
| } |
| |
| //! |
| //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae. |
| //! |
| |
| void ScTabView::PaintBlock( sal_Bool bReset ) |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| sal_Bool bMark = rMark.IsMarked(); |
| sal_Bool bMulti = rMark.IsMultiMarked(); |
| if (bMark || bMulti) |
| { |
| ScRange aMarkRange; |
| HideAllCursors(); |
| if (bMulti) |
| { |
| sal_Bool bFlag = rMark.GetMarkingFlag(); |
| rMark.SetMarking(sal_False); |
| rMark.MarkToMulti(); |
| rMark.GetMultiMarkArea(aMarkRange); |
| rMark.MarkToSimple(); |
| rMark.SetMarking(bFlag); |
| |
| bMark = rMark.IsMarked(); |
| bMulti = rMark.IsMultiMarked(); |
| } |
| else |
| rMark.GetMarkArea(aMarkRange); |
| |
| nBlockStartX = aMarkRange.aStart.Col(); |
| nBlockStartY = aMarkRange.aStart.Row(); |
| nBlockStartZ = aMarkRange.aStart.Tab(); |
| nBlockEndX = aMarkRange.aEnd.Col(); |
| nBlockEndY = aMarkRange.aEnd.Row(); |
| nBlockEndZ = aMarkRange.aEnd.Tab(); |
| |
| sal_Bool bDidReset = sal_False; |
| |
| if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ ) |
| { |
| if ( bReset ) |
| { |
| // Invertieren beim Loeschen nur auf aktiver View |
| if ( aViewData.IsActive() ) |
| { |
| sal_uInt16 i; |
| if ( bMulti ) |
| { |
| #ifdef OLD_SELECTION_PAINT |
| for (i=0; i<4; i++) |
| if (pGridWin[i] && pGridWin[i]->IsVisible()) |
| pGridWin[i]->InvertSimple( nBlockStartX, nBlockStartY, |
| nBlockEndX, nBlockEndY, |
| sal_True, sal_True ); |
| #endif |
| rMark.ResetMark(); |
| UpdateSelectionOverlay(); |
| bDidReset = sal_True; |
| } |
| else |
| { |
| #ifdef OLD_SELECTION_PAINT |
| // (mis)use InvertBlockMark to remove all of the selection |
| // -> set bBlockNeg (like when removing parts of a selection) |
| // and convert everything to Multi |
| |
| rMark.MarkToMulti(); |
| sal_Bool bOld = bBlockNeg; |
| bBlockNeg = sal_True; |
| // #73130# (negative) MarkArea must be set in case of repaint |
| rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, |
| nBlockEndX,nBlockEndY, nTab ) ); |
| |
| InvertBlockMark( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); |
| |
| bBlockNeg = bOld; |
| #endif |
| rMark.ResetMark(); |
| UpdateSelectionOverlay(); |
| bDidReset = sal_True; |
| } |
| |
| // repaint if controls are touched (#69680# in both cases) |
| // #i74768# Forms are rendered by DrawingLayer's EndDrawLayers() |
| static bool bSuppressControlExtraStuff(true); |
| |
| if(!bSuppressControlExtraStuff) |
| { |
| Rectangle aMMRect = pDoc->GetMMRect(nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY, nTab); |
| if (pDoc->HasControl( nTab, aMMRect )) |
| { |
| for (i=0; i<4; i++) |
| { |
| if (pGridWin[i] && pGridWin[i]->IsVisible()) |
| { |
| // MapMode muss logischer (1/100mm) sein !!! |
| pDoc->InvalidateControls( pGridWin[i], nTab, aMMRect ); |
| pGridWin[i]->Update(); |
| } |
| } |
| } |
| } |
| } |
| } |
| else |
| PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); |
| } |
| |
| if ( bReset && !bDidReset ) |
| rMark.ResetMark(); |
| |
| ShowAllCursors(); |
| } |
| } |
| |
| void ScTabView::SelectAll( sal_Bool bContinue ) |
| { |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| if (rMark.IsMarked()) |
| { |
| ScRange aMarkRange; |
| rMark.GetMarkArea( aMarkRange ); |
| if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) ) |
| return; |
| } |
| |
| DoneBlockMode( bContinue ); |
| InitBlockMode( 0,0,nTab ); |
| MarkCursor( MAXCOL,MAXROW,nTab ); |
| |
| SelectionChanged(); |
| } |
| |
| void ScTabView::SelectAllTables() |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| // SCTAB nTab = aViewData.GetTabNo(); |
| SCTAB nCount = pDoc->GetTableCount(); |
| |
| if (nCount>1) |
| { |
| for (SCTAB i=0; i<nCount; i++) |
| rMark.SelectTable( i, sal_True ); |
| |
| // Markierungen werden per Default nicht pro Tabelle gehalten |
| // pDoc->ExtendMarksFromTable( nTab ); |
| |
| aViewData.GetDocShell()->PostPaintExtras(); |
| SfxBindings& rBind = aViewData.GetBindings(); |
| rBind.Invalidate( FID_FILL_TAB ); |
| rBind.Invalidate( FID_TAB_DESELECTALL ); |
| } |
| } |
| |
| void ScTabView::DeselectAllTables() |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| SCTAB nCount = pDoc->GetTableCount(); |
| |
| for (SCTAB i=0; i<nCount; i++) |
| rMark.SelectTable( i, ( i == nTab ) ); |
| |
| aViewData.GetDocShell()->PostPaintExtras(); |
| SfxBindings& rBind = aViewData.GetBindings(); |
| rBind.Invalidate( FID_FILL_TAB ); |
| rBind.Invalidate( FID_TAB_DESELECTALL ); |
| } |
| |
| sal_Bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom, |
| long nWindowX, long nWindowY, ScDocument* pDoc, SCTAB nTab, |
| SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, |
| SCCOL nFixPosX, SCROW nFixPosY ) |
| { |
| double fZoomFactor = (double)Fraction(nZoom,100); |
| fScaleX *= fZoomFactor; |
| fScaleY *= fZoomFactor; |
| |
| long nBlockX = 0; |
| SCCOL nCol; |
| for (nCol=0; nCol<nFixPosX; nCol++) |
| { |
| // for frozen panes, add both parts |
| sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab ); |
| if (nColTwips) |
| { |
| nBlockX += (long)(nColTwips * fScaleX); |
| if (nBlockX > nWindowX) |
| return sal_False; |
| } |
| } |
| for (nCol=nStartCol; nCol<=nEndCol; nCol++) |
| { |
| sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab ); |
| if (nColTwips) |
| { |
| nBlockX += (long)(nColTwips * fScaleX); |
| if (nBlockX > nWindowX) |
| return sal_False; |
| } |
| } |
| |
| long nBlockY = 0; |
| for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow) |
| { |
| if (pDoc->RowHidden(nRow, nTab)) |
| continue; |
| |
| // for frozen panes, add both parts |
| sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab); |
| if (nRowTwips) |
| { |
| nBlockY += (long)(nRowTwips * fScaleY); |
| if (nBlockY > nWindowY) |
| return sal_False; |
| } |
| } |
| for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) |
| { |
| sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab); |
| if (nRowTwips) |
| { |
| nBlockY += (long)(nRowTwips * fScaleY); |
| if (nBlockY > nWindowY) |
| return sal_False; |
| } |
| } |
| |
| return sal_True; |
| } |
| |
| sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom ) |
| { |
| sal_uInt16 nZoom = 0; // Ergebnis |
| |
| switch ( eType ) |
| { |
| case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert |
| nZoom = nOldZoom; |
| break; |
| |
| case SVX_ZOOM_OPTIMAL: // nZoom entspricht der optimalen Gr"o\se |
| { |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| ScDocument* pDoc = aViewData.GetDocument(); |
| |
| if (!rMark.IsMarked() && !rMark.IsMultiMarked()) |
| nZoom = 100; // nothing selected |
| else |
| { |
| SCTAB nTab = aViewData.GetTabNo(); |
| ScRange aMarkRange; |
| if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE ) |
| rMark.GetMultiMarkArea( aMarkRange ); |
| |
| SCCOL nStartCol = aMarkRange.aStart.Col(); |
| SCROW nStartRow = aMarkRange.aStart.Row(); |
| SCTAB nStartTab = aMarkRange.aStart.Tab(); |
| SCCOL nEndCol = aMarkRange.aEnd.Col(); |
| SCROW nEndRow = aMarkRange.aEnd.Row(); |
| SCTAB nEndTab = aMarkRange.aEnd.Tab(); |
| |
| if ( nTab < nStartTab && nTab > nEndTab ) |
| nTab = nStartTab; |
| |
| ScSplitPos eUsedPart = aViewData.GetActivePart(); |
| |
| SCCOL nFixPosX = 0; |
| SCROW nFixPosY = 0; |
| if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) |
| { |
| // use right part |
| eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT; |
| nFixPosX = aViewData.GetFixPosX(); |
| if ( nStartCol < nFixPosX ) |
| nStartCol = nFixPosX; |
| } |
| if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) |
| { |
| // use bottom part |
| eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; |
| nFixPosY = aViewData.GetFixPosY(); |
| if ( nStartRow < nFixPosY ) |
| nStartRow = nFixPosY; |
| } |
| |
| if (pGridWin[eUsedPart]) |
| { |
| // Because scale is rounded to pixels, the only reliable way to find |
| // the right scale is to check if a zoom fits |
| |
| Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel(); |
| |
| // for frozen panes, use sum of both parts for calculation |
| |
| if ( nFixPosX != 0 ) |
| aWinSize.Width() += GetGridWidth( SC_SPLIT_LEFT ); |
| if ( nFixPosY != 0 ) |
| aWinSize.Height() += GetGridHeight( SC_SPLIT_TOP ); |
| |
| ScDocShell* pDocSh = aViewData.GetDocShell(); |
| double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor(); |
| double nPPTY = ScGlobal::nScreenPPTY; |
| |
| sal_uInt16 nMin = MINZOOM; |
| sal_uInt16 nMax = MAXZOOM; |
| while ( nMax > nMin ) |
| { |
| sal_uInt16 nTest = (nMin+nMax+1)/2; |
| if ( lcl_FitsInWindow( |
| nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(), |
| pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow, |
| nFixPosX, nFixPosY ) ) |
| nMin = nTest; |
| else |
| nMax = nTest-1; |
| } |
| DBG_ASSERT( nMin == nMax, "Schachtelung ist falsch" ); |
| nZoom = nMin; |
| |
| if ( nZoom != nOldZoom ) |
| { |
| // scroll to block only in active split part |
| // (the part for which the size was calculated) |
| |
| if ( nStartCol <= nEndCol ) |
| aViewData.SetPosX( WhichH(eUsedPart), nStartCol ); |
| if ( nStartRow <= nEndRow ) |
| aViewData.SetPosY( WhichV(eUsedPart), nStartRow ); |
| } |
| } |
| } |
| } |
| break; |
| |
| case SVX_ZOOM_WHOLEPAGE: // nZoom entspricht der ganzen Seite oder |
| case SVX_ZOOM_PAGEWIDTH: // nZoom entspricht der Seitenbreite |
| { |
| SCTAB nCurTab = aViewData.GetTabNo(); |
| ScDocument* pDoc = aViewData.GetDocument(); |
| ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); |
| SfxStyleSheetBase* pStyleSheet = |
| pStylePool->Find( pDoc->GetPageStyle( nCurTab ), |
| SFX_STYLE_FAMILY_PAGE ); |
| |
| DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" ); |
| |
| if ( pStyleSheet ) |
| { |
| ScPrintFunc aPrintFunc( aViewData.GetDocShell(), |
| aViewData.GetViewShell()->GetPrinter(sal_True), |
| nCurTab ); |
| |
| Size aPageSize = aPrintFunc.GetDataSize(); |
| |
| // use the size of the largest GridWin for normal split, |
| // or both combined for frozen panes, with the (document) size |
| // of the frozen part added to the page size |
| // (with frozen panes, the size of the individual parts |
| // depends on the scale that is to be calculated) |
| |
| if ( !pGridWin[SC_SPLIT_BOTTOMLEFT] ) return 0; |
| Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel(); |
| ScSplitMode eHMode = aViewData.GetHSplitMode(); |
| if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] ) |
| { |
| long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]-> |
| GetOutputSizePixel().Width(); |
| if ( eHMode == SC_SPLIT_FIX ) |
| { |
| aWinSize.Width() += nOtherWidth; |
| for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT); |
| nCol < aViewData.GetFixPosX(); nCol++ ) |
| aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab ); |
| } |
| else if ( nOtherWidth > aWinSize.Width() ) |
| aWinSize.Width() = nOtherWidth; |
| } |
| ScSplitMode eVMode = aViewData.GetVSplitMode(); |
| if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] ) |
| { |
| long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]-> |
| GetOutputSizePixel().Height(); |
| if ( eVMode == SC_SPLIT_FIX ) |
| { |
| aWinSize.Height() += nOtherHeight; |
| aPageSize.Height() += pDoc->GetRowHeight( |
| aViewData.GetPosY(SC_SPLIT_TOP), |
| aViewData.GetFixPosY()-1, nCurTab); |
| } |
| else if ( nOtherHeight > aWinSize.Height() ) |
| aWinSize.Height() = nOtherHeight; |
| } |
| |
| double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor(); |
| double nPPTY = ScGlobal::nScreenPPTY; |
| |
| long nZoomX = (long) ( aWinSize.Width() * 100 / |
| ( aPageSize.Width() * nPPTX ) ); |
| long nZoomY = (long) ( aWinSize.Height() * 100 / |
| ( aPageSize.Height() * nPPTY ) ); |
| long nNew = nZoomX; |
| |
| if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew) |
| nNew = nZoomY; |
| |
| nZoom = (sal_uInt16) nNew; |
| } |
| } |
| break; |
| |
| default: |
| DBG_ERROR("Unknown Zoom-Revision"); |
| nZoom = 0; |
| } |
| |
| return nZoom; |
| } |
| |
| // wird z.B. gerufen, wenn sich das View-Fenster verschiebt: |
| |
| void ScTabView::StopMarking() |
| { |
| ScSplitPos eActive = aViewData.GetActivePart(); |
| if (pGridWin[eActive]) |
| pGridWin[eActive]->StopMarking(); |
| |
| ScHSplitPos eH = WhichH(eActive); |
| if (pColBar[eH]) |
| pColBar[eH]->StopMarking(); |
| |
| ScVSplitPos eV = WhichV(eActive); |
| if (pRowBar[eV]) |
| pRowBar[eV]->StopMarking(); |
| } |
| |
| void ScTabView::HideNoteMarker() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i] && pGridWin[i]->IsVisible()) |
| pGridWin[i]->HideNoteMarker(); |
| } |
| |
| void ScTabView::MakeDrawLayer() |
| { |
| if (!pDrawView) |
| { |
| aViewData.GetDocShell()->MakeDrawLayer(); |
| |
| // pDrawView wird per Notify gesetzt |
| DBG_ASSERT(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht"); |
| |
| // #114409# |
| for(sal_uInt16 a(0); a < 4; a++) |
| { |
| if(pGridWin[a]) |
| { |
| pGridWin[a]->DrawLayerCreated(); |
| } |
| } |
| } |
| } |
| |
| void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId ) |
| { |
| if ( SC_MOD()->IsInExecuteDrop() ) |
| { |
| // #i28468# don't show error message when called from Drag&Drop, silently abort instead |
| return; |
| } |
| |
| StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen |
| |
| Window* pParent = aViewData.GetDialogParent(); |
| ScWaitCursorOff aWaitOff( pParent ); |
| sal_Bool bFocus = pParent && pParent->HasFocus(); |
| |
| if(nGlobStrId==STR_PROTECTIONERR) |
| { |
| if(aViewData.GetDocShell()->IsReadOnly()) |
| { |
| nGlobStrId=STR_READONLYERR; |
| } |
| } |
| |
| InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) ); |
| aBox.Execute(); |
| if (bFocus) |
| pParent->GrabFocus(); |
| } |
| |
| Window* ScTabView::GetParentOrChild( sal_uInt16 nChildId ) |
| { |
| SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame(); |
| |
| if ( pViewFrm->HasChildWindow(nChildId) ) |
| { |
| SfxChildWindow* pChild = pViewFrm->GetChildWindow(nChildId); |
| if (pChild) |
| { |
| Window* pWin = pChild->GetWindow(); |
| if (pWin && pWin->IsVisible()) |
| return pWin; |
| } |
| } |
| |
| return aViewData.GetDialogParent(); |
| } |
| |
| void ScTabView::UpdatePageBreakData( sal_Bool bForcePaint ) |
| { |
| ScPageBreakData* pNewData = NULL; |
| |
| if (aViewData.IsPagebreakMode()) |
| { |
| ScDocShell* pDocSh = aViewData.GetDocShell(); |
| ScDocument* pDoc = pDocSh->GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| sal_uInt16 nCount = pDoc->GetPrintRangeCount(nTab); |
| if (!nCount) |
| nCount = 1; |
| pNewData = new ScPageBreakData(nCount); |
| |
| ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData ); |
| // ScPrintFunc fuellt im ctor die PageBreakData |
| if ( nCount > 1 ) |
| { |
| aPrintFunc.ResetBreaks(nTab); |
| pNewData->AddPages(); |
| } |
| |
| // Druckbereiche veraendert? |
| if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) ) |
| PaintGrid(); |
| } |
| |
| delete pPageBreakData; |
| pPageBreakData = pNewData; |
| } |
| |
| |
| |