Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "scitems.hxx"
21 : #include <editeng/eeitem.hxx>
22 :
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>
31 :
32 : #define LOK_USE_UNSTABLE_API
33 : #include <LibreOfficeKit/LibreOfficeKitEnums.h>
34 :
35 : #include <svx/svdview.hxx>
36 : #include "tabvwsh.hxx"
37 :
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>
68 :
69 1 : static void lcl_LimitRect( Rectangle& rRect, const Rectangle& rVisible )
70 : {
71 1 : if ( rRect.Top() < rVisible.Top()-1 ) rRect.Top() = rVisible.Top()-1;
72 1 : if ( rRect.Bottom() > rVisible.Bottom()+1 ) rRect.Bottom() = rVisible.Bottom()+1;
73 :
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.
77 1 : }
78 :
79 1 : 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 )
83 : {
84 : // pButtonViewData wird nur benutzt, um die Button-Groesse zu setzen,
85 : // darf ansonsten NULL sein!
86 :
87 1 : Rectangle aInner = rInnerPixel;
88 1 : if ( bLayoutRTL )
89 : {
90 0 : aInner.Left() = rInnerPixel.Right();
91 0 : aInner.Right() = rInnerPixel.Left();
92 : }
93 :
94 1 : Rectangle aVisible( Point(0,0), pDev->GetOutputSizePixel() );
95 1 : lcl_LimitRect( aInner, aVisible );
96 :
97 1 : Rectangle aOuter = aInner;
98 1 : long nHor = (long) ( SC_SCENARIO_HSPACE * nPPTX );
99 1 : long nVer = (long) ( SC_SCENARIO_VSPACE * nPPTY );
100 1 : aOuter.Left() -= nHor;
101 1 : aOuter.Right() += nHor;
102 1 : aOuter.Top() -= nVer;
103 1 : aOuter.Bottom() += nVer;
104 :
105 : // use ScPatternAttr::GetFont only for font size
106 1 : vcl::Font aAttrFont;
107 1 : static_cast<const ScPatternAttr&>(pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).
108 1 : GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY);
109 :
110 : // everything else from application font
111 2 : vcl::Font aAppFont = pDev->GetSettings().GetStyleSettings().GetAppFont();
112 1 : aAppFont.SetSize( aAttrFont.GetSize() );
113 :
114 1 : aAppFont.SetAlign( ALIGN_TOP );
115 1 : pDev->SetFont( aAppFont );
116 :
117 1 : Size aTextSize( pDev->GetTextWidth( rTitle ), pDev->GetTextHeight() );
118 :
119 1 : if ( bTextBelow )
120 1 : aOuter.Bottom() += aTextSize.Height();
121 : else
122 0 : aOuter.Top() -= aTextSize.Height();
123 :
124 1 : pDev->SetLineColor();
125 1 : pDev->SetFillColor( rColor );
126 : // links, oben, rechts, unten
127 1 : pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aInner.Left(), aOuter.Bottom() ) );
128 1 : pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aOuter.Right(), aInner.Top() ) );
129 1 : pDev->DrawRect( Rectangle( aInner.Right(), aOuter.Top(), aOuter.Right(), aOuter.Bottom() ) );
130 1 : pDev->DrawRect( Rectangle( aOuter.Left(), aInner.Bottom(), aOuter.Right(), aOuter.Bottom() ) );
131 :
132 1 : long nButtonY = bTextBelow ? aInner.Bottom() : aOuter.Top();
133 :
134 2 : ScDDComboBoxButton aComboButton(pDev);
135 1 : aComboButton.SetOptSizePixel();
136 2 : long nBWidth = ( aComboButton.GetSizePixel().Width() * rZoomY.GetNumerator() )
137 1 : / rZoomY.GetDenominator();
138 1 : long nBHeight = nVer + aTextSize.Height() + 1;
139 1 : Size aButSize( nBWidth, nBHeight );
140 1 : long nButtonPos = bLayoutRTL ? aOuter.Left() : aOuter.Right()-nBWidth+1;
141 1 : aComboButton.Draw( Point(nButtonPos, nButtonY), aButSize, false );
142 1 : if (pButtonViewData)
143 1 : pButtonViewData->SetScenButSize( aButSize );
144 :
145 1 : long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left();
146 :
147 1 : bool bWasClip = false;
148 2 : vcl::Region aOldClip;
149 1 : bool bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() );
150 1 : if ( bClip )
151 : {
152 0 : if (pDev->IsClipRegion())
153 : {
154 0 : bWasClip = true;
155 0 : aOldClip = pDev->GetActiveClipRegion();
156 : }
157 0 : long nClipStartX = bLayoutRTL ? aOuter.Left() + nBWidth : aInner.Left();
158 0 : long nClipEndX = bLayoutRTL ? aInner.Right() : aOuter.Right() - nBWidth;
159 0 : pDev->SetClipRegion( vcl::Region(Rectangle( nClipStartX, nButtonY + nVer/2,
160 0 : nClipEndX, nButtonY + nVer/2 + aTextSize.Height())) );
161 : }
162 :
163 1 : pDev->DrawText( Point( nTextStart, nButtonY + nVer/2 ), rTitle );
164 :
165 1 : if ( bClip )
166 : {
167 0 : if ( bWasClip )
168 0 : pDev->SetClipRegion(aOldClip);
169 : else
170 0 : pDev->SetClipRegion();
171 : }
172 :
173 1 : pDev->SetFillColor();
174 1 : pDev->SetLineColor( COL_BLACK );
175 1 : pDev->DrawRect( aInner );
176 2 : pDev->DrawRect( aOuter );
177 1 : }
178 :
179 1 : static void lcl_DrawScenarioFrames( OutputDevice* pDev, ScViewData* pViewData, ScSplitPos eWhich,
180 : SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 )
181 : {
182 1 : ScDocument* pDoc = pViewData->GetDocument();
183 1 : SCTAB nTab = pViewData->GetTabNo();
184 1 : SCTAB nTabCount = pDoc->GetTableCount();
185 1 : if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
186 : {
187 1 : if ( nX1 > 0 ) --nX1;
188 1 : if ( nY1>=2 ) nY1 -= 2; // Hack: Titelzeile beruehrt zwei Zellen
189 1 : else if ( nY1 > 0 ) --nY1;
190 1 : if ( nX2 < MAXCOL ) ++nX2;
191 1 : if ( nY2 < MAXROW-1 ) nY2 += 2; // Hack: Titelzeile beruehrt zwei Zellen
192 0 : else if ( nY2 < MAXROW ) ++nY2;
193 1 : ScRange aViewRange( nX1,nY1,nTab, nX2,nY2,nTab );
194 :
195 : //! Ranges an der Table cachen!!!!
196 :
197 1 : ScMarkData aMarks;
198 2 : for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
199 1 : pDoc->MarkScenario( i, nTab, aMarks, false, SC_SCENARIO_SHOWFRAME );
200 2 : ScRangeListRef xRanges = new ScRangeList;
201 1 : aMarks.FillRangeListWithMarks( xRanges, false );
202 :
203 1 : bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
204 1 : long nLayoutSign = bLayoutRTL ? -1 : 1;
205 :
206 2 : for (size_t j = 0, n = xRanges->size(); j < n; ++j)
207 : {
208 1 : 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 1 : pDoc->ExtendTotalMerge( aRange );
212 :
213 : //! -> Repaint beim Zusammenfassen erweitern !!!
214 :
215 1 : if ( aRange.Intersects( aViewRange ) ) //! Platz fuer Text/Button?
216 : {
217 : Point aStartPos = pViewData->GetScrPos(
218 1 : aRange.aStart.Col(), aRange.aStart.Row(), eWhich, true );
219 : Point aEndPos = pViewData->GetScrPos(
220 1 : aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, true );
221 : // on the grid:
222 1 : aStartPos.X() -= nLayoutSign;
223 1 : aStartPos.Y() -= 1;
224 1 : aEndPos.X() -= nLayoutSign;
225 1 : aEndPos.Y() -= 1;
226 :
227 1 : bool bTextBelow = ( aRange.aStart.Row() == 0 );
228 :
229 1 : OUString aCurrent;
230 1 : Color aColor( COL_LIGHTGRAY );
231 2 : for (SCTAB nAct=nTab+1; nAct<nTabCount && pDoc->IsScenario(nAct); nAct++)
232 1 : if ( pDoc->IsActiveScenario(nAct) && pDoc->HasScenarioRange(nAct,aRange) )
233 : {
234 1 : OUString aDummyComment;
235 : sal_uInt16 nDummyFlags;
236 1 : pDoc->GetName( nAct, aCurrent );
237 1 : pDoc->GetScenarioData( nAct, aDummyComment, aColor, nDummyFlags );
238 : }
239 :
240 1 : if (aCurrent.isEmpty())
241 0 : aCurrent = ScGlobal::GetRscString( STR_EMPTYDATA );
242 :
243 : //! eigener Text "(keins)" statt "(leer)" ???
244 :
245 : lcl_DrawOneFrame( pDev, Rectangle( aStartPos, aEndPos ),
246 : aCurrent, aColor, bTextBelow,
247 1 : pViewData->GetPPTX(), pViewData->GetPPTY(), pViewData->GetZoomY(),
248 2 : pDoc, pViewData, bLayoutRTL );
249 : }
250 1 : }
251 : }
252 1 : }
253 :
254 16 : static void lcl_DrawHighlight( ScOutputData& rOutputData, ScViewData* pViewData,
255 : const std::vector<ScHighlightEntry>& rHighlightRanges )
256 : {
257 16 : SCTAB nTab = pViewData->GetTabNo();
258 16 : std::vector<ScHighlightEntry>::const_iterator pIter;
259 16 : for ( pIter = rHighlightRanges.begin(); pIter != rHighlightRanges.end(); ++pIter)
260 : {
261 0 : ScRange aRange = pIter->aRef;
262 0 : if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() )
263 : {
264 : rOutputData.DrawRefMark(
265 0 : aRange.aStart.Col(), aRange.aStart.Row(),
266 0 : aRange.aEnd.Col(), aRange.aEnd.Row(),
267 0 : pIter->aColor, false );
268 : }
269 : }
270 16 : }
271 :
272 0 : void ScGridWindow::DoInvertRect( const Rectangle& rPixel )
273 : {
274 0 : if ( rPixel == aInvertRect )
275 0 : aInvertRect = Rectangle(); // aufheben
276 : else
277 : {
278 : OSL_ENSURE( aInvertRect.IsEmpty(), "DoInvertRect nicht paarig" );
279 :
280 0 : aInvertRect = rPixel; // neues Rechteck merken
281 : }
282 :
283 0 : UpdateHeaderOverlay(); // uses aInvertRect
284 0 : }
285 :
286 4922 : void ScGridWindow::PrePaint(vcl::RenderContext& /*rRenderContext*/)
287 : {
288 : // forward PrePaint to DrawingLayer
289 4922 : ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
290 :
291 4922 : if(pTabViewShell)
292 : {
293 4922 : SdrView* pDrawView = pTabViewShell->GetSdrView();
294 :
295 4922 : if (pDrawView)
296 : {
297 4922 : pDrawView->PrePaint();
298 : }
299 : }
300 4922 : }
301 :
302 2964 : void ScGridWindow::Paint( vcl::RenderContext& /*rRenderContext*/, const Rectangle& rRect )
303 : {
304 2964 : ScDocument* pDoc = pViewData->GetDocument();
305 2964 : if ( pDoc->IsInInterpreter() )
306 : {
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.
310 :
311 0 : if ( bNeedsRepaint )
312 : {
313 : //! Rechtecke zusammenfassen?
314 0 : aRepaintPixel = Rectangle(); // mehrfach -> alles painten
315 : }
316 : else
317 : {
318 0 : bNeedsRepaint = true;
319 0 : aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich
320 : }
321 0 : return;
322 : }
323 :
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 2964 : GetSizePixel();
327 :
328 2964 : if (bIsInPaint)
329 0 : return;
330 :
331 2964 : bIsInPaint = true;
332 :
333 2964 : Rectangle aPixRect = LogicToPixel( rRect );
334 :
335 2964 : SCCOL nX1 = pViewData->GetPosX(eHWhich);
336 2964 : SCROW nY1 = pViewData->GetPosY(eVWhich);
337 :
338 2964 : SCTAB nTab = pViewData->GetTabNo();
339 :
340 2964 : double nPPTX = pViewData->GetPPTX();
341 2964 : double nPPTY = pViewData->GetPPTY();
342 :
343 2964 : Rectangle aMirroredPixel = aPixRect;
344 2964 : if ( pDoc->IsLayoutRTL( nTab ) )
345 : {
346 : // mirror and swap
347 1 : long nWidth = GetSizePixel().Width();
348 1 : aMirroredPixel.Left() = nWidth - 1 - aPixRect.Right();
349 1 : aMirroredPixel.Right() = nWidth - 1 - aPixRect.Left();
350 : }
351 :
352 2964 : long nScrX = ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
353 10880 : while ( nScrX <= aMirroredPixel.Left() && nX1 < MAXCOL )
354 : {
355 4952 : ++nX1;
356 4952 : nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX );
357 : }
358 2964 : SCCOL nX2 = nX1;
359 25343 : while ( nScrX <= aMirroredPixel.Right() && nX2 < MAXCOL )
360 : {
361 19415 : ++nX2;
362 19415 : nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX );
363 : }
364 :
365 2964 : long nScrY = 0;
366 2964 : ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, MAXROW, nPPTY, pDoc, nTab);
367 2964 : SCROW nY2 = nY1;
368 2964 : if (nScrY <= aPixRect.Bottom() && nY2 < MAXROW)
369 : {
370 2646 : ++nY2;
371 2646 : ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, MAXROW, nPPTY, pDoc, nTab);
372 : }
373 :
374 2964 : Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // don't continue with painting
375 :
376 2964 : bIsInPaint = false;
377 : }
378 :
379 2964 : void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode )
380 : {
381 2964 : ScDocShell* pDocSh = pViewData->GetDocShell();
382 2964 : ScDocument& rDoc = pDocSh->GetDocument();
383 :
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 2964 : if (rDoc.GetDrawLayer()->isTiledRendering())
389 0 : return;
390 :
391 2964 : ScModule* pScMod = SC_MOD();
392 2964 : bool bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg();
393 :
394 2964 : if (pViewData->IsMinimized())
395 0 : return;
396 :
397 2964 : PutInOrder( nX1, nX2 );
398 2964 : PutInOrder( nY1, nY2 );
399 :
400 : OSL_ENSURE( ValidCol(nX2) && ValidRow(nY2), "GridWin Draw area too big" );
401 :
402 2964 : UpdateVisibleRange();
403 :
404 2964 : if (nX2 < maVisibleRange.mnCol1 || nY2 < maVisibleRange.mnRow1)
405 0 : return;
406 : // invisible
407 2964 : if (nX1 < maVisibleRange.mnCol1)
408 0 : nX1 = maVisibleRange.mnCol1;
409 2964 : if (nY1 < maVisibleRange.mnRow1)
410 0 : nY1 = maVisibleRange.mnRow1;
411 :
412 2964 : if (nX1 > maVisibleRange.mnCol2 || nY1 > maVisibleRange.mnRow2)
413 0 : return;
414 :
415 2964 : if (nX2 > maVisibleRange.mnCol2)
416 0 : nX2 = maVisibleRange.mnCol2;
417 2964 : if (nY2 > maVisibleRange.mnRow2)
418 0 : nY2 = maVisibleRange.mnRow2;
419 :
420 2964 : if ( eMode != SC_UPDATE_MARKS && nX2 < maVisibleRange.mnCol2)
421 0 : nX2 = maVisibleRange.mnCol2; // zum Weiterzeichnen
422 :
423 : // point of no return
424 :
425 2964 : ++nPaintCount; // mark that painting is in progress
426 :
427 2964 : SCTAB nTab = pViewData->GetTabNo();
428 2964 : rDoc.ExtendHidden( nX1, nY1, nX2, nY2, nTab );
429 :
430 2964 : Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
431 2964 : long nMirrorWidth = GetSizePixel().Width();
432 2964 : bool bLayoutRTL = rDoc.IsLayoutRTL( nTab );
433 2964 : if ( bLayoutRTL )
434 : {
435 1 : long nEndPixel = pViewData->GetScrPos( nX2+1, maVisibleRange.mnRow1, eWhich ).X();
436 1 : nMirrorWidth = aScrPos.X() - nEndPixel;
437 1 : aScrPos.X() = nEndPixel + 1;
438 : }
439 :
440 2964 : long nScrX = aScrPos.X();
441 2964 : long nScrY = aScrPos.Y();
442 :
443 2964 : SCCOL nCurX = pViewData->GetCurX();
444 2964 : SCROW nCurY = pViewData->GetCurY();
445 2964 : SCCOL nCurEndX = nCurX;
446 2964 : SCROW nCurEndY = nCurY;
447 2964 : rDoc.ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab );
448 7073 : bool bCurVis = nCursorHideCount==0 &&
449 7565 : ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 );
450 :
451 : // AutoFill-Anfasser
452 4437 : if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab &&
453 2946 : ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) )
454 : {
455 0 : SCCOL nHdlX = aAutoMarkPos.Col();
456 0 : SCROW nHdlY = aAutoMarkPos.Row();
457 0 : rDoc.ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab );
458 0 : bCurVis = ( nHdlX+1 >= nX1 && nHdlX <= nX2 && nHdlY+1 >= nY1 && nHdlY <= nY2 );
459 : // left and top is unaffected
460 :
461 : //! AutoFill-Anfasser alleine (ohne Cursor) zeichnen ???
462 : }
463 :
464 2964 : double nPPTX = pViewData->GetPPTX();
465 2964 : double nPPTY = pViewData->GetPPTY();
466 :
467 2964 : const ScViewOptions& rOpts = pViewData->GetOptions();
468 :
469 : // data block
470 :
471 2964 : ScTableInfo aTabInfo;
472 : rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
473 2964 : nPPTX, nPPTY, false, rOpts.GetOption(VOPT_FORMULAS),
474 5928 : &pViewData->GetMarkData() );
475 :
476 5928 : Fraction aZoomX = pViewData->GetZoomX();
477 5928 : Fraction aZoomY = pViewData->GetZoomY();
478 : ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, &rDoc, nTab,
479 : nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
480 5928 : &aZoomX, &aZoomY );
481 :
482 2964 : aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL
483 2964 : aOutputData.SetSpellCheckContext(mpSpellCheckCxt.get());
484 :
485 5928 : ScopedVclPtr< VirtualDevice > xFmtVirtDev;
486 2964 : bool bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode?
487 :
488 2964 : if ( bTextWysiwyg )
489 : {
490 : // use printer for text formatting
491 :
492 27 : OutputDevice* pFmtDev = rDoc.GetPrinter();
493 27 : pFmtDev->SetMapMode( pViewData->GetLogicMode(eWhich) );
494 27 : aOutputData.SetFmtDevice( pFmtDev );
495 : }
496 2937 : else if ( aZoomX != aZoomY && pViewData->IsOle() )
497 : {
498 : // #i45033# For OLE inplace editing with different zoom factors,
499 : // use a virtual device with 1/100th mm as text formatting reference
500 :
501 0 : xFmtVirtDev.reset( VclPtr<VirtualDevice>::Create() );
502 0 : xFmtVirtDev->SetMapMode( MAP_100TH_MM );
503 0 : aOutputData.SetFmtDevice( xFmtVirtDev.get() );
504 :
505 0 : bLogicText = true; // use logic MapMode
506 : }
507 :
508 2964 : DrawContent(*this, aTabInfo, aOutputData, bLogicText, eMode);
509 :
510 : // Wenn waehrend des Paint etwas invertiert wurde (Selektion geaendert aus Basic-Macro),
511 : // ist das jetzt durcheinandergekommen und es muss neu gemalt werden
512 :
513 : OSL_ENSURE(nPaintCount, "nPaintCount falsch");
514 2964 : --nPaintCount;
515 2964 : if (!nPaintCount)
516 2964 : CheckNeedsRepaint();
517 :
518 : // Flag drawn formula cells "unchanged".
519 2964 : rDoc.ResetChanged(ScRange(nX1, nY1, nTab, nX2, nY2, nTab));
520 5928 : rDoc.ClearFormulaContext();
521 : }
522 :
523 2964 : void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableInfo, ScOutputData& aOutputData,
524 : bool bLogicText, ScUpdateMode eMode)
525 : {
526 2964 : ScModule* pScMod = SC_MOD();
527 2964 : ScDocShell* pDocSh = pViewData->GetDocShell();
528 2964 : ScDocument& rDoc = pDocSh->GetDocument();
529 2964 : const ScViewOptions& rOpts = pViewData->GetOptions();
530 2964 : bool bIsTiledRendering = rDoc.GetDrawLayer()->isTiledRendering();
531 :
532 2964 : SCTAB nTab = aOutputData.nTab;
533 2964 : SCCOL nX1 = aOutputData.nX1;
534 2964 : SCROW nY1 = aOutputData.nY1;
535 2964 : SCCOL nX2 = aOutputData.nX2;
536 2964 : SCROW nY2 = aOutputData.nY2;
537 2964 : long nScrX = aOutputData.nScrX;
538 2964 : long nScrY = aOutputData.nScrY;
539 :
540 2964 : const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig();
541 2964 : Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, false ).nColor );
542 2964 : if ( aGridColor.GetColor() == COL_TRANSPARENT )
543 : {
544 : // use view options' grid color only if color config has "automatic" color
545 2964 : aGridColor = rOpts.GetGridColor();
546 : }
547 :
548 2964 : aOutputData.SetSyntaxMode ( pViewData->IsSyntaxMode() );
549 2964 : aOutputData.SetGridColor ( aGridColor );
550 2964 : aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) );
551 2964 : aOutputData.SetShowFormulas ( rOpts.GetOption( VOPT_FORMULAS ) );
552 2964 : aOutputData.SetShowSpellErrors ( rDoc.GetDocOptions().IsAutoSpell() );
553 2964 : aOutputData.SetMarkClipped ( rOpts.GetOption( VOPT_CLIPMARKS ) );
554 :
555 2964 : aOutputData.SetUseStyleColor( true ); // always set in table view
556 :
557 2964 : aOutputData.SetEditObject( GetEditObject() );
558 2964 : aOutputData.SetViewShell( pViewData->GetViewShell() );
559 :
560 2964 : bool bGrid = rOpts.GetOption( VOPT_GRID ) && pViewData->GetShowGrid();
561 2964 : bool bGridFirst = !rOpts.GetOption( VOPT_GRID_ONTOP );
562 :
563 2964 : bool bPage = rOpts.GetOption( VOPT_PAGEBREAKS );
564 :
565 2964 : if ( eMode == SC_UPDATE_CHANGED )
566 : {
567 0 : aOutputData.FindChanged();
568 0 : aOutputData.SetSingleGrid(true);
569 : }
570 :
571 2964 : bool bPageMode = pViewData->IsPagebreakMode();
572 2964 : if (bPageMode) // nach FindChanged
573 : {
574 : // SetPagebreakMode initialisiert auch bPrinted Flags
575 0 : aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() );
576 : }
577 :
578 2964 : EditView* pEditView = NULL;
579 2964 : bool bEditMode = pViewData->HasEditView(eWhich);
580 2964 : if ( bEditMode && pViewData->GetRefTabNo() == nTab )
581 : {
582 : SCCOL nEditCol;
583 : SCROW nEditRow;
584 0 : pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
585 0 : SCCOL nEditEndCol = pViewData->GetEditEndCol();
586 0 : SCROW nEditEndRow = pViewData->GetEditEndRow();
587 :
588 0 : if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 )
589 0 : aOutputData.SetEditCell( nEditCol, nEditRow );
590 : else
591 0 : bEditMode = false;
592 : }
593 :
594 : // define drawing layer map mode and paint rectangle
595 2964 : MapMode aDrawMode = GetDrawMapMode();
596 2964 : if (bIsTiledRendering)
597 : {
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 0 : aDrawMode.SetOrigin(PixelToLogic(Point(nScrX, nScrY), aDrawMode));
604 : }
605 2964 : Rectangle aDrawingRectLogic;
606 2964 : bool bLayoutRTL = rDoc.IsLayoutRTL( nTab );
607 :
608 : {
609 : // get drawing pixel rect
610 2964 : Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
611 :
612 : // correct for border (left/right)
613 2964 : if(MAXCOL == nX2)
614 : {
615 5 : if(bLayoutRTL)
616 : {
617 0 : aDrawingRectPixel.Left() = 0L;
618 : }
619 : else
620 : {
621 5 : aDrawingRectPixel.Right() = GetOutputSizePixel().getWidth();
622 : }
623 : }
624 :
625 : // correct for border (bottom)
626 2964 : if(MAXROW == nY2)
627 : {
628 8 : aDrawingRectPixel.Bottom() = GetOutputSizePixel().getHeight();
629 : }
630 :
631 : // get logic positions
632 2964 : aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode);
633 : }
634 :
635 2964 : OutputDevice* pContentDev = &rDevice; // device for document content, used by overlay manager
636 2964 : SdrPaintWindow* pTargetPaintWindow = 0; // #i74769# work with SdrPaintWindow directly
637 :
638 : {
639 : // init redraw
640 2964 : ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
641 :
642 2964 : if(pTabViewShell)
643 : {
644 2964 : MapMode aCurrentMapMode(pContentDev->GetMapMode());
645 2964 : pContentDev->SetMapMode(aDrawMode);
646 2964 : SdrView* pDrawView = pTabViewShell->GetSdrView();
647 :
648 2964 : if(pDrawView)
649 : {
650 : // #i74769# Use new BeginDrawLayers() interface
651 2964 : vcl::Region aDrawingRegion(aDrawingRectLogic);
652 2964 : pTargetPaintWindow = pDrawView->BeginDrawLayers(pContentDev, aDrawingRegion);
653 : OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)");
654 :
655 2964 : if (!bIsTiledRendering)
656 : {
657 : // #i74769# get target device from SdrPaintWindow, this may be the prerender
658 : // device now, too.
659 2964 : pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice());
660 2964 : aOutputData.SetContentDevice(pContentDev);
661 2964 : }
662 : }
663 :
664 2964 : pContentDev->SetMapMode(aCurrentMapMode);
665 : }
666 : }
667 :
668 : // Rand (Wiese) (Pixel)
669 2964 : if ( nX2==MAXCOL || nY2==MAXROW )
670 : {
671 : // save MapMode and set to pixel
672 13 : MapMode aCurrentMapMode(pContentDev->GetMapMode());
673 13 : pContentDev->SetMapMode(MAP_PIXEL);
674 :
675 13 : Rectangle aPixRect = Rectangle( Point(), GetOutputSizePixel() );
676 13 : pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor );
677 13 : pContentDev->SetLineColor();
678 13 : if ( nX2==MAXCOL )
679 : {
680 5 : Rectangle aDrawRect( aPixRect );
681 5 : if ( bLayoutRTL )
682 0 : aDrawRect.Right() = nScrX - 1;
683 : else
684 5 : aDrawRect.Left() = nScrX + aOutputData.GetScrW();
685 5 : if (aDrawRect.Right() >= aDrawRect.Left())
686 5 : pContentDev->DrawRect( aDrawRect );
687 : }
688 13 : if ( nY2==MAXROW )
689 : {
690 8 : Rectangle aDrawRect( aPixRect );
691 8 : aDrawRect.Top() = nScrY + aOutputData.GetScrH();
692 8 : if ( nX2==MAXCOL )
693 : {
694 : // no double painting of the corner
695 0 : if ( bLayoutRTL )
696 0 : aDrawRect.Left() = nScrX;
697 : else
698 0 : aDrawRect.Right() = nScrX + aOutputData.GetScrW() - 1;
699 : }
700 8 : if (aDrawRect.Bottom() >= aDrawRect.Top())
701 8 : pContentDev->DrawRect( aDrawRect );
702 : }
703 :
704 : // restore MapMode
705 13 : pContentDev->SetMapMode(aCurrentMapMode);
706 : }
707 :
708 2964 : if ( rDoc.HasBackgroundDraw( nTab, aDrawingRectLogic ) )
709 : {
710 0 : pContentDev->SetMapMode(MAP_PIXEL);
711 0 : aOutputData.DrawClear();
712 :
713 : // Drawing Hintergrund
714 :
715 0 : pContentDev->SetMapMode(aDrawMode);
716 0 : DrawRedraw( aOutputData, eMode, SC_LAYER_BACK );
717 : }
718 : else
719 2964 : aOutputData.SetSolidBackground(true);
720 :
721 2964 : aOutputData.DrawDocumentBackground();
722 :
723 2964 : if ( bGridFirst && ( bGrid || bPage ) )
724 2964 : aOutputData.DrawGrid(*pContentDev, bGrid, bPage);
725 :
726 5928 : MapMode aPrevMapMode = pContentDev->GetMapMode();
727 2964 : pContentDev->SetMapMode(MAP_PIXEL);
728 :
729 2964 : aOutputData.DrawBackground();
730 :
731 2964 : pContentDev->SetMapMode(aPrevMapMode);
732 :
733 2964 : if ( !bGridFirst && ( bGrid || bPage ) )
734 0 : aOutputData.DrawGrid(*pContentDev, bGrid, bPage);
735 :
736 2964 : pContentDev->SetMapMode(MAP_PIXEL);
737 :
738 2964 : if ( bPageMode )
739 : {
740 : // DrawPagePreview draws complete lines/page numbers, must always be clipped
741 0 : if ( aOutputData.SetChangedClip() )
742 : {
743 0 : DrawPagePreview(nX1,nY1,nX2,nY2, pContentDev);
744 0 : pContentDev->SetClipRegion();
745 : }
746 : }
747 :
748 2964 : aOutputData.DrawShadow();
749 2964 : aOutputData.DrawFrame();
750 :
751 : // Show Note Mark
752 2964 : if ( rOpts.GetOption( VOPT_NOTES ) )
753 2964 : aOutputData.DrawNoteMarks();
754 :
755 2964 : if ( !bLogicText )
756 2937 : aOutputData.DrawStrings(false); // in pixel MapMode
757 :
758 : // edit cells and printer-metrics text must be before the buttons
759 : // (DataPilot buttons contain labels in UI font)
760 :
761 2964 : pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich));
762 2964 : if ( bLogicText )
763 27 : aOutputData.DrawStrings(true); // in logic MapMode if bLogicText is set
764 2964 : aOutputData.DrawEdit(true);
765 :
766 : // the buttons are painted in absolute coordinates
767 2964 : if (bIsTiledRendering)
768 : {
769 : // Tiled offset nScrX, nScrY
770 0 : MapMode aMap( MAP_PIXEL );
771 0 : aMap.SetOrigin(Point(nScrX, nScrY));
772 0 : pContentDev->SetMapMode(aMap);
773 : }
774 : else
775 2964 : pContentDev->SetMapMode(MAP_PIXEL);
776 :
777 : // Autofilter- und Pivot-Buttons
778 :
779 2964 : DrawButtons(nX1, nX2, rTableInfo, pContentDev); // Pixel
780 :
781 2964 : pContentDev->SetMapMode(MAP_PIXEL);
782 :
783 2964 : aOutputData.DrawClipMarks();
784 :
785 : // Szenario / ChangeTracking muss auf jeden Fall nach DrawGrid sein, auch bei !bGridFirst
786 :
787 : //! Test, ob ChangeTrack-Anzeige aktiv ist
788 : //! Szenario-Rahmen per View-Optionen abschaltbar?
789 :
790 2964 : SCTAB nTabCount = rDoc.GetTableCount();
791 2964 : const std::vector<ScHighlightEntry> &rHigh = pViewData->GetView()->GetHighlightRanges();
792 2964 : bool bHasScenario = ( nTab+1<nTabCount && rDoc.IsScenario(nTab+1) && !rDoc.IsScenario(nTab) );
793 2964 : bool bHasChange = ( rDoc.GetChangeTrack() != NULL );
794 :
795 2964 : if ( bHasChange || bHasScenario || !rHigh.empty() )
796 : {
797 :
798 : //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!)
799 :
800 16 : bool bAny = true;
801 16 : if (eMode == SC_UPDATE_CHANGED)
802 0 : bAny = aOutputData.SetChangedClip();
803 16 : if (bAny)
804 : {
805 16 : if ( bHasChange )
806 15 : aOutputData.DrawChangeTrack();
807 :
808 16 : if ( bHasScenario )
809 1 : lcl_DrawScenarioFrames( pContentDev, pViewData, eWhich, nX1,nY1,nX2,nY2 );
810 :
811 16 : lcl_DrawHighlight( aOutputData, pViewData, rHigh );
812 :
813 16 : if (eMode == SC_UPDATE_CHANGED)
814 0 : pContentDev->SetClipRegion();
815 : }
816 : }
817 :
818 : // Drawing Vordergrund
819 :
820 2964 : pContentDev->SetMapMode(aDrawMode);
821 :
822 2964 : DrawRedraw( aOutputData, eMode, SC_LAYER_FRONT );
823 2964 : DrawRedraw( aOutputData, eMode, SC_LAYER_INTERN );
824 2964 : DrawSdrGrid( aDrawingRectLogic, pContentDev );
825 :
826 2964 : if (!bIsInScroll) // Drawing Markierungen
827 : {
828 2866 : if(eMode == SC_UPDATE_CHANGED && aOutputData.SetChangedClip())
829 : {
830 0 : pContentDev->SetClipRegion();
831 : }
832 : }
833 :
834 2964 : pContentDev->SetMapMode(MAP_PIXEL);
835 :
836 2964 : if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() )
837 : {
838 0 : Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor );
839 0 : aOutputData.DrawRefMark( pViewData->GetRefStartX(), pViewData->GetRefStartY(),
840 0 : pViewData->GetRefEndX(), pViewData->GetRefEndY(),
841 0 : aRefColor, false );
842 : }
843 :
844 : // Range-Finder
845 :
846 2964 : ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
847 2964 : if (pHdl)
848 : {
849 2964 : ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
850 8892 : if ( pRangeFinder && !pRangeFinder->IsHidden() &&
851 2964 : pRangeFinder->GetDocName() == pDocSh->GetTitle() )
852 : {
853 0 : sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
854 0 : for (sal_uInt16 i=0; i<nCount; i++)
855 : {
856 0 : ScRangeFindData* pData = pRangeFinder->GetObject(i);
857 :
858 0 : ScRange aRef = pData->aRef;
859 0 : aRef.Justify();
860 0 : if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab )
861 0 : aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(),
862 0 : aRef.aEnd.Col(), aRef.aEnd.Row(),
863 : Color( pData->nColorData ),
864 0 : true );
865 : }
866 : }
867 : }
868 :
869 : {
870 : // end redraw
871 2964 : ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
872 :
873 2964 : if(pTabViewShell)
874 : {
875 2964 : MapMode aCurrentMapMode(pContentDev->GetMapMode());
876 2964 : pContentDev->SetMapMode(aDrawMode);
877 2964 : SdrView* pDrawView = pTabViewShell->GetSdrView();
878 :
879 2964 : if(pDrawView)
880 : {
881 : // #i74769# work with SdrPaintWindow directly
882 2964 : pDrawView->EndDrawLayers(*pTargetPaintWindow, true);
883 : }
884 :
885 2964 : pContentDev->SetMapMode(aCurrentMapMode);
886 : }
887 : }
888 :
889 : // In-place editing - when the user is typing, we need to paint the text
890 : // using the editeng.
891 : // It's being done after EndDrawLayers() to get it outside the overlay
892 : // buffer and on top of everything.
893 2964 : if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
894 : {
895 : // get the coordinates of the area we need to clear (overpaint by
896 : // the background)
897 0 : SCCOL nCol1 = pViewData->GetEditStartCol();
898 0 : SCROW nRow1 = pViewData->GetEditStartRow();
899 0 : SCCOL nCol2 = pViewData->GetEditEndCol();
900 0 : SCROW nRow2 = pViewData->GetEditEndRow();
901 0 : rDevice.SetLineColor();
902 0 : rDevice.SetFillColor(pEditView->GetBackgroundColor());
903 0 : Point aStart = pViewData->GetScrPos( nCol1, nRow1, eWhich );
904 0 : Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eWhich );
905 :
906 : // don't overwrite grid
907 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
908 0 : aEnd.X() -= 2 * nLayoutSign;
909 0 : aEnd.Y() -= 2;
910 :
911 : // set the correct mapmode
912 0 : Rectangle aBackground(aStart, aEnd);
913 0 : if (bIsTiledRendering)
914 : {
915 0 : aBackground += Point(nScrX, nScrY);
916 0 : rDevice.SetMapMode(aDrawMode);
917 : }
918 : else
919 0 : rDevice.SetMapMode(pViewData->GetLogicMode());
920 :
921 : // paint the background
922 0 : rDevice.DrawRect(rDevice.PixelToLogic(aBackground));
923 :
924 : // paint the editeng text
925 0 : pEditView->Paint(rDevice.PixelToLogic(Rectangle(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()))), &rDevice);
926 0 : rDevice.SetMapMode(MAP_PIXEL);
927 : }
928 :
929 2964 : if (pViewData->HasEditView(eWhich))
930 : {
931 : // flush OverlayManager before changing the MapMode
932 0 : flushOverlayManager();
933 :
934 : // set MapMode for text edit
935 0 : rDevice.SetMapMode(pViewData->GetLogicMode());
936 : }
937 : else
938 2964 : rDevice.SetMapMode(aDrawMode);
939 :
940 2964 : if (mpNoteMarker)
941 2964 : mpNoteMarker->Draw(); // ueber den Cursor, im Drawing-MapMode
942 2964 : }
943 :
944 0 : void ScGridWindow::PaintTile( VirtualDevice& rDevice,
945 : int nOutputWidth, int nOutputHeight,
946 : int nTilePosX, int nTilePosY,
947 : long nTileWidth, long nTileHeight )
948 : {
949 : // Output size is in pixels while tile position and size are in logical units (twips).
950 :
951 : // Assumption: always paint the whole sheet i.e. "visible" range is always
952 : // from (0,0) to last data position.
953 :
954 : // Tile geometry is independent of the zoom level, but the output size is
955 : // dependent of the zoom level. Determine the correct zoom level before
956 : // we start.
957 :
958 : // FIXME the painting works using a mixture of drawing with coordinates in
959 : // pixels and in logic coordinates; it should be cleaned up to use logic
960 : // coords only, and avoid all the SetMapMode()'s.
961 : // Similarly to Writer, we should set the mapmode once on the rDevice, and
962 : // not care about any zoom settings.
963 :
964 0 : Fraction aFracX(long(nOutputWidth * TWIPS_PER_PIXEL), nTileWidth);
965 0 : Fraction aFracY(long(nOutputHeight * TWIPS_PER_PIXEL), nTileHeight);
966 :
967 : // page break zoom, and aLogicMode in ScViewData
968 0 : pViewData->SetZoom(aFracX, aFracY, true);
969 :
970 0 : double fTilePosXPixel = static_cast<double>(nTilePosX) * nOutputWidth / nTileWidth;
971 0 : double fTilePosYPixel = static_cast<double>(nTilePosY) * nOutputHeight / nTileHeight;
972 :
973 0 : SCTAB nTab = pViewData->GetTabNo();
974 0 : ScDocument* pDoc = pViewData->GetDocument();
975 :
976 0 : SCCOL nStartCol = 0, nEndCol = 0;
977 0 : SCROW nStartRow = 0, nEndRow = 0;
978 :
979 : // size of the document including drawings, charts, etc.
980 0 : pDoc->GetPrintArea(nTab, nEndCol, nEndRow, false);
981 :
982 0 : double fPPTX = pViewData->GetPPTX();
983 0 : double fPPTY = pViewData->GetPPTY();
984 :
985 0 : ScTableInfo aTabInfo;
986 0 : pDoc->FillInfo(aTabInfo, nStartCol, nStartRow, nEndCol, nEndRow, nTab, fPPTX, fPPTY, false, false, NULL);
987 :
988 : ScOutputData aOutputData(&rDevice, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
989 : -fTilePosXPixel, -fTilePosYPixel, nStartCol, nStartRow, nEndCol, nEndRow,
990 0 : fPPTX, fPPTY);
991 :
992 : // setup the SdrPage so that drawinglayer works correctly
993 0 : ScDrawLayer* pModel = pDoc->GetDrawLayer();
994 0 : boost::scoped_ptr<FmFormView> pDrawView;
995 0 : if (pModel)
996 : {
997 0 : pDrawView.reset(new FmFormView(pModel, &rDevice));
998 0 : pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
999 0 : aOutputData.SetDrawView( pDrawView.get() );
1000 : }
1001 :
1002 : // draw the content
1003 0 : DrawContent(rDevice, aTabInfo, aOutputData, true, SC_UPDATE_ALL);
1004 0 : }
1005 :
1006 7486 : void ScGridWindow::LogicInvalidate(const Rectangle* pRectangle)
1007 : {
1008 7486 : OString sRectangle;
1009 7486 : if (!pRectangle)
1010 1094 : sRectangle = "EMPTY";
1011 : else
1012 : {
1013 6392 : Rectangle aRectangle(*pRectangle);
1014 : // When dragging shapes the map mode is disabled.
1015 6392 : if (IsMapModeEnabled())
1016 : {
1017 5310 : if (GetMapMode().GetMapUnit() == MAP_100TH_MM)
1018 5310 : aRectangle = OutputDevice::LogicToLogic(aRectangle, MAP_100TH_MM, MAP_TWIP);
1019 : }
1020 : else
1021 1082 : aRectangle = PixelToLogic(aRectangle, MapMode(MAP_TWIP));
1022 6392 : sRectangle = aRectangle.toString();
1023 : }
1024 :
1025 7486 : pViewData->GetDocument()->GetDrawLayer()->libreOfficeKitCallback(LOK_CALLBACK_INVALIDATE_TILES, sRectangle.getStr());
1026 7486 : }
1027 :
1028 0 : void ScGridWindow::SetCellSelectionPixel(int nType, int nPixelX, int nPixelY)
1029 : {
1030 0 : ScTabView* pTabView = pViewData->GetView();
1031 0 : ScTabViewShell* pViewShell = pViewData->GetViewShell();
1032 0 : ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewShell);
1033 :
1034 0 : if (pInputHandler && pInputHandler->IsInputMode())
1035 : {
1036 : // we need to switch off the editeng
1037 0 : ScTabView::UpdateInputLine();
1038 0 : pViewShell->UpdateInputHandler();
1039 : }
1040 :
1041 0 : if (nType == LOK_SETTEXTSELECTION_RESET)
1042 : {
1043 0 : pTabView->DoneBlockMode();
1044 0 : return;
1045 : }
1046 :
1047 : // obtain the current selection
1048 0 : ScRangeList aRangeList = pViewData->GetMarkData().GetMarkedRanges();
1049 :
1050 : SCCOL nCol1, nCol2;
1051 : SCROW nRow1, nRow2;
1052 : SCTAB nTab1, nTab2;
1053 :
1054 0 : bool bWasEmpty = false;
1055 0 : if (aRangeList.empty())
1056 : {
1057 0 : nCol1 = nCol2 = pViewData->GetCurX();
1058 0 : nRow1 = nRow2 = pViewData->GetCurY();
1059 0 : bWasEmpty = true;
1060 : }
1061 : else
1062 0 : aRangeList.Combine().GetVars(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1063 :
1064 : // convert the coordinates to column/row
1065 : SCsCOL nNewPosX;
1066 : SCsROW nNewPosY;
1067 0 : SCTAB nTab = pViewData->GetTabNo();
1068 0 : pViewData->GetPosFromPixel(nPixelX, nPixelY, eWhich, nNewPosX, nNewPosY);
1069 :
1070 : // change the selection
1071 0 : switch (nType)
1072 : {
1073 : case LOK_SETTEXTSELECTION_START:
1074 0 : if (nNewPosX != nCol1 || nNewPosY != nRow1 || bWasEmpty)
1075 : {
1076 0 : pTabView->SetCursor(nNewPosX, nNewPosY);
1077 0 : pTabView->DoneBlockMode();
1078 0 : pTabView->InitBlockMode(nNewPosX, nNewPosY, nTab, true);
1079 0 : pTabView->MarkCursor(nCol2, nRow2, nTab);
1080 : }
1081 0 : break;
1082 : case LOK_SETTEXTSELECTION_END:
1083 0 : if (nNewPosX != nCol2 || nNewPosY != nRow2 || bWasEmpty)
1084 : {
1085 0 : pTabView->SetCursor(nCol1, nRow1);
1086 0 : pTabView->DoneBlockMode();
1087 0 : pTabView->InitBlockMode(nCol1, nRow1, nTab, true);
1088 0 : pTabView->MarkCursor(nNewPosX, nNewPosY, nTab);
1089 : }
1090 0 : break;
1091 : default:
1092 : assert(false);
1093 0 : break;
1094 0 : }
1095 : }
1096 :
1097 12914 : void ScGridWindow::CheckNeedsRepaint()
1098 : {
1099 : // called at the end of painting, and from timer after background text width calculation
1100 :
1101 12914 : if (bNeedsRepaint)
1102 : {
1103 0 : bNeedsRepaint = false;
1104 0 : if (aRepaintPixel.IsEmpty())
1105 0 : Invalidate();
1106 : else
1107 0 : Invalidate(PixelToLogic(aRepaintPixel));
1108 0 : aRepaintPixel = Rectangle();
1109 :
1110 : // selection function in status bar might also be invalid
1111 0 : SfxBindings& rBindings = pViewData->GetBindings();
1112 0 : rBindings.Invalidate( SID_STATUS_SUM );
1113 0 : rBindings.Invalidate( SID_ATTR_SIZE );
1114 0 : rBindings.Invalidate( SID_TABLE_CELL );
1115 : }
1116 12914 : }
1117 :
1118 0 : void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev )
1119 : {
1120 0 : ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData();
1121 0 : if (pPageData)
1122 : {
1123 0 : ScDocument* pDoc = pViewData->GetDocument();
1124 0 : SCTAB nTab = pViewData->GetTabNo();
1125 0 : Size aWinSize = GetOutputSizePixel();
1126 0 : const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
1127 0 : Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor );
1128 0 : Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor );
1129 :
1130 0 : OUString aPageStr = ScGlobal::GetRscString( STR_PGNUM );
1131 0 : if ( nPageScript == SvtScriptType::NONE )
1132 : {
1133 : // get script type of translated "Page" string only once
1134 0 : nPageScript = pDoc->GetStringScriptType( aPageStr );
1135 0 : if (nPageScript == SvtScriptType::NONE)
1136 0 : nPageScript = ScGlobal::GetDefaultScriptType();
1137 : }
1138 :
1139 0 : vcl::Font aFont;
1140 0 : std::unique_ptr<ScEditEngineDefaulter> pEditEng;
1141 0 : const ScPatternAttr& rDefPattern = static_cast<const ScPatternAttr&>(pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN));
1142 0 : if ( nPageScript == SvtScriptType::LATIN )
1143 : {
1144 : // use single font and call DrawText directly
1145 0 : rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK );
1146 0 : aFont.SetColor( Color( COL_LIGHTGRAY ) );
1147 : // font size is set as needed
1148 : }
1149 : else
1150 : {
1151 : // use EditEngine to draw mixed-script string
1152 0 : pEditEng.reset(new ScEditEngineDefaulter( EditEngine::CreatePool(), true ));
1153 0 : pEditEng->SetRefMapMode( pContentDev->GetMapMode() );
1154 0 : SfxItemSet* pEditDefaults = new SfxItemSet( pEditEng->GetEmptyItemSet() );
1155 0 : rDefPattern.FillEditItemSet( pEditDefaults );
1156 0 : pEditDefaults->Put( SvxColorItem( Color( COL_LIGHTGRAY ), EE_CHAR_COLOR ) );
1157 0 : pEditEng->SetDefaults( pEditDefaults );
1158 : }
1159 :
1160 0 : sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
1161 0 : for (sal_uInt16 nPos=0; nPos<nCount; nPos++)
1162 : {
1163 0 : ScPrintRangeData& rData = pPageData->GetData(nPos);
1164 0 : ScRange aRange = rData.GetPrintRange();
1165 0 : if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 &&
1166 0 : aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 )
1167 : {
1168 : // 3 Pixel Rahmen um den Druckbereich
1169 : // (mittlerer Pixel auf den Gitterlinien)
1170 :
1171 0 : pContentDev->SetLineColor();
1172 0 : if (rData.IsAutomatic())
1173 0 : pContentDev->SetFillColor( aAutomatic );
1174 : else
1175 0 : pContentDev->SetFillColor( aManual );
1176 :
1177 : Point aStart = pViewData->GetScrPos(
1178 0 : aRange.aStart.Col(), aRange.aStart.Row(), eWhich, true );
1179 : Point aEnd = pViewData->GetScrPos(
1180 0 : aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, true );
1181 0 : aStart.X() -= 2;
1182 0 : aStart.Y() -= 2;
1183 :
1184 : // Ueberlaeufe verhindern:
1185 0 : if ( aStart.X() < -10 ) aStart.X() = -10;
1186 0 : if ( aStart.Y() < -10 ) aStart.Y() = -10;
1187 0 : if ( aEnd.X() > aWinSize.Width() + 10 )
1188 0 : aEnd.X() = aWinSize.Width() + 10;
1189 0 : if ( aEnd.Y() > aWinSize.Height() + 10 )
1190 0 : aEnd.Y() = aWinSize.Height() + 10;
1191 :
1192 0 : pContentDev->DrawRect( Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) );
1193 0 : pContentDev->DrawRect( Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) );
1194 0 : pContentDev->DrawRect( Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) );
1195 0 : pContentDev->DrawRect( Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) );
1196 :
1197 : // Seitenumbrueche
1198 : //! anders darstellen (gestrichelt ????)
1199 :
1200 0 : size_t nColBreaks = rData.GetPagesX();
1201 0 : const SCCOL* pColEnd = rData.GetPageEndX();
1202 : size_t nColPos;
1203 0 : for (nColPos=0; nColPos+1<nColBreaks; nColPos++)
1204 : {
1205 0 : SCCOL nBreak = pColEnd[nColPos]+1;
1206 0 : if ( nBreak >= nX1 && nBreak <= nX2+1 )
1207 : {
1208 : //! hidden suchen
1209 0 : if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL)
1210 0 : pContentDev->SetFillColor( aManual );
1211 : else
1212 0 : pContentDev->SetFillColor( aAutomatic );
1213 : Point aBreak = pViewData->GetScrPos(
1214 0 : nBreak, aRange.aStart.Row(), eWhich, true );
1215 0 : pContentDev->DrawRect( Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) );
1216 : }
1217 : }
1218 :
1219 0 : size_t nRowBreaks = rData.GetPagesY();
1220 0 : const SCROW* pRowEnd = rData.GetPageEndY();
1221 : size_t nRowPos;
1222 0 : for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++)
1223 : {
1224 0 : SCROW nBreak = pRowEnd[nRowPos]+1;
1225 0 : if ( nBreak >= nY1 && nBreak <= nY2+1 )
1226 : {
1227 : //! hidden suchen
1228 0 : if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL)
1229 0 : pContentDev->SetFillColor( aManual );
1230 : else
1231 0 : pContentDev->SetFillColor( aAutomatic );
1232 : Point aBreak = pViewData->GetScrPos(
1233 0 : aRange.aStart.Col(), nBreak, eWhich, true );
1234 0 : pContentDev->DrawRect( Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) );
1235 : }
1236 : }
1237 :
1238 : // Seitenzahlen
1239 :
1240 0 : SCROW nPrStartY = aRange.aStart.Row();
1241 0 : for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++)
1242 : {
1243 0 : SCROW nPrEndY = pRowEnd[nRowPos];
1244 0 : if ( nPrEndY >= nY1 && nPrStartY <= nY2 )
1245 : {
1246 0 : SCCOL nPrStartX = aRange.aStart.Col();
1247 0 : for (nColPos=0; nColPos<nColBreaks; nColPos++)
1248 : {
1249 0 : SCCOL nPrEndX = pColEnd[nColPos];
1250 0 : if ( nPrEndX >= nX1 && nPrStartX <= nX2 )
1251 : {
1252 : Point aPageStart = pViewData->GetScrPos(
1253 0 : nPrStartX, nPrStartY, eWhich, true );
1254 : Point aPageEnd = pViewData->GetScrPos(
1255 0 : nPrEndX+1,nPrEndY+1, eWhich, true );
1256 :
1257 0 : long nPageNo = rData.GetFirstPage();
1258 0 : if ( rData.IsTopDown() )
1259 0 : nPageNo += ((long)nColPos)*nRowBreaks+nRowPos;
1260 : else
1261 0 : nPageNo += ((long)nRowPos)*nColBreaks+nColPos;
1262 :
1263 0 : OUString aThisPageStr = OUString(aPageStr).replaceFirst("%1", OUString::number(nPageNo));
1264 :
1265 0 : if ( pEditEng )
1266 : {
1267 : // find right font size with EditEngine
1268 0 : long nHeight = 100;
1269 0 : pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1270 0 : pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1271 0 : pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1272 0 : pEditEng->SetText( aThisPageStr );
1273 0 : Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1274 :
1275 : // 40% of width or 60% of height
1276 0 : long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1277 0 : long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1278 0 : nHeight = std::min(nSizeX,nSizeY);
1279 0 : pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
1280 0 : pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
1281 0 : pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
1282 :
1283 : // centered output with EditEngine
1284 0 : Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() );
1285 0 : Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1286 0 : (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1287 0 : pEditEng->Draw( pContentDev, aPos );
1288 : }
1289 : else
1290 : {
1291 : // find right font size for DrawText
1292 0 : aFont.SetSize( Size( 0,100 ) );
1293 0 : pContentDev->SetFont( aFont );
1294 0 : Size aSize100( pContentDev->GetTextWidth( aThisPageStr ), pContentDev->GetTextHeight() );
1295 :
1296 : // 40% of width or 60% of height
1297 0 : long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width();
1298 0 : long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height();
1299 0 : aFont.SetSize( Size( 0,std::min(nSizeX,nSizeY) ) );
1300 0 : pContentDev->SetFont( aFont );
1301 :
1302 : // centered output with DrawText
1303 0 : Size aTextSize( pContentDev->GetTextWidth( aThisPageStr ), pContentDev->GetTextHeight() );
1304 0 : Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2,
1305 0 : (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 );
1306 0 : pContentDev->DrawText( aPos, aThisPageStr );
1307 0 : }
1308 : }
1309 0 : nPrStartX = nPrEndX + 1;
1310 : }
1311 : }
1312 0 : nPrStartY = nPrEndY + 1;
1313 : }
1314 : }
1315 0 : }
1316 : }
1317 0 : }
1318 :
1319 2964 : void ScGridWindow::DrawButtons(SCCOL nX1, SCCOL nX2, const ScTableInfo& rTabInfo, OutputDevice* pContentDev)
1320 : {
1321 2964 : aComboButton.SetOutputDevice( pContentDev );
1322 :
1323 2964 : ScDocument* pDoc = pViewData->GetDocument();
1324 2964 : ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc);
1325 :
1326 : SCCOL nCol;
1327 : SCROW nRow;
1328 : SCSIZE nArrY;
1329 : SCSIZE nQuery;
1330 2964 : SCTAB nTab = pViewData->GetTabNo();
1331 2964 : ScDBData* pDBData = NULL;
1332 5928 : std::unique_ptr<ScQueryParam> pQueryParam;
1333 :
1334 2964 : RowInfo* pRowInfo = rTabInfo.mpRowInfo;
1335 2964 : sal_uInt16 nArrCount = rTabInfo.mnArrCount;
1336 :
1337 2964 : bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1338 :
1339 2964 : Point aOldPos = aComboButton.GetPosPixel(); // Zustand fuer MouseDown/Up
1340 2964 : Size aOldSize = aComboButton.GetSizePixel(); // merken
1341 :
1342 25913 : for (nArrY=1; nArrY+1<nArrCount; nArrY++)
1343 : {
1344 22949 : if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged )
1345 : {
1346 9 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1347 :
1348 9 : nRow = pThisRowInfo->nRowNo;
1349 :
1350 104 : for (nCol=nX1; nCol<=nX2; nCol++)
1351 : {
1352 95 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1353 : //if several columns merged on a row, there should be only one auto button at the end of the columns.
1354 : //if several rows merged on a column, the button may be in the middle, so "!pInfo->bVOverlapped" should not be used
1355 95 : if ( pInfo->bAutoFilter && !pInfo->bHOverlapped )
1356 : {
1357 30 : if (!pQueryParam)
1358 9 : pQueryParam.reset(new ScQueryParam);
1359 :
1360 30 : bool bNewData = true;
1361 30 : if (pDBData)
1362 : {
1363 : SCCOL nStartCol;
1364 : SCROW nStartRow;
1365 : SCCOL nEndCol;
1366 : SCROW nEndRow;
1367 : SCTAB nAreaTab;
1368 21 : pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1369 42 : if ( nCol >= nStartCol && nCol <= nEndCol &&
1370 42 : nRow >= nStartRow && nRow <= nEndRow )
1371 21 : bNewData = false;
1372 : }
1373 30 : if (bNewData)
1374 : {
1375 9 : pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1376 9 : if (pDBData)
1377 9 : pDBData->GetQueryParam( *pQueryParam );
1378 : else
1379 : {
1380 : // can also be part of DataPilot table
1381 : // OSL_FAIL("Auto-Filter-Button ohne DBData");
1382 : }
1383 : }
1384 :
1385 : // pQueryParam kann nur MAXQUERY Eintraege enthalten
1386 :
1387 30 : bool bSimpleQuery = true;
1388 30 : bool bColumnFound = false;
1389 30 : if (!pQueryParam->bInplace)
1390 0 : bSimpleQuery = false;
1391 30 : SCSIZE nCount = pQueryParam->GetEntryCount();
1392 246 : for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery)
1393 216 : if (pQueryParam->GetEntry(nQuery).bDoQuery)
1394 : {
1395 : // hier nicht auf EQUAL beschraenken
1396 : // (auch bei ">1" soll der Spaltenkopf blau werden)
1397 :
1398 28 : if (pQueryParam->GetEntry(nQuery).nField == nCol)
1399 7 : bColumnFound = true;
1400 28 : if (nQuery > 0)
1401 4 : if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND)
1402 4 : bSimpleQuery = false;
1403 : }
1404 :
1405 30 : bool bArrowState = bSimpleQuery && bColumnFound;
1406 : long nSizeX;
1407 : long nSizeY;
1408 30 : SCCOL nStartCol= nCol;
1409 30 : SCROW nStartRow = nRow;
1410 : //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.
1411 : //should first get the start pos of the merge area, then get the nSizeX through the start pos.
1412 30 : pDoc->ExtendOverlapped(nStartCol, nStartRow,nCol, nRow, nTab);//get nStartCol,nStartRow
1413 30 : pViewData->GetMergeSizePixel( nStartCol, nStartRow, nSizeX, nSizeY );//get nSizeX
1414 30 : nSizeY = ScViewData::ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
1415 30 : Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1416 :
1417 30 : aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1), bLayoutRTL);
1418 30 : aCellBtn.setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL
1419 30 : aCellBtn.setDrawBaseButton(false);
1420 30 : aCellBtn.setDrawPopupButton(true);
1421 30 : aCellBtn.setHasHiddenMember(bArrowState);
1422 30 : aCellBtn.draw();
1423 : }
1424 : }
1425 : }
1426 :
1427 22949 : if ( pRowInfo[nArrY].bPivotButton && pRowInfo[nArrY].bChanged )
1428 : {
1429 76 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1430 76 : nRow = pThisRowInfo->nRowNo;
1431 760 : for (nCol=nX1; nCol<=nX2; nCol++)
1432 : {
1433 684 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1];
1434 684 : if (pInfo->bHOverlapped || pInfo->bVOverlapped)
1435 0 : continue;
1436 :
1437 684 : Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1438 : long nSizeX;
1439 : long nSizeY;
1440 684 : pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1441 684 : long nPosX = aScrPos.X();
1442 684 : long nPosY = aScrPos.Y();
1443 : // bLayoutRTL is handled in setBoundingBox
1444 :
1445 684 : OUString aStr = pDoc->GetString(nCol, nRow, nTab);
1446 684 : aCellBtn.setText(aStr);
1447 684 : aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1), bLayoutRTL);
1448 684 : aCellBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now
1449 684 : aCellBtn.setDrawBaseButton(pInfo->bPivotButton);
1450 684 : aCellBtn.setDrawPopupButton(pInfo->bPivotPopupButton);
1451 684 : aCellBtn.setHasHiddenMember(pInfo->bFilterActive);
1452 684 : aCellBtn.draw();
1453 684 : }
1454 : }
1455 :
1456 22949 : if ( bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged )
1457 : {
1458 0 : Rectangle aRect = GetListValButtonRect( aListValPos );
1459 0 : aComboButton.SetPosPixel( aRect.TopLeft() );
1460 0 : aComboButton.SetSizePixel( aRect.GetSize() );
1461 0 : pContentDev->SetClipRegion(vcl::Region(aRect));
1462 0 : aComboButton.Draw( false, false );
1463 0 : pContentDev->SetClipRegion(); // always called from Draw() without clip region
1464 0 : aComboButton.SetPosPixel( aOldPos ); // restore old state
1465 0 : aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter)
1466 : }
1467 : }
1468 :
1469 2964 : pQueryParam.reset();
1470 5928 : aComboButton.SetOutputDevice( this );
1471 2964 : }
1472 :
1473 0 : Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos )
1474 : {
1475 0 : ScDocument* pDoc = pViewData->GetDocument();
1476 0 : SCTAB nTab = pViewData->GetTabNo();
1477 0 : bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1478 0 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1479 :
1480 0 : ScDDComboBoxButton aButton( this ); // for optimal size
1481 0 : Size aBtnSize = aButton.GetSizePixel();
1482 :
1483 0 : SCCOL nCol = rButtonPos.Col();
1484 0 : SCROW nRow = rButtonPos.Row();
1485 :
1486 : long nCellSizeX; // width of this cell, including merged
1487 : long nDummy;
1488 0 : pViewData->GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy );
1489 :
1490 : // for height, only the cell's row is used, excluding merged cells
1491 0 : long nCellSizeY = ScViewData::ToPixel( pDoc->GetRowHeight( nRow, nTab ), pViewData->GetPPTY() );
1492 0 : long nAvailable = nCellSizeX;
1493 :
1494 : // left edge of next cell if there is a non-hidden next column
1495 0 : SCCOL nNextCol = nCol + 1;
1496 0 : const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE ));
1497 0 : if ( pMerge->GetColMerge() > 1 )
1498 0 : nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area
1499 0 : while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) )
1500 0 : ++nNextCol;
1501 0 : bool bNextCell = ( nNextCol <= MAXCOL );
1502 0 : if ( bNextCell )
1503 0 : nAvailable = ScViewData::ToPixel( pDoc->GetColWidth( nNextCol, nTab ), pViewData->GetPPTX() );
1504 :
1505 0 : if ( nAvailable < aBtnSize.Width() )
1506 0 : aBtnSize.Width() = nAvailable;
1507 0 : if ( nCellSizeY < aBtnSize.Height() )
1508 0 : aBtnSize.Height() = nCellSizeY;
1509 :
1510 0 : Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich, true );
1511 0 : aPos.X() += nCellSizeX * nLayoutSign; // start of next cell
1512 0 : if (!bNextCell)
1513 0 : aPos.X() -= aBtnSize.Width() * nLayoutSign; // right edge of cell if next cell not available
1514 0 : aPos.Y() += nCellSizeY - aBtnSize.Height();
1515 : // X remains at the left edge
1516 :
1517 0 : if ( bLayoutRTL )
1518 0 : aPos.X() -= aBtnSize.Width()-1; // align right edge of button with cell border
1519 :
1520 0 : return Rectangle( aPos, aBtnSize );
1521 : }
1522 :
1523 0 : bool ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab )
1524 : {
1525 0 : ScDocument* pDoc = pViewData->GetDocument();
1526 0 : ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1527 0 : ScQueryParam aQueryParam;
1528 :
1529 0 : if ( pDBData )
1530 0 : pDBData->GetQueryParam( aQueryParam );
1531 : else
1532 : {
1533 : OSL_FAIL("Auto-Filter-Button ohne DBData");
1534 : }
1535 :
1536 0 : bool bSimpleQuery = true;
1537 0 : bool bColumnFound = false;
1538 : SCSIZE nQuery;
1539 :
1540 0 : if ( !aQueryParam.bInplace )
1541 0 : bSimpleQuery = false;
1542 :
1543 : // aQueryParam kann nur MAXQUERY Eintraege enthalten
1544 :
1545 0 : SCSIZE nCount = aQueryParam.GetEntryCount();
1546 0 : for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery)
1547 0 : if ( aQueryParam.GetEntry(nQuery).bDoQuery )
1548 : {
1549 0 : if (aQueryParam.GetEntry(nQuery).nField == nCol)
1550 0 : bColumnFound = true;
1551 :
1552 0 : if (nQuery > 0)
1553 0 : if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND)
1554 0 : bSimpleQuery = false;
1555 : }
1556 :
1557 0 : return ( bSimpleQuery && bColumnFound );
1558 : }
1559 :
1560 2649 : void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects )
1561 : {
1562 2649 : ScMarkData aMultiMark( pViewData->GetMarkData() );
1563 2649 : aMultiMark.SetMarking( false );
1564 2649 : aMultiMark.MarkToMulti();
1565 2649 : ScDocument* pDoc = pViewData->GetDocument();
1566 2649 : SCTAB nTab = pViewData->GetTabNo();
1567 :
1568 2649 : bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1569 2649 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1570 2649 : if ( !aMultiMark.IsMultiMarked() )
1571 2261 : return;
1572 388 : ScRange aMultiRange;
1573 388 : aMultiMark.GetMultiMarkArea( aMultiRange );
1574 388 : SCCOL nX1 = aMultiRange.aStart.Col();
1575 388 : SCROW nY1 = aMultiRange.aStart.Row();
1576 388 : SCCOL nX2 = aMultiRange.aEnd.Col();
1577 388 : SCROW nY2 = aMultiRange.aEnd.Row();
1578 :
1579 388 : PutInOrder( nX1, nX2 );
1580 388 : PutInOrder( nY1, nY2 );
1581 :
1582 388 : bool bTestMerge = true;
1583 388 : bool bRepeat = true;
1584 :
1585 388 : SCCOL nTestX2 = nX2;
1586 388 : SCROW nTestY2 = nY2;
1587 388 : if (bTestMerge)
1588 388 : pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab );
1589 :
1590 388 : SCCOL nPosX = pViewData->GetPosX( eHWhich );
1591 388 : SCROW nPosY = pViewData->GetPosY( eVWhich );
1592 : // is the selection visible at all?
1593 388 : if (nTestX2 < nPosX || nTestY2 < nPosY)
1594 40 : return;
1595 348 : SCCOL nRealX1 = nX1;
1596 348 : if (nX1 < nPosX)
1597 0 : nX1 = nPosX;
1598 348 : if (nY1 < nPosY)
1599 0 : nY1 = nPosY;
1600 :
1601 348 : if (!pDoc->GetDrawLayer()->isTiledRendering())
1602 : {
1603 : // limit the selection to only what is visible on the screen
1604 348 : SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
1605 348 : if (nXRight > MAXCOL)
1606 0 : nXRight = MAXCOL;
1607 :
1608 348 : SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
1609 348 : if (nYBottom > MAXROW)
1610 0 : nYBottom = MAXROW;
1611 :
1612 : // is the selection visible at all?
1613 348 : if (nX1 > nXRight || nY1 > nYBottom)
1614 11 : return;
1615 :
1616 337 : if (nX2 > nXRight)
1617 9 : nX2 = nXRight;
1618 337 : if (nY2 > nYBottom)
1619 10 : nY2 = nYBottom;
1620 : }
1621 :
1622 337 : double nPPTX = pViewData->GetPPTX();
1623 337 : double nPPTY = pViewData->GetPPTY();
1624 :
1625 674 : ScInvertMerger aInvert( &rPixelRects );
1626 :
1627 337 : Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
1628 337 : long nScrY = aScrPos.Y();
1629 337 : bool bWasHidden = false;
1630 983 : for (SCROW nY=nY1; nY<=nY2; nY++)
1631 : {
1632 646 : bool bFirstRow = ( nY == nPosY ); // first visible row?
1633 646 : bool bDoHidden = false; // versteckte nachholen ?
1634 646 : sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab );
1635 646 : bool bDoRow = ( nHeightTwips != 0 );
1636 646 : if (bDoRow)
1637 : {
1638 646 : if (bTestMerge)
1639 646 : if (bWasHidden) // auf versteckte zusammengefasste testen
1640 : {
1641 0 : bDoHidden = true;
1642 0 : bDoRow = true;
1643 : }
1644 :
1645 646 : bWasHidden = false;
1646 : }
1647 : else
1648 : {
1649 0 : bWasHidden = true;
1650 0 : if (bTestMerge)
1651 0 : if (nY==nY2)
1652 0 : bDoRow = true; // letzte Zeile aus Block
1653 : }
1654 :
1655 646 : if ( bDoRow )
1656 : {
1657 646 : SCCOL nLoopEndX = nX2;
1658 646 : if (nX2 < nX1) // Rest von zusammengefasst
1659 : {
1660 0 : SCCOL nStartX = nX1;
1661 0 : while ( static_cast<const ScMergeFlagAttr*>(pDoc->
1662 0 : GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() )
1663 0 : --nStartX;
1664 0 : if (nStartX <= nX2)
1665 0 : nLoopEndX = nX1;
1666 : }
1667 :
1668 646 : long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1;
1669 646 : long nScrX = aScrPos.X();
1670 2741 : for (SCCOL nX=nX1; nX<=nLoopEndX; nX++)
1671 : {
1672 2095 : long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX );
1673 2095 : if ( nWidth > 0 )
1674 : {
1675 2095 : long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign;
1676 2095 : if (bTestMerge)
1677 : {
1678 2095 : SCROW nThisY = nY;
1679 2095 : const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab );
1680 : const ScMergeFlagAttr* pMergeFlag = static_cast<const ScMergeFlagAttr*>( &pPattern->
1681 2095 : GetItem(ATTR_MERGE_FLAG) );
1682 2095 : if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) )
1683 : {
1684 0 : while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 &&
1685 0 : (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) )
1686 : {
1687 0 : --nThisY;
1688 0 : pPattern = pDoc->GetPattern( nX, nThisY, nTab );
1689 0 : pMergeFlag = static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem(ATTR_MERGE_FLAG) );
1690 : }
1691 : }
1692 :
1693 : // nur Rest von zusammengefasster zu sehen ?
1694 2095 : SCCOL nThisX = nX;
1695 2095 : if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 )
1696 : {
1697 0 : while ( pMergeFlag->IsHorOverlapped() )
1698 : {
1699 0 : --nThisX;
1700 0 : pPattern = pDoc->GetPattern( nThisX, nThisY, nTab );
1701 0 : pMergeFlag = static_cast<const ScMergeFlagAttr*>( &pPattern->GetItem(ATTR_MERGE_FLAG) );
1702 : }
1703 : }
1704 :
1705 2095 : if ( aMultiMark.IsCellMarked( nThisX, nThisY, true ) == bRepeat )
1706 : {
1707 1639 : if ( !pMergeFlag->IsOverlapped() )
1708 : {
1709 1639 : const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(&pPattern->GetItem(ATTR_MERGE));
1710 1639 : if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0)
1711 : {
1712 : Point aEndPos = pViewData->GetScrPos(
1713 0 : nThisX + pMerge->GetColMerge(),
1714 0 : nThisY + pMerge->GetRowMerge(), eWhich );
1715 0 : if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY )
1716 : {
1717 : aInvert.AddRect( Rectangle( nScrX,nScrY,
1718 0 : aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) );
1719 : }
1720 : }
1721 1639 : else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1722 : {
1723 1639 : aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1724 : }
1725 : }
1726 : }
1727 : }
1728 : else // !bTestMerge
1729 : {
1730 0 : if ( aMultiMark.IsCellMarked( nX, nY, true ) == bRepeat &&
1731 0 : nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY )
1732 : {
1733 0 : aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) );
1734 : }
1735 : }
1736 :
1737 2095 : nScrX = nEndX + nLayoutSign;
1738 : }
1739 : }
1740 646 : nScrY = nEndY + 1;
1741 : }
1742 337 : }
1743 : }
1744 :
1745 26 : void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt )
1746 : {
1747 26 : Window::DataChanged(rDCEvt);
1748 :
1749 104 : if ( (rDCEvt.GetType() == DataChangedEventType::PRINTER) ||
1750 52 : (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
1751 52 : (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1752 130 : (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1753 78 : ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1754 104 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1755 : {
1756 26 : if ( rDCEvt.GetType() == DataChangedEventType::FONTS && eWhich == pViewData->GetActivePart() )
1757 0 : pViewData->GetDocShell()->UpdateFontList();
1758 :
1759 104 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1760 104 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1761 : {
1762 26 : if ( eWhich == pViewData->GetActivePart() ) // only once for the view
1763 : {
1764 26 : ScTabView* pView = pViewData->GetView();
1765 :
1766 : // update scale in case the UI ScreenZoom has changed
1767 26 : ScGlobal::UpdatePPT(this);
1768 26 : pView->RecalcPPT();
1769 :
1770 : // RepeatResize in case scroll bar sizes have changed
1771 26 : pView->RepeatResize();
1772 26 : pView->UpdateAllOverlays();
1773 :
1774 : // invalidate cell attribs in input handler, in case the
1775 : // EditEngine BackgroundColor has to be changed
1776 26 : if ( pViewData->IsActive() )
1777 : {
1778 26 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1779 26 : if (pHdl)
1780 0 : pHdl->ForgetLastPattern();
1781 : }
1782 : }
1783 : }
1784 :
1785 26 : Invalidate();
1786 : }
1787 182 : }
1788 :
1789 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|