| /************************************************************** |
| * |
| * 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 <svtools/colorcfg.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/editview.hxx> |
| #include <editeng/fhgtitem.hxx> |
| #include <editeng/scripttypeitem.hxx> |
| #include <sfx2/bindings.hxx> |
| #include <sfx2/printer.hxx> |
| |
| #include <svx/svdview.hxx> |
| #include "tabvwsh.hxx" |
| |
| #include "gridwin.hxx" |
| #include "viewdata.hxx" |
| #include "output.hxx" |
| #include "document.hxx" |
| #include "attrib.hxx" |
| #include "patattr.hxx" // InvertSimple |
| #include "dbcolect.hxx" |
| #include "docoptio.hxx" |
| #include "notemark.hxx" |
| #include "dbfunc.hxx" // oder GetPageBreakData an die ViewData |
| #include "scmod.hxx" |
| #include "inputhdl.hxx" |
| #include "rfindlst.hxx" |
| #include "hiranges.hxx" |
| #include "pagedata.hxx" |
| #include "docpool.hxx" |
| #include "globstr.hrc" |
| #include "docsh.hxx" // oder GetSfxInPlaceObject |
| #include "cbutton.hxx" |
| #include "invmerge.hxx" |
| #include "editutil.hxx" |
| #include "inputopt.hxx" |
| #include "fillinfo.hxx" |
| #include "dpcontrol.hxx" |
| #include "queryparam.hxx" |
| #include "sc.hrc" |
| #include <vcl/virdev.hxx> |
| |
| // #i74769# |
| #include <svx/sdrpaintwindow.hxx> |
| |
| //#include "tabvwsh.hxx" //! Test !!!! |
| |
| //------------------------------------------------------------------------ |
| |
| void lcl_LimitRect( Rectangle& rRect, const Rectangle& rVisible ) |
| { |
| if ( rRect.Top() < rVisible.Top()-1 ) rRect.Top() = rVisible.Top()-1; |
| // if ( rRect.Left() < rVisible.Left()-1 ) rRect.Left() = rVisible.Left()-1; |
| if ( rRect.Bottom() > rVisible.Bottom()+1 ) rRect.Bottom() = rVisible.Bottom()+1; |
| // if ( rRect.Right() > rVisible.Right()+1 ) rRect.Right() = rVisible.Right()+1; |
| |
| // #51122# auch wenn das inner-Rectangle nicht sichtbar ist, muss evtl. |
| // die Titelzeile gezeichnet werden, darum kein Rueckgabewert mehr. |
| // Wenn's weit daneben liegt, wird lcl_DrawOneFrame erst gar nicht gerufen. |
| } |
| |
| void lcl_DrawOneFrame( OutputDevice* pDev, const Rectangle& rInnerPixel, |
| const String& rTitle, const Color& rColor, sal_Bool bTextBelow, |
| double nPPTX, double nPPTY, const Fraction& rZoomY, |
| ScDocument* pDoc, ScViewData* pButtonViewData, sal_Bool bLayoutRTL ) |
| { |
| // pButtonViewData wird nur benutzt, um die Button-Groesse zu setzen, |
| // darf ansonsten NULL sein! |
| |
| Rectangle aInner = rInnerPixel; |
| if ( bLayoutRTL ) |
| { |
| aInner.Left() = rInnerPixel.Right(); |
| aInner.Right() = rInnerPixel.Left(); |
| } |
| |
| Rectangle aVisible( Point(0,0), pDev->GetOutputSizePixel() ); |
| lcl_LimitRect( aInner, aVisible ); |
| |
| Rectangle aOuter = aInner; |
| long nHor = (long) ( SC_SCENARIO_HSPACE * nPPTX ); |
| long nVer = (long) ( SC_SCENARIO_VSPACE * nPPTY ); |
| aOuter.Left() -= nHor; |
| aOuter.Right() += nHor; |
| aOuter.Top() -= nVer; |
| aOuter.Bottom() += nVer; |
| |
| // use ScPatternAttr::GetFont only for font size |
| Font aAttrFont; |
| ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)). |
| GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY); |
| |
| // everything else from application font |
| Font aAppFont = pDev->GetSettings().GetStyleSettings().GetAppFont(); |
| aAppFont.SetSize( aAttrFont.GetSize() ); |
| |
| aAppFont.SetAlign( ALIGN_TOP ); |
| pDev->SetFont( aAppFont ); |
| |
| Size aTextSize( pDev->GetTextWidth( rTitle ), pDev->GetTextHeight() ); |
| |
| if ( bTextBelow ) |
| aOuter.Bottom() += aTextSize.Height(); |
| else |
| aOuter.Top() -= aTextSize.Height(); |
| |
| pDev->SetLineColor(); |
| pDev->SetFillColor( rColor ); |
| // links, oben, rechts, unten |
| pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aInner.Left(), aOuter.Bottom() ) ); |
| pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aOuter.Right(), aInner.Top() ) ); |
| pDev->DrawRect( Rectangle( aInner.Right(), aOuter.Top(), aOuter.Right(), aOuter.Bottom() ) ); |
| pDev->DrawRect( Rectangle( aOuter.Left(), aInner.Bottom(), aOuter.Right(), aOuter.Bottom() ) ); |
| |
| long nButtonY = bTextBelow ? aInner.Bottom() : aOuter.Top(); |
| |
| ScDDComboBoxButton aComboButton((Window*)pDev); |
| aComboButton.SetOptSizePixel(); |
| long nBWidth = ( aComboButton.GetSizePixel().Width() * rZoomY.GetNumerator() ) |
| / rZoomY.GetDenominator(); |
| long nBHeight = nVer + aTextSize.Height() + 1; |
| Size aButSize( nBWidth, nBHeight ); |
| long nButtonPos = bLayoutRTL ? aOuter.Left() : aOuter.Right()-nBWidth+1; |
| aComboButton.Draw( Point(nButtonPos, nButtonY), aButSize, sal_False ); |
| if (pButtonViewData) |
| pButtonViewData->SetScenButSize( aButSize ); |
| |
| long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left(); |
| |
| sal_Bool bWasClip = sal_False; |
| Region aOldClip; |
| sal_Bool bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() ); |
| if ( bClip ) |
| { |
| if (pDev->IsClipRegion()) |
| { |
| bWasClip = sal_True; |
| aOldClip = pDev->GetActiveClipRegion(); |
| } |
| long nClipStartX = bLayoutRTL ? aOuter.Left() + nBWidth : aInner.Left(); |
| long nClipEndX = bLayoutRTL ? aInner.Right() : aOuter.Right() - nBWidth; |
| pDev->SetClipRegion( Rectangle( nClipStartX, nButtonY + nVer/2, |
| nClipEndX, nButtonY + nVer/2 + aTextSize.Height() ) ); |
| } |
| |
| pDev->DrawText( Point( nTextStart, nButtonY + nVer/2 ), rTitle ); |
| |
| if ( bClip ) |
| { |
| if ( bWasClip ) |
| pDev->SetClipRegion(aOldClip); |
| else |
| pDev->SetClipRegion(); |
| } |
| |
| pDev->SetFillColor(); |
| pDev->SetLineColor( COL_BLACK ); |
| pDev->DrawRect( aInner ); |
| pDev->DrawRect( aOuter ); |
| } |
| |
| void lcl_DrawScenarioFrames( OutputDevice* pDev, ScViewData* pViewData, ScSplitPos eWhich, |
| SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) |
| { |
| ScDocument* pDoc = pViewData->GetDocument(); |
| SCTAB nTab = pViewData->GetTabNo(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ) |
| { |
| if ( nX1 > 0 ) --nX1; |
| if ( nY1>=2 ) nY1 -= 2; // Hack: Titelzeile beruehrt zwei Zellen |
| else if ( nY1 > 0 ) --nY1; |
| if ( nX2 < MAXCOL ) ++nX2; |
| if ( nY2 < MAXROW-1 ) nY2 += 2; // Hack: Titelzeile beruehrt zwei Zellen |
| else if ( nY2 < MAXROW ) ++nY2; |
| ScRange aViewRange( nX1,nY1,nTab, nX2,nY2,nTab ); |
| |
| //! Ranges an der Table cachen!!!! |
| |
| ScMarkData aMarks; |
| for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) |
| pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME ); |
| ScRangeListRef xRanges = new ScRangeList; |
| aMarks.FillRangeListWithMarks( xRanges, sal_False ); |
| |
| sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| |
| sal_uInt16 nRangeCount = (sal_uInt16)xRanges->Count(); |
| for (sal_uInt16 j=0; j<nRangeCount; j++) |
| { |
| ScRange aRange = *xRanges->GetObject(j); |
| // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn |
| // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden |
| pDoc->ExtendTotalMerge( aRange ); |
| |
| //! -> Repaint beim Zusammenfassen erweitern !!! |
| |
| if ( aRange.Intersects( aViewRange ) ) //! Platz fuer Text/Button? |
| { |
| Point aStartPos = pViewData->GetScrPos( |
| aRange.aStart.Col(), aRange.aStart.Row(), eWhich, sal_True ); |
| Point aEndPos = pViewData->GetScrPos( |
| aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, sal_True ); |
| // on the grid: |
| aStartPos.X() -= nLayoutSign; |
| aStartPos.Y() -= 1; |
| aEndPos.X() -= nLayoutSign; |
| aEndPos.Y() -= 1; |
| |
| sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 ); |
| |
| String aCurrent; |
| Color aColor( COL_LIGHTGRAY ); |
| for (SCTAB nAct=nTab+1; nAct<nTabCount && pDoc->IsScenario(nAct); nAct++) |
| if ( pDoc->IsActiveScenario(nAct) && pDoc->HasScenarioRange(nAct,aRange) ) |
| { |
| String aDummyComment; |
| sal_uInt16 nDummyFlags; |
| pDoc->GetName( nAct, aCurrent ); |
| pDoc->GetScenarioData( nAct, aDummyComment, aColor, nDummyFlags ); |
| } |
| |
| if (!aCurrent.Len()) |
| aCurrent = ScGlobal::GetRscString( STR_EMPTYDATA ); |
| |
| //! eigener Text "(keins)" statt "(leer)" ??? |
| |
| lcl_DrawOneFrame( pDev, Rectangle( aStartPos, aEndPos ), |
| aCurrent, aColor, bTextBelow, |
| pViewData->GetPPTX(), pViewData->GetPPTY(), pViewData->GetZoomY(), |
| pDoc, pViewData, bLayoutRTL ); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void lcl_DrawHighlight( ScOutputData& rOutputData, ScViewData* pViewData, |
| ScHighlightRanges& rHighlightRanges ) |
| { |
| SCTAB nTab = pViewData->GetTabNo(); |
| sal_uLong nCount = rHighlightRanges.Count(); |
| for (sal_uLong i=0; i<nCount; i++) |
| { |
| ScHighlightEntry* pEntry = rHighlightRanges.GetObject( i ); |
| if (pEntry) |
| { |
| ScRange aRange = pEntry->aRef; |
| if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() ) |
| { |
| rOutputData.DrawRefMark( |
| aRange.aStart.Col(), aRange.aStart.Row(), |
| aRange.aEnd.Col(), aRange.aEnd.Row(), |
| pEntry->aColor, sal_False ); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void ScGridWindow::DoInvertRect( const Rectangle& rPixel ) |
| { |
| // Invert( PixelToLogic(rPixel) ); |
| |
| if ( rPixel == aInvertRect ) |
| aInvertRect = Rectangle(); // aufheben |
| else |
| { |
| DBG_ASSERT( aInvertRect.IsEmpty(), "DoInvertRect nicht paarig" ); |
| |
| aInvertRect = rPixel; // neues Rechteck merken |
| } |
| |
| UpdateHeaderOverlay(); // uses aInvertRect |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void __EXPORT ScGridWindow::PrePaint() |
| { |
| // forward PrePaint to DrawingLayer |
| ScTabViewShell* pTabViewShell = pViewData->GetViewShell(); |
| |
| if(pTabViewShell) |
| { |
| SdrView* pDrawView = pTabViewShell->GetSdrView(); |
| |
| if(pDrawView) |
| { |
| pDrawView->PrePaint(); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void __EXPORT ScGridWindow::Paint( const Rectangle& rRect ) |
| { |
| //TODO/LATER: how to get environment? Do we need that?! |
| /* |
| ScDocShell* pDocSh = pViewData->GetDocShell(); |
| SvInPlaceEnvironment* pEnv = pDocSh->GetIPEnv(); |
| if (pEnv && pEnv->GetRectsChangedLockCount()) |
| { |
| Invalidate(rRect); |
| return; |
| }*/ |
| |
| ScDocument* pDoc = pViewData->GetDocument(); |
| if ( pDoc->IsInInterpreter() ) |
| { |
| // via Reschedule, interpretierende Zellen nicht nochmal anstossen |
| // hier kein Invalidate, sonst kommt z.B. eine Error-Box nie an die Reihe |
| // (Bug 36381). Durch bNeedsRepaint wird spaeter alles nochmal gemalt. |
| |
| if ( bNeedsRepaint ) |
| { |
| //! Rechtecke zusammenfassen? |
| aRepaintPixel = Rectangle(); // mehrfach -> alles painten |
| } |
| else |
| { |
| bNeedsRepaint = sal_True; |
| aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich |
| } |
| return; |
| } |
| |
| // #i117893# If GetSizePixel needs to call the resize handler, the resulting nested Paint call |
| // (possibly for a larger rectangle) has to be allowed. Call GetSizePixel before setting bIsInPaint. |
| GetSizePixel(); |
| |
| if (bIsInPaint) |
| return; |
| |
| bIsInPaint = sal_True; |
| |
| Rectangle aPixRect = LogicToPixel( rRect ); |
| |
| SCCOL nX1 = pViewData->GetPosX(eHWhich); |
| SCROW nY1 = pViewData->GetPosY(eVWhich); |
| |
| SCTAB nTab = pViewData->GetTabNo(); |
| |
| double nPPTX = pViewData->GetPPTX(); |
| double nPPTY = pViewData->GetPPTY(); |
| |
| Rectangle aMirroredPixel = aPixRect; |
| if ( pDoc->IsLayoutRTL( nTab ) ) |
| { |
| // mirror and swap |
| long nWidth = GetSizePixel().Width(); |
| aMirroredPixel.Left() = nWidth - 1 - aPixRect.Right(); |
| aMirroredPixel.Right() = nWidth - 1 - aPixRect.Left(); |
| } |
| |
| long nScrX = ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX ); |
| while ( nScrX <= aMirroredPixel.Left() && nX1 < MAXCOL ) |
| { |
| ++nX1; |
| nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX ); |
| } |
| SCCOL nX2 = nX1; |
| while ( nScrX <= aMirroredPixel.Right() && nX2 < MAXCOL ) |
| { |
| ++nX2; |
| nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX ); |
| } |
| |
| long nScrY = 0; |
| ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, MAXROW, nPPTY, pDoc, nTab); |
| SCROW nY2 = nY1; |
| if (nScrY <= aPixRect.Bottom() && nY2 < MAXROW) |
| { |
| ++nY2; |
| ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, MAXROW, nPPTY, pDoc, nTab); |
| } |
| |
| Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // nicht weiterzeichnen |
| |
| bIsInPaint = sal_False; |
| } |
| |
| // |
| // Draw ---------------------------------------------------------------- |
| // |
| |
| void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode ) |
| { |
| ScModule* pScMod = SC_MOD(); |
| sal_Bool bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg(); |
| sal_Bool bGridFirst = sal_True; //! entscheiden!!! |
| |
| if (pViewData->IsMinimized()) |
| return; |
| |
| PutInOrder( nX1, nX2 ); |
| PutInOrder( nY1, nY2 ); |
| |
| DBG_ASSERT( ValidCol(nX2) && ValidRow(nY2), "GridWin Draw Bereich zu gross" ); |
| |
| SCCOL nPosX = pViewData->GetPosX( eHWhich ); |
| SCROW nPosY = pViewData->GetPosY( eVWhich ); |
| if (nX2 < nPosX || nY2 < nPosY) |
| return; // unsichtbar |
| if (nX1 < nPosX) nX1 = nPosX; |
| if (nY1 < nPosY) nY1 = nPosY; |
| |
| SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); |
| if (nXRight > MAXCOL) nXRight = MAXCOL; |
| SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); |
| if (nYBottom > MAXROW) nYBottom = MAXROW; |
| |
| // Store the current visible range. |
| maVisibleRange.mnCol1 = nPosX; |
| maVisibleRange.mnCol2 = nXRight; |
| maVisibleRange.mnRow1 = nPosY; |
| maVisibleRange.mnRow2 = nYBottom; |
| |
| if (nX1 > nXRight || nY1 > nYBottom) |
| return; // unsichtbar |
| if (nX2 > nXRight) nX2 = nXRight; |
| if (nY2 > nYBottom) nY2 = nYBottom; |
| |
| if ( eMode != SC_UPDATE_MARKS ) |
| if (nX2 < nXRight) |
| nX2 = nXRight; // zum Weiterzeichnen |
| |
| // ab hier kein return mehr |
| |
| ++nPaintCount; // merken, dass gemalt wird (wichtig beim Invertieren) |
| |
| ScDocShell* pDocSh = pViewData->GetDocShell(); |
| ScDocument* pDoc = pDocSh->GetDocument(); |
| SCTAB nTab = pViewData->GetTabNo(); |
| |
| pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab ); |
| |
| Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); |
| long nMirrorWidth = GetSizePixel().Width(); |
| sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| if ( bLayoutRTL ) |
| { |
| long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X(); |
| nMirrorWidth = aScrPos.X() - nEndPixel; |
| aScrPos.X() = nEndPixel + 1; |
| } |
| |
| long nScrX = aScrPos.X(); |
| long nScrY = aScrPos.Y(); |
| |
| SCCOL nCurX = pViewData->GetCurX(); |
| SCROW nCurY = pViewData->GetCurY(); |
| SCCOL nCurEndX = nCurX; |
| SCROW nCurEndY = nCurY; |
| pDoc->ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab ); |
| sal_Bool bCurVis = nCursorHideCount==0 && |
| ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 ); |
| |
| // AutoFill-Anfasser |
| if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab && |
| ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) ) |
| { |
| SCCOL nHdlX = aAutoMarkPos.Col(); |
| SCROW nHdlY = aAutoMarkPos.Row(); |
| pDoc->ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab ); |
| bCurVis = ( nHdlX+1 >= nX1 && nHdlX <= nX2 && nHdlY+1 >= nY1 && nHdlY <= nY2 ); |
| // links und oben ist nicht betroffen |
| |
| //! AutoFill-Anfasser alleine (ohne Cursor) zeichnen ??? |
| } |
| |
| double nPPTX = pViewData->GetPPTX(); |
| double nPPTY = pViewData->GetPPTY(); |
| |
| const ScViewOptions& rOpts = pViewData->GetOptions(); |
| sal_Bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS ); |
| sal_Bool bMarkClipped = rOpts.GetOption( VOPT_CLIPMARKS ); |
| |
| // Datenblock |
| |
| ScTableInfo aTabInfo; |
| pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, |
| nPPTX, nPPTY, sal_False, bFormulaMode, |
| &pViewData->GetMarkData() ); |
| |
| //-------------------------------------------------------------------- |
| |
| Fraction aZoomX = pViewData->GetZoomX(); |
| Fraction aZoomY = pViewData->GetZoomY(); |
| ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, |
| nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY, |
| &aZoomX, &aZoomY ); |
| |
| aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL |
| |
| std::auto_ptr< VirtualDevice > xFmtVirtDev; |
| sal_Bool bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode? |
| |
| if ( bTextWysiwyg ) |
| { |
| // use printer for text formatting |
| |
| OutputDevice* pFmtDev = pDoc->GetPrinter(); |
| pFmtDev->SetMapMode( pViewData->GetLogicMode(eWhich) ); |
| aOutputData.SetFmtDevice( pFmtDev ); |
| } |
| else if ( aZoomX != aZoomY && pViewData->IsOle() ) |
| { |
| // #i45033# For OLE inplace editing with different zoom factors, |
| // use a virtual device with 1/100th mm as text formatting reference |
| |
| xFmtVirtDev.reset( new VirtualDevice ); |
| xFmtVirtDev->SetMapMode( MAP_100TH_MM ); |
| aOutputData.SetFmtDevice( xFmtVirtDev.get() ); |
| |
| bLogicText = sal_True; // use logic MapMode |
| } |
| |
| const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig(); |
| Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, sal_False ).nColor ); |
| if ( aGridColor.GetColor() == COL_TRANSPARENT ) |
| { |
| // use view options' grid color only if color config has "automatic" color |
| aGridColor = rOpts.GetGridColor(); |
| } |
| |
| aOutputData.SetSyntaxMode ( pViewData->IsSyntaxMode() ); |
| aOutputData.SetGridColor ( aGridColor ); |
| aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) ); |
| aOutputData.SetShowFormulas ( bFormulaMode ); |
| aOutputData.SetShowSpellErrors ( pDoc->GetDocOptions().IsAutoSpell() ); |
| aOutputData.SetMarkClipped ( bMarkClipped ); |
| |
| aOutputData.SetUseStyleColor( sal_True ); // always set in table view |
| |
| aOutputData.SetEditObject( GetEditObject() ); |
| aOutputData.SetViewShell( pViewData->GetViewShell() ); |
| |
| sal_Bool bGrid = rOpts.GetOption( VOPT_GRID ); |
| sal_Bool bPage = rOpts.GetOption( VOPT_PAGEBREAKS ); |
| |
| if ( eMode == SC_UPDATE_CHANGED ) |
| { |
| aOutputData.FindChanged(); |
| aOutputData.SetSingleGrid(sal_True); |
| } |
| |
| sal_Bool bPageMode = pViewData->IsPagebreakMode(); |
| if (bPageMode) // nach FindChanged |
| { |
| // SetPagebreakMode initialisiert auch bPrinted Flags |
| aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() ); |
| } |
| |
| EditView* pEditView = NULL; |
| sal_Bool bEditMode = pViewData->HasEditView(eWhich); |
| if ( bEditMode && pViewData->GetRefTabNo() == nTab ) |
| { |
| SCCOL nEditCol; |
| SCROW nEditRow; |
| pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); |
| SCCOL nEditEndCol = pViewData->GetEditEndCol(); |
| SCROW nEditEndRow = pViewData->GetEditEndRow(); |
| |
| if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 ) |
| aOutputData.SetEditCell( nEditCol, nEditRow ); |
| else |
| bEditMode = sal_False; |
| |
| // nur Edit-Area zu zeichnen? |
| //! dann muss trotzdem noch der Rand / das Gitter gemalt werden! |
| |
| // if ( nEditCol <= nX1 && nEditEndCol >= nX2 && nEditRow <= nY1 && nEditEndRow >= nY2 ) |
| // bOnlyEdit = sal_True; |
| } |
| |
| // define drawing layer map mode and paint rectangle |
| const MapMode aDrawMode = GetDrawMapMode(); |
| Rectangle aDrawingRectLogic; |
| |
| { |
| // get drawing pixel rect |
| Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); |
| |
| // correct for border (left/right) |
| if(MAXCOL == nX2) |
| { |
| if(bLayoutRTL) |
| { |
| aDrawingRectPixel.Left() = 0L; |
| } |
| else |
| { |
| aDrawingRectPixel.Right() = GetOutputSizePixel().getWidth(); |
| } |
| } |
| |
| // correct for border (bottom) |
| if(MAXROW == nY2) |
| { |
| aDrawingRectPixel.Bottom() = GetOutputSizePixel().getHeight(); |
| } |
| |
| // get logic positions |
| aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode); |
| } |
| |
| // not necessary with overlay |
| // if (bCurVis) |
| // HideCursor(); |
| |
| OutputDevice* pContentDev = this; // device for document content, used by overlay manager |
| SdrPaintWindow* pTargetPaintWindow = 0; // #i74769# work with SdrPaintWindow directly |
| |
| { |
| // init redraw |
| ScTabViewShell* pTabViewShell = pViewData->GetViewShell(); |
| |
| if(pTabViewShell) |
| { |
| MapMode aCurrentMapMode(pContentDev->GetMapMode()); |
| pContentDev->SetMapMode(aDrawMode); |
| SdrView* pDrawView = pTabViewShell->GetSdrView(); |
| |
| if(pDrawView) |
| { |
| // #i74769# Use new BeginDrawLayers() interface |
| Region aDrawingRegion(aDrawingRectLogic); |
| pTargetPaintWindow = pDrawView->BeginDrawLayers(this, aDrawingRegion); |
| OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)"); |
| |
| // #i74769# get target device from SdrPaintWindow, this may be the prerender |
| // device now, too. |
| pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice()); |
| aOutputData.SetContentDevice( pContentDev ); |
| } |
| |
| pContentDev->SetMapMode(aCurrentMapMode); |
| } |
| } |
| |
| // Rand (Wiese) (Pixel) |
| if ( nX2==MAXCOL || nY2==MAXROW ) |
| { |
| // save MapMode and set to pixel |
| MapMode aCurrentMapMode(pContentDev->GetMapMode()); |
| pContentDev->SetMapMode(MAP_PIXEL); |
| |
| Rectangle aPixRect = Rectangle( Point(), GetOutputSizePixel() ); |
| pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor ); |
| pContentDev->SetLineColor(); |
| if ( nX2==MAXCOL ) |
| { |
| Rectangle aDrawRect( aPixRect ); |
| if ( bLayoutRTL ) |
| aDrawRect.Right() = nScrX - 1; |
| else |
| aDrawRect.Left() = nScrX + aOutputData.GetScrW(); |
| if (aDrawRect.Right() >= aDrawRect.Left()) |
| pContentDev->DrawRect( aDrawRect ); |
| } |
| if ( nY2==MAXROW ) |
| { |
| Rectangle aDrawRect( aPixRect ); |
| aDrawRect.Top() = nScrY + aOutputData.GetScrH(); |
| if ( nX2==MAXCOL ) |
| { |
| // no double painting of the corner |
| if ( bLayoutRTL ) |
| aDrawRect.Left() = nScrX; |
| else |
| aDrawRect.Right() = nScrX + aOutputData.GetScrW() - 1; |
| } |
| if (aDrawRect.Bottom() >= aDrawRect.Top()) |
| pContentDev->DrawRect( aDrawRect ); |
| } |
| |
| // restore MapMode |
| pContentDev->SetMapMode(aCurrentMapMode); |
| } |
| |
| if ( pDoc->HasBackgroundDraw( nTab, aDrawingRectLogic ) ) |
| { |
| pContentDev->SetMapMode(MAP_PIXEL); |
| aOutputData.DrawClear(); |
| |
| // Drawing Hintergrund |
| |
| pContentDev->SetMapMode(aDrawMode); |
| DrawRedraw( aOutputData, eMode, SC_LAYER_BACK ); |
| } |
| else |
| aOutputData.SetSolidBackground(sal_True); |
| |
| pContentDev->SetMapMode(MAP_PIXEL); |
| aOutputData.DrawBackground(); |
| if ( bGridFirst && ( bGrid || bPage ) ) |
| aOutputData.DrawGrid( bGrid, bPage ); |
| if ( bPageMode ) |
| { |
| // #87655# DrawPagePreview draws complete lines/page numbers, must always be clipped |
| if ( aOutputData.SetChangedClip() ) |
| { |
| DrawPagePreview(nX1,nY1,nX2,nY2, pContentDev); |
| pContentDev->SetClipRegion(); |
| } |
| } |
| aOutputData.DrawShadow(); |
| aOutputData.DrawFrame(); |
| if ( !bLogicText ) |
| aOutputData.DrawStrings(sal_False); // in pixel MapMode |
| |
| // edit cells and printer-metrics text must be before the buttons |
| // (DataPilot buttons contain labels in UI font) |
| |
| pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich)); |
| if ( bLogicText ) |
| aOutputData.DrawStrings(sal_True); // in logic MapMode if bTextWysiwyg is set |
| aOutputData.DrawEdit(sal_True); |
| pContentDev->SetMapMode(MAP_PIXEL); |
| |
| // Autofilter- und Pivot-Buttons |
| |
| DrawButtons( nX1, nY1, nX2, nY2, aTabInfo, pContentDev ); // Pixel |
| |
| // Notiz-Anzeiger |
| |
| if ( rOpts.GetOption( VOPT_NOTES ) ) |
| aOutputData.DrawNoteMarks(); |
| |
| if ( !bGridFirst && ( bGrid || bPage ) ) |
| { |
| aOutputData.DrawGrid( bGrid, bPage ); |
| } |
| aOutputData.DrawClipMarks(); |
| |
| // Szenario / ChangeTracking muss auf jeden Fall nach DrawGrid sein, auch bei !bGridFirst |
| |
| //! Test, ob ChangeTrack-Anzeige aktiv ist |
| //! Szenario-Rahmen per View-Optionen abschaltbar? |
| |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| ScHighlightRanges* pHigh = pViewData->GetView()->GetHighlightRanges(); |
| sal_Bool bHasScenario = ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ); |
| sal_Bool bHasChange = ( pDoc->GetChangeTrack() != NULL ); |
| |
| if ( bHasChange || bHasScenario || pHigh != NULL ) |
| { |
| |
| //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!) |
| |
| sal_Bool bAny = sal_True; |
| if (eMode == SC_UPDATE_CHANGED) |
| bAny = aOutputData.SetChangedClip(); |
| if (bAny) |
| { |
| if ( bHasChange ) |
| aOutputData.DrawChangeTrack(); |
| |
| if ( bHasScenario ) |
| lcl_DrawScenarioFrames( pContentDev, pViewData, eWhich, nX1,nY1,nX2,nY2 ); |
| |
| if ( pHigh ) |
| lcl_DrawHighlight( aOutputData, pViewData, *pHigh ); |
| |
| if (eMode == SC_UPDATE_CHANGED) |
| pContentDev->SetClipRegion(); |
| } |
| } |
| |
| // Drawing Vordergrund |
| |
| pContentDev->SetMapMode(aDrawMode); |
| |
| DrawRedraw( aOutputData, eMode, SC_LAYER_FRONT ); |
| DrawRedraw( aOutputData, eMode, SC_LAYER_INTERN ); |
| DrawSdrGrid( aDrawingRectLogic, pContentDev ); |
| |
| if (!bIsInScroll) // Drawing Markierungen |
| { |
| if(eMode == SC_UPDATE_CHANGED && aOutputData.SetChangedClip()) |
| { |
| pContentDev->SetClipRegion(); |
| } |
| |
| //sal_Bool bDraw = sal_True; |
| //if (eMode == SC_UPDATE_CHANGED) |
| // bDraw = NeedDrawMarks() && aOutputData.SetChangedClip(); |
| //if (bDraw) |
| //{ |
| // DrawMarks(); |
| // if (eMode == SC_UPDATE_CHANGED) |
| // pContentDev->SetClipRegion(); |
| //} |
| } |
| |
| pContentDev->SetMapMode(MAP_PIXEL); |
| |
| #ifdef OLD_SELECTION_PAINT |
| if (pViewData->IsActive()) |
| aOutputData.DrawMark( this ); |
| #endif |
| |
| if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() ) |
| { |
| // The AutoFill shrink area has an own overlay now |
| #if 0 |
| // Schraffur beim Loeschen per AutoFill |
| if ( pViewData->GetRefType() == SC_REFTYPE_FILL ) |
| { |
| ScRange aRange; |
| if ( pViewData->GetDelMark( aRange ) ) |
| { |
| if ( aRange.aStart.Col() < nX1 ) aRange.aStart.SetCol(nX1); |
| if ( aRange.aEnd.Col() > nX2 ) aRange.aEnd.SetCol(nX2); |
| if ( aRange.aStart.Row() < nY1 ) aRange.aStart.SetRow(nY1); |
| if ( aRange.aEnd.Row() > nY2 ) aRange.aEnd.SetRow(nY2); |
| if ( aRange.aStart.Col() <= aRange.aEnd.Col() && |
| aRange.aStart.Row() <= aRange.aEnd.Row() ) |
| { |
| Point aStart = pViewData->GetScrPos( aRange.aStart.Col(), |
| aRange.aStart.Row(), eWhich ); |
| Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1, |
| aRange.aEnd.Row()+1, eWhich ); |
| aEnd.X() -= 1; |
| aEnd.Y() -= 1; |
| |
| // Markierung aufheben - roter Rahmen bleibt stehen |
| Rectangle aRect( aStart,aEnd ); |
| Invert( aRect, INVERT_HIGHLIGHT ); |
| |
| //! Delete-Bereich extra kennzeichnen?!?!? |
| } |
| } |
| } |
| #endif |
| |
| Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor ); |
| aOutputData.DrawRefMark( pViewData->GetRefStartX(), pViewData->GetRefStartY(), |
| pViewData->GetRefEndX(), pViewData->GetRefEndY(), |
| aRefColor, sal_False ); |
| } |
| |
| // Range-Finder |
| |
| ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); |
| if (pHdl) |
| { |
| ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); |
| if ( pRangeFinder && !pRangeFinder->IsHidden() && |
| pRangeFinder->GetDocName() == pDocSh->GetTitle() ) |
| { |
| sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); |
| for (sal_uInt16 i=0; i<nCount; i++) |
| { |
| ScRangeFindData* pData = pRangeFinder->GetObject(i); |
| if (pData) |
| { |
| ScRange aRef = pData->aRef; |
| aRef.Justify(); |
| if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab ) |
| aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(), |
| aRef.aEnd.Col(), aRef.aEnd.Row(), |
| Color( ScRangeFindList::GetColorName( i ) ), |
| sal_True ); |
| } |
| } |
| } |
| } |
| |
| { |
| // end redraw |
| ScTabViewShell* pTabViewShell = pViewData->GetViewShell(); |
| |
| if(pTabViewShell) |
| { |
| MapMode aCurrentMapMode(pContentDev->GetMapMode()); |
| pContentDev->SetMapMode(aDrawMode); |
| SdrView* pDrawView = pTabViewShell->GetSdrView(); |
| |
| if(pDrawView) |
| { |
| // #i74769# work with SdrPaintWindow directly |
| pDrawView->EndDrawLayers(*pTargetPaintWindow, true); |
| } |
| |
| pContentDev->SetMapMode(aCurrentMapMode); |
| } |
| } |
| |
| // InPlace Edit-View |
| // moved after EndDrawLayers() to get it outside the overlay buffer and |
| // on top of everything |
| if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) ) |
| { |
| //! use pContentDev for EditView? |
| SetMapMode(MAP_PIXEL); |
| SCCOL nCol1 = pViewData->GetEditStartCol(); |
| SCROW nRow1 = pViewData->GetEditStartRow(); |
| SCCOL nCol2 = pViewData->GetEditEndCol(); |
| SCROW nRow2 = pViewData->GetEditEndRow(); |
| SetLineColor(); |
| SetFillColor( pEditView->GetBackgroundColor() ); |
| Point aStart = pViewData->GetScrPos( nCol1, nRow1, eWhich ); |
| Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eWhich ); |
| aEnd.X() -= 2 * nLayoutSign; // don't overwrite grid |
| aEnd.Y() -= 2; |
| DrawRect( Rectangle( aStart,aEnd ) ); |
| |
| SetMapMode(pViewData->GetLogicMode()); |
| pEditView->Paint( PixelToLogic( Rectangle( Point( nScrX, nScrY ), |
| Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) ) ); |
| SetMapMode(MAP_PIXEL); |
| } |
| |
| if (pViewData->HasEditView(eWhich)) |
| { |
| // flush OverlayManager before changing the MapMode |
| flushOverlayManager(); |
| |
| // set MapMode for text edit |
| SetMapMode(pViewData->GetLogicMode()); |
| } |
| else |
| SetMapMode(aDrawMode); |
| |
| if ( pNoteMarker ) |
| pNoteMarker->Draw(); // ueber den Cursor, im Drawing-MapMode |
| |
| //DrawStartTimer(); // fuer bunte Handles ohne System-Clipping |
| |
| // |
| // Wenn waehrend des Paint etwas invertiert wurde (Selektion geaendert aus Basic-Macro), |
| // ist das jetzt durcheinandergekommen und es muss neu gemalt werden |
| // |
| |
| DBG_ASSERT(nPaintCount, "nPaintCount falsch"); |
| --nPaintCount; |
| if (!nPaintCount) |
| CheckNeedsRepaint(); |
| } |
| |
| void ScGridWindow::CheckNeedsRepaint() |
| { |
| // called at the end of painting, and from timer after background text width calculation |
| |
| if (bNeedsRepaint) |
| { |
| bNeedsRepaint = sal_False; |
| if (aRepaintPixel.IsEmpty()) |
| Invalidate(); |
| else |
| Invalidate(PixelToLogic(aRepaintPixel)); |
| aRepaintPixel = Rectangle(); |
| |
| // selection function in status bar might also be invalid |
| SfxBindings& rBindings = pViewData->GetBindings(); |
| rBindings.Invalidate( SID_STATUS_SUM ); |
| rBindings.Invalidate( SID_ATTR_SIZE ); |
| rBindings.Invalidate( SID_TABLE_CELL ); |
| } |
| } |
| |
| void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev ) |
| { |
| ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData(); |
| if (pPageData) |
| { |
| ScDocument* pDoc = pViewData->GetDocument(); |
| SCTAB nTab = pViewData->GetTabNo(); |
| Size aWinSize = GetOutputSizePixel(); |
| const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig(); |
| Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor ); |
| Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor ); |
| |
| String aPageText = ScGlobal::GetRscString( STR_PAGE ); |
| if ( nPageScript == 0 ) |
| { |
| // get script type of translated "Page" string only once |
| nPageScript = pDoc->GetStringScriptType( aPageText ); |
| if (nPageScript == 0) |
| nPageScript = ScGlobal::GetDefaultScriptType(); |
| } |
| aPageText += ' '; |
| |
| Font aFont; |
| ScEditEngineDefaulter* pEditEng = NULL; |
| const ScPatternAttr& rDefPattern = ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)); |
| if ( nPageScript == SCRIPTTYPE_LATIN ) |
| { |
| // use single font and call DrawText directly |
| rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK ); |
| aFont.SetColor( Color( COL_LIGHTGRAY ) ); |
| // font size is set as needed |
| } |
| else |
| { |
| // use EditEngine to draw mixed-script string |
| pEditEng = new ScEditEngineDefaulter( EditEngine::CreatePool(), sal_True ); |
| pEditEng->SetRefMapMode( pContentDev->GetMapMode() ); |
| SfxItemSet* pEditDefaults = new SfxItemSet( pEditEng->GetEmptyItemSet() ); |
| rDefPattern.FillEditItemSet( pEditDefaults ); |
| pEditDefaults->Put( SvxColorItem( Color( COL_LIGHTGRAY ), EE_CHAR_COLOR ) ); |
| pEditEng->SetDefaults( pEditDefaults ); |
| } |
| |
| sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() ); |
| for (sal_uInt16 nPos=0; nPos<nCount; nPos++) |
| { |
| ScPrintRangeData& rData = pPageData->GetData(nPos); |
| ScRange aRange = rData.GetPrintRange(); |
| if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 && |
| aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 ) |
| { |
| // 3 Pixel Rahmen um den Druckbereich |
| // (mittlerer Pixel auf den Gitterlinien) |
| |
| pContentDev->SetLineColor(); |
| if (rData.IsAutomatic()) |
| pContentDev->SetFillColor( aAutomatic ); |
| else |
| pContentDev->SetFillColor( aManual ); |
| |
| Point aStart = pViewData->GetScrPos( |
| aRange.aStart.Col(), aRange.aStart.Row(), eWhich, sal_True ); |
| Point aEnd = pViewData->GetScrPos( |
| aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, sal_True ); |
| aStart.X() -= 2; |
| aStart.Y() -= 2; |
| |
| // Ueberlaeufe verhindern: |
| if ( aStart.X() < -10 ) aStart.X() = -10; |
| if ( aStart.Y() < -10 ) aStart.Y() = -10; |
| if ( aEnd.X() > aWinSize.Width() + 10 ) |
| aEnd.X() = aWinSize.Width() + 10; |
| if ( aEnd.Y() > aWinSize.Height() + 10 ) |
| aEnd.Y() = aWinSize.Height() + 10; |
| |
| pContentDev->DrawRect( Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) ); |
| pContentDev->DrawRect( Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) ); |
| pContentDev->DrawRect( Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) ); |
| pContentDev->DrawRect( Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) ); |
| |
| // Seitenumbrueche |
| //! anders darstellen (gestrichelt ????) |
| |
| size_t nColBreaks = rData.GetPagesX(); |
| const SCCOL* pColEnd = rData.GetPageEndX(); |
| size_t nColPos; |
| for (nColPos=0; nColPos+1<nColBreaks; nColPos++) |
| { |
| SCCOL nBreak = pColEnd[nColPos]+1; |
| if ( nBreak >= nX1 && nBreak <= nX2+1 ) |
| { |
| //! hidden suchen |
| if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL) |
| pContentDev->SetFillColor( aManual ); |
| else |
| pContentDev->SetFillColor( aAutomatic ); |
| Point aBreak = pViewData->GetScrPos( |
| nBreak, aRange.aStart.Row(), eWhich, sal_True ); |
| pContentDev->DrawRect( Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) ); |
| } |
| } |
| |
| size_t nRowBreaks = rData.GetPagesY(); |
| const SCROW* pRowEnd = rData.GetPageEndY(); |
| size_t nRowPos; |
| for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++) |
| { |
| SCROW nBreak = pRowEnd[nRowPos]+1; |
| if ( nBreak >= nY1 && nBreak <= nY2+1 ) |
| { |
| //! hidden suchen |
| if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL) |
| pContentDev->SetFillColor( aManual ); |
| else |
| pContentDev->SetFillColor( aAutomatic ); |
| Point aBreak = pViewData->GetScrPos( |
| aRange.aStart.Col(), nBreak, eWhich, sal_True ); |
| pContentDev->DrawRect( Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) ); |
| } |
| } |
| |
| // Seitenzahlen |
| |
| SCROW nPrStartY = aRange.aStart.Row(); |
| for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++) |
| { |
| SCROW nPrEndY = pRowEnd[nRowPos]; |
| if ( nPrEndY >= nY1 && nPrStartY <= nY2 ) |
| { |
| SCCOL nPrStartX = aRange.aStart.Col(); |
| for (nColPos=0; nColPos<nColBreaks; nColPos++) |
| { |
| SCCOL nPrEndX = pColEnd[nColPos]; |
| if ( nPrEndX >= nX1 && nPrStartX <= nX2 ) |
| { |
| Point aPageStart = pViewData->GetScrPos( |
| nPrStartX, nPrStartY, eWhich, sal_True ); |
| Point aPageEnd = pViewData->GetScrPos( |
| nPrEndX+1,nPrEndY+1, eWhich, sal_True ); |
| |
| long nPageNo = rData.GetFirstPage(); |
| if ( rData.IsTopDown() ) |
| nPageNo += ((long)nColPos)*nRowBreaks+nRowPos; |
| else |
| nPageNo += ((long)nRowPos)*nColBreaks+nColPos; |
| String aPageStr = aPageText; |
| aPageStr += String::CreateFromInt32(nPageNo); |
| |
| if ( pEditEng ) |
| { |
| // find right font size with EditEngine |
| long nHeight = 100; |
| pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); |
| pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); |
| pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); |
| pEditEng->SetText( aPageStr ); |
| Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() ); |
| |
| // 40% of width or 60% of height |
| long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width(); |
| long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height(); |
| nHeight = Min(nSizeX,nSizeY); |
| pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); |
| pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); |
| pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); |
| |
| // centered output with EditEngine |
| Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() ); |
| Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2, |
| (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 ); |
| pEditEng->Draw( pContentDev, aPos ); |
| } |
| else |
| { |
| // find right font size for DrawText |
| aFont.SetSize( Size( 0,100 ) ); |
| pContentDev->SetFont( aFont ); |
| Size aSize100( pContentDev->GetTextWidth( aPageStr ), pContentDev->GetTextHeight() ); |
| |
| // 40% of width or 60% of height |
| long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width(); |
| long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height(); |
| aFont.SetSize( Size( 0,Min(nSizeX,nSizeY) ) ); |
| pContentDev->SetFont( aFont ); |
| |
| // centered output with DrawText |
| Size aTextSize( pContentDev->GetTextWidth( aPageStr ), pContentDev->GetTextHeight() ); |
| Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2, |
| (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 ); |
| pContentDev->DrawText( aPos, aPageStr ); |
| } |
| } |
| nPrStartX = nPrEndX + 1; |
| } |
| } |
| nPrStartY = nPrEndY + 1; |
| } |
| } |
| } |
| |
| delete pEditEng; |
| } |
| } |
| |
| void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2*/, ScTableInfo& rTabInfo, OutputDevice* pContentDev ) |
| { |
| aComboButton.SetOutputDevice( pContentDev ); |
| |
| ScDocument* pDoc = pViewData->GetDocument(); |
| ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc); |
| |
| SCCOL nCol; |
| SCROW nRow; |
| SCSIZE nArrY; |
| SCSIZE nQuery; |
| SCTAB nTab = pViewData->GetTabNo(); |
| ScDBData* pDBData = NULL; |
| ScQueryParam* pQueryParam = NULL; |
| |
| RowInfo* pRowInfo = rTabInfo.mpRowInfo; |
| sal_uInt16 nArrCount = rTabInfo.mnArrCount; |
| |
| sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| |
| Point aOldPos = aComboButton.GetPosPixel(); // Zustand fuer MouseDown/Up |
| Size aOldSize = aComboButton.GetSizePixel(); // merken |
| |
| for (nArrY=1; nArrY+1<nArrCount; nArrY++) |
| { |
| if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged ) |
| { |
| RowInfo* pThisRowInfo = &pRowInfo[nArrY]; |
| |
| nRow = pThisRowInfo->nRowNo; |
| |
| |
| for (nCol=nX1; nCol<=nX2; nCol++) |
| { |
| CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1]; |
| //if several columns merged on a row, there should be only one auto button at the end of the columns. |
| //if several rows merged on a column, the button may be in the middle, so "!pInfo->bVOverlapped" should not be used |
| if ( pInfo->bAutoFilter && !pInfo->bHOverlapped ) |
| { |
| if (!pQueryParam) |
| pQueryParam = new ScQueryParam; |
| |
| sal_Bool bNewData = sal_True; |
| if (pDBData) |
| { |
| SCCOL nStartCol; |
| SCROW nStartRow; |
| SCCOL nEndCol; |
| SCROW nEndRow; |
| SCTAB nAreaTab; |
| pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); |
| if ( nCol >= nStartCol && nCol <= nEndCol && |
| nRow >= nStartRow && nRow <= nEndRow ) |
| bNewData = sal_False; |
| } |
| if (bNewData) |
| { |
| pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); |
| if (pDBData) |
| pDBData->GetQueryParam( *pQueryParam ); |
| else |
| { |
| // can also be part of DataPilot table |
| // DBG_ERROR("Auto-Filter-Button ohne DBData"); |
| } |
| } |
| |
| // pQueryParam kann nur MAXQUERY Eintraege enthalten |
| |
| sal_Bool bSimpleQuery = sal_True; |
| sal_Bool bColumnFound = sal_False; |
| if (!pQueryParam->bInplace) |
| bSimpleQuery = sal_False; |
| for (nQuery=0; nQuery<MAXQUERY && bSimpleQuery; nQuery++) |
| if (pQueryParam->GetEntry(nQuery).bDoQuery) |
| { |
| // hier nicht auf EQUAL beschraenken |
| // (auch bei ">1" soll der Spaltenkopf blau werden) |
| |
| if (pQueryParam->GetEntry(nQuery).nField == nCol) |
| bColumnFound = sal_True; |
| if (nQuery > 0) |
| if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND) |
| bSimpleQuery = sal_False; |
| } |
| |
| bool bArrowState = bSimpleQuery && bColumnFound; |
| long nSizeX; |
| long nSizeY; |
| SCCOL nStartCol= nCol; |
| SCROW nStartRow = nRow; |
| //if address(nCol,nRow) is not the start pos of the merge area, the value of the nSizeX will be incorrect, it will be the length of the cell. |
| //should first get the start pos of the merge area, then get the nSizeX through the start pos. |
| pDoc->ExtendOverlapped(nStartCol, nStartRow,nCol, nRow, nTab);//get nStartCol,nStartRow |
| pViewData->GetMergeSizePixel( nStartCol, nStartRow, nSizeX, nSizeY );//get nSizeX |
| nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY()); |
| Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich ); |
| |
| aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1), bLayoutRTL); |
| aCellBtn.setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL |
| aCellBtn.setDrawBaseButton(false); |
| aCellBtn.setDrawPopupButton(true); |
| aCellBtn.setHasHiddenMember(bArrowState); |
| aCellBtn.draw(); |
| } |
| } |
| } |
| |
| if ( pRowInfo[nArrY].bPushButton && pRowInfo[nArrY].bChanged ) |
| { |
| RowInfo* pThisRowInfo = &pRowInfo[nArrY]; |
| nRow = pThisRowInfo->nRowNo; |
| for (nCol=nX1; nCol<=nX2; nCol++) |
| { |
| CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1]; |
| if ( pInfo->bPushButton && !pInfo->bHOverlapped && !pInfo->bVOverlapped ) |
| { |
| Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich ); |
| long nSizeX; |
| long nSizeY; |
| pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); |
| long nPosX = aScrPos.X(); |
| long nPosY = aScrPos.Y(); |
| // bLayoutRTL is handled in setBoundingBox |
| |
| String aStr; |
| pDoc->GetString(nCol, nRow, nTab, aStr); |
| aCellBtn.setText(aStr); |
| aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1), bLayoutRTL); |
| aCellBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now |
| aCellBtn.setDrawBaseButton(true); |
| aCellBtn.setDrawPopupButton(pInfo->bPopupButton); |
| aCellBtn.setHasHiddenMember(pInfo->bFilterActive); |
| aCellBtn.draw(); |
| } |
| } |
| } |
| |
| if ( bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged ) |
| { |
| Rectangle aRect = GetListValButtonRect( aListValPos ); |
| aComboButton.SetPosPixel( aRect.TopLeft() ); |
| aComboButton.SetSizePixel( aRect.GetSize() ); |
| pContentDev->SetClipRegion( aRect ); |
| aComboButton.Draw( sal_False, sal_False ); |
| pContentDev->SetClipRegion(); // always called from Draw() without clip region |
| aComboButton.SetPosPixel( aOldPos ); // restore old state |
| aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter) |
| } |
| } |
| |
| delete pQueryParam; |
| aComboButton.SetOutputDevice( this ); |
| } |
| |
| Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos ) |
| { |
| ScDocument* pDoc = pViewData->GetDocument(); |
| SCTAB nTab = pViewData->GetTabNo(); |
| sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| |
| ScDDComboBoxButton aButton( this ); // for optimal size |
| Size aBtnSize = aButton.GetSizePixel(); |
| |
| SCCOL nCol = rButtonPos.Col(); |
| SCROW nRow = rButtonPos.Row(); |
| |
| long nCellSizeX; // width of this cell, including merged |
| long nDummy; |
| pViewData->GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy ); |
| |
| // for height, only the cell's row is used, excluding merged cells |
| long nCellSizeY = ScViewData::ToPixel( pDoc->GetRowHeight( nRow, nTab ), pViewData->GetPPTY() ); |
| long nAvailable = nCellSizeX; |
| |
| // left edge of next cell if there is a non-hidden next column |
| SCCOL nNextCol = nCol + 1; |
| const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE )); |
| if ( pMerge->GetColMerge() > 1 ) |
| nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area |
| while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) ) |
| ++nNextCol; |
| sal_Bool bNextCell = ( nNextCol <= MAXCOL ); |
| if ( bNextCell ) |
| nAvailable = ScViewData::ToPixel( pDoc->GetColWidth( nNextCol, nTab ), pViewData->GetPPTX() ); |
| |
| if ( nAvailable < aBtnSize.Width() ) |
| aBtnSize.Width() = nAvailable; |
| if ( nCellSizeY < aBtnSize.Height() ) |
| aBtnSize.Height() = nCellSizeY; |
| |
| Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich, sal_True ); |
| aPos.X() += nCellSizeX * nLayoutSign; // start of next cell |
| if (!bNextCell) |
| aPos.X() -= aBtnSize.Width() * nLayoutSign; // right edge of cell if next cell not available |
| aPos.Y() += nCellSizeY - aBtnSize.Height(); |
| // X remains at the left edge |
| |
| if ( bLayoutRTL ) |
| aPos.X() -= aBtnSize.Width()-1; // align right edge of button with cell border |
| |
| return Rectangle( aPos, aBtnSize ); |
| } |
| |
| sal_Bool ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab ) |
| { |
| ScDocument* pDoc = pViewData->GetDocument(); |
| ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); |
| ScQueryParam aQueryParam; |
| |
| if ( pDBData ) |
| pDBData->GetQueryParam( aQueryParam ); |
| else |
| { |
| DBG_ERROR("Auto-Filter-Button ohne DBData"); |
| } |
| |
| sal_Bool bSimpleQuery = sal_True; |
| sal_Bool bColumnFound = sal_False; |
| SCSIZE nQuery; |
| |
| if ( !aQueryParam.bInplace ) |
| bSimpleQuery = sal_False; |
| |
| // aQueryParam kann nur MAXQUERY Eintraege enthalten |
| |
| for ( nQuery=0; nQuery<MAXQUERY && bSimpleQuery; nQuery++ ) |
| if ( aQueryParam.GetEntry(nQuery).bDoQuery ) |
| { |
| if (aQueryParam.GetEntry(nQuery).nField == nCol) |
| bColumnFound = sal_True; |
| |
| if (nQuery > 0) |
| if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND) |
| bSimpleQuery = sal_False; |
| } |
| |
| return ( bSimpleQuery && bColumnFound ); |
| } |
| |
| void ScGridWindow::DrawComboButton( const Point& rCellPos, |
| long nCellSizeX, |
| long nCellSizeY, |
| sal_Bool bArrowState, |
| sal_Bool bBtnIn ) |
| { |
| Point aScrPos = rCellPos; |
| Size aBtnSize = aComboButton.GetSizePixel(); |
| |
| if ( nCellSizeX < aBtnSize.Width() || nCellSizeY < aBtnSize.Height() ) |
| { |
| if ( nCellSizeX < aBtnSize.Width() ) |
| aBtnSize.Width() = nCellSizeX; |
| |
| if ( nCellSizeY < aBtnSize.Height() ) |
| aBtnSize.Height() = nCellSizeY; |
| |
| aComboButton.SetSizePixel( aBtnSize ); |
| } |
| |
| sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); |
| |
| if ( bLayoutRTL ) |
| aScrPos.X() -= nCellSizeX - 1; |
| else |
| aScrPos.X() += nCellSizeX - aBtnSize.Width(); |
| aScrPos.Y() += nCellSizeY - aBtnSize.Height(); |
| |
| aComboButton.SetPosPixel( aScrPos ); |
| |
| HideCursor(); |
| aComboButton.Draw( bArrowState, bBtnIn ); |
| ShowCursor(); |
| } |
| |
| void ScGridWindow::InvertSimple( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, |
| sal_Bool bTestMerge, sal_Bool bRepeat ) |
| { |
| //! if INVERT_HIGHLIGHT swaps foreground and background (like on Mac), |
| //! use INVERT_HIGHLIGHT only for cells that have no background color set |
| //! (here and in ScOutputData::DrawMark) |
| |
| PutInOrder( nX1, nX2 ); |
| PutInOrder( nY1, nY2 ); |
| |
| ScMarkData& rMark = pViewData->GetMarkData(); |
| ScDocument* pDoc = pViewData->GetDocument(); |
| SCTAB nTab = pViewData->GetTabNo(); |
| |
| sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| |
| SCCOL nTestX2 = nX2; |
| SCROW nTestY2 = nY2; |
| if (bTestMerge) |
| pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab ); |
| |
| SCCOL nPosX = pViewData->GetPosX( eHWhich ); |
| SCROW nPosY = pViewData->GetPosY( eVWhich ); |
| if (nTestX2 < nPosX || nTestY2 < nPosY) |
| return; // unsichtbar |
| SCCOL nRealX1 = nX1; |
| if (nX1 < nPosX) |
| nX1 = nPosX; |
| if (nY1 < nPosY) |
| nY1 = nPosY; |
| |
| SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); |
| if (nXRight > MAXCOL) nXRight = MAXCOL; |
| SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); |
| if (nYBottom > MAXROW) nYBottom = MAXROW; |
| |
| if (nX1 > nXRight || nY1 > nYBottom) |
| return; // unsichtbar |
| if (nX2 > nXRight) nX2 = nXRight; |
| if (nY2 > nYBottom) nY2 = nYBottom; |
| |
| MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); // erst nach den return's !!! |
| |
| double nPPTX = pViewData->GetPPTX(); |
| double nPPTY = pViewData->GetPPTY(); |
| |
| ScInvertMerger aInvert( this ); |
| |
| Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); |
| long nScrY = aScrPos.Y(); |
| sal_Bool bWasHidden = sal_False; |
| for (SCROW nY=nY1; nY<=nY2; nY++) |
| { |
| sal_Bool bFirstRow = ( nY == nPosY ); // first visible row? |
| sal_Bool bDoHidden = sal_False; // versteckte nachholen ? |
| sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab ); |
| sal_Bool bDoRow = ( nHeightTwips != 0 ); |
| if (bDoRow) |
| { |
| if (bTestMerge) |
| if (bWasHidden) // auf versteckte zusammengefasste testen |
| { |
| // --nY; // nY geaendert -> vorherige zeichnen |
| bDoHidden = sal_True; |
| bDoRow = sal_True; |
| } |
| |
| bWasHidden = sal_False; |
| } |
| else |
| { |
| bWasHidden = sal_True; |
| if (bTestMerge) |
| if (nY==nY2) |
| bDoRow = sal_True; // letzte Zeile aus Block |
| } |
| |
| if ( bDoRow ) |
| { |
| SCCOL nLoopEndX = nX2; |
| if (nX2 < nX1) // Rest von zusammengefasst |
| { |
| SCCOL nStartX = nX1; |
| while ( ((const ScMergeFlagAttr*)pDoc-> |
| GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() ) |
| --nStartX; |
| if (nStartX <= nX2) |
| nLoopEndX = nX1; |
| } |
| |
| long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1; |
| long nScrX = aScrPos.X(); |
| for (SCCOL nX=nX1; nX<=nLoopEndX; nX++) |
| { |
| long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX ); |
| if ( nWidth > 0 ) |
| { |
| long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign; |
| if (bTestMerge) |
| { |
| SCROW nThisY = nY; |
| const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab ); |
| const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern-> |
| GetItem(ATTR_MERGE_FLAG); |
| if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) |
| { |
| while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && |
| (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) ) |
| { |
| --nThisY; |
| pPattern = pDoc->GetPattern( nX, nThisY, nTab ); |
| pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); |
| } |
| } |
| |
| // nur Rest von zusammengefasster zu sehen ? |
| SCCOL nThisX = nX; |
| if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 ) |
| { |
| while ( pMergeFlag->IsHorOverlapped() ) |
| { |
| --nThisX; |
| pPattern = pDoc->GetPattern( nThisX, nThisY, nTab ); |
| pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); |
| } |
| } |
| |
| if ( rMark.IsCellMarked( nThisX, nThisY, sal_True ) == bRepeat ) |
| { |
| if ( !pMergeFlag->IsOverlapped() ) |
| { |
| ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); |
| if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0) |
| { |
| Point aEndPos = pViewData->GetScrPos( |
| nThisX + pMerge->GetColMerge(), |
| nThisY + pMerge->GetRowMerge(), eWhich ); |
| if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY ) |
| { |
| aInvert.AddRect( Rectangle( nScrX,nScrY, |
| aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) ); |
| } |
| } |
| else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) |
| { |
| aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); |
| } |
| } |
| } |
| } |
| else // !bTestMerge |
| { |
| if ( rMark.IsCellMarked( nX, nY, sal_True ) == bRepeat && |
| nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) |
| { |
| aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); |
| } |
| } |
| |
| nScrX = nEndX + nLayoutSign; |
| } |
| } |
| nScrY = nEndY + 1; |
| } |
| } |
| |
| aInvert.Flush(); // before restoring MapMode |
| |
| SetMapMode(aOld); |
| |
| CheckInverted(); |
| } |
| |
| void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects ) |
| { |
| // transformed from ScGridWindow::InvertSimple |
| |
| // ScMarkData& rMark = pViewData->GetMarkData(); |
| ScMarkData aMultiMark( pViewData->GetMarkData() ); |
| aMultiMark.SetMarking( sal_False ); |
| aMultiMark.MarkToMulti(); |
| |
| ScDocument* pDoc = pViewData->GetDocument(); |
| SCTAB nTab = pViewData->GetTabNo(); |
| |
| sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| |
| if ( !aMultiMark.IsMultiMarked() ) |
| return; |
| |
| ScRange aMultiRange; |
| aMultiMark.GetMultiMarkArea( aMultiRange ); |
| SCCOL nX1 = aMultiRange.aStart.Col(); |
| SCROW nY1 = aMultiRange.aStart.Row(); |
| SCCOL nX2 = aMultiRange.aEnd.Col(); |
| SCROW nY2 = aMultiRange.aEnd.Row(); |
| |
| PutInOrder( nX1, nX2 ); |
| PutInOrder( nY1, nY2 ); |
| |
| sal_Bool bTestMerge = sal_True; |
| sal_Bool bRepeat = sal_True; |
| |
| SCCOL nTestX2 = nX2; |
| SCROW nTestY2 = nY2; |
| if (bTestMerge) |
| pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab ); |
| |
| SCCOL nPosX = pViewData->GetPosX( eHWhich ); |
| SCROW nPosY = pViewData->GetPosY( eVWhich ); |
| if (nTestX2 < nPosX || nTestY2 < nPosY) |
| return; // unsichtbar |
| SCCOL nRealX1 = nX1; |
| if (nX1 < nPosX) |
| nX1 = nPosX; |
| if (nY1 < nPosY) |
| nY1 = nPosY; |
| |
| SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); |
| if (nXRight > MAXCOL) nXRight = MAXCOL; |
| SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); |
| if (nYBottom > MAXROW) nYBottom = MAXROW; |
| |
| if (nX1 > nXRight || nY1 > nYBottom) |
| return; // unsichtbar |
| if (nX2 > nXRight) nX2 = nXRight; |
| if (nY2 > nYBottom) nY2 = nYBottom; |
| |
| // MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); // erst nach den return's !!! |
| |
| double nPPTX = pViewData->GetPPTX(); |
| double nPPTY = pViewData->GetPPTY(); |
| |
| ScInvertMerger aInvert( &rPixelRects ); |
| |
| Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); |
| long nScrY = aScrPos.Y(); |
| sal_Bool bWasHidden = sal_False; |
| for (SCROW nY=nY1; nY<=nY2; nY++) |
| { |
| sal_Bool bFirstRow = ( nY == nPosY ); // first visible row? |
| sal_Bool bDoHidden = sal_False; // versteckte nachholen ? |
| sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab ); |
| sal_Bool bDoRow = ( nHeightTwips != 0 ); |
| if (bDoRow) |
| { |
| if (bTestMerge) |
| if (bWasHidden) // auf versteckte zusammengefasste testen |
| { |
| bDoHidden = sal_True; |
| bDoRow = sal_True; |
| } |
| |
| bWasHidden = sal_False; |
| } |
| else |
| { |
| bWasHidden = sal_True; |
| if (bTestMerge) |
| if (nY==nY2) |
| bDoRow = sal_True; // letzte Zeile aus Block |
| } |
| |
| if ( bDoRow ) |
| { |
| SCCOL nLoopEndX = nX2; |
| if (nX2 < nX1) // Rest von zusammengefasst |
| { |
| SCCOL nStartX = nX1; |
| while ( ((const ScMergeFlagAttr*)pDoc-> |
| GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() ) |
| --nStartX; |
| if (nStartX <= nX2) |
| nLoopEndX = nX1; |
| } |
| |
| long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1; |
| long nScrX = aScrPos.X(); |
| for (SCCOL nX=nX1; nX<=nLoopEndX; nX++) |
| { |
| long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX ); |
| if ( nWidth > 0 ) |
| { |
| long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign; |
| if (bTestMerge) |
| { |
| SCROW nThisY = nY; |
| const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab ); |
| const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern-> |
| GetItem(ATTR_MERGE_FLAG); |
| if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) |
| { |
| while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && |
| (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) ) |
| { |
| --nThisY; |
| pPattern = pDoc->GetPattern( nX, nThisY, nTab ); |
| pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); |
| } |
| } |
| |
| // nur Rest von zusammengefasster zu sehen ? |
| SCCOL nThisX = nX; |
| if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 ) |
| { |
| while ( pMergeFlag->IsHorOverlapped() ) |
| { |
| --nThisX; |
| pPattern = pDoc->GetPattern( nThisX, nThisY, nTab ); |
| pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); |
| } |
| } |
| |
| if ( aMultiMark.IsCellMarked( nThisX, nThisY, sal_True ) == bRepeat ) |
| { |
| if ( !pMergeFlag->IsOverlapped() ) |
| { |
| ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); |
| if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0) |
| { |
| Point aEndPos = pViewData->GetScrPos( |
| nThisX + pMerge->GetColMerge(), |
| nThisY + pMerge->GetRowMerge(), eWhich ); |
| if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY ) |
| { |
| aInvert.AddRect( Rectangle( nScrX,nScrY, |
| aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) ); |
| } |
| } |
| else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) |
| { |
| aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); |
| } |
| } |
| } |
| } |
| else // !bTestMerge |
| { |
| if ( aMultiMark.IsCellMarked( nX, nY, sal_True ) == bRepeat && |
| nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) |
| { |
| aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); |
| } |
| } |
| |
| nScrX = nEndX + nLayoutSign; |
| } |
| } |
| nScrY = nEndY + 1; |
| } |
| } |
| |
| // aInvert.Flush(); // before restoring MapMode |
| } |
| |
| // ------------------------------------------------------------------------- |
| |
| //UNUSED2008-05 void ScGridWindow::DrawDragRect( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 if ( nX2 < pViewData->GetPosX(eHWhich) || nY2 < pViewData->GetPosY(eVWhich) ) |
| //UNUSED2008-05 return; |
| //UNUSED2008-05 |
| //UNUSED2008-05 Update(); // wegen XOR |
| //UNUSED2008-05 |
| //UNUSED2008-05 MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); |
| //UNUSED2008-05 |
| //UNUSED2008-05 SCTAB nTab = pViewData->GetTabNo(); |
| //UNUSED2008-05 |
| //UNUSED2008-05 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich)); |
| //UNUSED2008-05 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich)); |
| //UNUSED2008-05 if (nX1 < nPosX) nX1 = nPosX; |
| //UNUSED2008-05 if (nX2 < nPosX) nX2 = nPosX; |
| //UNUSED2008-05 if (nY1 < nPosY) nY1 = nPosY; |
| //UNUSED2008-05 if (nY2 < nPosY) nY2 = nPosY; |
| //UNUSED2008-05 |
| //UNUSED2008-05 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) ); |
| //UNUSED2008-05 |
| //UNUSED2008-05 long nSizeXPix=0; |
| //UNUSED2008-05 long nSizeYPix=0; |
| //UNUSED2008-05 ScDocument* pDoc = pViewData->GetDocument(); |
| //UNUSED2008-05 double nPPTX = pViewData->GetPPTX(); |
| //UNUSED2008-05 double nPPTY = pViewData->GetPPTY(); |
| //UNUSED2008-05 SCCOLROW i; |
| //UNUSED2008-05 |
| //UNUSED2008-05 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| //UNUSED2008-05 long nLayoutSign = bLayoutRTL ? -1 : 1; |
| //UNUSED2008-05 |
| //UNUSED2008-05 if (ValidCol(nX2) && nX2>=nX1) |
| //UNUSED2008-05 for (i=nX1; i<=nX2; i++) |
| //UNUSED2008-05 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX ); |
| //UNUSED2008-05 else |
| //UNUSED2008-05 { |
| //UNUSED2008-05 aScrPos.X() -= nLayoutSign; |
| //UNUSED2008-05 nSizeXPix += 2; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 if (ValidRow(nY2) && nY2>=nY1) |
| //UNUSED2008-05 for (i=nY1; i<=nY2; i++) |
| //UNUSED2008-05 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY ); |
| //UNUSED2008-05 else |
| //UNUSED2008-05 { |
| //UNUSED2008-05 aScrPos.Y() -= 1; |
| //UNUSED2008-05 nSizeYPix += 2; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 aScrPos.X() -= 2 * nLayoutSign; |
| //UNUSED2008-05 aScrPos.Y() -= 2; |
| //UNUSED2008-05 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); |
| //UNUSED2008-05 Rectangle aRect( aScrPos.X(), aScrPos.Y(), |
| //UNUSED2008-05 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 ); |
| //UNUSED2008-05 if ( bLayoutRTL ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 aRect.Left() = aRect.Right(); // end position is left |
| //UNUSED2008-05 aRect.Right() = aScrPos.X(); |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 Invert(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); |
| //UNUSED2008-05 Invert(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); |
| //UNUSED2008-05 Invert(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); |
| //UNUSED2008-05 Invert(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); |
| //UNUSED2008-05 |
| //UNUSED2008-05 SetMapMode(aOld); |
| //UNUSED2008-05 } |
| |
| // ------------------------------------------------------------------------- |
| |
| void ScGridWindow::DrawCursor() |
| { |
| // #114409# |
| // SCTAB nTab = pViewData->GetTabNo(); |
| // SCCOL nX = pViewData->GetCurX(); |
| // SCROW nY = pViewData->GetCurY(); |
| // |
| // // in verdeckten Zellen nicht zeichnen |
| // |
| // ScDocument* pDoc = pViewData->GetDocument(); |
| // const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab); |
| // const ScMergeFlagAttr& rMerge = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG); |
| // if (rMerge.IsOverlapped()) |
| // return; |
| // |
| // // links/oben ausserhalb des Bildschirms ? |
| // |
| // sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) ); |
| // if (!bVis) |
| // { |
| // SCCOL nEndX = nX; |
| // SCROW nEndY = nY; |
| // ScDocument* pDoc = pViewData->GetDocument(); |
| // const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE); |
| // if (rMerge.GetColMerge() > 1) |
| // nEndX += rMerge.GetColMerge()-1; |
| // if (rMerge.GetRowMerge() > 1) |
| // nEndY += rMerge.GetRowMerge()-1; |
| // bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) ); |
| // } |
| // |
| // if ( bVis ) |
| // { |
| // // hier kein Update, da aus Paint gerufen und laut Zaehler Cursor schon da |
| // // wenn Update noetig, dann bei Hide/Showcursor vor dem Hoch-/Runterzaehlen |
| // |
| // MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); |
| // |
| // Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); |
| // sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| // |
| // // completely right of/below the screen? |
| // // (test with logical start position in aScrPos) |
| // sal_Bool bMaybeVisible; |
| // if ( bLayoutRTL ) |
| // bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 ); |
| // else |
| // { |
| // Size aOutSize = GetOutputSizePixel(); |
| // bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 ); |
| // } |
| // if ( bMaybeVisible ) |
| // { |
| // long nSizeXPix; |
| // long nSizeYPix; |
| // pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); |
| // |
| // if ( bLayoutRTL ) |
| // aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring |
| // |
| // sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX || |
| // pViewData->GetVSplitMode() == SC_SPLIT_FIX ); |
| // if ( pViewData->GetActivePart()==eWhich || bFix ) |
| // { |
| // // old UNX version with two Invert calls causes flicker. |
| // // if optimization is needed, a new flag should be added |
| // // to InvertTracking |
| // |
| // aScrPos.X() -= 2; |
| // aScrPos.Y() -= 2; |
| // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); |
| // |
| // Invert(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); |
| // Invert(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); |
| // Invert(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); |
| // Invert(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); |
| // } |
| // else |
| // { |
| // Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) ); |
| // Invert( aRect ); |
| // } |
| // } |
| // |
| // SetMapMode(aOld); |
| // } |
| } |
| |
| // AutoFill-Anfasser: |
| |
| void ScGridWindow::DrawAutoFillMark() |
| { |
| // #114409# |
| // if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() ) |
| // { |
| // SCCOL nX = aAutoMarkPos.Col(); |
| // SCROW nY = aAutoMarkPos.Row(); |
| // SCTAB nTab = pViewData->GetTabNo(); |
| // ScDocument* pDoc = pViewData->GetDocument(); |
| // sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); |
| // |
| // Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); |
| // long nSizeXPix; |
| // long nSizeYPix; |
| // pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); |
| // if ( bLayoutRTL ) |
| // aFillPos.X() -= nSizeXPix + 3; |
| // else |
| // aFillPos.X() += nSizeXPix - 2; |
| // |
| // aFillPos.Y() += nSizeYPix; |
| // aFillPos.Y() -= 2; |
| // Rectangle aFillRect( aFillPos, Size(6,6) ); |
| // // Anfasser von Zeichenobjekten sind 7*7 |
| // |
| // MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); |
| // Invert( aFillRect ); |
| // SetMapMode(aOld); |
| // } |
| } |
| |
| // ------------------------------------------------------------------------- |
| |
| void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Window::DataChanged(rDCEvt); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_PRINTER) || |
| (rDCEvt.GetType() == DATACHANGED_DISPLAY) || |
| (rDCEvt.GetType() == DATACHANGED_FONTS) || |
| (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || |
| ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) |
| { |
| if ( rDCEvt.GetType() == DATACHANGED_FONTS && eWhich == pViewData->GetActivePart() ) |
| pViewData->GetDocShell()->UpdateFontList(); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE) ) |
| { |
| if ( eWhich == pViewData->GetActivePart() ) // only once for the view |
| { |
| ScTabView* pView = pViewData->GetView(); |
| |
| // update scale in case the UI ScreenZoom has changed |
| ScGlobal::UpdatePPT(this); |
| pView->RecalcPPT(); |
| |
| // RepeatResize in case scroll bar sizes have changed |
| pView->RepeatResize(); |
| pView->UpdateAllOverlays(); |
| |
| // invalidate cell attribs in input handler, in case the |
| // EditEngine BackgroundColor has to be changed |
| if ( pViewData->IsActive() ) |
| { |
| ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); |
| if (pHdl) |
| pHdl->ForgetLastPattern(); |
| } |
| } |
| } |
| |
| Invalidate(); |
| } |
| } |
| |
| |
| |
| |