bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / view / gridwin4.cxx
blobb5c76fdf4b1759b226201eef99c3a3452517ff95
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>
31 #include <svx/svdview.hxx>
32 #include "tabvwsh.hxx"
34 #include "gridwin.hxx"
35 #include "viewdata.hxx"
36 #include "output.hxx"
37 #include "document.hxx"
38 #include "attrib.hxx"
39 #include "patattr.hxx" // InvertSimple
40 #include "dbdata.hxx"
41 #include "docoptio.hxx"
42 #include "notemark.hxx"
43 #include "dbfunc.hxx" // oder GetPageBreakData an die ViewData
44 #include "scmod.hxx"
45 #include "inputhdl.hxx"
46 #include "rfindlst.hxx"
47 #include "hiranges.hxx"
48 #include "pagedata.hxx"
49 #include "docpool.hxx"
50 #include "globstr.hrc"
51 #include "docsh.hxx" // oder GetSfxInPlaceObject
52 #include "cbutton.hxx"
53 #include "invmerge.hxx"
54 #include "editutil.hxx"
55 #include "inputopt.hxx"
56 #include "fillinfo.hxx"
57 #include "dpcontrol.hxx"
58 #include "queryparam.hxx"
59 #include "queryentry.hxx"
60 #include "markdata.hxx"
61 #include "sc.hrc"
62 #include <vcl/virdev.hxx>
64 // #i74769#
65 #include <svx/sdrpaintwindow.hxx>
67 //------------------------------------------------------------------------
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( OutputDevice* pDev, const Rectangle& rInnerPixel,
80 const String& rTitle, const Color& rColor, sal_Bool bTextBelow,
81 double nPPTX, double nPPTY, const Fraction& rZoomY,
82 ScDocument* pDoc, ScViewData* pButtonViewData, sal_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 Font aAttrFont;
107 ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).
108 GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY);
110 // everything else from application font
111 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((Window*)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 sal_Bool bWasClip = false;
148 Region aOldClip;
149 sal_Bool bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() );
150 if ( bClip )
152 if (pDev->IsClipRegion())
154 bWasClip = sal_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( 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 sal_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, sal_True );
219 Point aEndPos = pViewData->GetScrPos(
220 aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, sal_True );
221 // on the grid:
222 aStartPos.X() -= nLayoutSign;
223 aStartPos.Y() -= 1;
224 aEndPos.X() -= nLayoutSign;
225 aEndPos.Y() -= 1;
227 sal_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 //------------------------------------------------------------------------
256 static void lcl_DrawHighlight( ScOutputData& rOutputData, ScViewData* pViewData,
257 const std::vector<ScHighlightEntry>& rHighlightRanges )
259 SCTAB nTab = pViewData->GetTabNo();
260 std::vector<ScHighlightEntry>::const_iterator pIter;
261 for ( pIter = rHighlightRanges.begin(); pIter != rHighlightRanges.end(); ++pIter)
263 ScRange aRange = pIter->aRef;
264 if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() )
266 rOutputData.DrawRefMark(
267 aRange.aStart.Col(), aRange.aStart.Row(),
268 aRange.aEnd.Col(), aRange.aEnd.Row(),
269 pIter->aColor, false );
274 //------------------------------------------------------------------------
276 void ScGridWindow::DoInvertRect( const Rectangle& rPixel )
278 if ( rPixel == aInvertRect )
279 aInvertRect = Rectangle(); // aufheben
280 else
282 OSL_ENSURE( aInvertRect.IsEmpty(), "DoInvertRect nicht paarig" );
284 aInvertRect = rPixel; // neues Rechteck merken
287 UpdateHeaderOverlay(); // uses aInvertRect
290 //------------------------------------------------------------------------
292 void ScGridWindow::PrePaint()
294 // forward PrePaint to DrawingLayer
295 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
297 if(pTabViewShell)
299 SdrView* pDrawView = pTabViewShell->GetSdrView();
301 if(pDrawView)
303 pDrawView->PrePaint();
308 //------------------------------------------------------------------------
310 void ScGridWindow::Paint( const Rectangle& rRect )
312 ScDocument* pDoc = pViewData->GetDocument();
313 if ( pDoc->IsInInterpreter() )
315 // via Reschedule, interpretierende Zellen nicht nochmal anstossen
316 // hier kein Invalidate, sonst kommt z.B. eine Error-Box nie an die Reihe
317 // (Bug 36381). Durch bNeedsRepaint wird spaeter alles nochmal gemalt.
319 if ( bNeedsRepaint )
321 //! Rechtecke zusammenfassen?
322 aRepaintPixel = Rectangle(); // mehrfach -> alles painten
324 else
326 bNeedsRepaint = true;
327 aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich
329 return;
332 // #i117893# If GetSizePixel needs to call the resize handler, the resulting nested Paint call
333 // (possibly for a larger rectangle) has to be allowed. Call GetSizePixel before setting bIsInPaint.
334 GetSizePixel();
336 if (bIsInPaint)
337 return;
339 bIsInPaint = true;
341 Rectangle aPixRect = LogicToPixel( rRect );
343 SCCOL nX1 = pViewData->GetPosX(eHWhich);
344 SCROW nY1 = pViewData->GetPosY(eVWhich);
346 SCTAB nTab = pViewData->GetTabNo();
348 double nPPTX = pViewData->GetPPTX();
349 double nPPTY = pViewData->GetPPTY();
351 Rectangle aMirroredPixel = aPixRect;
352 if ( pDoc->IsLayoutRTL( nTab ) )
354 // mirror and swap
355 long nWidth = GetSizePixel().Width();
356 aMirroredPixel.Left() = nWidth - 1 - aPixRect.Right();
357 aMirroredPixel.Right() = nWidth - 1 - aPixRect.Left();
360 long nScrX = ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
361 while ( nScrX <= aMirroredPixel.Left() && nX1 < MAXCOL )
363 ++nX1;
364 nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
366 SCCOL nX2 = nX1;
367 while ( nScrX <= aMirroredPixel.Right() && nX2 < MAXCOL )
369 ++nX2;
370 nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX );
373 long nScrY = 0;
374 ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, MAXROW, nPPTY, pDoc, nTab);
375 SCROW nY2 = nY1;
376 if (nScrY <= aPixRect.Bottom() && nY2 < MAXROW)
378 ++nY2;
379 ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, MAXROW, nPPTY, pDoc, nTab);
382 Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // nicht weiterzeichnen
384 bIsInPaint = false;
388 // Draw ----------------------------------------------------------------
391 void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode )
393 ScModule* pScMod = SC_MOD();
394 sal_Bool bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg();
396 if (pViewData->IsMinimized())
397 return;
399 PutInOrder( nX1, nX2 );
400 PutInOrder( nY1, nY2 );
402 OSL_ENSURE( ValidCol(nX2) && ValidRow(nY2), "GridWin Draw Bereich zu gross" );
404 UpdateVisibleRange();
406 if (nX2 < maVisibleRange.mnCol1 || nY2 < maVisibleRange.mnRow1)
407 return;
408 // unsichtbar
409 if (nX1 < maVisibleRange.mnCol1)
410 nX1 = maVisibleRange.mnCol1;
411 if (nY1 < maVisibleRange.mnRow1)
412 nY1 = maVisibleRange.mnRow1;
414 if (nX1 > maVisibleRange.mnCol2 || nY1 > maVisibleRange.mnRow2)
415 return;
417 if (nX2 > maVisibleRange.mnCol2)
418 nX2 = maVisibleRange.mnCol2;
419 if (nY2 > maVisibleRange.mnRow2)
420 nY2 = maVisibleRange.mnRow2;
422 if ( eMode != SC_UPDATE_MARKS && nX2 < maVisibleRange.mnCol2)
423 nX2 = maVisibleRange.mnCol2; // zum Weiterzeichnen
425 // ab hier kein return mehr
427 ++nPaintCount; // merken, dass gemalt wird (wichtig beim Invertieren)
429 ScDocShell* pDocSh = pViewData->GetDocShell();
430 ScDocument* pDoc = pDocSh->GetDocument();
431 SCTAB nTab = pViewData->GetTabNo();
433 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
435 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
436 long nMirrorWidth = GetSizePixel().Width();
437 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
438 long nLayoutSign = bLayoutRTL ? -1 : 1;
439 if ( bLayoutRTL )
441 long nEndPixel = pViewData->GetScrPos( nX2+1, maVisibleRange.mnRow1, eWhich ).X();
442 nMirrorWidth = aScrPos.X() - nEndPixel;
443 aScrPos.X() = nEndPixel + 1;
446 long nScrX = aScrPos.X();
447 long nScrY = aScrPos.Y();
449 SCCOL nCurX = pViewData->GetCurX();
450 SCROW nCurY = pViewData->GetCurY();
451 SCCOL nCurEndX = nCurX;
452 SCROW nCurEndY = nCurY;
453 pDoc->ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab );
454 sal_Bool bCurVis = nCursorHideCount==0 &&
455 ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 );
457 // AutoFill-Anfasser
458 if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab &&
459 ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) )
461 SCCOL nHdlX = aAutoMarkPos.Col();
462 SCROW nHdlY = aAutoMarkPos.Row();
463 pDoc->ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab );
464 bCurVis = ( nHdlX+1 >= nX1 && nHdlX <= nX2 && nHdlY+1 >= nY1 && nHdlY <= nY2 );
465 // links und oben ist nicht betroffen
467 //! AutoFill-Anfasser alleine (ohne Cursor) zeichnen ???
470 double nPPTX = pViewData->GetPPTX();
471 double nPPTY = pViewData->GetPPTY();
473 const ScViewOptions& rOpts = pViewData->GetOptions();
474 sal_Bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS );
475 sal_Bool bMarkClipped = rOpts.GetOption( VOPT_CLIPMARKS );
477 // Datenblock
479 ScTableInfo aTabInfo;
480 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
481 nPPTX, nPPTY, false, bFormulaMode,
482 &pViewData->GetMarkData() );
484 //--------------------------------------------------------------------
486 Fraction aZoomX = pViewData->GetZoomX();
487 Fraction aZoomY = pViewData->GetZoomY();
488 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
489 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
490 &aZoomX, &aZoomY );
492 aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL
494 std::auto_ptr< VirtualDevice > xFmtVirtDev;
495 sal_Bool bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode?
497 if ( bTextWysiwyg )
499 // use printer for text formatting
501 OutputDevice* pFmtDev = pDoc->GetPrinter();
502 pFmtDev->SetMapMode( pViewData->GetLogicMode(eWhich) );
503 aOutputData.SetFmtDevice( pFmtDev );
505 else if ( aZoomX != aZoomY && pViewData->IsOle() )
507 // #i45033# For OLE inplace editing with different zoom factors,
508 // use a virtual device with 1/100th mm as text formatting reference
510 xFmtVirtDev.reset( new VirtualDevice );
511 xFmtVirtDev->SetMapMode( MAP_100TH_MM );
512 aOutputData.SetFmtDevice( xFmtVirtDev.get() );
514 bLogicText = sal_True; // use logic MapMode
517 const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig();
518 Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, false ).nColor );
519 if ( aGridColor.GetColor() == COL_TRANSPARENT )
521 // use view options' grid color only if color config has "automatic" color
522 aGridColor = rOpts.GetGridColor();
525 aOutputData.SetSyntaxMode ( pViewData->IsSyntaxMode() );
526 aOutputData.SetGridColor ( aGridColor );
527 aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) );
528 aOutputData.SetShowFormulas ( bFormulaMode );
529 aOutputData.SetShowSpellErrors ( pDoc->GetDocOptions().IsAutoSpell() );
530 aOutputData.SetMarkClipped ( bMarkClipped );
532 aOutputData.SetUseStyleColor( true ); // always set in table view
534 aOutputData.SetEditObject( GetEditObject() );
535 aOutputData.SetViewShell( pViewData->GetViewShell() );
537 sal_Bool bGrid = rOpts.GetOption( VOPT_GRID ) && pViewData->GetShowGrid();
538 sal_Bool bGridFirst = !rOpts.GetOption( VOPT_GRID_ONTOP );
540 sal_Bool bPage = rOpts.GetOption( VOPT_PAGEBREAKS );
542 if ( eMode == SC_UPDATE_CHANGED )
544 aOutputData.FindChanged();
545 aOutputData.SetSingleGrid(sal_True);
548 sal_Bool bPageMode = pViewData->IsPagebreakMode();
549 if (bPageMode) // nach FindChanged
551 // SetPagebreakMode initialisiert auch bPrinted Flags
552 aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() );
555 EditView* pEditView = NULL;
556 sal_Bool bEditMode = pViewData->HasEditView(eWhich);
557 if ( bEditMode && pViewData->GetRefTabNo() == nTab )
559 SCCOL nEditCol;
560 SCROW nEditRow;
561 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
562 SCCOL nEditEndCol = pViewData->GetEditEndCol();
563 SCROW nEditEndRow = pViewData->GetEditEndRow();
565 if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 )
566 aOutputData.SetEditCell( nEditCol, nEditRow );
567 else
568 bEditMode = false;
571 // define drawing layer map mode and paint rectangle
572 const MapMode aDrawMode = GetDrawMapMode();
573 Rectangle aDrawingRectLogic;
576 // get drawing pixel rect
577 Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
579 // correct for border (left/right)
580 if(MAXCOL == nX2)
582 if(bLayoutRTL)
584 aDrawingRectPixel.Left() = 0L;
586 else
588 aDrawingRectPixel.Right() = GetOutputSizePixel().getWidth();
592 // correct for border (bottom)
593 if(MAXROW == nY2)
595 aDrawingRectPixel.Bottom() = GetOutputSizePixel().getHeight();
598 // get logic positions
599 aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode);
602 OutputDevice* pContentDev = this; // device for document content, used by overlay manager
603 SdrPaintWindow* pTargetPaintWindow = 0; // #i74769# work with SdrPaintWindow directly
606 // init redraw
607 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
609 if(pTabViewShell)
611 MapMode aCurrentMapMode(pContentDev->GetMapMode());
612 pContentDev->SetMapMode(aDrawMode);
613 SdrView* pDrawView = pTabViewShell->GetSdrView();
615 if(pDrawView)
617 // #i74769# Use new BeginDrawLayers() interface
618 Region aDrawingRegion(aDrawingRectLogic);
619 pTargetPaintWindow = pDrawView->BeginDrawLayers(this, aDrawingRegion);
620 OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)");
622 // #i74769# get target device from SdrPaintWindow, this may be the prerender
623 // device now, too.
624 pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice());
625 aOutputData.SetContentDevice( pContentDev );
628 pContentDev->SetMapMode(aCurrentMapMode);
632 // Rand (Wiese) (Pixel)
633 if ( nX2==MAXCOL || nY2==MAXROW )
635 // save MapMode and set to pixel
636 MapMode aCurrentMapMode(pContentDev->GetMapMode());
637 pContentDev->SetMapMode(MAP_PIXEL);
639 Rectangle aPixRect = Rectangle( Point(), GetOutputSizePixel() );
640 pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor );
641 pContentDev->SetLineColor();
642 if ( nX2==MAXCOL )
644 Rectangle aDrawRect( aPixRect );
645 if ( bLayoutRTL )
646 aDrawRect.Right() = nScrX - 1;
647 else
648 aDrawRect.Left() = nScrX + aOutputData.GetScrW();
649 if (aDrawRect.Right() >= aDrawRect.Left())
650 pContentDev->DrawRect( aDrawRect );
652 if ( nY2==MAXROW )
654 Rectangle aDrawRect( aPixRect );
655 aDrawRect.Top() = nScrY + aOutputData.GetScrH();
656 if ( nX2==MAXCOL )
658 // no double painting of the corner
659 if ( bLayoutRTL )
660 aDrawRect.Left() = nScrX;
661 else
662 aDrawRect.Right() = nScrX + aOutputData.GetScrW() - 1;
664 if (aDrawRect.Bottom() >= aDrawRect.Top())
665 pContentDev->DrawRect( aDrawRect );
668 // restore MapMode
669 pContentDev->SetMapMode(aCurrentMapMode);
672 if ( pDoc->HasBackgroundDraw( nTab, aDrawingRectLogic ) )
674 pContentDev->SetMapMode(MAP_PIXEL);
675 aOutputData.DrawClear();
677 // Drawing Hintergrund
679 pContentDev->SetMapMode(aDrawMode);
680 DrawRedraw( aOutputData, eMode, SC_LAYER_BACK );
682 else
683 aOutputData.SetSolidBackground(sal_True);
685 pContentDev->SetMapMode(MAP_PIXEL);
686 aOutputData.DrawDocumentBackground();
688 if ( bGridFirst && ( bGrid || bPage ) )
689 aOutputData.DrawGrid( bGrid, bPage );
691 aOutputData.DrawBackground();
693 if ( !bGridFirst && ( bGrid || bPage ) )
694 aOutputData.DrawGrid( bGrid, bPage );
696 if ( bPageMode )
698 // DrawPagePreview draws complete lines/page numbers, must always be clipped
699 if ( aOutputData.SetChangedClip() )
701 DrawPagePreview(nX1,nY1,nX2,nY2, pContentDev);
702 pContentDev->SetClipRegion();
706 aOutputData.DrawShadow();
707 aOutputData.DrawFrame();
708 if ( !bLogicText )
709 aOutputData.DrawStrings(false); // in pixel MapMode
711 // edit cells and printer-metrics text must be before the buttons
712 // (DataPilot buttons contain labels in UI font)
714 pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich));
715 if ( bLogicText )
716 aOutputData.DrawStrings(sal_True); // in logic MapMode if bTextWysiwyg is set
717 aOutputData.DrawEdit(sal_True);
718 pContentDev->SetMapMode(MAP_PIXEL);
720 // Autofilter- und Pivot-Buttons
722 DrawButtons( nX1, nX2, aTabInfo, pContentDev ); // Pixel
724 // Notiz-Anzeiger
726 if ( rOpts.GetOption( VOPT_NOTES ) )
727 aOutputData.DrawNoteMarks();
729 aOutputData.DrawClipMarks();
731 // Szenario / ChangeTracking muss auf jeden Fall nach DrawGrid sein, auch bei !bGridFirst
733 //! Test, ob ChangeTrack-Anzeige aktiv ist
734 //! Szenario-Rahmen per View-Optionen abschaltbar?
736 SCTAB nTabCount = pDoc->GetTableCount();
737 const std::vector<ScHighlightEntry> &rHigh = pViewData->GetView()->GetHighlightRanges();
738 sal_Bool bHasScenario = ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) );
739 sal_Bool bHasChange = ( pDoc->GetChangeTrack() != NULL );
741 if ( bHasChange || bHasScenario || !rHigh.empty() )
744 //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!)
746 sal_Bool bAny = sal_True;
747 if (eMode == SC_UPDATE_CHANGED)
748 bAny = aOutputData.SetChangedClip();
749 if (bAny)
751 if ( bHasChange )
752 aOutputData.DrawChangeTrack();
754 if ( bHasScenario )
755 lcl_DrawScenarioFrames( pContentDev, pViewData, eWhich, nX1,nY1,nX2,nY2 );
757 lcl_DrawHighlight( aOutputData, pViewData, rHigh );
759 if (eMode == SC_UPDATE_CHANGED)
760 pContentDev->SetClipRegion();
764 // Drawing Vordergrund
766 pContentDev->SetMapMode(aDrawMode);
768 DrawRedraw( aOutputData, eMode, SC_LAYER_FRONT );
769 DrawRedraw( aOutputData, eMode, SC_LAYER_INTERN );
770 DrawSdrGrid( aDrawingRectLogic, pContentDev );
772 if (!bIsInScroll) // Drawing Markierungen
774 if(eMode == SC_UPDATE_CHANGED && aOutputData.SetChangedClip())
776 pContentDev->SetClipRegion();
780 pContentDev->SetMapMode(MAP_PIXEL);
782 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() )
784 Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor );
785 aOutputData.DrawRefMark( pViewData->GetRefStartX(), pViewData->GetRefStartY(),
786 pViewData->GetRefEndX(), pViewData->GetRefEndY(),
787 aRefColor, false );
790 // Range-Finder
792 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
793 if (pHdl)
795 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
796 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
797 pRangeFinder->GetDocName() == pDocSh->GetTitle() )
799 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
800 for (sal_uInt16 i=0; i<nCount; i++)
802 ScRangeFindData* pData = pRangeFinder->GetObject(i);
804 ScRange aRef = pData->aRef;
805 aRef.Justify();
806 if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab )
807 aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(),
808 aRef.aEnd.Col(), aRef.aEnd.Row(),
809 Color( ScRangeFindList::GetColorName( i ) ),
810 sal_True );
816 // end redraw
817 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
819 if(pTabViewShell)
821 MapMode aCurrentMapMode(pContentDev->GetMapMode());
822 pContentDev->SetMapMode(aDrawMode);
823 SdrView* pDrawView = pTabViewShell->GetSdrView();
825 if(pDrawView)
827 // #i74769# work with SdrPaintWindow directly
828 pDrawView->EndDrawLayers(*pTargetPaintWindow, true);
831 pContentDev->SetMapMode(aCurrentMapMode);
835 // InPlace Edit-View
836 // moved after EndDrawLayers() to get it outside the overlay buffer and
837 // on top of everything
838 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
840 //! use pContentDev for EditView?
841 SetMapMode(MAP_PIXEL);
842 SCCOL nCol1 = pViewData->GetEditStartCol();
843 SCROW nRow1 = pViewData->GetEditStartRow();
844 SCCOL nCol2 = pViewData->GetEditEndCol();
845 SCROW nRow2 = pViewData->GetEditEndRow();
846 SetLineColor();
847 SetFillColor( pEditView->GetBackgroundColor() );
848 Point aStart = pViewData->GetScrPos( nCol1, nRow1, eWhich );
849 Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eWhich );
850 aEnd.X() -= 2 * nLayoutSign; // don't overwrite grid
851 aEnd.Y() -= 2;
852 DrawRect( Rectangle( aStart,aEnd ) );
854 SetMapMode(pViewData->GetLogicMode());
855 pEditView->Paint( PixelToLogic( Rectangle( Point( nScrX, nScrY ),
856 Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) ) );
857 SetMapMode(MAP_PIXEL);
860 if (pViewData->HasEditView(eWhich))
862 // flush OverlayManager before changing the MapMode
863 flushOverlayManager();
865 // set MapMode for text edit
866 SetMapMode(pViewData->GetLogicMode());
868 else
869 SetMapMode(aDrawMode);
871 if ( pNoteMarker )
872 pNoteMarker->Draw(); // ueber den Cursor, im Drawing-MapMode
875 // Wenn waehrend des Paint etwas invertiert wurde (Selektion geaendert aus Basic-Macro),
876 // ist das jetzt durcheinandergekommen und es muss neu gemalt werden
879 OSL_ENSURE(nPaintCount, "nPaintCount falsch");
880 --nPaintCount;
881 if (!nPaintCount)
882 CheckNeedsRepaint();
884 // Flag drawn formula cells "unchanged".
885 pDoc->ResetChanged(ScRange(nX1,nY1,nTab,nX2,nY2,nTab));
888 void ScGridWindow::CheckNeedsRepaint()
890 // called at the end of painting, and from timer after background text width calculation
892 if (bNeedsRepaint)
894 bNeedsRepaint = false;
895 if (aRepaintPixel.IsEmpty())
896 Invalidate();
897 else
898 Invalidate(PixelToLogic(aRepaintPixel));
899 aRepaintPixel = Rectangle();
901 // selection function in status bar might also be invalid
902 SfxBindings& rBindings = pViewData->GetBindings();
903 rBindings.Invalidate( SID_STATUS_SUM );
904 rBindings.Invalidate( SID_ATTR_SIZE );
905 rBindings.Invalidate( SID_TABLE_CELL );
909 void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev )
911 ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData();
912 if (pPageData)
914 ScDocument* pDoc = pViewData->GetDocument();
915 SCTAB nTab = pViewData->GetTabNo();
916 Size aWinSize = GetOutputSizePixel();
917 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
918 Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
919 Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor );
921 String aPageStr = ScGlobal::GetRscString( STR_PGNUM );
922 if ( nPageScript == 0 )
924 // get script type of translated "Page" string only once
925 nPageScript = pDoc->GetStringScriptType( aPageStr );
926 if (nPageScript == 0)
927 nPageScript = ScGlobal::GetDefaultScriptType();
930 Font aFont;
931 ScEditEngineDefaulter* pEditEng = NULL;
932 const ScPatternAttr& rDefPattern = ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN));
933 if ( nPageScript == SCRIPTTYPE_LATIN )
935 // use single font and call DrawText directly
936 rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK );
937 aFont.SetColor( Color( COL_LIGHTGRAY ) );
938 // font size is set as needed
940 else
942 // use EditEngine to draw mixed-script string
943 pEditEng = new ScEditEngineDefaulter( EditEngine::CreatePool(), sal_True );
944 pEditEng->SetRefMapMode( pContentDev->GetMapMode() );
945 SfxItemSet* pEditDefaults = new SfxItemSet( pEditEng->GetEmptyItemSet() );
946 rDefPattern.FillEditItemSet( pEditDefaults );
947 pEditDefaults->Put( SvxColorItem( Color( COL_LIGHTGRAY ), EE_CHAR_COLOR ) );
948 pEditEng->SetDefaults( pEditDefaults );
951 sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
952 for (sal_uInt16 nPos=0; nPos<nCount; nPos++)
954 ScPrintRangeData& rData = pPageData->GetData(nPos);
955 ScRange aRange = rData.GetPrintRange();
956 if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 &&
957 aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 )
959 // 3 Pixel Rahmen um den Druckbereich
960 // (mittlerer Pixel auf den Gitterlinien)
962 pContentDev->SetLineColor();
963 if (rData.IsAutomatic())
964 pContentDev->SetFillColor( aAutomatic );
965 else
966 pContentDev->SetFillColor( aManual );
968 Point aStart = pViewData->GetScrPos(
969 aRange.aStart.Col(), aRange.aStart.Row(), eWhich, sal_True );
970 Point aEnd = pViewData->GetScrPos(
971 aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, sal_True );
972 aStart.X() -= 2;
973 aStart.Y() -= 2;
975 // Ueberlaeufe verhindern:
976 if ( aStart.X() < -10 ) aStart.X() = -10;
977 if ( aStart.Y() < -10 ) aStart.Y() = -10;
978 if ( aEnd.X() > aWinSize.Width() + 10 )
979 aEnd.X() = aWinSize.Width() + 10;
980 if ( aEnd.Y() > aWinSize.Height() + 10 )
981 aEnd.Y() = aWinSize.Height() + 10;
983 pContentDev->DrawRect( Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) );
984 pContentDev->DrawRect( Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) );
985 pContentDev->DrawRect( Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) );
986 pContentDev->DrawRect( Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) );
988 // Seitenumbrueche
989 //! anders darstellen (gestrichelt ????)
991 size_t nColBreaks = rData.GetPagesX();
992 const SCCOL* pColEnd = rData.GetPageEndX();
993 size_t nColPos;
994 for (nColPos=0; nColPos+1<nColBreaks; nColPos++)
996 SCCOL nBreak = pColEnd[nColPos]+1;
997 if ( nBreak >= nX1 && nBreak <= nX2+1 )
999 //! hidden suchen
1000 if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL)
1001 pContentDev->SetFillColor( aManual );
1002 else
1003 pContentDev->SetFillColor( aAutomatic );
1004 Point aBreak = pViewData->GetScrPos(
1005 nBreak, aRange.aStart.Row(), eWhich, sal_True );
1006 pContentDev->DrawRect( Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) );
1010 size_t nRowBreaks = rData.GetPagesY();
1011 const SCROW* pRowEnd = rData.GetPageEndY();
1012 size_t nRowPos;
1013 for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++)
1015 SCROW nBreak = pRowEnd[nRowPos]+1;
1016 if ( nBreak >= nY1 && nBreak <= nY2+1 )
1018 //! hidden suchen
1019 if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL)
1020 pContentDev->SetFillColor( aManual );
1021 else
1022 pContentDev->SetFillColor( aAutomatic );
1023 Point aBreak = pViewData->GetScrPos(
1024 aRange.aStart.Col(), nBreak, eWhich, sal_True );
1025 pContentDev->DrawRect( Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) );
1029 // Seitenzahlen
1031 SCROW nPrStartY = aRange.aStart.Row();
1032 for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++)
1034 SCROW nPrEndY = pRowEnd[nRowPos];
1035 if ( nPrEndY >= nY1 && nPrStartY <= nY2 )
1037 SCCOL nPrStartX = aRange.aStart.Col();
1038 for (nColPos=0; nColPos<nColBreaks; nColPos++)
1040 SCCOL nPrEndX = pColEnd[nColPos];
1041 if ( nPrEndX >= nX1 && nPrStartX <= nX2 )
1043 Point aPageStart = pViewData->GetScrPos(
1044 nPrStartX, nPrStartY, eWhich, sal_True );
1045 Point aPageEnd = pViewData->GetScrPos(
1046 nPrEndX+1,nPrEndY+1, eWhich, sal_True );
1048 long nPageNo = rData.GetFirstPage();
1049 if ( rData.IsTopDown() )
1050 nPageNo += ((long)nColPos)*nRowBreaks+nRowPos;
1051 else
1052 nPageNo += ((long)nRowPos)*nColBreaks+nColPos;
1054 OUString aThisPageStr = OUString(aPageStr).replaceFirst("%1", OUString::number(nPageNo));
1056 if ( pEditEng )
1058 // find right font size with EditEngine
1059 long nHeight = 100;
1060 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1061 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1062 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1063 pEditEng->SetText( aThisPageStr );
1064 Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1066 // 40% of width or 60% of height
1067 long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1068 long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1069 nHeight = std::min(nSizeX,nSizeY);
1070 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1071 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1072 pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1074 // centered output with EditEngine
1075 Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1076 Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1077 (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1078 pEditEng->Draw( pContentDev, aPos );
1080 else
1082 // find right font size for DrawText
1083 aFont.SetSize( Size( 0,100 ) );
1084 pContentDev->SetFont( aFont );
1085 Size aSize100( pContentDev->GetTextWidth( aThisPageStr ), pContentDev->GetTextHeight() );
1087 // 40% of width or 60% of height
1088 long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1089 long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1090 aFont.SetSize( Size( 0,std::min(nSizeX,nSizeY) ) );
1091 pContentDev->SetFont( aFont );
1093 // centered output with DrawText
1094 Size aTextSize( pContentDev->GetTextWidth( aThisPageStr ), pContentDev->GetTextHeight() );
1095 Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1096 (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1097 pContentDev->DrawText( aPos, aThisPageStr );
1100 nPrStartX = nPrEndX + 1;
1103 nPrStartY = nPrEndY + 1;
1108 delete pEditEng;
1112 void ScGridWindow::DrawButtons( SCCOL nX1, SCCOL nX2, ScTableInfo& rTabInfo, OutputDevice* pContentDev)
1114 aComboButton.SetOutputDevice( pContentDev );
1116 ScDocument* pDoc = pViewData->GetDocument();
1117 ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc);
1119 SCCOL nCol;
1120 SCROW nRow;
1121 SCSIZE nArrY;
1122 SCSIZE nQuery;
1123 SCTAB nTab = pViewData->GetTabNo();
1124 ScDBData* pDBData = NULL;
1125 ScQueryParam* pQueryParam = NULL;
1127 RowInfo* pRowInfo = rTabInfo.mpRowInfo;
1128 sal_uInt16 nArrCount = rTabInfo.mnArrCount;
1130 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1132 Point aOldPos = aComboButton.GetPosPixel(); // Zustand fuer MouseDown/Up
1133 Size aOldSize = aComboButton.GetSizePixel(); // merken
1135 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1137 if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged )
1139 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1141 nRow = pThisRowInfo->nRowNo;
1144 for (nCol=nX1; nCol<=nX2; nCol++)
1146 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1147 //if several columns merged on a row, there should be only one auto button at the end of the columns.
1148 //if several rows merged on a column, the button may be in the middle, so "!pInfo->bVOverlapped" should not be used
1149 if ( pInfo->bAutoFilter && !pInfo->bHOverlapped )
1151 if (!pQueryParam)
1152 pQueryParam = new ScQueryParam;
1154 sal_Bool bNewData = sal_True;
1155 if (pDBData)
1157 SCCOL nStartCol;
1158 SCROW nStartRow;
1159 SCCOL nEndCol;
1160 SCROW nEndRow;
1161 SCTAB nAreaTab;
1162 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1163 if ( nCol >= nStartCol && nCol <= nEndCol &&
1164 nRow >= nStartRow && nRow <= nEndRow )
1165 bNewData = false;
1167 if (bNewData)
1169 pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1170 if (pDBData)
1171 pDBData->GetQueryParam( *pQueryParam );
1172 else
1174 // can also be part of DataPilot table
1175 // OSL_FAIL("Auto-Filter-Button ohne DBData");
1179 // pQueryParam kann nur MAXQUERY Eintraege enthalten
1181 sal_Bool bSimpleQuery = sal_True;
1182 sal_Bool bColumnFound = false;
1183 if (!pQueryParam->bInplace)
1184 bSimpleQuery = false;
1185 SCSIZE nCount = pQueryParam->GetEntryCount();
1186 for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery)
1187 if (pQueryParam->GetEntry(nQuery).bDoQuery)
1189 // hier nicht auf EQUAL beschraenken
1190 // (auch bei ">1" soll der Spaltenkopf blau werden)
1192 if (pQueryParam->GetEntry(nQuery).nField == nCol)
1193 bColumnFound = sal_True;
1194 if (nQuery > 0)
1195 if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND)
1196 bSimpleQuery = false;
1199 bool bArrowState = bSimpleQuery && bColumnFound;
1200 long nSizeX;
1201 long nSizeY;
1202 SCCOL nStartCol= nCol;
1203 SCROW nStartRow = nRow;
1204 //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.
1205 //should first get the start pos of the merge area, then get the nSizeX through the start pos.
1206 pDoc->ExtendOverlapped(nStartCol, nStartRow,nCol, nRow, nTab);//get nStartCol,nStartRow
1207 pViewData->GetMergeSizePixel( nStartCol, nStartRow, nSizeX, nSizeY );//get nSizeX
1208 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
1209 Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1211 aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1), bLayoutRTL);
1212 aCellBtn.setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL
1213 aCellBtn.setDrawBaseButton(false);
1214 aCellBtn.setDrawPopupButton(true);
1215 aCellBtn.setHasHiddenMember(bArrowState);
1216 aCellBtn.draw();
1221 if ( pRowInfo[nArrY].bPivotButton && pRowInfo[nArrY].bChanged )
1223 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1224 nRow = pThisRowInfo->nRowNo;
1225 for (nCol=nX1; nCol<=nX2; nCol++)
1227 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1228 if (pInfo->bHOverlapped || pInfo->bVOverlapped)
1229 continue;
1231 Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1232 long nSizeX;
1233 long nSizeY;
1234 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1235 long nPosX = aScrPos.X();
1236 long nPosY = aScrPos.Y();
1237 // bLayoutRTL is handled in setBoundingBox
1239 OUString aStr = pDoc->GetString(nCol, nRow, nTab);
1240 aCellBtn.setText(aStr);
1241 aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1), bLayoutRTL);
1242 aCellBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now
1243 aCellBtn.setDrawBaseButton(pInfo->bPivotButton);
1244 aCellBtn.setDrawPopupButton(pInfo->bPivotPopupButton);
1245 aCellBtn.setHasHiddenMember(pInfo->bFilterActive);
1246 aCellBtn.draw();
1250 if ( bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged )
1252 Rectangle aRect = GetListValButtonRect( aListValPos );
1253 aComboButton.SetPosPixel( aRect.TopLeft() );
1254 aComboButton.SetSizePixel( aRect.GetSize() );
1255 pContentDev->SetClipRegion(Region(aRect));
1256 aComboButton.Draw( false, false );
1257 pContentDev->SetClipRegion(); // always called from Draw() without clip region
1258 aComboButton.SetPosPixel( aOldPos ); // restore old state
1259 aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter)
1263 delete pQueryParam;
1264 aComboButton.SetOutputDevice( this );
1267 Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos )
1269 ScDocument* pDoc = pViewData->GetDocument();
1270 SCTAB nTab = pViewData->GetTabNo();
1271 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1272 long nLayoutSign = bLayoutRTL ? -1 : 1;
1274 ScDDComboBoxButton aButton( this ); // for optimal size
1275 Size aBtnSize = aButton.GetSizePixel();
1277 SCCOL nCol = rButtonPos.Col();
1278 SCROW nRow = rButtonPos.Row();
1280 long nCellSizeX; // width of this cell, including merged
1281 long nDummy;
1282 pViewData->GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy );
1284 // for height, only the cell's row is used, excluding merged cells
1285 long nCellSizeY = ScViewData::ToPixel( pDoc->GetRowHeight( nRow, nTab ), pViewData->GetPPTY() );
1286 long nAvailable = nCellSizeX;
1288 // left edge of next cell if there is a non-hidden next column
1289 SCCOL nNextCol = nCol + 1;
1290 const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE ));
1291 if ( pMerge->GetColMerge() > 1 )
1292 nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area
1293 while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) )
1294 ++nNextCol;
1295 sal_Bool bNextCell = ( nNextCol <= MAXCOL );
1296 if ( bNextCell )
1297 nAvailable = ScViewData::ToPixel( pDoc->GetColWidth( nNextCol, nTab ), pViewData->GetPPTX() );
1299 if ( nAvailable < aBtnSize.Width() )
1300 aBtnSize.Width() = nAvailable;
1301 if ( nCellSizeY < aBtnSize.Height() )
1302 aBtnSize.Height() = nCellSizeY;
1304 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich, sal_True );
1305 aPos.X() += nCellSizeX * nLayoutSign; // start of next cell
1306 if (!bNextCell)
1307 aPos.X() -= aBtnSize.Width() * nLayoutSign; // right edge of cell if next cell not available
1308 aPos.Y() += nCellSizeY - aBtnSize.Height();
1309 // X remains at the left edge
1311 if ( bLayoutRTL )
1312 aPos.X() -= aBtnSize.Width()-1; // align right edge of button with cell border
1314 return Rectangle( aPos, aBtnSize );
1317 bool ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab )
1319 ScDocument* pDoc = pViewData->GetDocument();
1320 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1321 ScQueryParam aQueryParam;
1323 if ( pDBData )
1324 pDBData->GetQueryParam( aQueryParam );
1325 else
1327 OSL_FAIL("Auto-Filter-Button ohne DBData");
1330 bool bSimpleQuery = true;
1331 bool bColumnFound = false;
1332 SCSIZE nQuery;
1334 if ( !aQueryParam.bInplace )
1335 bSimpleQuery = false;
1337 // aQueryParam kann nur MAXQUERY Eintraege enthalten
1339 SCSIZE nCount = aQueryParam.GetEntryCount();
1340 for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery)
1341 if ( aQueryParam.GetEntry(nQuery).bDoQuery )
1343 if (aQueryParam.GetEntry(nQuery).nField == nCol)
1344 bColumnFound = sal_True;
1346 if (nQuery > 0)
1347 if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND)
1348 bSimpleQuery = false;
1351 return ( bSimpleQuery && bColumnFound );
1354 void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects )
1356 ScMarkData aMultiMark( pViewData->GetMarkData() );
1357 aMultiMark.SetMarking( false );
1358 aMultiMark.MarkToMulti();
1360 ScDocument* pDoc = pViewData->GetDocument();
1361 SCTAB nTab = pViewData->GetTabNo();
1363 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1364 long nLayoutSign = bLayoutRTL ? -1 : 1;
1366 if ( !aMultiMark.IsMultiMarked() )
1367 return;
1369 ScRange aMultiRange;
1370 aMultiMark.GetMultiMarkArea( aMultiRange );
1371 SCCOL nX1 = aMultiRange.aStart.Col();
1372 SCROW nY1 = aMultiRange.aStart.Row();
1373 SCCOL nX2 = aMultiRange.aEnd.Col();
1374 SCROW nY2 = aMultiRange.aEnd.Row();
1376 PutInOrder( nX1, nX2 );
1377 PutInOrder( nY1, nY2 );
1379 sal_Bool bTestMerge = sal_True;
1380 bool bRepeat = true;
1382 SCCOL nTestX2 = nX2;
1383 SCROW nTestY2 = nY2;
1384 if (bTestMerge)
1385 pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab );
1387 SCCOL nPosX = pViewData->GetPosX( eHWhich );
1388 SCROW nPosY = pViewData->GetPosY( eVWhich );
1389 if (nTestX2 < nPosX || nTestY2 < nPosY)
1390 return; // unsichtbar
1391 SCCOL nRealX1 = nX1;
1392 if (nX1 < nPosX)
1393 nX1 = nPosX;
1394 if (nY1 < nPosY)
1395 nY1 = nPosY;
1397 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
1398 if (nXRight > MAXCOL) nXRight = MAXCOL;
1399 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
1400 if (nYBottom > MAXROW) nYBottom = MAXROW;
1402 if (nX1 > nXRight || nY1 > nYBottom)
1403 return; // unsichtbar
1404 if (nX2 > nXRight) nX2 = nXRight;
1405 if (nY2 > nYBottom) nY2 = nYBottom;
1407 double nPPTX = pViewData->GetPPTX();
1408 double nPPTY = pViewData->GetPPTY();
1410 ScInvertMerger aInvert( &rPixelRects );
1412 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
1413 long nScrY = aScrPos.Y();
1414 sal_Bool bWasHidden = false;
1415 for (SCROW nY=nY1; nY<=nY2; nY++)
1417 sal_Bool bFirstRow = ( nY == nPosY ); // first visible row?
1418 sal_Bool bDoHidden = false; // versteckte nachholen ?
1419 sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab );
1420 sal_Bool bDoRow = ( nHeightTwips != 0 );
1421 if (bDoRow)
1423 if (bTestMerge)
1424 if (bWasHidden) // auf versteckte zusammengefasste testen
1426 bDoHidden = sal_True;
1427 bDoRow = sal_True;
1430 bWasHidden = false;
1432 else
1434 bWasHidden = sal_True;
1435 if (bTestMerge)
1436 if (nY==nY2)
1437 bDoRow = sal_True; // letzte Zeile aus Block
1440 if ( bDoRow )
1442 SCCOL nLoopEndX = nX2;
1443 if (nX2 < nX1) // Rest von zusammengefasst
1445 SCCOL nStartX = nX1;
1446 while ( ((const ScMergeFlagAttr*)pDoc->
1447 GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() )
1448 --nStartX;
1449 if (nStartX <= nX2)
1450 nLoopEndX = nX1;
1453 long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1;
1454 long nScrX = aScrPos.X();
1455 for (SCCOL nX=nX1; nX<=nLoopEndX; nX++)
1457 long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX );
1458 if ( nWidth > 0 )
1460 long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign;
1461 if (bTestMerge)
1463 SCROW nThisY = nY;
1464 const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1465 const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern->
1466 GetItem(ATTR_MERGE_FLAG);
1467 if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) )
1469 while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 &&
1470 (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) )
1472 --nThisY;
1473 pPattern = pDoc->GetPattern( nX, nThisY, nTab );
1474 pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1478 // nur Rest von zusammengefasster zu sehen ?
1479 SCCOL nThisX = nX;
1480 if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 )
1482 while ( pMergeFlag->IsHorOverlapped() )
1484 --nThisX;
1485 pPattern = pDoc->GetPattern( nThisX, nThisY, nTab );
1486 pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1490 if ( aMultiMark.IsCellMarked( nThisX, nThisY, sal_True ) == bRepeat )
1492 if ( !pMergeFlag->IsOverlapped() )
1494 ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
1495 if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0)
1497 Point aEndPos = pViewData->GetScrPos(
1498 nThisX + pMerge->GetColMerge(),
1499 nThisY + pMerge->GetRowMerge(), eWhich );
1500 if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY )
1502 aInvert.AddRect( Rectangle( nScrX,nScrY,
1503 aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) );
1506 else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1508 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1513 else // !bTestMerge
1515 if ( aMultiMark.IsCellMarked( nX, nY, sal_True ) == bRepeat &&
1516 nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1518 aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1522 nScrX = nEndX + nLayoutSign;
1525 nScrY = nEndY + 1;
1530 // -------------------------------------------------------------------------
1532 void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt )
1534 Window::DataChanged(rDCEvt);
1536 if ( (rDCEvt.GetType() == DATACHANGED_PRINTER) ||
1537 (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
1538 (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1539 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1540 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1541 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1543 if ( rDCEvt.GetType() == DATACHANGED_FONTS && eWhich == pViewData->GetActivePart() )
1544 pViewData->GetDocShell()->UpdateFontList();
1546 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1547 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1549 if ( eWhich == pViewData->GetActivePart() ) // only once for the view
1551 ScTabView* pView = pViewData->GetView();
1553 // update scale in case the UI ScreenZoom has changed
1554 ScGlobal::UpdatePPT(this);
1555 pView->RecalcPPT();
1557 // RepeatResize in case scroll bar sizes have changed
1558 pView->RepeatResize();
1559 pView->UpdateAllOverlays();
1561 // invalidate cell attribs in input handler, in case the
1562 // EditEngine BackgroundColor has to be changed
1563 if ( pViewData->IsActive() )
1565 ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1566 if (pHdl)
1567 pHdl->ForgetLastPattern();
1572 Invalidate();
1576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */