diff options
Diffstat (limited to 'sc/source/ui/view/gridwin4.cxx')
-rw-r--r-- | sc/source/ui/view/gridwin4.cxx | 2069 |
1 files changed, 2069 insertions, 0 deletions
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx new file mode 100644 index 000000000000..f698913ea758 --- /dev/null +++ b/sc/source/ui/view/gridwin4.cxx @@ -0,0 +1,2069 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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, BOOL bTextBelow, + double nPPTX, double nPPTY, const Fraction& rZoomY, + ScDocument* pDoc, ScViewData* pButtonViewData, 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, FALSE ); + if (pButtonViewData) + pButtonViewData->SetScenButSize( aButSize ); + + long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left(); + + BOOL bWasClip = FALSE; + Region aOldClip; + BOOL bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() ); + if ( bClip ) + { + if (pDev->IsClipRegion()) + { + bWasClip = 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, FALSE, SC_SCENARIO_SHOWFRAME ); + ScRangeListRef xRanges = new ScRangeList; + aMarks.FillRangeListWithMarks( xRanges, FALSE ); + + BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + USHORT nRangeCount = (USHORT)xRanges->Count(); + for (USHORT 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, TRUE ); + Point aEndPos = pViewData->GetScrPos( + aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, TRUE ); + // on the grid: + aStartPos.X() -= nLayoutSign; + aStartPos.Y() -= 1; + aEndPos.X() -= nLayoutSign; + aEndPos.Y() -= 1; + + 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; + USHORT 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(); + ULONG nCount = rHighlightRanges.Count(); + for (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, 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 = TRUE; + aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich + } + return; + } + + if (bIsInPaint) + return; + + bIsInPaint = 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 = ScViewData::ToPixel( pDoc->GetRowHeight( nY1, nTab ), nPPTY ); + while ( nScrY <= aPixRect.Top() && nY1 < MAXROW ) + { + ++nY1; + nScrY += ScViewData::ToPixel( pDoc->GetRowHeight( nY1, nTab ), nPPTY ); + } + SCROW nY2 = nY1; + while ( nScrY <= aPixRect.Bottom() && nY2 < MAXROW ) + { + ++nY2; + nScrY += ScViewData::ToPixel( pDoc->GetRowHeight( nY2, nTab ), nPPTY ); + } + + Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // nicht weiterzeichnen + + bIsInPaint = FALSE; +} + +// +// Draw ---------------------------------------------------------------- +// + +void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode ) +{ + ScModule* pScMod = SC_MOD(); + BOOL bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg(); + BOOL bGridFirst = 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; + + 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(); + 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 ); + 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(); + BOOL bFormulaMode = rOpts.GetOption( VOPT_FORMULAS ); + BOOL bMarkClipped = rOpts.GetOption( VOPT_CLIPMARKS ); + + // Datenblock + + ScTableInfo aTabInfo; + pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, + nPPTX, nPPTY, 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; + 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 = TRUE; // use logic MapMode + } + + const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig(); + Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, 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( TRUE ); // always set in table view + + aOutputData.SetEditObject( GetEditObject() ); + aOutputData.SetViewShell( pViewData->GetViewShell() ); + + BOOL bGrid = rOpts.GetOption( VOPT_GRID ); + BOOL bPage = rOpts.GetOption( VOPT_PAGEBREAKS ); + + if ( eMode == SC_UPDATE_CHANGED ) + { + aOutputData.FindChanged(); + aOutputData.SetSingleGrid(TRUE); + } + + BOOL bPageMode = pViewData->IsPagebreakMode(); + if (bPageMode) // nach FindChanged + { + // SetPagebreakMode initialisiert auch bPrinted Flags + aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() ); + } + + EditView* pEditView = NULL; + 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 = 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 = 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(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(FALSE); // in pixel MapMode + + // Autofilter- und Pivot-Buttons + + DrawButtons( nX1, nY1, nX2, nY2, aTabInfo, pContentDev ); // Pixel + + // Notiz-Anzeiger + + if ( rOpts.GetOption( VOPT_NOTES ) ) + aOutputData.DrawNoteMarks(); + + // Edit-Zellen + + pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich)); + if ( bLogicText ) + aOutputData.DrawStrings(TRUE); // in logic MapMode if bTextWysiwyg is set + aOutputData.DrawEdit(TRUE); + + pContentDev->SetMapMode(MAP_PIXEL); + 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(); + BOOL bHasScenario = ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ); + BOOL bHasChange = ( pDoc->GetChangeTrack() != NULL ); + + if ( bHasChange || bHasScenario || pHigh != NULL ) + { + + //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!) + + BOOL bAny = 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(); + } + + //BOOL bDraw = 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, FALSE ); + } + + // Range-Finder + + ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); + if (pHdl) + { + ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); + if ( pRangeFinder && !pRangeFinder->IsHidden() && + pRangeFinder->GetDocName() == pDocSh->GetTitle() ) + { + USHORT nCount = (USHORT)pRangeFinder->Count(); + for (USHORT 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 ) ), + 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 = 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(), 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 ); + } + + USHORT nCount = sal::static_int_cast<USHORT>( pPageData->GetCount() ); + for (USHORT 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, TRUE ); + Point aEnd = pViewData->GetScrPos( + aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, 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->GetColFlags( nBreak, nTab ) & CR_MANUALBREAK ) + pContentDev->SetFillColor( aManual ); + else + pContentDev->SetFillColor( aAutomatic ); + Point aBreak = pViewData->GetScrPos( + nBreak, aRange.aStart.Row(), eWhich, 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->GetRowFlags( nBreak, nTab ) & CR_MANUALBREAK ) + pContentDev->SetFillColor( aManual ); + else + pContentDev->SetFillColor( aAutomatic ); + Point aBreak = pViewData->GetScrPos( + aRange.aStart.Col(), nBreak, eWhich, 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, TRUE ); + Point aPageEnd = pViewData->GetScrPos( + nPrEndX+1,nPrEndY+1, eWhich, 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 ); + + ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY()); + + SCCOL nCol; + SCROW nRow; + SCSIZE nArrY; + SCSIZE nQuery; + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + ScDBData* pDBData = NULL; + ScQueryParam* pQueryParam = NULL; + + RowInfo* pRowInfo = rTabInfo.mpRowInfo; + USHORT nArrCount = rTabInfo.mnArrCount; + + 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 ( pInfo->bAutoFilter && !pInfo->bHOverlapped && !pInfo->bVOverlapped ) + { + if (!pQueryParam) + pQueryParam = new ScQueryParam; + + BOOL bNewData = 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 = 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 + + BOOL bSimpleQuery = TRUE; + BOOL bColumnFound = FALSE; + if (!pQueryParam->bInplace) + bSimpleQuery = 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 = TRUE; + if (nQuery > 0) + if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND) + bSimpleQuery = FALSE; + } + + bool bArrowState = bSimpleQuery && bColumnFound; + long nSizeX; + long nSizeY; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich ); + + aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1)); + 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(); + if ( bLayoutRTL ) + { + // overwrite the right, not left (visually) grid as long as the + // left/right colors of the button borders aren't mirrored. + nPosX -= nSizeX - 2; + } + + String aStr; + pDoc->GetString(nCol, nRow, nTab, aStr); + aCellBtn.setText(aStr); + aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1)); + 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( FALSE, 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(); + 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->GetColFlags( nNextCol, nTab ) & CR_HIDDEN) ) + ++nNextCol; + 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, 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 ); +} + +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"); + } + + BOOL bSimpleQuery = TRUE; + BOOL bColumnFound = FALSE; + SCSIZE nQuery; + + if ( !aQueryParam.bInplace ) + bSimpleQuery = 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 = TRUE; + + if (nQuery > 0) + if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND) + bSimpleQuery = FALSE; + } + + return ( bSimpleQuery && bColumnFound ); +} + +void ScGridWindow::DrawComboButton( const Point& rCellPos, + long nCellSizeX, + long nCellSizeY, + BOOL bArrowState, + 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 ); + } + + 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, + BOOL bTestMerge, 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(); + + 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(); + BOOL bWasHidden = FALSE; + for (SCROW nY=nY1; nY<=nY2; nY++) + { + BOOL bFirstRow = ( nY == nPosY ); // first visible row? + BOOL bDoHidden = FALSE; // versteckte nachholen ? + USHORT nHeightTwips = pDoc->GetRowHeight( nY,nTab ); + BOOL bDoRow = ( nHeightTwips != 0 ); + if (bDoRow) + { + if (bTestMerge) + if (bWasHidden) // auf versteckte zusammengefasste testen + { +// --nY; // nY geaendert -> vorherige zeichnen + bDoHidden = TRUE; + bDoRow = TRUE; + } + + bWasHidden = FALSE; + } + else + { + bWasHidden = TRUE; + if (bTestMerge) + if (nY==nY2) + bDoRow = 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->GetRowFlags( nThisY-1, nTab ) & CR_HIDDEN) || 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, 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, 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( FALSE ); + aMultiMark.MarkToMulti(); + + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + + 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 ); + + BOOL bTestMerge = TRUE; + BOOL bRepeat = 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(); + BOOL bWasHidden = FALSE; + for (SCROW nY=nY1; nY<=nY2; nY++) + { + BOOL bFirstRow = ( nY == nPosY ); // first visible row? + BOOL bDoHidden = FALSE; // versteckte nachholen ? + USHORT nHeightTwips = pDoc->GetRowHeight( nY,nTab ); + BOOL bDoRow = ( nHeightTwips != 0 ); + if (bDoRow) + { + if (bTestMerge) + if (bWasHidden) // auf versteckte zusammengefasste testen + { + bDoHidden = TRUE; + bDoRow = TRUE; + } + + bWasHidden = FALSE; + } + else + { + bWasHidden = TRUE; + if (bTestMerge) + if (nY==nY2) + bDoRow = 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->GetRowFlags( nThisY-1, nTab ) & CR_HIDDEN) || 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, 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, 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 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 ? +// +// 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, TRUE ); +// BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab ); +// +// // completely right of/below the screen? +// // (test with logical start position in aScrPos) +// 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 +// +// 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(); +// BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab ); +// +// Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, 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(); + } +} + + + + |