update dev300-m58
[ooovba.git] / sc / source / ui / view / gridwin4.cxx
blob0cce71a1d5d6c5a5f114ec0185cac2dc69154a46
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gridwin4.cxx,v $
10 * $Revision: 1.40 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "scitems.hxx"
39 #include <svx/eeitem.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <svx/colritem.hxx>
44 #include <svx/editview.hxx>
45 #include <svx/fhgtitem.hxx>
46 #include <svx/scripttypeitem.hxx>
47 #include <sfx2/bindings.hxx>
48 #include <sfx2/printer.hxx>
50 #include <svx/svdview.hxx>
51 #include "tabvwsh.hxx"
53 #include "gridwin.hxx"
54 #include "viewdata.hxx"
55 #include "output.hxx"
56 #include "document.hxx"
57 #include "attrib.hxx"
58 #include "patattr.hxx" // InvertSimple
59 #include "dbcolect.hxx"
60 #include "docoptio.hxx"
61 #include "notemark.hxx"
62 #include "dbfunc.hxx" // oder GetPageBreakData an die ViewData
63 #include "scmod.hxx"
64 #include "inputhdl.hxx"
65 #include "rfindlst.hxx"
66 #include "hiranges.hxx"
67 #include "pagedata.hxx"
68 #include "docpool.hxx"
69 #include "globstr.hrc"
70 #include "docsh.hxx" // oder GetSfxInPlaceObject
71 #include "cbutton.hxx"
72 #include "invmerge.hxx"
73 #include "editutil.hxx"
74 #include "inputopt.hxx"
75 #include "fillinfo.hxx"
76 #include "dpcontrol.hxx"
77 #include "queryparam.hxx"
78 #include "sc.hrc"
79 #include <vcl/virdev.hxx>
81 // #i74769#
82 #include <svx/sdrpaintwindow.hxx>
84 //#include "tabvwsh.hxx" //! Test !!!!
86 //------------------------------------------------------------------------
88 void lcl_LimitRect( Rectangle& rRect, const Rectangle& rVisible )
90 if ( rRect.Top() < rVisible.Top()-1 ) rRect.Top() = rVisible.Top()-1;
91 // if ( rRect.Left() < rVisible.Left()-1 ) rRect.Left() = rVisible.Left()-1;
92 if ( rRect.Bottom() > rVisible.Bottom()+1 ) rRect.Bottom() = rVisible.Bottom()+1;
93 // if ( rRect.Right() > rVisible.Right()+1 ) rRect.Right() = rVisible.Right()+1;
95 // #51122# auch wenn das inner-Rectangle nicht sichtbar ist, muss evtl.
96 // die Titelzeile gezeichnet werden, darum kein Rueckgabewert mehr.
97 // Wenn's weit daneben liegt, wird lcl_DrawOneFrame erst gar nicht gerufen.
100 void lcl_DrawOneFrame( OutputDevice* pDev, const Rectangle& rInnerPixel,
101 const String& rTitle, const Color& rColor, BOOL bTextBelow,
102 double nPPTX, double nPPTY, const Fraction& rZoomY,
103 ScDocument* pDoc, ScViewData* pButtonViewData, BOOL bLayoutRTL )
105 // pButtonViewData wird nur benutzt, um die Button-Groesse zu setzen,
106 // darf ansonsten NULL sein!
108 Rectangle aInner = rInnerPixel;
109 if ( bLayoutRTL )
111 aInner.Left() = rInnerPixel.Right();
112 aInner.Right() = rInnerPixel.Left();
115 Rectangle aVisible( Point(0,0), pDev->GetOutputSizePixel() );
116 lcl_LimitRect( aInner, aVisible );
118 Rectangle aOuter = aInner;
119 long nHor = (long) ( SC_SCENARIO_HSPACE * nPPTX );
120 long nVer = (long) ( SC_SCENARIO_VSPACE * nPPTY );
121 aOuter.Left() -= nHor;
122 aOuter.Right() += nHor;
123 aOuter.Top() -= nVer;
124 aOuter.Bottom() += nVer;
126 // use ScPatternAttr::GetFont only for font size
127 Font aAttrFont;
128 ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).
129 GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY);
131 // everything else from application font
132 Font aAppFont = pDev->GetSettings().GetStyleSettings().GetAppFont();
133 aAppFont.SetSize( aAttrFont.GetSize() );
135 aAppFont.SetAlign( ALIGN_TOP );
136 pDev->SetFont( aAppFont );
138 Size aTextSize( pDev->GetTextWidth( rTitle ), pDev->GetTextHeight() );
140 if ( bTextBelow )
141 aOuter.Bottom() += aTextSize.Height();
142 else
143 aOuter.Top() -= aTextSize.Height();
145 pDev->SetLineColor();
146 pDev->SetFillColor( rColor );
147 // links, oben, rechts, unten
148 pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aInner.Left(), aOuter.Bottom() ) );
149 pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aOuter.Right(), aInner.Top() ) );
150 pDev->DrawRect( Rectangle( aInner.Right(), aOuter.Top(), aOuter.Right(), aOuter.Bottom() ) );
151 pDev->DrawRect( Rectangle( aOuter.Left(), aInner.Bottom(), aOuter.Right(), aOuter.Bottom() ) );
153 long nButtonY = bTextBelow ? aInner.Bottom() : aOuter.Top();
155 ScDDComboBoxButton aComboButton((Window*)pDev);
156 aComboButton.SetOptSizePixel();
157 long nBWidth = ( aComboButton.GetSizePixel().Width() * rZoomY.GetNumerator() )
158 / rZoomY.GetDenominator();
159 long nBHeight = nVer + aTextSize.Height() + 1;
160 Size aButSize( nBWidth, nBHeight );
161 long nButtonPos = bLayoutRTL ? aOuter.Left() : aOuter.Right()-nBWidth+1;
162 aComboButton.Draw( Point(nButtonPos, nButtonY), aButSize, FALSE );
163 if (pButtonViewData)
164 pButtonViewData->SetScenButSize( aButSize );
166 long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left();
168 BOOL bWasClip = FALSE;
169 Region aOldClip;
170 BOOL bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() );
171 if ( bClip )
173 if (pDev->IsClipRegion())
175 bWasClip = TRUE;
176 aOldClip = pDev->GetActiveClipRegion();
178 long nClipStartX = bLayoutRTL ? aOuter.Left() + nBWidth : aInner.Left();
179 long nClipEndX = bLayoutRTL ? aInner.Right() : aOuter.Right() - nBWidth;
180 pDev->SetClipRegion( Rectangle( nClipStartX, nButtonY + nVer/2,
181 nClipEndX, nButtonY + nVer/2 + aTextSize.Height() ) );
184 pDev->DrawText( Point( nTextStart, nButtonY + nVer/2 ), rTitle );
186 if ( bClip )
188 if ( bWasClip )
189 pDev->SetClipRegion(aOldClip);
190 else
191 pDev->SetClipRegion();
194 pDev->SetFillColor();
195 pDev->SetLineColor( COL_BLACK );
196 pDev->DrawRect( aInner );
197 pDev->DrawRect( aOuter );
200 void lcl_DrawScenarioFrames( OutputDevice* pDev, ScViewData* pViewData, ScSplitPos eWhich,
201 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 )
203 ScDocument* pDoc = pViewData->GetDocument();
204 SCTAB nTab = pViewData->GetTabNo();
205 SCTAB nTabCount = pDoc->GetTableCount();
206 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
208 if ( nX1 > 0 ) --nX1;
209 if ( nY1>=2 ) nY1 -= 2; // Hack: Titelzeile beruehrt zwei Zellen
210 else if ( nY1 > 0 ) --nY1;
211 if ( nX2 < MAXCOL ) ++nX2;
212 if ( nY2 < MAXROW-1 ) nY2 += 2; // Hack: Titelzeile beruehrt zwei Zellen
213 else if ( nY2 < MAXROW ) ++nY2;
214 ScRange aViewRange( nX1,nY1,nTab, nX2,nY2,nTab );
216 //! Ranges an der Table cachen!!!!
218 ScMarkData aMarks;
219 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
220 pDoc->MarkScenario( i, nTab, aMarks, FALSE, SC_SCENARIO_SHOWFRAME );
221 ScRangeListRef xRanges = new ScRangeList;
222 aMarks.FillRangeListWithMarks( xRanges, FALSE );
224 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
225 long nLayoutSign = bLayoutRTL ? -1 : 1;
227 USHORT nRangeCount = (USHORT)xRanges->Count();
228 for (USHORT j=0; j<nRangeCount; j++)
230 ScRange aRange = *xRanges->GetObject(j);
231 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
232 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
233 pDoc->ExtendTotalMerge( aRange );
235 //! -> Repaint beim Zusammenfassen erweitern !!!
237 if ( aRange.Intersects( aViewRange ) ) //! Platz fuer Text/Button?
239 Point aStartPos = pViewData->GetScrPos(
240 aRange.aStart.Col(), aRange.aStart.Row(), eWhich, TRUE );
241 Point aEndPos = pViewData->GetScrPos(
242 aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, TRUE );
243 // on the grid:
244 aStartPos.X() -= nLayoutSign;
245 aStartPos.Y() -= 1;
246 aEndPos.X() -= nLayoutSign;
247 aEndPos.Y() -= 1;
249 BOOL bTextBelow = ( aRange.aStart.Row() == 0 );
251 String aCurrent;
252 Color aColor( COL_LIGHTGRAY );
253 for (SCTAB nAct=nTab+1; nAct<nTabCount && pDoc->IsScenario(nAct); nAct++)
254 if ( pDoc->IsActiveScenario(nAct) && pDoc->HasScenarioRange(nAct,aRange) )
256 String aDummyComment;
257 USHORT nDummyFlags;
258 pDoc->GetName( nAct, aCurrent );
259 pDoc->GetScenarioData( nAct, aDummyComment, aColor, nDummyFlags );
262 if (!aCurrent.Len())
263 aCurrent = ScGlobal::GetRscString( STR_EMPTYDATA );
265 //! eigener Text "(keins)" statt "(leer)" ???
267 lcl_DrawOneFrame( pDev, Rectangle( aStartPos, aEndPos ),
268 aCurrent, aColor, bTextBelow,
269 pViewData->GetPPTX(), pViewData->GetPPTY(), pViewData->GetZoomY(),
270 pDoc, pViewData, bLayoutRTL );
276 //------------------------------------------------------------------------
278 void lcl_DrawHighlight( ScOutputData& rOutputData, ScViewData* pViewData,
279 ScHighlightRanges& rHighlightRanges )
281 SCTAB nTab = pViewData->GetTabNo();
282 ULONG nCount = rHighlightRanges.Count();
283 for (ULONG i=0; i<nCount; i++)
285 ScHighlightEntry* pEntry = rHighlightRanges.GetObject( i );
286 if (pEntry)
288 ScRange aRange = pEntry->aRef;
289 if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() )
291 rOutputData.DrawRefMark(
292 aRange.aStart.Col(), aRange.aStart.Row(),
293 aRange.aEnd.Col(), aRange.aEnd.Row(),
294 pEntry->aColor, FALSE );
300 //------------------------------------------------------------------------
302 void ScGridWindow::DoInvertRect( const Rectangle& rPixel )
304 // Invert( PixelToLogic(rPixel) );
306 if ( rPixel == aInvertRect )
307 aInvertRect = Rectangle(); // aufheben
308 else
310 DBG_ASSERT( aInvertRect.IsEmpty(), "DoInvertRect nicht paarig" );
312 aInvertRect = rPixel; // neues Rechteck merken
315 UpdateHeaderOverlay(); // uses aInvertRect
318 //------------------------------------------------------------------------
320 void __EXPORT ScGridWindow::PrePaint()
322 // forward PrePaint to DrawingLayer
323 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
325 if(pTabViewShell)
327 SdrView* pDrawView = pTabViewShell->GetSdrView();
329 if(pDrawView)
331 pDrawView->PrePaint();
336 //------------------------------------------------------------------------
338 void __EXPORT ScGridWindow::Paint( const Rectangle& rRect )
340 //TODO/LATER: how to get environment? Do we need that?!
342 ScDocShell* pDocSh = pViewData->GetDocShell();
343 SvInPlaceEnvironment* pEnv = pDocSh->GetIPEnv();
344 if (pEnv && pEnv->GetRectsChangedLockCount())
346 Invalidate(rRect);
347 return;
350 ScDocument* pDoc = pViewData->GetDocument();
351 if ( pDoc->IsInInterpreter() )
353 // via Reschedule, interpretierende Zellen nicht nochmal anstossen
354 // hier kein Invalidate, sonst kommt z.B. eine Error-Box nie an die Reihe
355 // (Bug 36381). Durch bNeedsRepaint wird spaeter alles nochmal gemalt.
357 if ( bNeedsRepaint )
359 //! Rechtecke zusammenfassen?
360 aRepaintPixel = Rectangle(); // mehrfach -> alles painten
362 else
364 bNeedsRepaint = TRUE;
365 aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich
367 return;
370 if (bIsInPaint)
371 return;
373 bIsInPaint = TRUE;
375 Rectangle aPixRect = LogicToPixel( rRect );
377 SCCOL nX1 = pViewData->GetPosX(eHWhich);
378 SCROW nY1 = pViewData->GetPosY(eVWhich);
380 SCTAB nTab = pViewData->GetTabNo();
382 double nPPTX = pViewData->GetPPTX();
383 double nPPTY = pViewData->GetPPTY();
385 Rectangle aMirroredPixel = aPixRect;
386 if ( pDoc->IsLayoutRTL( nTab ) )
388 // mirror and swap
389 long nWidth = GetSizePixel().Width();
390 aMirroredPixel.Left() = nWidth - 1 - aPixRect.Right();
391 aMirroredPixel.Right() = nWidth - 1 - aPixRect.Left();
394 long nScrX = ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
395 while ( nScrX <= aMirroredPixel.Left() && nX1 < MAXCOL )
397 ++nX1;
398 nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
400 SCCOL nX2 = nX1;
401 while ( nScrX <= aMirroredPixel.Right() && nX2 < MAXCOL )
403 ++nX2;
404 nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX );
407 long nScrY = ScViewData::ToPixel( pDoc->GetRowHeight( nY1, nTab ), nPPTY );
408 while ( nScrY <= aPixRect.Top() && nY1 < MAXROW )
410 ++nY1;
411 nScrY += ScViewData::ToPixel( pDoc->GetRowHeight( nY1, nTab ), nPPTY );
413 SCROW nY2 = nY1;
414 while ( nScrY <= aPixRect.Bottom() && nY2 < MAXROW )
416 ++nY2;
417 nScrY += ScViewData::ToPixel( pDoc->GetRowHeight( nY2, nTab ), nPPTY );
420 Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // nicht weiterzeichnen
422 bIsInPaint = FALSE;
426 // Draw ----------------------------------------------------------------
429 void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode )
431 ScModule* pScMod = SC_MOD();
432 BOOL bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg();
433 BOOL bGridFirst = TRUE; //! entscheiden!!!
435 if (pViewData->IsMinimized())
436 return;
438 PutInOrder( nX1, nX2 );
439 PutInOrder( nY1, nY2 );
441 DBG_ASSERT( ValidCol(nX2) && ValidRow(nY2), "GridWin Draw Bereich zu gross" );
443 SCCOL nPosX = pViewData->GetPosX( eHWhich );
444 SCROW nPosY = pViewData->GetPosY( eVWhich );
445 if (nX2 < nPosX || nY2 < nPosY)
446 return; // unsichtbar
447 if (nX1 < nPosX) nX1 = nPosX;
448 if (nY1 < nPosY) nY1 = nPosY;
450 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
451 if (nXRight > MAXCOL) nXRight = MAXCOL;
452 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
453 if (nYBottom > MAXROW) nYBottom = MAXROW;
455 // Store the current visible range.
456 maVisibleRange.mnCol1 = nPosX;
457 maVisibleRange.mnCol2 = nXRight;
458 maVisibleRange.mnRow1 = nPosY;
459 maVisibleRange.mnRow2 = nYBottom;
461 if (nX1 > nXRight || nY1 > nYBottom)
462 return; // unsichtbar
463 if (nX2 > nXRight) nX2 = nXRight;
464 if (nY2 > nYBottom) nY2 = nYBottom;
466 if ( eMode != SC_UPDATE_MARKS )
467 if (nX2 < nXRight)
468 nX2 = nXRight; // zum Weiterzeichnen
470 // ab hier kein return mehr
472 ++nPaintCount; // merken, dass gemalt wird (wichtig beim Invertieren)
474 ScDocShell* pDocSh = pViewData->GetDocShell();
475 ScDocument* pDoc = pDocSh->GetDocument();
476 SCTAB nTab = pViewData->GetTabNo();
478 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
480 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
481 long nMirrorWidth = GetSizePixel().Width();
482 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
483 long nLayoutSign = bLayoutRTL ? -1 : 1;
484 if ( bLayoutRTL )
486 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
487 nMirrorWidth = aScrPos.X() - nEndPixel;
488 aScrPos.X() = nEndPixel + 1;
491 long nScrX = aScrPos.X();
492 long nScrY = aScrPos.Y();
494 SCCOL nCurX = pViewData->GetCurX();
495 SCROW nCurY = pViewData->GetCurY();
496 SCCOL nCurEndX = nCurX;
497 SCROW nCurEndY = nCurY;
498 pDoc->ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab );
499 BOOL bCurVis = nCursorHideCount==0 &&
500 ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 );
502 // AutoFill-Anfasser
503 if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab &&
504 ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) )
506 SCCOL nHdlX = aAutoMarkPos.Col();
507 SCROW nHdlY = aAutoMarkPos.Row();
508 pDoc->ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab );
509 bCurVis = ( nHdlX+1 >= nX1 && nHdlX <= nX2 && nHdlY+1 >= nY1 && nHdlY <= nY2 );
510 // links und oben ist nicht betroffen
512 //! AutoFill-Anfasser alleine (ohne Cursor) zeichnen ???
515 double nPPTX = pViewData->GetPPTX();
516 double nPPTY = pViewData->GetPPTY();
518 const ScViewOptions& rOpts = pViewData->GetOptions();
519 BOOL bFormulaMode = rOpts.GetOption( VOPT_FORMULAS );
520 BOOL bMarkClipped = rOpts.GetOption( VOPT_CLIPMARKS );
522 // Datenblock
524 ScTableInfo aTabInfo;
525 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
526 nPPTX, nPPTY, FALSE, bFormulaMode,
527 &pViewData->GetMarkData() );
529 //--------------------------------------------------------------------
531 Fraction aZoomX = pViewData->GetZoomX();
532 Fraction aZoomY = pViewData->GetZoomY();
533 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
534 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
535 &aZoomX, &aZoomY );
537 aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL
539 std::auto_ptr< VirtualDevice > xFmtVirtDev;
540 BOOL bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode?
542 if ( bTextWysiwyg )
544 // use printer for text formatting
546 OutputDevice* pFmtDev = pDoc->GetPrinter();
547 pFmtDev->SetMapMode( pViewData->GetLogicMode(eWhich) );
548 aOutputData.SetFmtDevice( pFmtDev );
550 else if ( aZoomX != aZoomY && pViewData->IsOle() )
552 // #i45033# For OLE inplace editing with different zoom factors,
553 // use a virtual device with 1/100th mm as text formatting reference
555 xFmtVirtDev.reset( new VirtualDevice );
556 xFmtVirtDev->SetMapMode( MAP_100TH_MM );
557 aOutputData.SetFmtDevice( xFmtVirtDev.get() );
559 bLogicText = TRUE; // use logic MapMode
562 const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig();
563 Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, FALSE ).nColor );
564 if ( aGridColor.GetColor() == COL_TRANSPARENT )
566 // use view options' grid color only if color config has "automatic" color
567 aGridColor = rOpts.GetGridColor();
570 aOutputData.SetSyntaxMode ( pViewData->IsSyntaxMode() );
571 aOutputData.SetGridColor ( aGridColor );
572 aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) );
573 aOutputData.SetShowFormulas ( bFormulaMode );
574 aOutputData.SetShowSpellErrors ( pDoc->GetDocOptions().IsAutoSpell() );
575 aOutputData.SetMarkClipped ( bMarkClipped );
577 aOutputData.SetUseStyleColor( TRUE ); // always set in table view
579 aOutputData.SetEditObject( GetEditObject() );
580 aOutputData.SetViewShell( pViewData->GetViewShell() );
582 BOOL bGrid = rOpts.GetOption( VOPT_GRID ) && pViewData->GetShowGrid();
584 BOOL bPage = rOpts.GetOption( VOPT_PAGEBREAKS );
586 if ( eMode == SC_UPDATE_CHANGED )
588 aOutputData.FindChanged();
589 aOutputData.SetSingleGrid(TRUE);
592 BOOL bPageMode = pViewData->IsPagebreakMode();
593 if (bPageMode) // nach FindChanged
595 // SetPagebreakMode initialisiert auch bPrinted Flags
596 aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() );
599 EditView* pEditView = NULL;
600 BOOL bEditMode = pViewData->HasEditView(eWhich);
601 if ( bEditMode && pViewData->GetRefTabNo() == nTab )
603 SCCOL nEditCol;
604 SCROW nEditRow;
605 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
606 SCCOL nEditEndCol = pViewData->GetEditEndCol();
607 SCROW nEditEndRow = pViewData->GetEditEndRow();
609 if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 )
610 aOutputData.SetEditCell( nEditCol, nEditRow );
611 else
612 bEditMode = FALSE;
614 // nur Edit-Area zu zeichnen?
615 //! dann muss trotzdem noch der Rand / das Gitter gemalt werden!
617 // if ( nEditCol <= nX1 && nEditEndCol >= nX2 && nEditRow <= nY1 && nEditEndRow >= nY2 )
618 // bOnlyEdit = TRUE;
621 // define drawing layer map mode and paint rectangle
622 const MapMode aDrawMode = GetDrawMapMode();
623 Rectangle aDrawingRectLogic;
626 // get drawing pixel rect
627 Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
629 // correct for border (left/right)
630 if(MAXCOL == nX2)
632 if(bLayoutRTL)
634 aDrawingRectPixel.Left() = 0L;
636 else
638 aDrawingRectPixel.Right() = GetOutputSizePixel().getWidth();
642 // correct for border (bottom)
643 if(MAXROW == nY2)
645 aDrawingRectPixel.Bottom() = GetOutputSizePixel().getHeight();
648 // get logic positions
649 aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode);
652 // not necessary with overlay
653 // if (bCurVis)
654 // HideCursor();
656 OutputDevice* pContentDev = this; // device for document content, used by overlay manager
657 SdrPaintWindow* pTargetPaintWindow = 0; // #i74769# work with SdrPaintWindow directly
660 // init redraw
661 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
663 if(pTabViewShell)
665 MapMode aCurrentMapMode(pContentDev->GetMapMode());
666 pContentDev->SetMapMode(aDrawMode);
667 SdrView* pDrawView = pTabViewShell->GetSdrView();
669 if(pDrawView)
671 // #i74769# Use new BeginDrawLayers() interface
672 Region aDrawingRegion(aDrawingRectLogic);
673 pTargetPaintWindow = pDrawView->BeginDrawLayers(this, aDrawingRegion);
674 OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)");
676 // #i74769# get target device from SdrPaintWindow, this may be the prerender
677 // device now, too.
678 pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice());
679 aOutputData.SetContentDevice( pContentDev );
682 pContentDev->SetMapMode(aCurrentMapMode);
686 // Rand (Wiese) (Pixel)
687 if ( nX2==MAXCOL || nY2==MAXROW )
689 // save MapMode and set to pixel
690 MapMode aCurrentMapMode(pContentDev->GetMapMode());
691 pContentDev->SetMapMode(MAP_PIXEL);
693 Rectangle aPixRect = Rectangle( Point(), GetOutputSizePixel() );
694 pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor );
695 pContentDev->SetLineColor();
696 if ( nX2==MAXCOL )
698 Rectangle aDrawRect( aPixRect );
699 if ( bLayoutRTL )
700 aDrawRect.Right() = nScrX - 1;
701 else
702 aDrawRect.Left() = nScrX + aOutputData.GetScrW();
703 if (aDrawRect.Right() >= aDrawRect.Left())
704 pContentDev->DrawRect( aDrawRect );
706 if ( nY2==MAXROW )
708 Rectangle aDrawRect( aPixRect );
709 aDrawRect.Top() = nScrY + aOutputData.GetScrH();
710 if ( nX2==MAXCOL )
712 // no double painting of the corner
713 if ( bLayoutRTL )
714 aDrawRect.Left() = nScrX;
715 else
716 aDrawRect.Right() = nScrX + aOutputData.GetScrW() - 1;
718 if (aDrawRect.Bottom() >= aDrawRect.Top())
719 pContentDev->DrawRect( aDrawRect );
722 // restore MapMode
723 pContentDev->SetMapMode(aCurrentMapMode);
726 if ( pDoc->HasBackgroundDraw( nTab, aDrawingRectLogic ) )
728 pContentDev->SetMapMode(MAP_PIXEL);
729 aOutputData.DrawClear();
731 // Drawing Hintergrund
733 pContentDev->SetMapMode(aDrawMode);
734 DrawRedraw( aOutputData, eMode, SC_LAYER_BACK );
736 else
737 aOutputData.SetSolidBackground(TRUE);
739 pContentDev->SetMapMode(MAP_PIXEL);
740 aOutputData.DrawDocumentBackground();
741 if ( bGridFirst && ( bGrid || bPage ) )
742 aOutputData.DrawGrid( bGrid, bPage );
743 aOutputData.DrawBackground();
744 if ( bPageMode )
746 // #87655# DrawPagePreview draws complete lines/page numbers, must always be clipped
747 if ( aOutputData.SetChangedClip() )
749 DrawPagePreview(nX1,nY1,nX2,nY2, pContentDev);
750 pContentDev->SetClipRegion();
753 aOutputData.DrawShadow();
754 aOutputData.DrawFrame();
755 if ( !bLogicText )
756 aOutputData.DrawStrings(FALSE); // in pixel MapMode
758 // Autofilter- und Pivot-Buttons
760 DrawButtons( nX1, nY1, nX2, nY2, aTabInfo, pContentDev ); // Pixel
762 // Notiz-Anzeiger
764 if ( rOpts.GetOption( VOPT_NOTES ) )
765 aOutputData.DrawNoteMarks();
767 // Edit-Zellen
769 pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich));
770 if ( bLogicText )
771 aOutputData.DrawStrings(TRUE); // in logic MapMode if bTextWysiwyg is set
772 aOutputData.DrawEdit(TRUE);
774 pContentDev->SetMapMode(MAP_PIXEL);
775 if ( !bGridFirst && ( bGrid || bPage ) )
777 aOutputData.DrawGrid( bGrid, bPage );
779 aOutputData.DrawClipMarks();
781 // Szenario / ChangeTracking muss auf jeden Fall nach DrawGrid sein, auch bei !bGridFirst
783 //! Test, ob ChangeTrack-Anzeige aktiv ist
784 //! Szenario-Rahmen per View-Optionen abschaltbar?
786 SCTAB nTabCount = pDoc->GetTableCount();
787 ScHighlightRanges* pHigh = pViewData->GetView()->GetHighlightRanges();
788 BOOL bHasScenario = ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) );
789 BOOL bHasChange = ( pDoc->GetChangeTrack() != NULL );
791 if ( bHasChange || bHasScenario || pHigh != NULL )
794 //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!)
796 BOOL bAny = TRUE;
797 if (eMode == SC_UPDATE_CHANGED)
798 bAny = aOutputData.SetChangedClip();
799 if (bAny)
801 if ( bHasChange )
802 aOutputData.DrawChangeTrack();
804 if ( bHasScenario )
805 lcl_DrawScenarioFrames( pContentDev, pViewData, eWhich, nX1,nY1,nX2,nY2 );
807 if ( pHigh )
808 lcl_DrawHighlight( aOutputData, pViewData, *pHigh );
810 if (eMode == SC_UPDATE_CHANGED)
811 pContentDev->SetClipRegion();
815 // Drawing Vordergrund
817 pContentDev->SetMapMode(aDrawMode);
819 DrawRedraw( aOutputData, eMode, SC_LAYER_FRONT );
820 DrawRedraw( aOutputData, eMode, SC_LAYER_INTERN );
821 DrawSdrGrid( aDrawingRectLogic, pContentDev );
823 if (!bIsInScroll) // Drawing Markierungen
825 if(eMode == SC_UPDATE_CHANGED && aOutputData.SetChangedClip())
827 pContentDev->SetClipRegion();
830 //BOOL bDraw = TRUE;
831 //if (eMode == SC_UPDATE_CHANGED)
832 // bDraw = NeedDrawMarks() && aOutputData.SetChangedClip();
833 //if (bDraw)
835 // DrawMarks();
836 // if (eMode == SC_UPDATE_CHANGED)
837 // pContentDev->SetClipRegion();
841 pContentDev->SetMapMode(MAP_PIXEL);
843 #ifdef OLD_SELECTION_PAINT
844 if (pViewData->IsActive())
845 aOutputData.DrawMark( this );
846 #endif
848 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() )
850 // The AutoFill shrink area has an own overlay now
851 #if 0
852 // Schraffur beim Loeschen per AutoFill
853 if ( pViewData->GetRefType() == SC_REFTYPE_FILL )
855 ScRange aRange;
856 if ( pViewData->GetDelMark( aRange ) )
858 if ( aRange.aStart.Col() < nX1 ) aRange.aStart.SetCol(nX1);
859 if ( aRange.aEnd.Col() > nX2 ) aRange.aEnd.SetCol(nX2);
860 if ( aRange.aStart.Row() < nY1 ) aRange.aStart.SetRow(nY1);
861 if ( aRange.aEnd.Row() > nY2 ) aRange.aEnd.SetRow(nY2);
862 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
863 aRange.aStart.Row() <= aRange.aEnd.Row() )
865 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
866 aRange.aStart.Row(), eWhich );
867 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
868 aRange.aEnd.Row()+1, eWhich );
869 aEnd.X() -= 1;
870 aEnd.Y() -= 1;
872 // Markierung aufheben - roter Rahmen bleibt stehen
873 Rectangle aRect( aStart,aEnd );
874 Invert( aRect, INVERT_HIGHLIGHT );
876 //! Delete-Bereich extra kennzeichnen?!?!?
880 #endif
882 Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor );
883 aOutputData.DrawRefMark( pViewData->GetRefStartX(), pViewData->GetRefStartY(),
884 pViewData->GetRefEndX(), pViewData->GetRefEndY(),
885 aRefColor, FALSE );
888 // Range-Finder
890 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
891 if (pHdl)
893 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
894 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
895 pRangeFinder->GetDocName() == pDocSh->GetTitle() )
897 USHORT nCount = (USHORT)pRangeFinder->Count();
898 for (USHORT i=0; i<nCount; i++)
900 ScRangeFindData* pData = pRangeFinder->GetObject(i);
901 if (pData)
903 ScRange aRef = pData->aRef;
904 aRef.Justify();
905 if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab )
906 aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(),
907 aRef.aEnd.Col(), aRef.aEnd.Row(),
908 Color( ScRangeFindList::GetColorName( i ) ),
909 TRUE );
916 // end redraw
917 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
919 if(pTabViewShell)
921 MapMode aCurrentMapMode(pContentDev->GetMapMode());
922 pContentDev->SetMapMode(aDrawMode);
923 SdrView* pDrawView = pTabViewShell->GetSdrView();
925 if(pDrawView)
927 // #i74769# work with SdrPaintWindow directly
928 pDrawView->EndDrawLayers(*pTargetPaintWindow, true);
931 pContentDev->SetMapMode(aCurrentMapMode);
935 // InPlace Edit-View
936 // moved after EndDrawLayers() to get it outside the overlay buffer and
937 // on top of everything
938 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
940 //! use pContentDev for EditView?
941 SetMapMode(MAP_PIXEL);
942 SCCOL nCol1 = pViewData->GetEditStartCol();
943 SCROW nRow1 = pViewData->GetEditStartRow();
944 SCCOL nCol2 = pViewData->GetEditEndCol();
945 SCROW nRow2 = pViewData->GetEditEndRow();
946 SetLineColor();
947 SetFillColor( pEditView->GetBackgroundColor() );
948 Point aStart = pViewData->GetScrPos( nCol1, nRow1, eWhich );
949 Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eWhich );
950 aEnd.X() -= 2 * nLayoutSign; // don't overwrite grid
951 aEnd.Y() -= 2;
952 DrawRect( Rectangle( aStart,aEnd ) );
954 SetMapMode(pViewData->GetLogicMode());
955 pEditView->Paint( PixelToLogic( Rectangle( Point( nScrX, nScrY ),
956 Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) ) );
957 SetMapMode(MAP_PIXEL);
960 if (pViewData->HasEditView(eWhich))
962 // flush OverlayManager before changing the MapMode
963 flushOverlayManager();
965 // set MapMode for text edit
966 SetMapMode(pViewData->GetLogicMode());
968 else
969 SetMapMode(aDrawMode);
971 if ( pNoteMarker )
972 pNoteMarker->Draw(); // ueber den Cursor, im Drawing-MapMode
974 //DrawStartTimer(); // fuer bunte Handles ohne System-Clipping
977 // Wenn waehrend des Paint etwas invertiert wurde (Selektion geaendert aus Basic-Macro),
978 // ist das jetzt durcheinandergekommen und es muss neu gemalt werden
981 DBG_ASSERT(nPaintCount, "nPaintCount falsch");
982 --nPaintCount;
983 if (!nPaintCount)
984 CheckNeedsRepaint();
987 void ScGridWindow::CheckNeedsRepaint()
989 // called at the end of painting, and from timer after background text width calculation
991 if (bNeedsRepaint)
993 bNeedsRepaint = FALSE;
994 if (aRepaintPixel.IsEmpty())
995 Invalidate();
996 else
997 Invalidate(PixelToLogic(aRepaintPixel));
998 aRepaintPixel = Rectangle();
1000 // selection function in status bar might also be invalid
1001 SfxBindings& rBindings = pViewData->GetBindings();
1002 rBindings.Invalidate( SID_STATUS_SUM );
1003 rBindings.Invalidate( SID_ATTR_SIZE );
1004 rBindings.Invalidate( SID_TABLE_CELL );
1008 void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev )
1010 ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData();
1011 if (pPageData)
1013 ScDocument* pDoc = pViewData->GetDocument();
1014 SCTAB nTab = pViewData->GetTabNo();
1015 Size aWinSize = GetOutputSizePixel();
1016 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
1017 Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
1018 Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor );
1020 String aPageText = ScGlobal::GetRscString( STR_PAGE );
1021 if ( nPageScript == 0 )
1023 // get script type of translated "Page" string only once
1024 nPageScript = pDoc->GetStringScriptType( aPageText );
1025 if (nPageScript == 0)
1026 nPageScript = ScGlobal::GetDefaultScriptType();
1028 aPageText += ' ';
1030 Font aFont;
1031 ScEditEngineDefaulter* pEditEng = NULL;
1032 const ScPatternAttr& rDefPattern = ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN));
1033 if ( nPageScript == SCRIPTTYPE_LATIN )
1035 // use single font and call DrawText directly
1036 rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK );
1037 aFont.SetColor( Color( COL_LIGHTGRAY ) );
1038 // font size is set as needed
1040 else
1042 // use EditEngine to draw mixed-script string
1043 pEditEng = new ScEditEngineDefaulter( EditEngine::CreatePool(), TRUE );
1044 pEditEng->SetRefMapMode( pContentDev->GetMapMode() );
1045 SfxItemSet* pEditDefaults = new SfxItemSet( pEditEng->GetEmptyItemSet() );
1046 rDefPattern.FillEditItemSet( pEditDefaults );
1047 pEditDefaults->Put( SvxColorItem( Color( COL_LIGHTGRAY ), EE_CHAR_COLOR ) );
1048 pEditEng->SetDefaults( pEditDefaults );
1051 USHORT nCount = sal::static_int_cast<USHORT>( pPageData->GetCount() );
1052 for (USHORT nPos=0; nPos<nCount; nPos++)
1054 ScPrintRangeData& rData = pPageData->GetData(nPos);
1055 ScRange aRange = rData.GetPrintRange();
1056 if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 &&
1057 aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 )
1059 // 3 Pixel Rahmen um den Druckbereich
1060 // (mittlerer Pixel auf den Gitterlinien)
1062 pContentDev->SetLineColor();
1063 if (rData.IsAutomatic())
1064 pContentDev->SetFillColor( aAutomatic );
1065 else
1066 pContentDev->SetFillColor( aManual );
1068 Point aStart = pViewData->GetScrPos(
1069 aRange.aStart.Col(), aRange.aStart.Row(), eWhich, TRUE );
1070 Point aEnd = pViewData->GetScrPos(
1071 aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, TRUE );
1072 aStart.X() -= 2;
1073 aStart.Y() -= 2;
1075 // Ueberlaeufe verhindern:
1076 if ( aStart.X() < -10 ) aStart.X() = -10;
1077 if ( aStart.Y() < -10 ) aStart.Y() = -10;
1078 if ( aEnd.X() > aWinSize.Width() + 10 )
1079 aEnd.X() = aWinSize.Width() + 10;
1080 if ( aEnd.Y() > aWinSize.Height() + 10 )
1081 aEnd.Y() = aWinSize.Height() + 10;
1083 pContentDev->DrawRect( Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) );
1084 pContentDev->DrawRect( Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) );
1085 pContentDev->DrawRect( Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) );
1086 pContentDev->DrawRect( Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) );
1088 // Seitenumbrueche
1089 //! anders darstellen (gestrichelt ????)
1091 size_t nColBreaks = rData.GetPagesX();
1092 const SCCOL* pColEnd = rData.GetPageEndX();
1093 size_t nColPos;
1094 for (nColPos=0; nColPos+1<nColBreaks; nColPos++)
1096 SCCOL nBreak = pColEnd[nColPos]+1;
1097 if ( nBreak >= nX1 && nBreak <= nX2+1 )
1099 //! hidden suchen
1100 if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL)
1101 pContentDev->SetFillColor( aManual );
1102 else
1103 pContentDev->SetFillColor( aAutomatic );
1104 Point aBreak = pViewData->GetScrPos(
1105 nBreak, aRange.aStart.Row(), eWhich, TRUE );
1106 pContentDev->DrawRect( Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) );
1110 size_t nRowBreaks = rData.GetPagesY();
1111 const SCROW* pRowEnd = rData.GetPageEndY();
1112 size_t nRowPos;
1113 for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++)
1115 SCROW nBreak = pRowEnd[nRowPos]+1;
1116 if ( nBreak >= nY1 && nBreak <= nY2+1 )
1118 //! hidden suchen
1119 if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL)
1120 pContentDev->SetFillColor( aManual );
1121 else
1122 pContentDev->SetFillColor( aAutomatic );
1123 Point aBreak = pViewData->GetScrPos(
1124 aRange.aStart.Col(), nBreak, eWhich, TRUE );
1125 pContentDev->DrawRect( Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) );
1129 // Seitenzahlen
1131 SCROW nPrStartY = aRange.aStart.Row();
1132 for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++)
1134 SCROW nPrEndY = pRowEnd[nRowPos];
1135 if ( nPrEndY >= nY1 && nPrStartY <= nY2 )
1137 SCCOL nPrStartX = aRange.aStart.Col();
1138 for (nColPos=0; nColPos<nColBreaks; nColPos++)
1140 SCCOL nPrEndX = pColEnd[nColPos];
1141 if ( nPrEndX >= nX1 && nPrStartX <= nX2 )
1143 Point aPageStart = pViewData->GetScrPos(
1144 nPrStartX, nPrStartY, eWhich, TRUE );
1145 Point aPageEnd = pViewData->GetScrPos(
1146 nPrEndX+1,nPrEndY+1, eWhich, TRUE );
1148 long nPageNo = rData.GetFirstPage();
1149 if ( rData.IsTopDown() )
1150 nPageNo += ((long)nColPos)*nRowBreaks+nRowPos;
1151 else
1152 nPageNo += ((long)nRowPos)*nColBreaks+nColPos;
1153 String aPageStr = aPageText;
1154 aPageStr += String::CreateFromInt32(nPageNo);
1156 if ( pEditEng )
1158 // find right font size with EditEngine
1159 long nHeight = 100;
1160 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1161 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1162 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1163 pEditEng->SetText( aPageStr );
1164 Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1166 // 40% of width or 60% of height
1167 long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1168 long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1169 nHeight = Min(nSizeX,nSizeY);
1170 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1171 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1172 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1174 // centered output with EditEngine
1175 Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1176 Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1177 (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1178 pEditEng->Draw( pContentDev, aPos );
1180 else
1182 // find right font size for DrawText
1183 aFont.SetSize( Size( 0,100 ) );
1184 pContentDev->SetFont( aFont );
1185 Size aSize100( pContentDev->GetTextWidth( aPageStr ), pContentDev->GetTextHeight() );
1187 // 40% of width or 60% of height
1188 long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1189 long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1190 aFont.SetSize( Size( 0,Min(nSizeX,nSizeY) ) );
1191 pContentDev->SetFont( aFont );
1193 // centered output with DrawText
1194 Size aTextSize( pContentDev->GetTextWidth( aPageStr ), pContentDev->GetTextHeight() );
1195 Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1196 (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1197 pContentDev->DrawText( aPos, aPageStr );
1200 nPrStartX = nPrEndX + 1;
1203 nPrStartY = nPrEndY + 1;
1208 delete pEditEng;
1212 void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2*/, ScTableInfo& rTabInfo, OutputDevice* pContentDev )
1214 aComboButton.SetOutputDevice( pContentDev );
1216 ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY());
1218 SCCOL nCol;
1219 SCROW nRow;
1220 SCSIZE nArrY;
1221 SCSIZE nQuery;
1222 SCTAB nTab = pViewData->GetTabNo();
1223 ScDocument* pDoc = pViewData->GetDocument();
1224 ScDBData* pDBData = NULL;
1225 ScQueryParam* pQueryParam = NULL;
1227 RowInfo* pRowInfo = rTabInfo.mpRowInfo;
1228 USHORT nArrCount = rTabInfo.mnArrCount;
1230 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1232 Point aOldPos = aComboButton.GetPosPixel(); // Zustand fuer MouseDown/Up
1233 Size aOldSize = aComboButton.GetSizePixel(); // merken
1235 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1237 if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged )
1239 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1241 nRow = pThisRowInfo->nRowNo;
1244 for (nCol=nX1; nCol<=nX2; nCol++)
1246 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1247 if ( pInfo->bAutoFilter && !pInfo->bHOverlapped && !pInfo->bVOverlapped )
1249 if (!pQueryParam)
1250 pQueryParam = new ScQueryParam;
1252 BOOL bNewData = TRUE;
1253 if (pDBData)
1255 SCCOL nStartCol;
1256 SCROW nStartRow;
1257 SCCOL nEndCol;
1258 SCROW nEndRow;
1259 SCTAB nAreaTab;
1260 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1261 if ( nCol >= nStartCol && nCol <= nEndCol &&
1262 nRow >= nStartRow && nRow <= nEndRow )
1263 bNewData = FALSE;
1265 if (bNewData)
1267 pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1268 if (pDBData)
1269 pDBData->GetQueryParam( *pQueryParam );
1270 else
1272 // can also be part of DataPilot table
1273 // DBG_ERROR("Auto-Filter-Button ohne DBData");
1277 // pQueryParam kann nur MAXQUERY Eintraege enthalten
1279 BOOL bSimpleQuery = TRUE;
1280 BOOL bColumnFound = FALSE;
1281 if (!pQueryParam->bInplace)
1282 bSimpleQuery = FALSE;
1283 for (nQuery=0; nQuery<MAXQUERY && bSimpleQuery; nQuery++)
1284 if (pQueryParam->GetEntry(nQuery).bDoQuery)
1286 // hier nicht auf EQUAL beschraenken
1287 // (auch bei ">1" soll der Spaltenkopf blau werden)
1289 if (pQueryParam->GetEntry(nQuery).nField == nCol)
1290 bColumnFound = TRUE;
1291 if (nQuery > 0)
1292 if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND)
1293 bSimpleQuery = FALSE;
1296 bool bArrowState = bSimpleQuery && bColumnFound;
1297 long nSizeX;
1298 long nSizeY;
1299 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1300 Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1302 aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1));
1303 aCellBtn.setDrawBaseButton(false);
1304 aCellBtn.setDrawPopupButton(true);
1305 aCellBtn.setHasHiddenMember(bArrowState);
1306 aCellBtn.draw();
1311 if ( pRowInfo[nArrY].bPushButton && pRowInfo[nArrY].bChanged )
1313 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1314 nRow = pThisRowInfo->nRowNo;
1315 for (nCol=nX1; nCol<=nX2; nCol++)
1317 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1318 if ( pInfo->bPushButton && !pInfo->bHOverlapped && !pInfo->bVOverlapped )
1320 Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1321 long nSizeX;
1322 long nSizeY;
1323 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1324 long nPosX = aScrPos.X();
1325 long nPosY = aScrPos.Y();
1326 if ( bLayoutRTL )
1328 // overwrite the right, not left (visually) grid as long as the
1329 // left/right colors of the button borders aren't mirrored.
1330 nPosX -= nSizeX - 2;
1333 String aStr;
1334 pDoc->GetString(nCol, nRow, nTab, aStr);
1335 aCellBtn.setText(aStr);
1336 aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1));
1337 aCellBtn.setDrawBaseButton(true);
1338 aCellBtn.setDrawPopupButton(pInfo->bPopupButton);
1339 aCellBtn.setHasHiddenMember(pInfo->bFilterActive);
1340 aCellBtn.draw();
1345 if ( bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged )
1347 Rectangle aRect = GetListValButtonRect( aListValPos );
1348 aComboButton.SetPosPixel( aRect.TopLeft() );
1349 aComboButton.SetSizePixel( aRect.GetSize() );
1350 pContentDev->SetClipRegion( aRect );
1351 aComboButton.Draw( FALSE, FALSE );
1352 pContentDev->SetClipRegion(); // always called from Draw() without clip region
1353 aComboButton.SetPosPixel( aOldPos ); // restore old state
1354 aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter)
1358 delete pQueryParam;
1359 aComboButton.SetOutputDevice( this );
1362 Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos )
1364 ScDocument* pDoc = pViewData->GetDocument();
1365 SCTAB nTab = pViewData->GetTabNo();
1366 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1367 long nLayoutSign = bLayoutRTL ? -1 : 1;
1369 ScDDComboBoxButton aButton( this ); // for optimal size
1370 Size aBtnSize = aButton.GetSizePixel();
1372 SCCOL nCol = rButtonPos.Col();
1373 SCROW nRow = rButtonPos.Row();
1375 long nCellSizeX; // width of this cell, including merged
1376 long nDummy;
1377 pViewData->GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy );
1379 // for height, only the cell's row is used, excluding merged cells
1380 long nCellSizeY = ScViewData::ToPixel( pDoc->GetRowHeight( nRow, nTab ), pViewData->GetPPTY() );
1381 long nAvailable = nCellSizeX;
1383 // left edge of next cell if there is a non-hidden next column
1384 SCCOL nNextCol = nCol + 1;
1385 const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE ));
1386 if ( pMerge->GetColMerge() > 1 )
1387 nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area
1388 while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) )
1389 ++nNextCol;
1390 BOOL bNextCell = ( nNextCol <= MAXCOL );
1391 if ( bNextCell )
1392 nAvailable = ScViewData::ToPixel( pDoc->GetColWidth( nNextCol, nTab ), pViewData->GetPPTX() );
1394 if ( nAvailable < aBtnSize.Width() )
1395 aBtnSize.Width() = nAvailable;
1396 if ( nCellSizeY < aBtnSize.Height() )
1397 aBtnSize.Height() = nCellSizeY;
1399 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich, TRUE );
1400 aPos.X() += nCellSizeX * nLayoutSign; // start of next cell
1401 if (!bNextCell)
1402 aPos.X() -= aBtnSize.Width() * nLayoutSign; // right edge of cell if next cell not available
1403 aPos.Y() += nCellSizeY - aBtnSize.Height();
1404 // X remains at the left edge
1406 if ( bLayoutRTL )
1407 aPos.X() -= aBtnSize.Width()-1; // align right edge of button with cell border
1409 return Rectangle( aPos, aBtnSize );
1412 BOOL ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab )
1414 ScDocument* pDoc = pViewData->GetDocument();
1415 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1416 ScQueryParam aQueryParam;
1418 if ( pDBData )
1419 pDBData->GetQueryParam( aQueryParam );
1420 else
1422 DBG_ERROR("Auto-Filter-Button ohne DBData");
1425 BOOL bSimpleQuery = TRUE;
1426 BOOL bColumnFound = FALSE;
1427 SCSIZE nQuery;
1429 if ( !aQueryParam.bInplace )
1430 bSimpleQuery = FALSE;
1432 // aQueryParam kann nur MAXQUERY Eintraege enthalten
1434 for ( nQuery=0; nQuery<MAXQUERY && bSimpleQuery; nQuery++ )
1435 if ( aQueryParam.GetEntry(nQuery).bDoQuery )
1437 if (aQueryParam.GetEntry(nQuery).nField == nCol)
1438 bColumnFound = TRUE;
1440 if (nQuery > 0)
1441 if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND)
1442 bSimpleQuery = FALSE;
1445 return ( bSimpleQuery && bColumnFound );
1448 void ScGridWindow::DrawComboButton( const Point& rCellPos,
1449 long nCellSizeX,
1450 long nCellSizeY,
1451 BOOL bArrowState,
1452 BOOL bBtnIn )
1454 Point aScrPos = rCellPos;
1455 Size aBtnSize = aComboButton.GetSizePixel();
1457 if ( nCellSizeX < aBtnSize.Width() || nCellSizeY < aBtnSize.Height() )
1459 if ( nCellSizeX < aBtnSize.Width() )
1460 aBtnSize.Width() = nCellSizeX;
1462 if ( nCellSizeY < aBtnSize.Height() )
1463 aBtnSize.Height() = nCellSizeY;
1465 aComboButton.SetSizePixel( aBtnSize );
1468 BOOL bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
1470 if ( bLayoutRTL )
1471 aScrPos.X() -= nCellSizeX - 1;
1472 else
1473 aScrPos.X() += nCellSizeX - aBtnSize.Width();
1474 aScrPos.Y() += nCellSizeY - aBtnSize.Height();
1476 aComboButton.SetPosPixel( aScrPos );
1478 HideCursor();
1479 aComboButton.Draw( bArrowState, bBtnIn );
1480 ShowCursor();
1483 void ScGridWindow::InvertSimple( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1484 BOOL bTestMerge, BOOL bRepeat )
1486 //! if INVERT_HIGHLIGHT swaps foreground and background (like on Mac),
1487 //! use INVERT_HIGHLIGHT only for cells that have no background color set
1488 //! (here and in ScOutputData::DrawMark)
1490 PutInOrder( nX1, nX2 );
1491 PutInOrder( nY1, nY2 );
1493 ScMarkData& rMark = pViewData->GetMarkData();
1494 ScDocument* pDoc = pViewData->GetDocument();
1495 SCTAB nTab = pViewData->GetTabNo();
1497 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1498 long nLayoutSign = bLayoutRTL ? -1 : 1;
1500 SCCOL nTestX2 = nX2;
1501 SCROW nTestY2 = nY2;
1502 if (bTestMerge)
1503 pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab );
1505 SCCOL nPosX = pViewData->GetPosX( eHWhich );
1506 SCROW nPosY = pViewData->GetPosY( eVWhich );
1507 if (nTestX2 < nPosX || nTestY2 < nPosY)
1508 return; // unsichtbar
1509 SCCOL nRealX1 = nX1;
1510 if (nX1 < nPosX)
1511 nX1 = nPosX;
1512 if (nY1 < nPosY)
1513 nY1 = nPosY;
1515 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
1516 if (nXRight > MAXCOL) nXRight = MAXCOL;
1517 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
1518 if (nYBottom > MAXROW) nYBottom = MAXROW;
1520 if (nX1 > nXRight || nY1 > nYBottom)
1521 return; // unsichtbar
1522 if (nX2 > nXRight) nX2 = nXRight;
1523 if (nY2 > nYBottom) nY2 = nYBottom;
1525 MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); // erst nach den return's !!!
1527 double nPPTX = pViewData->GetPPTX();
1528 double nPPTY = pViewData->GetPPTY();
1530 ScInvertMerger aInvert( this );
1532 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
1533 long nScrY = aScrPos.Y();
1534 BOOL bWasHidden = FALSE;
1535 for (SCROW nY=nY1; nY<=nY2; nY++)
1537 BOOL bFirstRow = ( nY == nPosY ); // first visible row?
1538 BOOL bDoHidden = FALSE; // versteckte nachholen ?
1539 USHORT nHeightTwips = pDoc->GetRowHeight( nY,nTab );
1540 BOOL bDoRow = ( nHeightTwips != 0 );
1541 if (bDoRow)
1543 if (bTestMerge)
1544 if (bWasHidden) // auf versteckte zusammengefasste testen
1546 // --nY; // nY geaendert -> vorherige zeichnen
1547 bDoHidden = TRUE;
1548 bDoRow = TRUE;
1551 bWasHidden = FALSE;
1553 else
1555 bWasHidden = TRUE;
1556 if (bTestMerge)
1557 if (nY==nY2)
1558 bDoRow = TRUE; // letzte Zeile aus Block
1561 if ( bDoRow )
1563 SCCOL nLoopEndX = nX2;
1564 if (nX2 < nX1) // Rest von zusammengefasst
1566 SCCOL nStartX = nX1;
1567 while ( ((const ScMergeFlagAttr*)pDoc->
1568 GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() )
1569 --nStartX;
1570 if (nStartX <= nX2)
1571 nLoopEndX = nX1;
1574 long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1;
1575 long nScrX = aScrPos.X();
1576 for (SCCOL nX=nX1; nX<=nLoopEndX; nX++)
1578 long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX );
1579 if ( nWidth > 0 )
1581 long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign;
1582 if (bTestMerge)
1584 SCROW nThisY = nY;
1585 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1586 const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern->
1587 GetItem(ATTR_MERGE_FLAG);
1588 if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) )
1590 while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 &&
1591 (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) )
1593 --nThisY;
1594 pPattern = pDoc->GetPattern( nX, nThisY, nTab );
1595 pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1599 // nur Rest von zusammengefasster zu sehen ?
1600 SCCOL nThisX = nX;
1601 if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 )
1603 while ( pMergeFlag->IsHorOverlapped() )
1605 --nThisX;
1606 pPattern = pDoc->GetPattern( nThisX, nThisY, nTab );
1607 pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1611 if ( rMark.IsCellMarked( nThisX, nThisY, TRUE ) == bRepeat )
1613 if ( !pMergeFlag->IsOverlapped() )
1615 ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
1616 if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0)
1618 Point aEndPos = pViewData->GetScrPos(
1619 nThisX + pMerge->GetColMerge(),
1620 nThisY + pMerge->GetRowMerge(), eWhich );
1621 if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY )
1623 aInvert.AddRect( Rectangle( nScrX,nScrY,
1624 aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) );
1627 else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1629 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1634 else // !bTestMerge
1636 if ( rMark.IsCellMarked( nX, nY, TRUE ) == bRepeat &&
1637 nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1639 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1643 nScrX = nEndX + nLayoutSign;
1646 nScrY = nEndY + 1;
1650 aInvert.Flush(); // before restoring MapMode
1652 SetMapMode(aOld);
1654 CheckInverted();
1657 void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects )
1659 // transformed from ScGridWindow::InvertSimple
1661 // ScMarkData& rMark = pViewData->GetMarkData();
1662 ScMarkData aMultiMark( pViewData->GetMarkData() );
1663 aMultiMark.SetMarking( FALSE );
1664 aMultiMark.MarkToMulti();
1666 ScDocument* pDoc = pViewData->GetDocument();
1667 SCTAB nTab = pViewData->GetTabNo();
1669 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1670 long nLayoutSign = bLayoutRTL ? -1 : 1;
1672 if ( !aMultiMark.IsMultiMarked() )
1673 return;
1675 ScRange aMultiRange;
1676 aMultiMark.GetMultiMarkArea( aMultiRange );
1677 SCCOL nX1 = aMultiRange.aStart.Col();
1678 SCROW nY1 = aMultiRange.aStart.Row();
1679 SCCOL nX2 = aMultiRange.aEnd.Col();
1680 SCROW nY2 = aMultiRange.aEnd.Row();
1682 PutInOrder( nX1, nX2 );
1683 PutInOrder( nY1, nY2 );
1685 BOOL bTestMerge = TRUE;
1686 BOOL bRepeat = TRUE;
1688 SCCOL nTestX2 = nX2;
1689 SCROW nTestY2 = nY2;
1690 if (bTestMerge)
1691 pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab );
1693 SCCOL nPosX = pViewData->GetPosX( eHWhich );
1694 SCROW nPosY = pViewData->GetPosY( eVWhich );
1695 if (nTestX2 < nPosX || nTestY2 < nPosY)
1696 return; // unsichtbar
1697 SCCOL nRealX1 = nX1;
1698 if (nX1 < nPosX)
1699 nX1 = nPosX;
1700 if (nY1 < nPosY)
1701 nY1 = nPosY;
1703 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
1704 if (nXRight > MAXCOL) nXRight = MAXCOL;
1705 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
1706 if (nYBottom > MAXROW) nYBottom = MAXROW;
1708 if (nX1 > nXRight || nY1 > nYBottom)
1709 return; // unsichtbar
1710 if (nX2 > nXRight) nX2 = nXRight;
1711 if (nY2 > nYBottom) nY2 = nYBottom;
1713 // MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); // erst nach den return's !!!
1715 double nPPTX = pViewData->GetPPTX();
1716 double nPPTY = pViewData->GetPPTY();
1718 ScInvertMerger aInvert( &rPixelRects );
1720 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
1721 long nScrY = aScrPos.Y();
1722 BOOL bWasHidden = FALSE;
1723 for (SCROW nY=nY1; nY<=nY2; nY++)
1725 BOOL bFirstRow = ( nY == nPosY ); // first visible row?
1726 BOOL bDoHidden = FALSE; // versteckte nachholen ?
1727 USHORT nHeightTwips = pDoc->GetRowHeight( nY,nTab );
1728 BOOL bDoRow = ( nHeightTwips != 0 );
1729 if (bDoRow)
1731 if (bTestMerge)
1732 if (bWasHidden) // auf versteckte zusammengefasste testen
1734 bDoHidden = TRUE;
1735 bDoRow = TRUE;
1738 bWasHidden = FALSE;
1740 else
1742 bWasHidden = TRUE;
1743 if (bTestMerge)
1744 if (nY==nY2)
1745 bDoRow = TRUE; // letzte Zeile aus Block
1748 if ( bDoRow )
1750 SCCOL nLoopEndX = nX2;
1751 if (nX2 < nX1) // Rest von zusammengefasst
1753 SCCOL nStartX = nX1;
1754 while ( ((const ScMergeFlagAttr*)pDoc->
1755 GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() )
1756 --nStartX;
1757 if (nStartX <= nX2)
1758 nLoopEndX = nX1;
1761 long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1;
1762 long nScrX = aScrPos.X();
1763 for (SCCOL nX=nX1; nX<=nLoopEndX; nX++)
1765 long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX );
1766 if ( nWidth > 0 )
1768 long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign;
1769 if (bTestMerge)
1771 SCROW nThisY = nY;
1772 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1773 const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern->
1774 GetItem(ATTR_MERGE_FLAG);
1775 if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) )
1777 while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 &&
1778 (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) )
1780 --nThisY;
1781 pPattern = pDoc->GetPattern( nX, nThisY, nTab );
1782 pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1786 // nur Rest von zusammengefasster zu sehen ?
1787 SCCOL nThisX = nX;
1788 if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 )
1790 while ( pMergeFlag->IsHorOverlapped() )
1792 --nThisX;
1793 pPattern = pDoc->GetPattern( nThisX, nThisY, nTab );
1794 pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1798 if ( aMultiMark.IsCellMarked( nThisX, nThisY, TRUE ) == bRepeat )
1800 if ( !pMergeFlag->IsOverlapped() )
1802 ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
1803 if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0)
1805 Point aEndPos = pViewData->GetScrPos(
1806 nThisX + pMerge->GetColMerge(),
1807 nThisY + pMerge->GetRowMerge(), eWhich );
1808 if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY )
1810 aInvert.AddRect( Rectangle( nScrX,nScrY,
1811 aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) );
1814 else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1816 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1821 else // !bTestMerge
1823 if ( aMultiMark.IsCellMarked( nX, nY, TRUE ) == bRepeat &&
1824 nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1826 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1830 nScrX = nEndX + nLayoutSign;
1833 nScrY = nEndY + 1;
1837 // aInvert.Flush(); // before restoring MapMode
1840 // -------------------------------------------------------------------------
1842 //UNUSED2008-05 void ScGridWindow::DrawDragRect( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 )
1843 //UNUSED2008-05 {
1844 //UNUSED2008-05 if ( nX2 < pViewData->GetPosX(eHWhich) || nY2 < pViewData->GetPosY(eVWhich) )
1845 //UNUSED2008-05 return;
1846 //UNUSED2008-05
1847 //UNUSED2008-05 Update(); // wegen XOR
1848 //UNUSED2008-05
1849 //UNUSED2008-05 MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL);
1850 //UNUSED2008-05
1851 //UNUSED2008-05 SCTAB nTab = pViewData->GetTabNo();
1852 //UNUSED2008-05
1853 //UNUSED2008-05 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
1854 //UNUSED2008-05 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
1855 //UNUSED2008-05 if (nX1 < nPosX) nX1 = nPosX;
1856 //UNUSED2008-05 if (nX2 < nPosX) nX2 = nPosX;
1857 //UNUSED2008-05 if (nY1 < nPosY) nY1 = nPosY;
1858 //UNUSED2008-05 if (nY2 < nPosY) nY2 = nPosY;
1859 //UNUSED2008-05
1860 //UNUSED2008-05 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
1861 //UNUSED2008-05
1862 //UNUSED2008-05 long nSizeXPix=0;
1863 //UNUSED2008-05 long nSizeYPix=0;
1864 //UNUSED2008-05 ScDocument* pDoc = pViewData->GetDocument();
1865 //UNUSED2008-05 double nPPTX = pViewData->GetPPTX();
1866 //UNUSED2008-05 double nPPTY = pViewData->GetPPTY();
1867 //UNUSED2008-05 SCCOLROW i;
1868 //UNUSED2008-05
1869 //UNUSED2008-05 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1870 //UNUSED2008-05 long nLayoutSign = bLayoutRTL ? -1 : 1;
1871 //UNUSED2008-05
1872 //UNUSED2008-05 if (ValidCol(nX2) && nX2>=nX1)
1873 //UNUSED2008-05 for (i=nX1; i<=nX2; i++)
1874 //UNUSED2008-05 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
1875 //UNUSED2008-05 else
1876 //UNUSED2008-05 {
1877 //UNUSED2008-05 aScrPos.X() -= nLayoutSign;
1878 //UNUSED2008-05 nSizeXPix += 2;
1879 //UNUSED2008-05 }
1880 //UNUSED2008-05
1881 //UNUSED2008-05 if (ValidRow(nY2) && nY2>=nY1)
1882 //UNUSED2008-05 for (i=nY1; i<=nY2; i++)
1883 //UNUSED2008-05 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
1884 //UNUSED2008-05 else
1885 //UNUSED2008-05 {
1886 //UNUSED2008-05 aScrPos.Y() -= 1;
1887 //UNUSED2008-05 nSizeYPix += 2;
1888 //UNUSED2008-05 }
1889 //UNUSED2008-05
1890 //UNUSED2008-05 aScrPos.X() -= 2 * nLayoutSign;
1891 //UNUSED2008-05 aScrPos.Y() -= 2;
1892 //UNUSED2008-05 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
1893 //UNUSED2008-05 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
1894 //UNUSED2008-05 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
1895 //UNUSED2008-05 if ( bLayoutRTL )
1896 //UNUSED2008-05 {
1897 //UNUSED2008-05 aRect.Left() = aRect.Right(); // end position is left
1898 //UNUSED2008-05 aRect.Right() = aScrPos.X();
1899 //UNUSED2008-05 }
1900 //UNUSED2008-05
1901 //UNUSED2008-05 Invert(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
1902 //UNUSED2008-05 Invert(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
1903 //UNUSED2008-05 Invert(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
1904 //UNUSED2008-05 Invert(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
1905 //UNUSED2008-05
1906 //UNUSED2008-05 SetMapMode(aOld);
1907 //UNUSED2008-05 }
1909 // -------------------------------------------------------------------------
1911 void ScGridWindow::DrawCursor()
1913 // #114409#
1914 // SCTAB nTab = pViewData->GetTabNo();
1915 // SCCOL nX = pViewData->GetCurX();
1916 // SCROW nY = pViewData->GetCurY();
1918 // // in verdeckten Zellen nicht zeichnen
1920 // ScDocument* pDoc = pViewData->GetDocument();
1921 // const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
1922 // const ScMergeFlagAttr& rMerge = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
1923 // if (rMerge.IsOverlapped())
1924 // return;
1926 // // links/oben ausserhalb des Bildschirms ?
1928 // BOOL bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
1929 // if (!bVis)
1930 // {
1931 // SCCOL nEndX = nX;
1932 // SCROW nEndY = nY;
1933 // ScDocument* pDoc = pViewData->GetDocument();
1934 // const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
1935 // if (rMerge.GetColMerge() > 1)
1936 // nEndX += rMerge.GetColMerge()-1;
1937 // if (rMerge.GetRowMerge() > 1)
1938 // nEndY += rMerge.GetRowMerge()-1;
1939 // bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
1940 // }
1942 // if ( bVis )
1943 // {
1944 // // hier kein Update, da aus Paint gerufen und laut Zaehler Cursor schon da
1945 // // wenn Update noetig, dann bei Hide/Showcursor vor dem Hoch-/Runterzaehlen
1947 // MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL);
1949 // Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
1950 // BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1952 // // completely right of/below the screen?
1953 // // (test with logical start position in aScrPos)
1954 // BOOL bMaybeVisible;
1955 // if ( bLayoutRTL )
1956 // bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
1957 // else
1958 // {
1959 // Size aOutSize = GetOutputSizePixel();
1960 // bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
1961 // }
1962 // if ( bMaybeVisible )
1963 // {
1964 // long nSizeXPix;
1965 // long nSizeYPix;
1966 // pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
1968 // if ( bLayoutRTL )
1969 // aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
1971 // BOOL bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ||
1972 // pViewData->GetVSplitMode() == SC_SPLIT_FIX );
1973 // if ( pViewData->GetActivePart()==eWhich || bFix )
1974 // {
1975 // // old UNX version with two Invert calls causes flicker.
1976 // // if optimization is needed, a new flag should be added
1977 // // to InvertTracking
1979 // aScrPos.X() -= 2;
1980 // aScrPos.Y() -= 2;
1981 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
1983 // Invert(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
1984 // Invert(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
1985 // Invert(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
1986 // Invert(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
1987 // }
1988 // else
1989 // {
1990 // Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) );
1991 // Invert( aRect );
1992 // }
1993 // }
1995 // SetMapMode(aOld);
1996 // }
1999 // AutoFill-Anfasser:
2001 void ScGridWindow::DrawAutoFillMark()
2003 // #114409#
2004 // if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() )
2005 // {
2006 // SCCOL nX = aAutoMarkPos.Col();
2007 // SCROW nY = aAutoMarkPos.Row();
2008 // SCTAB nTab = pViewData->GetTabNo();
2009 // ScDocument* pDoc = pViewData->GetDocument();
2010 // BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
2012 // Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
2013 // long nSizeXPix;
2014 // long nSizeYPix;
2015 // pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
2016 // if ( bLayoutRTL )
2017 // aFillPos.X() -= nSizeXPix + 3;
2018 // else
2019 // aFillPos.X() += nSizeXPix - 2;
2021 // aFillPos.Y() += nSizeYPix;
2022 // aFillPos.Y() -= 2;
2023 // Rectangle aFillRect( aFillPos, Size(6,6) );
2024 // // Anfasser von Zeichenobjekten sind 7*7
2026 // MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL);
2027 // Invert( aFillRect );
2028 // SetMapMode(aOld);
2029 // }
2032 // -------------------------------------------------------------------------
2034 void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt )
2036 Window::DataChanged(rDCEvt);
2038 if ( (rDCEvt.GetType() == DATACHANGED_PRINTER) ||
2039 (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
2040 (rDCEvt.GetType() == DATACHANGED_FONTS) ||
2041 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
2042 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2043 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
2045 if ( rDCEvt.GetType() == DATACHANGED_FONTS && eWhich == pViewData->GetActivePart() )
2046 pViewData->GetDocShell()->UpdateFontList();
2048 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2049 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
2051 if ( eWhich == pViewData->GetActivePart() ) // only once for the view
2053 ScTabView* pView = pViewData->GetView();
2055 // update scale in case the UI ScreenZoom has changed
2056 ScGlobal::UpdatePPT(this);
2057 pView->RecalcPPT();
2059 // RepeatResize in case scroll bar sizes have changed
2060 pView->RepeatResize();
2061 pView->UpdateAllOverlays();
2063 // invalidate cell attribs in input handler, in case the
2064 // EditEngine BackgroundColor has to be changed
2065 if ( pViewData->IsActive() )
2067 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
2068 if (pHdl)
2069 pHdl->ForgetLastPattern();
2074 Invalidate();