fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / gridwin4.cxx
blobceaf3d8d7c3a33ec701ee7be66385cf579b2bf59
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <editeng/eeitem.hxx>
23 #include <svtools/colorcfg.hxx>
24 #include <editeng/colritem.hxx>
25 #include <editeng/editview.hxx>
26 #include <editeng/fhgtitem.hxx>
27 #include <editeng/scripttypeitem.hxx>
28 #include <sfx2/bindings.hxx>
29 #include <sfx2/printer.hxx>
30 #include <vcl/settings.hxx>
32 #define LOK_USE_UNSTABLE_API
33 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
35 #include <svx/svdview.hxx>
36 #include "tabvwsh.hxx"
38 #include "gridwin.hxx"
39 #include "viewdata.hxx"
40 #include "output.hxx"
41 #include "document.hxx"
42 #include "attrib.hxx"
43 #include "patattr.hxx"
44 #include "dbdata.hxx"
45 #include "docoptio.hxx"
46 #include "notemark.hxx"
47 #include "dbfunc.hxx"
48 #include "scmod.hxx"
49 #include "inputhdl.hxx"
50 #include "rfindlst.hxx"
51 #include "hiranges.hxx"
52 #include "pagedata.hxx"
53 #include "docpool.hxx"
54 #include "globstr.hrc"
55 #include "docsh.hxx"
56 #include "cbutton.hxx"
57 #include "invmerge.hxx"
58 #include "editutil.hxx"
59 #include "inputopt.hxx"
60 #include "fillinfo.hxx"
61 #include "dpcontrol.hxx"
62 #include "queryparam.hxx"
63 #include "queryentry.hxx"
64 #include "markdata.hxx"
65 #include "sc.hrc"
66 #include <vcl/virdev.hxx>
67 #include <svx/sdrpaintwindow.hxx>
69 static void lcl_LimitRect( Rectangle& rRect, const Rectangle& rVisible )
71 if ( rRect.Top() < rVisible.Top()-1 ) rRect.Top() = rVisible.Top()-1;
72 if ( rRect.Bottom() > rVisible.Bottom()+1 ) rRect.Bottom() = rVisible.Bottom()+1;
74 // auch wenn das inner-Rectangle nicht sichtbar ist, muss evtl.
75 // die Titelzeile gezeichnet werden, darum kein Rueckgabewert mehr.
76 // Wenn's weit daneben liegt, wird lcl_DrawOneFrame erst gar nicht gerufen.
79 static void lcl_DrawOneFrame( vcl::RenderContext* pDev, const Rectangle& rInnerPixel,
80 const OUString& rTitle, const Color& rColor, bool bTextBelow,
81 double nPPTX, double nPPTY, const Fraction& rZoomY,
82 ScDocument* pDoc, ScViewData* pButtonViewData, bool bLayoutRTL )
84 // pButtonViewData wird nur benutzt, um die Button-Groesse zu setzen,
85 // darf ansonsten NULL sein!
87 Rectangle aInner = rInnerPixel;
88 if ( bLayoutRTL )
90 aInner.Left() = rInnerPixel.Right();
91 aInner.Right() = rInnerPixel.Left();
94 Rectangle aVisible( Point(0,0), pDev->GetOutputSizePixel() );
95 lcl_LimitRect( aInner, aVisible );
97 Rectangle aOuter = aInner;
98 long nHor = (long) ( SC_SCENARIO_HSPACE * nPPTX );
99 long nVer = (long) ( SC_SCENARIO_VSPACE * nPPTY );
100 aOuter.Left() -= nHor;
101 aOuter.Right() += nHor;
102 aOuter.Top() -= nVer;
103 aOuter.Bottom() += nVer;
105 // use ScPatternAttr::GetFont only for font size
106 vcl::Font aAttrFont;
107 static_cast<const ScPatternAttr&>(pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).
108 GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY);
110 // everything else from application font
111 vcl::Font aAppFont = pDev->GetSettings().GetStyleSettings().GetAppFont();
112 aAppFont.SetSize( aAttrFont.GetSize() );
114 aAppFont.SetAlign( ALIGN_TOP );
115 pDev->SetFont( aAppFont );
117 Size aTextSize( pDev->GetTextWidth( rTitle ), pDev->GetTextHeight() );
119 if ( bTextBelow )
120 aOuter.Bottom() += aTextSize.Height();
121 else
122 aOuter.Top() -= aTextSize.Height();
124 pDev->SetLineColor();
125 pDev->SetFillColor( rColor );
126 // links, oben, rechts, unten
127 pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aInner.Left(), aOuter.Bottom() ) );
128 pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aOuter.Right(), aInner.Top() ) );
129 pDev->DrawRect( Rectangle( aInner.Right(), aOuter.Top(), aOuter.Right(), aOuter.Bottom() ) );
130 pDev->DrawRect( Rectangle( aOuter.Left(), aInner.Bottom(), aOuter.Right(), aOuter.Bottom() ) );
132 long nButtonY = bTextBelow ? aInner.Bottom() : aOuter.Top();
134 ScDDComboBoxButton aComboButton(pDev);
135 aComboButton.SetOptSizePixel();
136 long nBWidth = ( aComboButton.GetSizePixel().Width() * rZoomY.GetNumerator() )
137 / rZoomY.GetDenominator();
138 long nBHeight = nVer + aTextSize.Height() + 1;
139 Size aButSize( nBWidth, nBHeight );
140 long nButtonPos = bLayoutRTL ? aOuter.Left() : aOuter.Right()-nBWidth+1;
141 aComboButton.Draw( Point(nButtonPos, nButtonY), aButSize, false );
142 if (pButtonViewData)
143 pButtonViewData->SetScenButSize( aButSize );
145 long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left();
147 bool bWasClip = false;
148 vcl::Region aOldClip;
149 bool bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() );
150 if ( bClip )
152 if (pDev->IsClipRegion())
154 bWasClip = true;
155 aOldClip = pDev->GetActiveClipRegion();
157 long nClipStartX = bLayoutRTL ? aOuter.Left() + nBWidth : aInner.Left();
158 long nClipEndX = bLayoutRTL ? aInner.Right() : aOuter.Right() - nBWidth;
159 pDev->SetClipRegion( vcl::Region(Rectangle( nClipStartX, nButtonY + nVer/2,
160 nClipEndX, nButtonY + nVer/2 + aTextSize.Height())) );
163 pDev->DrawText( Point( nTextStart, nButtonY + nVer/2 ), rTitle );
165 if ( bClip )
167 if ( bWasClip )
168 pDev->SetClipRegion(aOldClip);
169 else
170 pDev->SetClipRegion();
173 pDev->SetFillColor();
174 pDev->SetLineColor( COL_BLACK );
175 pDev->DrawRect( aInner );
176 pDev->DrawRect( aOuter );
179 static void lcl_DrawScenarioFrames( OutputDevice* pDev, ScViewData* pViewData, ScSplitPos eWhich,
180 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 )
182 ScDocument* pDoc = pViewData->GetDocument();
183 SCTAB nTab = pViewData->GetTabNo();
184 SCTAB nTabCount = pDoc->GetTableCount();
185 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
187 if ( nX1 > 0 ) --nX1;
188 if ( nY1>=2 ) nY1 -= 2; // Hack: Titelzeile beruehrt zwei Zellen
189 else if ( nY1 > 0 ) --nY1;
190 if ( nX2 < MAXCOL ) ++nX2;
191 if ( nY2 < MAXROW-1 ) nY2 += 2; // Hack: Titelzeile beruehrt zwei Zellen
192 else if ( nY2 < MAXROW ) ++nY2;
193 ScRange aViewRange( nX1,nY1,nTab, nX2,nY2,nTab );
195 //! Ranges an der Table cachen!!!!
197 ScMarkData aMarks;
198 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
199 pDoc->MarkScenario( i, nTab, aMarks, false, SC_SCENARIO_SHOWFRAME );
200 ScRangeListRef xRanges = new ScRangeList;
201 aMarks.FillRangeListWithMarks( xRanges, false );
203 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
204 long nLayoutSign = bLayoutRTL ? -1 : 1;
206 for (size_t j = 0, n = xRanges->size(); j < n; ++j)
208 ScRange aRange = *(*xRanges)[j];
209 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
210 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
211 pDoc->ExtendTotalMerge( aRange );
213 //! -> Repaint beim Zusammenfassen erweitern !!!
215 if ( aRange.Intersects( aViewRange ) ) //! Platz fuer Text/Button?
217 Point aStartPos = pViewData->GetScrPos(
218 aRange.aStart.Col(), aRange.aStart.Row(), eWhich, true );
219 Point aEndPos = pViewData->GetScrPos(
220 aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, true );
221 // on the grid:
222 aStartPos.X() -= nLayoutSign;
223 aStartPos.Y() -= 1;
224 aEndPos.X() -= nLayoutSign;
225 aEndPos.Y() -= 1;
227 bool bTextBelow = ( aRange.aStart.Row() == 0 );
229 OUString aCurrent;
230 Color aColor( COL_LIGHTGRAY );
231 for (SCTAB nAct=nTab+1; nAct<nTabCount && pDoc->IsScenario(nAct); nAct++)
232 if ( pDoc->IsActiveScenario(nAct) && pDoc->HasScenarioRange(nAct,aRange) )
234 OUString aDummyComment;
235 sal_uInt16 nDummyFlags;
236 pDoc->GetName( nAct, aCurrent );
237 pDoc->GetScenarioData( nAct, aDummyComment, aColor, nDummyFlags );
240 if (aCurrent.isEmpty())
241 aCurrent = ScGlobal::GetRscString( STR_EMPTYDATA );
243 //! eigener Text "(keins)" statt "(leer)" ???
245 lcl_DrawOneFrame( pDev, Rectangle( aStartPos, aEndPos ),
246 aCurrent, aColor, bTextBelow,
247 pViewData->GetPPTX(), pViewData->GetPPTY(), pViewData->GetZoomY(),
248 pDoc, pViewData, bLayoutRTL );
254 static void lcl_DrawHighlight( ScOutputData& rOutputData, ScViewData* pViewData,
255 const std::vector<ScHighlightEntry>& rHighlightRanges )
257 SCTAB nTab = pViewData->GetTabNo();
258 std::vector<ScHighlightEntry>::const_iterator pIter;
259 for ( pIter = rHighlightRanges.begin(); pIter != rHighlightRanges.end(); ++pIter)
261 ScRange aRange = pIter->aRef;
262 if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() )
264 rOutputData.DrawRefMark(
265 aRange.aStart.Col(), aRange.aStart.Row(),
266 aRange.aEnd.Col(), aRange.aEnd.Row(),
267 pIter->aColor, false );
272 void ScGridWindow::DoInvertRect( const Rectangle& rPixel )
274 if ( rPixel == aInvertRect )
275 aInvertRect = Rectangle(); // aufheben
276 else
278 OSL_ENSURE( aInvertRect.IsEmpty(), "DoInvertRect nicht paarig" );
280 aInvertRect = rPixel; // neues Rechteck merken
283 UpdateHeaderOverlay(); // uses aInvertRect
286 void ScGridWindow::PrePaint(vcl::RenderContext& /*rRenderContext*/)
288 // forward PrePaint to DrawingLayer
289 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
291 if(pTabViewShell)
293 SdrView* pDrawView = pTabViewShell->GetSdrView();
295 if (pDrawView)
297 pDrawView->PrePaint();
302 void ScGridWindow::Paint( vcl::RenderContext& /*rRenderContext*/, const Rectangle& rRect )
304 ScDocument* pDoc = pViewData->GetDocument();
305 if ( pDoc->IsInInterpreter() )
307 // via Reschedule, interpretierende Zellen nicht nochmal anstossen
308 // hier kein Invalidate, sonst kommt z.B. eine Error-Box nie an die Reihe
309 // (Bug 36381). Durch bNeedsRepaint wird spaeter alles nochmal gemalt.
311 if ( bNeedsRepaint )
313 //! Rechtecke zusammenfassen?
314 aRepaintPixel = Rectangle(); // mehrfach -> alles painten
316 else
318 bNeedsRepaint = true;
319 aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich
321 return;
324 // #i117893# If GetSizePixel needs to call the resize handler, the resulting nested Paint call
325 // (possibly for a larger rectangle) has to be allowed. Call GetSizePixel before setting bIsInPaint.
326 GetSizePixel();
328 if (bIsInPaint)
329 return;
331 bIsInPaint = true;
333 Rectangle aPixRect = LogicToPixel( rRect );
335 SCCOL nX1 = pViewData->GetPosX(eHWhich);
336 SCROW nY1 = pViewData->GetPosY(eVWhich);
338 SCTAB nTab = pViewData->GetTabNo();
340 double nPPTX = pViewData->GetPPTX();
341 double nPPTY = pViewData->GetPPTY();
343 Rectangle aMirroredPixel = aPixRect;
344 if ( pDoc->IsLayoutRTL( nTab ) )
346 // mirror and swap
347 long nWidth = GetSizePixel().Width();
348 aMirroredPixel.Left() = nWidth - 1 - aPixRect.Right();
349 aMirroredPixel.Right() = nWidth - 1 - aPixRect.Left();
352 long nScrX = ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
353 while ( nScrX <= aMirroredPixel.Left() && nX1 < MAXCOL )
355 ++nX1;
356 nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
358 SCCOL nX2 = nX1;
359 while ( nScrX <= aMirroredPixel.Right() && nX2 < MAXCOL )
361 ++nX2;
362 nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX );
365 long nScrY = 0;
366 ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, MAXROW, nPPTY, pDoc, nTab);
367 SCROW nY2 = nY1;
368 if (nScrY <= aPixRect.Bottom() && nY2 < MAXROW)
370 ++nY2;
371 ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, MAXROW, nPPTY, pDoc, nTab);
374 Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // don't continue with painting
376 bIsInPaint = false;
379 void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode )
381 ScDocShell* pDocSh = pViewData->GetDocShell();
382 ScDocument& rDoc = pDocSh->GetDocument();
384 // let's ignore the normal Draw() attempts when doing the tiled rendering,
385 // all the rendering should go through PaintTile() in that case.
386 // TODO revisit if we can actually turn this into an assert(), and clean
387 // up the callers
388 if (rDoc.GetDrawLayer()->isTiledRendering())
389 return;
391 ScModule* pScMod = SC_MOD();
392 bool bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg();
394 if (pViewData->IsMinimized())
395 return;
397 PutInOrder( nX1, nX2 );
398 PutInOrder( nY1, nY2 );
400 OSL_ENSURE( ValidCol(nX2) && ValidRow(nY2), "GridWin Draw area too big" );
402 UpdateVisibleRange();
404 if (nX2 < maVisibleRange.mnCol1 || nY2 < maVisibleRange.mnRow1)
405 return;
406 // invisible
407 if (nX1 < maVisibleRange.mnCol1)
408 nX1 = maVisibleRange.mnCol1;
409 if (nY1 < maVisibleRange.mnRow1)
410 nY1 = maVisibleRange.mnRow1;
412 if (nX1 > maVisibleRange.mnCol2 || nY1 > maVisibleRange.mnRow2)
413 return;
415 if (nX2 > maVisibleRange.mnCol2)
416 nX2 = maVisibleRange.mnCol2;
417 if (nY2 > maVisibleRange.mnRow2)
418 nY2 = maVisibleRange.mnRow2;
420 if ( eMode != SC_UPDATE_MARKS && nX2 < maVisibleRange.mnCol2)
421 nX2 = maVisibleRange.mnCol2; // zum Weiterzeichnen
423 // point of no return
425 ++nPaintCount; // mark that painting is in progress
427 SCTAB nTab = pViewData->GetTabNo();
428 rDoc.ExtendHidden( nX1, nY1, nX2, nY2, nTab );
430 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
431 long nMirrorWidth = GetSizePixel().Width();
432 bool bLayoutRTL = rDoc.IsLayoutRTL( nTab );
433 if ( bLayoutRTL )
435 long nEndPixel = pViewData->GetScrPos( nX2+1, maVisibleRange.mnRow1, eWhich ).X();
436 nMirrorWidth = aScrPos.X() - nEndPixel;
437 aScrPos.X() = nEndPixel + 1;
440 long nScrX = aScrPos.X();
441 long nScrY = aScrPos.Y();
443 SCCOL nCurX = pViewData->GetCurX();
444 SCROW nCurY = pViewData->GetCurY();
445 SCCOL nCurEndX = nCurX;
446 SCROW nCurEndY = nCurY;
447 rDoc.ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab );
448 bool bCurVis = nCursorHideCount==0 &&
449 ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 );
451 // AutoFill-Anfasser
452 if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab &&
453 ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) )
455 SCCOL nHdlX = aAutoMarkPos.Col();
456 SCROW nHdlY = aAutoMarkPos.Row();
457 rDoc.ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab );
458 bCurVis = ( nHdlX+1 >= nX1 && nHdlX <= nX2 && nHdlY+1 >= nY1 && nHdlY <= nY2 );
459 // left and top is unaffected
461 //! AutoFill-Anfasser alleine (ohne Cursor) zeichnen ???
464 double nPPTX = pViewData->GetPPTX();
465 double nPPTY = pViewData->GetPPTY();
467 const ScViewOptions& rOpts = pViewData->GetOptions();
469 // data block
471 ScTableInfo aTabInfo;
472 rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
473 nPPTX, nPPTY, false, rOpts.GetOption(VOPT_FORMULAS),
474 &pViewData->GetMarkData() );
476 Fraction aZoomX = pViewData->GetZoomX();
477 Fraction aZoomY = pViewData->GetZoomY();
478 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, &rDoc, nTab,
479 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
480 &aZoomX, &aZoomY );
482 aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL
483 aOutputData.SetSpellCheckContext(mpSpellCheckCxt.get());
485 ScopedVclPtr< VirtualDevice > xFmtVirtDev;
486 bool bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode?
488 if ( bTextWysiwyg )
490 // use printer for text formatting
492 OutputDevice* pFmtDev = rDoc.GetPrinter();
493 pFmtDev->SetMapMode( pViewData->GetLogicMode(eWhich) );
494 aOutputData.SetFmtDevice( pFmtDev );
496 else if ( aZoomX != aZoomY && pViewData->IsOle() )
498 // #i45033# For OLE inplace editing with different zoom factors,
499 // use a virtual device with 1/100th mm as text formatting reference
501 xFmtVirtDev.reset( VclPtr<VirtualDevice>::Create() );
502 xFmtVirtDev->SetMapMode( MAP_100TH_MM );
503 aOutputData.SetFmtDevice( xFmtVirtDev.get() );
505 bLogicText = true; // use logic MapMode
508 DrawContent(*this, aTabInfo, aOutputData, bLogicText, eMode);
510 // Wenn waehrend des Paint etwas invertiert wurde (Selektion geaendert aus Basic-Macro),
511 // ist das jetzt durcheinandergekommen und es muss neu gemalt werden
513 OSL_ENSURE(nPaintCount, "nPaintCount falsch");
514 --nPaintCount;
515 if (!nPaintCount)
516 CheckNeedsRepaint();
518 // Flag drawn formula cells "unchanged".
519 rDoc.ResetChanged(ScRange(nX1, nY1, nTab, nX2, nY2, nTab));
520 rDoc.ClearFormulaContext();
523 void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableInfo, ScOutputData& aOutputData,
524 bool bLogicText, ScUpdateMode eMode)
526 ScModule* pScMod = SC_MOD();
527 ScDocShell* pDocSh = pViewData->GetDocShell();
528 ScDocument& rDoc = pDocSh->GetDocument();
529 const ScViewOptions& rOpts = pViewData->GetOptions();
530 bool bIsTiledRendering = rDoc.GetDrawLayer()->isTiledRendering();
532 SCTAB nTab = aOutputData.nTab;
533 SCCOL nX1 = aOutputData.nX1;
534 SCROW nY1 = aOutputData.nY1;
535 SCCOL nX2 = aOutputData.nX2;
536 SCROW nY2 = aOutputData.nY2;
537 long nScrX = aOutputData.nScrX;
538 long nScrY = aOutputData.nScrY;
540 const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig();
541 Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, false ).nColor );
542 if ( aGridColor.GetColor() == COL_TRANSPARENT )
544 // use view options' grid color only if color config has "automatic" color
545 aGridColor = rOpts.GetGridColor();
548 aOutputData.SetSyntaxMode ( pViewData->IsSyntaxMode() );
549 aOutputData.SetGridColor ( aGridColor );
550 aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) );
551 aOutputData.SetShowFormulas ( rOpts.GetOption( VOPT_FORMULAS ) );
552 aOutputData.SetShowSpellErrors ( rDoc.GetDocOptions().IsAutoSpell() );
553 aOutputData.SetMarkClipped ( rOpts.GetOption( VOPT_CLIPMARKS ) );
555 aOutputData.SetUseStyleColor( true ); // always set in table view
557 aOutputData.SetEditObject( GetEditObject() );
558 aOutputData.SetViewShell( pViewData->GetViewShell() );
560 bool bGrid = rOpts.GetOption( VOPT_GRID ) && pViewData->GetShowGrid();
561 bool bGridFirst = !rOpts.GetOption( VOPT_GRID_ONTOP );
563 bool bPage = rOpts.GetOption( VOPT_PAGEBREAKS );
565 if ( eMode == SC_UPDATE_CHANGED )
567 aOutputData.FindChanged();
568 aOutputData.SetSingleGrid(true);
571 bool bPageMode = pViewData->IsPagebreakMode();
572 if (bPageMode) // nach FindChanged
574 // SetPagebreakMode initialisiert auch bPrinted Flags
575 aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() );
578 EditView* pEditView = NULL;
579 bool bEditMode = pViewData->HasEditView(eWhich);
580 if ( bEditMode && pViewData->GetRefTabNo() == nTab )
582 SCCOL nEditCol;
583 SCROW nEditRow;
584 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
585 SCCOL nEditEndCol = pViewData->GetEditEndCol();
586 SCROW nEditEndRow = pViewData->GetEditEndRow();
588 if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 )
589 aOutputData.SetEditCell( nEditCol, nEditRow );
590 else
591 bEditMode = false;
594 // define drawing layer map mode and paint rectangle
595 MapMode aDrawMode = GetDrawMapMode();
596 if (bIsTiledRendering)
598 // FIXME this shouldn't be necessary once we change the entire Calc to
599 // work in the logic coordinates (ideally 100ths of mm - so that it is
600 // the same as editeng and drawinglayer), and get rid of all the
601 // SetMapMode's and other unneccessary fun we have with pixels
602 // See also ScGridWindow::GetDrawMapMode() for the rest of this hack
603 aDrawMode.SetOrigin(PixelToLogic(Point(nScrX, nScrY), aDrawMode));
605 Rectangle aDrawingRectLogic;
606 bool bLayoutRTL = rDoc.IsLayoutRTL( nTab );
609 // get drawing pixel rect
610 Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
612 // correct for border (left/right)
613 if(MAXCOL == nX2)
615 if(bLayoutRTL)
617 aDrawingRectPixel.Left() = 0L;
619 else
621 aDrawingRectPixel.Right() = GetOutputSizePixel().getWidth();
625 // correct for border (bottom)
626 if(MAXROW == nY2)
628 aDrawingRectPixel.Bottom() = GetOutputSizePixel().getHeight();
631 // get logic positions
632 aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode);
635 OutputDevice* pContentDev = &rDevice; // device for document content, used by overlay manager
636 SdrPaintWindow* pTargetPaintWindow = 0; // #i74769# work with SdrPaintWindow directly
639 // init redraw
640 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
642 if(pTabViewShell)
644 MapMode aCurrentMapMode(pContentDev->GetMapMode());
645 pContentDev->SetMapMode(aDrawMode);
646 SdrView* pDrawView = pTabViewShell->GetSdrView();
648 if(pDrawView)
650 // #i74769# Use new BeginDrawLayers() interface
651 vcl::Region aDrawingRegion(aDrawingRectLogic);
652 pTargetPaintWindow = pDrawView->BeginDrawLayers(pContentDev, aDrawingRegion);
653 OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)");
655 if (!bIsTiledRendering)
657 // #i74769# get target device from SdrPaintWindow, this may be the prerender
658 // device now, too.
659 pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice());
660 aOutputData.SetContentDevice(pContentDev);
664 pContentDev->SetMapMode(aCurrentMapMode);
668 // Rand (Wiese) (Pixel)
669 if ( nX2==MAXCOL || nY2==MAXROW )
671 // save MapMode and set to pixel
672 MapMode aCurrentMapMode(pContentDev->GetMapMode());
673 pContentDev->SetMapMode(MAP_PIXEL);
675 Rectangle aPixRect = Rectangle( Point(), GetOutputSizePixel() );
676 pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor );
677 pContentDev->SetLineColor();
678 if ( nX2==MAXCOL )
680 Rectangle aDrawRect( aPixRect );
681 if ( bLayoutRTL )
682 aDrawRect.Right() = nScrX - 1;
683 else
684 aDrawRect.Left() = nScrX + aOutputData.GetScrW();
685 if (aDrawRect.Right() >= aDrawRect.Left())
686 pContentDev->DrawRect( aDrawRect );
688 if ( nY2==MAXROW )
690 Rectangle aDrawRect( aPixRect );
691 aDrawRect.Top() = nScrY + aOutputData.GetScrH();
692 if ( nX2==MAXCOL )
694 // no double painting of the corner
695 if ( bLayoutRTL )
696 aDrawRect.Left() = nScrX;
697 else
698 aDrawRect.Right() = nScrX + aOutputData.GetScrW() - 1;
700 if (aDrawRect.Bottom() >= aDrawRect.Top())
701 pContentDev->DrawRect( aDrawRect );
704 // restore MapMode
705 pContentDev->SetMapMode(aCurrentMapMode);
708 if ( rDoc.HasBackgroundDraw( nTab, aDrawingRectLogic ) )
710 pContentDev->SetMapMode(MAP_PIXEL);
711 aOutputData.DrawClear();
713 // Drawing Hintergrund
715 pContentDev->SetMapMode(aDrawMode);
716 DrawRedraw( aOutputData, eMode, SC_LAYER_BACK );
718 else
719 aOutputData.SetSolidBackground(true);
721 pContentDev->SetMapMode(MAP_PIXEL);
722 aOutputData.DrawDocumentBackground();
724 if ( bGridFirst && ( bGrid || bPage ) )
725 aOutputData.DrawGrid( bGrid, bPage );
727 aOutputData.DrawBackground();
729 if ( !bGridFirst && ( bGrid || bPage ) )
730 aOutputData.DrawGrid( bGrid, bPage );
732 if ( bPageMode )
734 // DrawPagePreview draws complete lines/page numbers, must always be clipped
735 if ( aOutputData.SetChangedClip() )
737 DrawPagePreview(nX1,nY1,nX2,nY2, pContentDev);
738 pContentDev->SetClipRegion();
742 aOutputData.DrawShadow();
743 aOutputData.DrawFrame();
745 // Show Note Mark
746 if ( rOpts.GetOption( VOPT_NOTES ) )
747 aOutputData.DrawNoteMarks();
749 if ( !bLogicText )
750 aOutputData.DrawStrings(false); // in pixel MapMode
752 // edit cells and printer-metrics text must be before the buttons
753 // (DataPilot buttons contain labels in UI font)
755 pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich));
756 if ( bLogicText )
757 aOutputData.DrawStrings(true); // in logic MapMode if bLogicText is set
758 aOutputData.DrawEdit(true);
760 // the buttons are painted in absolute coordinates
761 if (bIsTiledRendering)
763 // Tiled offset nScrX, nScrY
764 MapMode aMap( MAP_PIXEL );
765 aMap.SetOrigin(Point(nScrX, nScrY));
766 pContentDev->SetMapMode(aMap);
768 else
769 pContentDev->SetMapMode(MAP_PIXEL);
771 // Autofilter- und Pivot-Buttons
773 DrawButtons(nX1, nX2, rTableInfo, pContentDev); // Pixel
775 pContentDev->SetMapMode(MAP_PIXEL);
777 aOutputData.DrawClipMarks();
779 // Szenario / ChangeTracking muss auf jeden Fall nach DrawGrid sein, auch bei !bGridFirst
781 //! Test, ob ChangeTrack-Anzeige aktiv ist
782 //! Szenario-Rahmen per View-Optionen abschaltbar?
784 SCTAB nTabCount = rDoc.GetTableCount();
785 const std::vector<ScHighlightEntry> &rHigh = pViewData->GetView()->GetHighlightRanges();
786 bool bHasScenario = ( nTab+1<nTabCount && rDoc.IsScenario(nTab+1) && !rDoc.IsScenario(nTab) );
787 bool bHasChange = ( rDoc.GetChangeTrack() != NULL );
789 if ( bHasChange || bHasScenario || !rHigh.empty() )
792 //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!)
794 bool bAny = true;
795 if (eMode == SC_UPDATE_CHANGED)
796 bAny = aOutputData.SetChangedClip();
797 if (bAny)
799 if ( bHasChange )
800 aOutputData.DrawChangeTrack();
802 if ( bHasScenario )
803 lcl_DrawScenarioFrames( pContentDev, pViewData, eWhich, nX1,nY1,nX2,nY2 );
805 lcl_DrawHighlight( aOutputData, pViewData, rHigh );
807 if (eMode == SC_UPDATE_CHANGED)
808 pContentDev->SetClipRegion();
812 // Drawing Vordergrund
814 pContentDev->SetMapMode(aDrawMode);
816 DrawRedraw( aOutputData, eMode, SC_LAYER_FRONT );
817 DrawRedraw( aOutputData, eMode, SC_LAYER_INTERN );
818 DrawSdrGrid( aDrawingRectLogic, pContentDev );
820 if (!bIsInScroll) // Drawing Markierungen
822 if(eMode == SC_UPDATE_CHANGED && aOutputData.SetChangedClip())
824 pContentDev->SetClipRegion();
828 pContentDev->SetMapMode(MAP_PIXEL);
830 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() )
832 Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor );
833 aOutputData.DrawRefMark( pViewData->GetRefStartX(), pViewData->GetRefStartY(),
834 pViewData->GetRefEndX(), pViewData->GetRefEndY(),
835 aRefColor, false );
838 // Range-Finder
840 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
841 if (pHdl)
843 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
844 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
845 pRangeFinder->GetDocName() == pDocSh->GetTitle() )
847 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
848 for (sal_uInt16 i=0; i<nCount; i++)
850 ScRangeFindData* pData = pRangeFinder->GetObject(i);
852 ScRange aRef = pData->aRef;
853 aRef.Justify();
854 if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab )
855 aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(),
856 aRef.aEnd.Col(), aRef.aEnd.Row(),
857 Color( pData->nColorData ),
858 true );
864 // end redraw
865 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
867 if(pTabViewShell)
869 MapMode aCurrentMapMode(pContentDev->GetMapMode());
870 pContentDev->SetMapMode(aDrawMode);
871 SdrView* pDrawView = pTabViewShell->GetSdrView();
873 if(pDrawView)
875 // #i74769# work with SdrPaintWindow directly
876 pDrawView->EndDrawLayers(*pTargetPaintWindow, true);
879 pContentDev->SetMapMode(aCurrentMapMode);
883 // In-place editing - when the user is typing, we need to paint the text
884 // using the editeng.
885 // It's being done after EndDrawLayers() to get it outside the overlay
886 // buffer and on top of everything.
887 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
889 // get the coordinates of the area we need to clear (overpaint by
890 // the background)
891 SCCOL nCol1 = pViewData->GetEditStartCol();
892 SCROW nRow1 = pViewData->GetEditStartRow();
893 SCCOL nCol2 = pViewData->GetEditEndCol();
894 SCROW nRow2 = pViewData->GetEditEndRow();
895 rDevice.SetLineColor();
896 rDevice.SetFillColor(pEditView->GetBackgroundColor());
897 Point aStart = pViewData->GetScrPos( nCol1, nRow1, eWhich );
898 Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eWhich );
900 // don't overwrite grid
901 long nLayoutSign = bLayoutRTL ? -1 : 1;
902 aEnd.X() -= 2 * nLayoutSign;
903 aEnd.Y() -= 2;
905 // set the correct mapmode
906 Rectangle aBackground(aStart, aEnd);
907 if (bIsTiledRendering)
909 aBackground += Point(nScrX, nScrY);
910 rDevice.SetMapMode(aDrawMode);
912 else
913 rDevice.SetMapMode(pViewData->GetLogicMode());
915 // paint the background
916 rDevice.DrawRect(rDevice.PixelToLogic(aBackground));
918 // paint the editeng text
919 pEditView->Paint(rDevice.PixelToLogic(Rectangle(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()))), &rDevice);
920 rDevice.SetMapMode(MAP_PIXEL);
923 if (pViewData->HasEditView(eWhich))
925 // flush OverlayManager before changing the MapMode
926 flushOverlayManager();
928 // set MapMode for text edit
929 rDevice.SetMapMode(pViewData->GetLogicMode());
931 else
932 rDevice.SetMapMode(aDrawMode);
934 if (mpNoteMarker)
935 mpNoteMarker->Draw(); // ueber den Cursor, im Drawing-MapMode
938 void ScGridWindow::PaintTile( VirtualDevice& rDevice,
939 int nOutputWidth, int nOutputHeight,
940 int nTilePosX, int nTilePosY,
941 long nTileWidth, long nTileHeight )
943 // Output size is in pixels while tile position and size are in logical units (twips).
945 // Assumption: always paint the whole sheet i.e. "visible" range is always
946 // from (0,0) to last data position.
948 // Tile geometry is independent of the zoom level, but the output size is
949 // dependent of the zoom level. Determine the correct zoom level before
950 // we start.
952 // FIXME the painting works using a mixture of drawing with coordinates in
953 // pixels and in logic coordinates; it should be cleaned up to use logic
954 // coords only, and avoid all the SetMapMode()'s.
955 // Similarly to Writer, we should set the mapmode once on the rDevice, and
956 // not care about any zoom settings.
958 Fraction aFracX(long(nOutputWidth * TWIPS_PER_PIXEL), nTileWidth);
959 Fraction aFracY(long(nOutputHeight * TWIPS_PER_PIXEL), nTileHeight);
961 // page break zoom, and aLogicMode in ScViewData
962 pViewData->SetZoom(aFracX, aFracY, true);
964 double fTilePosXPixel = static_cast<double>(nTilePosX) * nOutputWidth / nTileWidth;
965 double fTilePosYPixel = static_cast<double>(nTilePosY) * nOutputHeight / nTileHeight;
967 SCTAB nTab = pViewData->GetTabNo();
968 ScDocument* pDoc = pViewData->GetDocument();
970 SCCOL nStartCol = 0, nEndCol = 0;
971 SCROW nStartRow = 0, nEndRow = 0;
973 // size of the document including drawings, charts, etc.
974 pDoc->GetTiledRenderingArea(nTab, nEndCol, nEndRow);
976 double fPPTX = pViewData->GetPPTX();
977 double fPPTY = pViewData->GetPPTY();
979 ScTableInfo aTabInfo;
980 pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, nEndCol, nEndRow, nTab, fPPTX, fPPTY, false, false, NULL);
982 ScOutputData aOutputData(&rDevice, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
983 -fTilePosXPixel, -fTilePosYPixel, nStartCol, nStartRow, nEndCol, nEndRow,
984 fPPTX, fPPTY);
986 // setup the SdrPage so that drawinglayer works correctly
987 ScDrawLayer* pModel = pDoc->GetDrawLayer();
988 boost::scoped_ptr<FmFormView> pDrawView;
989 if (pModel)
991 pDrawView.reset(new FmFormView(pModel, &rDevice));
992 pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
993 aOutputData.SetDrawView( pDrawView.get() );
996 // draw the content
997 DrawContent(rDevice, aTabInfo, aOutputData, true, SC_UPDATE_ALL);
1000 void ScGridWindow::LogicInvalidate(const Rectangle* pRectangle)
1002 OString sRectangle;
1003 if (!pRectangle)
1004 sRectangle = "EMPTY";
1005 else
1007 Rectangle aRectangle(*pRectangle);
1008 // When dragging shapes the map mode is disabled.
1009 if (IsMapModeEnabled())
1011 if (GetMapMode().GetMapUnit() == MAP_100TH_MM)
1012 aRectangle = OutputDevice::LogicToLogic(aRectangle, MAP_100TH_MM, MAP_TWIP);
1014 else
1015 aRectangle = PixelToLogic(aRectangle, MapMode(MAP_TWIP));
1016 sRectangle = aRectangle.toString();
1019 pViewData->GetDocument()->GetDrawLayer()->libreOfficeKitCallback(LOK_CALLBACK_INVALIDATE_TILES, sRectangle.getStr());
1022 void ScGridWindow::SetCellSelectionPixel(int nType, int nPixelX, int nPixelY)
1024 ScTabView* pTabView = pViewData->GetView();
1025 ScTabViewShell* pViewShell = pViewData->GetViewShell();
1026 ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewShell);
1028 if (pInputHandler && pInputHandler->IsInputMode())
1030 // we need to switch off the editeng
1031 ScTabView::UpdateInputLine();
1032 pViewShell->UpdateInputHandler();
1035 if (nType == LOK_SETTEXTSELECTION_RESET)
1037 pTabView->DoneBlockMode();
1038 return;
1041 // obtain the current selection
1042 ScRangeList aRangeList = pViewData->GetMarkData().GetMarkedRanges();
1044 SCCOL nCol1, nCol2;
1045 SCROW nRow1, nRow2;
1046 SCTAB nTab1, nTab2;
1048 bool bWasEmpty = false;
1049 if (aRangeList.empty())
1051 nCol1 = nCol2 = pViewData->GetCurX();
1052 nRow1 = nRow2 = pViewData->GetCurY();
1053 bWasEmpty = true;
1055 else
1056 aRangeList.Combine().GetVars(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1058 // convert the coordinates to column/row
1059 SCsCOL nNewPosX;
1060 SCsROW nNewPosY;
1061 SCTAB nTab = pViewData->GetTabNo();
1062 pViewData->GetPosFromPixel(nPixelX, nPixelY, eWhich, nNewPosX, nNewPosY);
1064 // change the selection
1065 switch (nType)
1067 case LOK_SETTEXTSELECTION_START:
1068 if (nNewPosX != nCol1 || nNewPosY != nRow1 || bWasEmpty)
1070 pTabView->SetCursor(nNewPosX, nNewPosY);
1071 pTabView->DoneBlockMode();
1072 pTabView->InitBlockMode(nNewPosX, nNewPosY, nTab, true);
1073 pTabView->MarkCursor(nCol2, nRow2, nTab);
1075 break;
1076 case LOK_SETTEXTSELECTION_END:
1077 if (nNewPosX != nCol2 || nNewPosY != nRow2 || bWasEmpty)
1079 pTabView->SetCursor(nCol1, nRow1);
1080 pTabView->DoneBlockMode();
1081 pTabView->InitBlockMode(nCol1, nRow1, nTab, true);
1082 pTabView->MarkCursor(nNewPosX, nNewPosY, nTab);
1084 break;
1085 default:
1086 assert(false);
1087 break;
1091 void ScGridWindow::CheckNeedsRepaint()
1093 // called at the end of painting, and from timer after background text width calculation
1095 if (bNeedsRepaint)
1097 bNeedsRepaint = false;
1098 if (aRepaintPixel.IsEmpty())
1099 Invalidate();
1100 else
1101 Invalidate(PixelToLogic(aRepaintPixel));
1102 aRepaintPixel = Rectangle();
1104 // selection function in status bar might also be invalid
1105 SfxBindings& rBindings = pViewData->GetBindings();
1106 rBindings.Invalidate( SID_STATUS_SUM );
1107 rBindings.Invalidate( SID_ATTR_SIZE );
1108 rBindings.Invalidate( SID_TABLE_CELL );
1112 void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev )
1114 ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData();
1115 if (pPageData)
1117 ScDocument* pDoc = pViewData->GetDocument();
1118 SCTAB nTab = pViewData->GetTabNo();
1119 Size aWinSize = GetOutputSizePixel();
1120 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
1121 Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
1122 Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor );
1124 OUString aPageStr = ScGlobal::GetRscString( STR_PGNUM );
1125 if ( nPageScript == SvtScriptType::NONE )
1127 // get script type of translated "Page" string only once
1128 nPageScript = pDoc->GetStringScriptType( aPageStr );
1129 if (nPageScript == SvtScriptType::NONE)
1130 nPageScript = ScGlobal::GetDefaultScriptType();
1133 vcl::Font aFont;
1134 std::unique_ptr<ScEditEngineDefaulter> pEditEng;
1135 const ScPatternAttr& rDefPattern = static_cast<const ScPatternAttr&>(pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN));
1136 if ( nPageScript == SvtScriptType::LATIN )
1138 // use single font and call DrawText directly
1139 rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK );
1140 aFont.SetColor( Color( COL_LIGHTGRAY ) );
1141 // font size is set as needed
1143 else
1145 // use EditEngine to draw mixed-script string
1146 pEditEng.reset(new ScEditEngineDefaulter( EditEngine::CreatePool(), true ));
1147 pEditEng->SetRefMapMode( pContentDev->GetMapMode() );
1148 SfxItemSet* pEditDefaults = new SfxItemSet( pEditEng->GetEmptyItemSet() );
1149 rDefPattern.FillEditItemSet( pEditDefaults );
1150 pEditDefaults->Put( SvxColorItem( Color( COL_LIGHTGRAY ), EE_CHAR_COLOR ) );
1151 pEditEng->SetDefaults( pEditDefaults );
1154 sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
1155 for (sal_uInt16 nPos=0; nPos<nCount; nPos++)
1157 ScPrintRangeData& rData = pPageData->GetData(nPos);
1158 ScRange aRange = rData.GetPrintRange();
1159 if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 &&
1160 aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 )
1162 // 3 Pixel Rahmen um den Druckbereich
1163 // (mittlerer Pixel auf den Gitterlinien)
1165 pContentDev->SetLineColor();
1166 if (rData.IsAutomatic())
1167 pContentDev->SetFillColor( aAutomatic );
1168 else
1169 pContentDev->SetFillColor( aManual );
1171 Point aStart = pViewData->GetScrPos(
1172 aRange.aStart.Col(), aRange.aStart.Row(), eWhich, true );
1173 Point aEnd = pViewData->GetScrPos(
1174 aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, true );
1175 aStart.X() -= 2;
1176 aStart.Y() -= 2;
1178 // Ueberlaeufe verhindern:
1179 if ( aStart.X() < -10 ) aStart.X() = -10;
1180 if ( aStart.Y() < -10 ) aStart.Y() = -10;
1181 if ( aEnd.X() > aWinSize.Width() + 10 )
1182 aEnd.X() = aWinSize.Width() + 10;
1183 if ( aEnd.Y() > aWinSize.Height() + 10 )
1184 aEnd.Y() = aWinSize.Height() + 10;
1186 pContentDev->DrawRect( Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) );
1187 pContentDev->DrawRect( Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) );
1188 pContentDev->DrawRect( Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) );
1189 pContentDev->DrawRect( Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) );
1191 // Seitenumbrueche
1192 //! anders darstellen (gestrichelt ????)
1194 size_t nColBreaks = rData.GetPagesX();
1195 const SCCOL* pColEnd = rData.GetPageEndX();
1196 size_t nColPos;
1197 for (nColPos=0; nColPos+1<nColBreaks; nColPos++)
1199 SCCOL nBreak = pColEnd[nColPos]+1;
1200 if ( nBreak >= nX1 && nBreak <= nX2+1 )
1202 //! hidden suchen
1203 if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL)
1204 pContentDev->SetFillColor( aManual );
1205 else
1206 pContentDev->SetFillColor( aAutomatic );
1207 Point aBreak = pViewData->GetScrPos(
1208 nBreak, aRange.aStart.Row(), eWhich, true );
1209 pContentDev->DrawRect( Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) );
1213 size_t nRowBreaks = rData.GetPagesY();
1214 const SCROW* pRowEnd = rData.GetPageEndY();
1215 size_t nRowPos;
1216 for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++)
1218 SCROW nBreak = pRowEnd[nRowPos]+1;
1219 if ( nBreak >= nY1 && nBreak <= nY2+1 )
1221 //! hidden suchen
1222 if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL)
1223 pContentDev->SetFillColor( aManual );
1224 else
1225 pContentDev->SetFillColor( aAutomatic );
1226 Point aBreak = pViewData->GetScrPos(
1227 aRange.aStart.Col(), nBreak, eWhich, true );
1228 pContentDev->DrawRect( Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) );
1232 // Seitenzahlen
1234 SCROW nPrStartY = aRange.aStart.Row();
1235 for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++)
1237 SCROW nPrEndY = pRowEnd[nRowPos];
1238 if ( nPrEndY >= nY1 && nPrStartY <= nY2 )
1240 SCCOL nPrStartX = aRange.aStart.Col();
1241 for (nColPos=0; nColPos<nColBreaks; nColPos++)
1243 SCCOL nPrEndX = pColEnd[nColPos];
1244 if ( nPrEndX >= nX1 && nPrStartX <= nX2 )
1246 Point aPageStart = pViewData->GetScrPos(
1247 nPrStartX, nPrStartY, eWhich, true );
1248 Point aPageEnd = pViewData->GetScrPos(
1249 nPrEndX+1,nPrEndY+1, eWhich, true );
1251 long nPageNo = rData.GetFirstPage();
1252 if ( rData.IsTopDown() )
1253 nPageNo += ((long)nColPos)*nRowBreaks+nRowPos;
1254 else
1255 nPageNo += ((long)nRowPos)*nColBreaks+nColPos;
1257 OUString aThisPageStr = OUString(aPageStr).replaceFirst("%1", OUString::number(nPageNo));
1259 if ( pEditEng )
1261 // find right font size with EditEngine
1262 long nHeight = 100;
1263 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1264 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1265 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1266 pEditEng->SetText( aThisPageStr );
1267 Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1269 // 40% of width or 60% of height
1270 long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1271 long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1272 nHeight = std::min(nSizeX,nSizeY);
1273 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1274 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1275 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1277 // centered output with EditEngine
1278 Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1279 Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1280 (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1281 pEditEng->Draw( pContentDev, aPos );
1283 else
1285 // find right font size for DrawText
1286 aFont.SetSize( Size( 0,100 ) );
1287 pContentDev->SetFont( aFont );
1288 Size aSize100( pContentDev->GetTextWidth( aThisPageStr ), pContentDev->GetTextHeight() );
1290 // 40% of width or 60% of height
1291 long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1292 long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1293 aFont.SetSize( Size( 0,std::min(nSizeX,nSizeY) ) );
1294 pContentDev->SetFont( aFont );
1296 // centered output with DrawText
1297 Size aTextSize( pContentDev->GetTextWidth( aThisPageStr ), pContentDev->GetTextHeight() );
1298 Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1299 (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1300 pContentDev->DrawText( aPos, aThisPageStr );
1303 nPrStartX = nPrEndX + 1;
1306 nPrStartY = nPrEndY + 1;
1313 void ScGridWindow::DrawButtons(SCCOL nX1, SCCOL nX2, const ScTableInfo& rTabInfo, OutputDevice* pContentDev)
1315 aComboButton.SetOutputDevice( pContentDev );
1317 ScDocument* pDoc = pViewData->GetDocument();
1318 ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc);
1320 SCCOL nCol;
1321 SCROW nRow;
1322 SCSIZE nArrY;
1323 SCSIZE nQuery;
1324 SCTAB nTab = pViewData->GetTabNo();
1325 ScDBData* pDBData = NULL;
1326 std::unique_ptr<ScQueryParam> pQueryParam;
1328 RowInfo* pRowInfo = rTabInfo.mpRowInfo;
1329 sal_uInt16 nArrCount = rTabInfo.mnArrCount;
1331 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1333 Point aOldPos = aComboButton.GetPosPixel(); // Zustand fuer MouseDown/Up
1334 Size aOldSize = aComboButton.GetSizePixel(); // merken
1336 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1338 if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged )
1340 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1342 nRow = pThisRowInfo->nRowNo;
1344 for (nCol=nX1; nCol<=nX2; nCol++)
1346 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1347 //if several columns merged on a row, there should be only one auto button at the end of the columns.
1348 //if several rows merged on a column, the button may be in the middle, so "!pInfo->bVOverlapped" should not be used
1349 if ( pInfo->bAutoFilter && !pInfo->bHOverlapped )
1351 if (!pQueryParam)
1352 pQueryParam.reset(new ScQueryParam);
1354 bool bNewData = true;
1355 if (pDBData)
1357 SCCOL nStartCol;
1358 SCROW nStartRow;
1359 SCCOL nEndCol;
1360 SCROW nEndRow;
1361 SCTAB nAreaTab;
1362 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1363 if ( nCol >= nStartCol && nCol <= nEndCol &&
1364 nRow >= nStartRow && nRow <= nEndRow )
1365 bNewData = false;
1367 if (bNewData)
1369 pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1370 if (pDBData)
1371 pDBData->GetQueryParam( *pQueryParam );
1372 else
1374 // can also be part of DataPilot table
1375 // OSL_FAIL("Auto-Filter-Button ohne DBData");
1379 // pQueryParam kann nur MAXQUERY Eintraege enthalten
1381 bool bSimpleQuery = true;
1382 bool bColumnFound = false;
1383 if (!pQueryParam->bInplace)
1384 bSimpleQuery = false;
1385 SCSIZE nCount = pQueryParam->GetEntryCount();
1386 for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery)
1387 if (pQueryParam->GetEntry(nQuery).bDoQuery)
1389 // hier nicht auf EQUAL beschraenken
1390 // (auch bei ">1" soll der Spaltenkopf blau werden)
1392 if (pQueryParam->GetEntry(nQuery).nField == nCol)
1393 bColumnFound = true;
1394 if (nQuery > 0)
1395 if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND)
1396 bSimpleQuery = false;
1399 bool bArrowState = bSimpleQuery && bColumnFound;
1400 long nSizeX;
1401 long nSizeY;
1402 SCCOL nStartCol= nCol;
1403 SCROW nStartRow = nRow;
1404 //if address(nCol,nRow) is not the start pos of the merge area, the value of the nSizeX will be incorrect, it will be the length of the cell.
1405 //should first get the start pos of the merge area, then get the nSizeX through the start pos.
1406 pDoc->ExtendOverlapped(nStartCol, nStartRow,nCol, nRow, nTab);//get nStartCol,nStartRow
1407 pViewData->GetMergeSizePixel( nStartCol, nStartRow, nSizeX, nSizeY );//get nSizeX
1408 nSizeY = ScViewData::ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
1409 Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1411 aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1), bLayoutRTL);
1412 aCellBtn.setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL
1413 aCellBtn.setDrawBaseButton(false);
1414 aCellBtn.setDrawPopupButton(true);
1415 aCellBtn.setHasHiddenMember(bArrowState);
1416 aCellBtn.draw();
1421 if ( pRowInfo[nArrY].bPivotButton && pRowInfo[nArrY].bChanged )
1423 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1424 nRow = pThisRowInfo->nRowNo;
1425 for (nCol=nX1; nCol<=nX2; nCol++)
1427 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1428 if (pInfo->bHOverlapped || pInfo->bVOverlapped)
1429 continue;
1431 Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1432 long nSizeX;
1433 long nSizeY;
1434 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1435 long nPosX = aScrPos.X();
1436 long nPosY = aScrPos.Y();
1437 // bLayoutRTL is handled in setBoundingBox
1439 OUString aStr = pDoc->GetString(nCol, nRow, nTab);
1440 aCellBtn.setText(aStr);
1441 aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1), bLayoutRTL);
1442 aCellBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now
1443 aCellBtn.setDrawBaseButton(pInfo->bPivotButton);
1444 aCellBtn.setDrawPopupButton(pInfo->bPivotPopupButton);
1445 aCellBtn.setHasHiddenMember(pInfo->bFilterActive);
1446 aCellBtn.draw();
1450 if ( bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged )
1452 Rectangle aRect = GetListValButtonRect( aListValPos );
1453 aComboButton.SetPosPixel( aRect.TopLeft() );
1454 aComboButton.SetSizePixel( aRect.GetSize() );
1455 pContentDev->SetClipRegion(vcl::Region(aRect));
1456 aComboButton.Draw( false, false );
1457 pContentDev->SetClipRegion(); // always called from Draw() without clip region
1458 aComboButton.SetPosPixel( aOldPos ); // restore old state
1459 aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter)
1463 pQueryParam.reset();
1464 aComboButton.SetOutputDevice( this );
1467 Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos )
1469 ScDocument* pDoc = pViewData->GetDocument();
1470 SCTAB nTab = pViewData->GetTabNo();
1471 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1472 long nLayoutSign = bLayoutRTL ? -1 : 1;
1474 ScDDComboBoxButton aButton( this ); // for optimal size
1475 Size aBtnSize = aButton.GetSizePixel();
1477 SCCOL nCol = rButtonPos.Col();
1478 SCROW nRow = rButtonPos.Row();
1480 long nCellSizeX; // width of this cell, including merged
1481 long nDummy;
1482 pViewData->GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy );
1484 // for height, only the cell's row is used, excluding merged cells
1485 long nCellSizeY = ScViewData::ToPixel( pDoc->GetRowHeight( nRow, nTab ), pViewData->GetPPTY() );
1486 long nAvailable = nCellSizeX;
1488 // left edge of next cell if there is a non-hidden next column
1489 SCCOL nNextCol = nCol + 1;
1490 const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE ));
1491 if ( pMerge->GetColMerge() > 1 )
1492 nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area
1493 while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) )
1494 ++nNextCol;
1495 bool bNextCell = ( nNextCol <= MAXCOL );
1496 if ( bNextCell )
1497 nAvailable = ScViewData::ToPixel( pDoc->GetColWidth( nNextCol, nTab ), pViewData->GetPPTX() );
1499 if ( nAvailable < aBtnSize.Width() )
1500 aBtnSize.Width() = nAvailable;
1501 if ( nCellSizeY < aBtnSize.Height() )
1502 aBtnSize.Height() = nCellSizeY;
1504 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich, true );
1505 aPos.X() += nCellSizeX * nLayoutSign; // start of next cell
1506 if (!bNextCell)
1507 aPos.X() -= aBtnSize.Width() * nLayoutSign; // right edge of cell if next cell not available
1508 aPos.Y() += nCellSizeY - aBtnSize.Height();
1509 // X remains at the left edge
1511 if ( bLayoutRTL )
1512 aPos.X() -= aBtnSize.Width()-1; // align right edge of button with cell border
1514 return Rectangle( aPos, aBtnSize );
1517 bool ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab )
1519 ScDocument* pDoc = pViewData->GetDocument();
1520 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1521 ScQueryParam aQueryParam;
1523 if ( pDBData )
1524 pDBData->GetQueryParam( aQueryParam );
1525 else
1527 OSL_FAIL("Auto-Filter-Button ohne DBData");
1530 bool bSimpleQuery = true;
1531 bool bColumnFound = false;
1532 SCSIZE nQuery;
1534 if ( !aQueryParam.bInplace )
1535 bSimpleQuery = false;
1537 // aQueryParam kann nur MAXQUERY Eintraege enthalten
1539 SCSIZE nCount = aQueryParam.GetEntryCount();
1540 for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery)
1541 if ( aQueryParam.GetEntry(nQuery).bDoQuery )
1543 if (aQueryParam.GetEntry(nQuery).nField == nCol)
1544 bColumnFound = true;
1546 if (nQuery > 0)
1547 if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND)
1548 bSimpleQuery = false;
1551 return ( bSimpleQuery && bColumnFound );
1554 void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects )
1556 ScMarkData aMultiMark( pViewData->GetMarkData() );
1557 aMultiMark.SetMarking( false );
1558 aMultiMark.MarkToMulti();
1559 ScDocument* pDoc = pViewData->GetDocument();
1560 SCTAB nTab = pViewData->GetTabNo();
1562 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1563 long nLayoutSign = bLayoutRTL ? -1 : 1;
1564 if ( !aMultiMark.IsMultiMarked() )
1565 return;
1566 ScRange aMultiRange;
1567 aMultiMark.GetMultiMarkArea( aMultiRange );
1568 SCCOL nX1 = aMultiRange.aStart.Col();
1569 SCROW nY1 = aMultiRange.aStart.Row();
1570 SCCOL nX2 = aMultiRange.aEnd.Col();
1571 SCROW nY2 = aMultiRange.aEnd.Row();
1573 PutInOrder( nX1, nX2 );
1574 PutInOrder( nY1, nY2 );
1576 bool bTestMerge = true;
1577 bool bRepeat = true;
1579 SCCOL nTestX2 = nX2;
1580 SCROW nTestY2 = nY2;
1581 if (bTestMerge)
1582 pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab );
1584 SCCOL nPosX = pViewData->GetPosX( eHWhich );
1585 SCROW nPosY = pViewData->GetPosY( eVWhich );
1586 // is the selection visible at all?
1587 if (nTestX2 < nPosX || nTestY2 < nPosY)
1588 return;
1589 SCCOL nRealX1 = nX1;
1590 if (nX1 < nPosX)
1591 nX1 = nPosX;
1592 if (nY1 < nPosY)
1593 nY1 = nPosY;
1595 if (!pDoc->GetDrawLayer()->isTiledRendering())
1597 // limit the selection to only what is visible on the screen
1598 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
1599 if (nXRight > MAXCOL)
1600 nXRight = MAXCOL;
1602 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
1603 if (nYBottom > MAXROW)
1604 nYBottom = MAXROW;
1606 // is the selection visible at all?
1607 if (nX1 > nXRight || nY1 > nYBottom)
1608 return;
1610 if (nX2 > nXRight)
1611 nX2 = nXRight;
1612 if (nY2 > nYBottom)
1613 nY2 = nYBottom;
1616 double nPPTX = pViewData->GetPPTX();
1617 double nPPTY = pViewData->GetPPTY();
1619 ScInvertMerger aInvert( &rPixelRects );
1621 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
1622 long nScrY = aScrPos.Y();
1623 bool bWasHidden = false;
1624 for (SCROW nY=nY1; nY<=nY2; nY++)
1626 bool bFirstRow = ( nY == nPosY ); // first visible row?
1627 bool bDoHidden = false; // versteckte nachholen ?
1628 sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab );
1629 bool bDoRow = ( nHeightTwips != 0 );
1630 if (bDoRow)
1632 if (bTestMerge)
1633 if (bWasHidden) // auf versteckte zusammengefasste testen
1635 bDoHidden = true;
1636 bDoRow = true;
1639 bWasHidden = false;
1641 else
1643 bWasHidden = true;
1644 if (bTestMerge)
1645 if (nY==nY2)
1646 bDoRow = true; // letzte Zeile aus Block
1649 if ( bDoRow )
1651 SCCOL nLoopEndX = nX2;
1652 if (nX2 < nX1) // Rest von zusammengefasst
1654 SCCOL nStartX = nX1;
1655 while ( static_cast<const ScMergeFlagAttr*>(pDoc->
1656 GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() )
1657 --nStartX;
1658 if (nStartX <= nX2)
1659 nLoopEndX = nX1;
1662 long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1;
1663 long nScrX = aScrPos.X();
1664 for (SCCOL nX=nX1; nX<=nLoopEndX; nX++)
1666 long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX );
1667 if ( nWidth > 0 )
1669 long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign;
1670 if (bTestMerge)
1672 SCROW nThisY = nY;
1673 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1674 const ScMergeFlagAttr* pMergeFlag = static_cast<const ScMergeFlagAttr*>( &pPattern->
1675 GetItem(ATTR_MERGE_FLAG) );
1676 if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) )
1678 while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 &&
1679 (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) )
1681 --nThisY;
1682 pPattern = pDoc->GetPattern( nX, nThisY, nTab );
1683 pMergeFlag = static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem(ATTR_MERGE_FLAG) );
1687 // nur Rest von zusammengefasster zu sehen ?
1688 SCCOL nThisX = nX;
1689 if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 )
1691 while ( pMergeFlag->IsHorOverlapped() )
1693 --nThisX;
1694 pPattern = pDoc->GetPattern( nThisX, nThisY, nTab );
1695 pMergeFlag = static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem(ATTR_MERGE_FLAG) );
1699 if ( aMultiMark.IsCellMarked( nThisX, nThisY, true ) == bRepeat )
1701 if ( !pMergeFlag->IsOverlapped() )
1703 const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(&pPattern->GetItem(ATTR_MERGE));
1704 if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0)
1706 Point aEndPos = pViewData->GetScrPos(
1707 nThisX + pMerge->GetColMerge(),
1708 nThisY + pMerge->GetRowMerge(), eWhich );
1709 if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY )
1711 aInvert.AddRect( Rectangle( nScrX,nScrY,
1712 aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) );
1715 else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1717 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1722 else // !bTestMerge
1724 if ( aMultiMark.IsCellMarked( nX, nY, true ) == bRepeat &&
1725 nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1727 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1731 nScrX = nEndX + nLayoutSign;
1734 nScrY = nEndY + 1;
1739 void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt )
1741 Window::DataChanged(rDCEvt);
1743 if ( (rDCEvt.GetType() == DataChangedEventType::PRINTER) ||
1744 (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
1745 (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1746 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1747 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1748 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1750 if ( rDCEvt.GetType() == DataChangedEventType::FONTS && eWhich == pViewData->GetActivePart() )
1751 pViewData->GetDocShell()->UpdateFontList();
1753 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1754 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1756 if ( eWhich == pViewData->GetActivePart() ) // only once for the view
1758 ScTabView* pView = pViewData->GetView();
1760 // update scale in case the UI ScreenZoom has changed
1761 ScGlobal::UpdatePPT(this);
1762 pView->RecalcPPT();
1764 // RepeatResize in case scroll bar sizes have changed
1765 pView->RepeatResize();
1766 pView->UpdateAllOverlays();
1768 // invalidate cell attribs in input handler, in case the
1769 // EditEngine BackgroundColor has to be changed
1770 if ( pViewData->IsActive() )
1772 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1773 if (pHdl)
1774 pHdl->ForgetLastPattern();
1779 Invalidate();
1783 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */