File: | home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx |
Warning: | line 970, column 17 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <memory> | ||||||
21 | #include <scitems.hxx> | ||||||
22 | #include <editeng/eeitem.hxx> | ||||||
23 | |||||||
24 | #include <svtools/colorcfg.hxx> | ||||||
25 | #include <editeng/colritem.hxx> | ||||||
26 | #include <editeng/editview.hxx> | ||||||
27 | #include <editeng/fhgtitem.hxx> | ||||||
28 | #include <sfx2/bindings.hxx> | ||||||
29 | #include <sfx2/printer.hxx> | ||||||
30 | #include <vcl/cursor.hxx> | ||||||
31 | #include <vcl/settings.hxx> | ||||||
32 | |||||||
33 | #include <LibreOfficeKit/LibreOfficeKitEnums.h> | ||||||
34 | #include <comphelper/lok.hxx> | ||||||
35 | #include <sfx2/lokhelper.hxx> | ||||||
36 | |||||||
37 | #include <svx/svdview.hxx> | ||||||
38 | #include <svx/svdpagv.hxx> | ||||||
39 | #include <svx/sdrpagewindow.hxx> | ||||||
40 | #include <svx/sdr/contact/objectcontactofpageview.hxx> | ||||||
41 | #include <svx/sdr/contact/viewobjectcontact.hxx> | ||||||
42 | #include <svx/sdr/contact/viewcontact.hxx> | ||||||
43 | #include <tabvwsh.hxx> | ||||||
44 | |||||||
45 | #include <gridwin.hxx> | ||||||
46 | #include <viewdata.hxx> | ||||||
47 | #include <output.hxx> | ||||||
48 | #include <document.hxx> | ||||||
49 | #include <attrib.hxx> | ||||||
50 | #include <patattr.hxx> | ||||||
51 | #include <dbdata.hxx> | ||||||
52 | #include <docoptio.hxx> | ||||||
53 | #include <notemark.hxx> | ||||||
54 | #include <dbfunc.hxx> | ||||||
55 | #include <scmod.hxx> | ||||||
56 | #include <inputhdl.hxx> | ||||||
57 | #include <rfindlst.hxx> | ||||||
58 | #include <hiranges.hxx> | ||||||
59 | #include <pagedata.hxx> | ||||||
60 | #include <docpool.hxx> | ||||||
61 | #include <globstr.hrc> | ||||||
62 | #include <scresid.hxx> | ||||||
63 | #include <docsh.hxx> | ||||||
64 | #include <cbutton.hxx> | ||||||
65 | #include <invmerge.hxx> | ||||||
66 | #include <editutil.hxx> | ||||||
67 | #include <inputopt.hxx> | ||||||
68 | #include <fillinfo.hxx> | ||||||
69 | #include <dpcontrol.hxx> | ||||||
70 | #include <queryparam.hxx> | ||||||
71 | #include <queryentry.hxx> | ||||||
72 | #include <markdata.hxx> | ||||||
73 | #include <sc.hrc> | ||||||
74 | #include <vcl/virdev.hxx> | ||||||
75 | #include <svx/sdrpaintwindow.hxx> | ||||||
76 | #include <drwlayer.hxx> | ||||||
77 | |||||||
78 | static void lcl_LimitRect( tools::Rectangle& rRect, const tools::Rectangle& rVisible ) | ||||||
79 | { | ||||||
80 | if ( rRect.Top() < rVisible.Top()-1 ) rRect.SetTop( rVisible.Top()-1 ); | ||||||
81 | if ( rRect.Bottom() > rVisible.Bottom()+1 ) rRect.SetBottom( rVisible.Bottom()+1 ); | ||||||
82 | |||||||
83 | // The header row must be drawn also when the inner rectangle is not visible, | ||||||
84 | // that is why there is no return value anymore. | ||||||
85 | // When it is far away, then lcl_DrawOneFrame is not even called. | ||||||
86 | } | ||||||
87 | |||||||
88 | static void lcl_DrawOneFrame( vcl::RenderContext* pDev, const tools::Rectangle& rInnerPixel, | ||||||
89 | const OUString& rTitle, const Color& rColor, bool bTextBelow, | ||||||
90 | double nPPTX, double nPPTY, const Fraction& rZoomY, | ||||||
91 | ScDocument& rDoc, ScViewData& rButtonViewData, bool bLayoutRTL ) | ||||||
92 | { | ||||||
93 | // rButtonViewData is only used to set the button size, | ||||||
94 | |||||||
95 | tools::Rectangle aInner = rInnerPixel; | ||||||
96 | if ( bLayoutRTL ) | ||||||
97 | { | ||||||
98 | aInner.SetLeft( rInnerPixel.Right() ); | ||||||
99 | aInner.SetRight( rInnerPixel.Left() ); | ||||||
100 | } | ||||||
101 | |||||||
102 | tools::Rectangle aVisible( Point(0,0), pDev->GetOutputSizePixel() ); | ||||||
103 | lcl_LimitRect( aInner, aVisible ); | ||||||
104 | |||||||
105 | tools::Rectangle aOuter = aInner; | ||||||
106 | long nHor = static_cast<long>( SC_SCENARIO_HSPACE60 * nPPTX ); | ||||||
107 | long nVer = static_cast<long>( SC_SCENARIO_VSPACE50 * nPPTY ); | ||||||
108 | aOuter.AdjustLeft( -nHor ); | ||||||
109 | aOuter.AdjustRight(nHor ); | ||||||
110 | aOuter.AdjustTop( -nVer ); | ||||||
111 | aOuter.AdjustBottom(nVer ); | ||||||
112 | |||||||
113 | // use ScPatternAttr::GetFont only for font size | ||||||
114 | vcl::Font aAttrFont; | ||||||
115 | rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN). | ||||||
116 | GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY); | ||||||
117 | |||||||
118 | // everything else from application font | ||||||
119 | vcl::Font aAppFont = pDev->GetSettings().GetStyleSettings().GetAppFont(); | ||||||
120 | aAppFont.SetFontSize( aAttrFont.GetFontSize() ); | ||||||
121 | |||||||
122 | aAppFont.SetAlignment( ALIGN_TOP ); | ||||||
123 | pDev->SetFont( aAppFont ); | ||||||
124 | |||||||
125 | Size aTextSize( pDev->GetTextWidth( rTitle ), pDev->GetTextHeight() ); | ||||||
126 | |||||||
127 | if ( bTextBelow ) | ||||||
128 | aOuter.AdjustBottom(aTextSize.Height() ); | ||||||
129 | else | ||||||
130 | aOuter.AdjustTop( -(aTextSize.Height()) ); | ||||||
131 | |||||||
132 | pDev->SetLineColor(); | ||||||
133 | pDev->SetFillColor( rColor ); | ||||||
134 | // left, top, right, bottom | ||||||
135 | pDev->DrawRect( tools::Rectangle( aOuter.Left(), aOuter.Top(), aInner.Left(), aOuter.Bottom() ) ); | ||||||
136 | pDev->DrawRect( tools::Rectangle( aOuter.Left(), aOuter.Top(), aOuter.Right(), aInner.Top() ) ); | ||||||
137 | pDev->DrawRect( tools::Rectangle( aInner.Right(), aOuter.Top(), aOuter.Right(), aOuter.Bottom() ) ); | ||||||
138 | pDev->DrawRect( tools::Rectangle( aOuter.Left(), aInner.Bottom(), aOuter.Right(), aOuter.Bottom() ) ); | ||||||
139 | |||||||
140 | long nButtonY = bTextBelow ? aInner.Bottom() : aOuter.Top(); | ||||||
141 | |||||||
142 | ScDDComboBoxButton aComboButton(pDev); | ||||||
143 | aComboButton.SetOptSizePixel(); | ||||||
144 | long nBWidth = long(aComboButton.GetSizePixel().Width() * rZoomY); | ||||||
145 | long nBHeight = nVer + aTextSize.Height() + 1; | ||||||
146 | Size aButSize( nBWidth, nBHeight ); | ||||||
147 | long nButtonPos = bLayoutRTL ? aOuter.Left() : aOuter.Right()-nBWidth+1; | ||||||
148 | aComboButton.Draw( Point(nButtonPos, nButtonY), aButSize ); | ||||||
149 | rButtonViewData.SetScenButSize( aButSize ); | ||||||
150 | |||||||
151 | long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left(); | ||||||
152 | |||||||
153 | bool bWasClip = false; | ||||||
154 | vcl::Region aOldClip; | ||||||
155 | bool bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() ); | ||||||
156 | if ( bClip ) | ||||||
157 | { | ||||||
158 | if (pDev->IsClipRegion()) | ||||||
159 | { | ||||||
160 | bWasClip = true; | ||||||
161 | aOldClip = pDev->GetActiveClipRegion(); | ||||||
162 | } | ||||||
163 | long nClipStartX = bLayoutRTL ? aOuter.Left() + nBWidth : aInner.Left(); | ||||||
164 | long nClipEndX = bLayoutRTL ? aInner.Right() : aOuter.Right() - nBWidth; | ||||||
165 | pDev->SetClipRegion( vcl::Region(tools::Rectangle( nClipStartX, nButtonY + nVer/2, | ||||||
166 | nClipEndX, nButtonY + nVer/2 + aTextSize.Height())) ); | ||||||
167 | } | ||||||
168 | |||||||
169 | pDev->DrawText( Point( nTextStart, nButtonY + nVer/2 ), rTitle ); | ||||||
170 | |||||||
171 | if ( bClip ) | ||||||
172 | { | ||||||
173 | if ( bWasClip ) | ||||||
174 | pDev->SetClipRegion(aOldClip); | ||||||
175 | else | ||||||
176 | pDev->SetClipRegion(); | ||||||
177 | } | ||||||
178 | |||||||
179 | pDev->SetFillColor(); | ||||||
180 | pDev->SetLineColor( COL_BLACK ); | ||||||
181 | pDev->DrawRect( aInner ); | ||||||
182 | pDev->DrawRect( aOuter ); | ||||||
183 | } | ||||||
184 | |||||||
185 | static void lcl_DrawScenarioFrames( OutputDevice* pDev, ScViewData& rViewData, ScSplitPos eWhich, | ||||||
186 | SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) | ||||||
187 | { | ||||||
188 | ScDocument& rDoc = rViewData.GetDocument(); | ||||||
189 | SCTAB nTab = rViewData.GetTabNo(); | ||||||
190 | SCTAB nTabCount = rDoc.GetTableCount(); | ||||||
191 | if ( nTab+1 >= nTabCount || !rDoc.IsScenario(nTab+1) || rDoc.IsScenario(nTab) ) | ||||||
192 | return; | ||||||
193 | |||||||
194 | if ( nX1 > 0 ) --nX1; | ||||||
195 | if ( nY1>=2 ) nY1 -= 2; // Hack: Header row affects two cells | ||||||
196 | else if ( nY1 > 0 ) --nY1; | ||||||
197 | if ( nX2 < rDoc.MaxCol() ) ++nX2; | ||||||
198 | if ( nY2 < rDoc.MaxRow()-1 ) nY2 += 2; // Hack: Header row affects two cells | ||||||
199 | else if ( nY2 < rDoc.MaxRow() ) ++nY2; | ||||||
200 | ScRange aViewRange( nX1,nY1,nTab, nX2,nY2,nTab ); | ||||||
201 | |||||||
202 | //! cache the ranges in table!!!! | ||||||
203 | |||||||
204 | ScMarkData aMarks(rDoc.GetSheetLimits()); | ||||||
205 | for (SCTAB i=nTab+1; i<nTabCount && rDoc.IsScenario(i); i++) | ||||||
206 | rDoc.MarkScenario( i, nTab, aMarks, false, ScScenarioFlags::ShowFrame ); | ||||||
207 | ScRangeListRef xRanges = new ScRangeList; | ||||||
208 | aMarks.FillRangeListWithMarks( xRanges.get(), false ); | ||||||
209 | |||||||
210 | bool bLayoutRTL = rDoc.IsLayoutRTL( nTab ); | ||||||
211 | long nLayoutSign = bLayoutRTL ? -1 : 1; | ||||||
212 | |||||||
213 | for (size_t j = 0, n = xRanges->size(); j < n; ++j) | ||||||
214 | { | ||||||
215 | ScRange aRange = (*xRanges)[j]; | ||||||
216 | // Always extend scenario frame to merged cells where no new non-covered cells | ||||||
217 | // are framed | ||||||
218 | rDoc.ExtendTotalMerge( aRange ); | ||||||
219 | |||||||
220 | //! -> Extend repaint when merging !!! | ||||||
221 | |||||||
222 | if ( aRange.Intersects( aViewRange ) ) //! Space for Text/Button? | ||||||
223 | { | ||||||
224 | Point aStartPos = rViewData.GetScrPos( | ||||||
225 | aRange.aStart.Col(), aRange.aStart.Row(), eWhich, true ); | ||||||
226 | Point aEndPos = rViewData.GetScrPos( | ||||||
227 | aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, true ); | ||||||
228 | // on the grid: | ||||||
229 | aStartPos.AdjustX( -nLayoutSign ); | ||||||
230 | aStartPos.AdjustY( -1 ); | ||||||
231 | aEndPos.AdjustX( -nLayoutSign ); | ||||||
232 | aEndPos.AdjustY( -1 ); | ||||||
233 | |||||||
234 | bool bTextBelow = ( aRange.aStart.Row() == 0 ); | ||||||
235 | |||||||
236 | OUString aCurrent; | ||||||
237 | Color aColor( COL_LIGHTGRAY ); | ||||||
238 | for (SCTAB nAct=nTab+1; nAct<nTabCount && rDoc.IsScenario(nAct); nAct++) | ||||||
239 | if ( rDoc.IsActiveScenario(nAct) && rDoc.HasScenarioRange(nAct,aRange) ) | ||||||
240 | { | ||||||
241 | OUString aDummyComment; | ||||||
242 | ScScenarioFlags nDummyFlags; | ||||||
243 | rDoc.GetName( nAct, aCurrent ); | ||||||
244 | rDoc.GetScenarioData( nAct, aDummyComment, aColor, nDummyFlags ); | ||||||
245 | } | ||||||
246 | |||||||
247 | if (aCurrent.isEmpty()) | ||||||
248 | aCurrent = ScResId( STR_EMPTYDATAreinterpret_cast<char const *>("STR_EMPTYDATA" "\004" u8"(empty)" ) ); | ||||||
249 | |||||||
250 | //! Own text "(None)" instead of "(Empty)" ??? | ||||||
251 | |||||||
252 | lcl_DrawOneFrame( pDev, tools::Rectangle( aStartPos, aEndPos ), | ||||||
253 | aCurrent, aColor, bTextBelow, | ||||||
254 | rViewData.GetPPTX(), rViewData.GetPPTY(), rViewData.GetZoomY(), | ||||||
255 | rDoc, rViewData, bLayoutRTL ); | ||||||
256 | } | ||||||
257 | } | ||||||
258 | } | ||||||
259 | |||||||
260 | static void lcl_DrawHighlight( ScOutputData& rOutputData, const ScViewData& rViewData, | ||||||
261 | const std::vector<ScHighlightEntry>& rHighlightRanges ) | ||||||
262 | { | ||||||
263 | SCTAB nTab = rViewData.GetTabNo(); | ||||||
264 | for ( const auto& rHighlightRange : rHighlightRanges) | ||||||
265 | { | ||||||
266 | ScRange aRange = rHighlightRange.aRef; | ||||||
267 | if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() ) | ||||||
268 | { | ||||||
269 | rOutputData.DrawRefMark( | ||||||
270 | aRange.aStart.Col(), aRange.aStart.Row(), | ||||||
271 | aRange.aEnd.Col(), aRange.aEnd.Row(), | ||||||
272 | rHighlightRange.aColor, false ); | ||||||
273 | } | ||||||
274 | } | ||||||
275 | } | ||||||
276 | |||||||
277 | void ScGridWindow::DoInvertRect( const tools::Rectangle& rPixel ) | ||||||
278 | { | ||||||
279 | if ( rPixel == aInvertRect ) | ||||||
280 | aInvertRect = tools::Rectangle(); // Cancel | ||||||
281 | else | ||||||
282 | { | ||||||
283 | OSL_ENSURE( aInvertRect.IsEmpty(), "DoInvertRect no pairs" )do { if (true && (!(aInvertRect.IsEmpty()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx" ":" "283" ": "), "%s", "DoInvertRect no pairs"); } } while ( false); | ||||||
284 | |||||||
285 | aInvertRect = rPixel; // Mark new rectangle | ||||||
286 | } | ||||||
287 | |||||||
288 | UpdateHeaderOverlay(); // uses aInvertRect | ||||||
289 | } | ||||||
290 | |||||||
291 | void ScGridWindow::PrePaint(vcl::RenderContext& /*rRenderContext*/) | ||||||
292 | { | ||||||
293 | // forward PrePaint to DrawingLayer | ||||||
294 | ScTabViewShell* pTabViewShell = mrViewData.GetViewShell(); | ||||||
295 | |||||||
296 | if(pTabViewShell) | ||||||
297 | { | ||||||
298 | SdrView* pDrawView = pTabViewShell->GetScDrawView(); | ||||||
299 | |||||||
300 | if (pDrawView) | ||||||
301 | { | ||||||
302 | pDrawView->PrePaint(); | ||||||
303 | } | ||||||
304 | } | ||||||
305 | } | ||||||
306 | |||||||
307 | bool ScGridWindow::NeedLOKCursorInvalidation(const tools::Rectangle& rCursorRect, | ||||||
308 | const Fraction aScaleX, const Fraction aScaleY) | ||||||
309 | { | ||||||
310 | // Don't see the need for a map as there will be only a few zoom levels | ||||||
311 | // and as of now X and Y zooms in online are the same. | ||||||
312 | for (auto& rEntry : maLOKLastCursor) | ||||||
313 | { | ||||||
314 | if (aScaleX == rEntry.aScaleX && aScaleY == rEntry.aScaleY) | ||||||
315 | { | ||||||
316 | if (rCursorRect == rEntry.aRect) | ||||||
317 | return false; // No change | ||||||
318 | |||||||
319 | // Update and allow invalidate. | ||||||
320 | rEntry.aRect = rCursorRect; | ||||||
321 | return true; | ||||||
322 | } | ||||||
323 | } | ||||||
324 | |||||||
325 | maLOKLastCursor.push_back(LOKCursorEntry{aScaleX, aScaleY, rCursorRect}); | ||||||
326 | return true; | ||||||
327 | } | ||||||
328 | |||||||
329 | void ScGridWindow::InvalidateLOKViewCursor(const tools::Rectangle& rCursorRect, | ||||||
330 | const Fraction aScaleX, const Fraction aScaleY) | ||||||
331 | { | ||||||
332 | if (!NeedLOKCursorInvalidation(rCursorRect, aScaleX, aScaleY)) | ||||||
333 | return; | ||||||
334 | |||||||
335 | ScTabViewShell* pThisViewShell = mrViewData.GetViewShell(); | ||||||
336 | SfxViewShell* pViewShell = SfxViewShell::GetFirst(); | ||||||
337 | |||||||
338 | while (pViewShell) | ||||||
339 | { | ||||||
340 | if (pViewShell != pThisViewShell && pViewShell->GetDocId() == pThisViewShell->GetDocId()) | ||||||
341 | { | ||||||
342 | ScTabViewShell* pOtherViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); | ||||||
343 | if (pOtherViewShell) | ||||||
344 | { | ||||||
345 | ScViewData& rOtherViewData = pOtherViewShell->GetViewData(); | ||||||
346 | Fraction aZoomX = rOtherViewData.GetZoomX(); | ||||||
347 | Fraction aZoomY = rOtherViewData.GetZoomY(); | ||||||
348 | if (aZoomX == aScaleX && aZoomY == aScaleY) | ||||||
349 | { | ||||||
350 | SfxLokHelper::notifyOtherView(pThisViewShell, pOtherViewShell, | ||||||
351 | LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", rCursorRect.toString()); | ||||||
352 | } | ||||||
353 | } | ||||||
354 | } | ||||||
355 | |||||||
356 | pViewShell = SfxViewShell::GetNext(*pViewShell); | ||||||
357 | } | ||||||
358 | } | ||||||
359 | |||||||
360 | void ScGridWindow::Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect ) | ||||||
361 | { | ||||||
362 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
363 | if ( rDoc.IsInInterpreter() ) | ||||||
364 | { | ||||||
365 | // Via Reschedule, interpreted cells do not trigger Invalidate again, | ||||||
366 | // otherwise for instance an error box would never appear (bug 36381). | ||||||
367 | // Later, through bNeedsRepaint everything is painted again. | ||||||
368 | if ( bNeedsRepaint ) | ||||||
369 | { | ||||||
370 | //! Merge Rectangle? | ||||||
371 | aRepaintPixel = tools::Rectangle(); // multiple -> paint all | ||||||
372 | } | ||||||
373 | else | ||||||
374 | { | ||||||
375 | bNeedsRepaint = true; | ||||||
376 | aRepaintPixel = LogicToPixel(rRect); // only affected ranges | ||||||
377 | } | ||||||
378 | return; | ||||||
379 | } | ||||||
380 | |||||||
381 | // #i117893# If GetSizePixel needs to call the resize handler, the resulting nested Paint call | ||||||
382 | // (possibly for a larger rectangle) has to be allowed. Call GetSizePixel before setting bIsInPaint. | ||||||
383 | GetSizePixel(); | ||||||
384 | |||||||
385 | if (bIsInPaint) | ||||||
386 | return; | ||||||
387 | |||||||
388 | bIsInPaint = true; | ||||||
389 | |||||||
390 | tools::Rectangle aPixRect = LogicToPixel( rRect ); | ||||||
391 | |||||||
392 | SCCOL nX1 = mrViewData.GetPosX(eHWhich); | ||||||
393 | SCROW nY1 = mrViewData.GetPosY(eVWhich); | ||||||
394 | |||||||
395 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
396 | |||||||
397 | double nPPTX = mrViewData.GetPPTX(); | ||||||
398 | double nPPTY = mrViewData.GetPPTY(); | ||||||
399 | |||||||
400 | tools::Rectangle aMirroredPixel = aPixRect; | ||||||
401 | if ( rDoc.IsLayoutRTL( nTab ) ) | ||||||
402 | { | ||||||
403 | // mirror and swap | ||||||
404 | long nWidth = GetSizePixel().Width(); | ||||||
405 | aMirroredPixel.SetLeft( nWidth - 1 - aPixRect.Right() ); | ||||||
406 | aMirroredPixel.SetRight( nWidth - 1 - aPixRect.Left() ); | ||||||
407 | } | ||||||
408 | |||||||
409 | long nScrX = ScViewData::ToPixel( rDoc.GetColWidth( nX1, nTab ), nPPTX ); | ||||||
410 | while ( nScrX <= aMirroredPixel.Left() && nX1 < rDoc.MaxCol() ) | ||||||
411 | { | ||||||
412 | ++nX1; | ||||||
413 | nScrX += ScViewData::ToPixel( rDoc.GetColWidth( nX1, nTab ), nPPTX ); | ||||||
414 | } | ||||||
415 | SCCOL nX2 = nX1; | ||||||
416 | while ( nScrX <= aMirroredPixel.Right() && nX2 < rDoc.MaxCol() ) | ||||||
417 | { | ||||||
418 | ++nX2; | ||||||
419 | nScrX += ScViewData::ToPixel( rDoc.GetColWidth( nX2, nTab ), nPPTX ); | ||||||
420 | } | ||||||
421 | |||||||
422 | long nScrY = 0; | ||||||
423 | ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, rDoc.MaxRow(), nPPTY, &rDoc, nTab); | ||||||
424 | SCROW nY2 = nY1; | ||||||
425 | if (nScrY <= aPixRect.Bottom() && nY2 < rDoc.MaxRow()) | ||||||
426 | { | ||||||
427 | ++nY2; | ||||||
428 | ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, rDoc.MaxRow(), nPPTY, &rDoc, nTab); | ||||||
429 | } | ||||||
430 | |||||||
431 | Draw( nX1,nY1,nX2,nY2, ScUpdateMode::Marks ); // don't continue with painting | ||||||
432 | |||||||
433 | bIsInPaint = false; | ||||||
434 | } | ||||||
435 | |||||||
436 | void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode ) | ||||||
437 | { | ||||||
438 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
439 | |||||||
440 | // let's ignore the normal Draw() attempts when doing the tiled rendering, | ||||||
441 | // all the rendering should go through PaintTile() in that case. | ||||||
442 | // TODO revisit if we can actually turn this into an assert(), and clean | ||||||
443 | // up the callers | ||||||
444 | if (comphelper::LibreOfficeKit::isActive()) | ||||||
445 | return; | ||||||
446 | |||||||
447 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | ||||||
448 | bool bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg(); | ||||||
449 | |||||||
450 | if (mrViewData.IsMinimized()) | ||||||
451 | return; | ||||||
452 | |||||||
453 | PutInOrder( nX1, nX2 ); | ||||||
454 | PutInOrder( nY1, nY2 ); | ||||||
455 | |||||||
456 | OSL_ENSURE( rDoc.ValidCol(nX2) && rDoc.ValidRow(nY2), "GridWin Draw area too big" )do { if (true && (!(rDoc.ValidCol(nX2) && rDoc .ValidRow(nY2)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx" ":" "456" ": "), "%s", "GridWin Draw area too big"); } } while (false); | ||||||
457 | |||||||
458 | UpdateVisibleRange(); | ||||||
459 | |||||||
460 | if (nX2 < maVisibleRange.mnCol1 || nY2 < maVisibleRange.mnRow1) | ||||||
461 | return; | ||||||
462 | // invisible | ||||||
463 | if (nX1 < maVisibleRange.mnCol1) | ||||||
464 | nX1 = maVisibleRange.mnCol1; | ||||||
465 | if (nY1 < maVisibleRange.mnRow1) | ||||||
466 | nY1 = maVisibleRange.mnRow1; | ||||||
467 | |||||||
468 | if (nX1 > maVisibleRange.mnCol2 || nY1 > maVisibleRange.mnRow2) | ||||||
469 | return; | ||||||
470 | |||||||
471 | if (nX2 > maVisibleRange.mnCol2) | ||||||
472 | nX2 = maVisibleRange.mnCol2; | ||||||
473 | if (nY2 > maVisibleRange.mnRow2) | ||||||
474 | nY2 = maVisibleRange.mnRow2; | ||||||
475 | |||||||
476 | if ( eMode != ScUpdateMode::Marks && nX2 < maVisibleRange.mnCol2) | ||||||
477 | nX2 = maVisibleRange.mnCol2; // to continue painting | ||||||
478 | |||||||
479 | // point of no return | ||||||
480 | |||||||
481 | ++nPaintCount; // mark that painting is in progress | ||||||
482 | |||||||
483 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
484 | rDoc.ExtendHidden( nX1, nY1, nX2, nY2, nTab ); | ||||||
485 | |||||||
486 | Point aScrPos = mrViewData.GetScrPos( nX1, nY1, eWhich ); | ||||||
487 | long nMirrorWidth = GetSizePixel().Width(); | ||||||
488 | bool bLayoutRTL = rDoc.IsLayoutRTL( nTab ); | ||||||
489 | if ( bLayoutRTL ) | ||||||
490 | { | ||||||
491 | long nEndPixel = mrViewData.GetScrPos( nX2+1, maVisibleRange.mnRow1, eWhich ).X(); | ||||||
492 | nMirrorWidth = aScrPos.X() - nEndPixel; | ||||||
493 | aScrPos.setX( nEndPixel + 1 ); | ||||||
494 | } | ||||||
495 | |||||||
496 | long nScrX = aScrPos.X(); | ||||||
497 | long nScrY = aScrPos.Y(); | ||||||
498 | |||||||
499 | SCCOL nCurX = mrViewData.GetCurX(); | ||||||
500 | SCROW nCurY = mrViewData.GetCurY(); | ||||||
501 | SCCOL nCurEndX = nCurX; | ||||||
502 | SCROW nCurEndY = nCurY; | ||||||
503 | rDoc.ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab ); | ||||||
504 | bool bCurVis = nCursorHideCount==0 && | ||||||
505 | ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 ); | ||||||
506 | |||||||
507 | // AutoFill Handles | ||||||
508 | if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab && | ||||||
509 | ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) ) | ||||||
510 | { | ||||||
511 | SCCOL nHdlX = aAutoMarkPos.Col(); | ||||||
512 | SCROW nHdlY = aAutoMarkPos.Row(); | ||||||
513 | rDoc.ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab ); | ||||||
514 | // left and top is unaffected | ||||||
515 | |||||||
516 | //! Paint AutoFill handles alone (without Cursor) ??? | ||||||
517 | } | ||||||
518 | |||||||
519 | double nPPTX = mrViewData.GetPPTX(); | ||||||
520 | double nPPTY = mrViewData.GetPPTY(); | ||||||
521 | |||||||
522 | const ScViewOptions& rOpts = mrViewData.GetOptions(); | ||||||
523 | |||||||
524 | // data block | ||||||
525 | |||||||
526 | ScTableInfo aTabInfo; | ||||||
527 | rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, | ||||||
528 | nPPTX, nPPTY, false, rOpts.GetOption(VOPT_FORMULAS), | ||||||
529 | &mrViewData.GetMarkData() ); | ||||||
530 | |||||||
531 | Fraction aZoomX = mrViewData.GetZoomX(); | ||||||
532 | Fraction aZoomY = mrViewData.GetZoomY(); | ||||||
533 | ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, &rDoc, nTab, | ||||||
534 | nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY, | ||||||
535 | &aZoomX, &aZoomY ); | ||||||
536 | |||||||
537 | aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL | ||||||
538 | aOutputData.SetSpellCheckContext(mpSpellCheckCxt.get()); | ||||||
539 | |||||||
540 | ScopedVclPtr< VirtualDevice > xFmtVirtDev; | ||||||
541 | bool bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode? | ||||||
542 | |||||||
543 | if ( bTextWysiwyg ) | ||||||
544 | { | ||||||
545 | // use printer for text formatting | ||||||
546 | |||||||
547 | OutputDevice* pFmtDev = rDoc.GetPrinter(); | ||||||
548 | pFmtDev->SetMapMode( mrViewData.GetLogicMode(eWhich) ); | ||||||
549 | aOutputData.SetFmtDevice( pFmtDev ); | ||||||
550 | } | ||||||
551 | else if ( aZoomX != aZoomY && mrViewData.IsOle() ) | ||||||
552 | { | ||||||
553 | // #i45033# For OLE inplace editing with different zoom factors, | ||||||
554 | // use a virtual device with 1/100th mm as text formatting reference | ||||||
555 | |||||||
556 | xFmtVirtDev.disposeAndReset( VclPtr<VirtualDevice>::Create() ); | ||||||
557 | xFmtVirtDev->SetMapMode(MapMode(MapUnit::Map100thMM)); | ||||||
558 | aOutputData.SetFmtDevice( xFmtVirtDev.get() ); | ||||||
559 | |||||||
560 | bLogicText = true; // use logic MapMode | ||||||
561 | } | ||||||
562 | |||||||
563 | DrawContent(*this, aTabInfo, aOutputData, bLogicText); | ||||||
564 | |||||||
565 | // If something was inverted during the Paint (selection changed from Basic Macro) | ||||||
566 | // then this is now mixed up and has to be repainted | ||||||
567 | OSL_ENSURE(nPaintCount, "Wrong nPaintCount")do { if (true && (!(nPaintCount))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx" ":" "567" ": "), "%s", "Wrong nPaintCount"); } } while (false ); | ||||||
568 | --nPaintCount; | ||||||
569 | if (!nPaintCount) | ||||||
570 | CheckNeedsRepaint(); | ||||||
571 | |||||||
572 | // Flag drawn formula cells "unchanged". | ||||||
573 | rDoc.ResetChanged(ScRange(nX1, nY1, nTab, nX2, nY2, nTab)); | ||||||
574 | rDoc.PrepareFormulaCalc(); | ||||||
575 | } | ||||||
576 | |||||||
577 | namespace { | ||||||
578 | |||||||
579 | class SuppressEditViewMessagesGuard | ||||||
580 | { | ||||||
581 | public: | ||||||
582 | SuppressEditViewMessagesGuard(EditView& rEditView) : | ||||||
583 | mrEditView(rEditView), | ||||||
584 | mbOrigSuppressFlag(rEditView.IsSuppressLOKMessages()) | ||||||
585 | { | ||||||
586 | if (!mbOrigSuppressFlag) | ||||||
587 | mrEditView.SuppressLOKMessages(true); | ||||||
588 | } | ||||||
589 | |||||||
590 | ~SuppressEditViewMessagesGuard() | ||||||
591 | { | ||||||
592 | if (mrEditView.IsSuppressLOKMessages() != mbOrigSuppressFlag) | ||||||
593 | mrEditView.SuppressLOKMessages(mbOrigSuppressFlag); | ||||||
594 | } | ||||||
595 | |||||||
596 | private: | ||||||
597 | EditView& mrEditView; | ||||||
598 | const bool mbOrigSuppressFlag; | ||||||
599 | }; | ||||||
600 | |||||||
601 | } | ||||||
602 | |||||||
603 | void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableInfo, ScOutputData& aOutputData, | ||||||
604 | bool bLogicText) | ||||||
605 | { | ||||||
606 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | ||||||
607 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
608 | const ScViewOptions& rOpts = mrViewData.GetOptions(); | ||||||
609 | bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive(); | ||||||
610 | bool bNoBackgroundAndGrid = bIsTiledRendering | ||||||
| |||||||
611 | && comphelper::LibreOfficeKit::isCompatFlagSet( | ||||||
612 | comphelper::LibreOfficeKit::Compat::scNoGridBackground); | ||||||
613 | |||||||
614 | SCTAB nTab = aOutputData.nTab; | ||||||
615 | SCCOL nX1 = aOutputData.nX1; | ||||||
616 | SCROW nY1 = aOutputData.nY1; | ||||||
617 | SCCOL nX2 = aOutputData.nX2; | ||||||
618 | SCROW nY2 = aOutputData.nY2; | ||||||
619 | long nScrX = aOutputData.nScrX; | ||||||
620 | long nScrY = aOutputData.nScrY; | ||||||
621 | |||||||
622 | const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig(); | ||||||
623 | Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, false ).nColor ); | ||||||
624 | if ( aGridColor == COL_TRANSPARENT ) | ||||||
625 | { | ||||||
626 | // use view options' grid color only if color config has "automatic" color | ||||||
627 | aGridColor = rOpts.GetGridColor(); | ||||||
628 | } | ||||||
629 | |||||||
630 | aOutputData.SetSyntaxMode ( mrViewData.IsSyntaxMode() ); | ||||||
631 | aOutputData.SetGridColor ( aGridColor ); | ||||||
632 | aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) ); | ||||||
633 | aOutputData.SetShowFormulas ( rOpts.GetOption( VOPT_FORMULAS ) ); | ||||||
634 | aOutputData.SetShowSpellErrors ( rDoc.GetDocOptions().IsAutoSpell() ); | ||||||
635 | aOutputData.SetMarkClipped ( rOpts.GetOption( VOPT_CLIPMARKS ) ); | ||||||
636 | |||||||
637 | aOutputData.SetUseStyleColor( true ); // always set in table view | ||||||
638 | |||||||
639 | aOutputData.SetViewShell( mrViewData.GetViewShell() ); | ||||||
640 | |||||||
641 | bool bGrid = rOpts.GetOption( VOPT_GRID ) && mrViewData.GetShowGrid(); | ||||||
642 | bool bGridFirst = !rOpts.GetOption( VOPT_GRID_ONTOP ); | ||||||
643 | |||||||
644 | bool bPage = rOpts.GetOption( VOPT_PAGEBREAKS ) && !bIsTiledRendering; | ||||||
645 | |||||||
646 | bool bPageMode = mrViewData.IsPagebreakMode(); | ||||||
647 | if (bPageMode) // after FindChanged | ||||||
648 | { | ||||||
649 | // SetPagebreakMode also initializes bPrinted Flags | ||||||
650 | aOutputData.SetPagebreakMode( mrViewData.GetView()->GetPageBreakData() ); | ||||||
651 | } | ||||||
652 | |||||||
653 | EditView* pEditView = nullptr; | ||||||
654 | bool bEditMode = mrViewData.HasEditView(eWhich); | ||||||
655 | if ( bEditMode && mrViewData.GetRefTabNo() == nTab ) | ||||||
656 | { | ||||||
657 | SCCOL nEditCol; | ||||||
658 | SCROW nEditRow; | ||||||
659 | mrViewData.GetEditView( eWhich, pEditView, nEditCol, nEditRow ); | ||||||
660 | SCCOL nEditEndCol = mrViewData.GetEditEndCol(); | ||||||
661 | SCROW nEditEndRow = mrViewData.GetEditEndRow(); | ||||||
662 | |||||||
663 | if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 ) | ||||||
664 | aOutputData.SetEditCell( nEditCol, nEditRow ); | ||||||
665 | else | ||||||
666 | bEditMode = false; | ||||||
667 | } | ||||||
668 | |||||||
669 | const MapMode aOriginalMode = rDevice.GetMapMode(); | ||||||
670 | |||||||
671 | // define drawing layer map mode and paint rectangle | ||||||
672 | MapMode aDrawMode = GetDrawMapMode(); | ||||||
673 | if (bIsTiledRendering
| ||||||
674 | { | ||||||
675 | // FIXME this shouldn't be necessary once we change the entire Calc to | ||||||
676 | // work in the logic coordinates (ideally 100ths of mm - so that it is | ||||||
677 | // the same as editeng and drawinglayer), and get rid of all the | ||||||
678 | // SetMapMode's and other unnecessary fun we have with pixels | ||||||
679 | // See also ScGridWindow::GetDrawMapMode() for the rest of this hack | ||||||
680 | aDrawMode.SetOrigin(PixelToLogic(Point(nScrX, nScrY), aDrawMode)); | ||||||
681 | } | ||||||
682 | tools::Rectangle aDrawingRectLogic; | ||||||
683 | bool bLayoutRTL = rDoc.IsLayoutRTL( nTab ); | ||||||
684 | |||||||
685 | { | ||||||
686 | // get drawing pixel rect | ||||||
687 | tools::Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); | ||||||
688 | |||||||
689 | // correct for border (left/right) | ||||||
690 | if(rDoc.MaxCol() == nX2) | ||||||
691 | { | ||||||
692 | if(bLayoutRTL) | ||||||
693 | { | ||||||
694 | aDrawingRectPixel.SetLeft( 0 ); | ||||||
695 | } | ||||||
696 | else | ||||||
697 | { | ||||||
698 | aDrawingRectPixel.SetRight( GetOutputSizePixel().getWidth() ); | ||||||
699 | } | ||||||
700 | } | ||||||
701 | |||||||
702 | // correct for border (bottom) | ||||||
703 | if(rDoc.MaxRow() == nY2) | ||||||
704 | { | ||||||
705 | aDrawingRectPixel.SetBottom( GetOutputSizePixel().getHeight() ); | ||||||
706 | } | ||||||
707 | |||||||
708 | // get logic positions | ||||||
709 | aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode); | ||||||
710 | } | ||||||
711 | |||||||
712 | OutputDevice* pContentDev = &rDevice; // device for document content, used by overlay manager | ||||||
713 | SdrPaintWindow* pTargetPaintWindow = nullptr; // #i74769# work with SdrPaintWindow directly | ||||||
714 | |||||||
715 | { | ||||||
716 | // init redraw | ||||||
717 | ScTabViewShell* pTabViewShell = mrViewData.GetViewShell(); | ||||||
718 | |||||||
719 | if(pTabViewShell) | ||||||
720 | { | ||||||
721 | MapMode aCurrentMapMode(pContentDev->GetMapMode()); | ||||||
722 | pContentDev->SetMapMode(aDrawMode); | ||||||
723 | SdrView* pDrawView = pTabViewShell->GetScDrawView(); | ||||||
724 | |||||||
725 | if(pDrawView) | ||||||
726 | { | ||||||
727 | // #i74769# Use new BeginDrawLayers() interface | ||||||
728 | vcl::Region aDrawingRegion(aDrawingRectLogic); | ||||||
729 | pTargetPaintWindow = pDrawView->BeginDrawLayers(pContentDev, aDrawingRegion); | ||||||
730 | OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)")do { if (true && (!(pTargetPaintWindow))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx" ":" "730" ": "), "%s", "BeginDrawLayers: Got no SdrPaintWindow (!)" ); } } while (false); | ||||||
731 | |||||||
732 | if (!bIsTiledRendering) | ||||||
733 | { | ||||||
734 | // #i74769# get target device from SdrPaintWindow, this may be the prerender | ||||||
735 | // device now, too. | ||||||
736 | pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice()); | ||||||
737 | aOutputData.SetContentDevice(pContentDev); | ||||||
738 | } | ||||||
739 | } | ||||||
740 | |||||||
741 | pContentDev->SetMapMode(aCurrentMapMode); | ||||||
742 | } | ||||||
743 | } | ||||||
744 | |||||||
745 | // edge (area) (Pixel) | ||||||
746 | if ( nX2==rDoc.MaxCol() || nY2==rDoc.MaxRow() ) | ||||||
747 | { | ||||||
748 | // save MapMode and set to pixel | ||||||
749 | MapMode aCurrentMapMode(pContentDev->GetMapMode()); | ||||||
750 | pContentDev->SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
751 | |||||||
752 | tools::Rectangle aPixRect( Point(), GetOutputSizePixel() ); | ||||||
753 | pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor ); | ||||||
754 | pContentDev->SetLineColor(); | ||||||
755 | if ( nX2==rDoc.MaxCol() ) | ||||||
756 | { | ||||||
757 | tools::Rectangle aDrawRect( aPixRect ); | ||||||
758 | if ( bLayoutRTL ) | ||||||
759 | aDrawRect.SetRight( nScrX - 1 ); | ||||||
760 | else | ||||||
761 | aDrawRect.SetLeft( nScrX + aOutputData.GetScrW() ); | ||||||
762 | if (aDrawRect.Right() >= aDrawRect.Left()) | ||||||
763 | pContentDev->DrawRect( aDrawRect ); | ||||||
764 | } | ||||||
765 | if ( nY2==rDoc.MaxRow() ) | ||||||
766 | { | ||||||
767 | tools::Rectangle aDrawRect( aPixRect ); | ||||||
768 | aDrawRect.SetTop( nScrY + aOutputData.GetScrH() ); | ||||||
769 | if ( nX2==rDoc.MaxCol() ) | ||||||
770 | { | ||||||
771 | // no double painting of the corner | ||||||
772 | if ( bLayoutRTL ) | ||||||
773 | aDrawRect.SetLeft( nScrX ); | ||||||
774 | else | ||||||
775 | aDrawRect.SetRight( nScrX + aOutputData.GetScrW() - 1 ); | ||||||
776 | } | ||||||
777 | if (aDrawRect.Bottom() >= aDrawRect.Top()) | ||||||
778 | pContentDev->DrawRect( aDrawRect ); | ||||||
779 | } | ||||||
780 | |||||||
781 | // restore MapMode | ||||||
782 | pContentDev->SetMapMode(aCurrentMapMode); | ||||||
783 | } | ||||||
784 | |||||||
785 | if ( rDoc.HasBackgroundDraw( nTab, aDrawingRectLogic ) ) | ||||||
786 | { | ||||||
787 | pContentDev->SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
788 | aOutputData.DrawClear(); | ||||||
789 | |||||||
790 | // drawing background | ||||||
791 | |||||||
792 | pContentDev->SetMapMode(aDrawMode); | ||||||
793 | DrawRedraw( aOutputData, SC_LAYER_BACK ); | ||||||
794 | } | ||||||
795 | else | ||||||
796 | aOutputData.SetSolidBackground(!bNoBackgroundAndGrid); | ||||||
797 | |||||||
798 | aOutputData.DrawDocumentBackground(); | ||||||
799 | |||||||
800 | if (bGridFirst
| ||||||
801 | aOutputData.DrawGrid(*pContentDev, bGrid, bPage); | ||||||
802 | |||||||
803 | aOutputData.DrawBackground(*pContentDev); | ||||||
804 | |||||||
805 | if (!bGridFirst
| ||||||
806 | aOutputData.DrawGrid(*pContentDev, bGrid, bPage); | ||||||
807 | |||||||
808 | pContentDev->SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
809 | |||||||
810 | if ( bPageMode
| ||||||
811 | { | ||||||
812 | // DrawPagePreview draws complete lines/page numbers, must always be clipped | ||||||
813 | if ( aOutputData.SetChangedClip() ) | ||||||
814 | { | ||||||
815 | DrawPagePreview(nX1,nY1,nX2,nY2, *pContentDev); | ||||||
816 | pContentDev->SetClipRegion(); | ||||||
817 | } | ||||||
818 | } | ||||||
819 | |||||||
820 | aOutputData.DrawShadow(); | ||||||
821 | aOutputData.DrawFrame(*pContentDev); | ||||||
822 | |||||||
823 | // Show Note Mark | ||||||
824 | if ( rOpts.GetOption( VOPT_NOTES ) ) | ||||||
825 | aOutputData.DrawNoteMarks(*pContentDev); | ||||||
826 | |||||||
827 | if ( !bLogicText ) | ||||||
828 | aOutputData.DrawStrings(); // in pixel MapMode | ||||||
829 | |||||||
830 | // edit cells and printer-metrics text must be before the buttons | ||||||
831 | // (DataPilot buttons contain labels in UI font) | ||||||
832 | |||||||
833 | pContentDev->SetMapMode(mrViewData.GetLogicMode(eWhich)); | ||||||
834 | if ( bLogicText
| ||||||
835 | aOutputData.DrawStrings(true); // in logic MapMode if bLogicText is set | ||||||
836 | aOutputData.DrawEdit(true); | ||||||
837 | |||||||
838 | // the buttons are painted in absolute coordinates | ||||||
839 | if (bIsTiledRendering
| ||||||
840 | { | ||||||
841 | // Tiled offset nScrX, nScrY | ||||||
842 | MapMode aMap( MapUnit::MapPixel ); | ||||||
843 | Point aOrigin = aOriginalMode.GetOrigin(); | ||||||
844 | aOrigin.setX(aOrigin.getX() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScrX); | ||||||
845 | aOrigin.setY(aOrigin.getY() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScrY); | ||||||
846 | aMap.SetOrigin(aOrigin); | ||||||
847 | pContentDev->SetMapMode(aMap); | ||||||
848 | } | ||||||
849 | else | ||||||
850 | pContentDev->SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
851 | |||||||
852 | // Autofilter- and Pivot-Buttons | ||||||
853 | |||||||
854 | DrawButtons(nX1, nX2, rTableInfo, pContentDev); // Pixel | ||||||
855 | |||||||
856 | pContentDev->SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
857 | |||||||
858 | aOutputData.DrawClipMarks(); | ||||||
859 | |||||||
860 | // In any case, Scenario / ChangeTracking must happen after DrawGrid, also for !bGridFirst | ||||||
861 | |||||||
862 | //! test if ChangeTrack display is active | ||||||
863 | //! Disable scenario frame via view option? | ||||||
864 | |||||||
865 | SCTAB nTabCount = rDoc.GetTableCount(); | ||||||
866 | const std::vector<ScHighlightEntry> &rHigh = mrViewData.GetView()->GetHighlightRanges(); | ||||||
867 | bool bHasScenario = ( nTab+1<nTabCount && rDoc.IsScenario(nTab+1) && !rDoc.IsScenario(nTab) ); | ||||||
868 | bool bHasChange = ( rDoc.GetChangeTrack() != nullptr ); | ||||||
869 | |||||||
870 | if ( bHasChange
| ||||||
871 | { | ||||||
872 | //! Merge SetChangedClip() with DrawMarks() ?? (different MapMode!) | ||||||
873 | |||||||
874 | if ( bHasChange ) | ||||||
875 | aOutputData.DrawChangeTrack(); | ||||||
876 | |||||||
877 | if ( bHasScenario ) | ||||||
878 | lcl_DrawScenarioFrames( pContentDev, mrViewData, eWhich, nX1,nY1,nX2,nY2 ); | ||||||
879 | |||||||
880 | lcl_DrawHighlight( aOutputData, mrViewData, rHigh ); | ||||||
881 | } | ||||||
882 | |||||||
883 | // Drawing foreground | ||||||
884 | |||||||
885 | pContentDev->SetMapMode(aDrawMode); | ||||||
886 | |||||||
887 | // Bitmaps and buttons are in absolute pixel coordinates. | ||||||
888 | const MapMode aOrig = pContentDev->GetMapMode(); | ||||||
889 | if (bIsTiledRendering
| ||||||
890 | { | ||||||
891 | Point aOrigin = aOriginalMode.GetOrigin(); | ||||||
892 | Size aPixelOffset(aOrigin.getX() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0), aOrigin.getY() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0)); | ||||||
893 | pContentDev->SetPixelOffset(aPixelOffset); | ||||||
894 | comphelper::LibreOfficeKit::setLocalRendering(); | ||||||
895 | } | ||||||
896 | |||||||
897 | DrawRedraw( aOutputData, SC_LAYER_FRONT ); | ||||||
898 | DrawRedraw( aOutputData, SC_LAYER_INTERN ); | ||||||
899 | DrawSdrGrid( aDrawingRectLogic, pContentDev ); | ||||||
900 | |||||||
901 | if (bIsTiledRendering
| ||||||
902 | { | ||||||
903 | pContentDev->SetPixelOffset(Size()); | ||||||
904 | pContentDev->SetMapMode(aOrig); | ||||||
905 | } | ||||||
906 | |||||||
907 | pContentDev->SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
908 | |||||||
909 | if ( mrViewData.IsRefMode() && nTab >= mrViewData.GetRefStartZ() && nTab <= mrViewData.GetRefEndZ() ) | ||||||
910 | { | ||||||
911 | Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor ); | ||||||
912 | aOutputData.DrawRefMark( mrViewData.GetRefStartX(), mrViewData.GetRefStartY(), | ||||||
913 | mrViewData.GetRefEndX(), mrViewData.GetRefEndY(), | ||||||
914 | aRefColor, false ); | ||||||
915 | } | ||||||
916 | |||||||
917 | // range finder | ||||||
918 | |||||||
919 | ScInputHandler* pHdl = pScMod->GetInputHdl( mrViewData.GetViewShell() ); | ||||||
920 | if (pHdl) | ||||||
921 | { | ||||||
922 | ScDocShell* pDocSh = mrViewData.GetDocShell(); | ||||||
923 | ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); | ||||||
924 | if ( pRangeFinder && !pRangeFinder->IsHidden() && | ||||||
925 | pRangeFinder->GetDocName() == pDocSh->GetTitle() ) | ||||||
926 | { | ||||||
927 | sal_uInt16 nCount = static_cast<sal_uInt16>(pRangeFinder->Count()); | ||||||
928 | for (sal_uInt16 i=0; i<nCount; i++) | ||||||
929 | { | ||||||
930 | ScRangeFindData& rData = pRangeFinder->GetObject(i); | ||||||
931 | |||||||
932 | ScRange aRef = rData.aRef; | ||||||
933 | aRef.PutInOrder(); | ||||||
934 | if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab ) | ||||||
935 | aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(), | ||||||
936 | aRef.aEnd.Col(), aRef.aEnd.Row(), | ||||||
937 | rData.nColor, | ||||||
938 | true ); | ||||||
939 | } | ||||||
940 | } | ||||||
941 | } | ||||||
942 | |||||||
943 | { | ||||||
944 | // end redraw | ||||||
945 | ScTabViewShell* pTabViewShell = mrViewData.GetViewShell(); | ||||||
946 | |||||||
947 | if(pTabViewShell) | ||||||
948 | { | ||||||
949 | MapMode aCurrentMapMode(pContentDev->GetMapMode()); | ||||||
950 | pContentDev->SetMapMode(aDrawMode); | ||||||
951 | |||||||
952 | if (bIsTiledRendering
| ||||||
953 | { | ||||||
954 | Point aOrigin = aOriginalMode.GetOrigin(); | ||||||
955 | aOrigin.setX(aOrigin.getX() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + aOutputData.nScrX); | ||||||
956 | aOrigin.setY(aOrigin.getY() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + aOutputData.nScrY); | ||||||
957 | const double twipFactor = 15 * 1.76388889; // 26.45833335 | ||||||
958 | aOrigin = Point(aOrigin.getX() * twipFactor, | ||||||
959 | aOrigin.getY() * twipFactor); | ||||||
960 | MapMode aNew = rDevice.GetMapMode(); | ||||||
961 | aNew.SetOrigin(aOrigin); | ||||||
962 | rDevice.SetMapMode(aNew); | ||||||
963 | } | ||||||
964 | |||||||
965 | SdrView* pDrawView = pTabViewShell->GetScDrawView(); | ||||||
966 | |||||||
967 | if(pDrawView) | ||||||
968 | { | ||||||
969 | // #i74769# work with SdrPaintWindow directly | ||||||
970 | pDrawView->EndDrawLayers(*pTargetPaintWindow, true); | ||||||
| |||||||
971 | } | ||||||
972 | |||||||
973 | pContentDev->SetMapMode(aCurrentMapMode); | ||||||
974 | } | ||||||
975 | } | ||||||
976 | |||||||
977 | // paint in-place editing on other views | ||||||
978 | if (bIsTiledRendering) | ||||||
979 | { | ||||||
980 | ScTabViewShell* pThisViewShell = mrViewData.GetViewShell(); | ||||||
981 | SfxViewShell* pViewShell = SfxViewShell::GetFirst(); | ||||||
982 | |||||||
983 | while (pViewShell) | ||||||
984 | { | ||||||
985 | if (pViewShell != pThisViewShell && pViewShell->GetDocId() == pThisViewShell->GetDocId()) | ||||||
986 | { | ||||||
987 | ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); | ||||||
988 | if (pTabViewShell) | ||||||
989 | { | ||||||
990 | ScViewData& rOtherViewData = pTabViewShell->GetViewData(); | ||||||
991 | ScSplitPos eOtherWhich = rOtherViewData.GetEditActivePart(); | ||||||
992 | |||||||
993 | bool bOtherEditMode = rOtherViewData.HasEditView(eOtherWhich); | ||||||
994 | SCCOL nCol1 = rOtherViewData.GetEditStartCol(); | ||||||
995 | SCROW nRow1 = rOtherViewData.GetEditStartRow(); | ||||||
996 | SCCOL nCol2 = rOtherViewData.GetEditEndCol(); | ||||||
997 | SCROW nRow2 = rOtherViewData.GetEditEndRow(); | ||||||
998 | bOtherEditMode = bOtherEditMode | ||||||
999 | && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 && nRow1 <= nY2 ); | ||||||
1000 | if (bOtherEditMode && rOtherViewData.GetRefTabNo() == nTab) | ||||||
1001 | { | ||||||
1002 | EditView* pOtherEditView = rOtherViewData.GetEditView(eOtherWhich); | ||||||
1003 | if (pOtherEditView) | ||||||
1004 | { | ||||||
1005 | long nScreenX = aOutputData.nScrX; | ||||||
1006 | long nScreenY = aOutputData.nScrY; | ||||||
1007 | |||||||
1008 | rDevice.SetLineColor(); | ||||||
1009 | rDevice.SetFillColor(pOtherEditView->GetBackgroundColor()); | ||||||
1010 | Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eOtherWhich ); | ||||||
1011 | Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich ); | ||||||
1012 | |||||||
1013 | // don't overwrite grid | ||||||
1014 | long nLayoutSign = bLayoutRTL ? -1 : 1; | ||||||
1015 | aEnd.AdjustX( -(2 * nLayoutSign) ); | ||||||
1016 | aEnd.AdjustY( -2 ); | ||||||
1017 | |||||||
1018 | tools::Rectangle aBackground(aStart, aEnd); | ||||||
1019 | |||||||
1020 | // Need to draw the background in absolute coords. | ||||||
1021 | Point aOrigin = aOriginalMode.GetOrigin(); | ||||||
1022 | aOrigin.setX(aOrigin.getX() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScreenX); | ||||||
1023 | aOrigin.setY(aOrigin.getY() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScreenY); | ||||||
1024 | aBackground += aOrigin; | ||||||
1025 | rDevice.SetMapMode(aDrawMode); | ||||||
1026 | |||||||
1027 | static const double twipFactor = 15 * 1.76388889; // 26.45833335 | ||||||
1028 | // keep into account the zoom factor | ||||||
1029 | aOrigin = Point((aOrigin.getX() * twipFactor) / static_cast<double>(aDrawMode.GetScaleX()), | ||||||
1030 | (aOrigin.getY() * twipFactor) / static_cast<double>(aDrawMode.GetScaleY())); | ||||||
1031 | |||||||
1032 | MapMode aNew = rDevice.GetMapMode(); | ||||||
1033 | aNew.SetOrigin(aOrigin); | ||||||
1034 | rDevice.SetMapMode(aNew); | ||||||
1035 | |||||||
1036 | // paint the background | ||||||
1037 | rDevice.DrawRect(rDevice.PixelToLogic(aBackground)); | ||||||
1038 | |||||||
1039 | tools::Rectangle aEditRect(aBackground); | ||||||
1040 | aEditRect.AdjustLeft(1); | ||||||
1041 | aEditRect.AdjustTop(1); | ||||||
1042 | |||||||
1043 | // EditView has an 'output area' which is used to clip the 'paint area' we provide below. | ||||||
1044 | // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin | ||||||
1045 | // attached to the EditView, so we have to change its mapmode too (temporarily). We save the | ||||||
1046 | // original mapmode and 'output area' and roll them back when we finish painting to rDevice. | ||||||
1047 | vcl::Window* pOtherWin = pOtherEditView->GetWindow(); | ||||||
1048 | const tools::Rectangle aOrigOutputArea(pOtherEditView->GetOutputArea()); // Not in pixels. | ||||||
1049 | const MapMode aOrigMapMode = pOtherWin->GetMapMode(); | ||||||
1050 | pOtherWin->SetMapMode(rDevice.GetMapMode()); | ||||||
1051 | |||||||
1052 | // Avoid sending wrong cursor/selection messages by the 'other' view, as the output-area is going | ||||||
1053 | // to be tweaked temporarily to match the current view's zoom. | ||||||
1054 | SuppressEditViewMessagesGuard aGuard(*pOtherEditView); | ||||||
1055 | |||||||
1056 | pOtherEditView->SetOutputArea(rDevice.PixelToLogic(aEditRect)); | ||||||
1057 | pOtherEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice); | ||||||
1058 | |||||||
1059 | // Rollback the mapmode and 'output area'. | ||||||
1060 | pOtherWin->SetMapMode(aOrigMapMode); | ||||||
1061 | pOtherEditView->SetOutputArea(aOrigOutputArea); | ||||||
1062 | rDevice.SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
1063 | } | ||||||
1064 | } | ||||||
1065 | } | ||||||
1066 | } | ||||||
1067 | |||||||
1068 | pViewShell = SfxViewShell::GetNext(*pViewShell); | ||||||
1069 | } | ||||||
1070 | |||||||
1071 | } | ||||||
1072 | |||||||
1073 | // In-place editing - when the user is typing, we need to paint the text | ||||||
1074 | // using the editeng. | ||||||
1075 | // It's being done after EndDrawLayers() to get it outside the overlay | ||||||
1076 | // buffer and on top of everything. | ||||||
1077 | if ( bEditMode && (mrViewData.GetRefTabNo() == mrViewData.GetTabNo()) ) | ||||||
1078 | { | ||||||
1079 | // get the coordinates of the area we need to clear (overpaint by | ||||||
1080 | // the background) | ||||||
1081 | SCCOL nCol1 = mrViewData.GetEditStartCol(); | ||||||
1082 | SCROW nRow1 = mrViewData.GetEditStartRow(); | ||||||
1083 | SCCOL nCol2 = mrViewData.GetEditEndCol(); | ||||||
1084 | SCROW nRow2 = mrViewData.GetEditEndRow(); | ||||||
1085 | rDevice.SetLineColor(); | ||||||
1086 | rDevice.SetFillColor(pEditView->GetBackgroundColor()); | ||||||
1087 | Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eWhich ); | ||||||
1088 | Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eWhich ); | ||||||
1089 | |||||||
1090 | // don't overwrite grid | ||||||
1091 | long nLayoutSign = bLayoutRTL ? -1 : 1; | ||||||
1092 | aEnd.AdjustX( -(2 * nLayoutSign) ); | ||||||
1093 | aEnd.AdjustY( -2 ); | ||||||
1094 | |||||||
1095 | // toggle the cursor off if its on to ensure the cursor invert | ||||||
1096 | // background logic remains valid after the background is cleared on | ||||||
1097 | // the next cursor flash | ||||||
1098 | vcl::Cursor* pCrsr = pEditView->GetCursor(); | ||||||
1099 | const bool bVisCursor = pCrsr && pCrsr->IsVisible(); | ||||||
1100 | if (bVisCursor) | ||||||
1101 | pCrsr->Hide(); | ||||||
1102 | |||||||
1103 | // set the correct mapmode | ||||||
1104 | tools::Rectangle aBackground(aStart, aEnd); | ||||||
1105 | tools::Rectangle aBGAbs(aStart, aEnd); | ||||||
1106 | |||||||
1107 | if (bIsTiledRendering) | ||||||
1108 | { | ||||||
1109 | // Need to draw the background in absolute coords. | ||||||
1110 | Point aOrigin = aOriginalMode.GetOrigin(); | ||||||
1111 | aOrigin.setX(aOrigin.getX() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScrX); | ||||||
1112 | aOrigin.setY(aOrigin.getY() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScrY); | ||||||
1113 | aBackground += aOrigin; | ||||||
1114 | rDevice.SetMapMode(aDrawMode); | ||||||
1115 | } | ||||||
1116 | else | ||||||
1117 | rDevice.SetMapMode(mrViewData.GetLogicMode()); | ||||||
1118 | |||||||
1119 | if (bIsTiledRendering) | ||||||
1120 | { | ||||||
1121 | Point aOrigin = aOriginalMode.GetOrigin(); | ||||||
1122 | aOrigin.setX(aOrigin.getX() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScrX); | ||||||
1123 | aOrigin.setY(aOrigin.getY() / TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0) + nScrY); | ||||||
1124 | static const double twipFactor = 15 * 1.76388889; // 26.45833335 | ||||||
1125 | // keep into account the zoom factor | ||||||
1126 | aOrigin = Point((aOrigin.getX() * twipFactor) / static_cast<double>(aDrawMode.GetScaleX()), | ||||||
1127 | (aOrigin.getY() * twipFactor) / static_cast<double>(aDrawMode.GetScaleY())); | ||||||
1128 | MapMode aNew = rDevice.GetMapMode(); | ||||||
1129 | aNew.SetOrigin(aOrigin); | ||||||
1130 | rDevice.SetMapMode(aNew); | ||||||
1131 | } | ||||||
1132 | |||||||
1133 | // paint the background | ||||||
1134 | tools::Rectangle aLogicRect(rDevice.PixelToLogic(aBackground)); | ||||||
1135 | //tdf#100925, rhbz#1283420, Draw some text here, to get | ||||||
1136 | //X11CairoTextRender::getCairoContext called, so that the forced read | ||||||
1137 | //from the underlying X Drawable gets it to sync. | ||||||
1138 | rDevice.DrawText(aLogicRect.BottomLeft(), " "); | ||||||
1139 | rDevice.DrawRect(aLogicRect); | ||||||
1140 | |||||||
1141 | // paint the editeng text | ||||||
1142 | if (bIsTiledRendering) | ||||||
1143 | { | ||||||
1144 | tools::Rectangle aEditRect(aBackground); | ||||||
1145 | aEditRect.AdjustLeft(1); | ||||||
1146 | aEditRect.AdjustTop(1); | ||||||
1147 | // EditView has an 'output area' which is used to clip the paint area we provide below. | ||||||
1148 | // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin | ||||||
1149 | // attached to the EditView, so we have to change its mapmode too (temporarily). We save the | ||||||
1150 | // original mapmode and 'output area' and roll them back when we finish painting to rDevice. | ||||||
1151 | const tools::Rectangle aOrigOutputArea(pEditView->GetOutputArea()); // Not in pixels. | ||||||
1152 | const MapMode aOrigMapMode = GetMapMode(); | ||||||
1153 | SetMapMode(rDevice.GetMapMode()); | ||||||
1154 | |||||||
1155 | // Avoid sending wrong cursor/selection messages by the current view, as the output-area is going | ||||||
1156 | // to be tweaked temporarily to match other view's zoom. (This does not affect the manual | ||||||
1157 | // cursor-messaging done in the non print-twips mode) | ||||||
1158 | SuppressEditViewMessagesGuard aGuard(*pEditView); | ||||||
1159 | |||||||
1160 | pEditView->SetOutputArea(rDevice.PixelToLogic(aEditRect)); | ||||||
1161 | pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice); | ||||||
1162 | |||||||
1163 | // EditView will do the cursor notifications correctly if we're in | ||||||
1164 | // print-twips messaging mode. | ||||||
1165 | if (!comphelper::LibreOfficeKit::isCompatFlagSet( | ||||||
1166 | comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs)) | ||||||
1167 | { | ||||||
1168 | // Now we need to get relative cursor position within the editview. | ||||||
1169 | // This is for sending the pixel-aligned twips position of the cursor to the specific views with | ||||||
1170 | // the same given zoom level. | ||||||
1171 | tools::Rectangle aCursorRect = pEditView->GetEditCursor(); | ||||||
1172 | Point aCursPos = OutputDevice::LogicToLogic(aCursorRect.TopLeft(), | ||||||
1173 | MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip)); | ||||||
1174 | |||||||
1175 | const MapMode& rDevMM = rDevice.GetMapMode(); | ||||||
1176 | MapMode aMM(MapUnit::MapTwip); | ||||||
1177 | aMM.SetScaleX(rDevMM.GetScaleX()); | ||||||
1178 | aMM.SetScaleY(rDevMM.GetScaleY()); | ||||||
1179 | |||||||
1180 | aBGAbs.AdjustLeft(1); | ||||||
1181 | aBGAbs.AdjustTop(1); | ||||||
1182 | aCursorRect = OutputDevice::PixelToLogic(aBGAbs, aMM); | ||||||
1183 | aCursorRect.setWidth(0); | ||||||
1184 | aCursorRect.Move(aCursPos.getX(), 0); | ||||||
1185 | // Sends view cursor position to views of all matching zooms if needed (avoids duplicates). | ||||||
1186 | InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), aMM.GetScaleY()); | ||||||
1187 | } | ||||||
1188 | |||||||
1189 | // Rollback the mapmode and 'output area'. | ||||||
1190 | SetMapMode(aOrigMapMode); | ||||||
1191 | pEditView->SetOutputArea(aOrigOutputArea); | ||||||
1192 | } | ||||||
1193 | else | ||||||
1194 | { | ||||||
1195 | tools::Rectangle aEditRect(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); | ||||||
1196 | pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice); | ||||||
1197 | } | ||||||
1198 | |||||||
1199 | rDevice.SetMapMode(MapMode(MapUnit::MapPixel)); | ||||||
1200 | |||||||
1201 | // restore the cursor it was originally visible | ||||||
1202 | if (bVisCursor) | ||||||
1203 | pCrsr->Show(); | ||||||
1204 | } | ||||||
1205 | |||||||
1206 | if (mrViewData.HasEditView(eWhich)) | ||||||
1207 | { | ||||||
1208 | // flush OverlayManager before changing the MapMode | ||||||
1209 | flushOverlayManager(); | ||||||
1210 | |||||||
1211 | // set MapMode for text edit | ||||||
1212 | rDevice.SetMapMode(mrViewData.GetLogicMode()); | ||||||
1213 | } | ||||||
1214 | else | ||||||
1215 | rDevice.SetMapMode(aDrawMode); | ||||||
1216 | |||||||
1217 | if (mpNoteMarker) | ||||||
1218 | mpNoteMarker->Draw(); // Above the cursor, in drawing map mode | ||||||
1219 | } | ||||||
1220 | |||||||
1221 | namespace | ||||||
1222 | { | ||||||
1223 | template<typename IndexType> | ||||||
1224 | void lcl_getBoundingRowColumnforTile(ScViewData& rViewData, | ||||||
1225 | long nTileStartPosPx, long nTileEndPosPx, | ||||||
1226 | sal_Int32& nTopLeftTileOffset, sal_Int32& nTopLeftTileOrigin, | ||||||
1227 | sal_Int32& nTopLeftTileIndex, sal_Int32& nBottomRightTileIndex) | ||||||
1228 | { | ||||||
1229 | const bool bColumnHeader = std::is_same<IndexType, SCCOL>::value; | ||||||
1230 | |||||||
1231 | SCTAB nTab = rViewData.GetTabNo(); | ||||||
1232 | |||||||
1233 | IndexType nStartIndex = -1; | ||||||
1234 | IndexType nEndIndex = -1; | ||||||
1235 | long nStartPosPx = 0; | ||||||
1236 | long nEndPosPx = 0; | ||||||
1237 | |||||||
1238 | ScPositionHelper& rPositionHelper = | ||||||
1239 | bColumnHeader ? rViewData.GetLOKWidthHelper() : rViewData.GetLOKHeightHelper(); | ||||||
1240 | const auto& rStartNearest = rPositionHelper.getNearestByPosition(nTileStartPosPx); | ||||||
1241 | const auto& rEndNearest = rPositionHelper.getNearestByPosition(nTileEndPosPx); | ||||||
1242 | |||||||
1243 | ScBoundsProvider aBoundsProvider(rViewData, nTab, bColumnHeader); | ||||||
1244 | aBoundsProvider.Compute(rStartNearest, rEndNearest, nTileStartPosPx, nTileEndPosPx); | ||||||
1245 | aBoundsProvider.GetStartIndexAndPosition(nStartIndex, nStartPosPx); ++nStartIndex; | ||||||
1246 | aBoundsProvider.GetEndIndexAndPosition(nEndIndex, nEndPosPx); | ||||||
1247 | |||||||
1248 | nTopLeftTileOffset = nTileStartPosPx - nStartPosPx; | ||||||
1249 | nTopLeftTileOrigin = nStartPosPx; | ||||||
1250 | nTopLeftTileIndex = nStartIndex; | ||||||
1251 | nBottomRightTileIndex = nEndIndex; | ||||||
1252 | } | ||||||
1253 | |||||||
1254 | class ScLOKProxyObjectContact final : public sdr::contact::ObjectContactOfPageView | ||||||
1255 | { | ||||||
1256 | private: | ||||||
1257 | sdr::contact::ObjectContact& mrRealObjectContact; | ||||||
1258 | |||||||
1259 | public: | ||||||
1260 | explicit ScLOKProxyObjectContact( | ||||||
1261 | sdr::contact::ObjectContact& rRealOC, | ||||||
1262 | SdrPageWindow& rPageWindow, | ||||||
1263 | const char* pDebugName) : | ||||||
1264 | ObjectContactOfPageView(rPageWindow, pDebugName), | ||||||
1265 | mrRealObjectContact(rRealOC) | ||||||
1266 | { | ||||||
1267 | } | ||||||
1268 | |||||||
1269 | virtual bool supportsGridOffsets() const override { return true; } | ||||||
1270 | |||||||
1271 | virtual void calculateGridOffsetForViewOjectContact( | ||||||
1272 | basegfx::B2DVector& rTarget, | ||||||
1273 | const sdr::contact::ViewObjectContact& rClient) const override | ||||||
1274 | { | ||||||
1275 | SdrObject* pTargetSdrObject(rClient.GetViewContact().TryToGetSdrObject()); | ||||||
1276 | if (pTargetSdrObject) | ||||||
1277 | rTarget = pTargetSdrObject->GetViewContact().GetViewObjectContact(mrRealObjectContact).getGridOffset(); | ||||||
1278 | } | ||||||
1279 | }; | ||||||
1280 | |||||||
1281 | class ScLOKDrawView : public FmFormView | ||||||
1282 | { | ||||||
1283 | public: | ||||||
1284 | ScLOKDrawView(OutputDevice* pOut, ScViewData& rData) : | ||||||
1285 | FmFormView(*rData.GetDocument().GetDrawLayer(), pOut), | ||||||
1286 | pScDrawView(rData.GetScDrawView()) | ||||||
1287 | { | ||||||
1288 | } | ||||||
1289 | |||||||
1290 | virtual sdr::contact::ObjectContact* createViewSpecificObjectContact( | ||||||
1291 | SdrPageWindow& rPageWindow, const char* pDebugName) const override | ||||||
1292 | { | ||||||
1293 | if (!pScDrawView) | ||||||
1294 | return SdrView::createViewSpecificObjectContact(rPageWindow, pDebugName); | ||||||
1295 | |||||||
1296 | SdrPageView* pPageView(pScDrawView->GetSdrPageView()); | ||||||
1297 | if (!pPageView) | ||||||
1298 | return SdrView::createViewSpecificObjectContact(rPageWindow, pDebugName); | ||||||
1299 | |||||||
1300 | SdrPageWindow* pSdrPageWindow = pPageView->GetPageWindow(0); | ||||||
1301 | if (!pSdrPageWindow) | ||||||
1302 | return SdrView::createViewSpecificObjectContact(rPageWindow, pDebugName); | ||||||
1303 | |||||||
1304 | return new ScLOKProxyObjectContact(pSdrPageWindow->GetObjectContact(), rPageWindow, pDebugName); | ||||||
1305 | } | ||||||
1306 | |||||||
1307 | private: | ||||||
1308 | ScDrawView* pScDrawView; | ||||||
1309 | }; | ||||||
1310 | } // anonymous namespace | ||||||
1311 | |||||||
1312 | void ScGridWindow::PaintTile( VirtualDevice& rDevice, | ||||||
1313 | int nOutputWidth, int nOutputHeight, | ||||||
1314 | int nTilePosX, int nTilePosY, | ||||||
1315 | long nTileWidth, long nTileHeight ) | ||||||
1316 | { | ||||||
1317 | Fraction origZoomX = mrViewData.GetZoomX(); | ||||||
1318 | Fraction origZoomY = mrViewData.GetZoomY(); | ||||||
1319 | |||||||
1320 | // Output size is in pixels while tile position and size are in logical units (twips). | ||||||
1321 | |||||||
1322 | // Assumption: always paint the whole sheet i.e. "visible" range is always | ||||||
1323 | // from (0,0) to last data position. | ||||||
1324 | |||||||
1325 | // Tile geometry is independent of the zoom level, but the output size is | ||||||
1326 | // dependent of the zoom level. Determine the correct zoom level before | ||||||
1327 | // we start. | ||||||
1328 | |||||||
1329 | // FIXME the painting works using a mixture of drawing with coordinates in | ||||||
1330 | // pixels and in logic coordinates; it should be cleaned up to use logic | ||||||
1331 | // coords only, and avoid all the SetMapMode()'s. | ||||||
1332 | // Similarly to Writer, we should set the mapmode once on the rDevice, and | ||||||
1333 | // not care about any zoom settings. | ||||||
1334 | |||||||
1335 | Fraction aFracX(long(nOutputWidth * TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0)), nTileWidth); | ||||||
1336 | Fraction aFracY(long(nOutputHeight * TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0)), nTileHeight); | ||||||
1337 | |||||||
1338 | const bool bChangeZoom = (aFracX != origZoomX || aFracY != origZoomY); | ||||||
1339 | |||||||
1340 | // page break zoom, and aLogicMode in ScViewData | ||||||
1341 | // FIXME: there are issues when SetZoom is called conditionally. | ||||||
1342 | mrViewData.SetZoom(aFracX, aFracY, true); | ||||||
1343 | if (bChangeZoom) | ||||||
1344 | { | ||||||
1345 | if (ScDrawView* pDrawView = mrViewData.GetScDrawView()) | ||||||
1346 | pDrawView->resetGridOffsetsForAllSdrPageViews(); | ||||||
1347 | } | ||||||
1348 | |||||||
1349 | const double fTilePosXPixel = static_cast<double>(nTilePosX) * nOutputWidth / nTileWidth; | ||||||
1350 | const double fTilePosYPixel = static_cast<double>(nTilePosY) * nOutputHeight / nTileHeight; | ||||||
1351 | const double fTileBottomPixel = static_cast<double>(nTilePosY + nTileHeight) * nOutputHeight / nTileHeight; | ||||||
1352 | const double fTileRightPixel = static_cast<double>(nTilePosX + nTileWidth) * nOutputWidth / nTileWidth; | ||||||
1353 | |||||||
1354 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
1355 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
1356 | |||||||
1357 | const double fPPTX = mrViewData.GetPPTX(); | ||||||
1358 | const double fPPTY = mrViewData.GetPPTY(); | ||||||
1359 | |||||||
1360 | // find approximate col/row offsets of nearby. | ||||||
1361 | sal_Int32 nTopLeftTileRowOffset = 0; | ||||||
1362 | sal_Int32 nTopLeftTileColOffset = 0; | ||||||
1363 | sal_Int32 nTopLeftTileRowOrigin = 0; | ||||||
1364 | sal_Int32 nTopLeftTileColOrigin = 0; | ||||||
1365 | |||||||
1366 | sal_Int32 nTopLeftTileRow = 0; | ||||||
1367 | sal_Int32 nTopLeftTileCol = 0; | ||||||
1368 | sal_Int32 nBottomRightTileRow = 0; | ||||||
1369 | sal_Int32 nBottomRightTileCol = 0; | ||||||
1370 | |||||||
1371 | lcl_getBoundingRowColumnforTile<SCROW>(mrViewData, | ||||||
1372 | fTilePosYPixel, fTileBottomPixel, | ||||||
1373 | nTopLeftTileRowOffset, nTopLeftTileRowOrigin, | ||||||
1374 | nTopLeftTileRow, nBottomRightTileRow); | ||||||
1375 | |||||||
1376 | lcl_getBoundingRowColumnforTile<SCCOL>(mrViewData, | ||||||
1377 | fTilePosXPixel, fTileRightPixel, | ||||||
1378 | nTopLeftTileColOffset, nTopLeftTileColOrigin, | ||||||
1379 | nTopLeftTileCol, nBottomRightTileCol); | ||||||
1380 | |||||||
1381 | // Enlarge | ||||||
1382 | nBottomRightTileCol++; | ||||||
1383 | nBottomRightTileRow++; | ||||||
1384 | |||||||
1385 | if (nBottomRightTileCol > rDoc.MaxCol()) | ||||||
1386 | nBottomRightTileCol = rDoc.MaxCol(); | ||||||
1387 | |||||||
1388 | if (nBottomRightTileRow > MAXTILEDROW) | ||||||
1389 | nBottomRightTileRow = MAXTILEDROW; | ||||||
1390 | |||||||
1391 | // size of the document including drawings, charts, etc. | ||||||
1392 | SCCOL nEndCol = 0; | ||||||
1393 | SCROW nEndRow = 0; | ||||||
1394 | rDoc.GetTiledRenderingArea(nTab, nEndCol, nEndRow); | ||||||
1395 | |||||||
1396 | if (nEndCol < nBottomRightTileCol) | ||||||
1397 | nEndCol = nBottomRightTileCol; | ||||||
1398 | |||||||
1399 | if (nEndRow < nBottomRightTileRow) | ||||||
1400 | nEndRow = nBottomRightTileRow; | ||||||
1401 | |||||||
1402 | nTopLeftTileCol = std::max<sal_Int32>(nTopLeftTileCol, 0); | ||||||
1403 | nTopLeftTileRow = std::max<sal_Int32>(nTopLeftTileRow, 0); | ||||||
1404 | nTopLeftTileColOrigin = nTopLeftTileColOrigin * TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0); | ||||||
1405 | nTopLeftTileRowOrigin = nTopLeftTileRowOrigin * TWIPS_PER_PIXEL((20.0 * 72.0) / 96.0); | ||||||
1406 | |||||||
1407 | // Checkout -> 'rDoc.ExtendMerge' ... if we miss merged cells. | ||||||
1408 | |||||||
1409 | // Origin must be the offset of the first col and row | ||||||
1410 | // containing our top-left pixel. | ||||||
1411 | const MapMode aOriginalMode = rDevice.GetMapMode(); | ||||||
1412 | MapMode aAbsMode = aOriginalMode; | ||||||
1413 | const Point aOrigin(-nTopLeftTileColOrigin, -nTopLeftTileRowOrigin); | ||||||
1414 | aAbsMode.SetOrigin(aOrigin); | ||||||
1415 | rDevice.SetMapMode(aAbsMode); | ||||||
1416 | |||||||
1417 | ScTableInfo aTabInfo(nEndRow + 3); | ||||||
1418 | rDoc.FillInfo(aTabInfo, nTopLeftTileCol, nTopLeftTileRow, | ||||||
1419 | nBottomRightTileCol, nBottomRightTileRow, | ||||||
1420 | nTab, fPPTX, fPPTY, false, false); | ||||||
1421 | |||||||
1422 | // FIXME: is this called some | ||||||
1423 | // Point aScrPos = mrViewData.GetScrPos( nX1, nY1, eWhich ); | ||||||
1424 | |||||||
1425 | ScOutputData aOutputData(&rDevice, OUTTYPE_WINDOW, aTabInfo, &rDoc, nTab, | ||||||
1426 | -nTopLeftTileColOffset, | ||||||
1427 | -nTopLeftTileRowOffset, | ||||||
1428 | nTopLeftTileCol, nTopLeftTileRow, | ||||||
1429 | nBottomRightTileCol, nBottomRightTileRow, | ||||||
1430 | fPPTX, fPPTY, nullptr, nullptr); | ||||||
1431 | |||||||
1432 | // setup the SdrPage so that drawinglayer works correctly | ||||||
1433 | ScDrawLayer* pModel = rDoc.GetDrawLayer(); | ||||||
1434 | if (pModel) | ||||||
1435 | { | ||||||
1436 | bool bPrintTwipsMsgs = comphelper::LibreOfficeKit::isCompatFlagSet( | ||||||
1437 | comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs); | ||||||
1438 | mpLOKDrawView.reset(bPrintTwipsMsgs ? | ||||||
1439 | new ScLOKDrawView( | ||||||
1440 | &rDevice, | ||||||
1441 | mrViewData) : | ||||||
1442 | new FmFormView( | ||||||
1443 | *pModel, | ||||||
1444 | &rDevice)); | ||||||
1445 | mpLOKDrawView->ShowSdrPage(mpLOKDrawView->GetModel()->GetPage(nTab)); | ||||||
1446 | aOutputData.SetDrawView(mpLOKDrawView.get()); | ||||||
1447 | aOutputData.SetSpellCheckContext(mpSpellCheckCxt.get()); | ||||||
1448 | } | ||||||
1449 | |||||||
1450 | // draw the content | ||||||
1451 | DrawContent(rDevice, aTabInfo, aOutputData, true); | ||||||
1452 | rDevice.SetMapMode(aOriginalMode); | ||||||
1453 | |||||||
1454 | // Flag drawn formula cells "unchanged". | ||||||
1455 | rDoc.ResetChanged(ScRange(nTopLeftTileCol, nTopLeftTileRow, nTab, nBottomRightTileCol, nBottomRightTileRow, nTab)); | ||||||
1456 | rDoc.PrepareFormulaCalc(); | ||||||
1457 | |||||||
1458 | mrViewData.SetZoom(origZoomX, origZoomY, true); | ||||||
1459 | if (bChangeZoom) | ||||||
1460 | { | ||||||
1461 | if (ScDrawView* pDrawView = mrViewData.GetScDrawView()) | ||||||
1462 | pDrawView->resetGridOffsetsForAllSdrPageViews(); | ||||||
1463 | } | ||||||
1464 | } | ||||||
1465 | |||||||
1466 | void ScGridWindow::LogicInvalidate(const tools::Rectangle* pRectangle) | ||||||
1467 | { | ||||||
1468 | OString sRectangle; | ||||||
1469 | if (!pRectangle) | ||||||
1470 | sRectangle = "EMPTY"; | ||||||
1471 | else | ||||||
1472 | { | ||||||
1473 | tools::Rectangle aRectangle(*pRectangle); | ||||||
1474 | // When dragging shapes the map mode is disabled. | ||||||
1475 | if (IsMapModeEnabled()) | ||||||
1476 | { | ||||||
1477 | if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM) | ||||||
1478 | aRectangle = OutputDevice::LogicToLogic(aRectangle, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip)); | ||||||
1479 | } | ||||||
1480 | else | ||||||
1481 | aRectangle = PixelToLogic(aRectangle, MapMode(MapUnit::MapTwip)); | ||||||
1482 | sRectangle = aRectangle.toString(); | ||||||
1483 | } | ||||||
1484 | |||||||
1485 | ScTabViewShell* pViewShell = mrViewData.GetViewShell(); | ||||||
1486 | SfxLokHelper::notifyInvalidation(pViewShell, sRectangle); | ||||||
1487 | } | ||||||
1488 | |||||||
1489 | void ScGridWindow::SetCellSelectionPixel(int nType, int nPixelX, int nPixelY) | ||||||
1490 | { | ||||||
1491 | ScTabView* pTabView = mrViewData.GetView(); | ||||||
1492 | ScTabViewShell* pViewShell = mrViewData.GetViewShell(); | ||||||
1493 | ScInputHandler* pInputHandler = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl(pViewShell); | ||||||
1494 | |||||||
1495 | if (pInputHandler && pInputHandler->IsInputMode()) | ||||||
1496 | { | ||||||
1497 | // we need to switch off the editeng | ||||||
1498 | ScTabView::UpdateInputLine(); | ||||||
1499 | pViewShell->UpdateInputHandler(); | ||||||
1500 | } | ||||||
1501 | |||||||
1502 | if (nType == LOK_SETTEXTSELECTION_RESET) | ||||||
1503 | { | ||||||
1504 | pTabView->DoneBlockMode(); | ||||||
1505 | return; | ||||||
1506 | } | ||||||
1507 | |||||||
1508 | // obtain the current selection | ||||||
1509 | ScRangeList aRangeList = mrViewData.GetMarkData().GetMarkedRanges(); | ||||||
1510 | |||||||
1511 | SCCOL nCol1, nCol2; | ||||||
1512 | SCROW nRow1, nRow2; | ||||||
1513 | SCTAB nTab1, nTab2; | ||||||
1514 | |||||||
1515 | bool bWasEmpty = false; | ||||||
1516 | if (aRangeList.empty()) | ||||||
1517 | { | ||||||
1518 | nCol1 = nCol2 = mrViewData.GetCurX(); | ||||||
1519 | nRow1 = nRow2 = mrViewData.GetCurY(); | ||||||
1520 | bWasEmpty = true; | ||||||
1521 | } | ||||||
1522 | else | ||||||
1523 | aRangeList.Combine().GetVars(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); | ||||||
1524 | |||||||
1525 | // convert the coordinates to column/row | ||||||
1526 | SCCOL nNewPosX; | ||||||
1527 | SCROW nNewPosY; | ||||||
1528 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
1529 | mrViewData.GetPosFromPixel(nPixelX, nPixelY, eWhich, nNewPosX, nNewPosY); | ||||||
1530 | |||||||
1531 | // change the selection | ||||||
1532 | switch (nType) | ||||||
1533 | { | ||||||
1534 | case LOK_SETTEXTSELECTION_START: | ||||||
1535 | if (nNewPosX != nCol1 || nNewPosY != nRow1 || bWasEmpty) | ||||||
1536 | { | ||||||
1537 | pTabView->SetCursor(nNewPosX, nNewPosY); | ||||||
1538 | pTabView->DoneBlockMode(); | ||||||
1539 | pTabView->InitBlockMode(nNewPosX, nNewPosY, nTab, true); | ||||||
1540 | pTabView->MarkCursor(nCol2, nRow2, nTab); | ||||||
1541 | } | ||||||
1542 | break; | ||||||
1543 | case LOK_SETTEXTSELECTION_END: | ||||||
1544 | if (nNewPosX != nCol2 || nNewPosY != nRow2 || bWasEmpty) | ||||||
1545 | { | ||||||
1546 | pTabView->SetCursor(nCol1, nRow1); | ||||||
1547 | pTabView->DoneBlockMode(); | ||||||
1548 | pTabView->InitBlockMode(nCol1, nRow1, nTab, true); | ||||||
1549 | pTabView->MarkCursor(nNewPosX, nNewPosY, nTab); | ||||||
1550 | } | ||||||
1551 | break; | ||||||
1552 | default: | ||||||
1553 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx" , 1553, __extension__ __PRETTY_FUNCTION__)); | ||||||
1554 | break; | ||||||
1555 | } | ||||||
1556 | } | ||||||
1557 | |||||||
1558 | void ScGridWindow::CheckNeedsRepaint() | ||||||
1559 | { | ||||||
1560 | // called at the end of painting, and from timer after background text width calculation | ||||||
1561 | |||||||
1562 | if (!bNeedsRepaint) | ||||||
1563 | return; | ||||||
1564 | |||||||
1565 | bNeedsRepaint = false; | ||||||
1566 | if (aRepaintPixel.IsEmpty()) | ||||||
1567 | Invalidate(); | ||||||
1568 | else | ||||||
1569 | Invalidate(PixelToLogic(aRepaintPixel)); | ||||||
1570 | aRepaintPixel = tools::Rectangle(); | ||||||
1571 | |||||||
1572 | // selection function in status bar might also be invalid | ||||||
1573 | SfxBindings& rBindings = mrViewData.GetBindings(); | ||||||
1574 | rBindings.Invalidate( SID_STATUS_SUM((26000 + 100) + 30) ); | ||||||
1575 | rBindings.Invalidate( SID_ATTR_SIZETypedWhichId<SvxSizeItem>( 10000 + 224 ) ); | ||||||
1576 | rBindings.Invalidate( SID_TABLE_CELL( 10000 + 225 ) ); | ||||||
1577 | } | ||||||
1578 | |||||||
1579 | void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, vcl::RenderContext& rRenderContext) | ||||||
1580 | { | ||||||
1581 | ScPageBreakData* pPageData = mrViewData.GetView()->GetPageBreakData(); | ||||||
1582 | if (!pPageData) | ||||||
1583 | return; | ||||||
1584 | |||||||
1585 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
1586 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
1587 | Size aWinSize = GetOutputSizePixel(); | ||||||
1588 | const svtools::ColorConfig& rColorCfg = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetColorConfig(); | ||||||
1589 | Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor ); | ||||||
1590 | Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor ); | ||||||
1591 | |||||||
1592 | OUString aPageStr = ScResId( STR_PGNUMreinterpret_cast<char const *>("STR_PGNUM" "\004" u8"Page %1" ) ); | ||||||
1593 | if ( nPageScript == SvtScriptType::NONE ) | ||||||
1594 | { | ||||||
1595 | // get script type of translated "Page" string only once | ||||||
1596 | nPageScript = rDoc.GetStringScriptType( aPageStr ); | ||||||
1597 | if (nPageScript == SvtScriptType::NONE) | ||||||
1598 | nPageScript = ScGlobal::GetDefaultScriptType(); | ||||||
1599 | } | ||||||
1600 | |||||||
1601 | vcl::Font aFont; | ||||||
1602 | std::unique_ptr<ScEditEngineDefaulter> pEditEng; | ||||||
1603 | const ScPatternAttr& rDefPattern = rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN); | ||||||
1604 | if ( nPageScript == SvtScriptType::LATIN ) | ||||||
1605 | { | ||||||
1606 | // use single font and call DrawText directly | ||||||
1607 | rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK ); | ||||||
1608 | aFont.SetColor( COL_LIGHTGRAY ); | ||||||
1609 | // font size is set as needed | ||||||
1610 | } | ||||||
1611 | else | ||||||
1612 | { | ||||||
1613 | // use EditEngine to draw mixed-script string | ||||||
1614 | pEditEng.reset(new ScEditEngineDefaulter( EditEngine::CreatePool(), true )); | ||||||
1615 | pEditEng->SetRefMapMode(rRenderContext.GetMapMode()); | ||||||
1616 | auto pEditDefaults = std::make_unique<SfxItemSet>( pEditEng->GetEmptyItemSet() ); | ||||||
1617 | rDefPattern.FillEditItemSet( pEditDefaults.get() ); | ||||||
1618 | pEditDefaults->Put( SvxColorItem( COL_LIGHTGRAY, EE_CHAR_COLOR ) ); | ||||||
1619 | pEditEng->SetDefaults( std::move(pEditDefaults) ); | ||||||
1620 | } | ||||||
1621 | |||||||
1622 | sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() ); | ||||||
1623 | for (sal_uInt16 nPos=0; nPos<nCount; nPos++) | ||||||
1624 | { | ||||||
1625 | ScPrintRangeData& rData = pPageData->GetData(nPos); | ||||||
1626 | ScRange aRange = rData.GetPrintRange(); | ||||||
1627 | if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 && | ||||||
1628 | aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 ) | ||||||
1629 | { | ||||||
1630 | // 3 pixel frame around the print area | ||||||
1631 | // (middle pixel on the grid lines) | ||||||
1632 | |||||||
1633 | rRenderContext.SetLineColor(); | ||||||
1634 | if (rData.IsAutomatic()) | ||||||
1635 | rRenderContext.SetFillColor( aAutomatic ); | ||||||
1636 | else | ||||||
1637 | rRenderContext.SetFillColor( aManual ); | ||||||
1638 | |||||||
1639 | Point aStart = mrViewData.GetScrPos( | ||||||
1640 | aRange.aStart.Col(), aRange.aStart.Row(), eWhich, true ); | ||||||
1641 | Point aEnd = mrViewData.GetScrPos( | ||||||
1642 | aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, true ); | ||||||
1643 | aStart.AdjustX( -2 ); | ||||||
1644 | aStart.AdjustY( -2 ); | ||||||
1645 | |||||||
1646 | // Prevent overflows: | ||||||
1647 | if ( aStart.X() < -10 ) aStart.setX( -10 ); | ||||||
1648 | if ( aStart.Y() < -10 ) aStart.setY( -10 ); | ||||||
1649 | if ( aEnd.X() > aWinSize.Width() + 10 ) | ||||||
1650 | aEnd.setX( aWinSize.Width() + 10 ); | ||||||
1651 | if ( aEnd.Y() > aWinSize.Height() + 10 ) | ||||||
1652 | aEnd.setY( aWinSize.Height() + 10 ); | ||||||
1653 | |||||||
1654 | rRenderContext.DrawRect( tools::Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) ); | ||||||
1655 | rRenderContext.DrawRect( tools::Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) ); | ||||||
1656 | rRenderContext.DrawRect( tools::Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) ); | ||||||
1657 | rRenderContext.DrawRect( tools::Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) ); | ||||||
1658 | |||||||
1659 | // Page breaks | ||||||
1660 | //! Display differently (dashed ????) | ||||||
1661 | |||||||
1662 | size_t nColBreaks = rData.GetPagesX(); | ||||||
1663 | const SCCOL* pColEnd = rData.GetPageEndX(); | ||||||
1664 | size_t nColPos; | ||||||
1665 | for (nColPos=0; nColPos+1<nColBreaks; nColPos++) | ||||||
1666 | { | ||||||
1667 | SCCOL nBreak = pColEnd[nColPos]+1; | ||||||
1668 | if ( nBreak >= nX1 && nBreak <= nX2+1 ) | ||||||
1669 | { | ||||||
1670 | //! Search for hidden | ||||||
1671 | if (rDoc.HasColBreak(nBreak, nTab) & ScBreakType::Manual) | ||||||
1672 | rRenderContext.SetFillColor( aManual ); | ||||||
1673 | else | ||||||
1674 | rRenderContext.SetFillColor( aAutomatic ); | ||||||
1675 | Point aBreak = mrViewData.GetScrPos( | ||||||
1676 | nBreak, aRange.aStart.Row(), eWhich, true ); | ||||||
1677 | rRenderContext.DrawRect( tools::Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) ); | ||||||
1678 | } | ||||||
1679 | } | ||||||
1680 | |||||||
1681 | size_t nRowBreaks = rData.GetPagesY(); | ||||||
1682 | const SCROW* pRowEnd = rData.GetPageEndY(); | ||||||
1683 | size_t nRowPos; | ||||||
1684 | for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++) | ||||||
1685 | { | ||||||
1686 | SCROW nBreak = pRowEnd[nRowPos]+1; | ||||||
1687 | if ( nBreak >= nY1 && nBreak <= nY2+1 ) | ||||||
1688 | { | ||||||
1689 | //! Search for hidden | ||||||
1690 | if (rDoc.HasRowBreak(nBreak, nTab) & ScBreakType::Manual) | ||||||
1691 | rRenderContext.SetFillColor( aManual ); | ||||||
1692 | else | ||||||
1693 | rRenderContext.SetFillColor( aAutomatic ); | ||||||
1694 | Point aBreak = mrViewData.GetScrPos( | ||||||
1695 | aRange.aStart.Col(), nBreak, eWhich, true ); | ||||||
1696 | rRenderContext.DrawRect( tools::Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) ); | ||||||
1697 | } | ||||||
1698 | } | ||||||
1699 | |||||||
1700 | // Page numbers | ||||||
1701 | |||||||
1702 | SCROW nPrStartY = aRange.aStart.Row(); | ||||||
1703 | for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++) | ||||||
1704 | { | ||||||
1705 | SCROW nPrEndY = pRowEnd[nRowPos]; | ||||||
1706 | if ( nPrEndY >= nY1 && nPrStartY <= nY2 ) | ||||||
1707 | { | ||||||
1708 | SCCOL nPrStartX = aRange.aStart.Col(); | ||||||
1709 | for (nColPos=0; nColPos<nColBreaks; nColPos++) | ||||||
1710 | { | ||||||
1711 | SCCOL nPrEndX = pColEnd[nColPos]; | ||||||
1712 | if ( nPrEndX >= nX1 && nPrStartX <= nX2 ) | ||||||
1713 | { | ||||||
1714 | Point aPageStart = mrViewData.GetScrPos( | ||||||
1715 | nPrStartX, nPrStartY, eWhich, true ); | ||||||
1716 | Point aPageEnd = mrViewData.GetScrPos( | ||||||
1717 | nPrEndX+1,nPrEndY+1, eWhich, true ); | ||||||
1718 | |||||||
1719 | long nPageNo = rData.GetFirstPage(); | ||||||
1720 | if ( rData.IsTopDown() ) | ||||||
1721 | nPageNo += static_cast<long>(nColPos)*nRowBreaks+nRowPos; | ||||||
1722 | else | ||||||
1723 | nPageNo += static_cast<long>(nRowPos)*nColBreaks+nColPos; | ||||||
1724 | |||||||
1725 | OUString aThisPageStr = aPageStr.replaceFirst("%1", OUString::number(nPageNo)); | ||||||
1726 | |||||||
1727 | if ( pEditEng ) | ||||||
1728 | { | ||||||
1729 | // find right font size with EditEngine | ||||||
1730 | long nHeight = 100; | ||||||
1731 | pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); | ||||||
1732 | pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); | ||||||
1733 | pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); | ||||||
1734 | pEditEng->SetTextCurrentDefaults( aThisPageStr ); | ||||||
1735 | Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() ); | ||||||
1736 | |||||||
1737 | // 40% of width or 60% of height | ||||||
1738 | long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width(); | ||||||
1739 | long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height(); | ||||||
1740 | nHeight = std::min(nSizeX,nSizeY); | ||||||
1741 | pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); | ||||||
1742 | pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); | ||||||
1743 | pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); | ||||||
1744 | |||||||
1745 | // centered output with EditEngine | ||||||
1746 | Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() ); | ||||||
1747 | Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2, | ||||||
1748 | (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 ); | ||||||
1749 | pEditEng->Draw( &rRenderContext, aPos ); | ||||||
1750 | } | ||||||
1751 | else | ||||||
1752 | { | ||||||
1753 | // find right font size for DrawText | ||||||
1754 | aFont.SetFontSize( Size( 0,100 ) ); | ||||||
1755 | rRenderContext.SetFont( aFont ); | ||||||
1756 | Size aSize100(rRenderContext.GetTextWidth( aThisPageStr ), rRenderContext.GetTextHeight() ); | ||||||
1757 | |||||||
1758 | // 40% of width or 60% of height | ||||||
1759 | long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width(); | ||||||
1760 | long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height(); | ||||||
1761 | aFont.SetFontSize( Size( 0,std::min(nSizeX,nSizeY) ) ); | ||||||
1762 | rRenderContext.SetFont( aFont ); | ||||||
1763 | |||||||
1764 | // centered output with DrawText | ||||||
1765 | Size aTextSize(rRenderContext.GetTextWidth( aThisPageStr ), rRenderContext.GetTextHeight() ); | ||||||
1766 | Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2, | ||||||
1767 | (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 ); | ||||||
1768 | rRenderContext.DrawText( aPos, aThisPageStr ); | ||||||
1769 | } | ||||||
1770 | } | ||||||
1771 | nPrStartX = nPrEndX + 1; | ||||||
1772 | } | ||||||
1773 | } | ||||||
1774 | nPrStartY = nPrEndY + 1; | ||||||
1775 | } | ||||||
1776 | } | ||||||
1777 | } | ||||||
1778 | } | ||||||
1779 | |||||||
1780 | void ScGridWindow::DrawButtons(SCCOL nX1, SCCOL nX2, const ScTableInfo& rTabInfo, OutputDevice* pContentDev) | ||||||
1781 | { | ||||||
1782 | aComboButton.SetOutputDevice( pContentDev ); | ||||||
1783 | |||||||
1784 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
1785 | ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &mrViewData.GetZoomY(), &rDoc); | ||||||
1786 | |||||||
1787 | SCCOL nCol; | ||||||
1788 | SCROW nRow; | ||||||
1789 | SCSIZE nArrY; | ||||||
1790 | SCSIZE nQuery; | ||||||
1791 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
1792 | ScDBData* pDBData = nullptr; | ||||||
1793 | std::unique_ptr<ScQueryParam> pQueryParam; | ||||||
1794 | |||||||
1795 | RowInfo* pRowInfo = rTabInfo.mpRowInfo.get(); | ||||||
1796 | sal_uInt16 nArrCount = rTabInfo.mnArrCount; | ||||||
1797 | |||||||
1798 | bool bLayoutRTL = rDoc.IsLayoutRTL( nTab ); | ||||||
1799 | |||||||
1800 | Point aOldPos = aComboButton.GetPosPixel(); // store state for MouseDown/Up | ||||||
1801 | Size aOldSize = aComboButton.GetSizePixel(); | ||||||
1802 | |||||||
1803 | for (nArrY=1; nArrY+1<nArrCount; nArrY++) | ||||||
1804 | { | ||||||
1805 | if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged ) | ||||||
1806 | { | ||||||
1807 | RowInfo* pThisRowInfo = &pRowInfo[nArrY]; | ||||||
1808 | |||||||
1809 | nRow = pThisRowInfo->nRowNo; | ||||||
1810 | |||||||
1811 | for (nCol=nX1; nCol<=nX2; nCol++) | ||||||
1812 | { | ||||||
1813 | CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1]; | ||||||
1814 | //if several columns merged on a row, there should be only one auto button at the end of the columns. | ||||||
1815 | //if several rows merged on a column, the button may be in the middle, so "!pInfo->bVOverlapped" should not be used | ||||||
1816 | if ( pInfo->bAutoFilter && !pInfo->bHOverlapped ) | ||||||
1817 | { | ||||||
1818 | if (!pQueryParam) | ||||||
1819 | pQueryParam.reset(new ScQueryParam); | ||||||
1820 | |||||||
1821 | bool bNewData = true; | ||||||
1822 | if (pDBData) | ||||||
1823 | { | ||||||
1824 | SCCOL nStartCol; | ||||||
1825 | SCROW nStartRow; | ||||||
1826 | SCCOL nEndCol; | ||||||
1827 | SCROW nEndRow; | ||||||
1828 | SCTAB nAreaTab; | ||||||
1829 | pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); | ||||||
1830 | if ( nCol >= nStartCol && nCol <= nEndCol && | ||||||
1831 | nRow >= nStartRow && nRow <= nEndRow ) | ||||||
1832 | bNewData = false; | ||||||
1833 | } | ||||||
1834 | if (bNewData) | ||||||
1835 | { | ||||||
1836 | pDBData = rDoc.GetDBAtCursor( nCol, nRow, nTab, ScDBDataPortion::AREA ); | ||||||
1837 | if (pDBData) | ||||||
1838 | pDBData->GetQueryParam( *pQueryParam ); | ||||||
1839 | else | ||||||
1840 | { | ||||||
1841 | // can also be part of DataPilot table | ||||||
1842 | } | ||||||
1843 | } | ||||||
1844 | |||||||
1845 | // pQueryParam can only include MAXQUERY entries | ||||||
1846 | |||||||
1847 | bool bSimpleQuery = true; | ||||||
1848 | bool bColumnFound = false; | ||||||
1849 | if (!pQueryParam->bInplace) | ||||||
1850 | bSimpleQuery = false; | ||||||
1851 | SCSIZE nCount = pQueryParam->GetEntryCount(); | ||||||
1852 | for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery) | ||||||
1853 | if (pQueryParam->GetEntry(nQuery).bDoQuery) | ||||||
1854 | { | ||||||
1855 | // Do no restrict to EQUAL here | ||||||
1856 | // (Column head should become blue also when ">1") | ||||||
1857 | |||||||
1858 | if (pQueryParam->GetEntry(nQuery).nField == nCol) | ||||||
1859 | bColumnFound = true; | ||||||
1860 | if (nQuery > 0) | ||||||
1861 | if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND) | ||||||
1862 | bSimpleQuery = false; | ||||||
1863 | } | ||||||
1864 | |||||||
1865 | bool bArrowState = bSimpleQuery && bColumnFound; | ||||||
1866 | long nSizeX; | ||||||
1867 | long nSizeY; | ||||||
1868 | SCCOL nStartCol= nCol; | ||||||
1869 | SCROW nStartRow = nRow; | ||||||
1870 | //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. | ||||||
1871 | //should first get the start pos of the merge area, then get the nSizeX through the start pos. | ||||||
1872 | rDoc.ExtendOverlapped(nStartCol, nStartRow,nCol, nRow, nTab);//get nStartCol,nStartRow | ||||||
1873 | mrViewData.GetMergeSizePixel( nStartCol, nStartRow, nSizeX, nSizeY );//get nSizeX | ||||||
1874 | nSizeY = ScViewData::ToPixel(rDoc.GetRowHeight(nRow, nTab), mrViewData.GetPPTY()); | ||||||
1875 | Point aScrPos = mrViewData.GetScrPos( nCol, nRow, eWhich ); | ||||||
1876 | |||||||
1877 | aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1), bLayoutRTL); | ||||||
1878 | aCellBtn.setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL | ||||||
1879 | aCellBtn.setDrawBaseButton(false); | ||||||
1880 | aCellBtn.setDrawPopupButton(true); | ||||||
1881 | aCellBtn.setHasHiddenMember(bArrowState); | ||||||
1882 | aCellBtn.draw(); | ||||||
1883 | } | ||||||
1884 | } | ||||||
1885 | } | ||||||
1886 | |||||||
1887 | if ( pRowInfo[nArrY].bPivotButton && pRowInfo[nArrY].bChanged ) | ||||||
1888 | { | ||||||
1889 | RowInfo* pThisRowInfo = &pRowInfo[nArrY]; | ||||||
1890 | nRow = pThisRowInfo->nRowNo; | ||||||
1891 | for (nCol=nX1; nCol<=nX2; nCol++) | ||||||
1892 | { | ||||||
1893 | CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1]; | ||||||
1894 | if (pInfo->bHOverlapped || pInfo->bVOverlapped) | ||||||
1895 | continue; | ||||||
1896 | |||||||
1897 | Point aScrPos = mrViewData.GetScrPos( nCol, nRow, eWhich ); | ||||||
1898 | long nSizeX; | ||||||
1899 | long nSizeY; | ||||||
1900 | mrViewData.GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); | ||||||
1901 | long nPosX = aScrPos.X(); | ||||||
1902 | long nPosY = aScrPos.Y(); | ||||||
1903 | // bLayoutRTL is handled in setBoundingBox | ||||||
1904 | |||||||
1905 | OUString aStr = rDoc.GetString(nCol, nRow, nTab); | ||||||
1906 | aCellBtn.setText(aStr); | ||||||
1907 | aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1), bLayoutRTL); | ||||||
1908 | aCellBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now | ||||||
1909 | aCellBtn.setDrawBaseButton(pInfo->bPivotButton); | ||||||
1910 | aCellBtn.setDrawPopupButton(pInfo->bPivotPopupButton); | ||||||
1911 | aCellBtn.setHasHiddenMember(pInfo->bFilterActive); | ||||||
1912 | aCellBtn.draw(); | ||||||
1913 | } | ||||||
1914 | } | ||||||
1915 | |||||||
1916 | if ( !comphelper::LibreOfficeKit::isActive() && bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged ) | ||||||
1917 | { | ||||||
1918 | tools::Rectangle aRect = GetListValButtonRect( aListValPos ); | ||||||
1919 | aComboButton.SetPosPixel( aRect.TopLeft() ); | ||||||
1920 | aComboButton.SetSizePixel( aRect.GetSize() ); | ||||||
1921 | pContentDev->SetClipRegion(vcl::Region(aRect)); | ||||||
1922 | aComboButton.Draw(); | ||||||
1923 | pContentDev->SetClipRegion(); // always called from Draw() without clip region | ||||||
1924 | aComboButton.SetPosPixel( aOldPos ); // restore old state | ||||||
1925 | aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter) | ||||||
1926 | } | ||||||
1927 | } | ||||||
1928 | |||||||
1929 | pQueryParam.reset(); | ||||||
1930 | aComboButton.SetOutputDevice( this ); | ||||||
1931 | } | ||||||
1932 | |||||||
1933 | tools::Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos ) | ||||||
1934 | { | ||||||
1935 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
1936 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
1937 | bool bLayoutRTL = rDoc.IsLayoutRTL( nTab ); | ||||||
1938 | long nLayoutSign = bLayoutRTL ? -1 : 1; | ||||||
1939 | |||||||
1940 | ScDDComboBoxButton aButton( this ); // for optimal size | ||||||
1941 | Size aBtnSize = aButton.GetSizePixel(); | ||||||
1942 | |||||||
1943 | SCCOL nCol = rButtonPos.Col(); | ||||||
1944 | SCROW nRow = rButtonPos.Row(); | ||||||
1945 | |||||||
1946 | long nCellSizeX; // width of this cell, including merged | ||||||
1947 | long nDummy; | ||||||
1948 | mrViewData.GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy ); | ||||||
1949 | |||||||
1950 | // for height, only the cell's row is used, excluding merged cells | ||||||
1951 | long nCellSizeY = ScViewData::ToPixel( rDoc.GetRowHeight( nRow, nTab ), mrViewData.GetPPTY() ); | ||||||
1952 | long nAvailable = nCellSizeX; | ||||||
1953 | |||||||
1954 | // left edge of next cell if there is a non-hidden next column | ||||||
1955 | SCCOL nNextCol = nCol + 1; | ||||||
1956 | const ScMergeAttr* pMerge = rDoc.GetAttr( nCol,nRow,nTab, ATTR_MERGE ); | ||||||
1957 | if ( pMerge->GetColMerge() > 1 ) | ||||||
1958 | nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area | ||||||
1959 | while ( nNextCol <= rDoc.MaxCol() && rDoc.ColHidden(nNextCol, nTab) ) | ||||||
1960 | ++nNextCol; | ||||||
1961 | bool bNextCell = ( nNextCol <= rDoc.MaxCol() ); | ||||||
1962 | if ( bNextCell ) | ||||||
1963 | nAvailable = ScViewData::ToPixel( rDoc.GetColWidth( nNextCol, nTab ), mrViewData.GetPPTX() ); | ||||||
1964 | |||||||
1965 | if ( nAvailable < aBtnSize.Width() ) | ||||||
1966 | aBtnSize.setWidth( nAvailable ); | ||||||
1967 | if ( nCellSizeY < aBtnSize.Height() ) | ||||||
1968 | aBtnSize.setHeight( nCellSizeY ); | ||||||
1969 | |||||||
1970 | Point aPos = mrViewData.GetScrPos( nCol, nRow, eWhich, true ); | ||||||
1971 | aPos.AdjustX(nCellSizeX * nLayoutSign ); // start of next cell | ||||||
1972 | if (!bNextCell) | ||||||
1973 | aPos.AdjustX( -(aBtnSize.Width() * nLayoutSign) ); // right edge of cell if next cell not available | ||||||
1974 | aPos.AdjustY(nCellSizeY - aBtnSize.Height() ); | ||||||
1975 | // X remains at the left edge | ||||||
1976 | |||||||
1977 | if ( bLayoutRTL ) | ||||||
1978 | aPos.AdjustX( -(aBtnSize.Width()-1) ); // align right edge of button with cell border | ||||||
1979 | |||||||
1980 | return tools::Rectangle( aPos, aBtnSize ); | ||||||
1981 | } | ||||||
1982 | |||||||
1983 | bool ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab ) | ||||||
1984 | { | ||||||
1985 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
1986 | ScDBData* pDBData = rDoc.GetDBAtCursor( nCol, nRow, nTab, ScDBDataPortion::AREA ); | ||||||
1987 | ScQueryParam aQueryParam; | ||||||
1988 | |||||||
1989 | if ( pDBData ) | ||||||
1990 | pDBData->GetQueryParam( aQueryParam ); | ||||||
1991 | else | ||||||
1992 | { | ||||||
1993 | OSL_FAIL("Auto filter button without DBData")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/gridwin4.cxx" ":" "1993" ": "), "%s", "Auto filter button without DBData") ; } } while (false); | ||||||
1994 | } | ||||||
1995 | |||||||
1996 | bool bSimpleQuery = true; | ||||||
1997 | bool bColumnFound = false; | ||||||
1998 | SCSIZE nQuery; | ||||||
1999 | |||||||
2000 | if ( !aQueryParam.bInplace ) | ||||||
2001 | bSimpleQuery = false; | ||||||
2002 | |||||||
2003 | // aQueryParam can only include MAXQUERY entries | ||||||
2004 | |||||||
2005 | SCSIZE nCount = aQueryParam.GetEntryCount(); | ||||||
2006 | for (nQuery = 0; nQuery < nCount && bSimpleQuery; ++nQuery) | ||||||
2007 | if ( aQueryParam.GetEntry(nQuery).bDoQuery ) | ||||||
2008 | { | ||||||
2009 | if (aQueryParam.GetEntry(nQuery).nField == nCol) | ||||||
2010 | bColumnFound = true; | ||||||
2011 | |||||||
2012 | if (nQuery > 0) | ||||||
2013 | if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND) | ||||||
2014 | bSimpleQuery = false; | ||||||
2015 | } | ||||||
2016 | |||||||
2017 | return ( bSimpleQuery && bColumnFound ); | ||||||
2018 | } | ||||||
2019 | |||||||
2020 | void ScGridWindow::GetSelectionRects( ::std::vector< tools::Rectangle >& rPixelRects ) const | ||||||
2021 | { | ||||||
2022 | GetPixelRectsFor( mrViewData.GetMarkData(), rPixelRects ); | ||||||
2023 | } | ||||||
2024 | |||||||
2025 | void ScGridWindow::GetSelectionRectsPrintTwips(::std::vector< tools::Rectangle >& rRects) const | ||||||
2026 | { | ||||||
2027 | GetRectsAnyFor(mrViewData.GetMarkData(), rRects, true); | ||||||
2028 | } | ||||||
2029 | |||||||
2030 | /// convert rMarkData into pixel rectangles for this view | ||||||
2031 | void ScGridWindow::GetPixelRectsFor( const ScMarkData &rMarkData, | ||||||
2032 | ::std::vector< tools::Rectangle >& rPixelRects ) const | ||||||
2033 | { | ||||||
2034 | GetRectsAnyFor(rMarkData, rPixelRects, false); | ||||||
2035 | } | ||||||
2036 | |||||||
2037 | void ScGridWindow::GetRectsAnyFor(const ScMarkData &rMarkData, | ||||||
2038 | ::std::vector< tools::Rectangle >& rRects, | ||||||
2039 | bool bInPrintTwips) const | ||||||
2040 | { | ||||||
2041 | ScMarkData aMultiMark( rMarkData ); | ||||||
2042 | aMultiMark.SetMarking( false ); | ||||||
2043 | aMultiMark.MarkToMulti(); | ||||||
2044 | ScDocument& rDoc = mrViewData.GetDocument(); | ||||||
2045 | SCTAB nTab = mrViewData.GetTabNo(); | ||||||
2046 | |||||||
2047 | bool bLayoutRTL = rDoc.IsLayoutRTL( nTab ); | ||||||
2048 | long nLayoutSign = bLayoutRTL ? -1 : 1; | ||||||
2049 | if ( !aMultiMark.IsMultiMarked() ) | ||||||
2050 | return; | ||||||
2051 | ScRange aMultiRange; | ||||||
2052 | aMultiMark.GetMultiMarkArea( aMultiRange ); | ||||||
2053 | SCCOL nX1 = aMultiRange.aStart.Col(); | ||||||
2054 | SCROW nY1 = aMultiRange.aStart.Row(); | ||||||
2055 | SCCOL nX2 = aMultiRange.aEnd.Col(); | ||||||
2056 | SCROW nY2 = aMultiRange.aEnd.Row(); | ||||||
2057 | |||||||
2058 | PutInOrder( nX1, nX2 ); | ||||||
2059 | PutInOrder( nY1, nY2 ); | ||||||
2060 | |||||||
2061 | SCCOL nTestX2 = nX2; | ||||||
2062 | SCROW nTestY2 = nY2; | ||||||
2063 | |||||||
2064 | rDoc.ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab ); | ||||||
2065 | |||||||
2066 | SCCOL nPosX = mrViewData.GetPosX( eHWhich ); | ||||||
2067 | SCROW nPosY = mrViewData.GetPosY( eVWhich ); | ||||||
2068 | // is the selection visible at all? | ||||||
2069 | if (nTestX2 < nPosX || nTestY2 < nPosY) | ||||||
2070 | return; | ||||||
2071 | SCCOL nRealX1 = nX1; | ||||||
2072 | if (nX1 < nPosX) | ||||||
2073 | nX1 = nPosX; | ||||||
2074 | if (nY1 < nPosY) | ||||||
2075 | nY1 = nPosY; | ||||||
2076 | |||||||
2077 | if (!comphelper::LibreOfficeKit::isActive()) | ||||||
2078 | { | ||||||
2079 | // limit the selection to only what is visible on the screen | ||||||
2080 | SCCOL nXRight = nPosX + mrViewData.VisibleCellsX(eHWhich); | ||||||
2081 | if (nXRight > rDoc.MaxCol()) | ||||||
2082 | nXRight = rDoc.MaxCol(); | ||||||
2083 | |||||||
2084 | SCROW nYBottom = nPosY + mrViewData.VisibleCellsY(eVWhich); | ||||||
2085 | if (nYBottom > rDoc.MaxRow()) | ||||||
2086 | nYBottom = rDoc.MaxRow(); | ||||||
2087 | |||||||
2088 | // is the selection visible at all? | ||||||
2089 | if (nX1 > nXRight || nY1 > nYBottom) | ||||||
2090 | return; | ||||||
2091 | |||||||
2092 | if (nX2 > nXRight) | ||||||
2093 | nX2 = nXRight; | ||||||
2094 | if (nY2 > nYBottom) | ||||||
2095 | nY2 = nYBottom; | ||||||
2096 | } | ||||||
2097 | else | ||||||
2098 | { | ||||||
2099 | SCCOL nMaxTiledCol; | ||||||
2100 | SCROW nMaxTiledRow; | ||||||
2101 | rDoc.GetTiledRenderingArea(nTab, nMaxTiledCol, nMaxTiledRow); | ||||||
2102 | |||||||
2103 | if (nX2 > nMaxTiledCol) | ||||||
2104 | nX2 = nMaxTiledCol; | ||||||
2105 | if (nY2 > nMaxTiledRow) | ||||||
2106 | nY2 = nMaxTiledRow; | ||||||
2107 | } | ||||||
2108 | |||||||
2109 | double nPPTX = mrViewData.GetPPTX(); | ||||||
2110 | double nPPTY = mrViewData.GetPPTY(); | ||||||
2111 | |||||||
2112 | ScInvertMerger aInvert( &rRects ); | ||||||
2113 | |||||||
2114 | Point aScrPos = bInPrintTwips ? mrViewData.GetPrintTwipsPos(nX1, nY1) : | ||||||
2115 | mrViewData.GetScrPos(nX1, nY1, eWhich); | ||||||
2116 | long nScrY = aScrPos.Y(); | ||||||
2117 | bool bWasHidden = false; | ||||||
2118 | for (SCROW nY=nY1; nY<=nY2; nY++) | ||||||
2119 | { | ||||||
2120 | bool bFirstRow = ( nY == nPosY ); // first visible row? | ||||||
2121 | bool bDoHidden = false; // repeat hidden ? | ||||||
2122 | sal_uInt16 nHeightTwips = rDoc.GetRowHeight( nY,nTab ); | ||||||
2123 | bool bDoRow = ( nHeightTwips != 0 ); | ||||||
2124 | if (bDoRow) | ||||||
2125 | { | ||||||
2126 | if (bWasHidden) // test hidden merge | ||||||
2127 | { | ||||||
2128 | bDoHidden = true; | ||||||
2129 | bDoRow = true; | ||||||
2130 | } | ||||||
2131 | |||||||
2132 | bWasHidden = false; | ||||||
2133 | } | ||||||
2134 | else | ||||||
2135 | { | ||||||
2136 | bWasHidden = true; | ||||||
2137 | if (nY==nY2) | ||||||
2138 | bDoRow = true; // last cell of the block | ||||||
2139 | } | ||||||
2140 | |||||||
2141 | if ( bDoRow ) | ||||||
2142 | { | ||||||
2143 | SCCOL nLoopEndX = nX2; | ||||||
2144 | if (nX2 < nX1) // the rest of the merge | ||||||
2145 | { | ||||||
2146 | SCCOL nStartX = nX1; | ||||||
2147 | while ( rDoc.GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG)->IsHorOverlapped() ) | ||||||
2148 | --nStartX; | ||||||
2149 | if (nStartX <= nX2) | ||||||
2150 | nLoopEndX = nX1; | ||||||
2151 | } | ||||||
2152 | |||||||
2153 | const long nHeight = bInPrintTwips ? | ||||||
2154 | nHeightTwips : ScViewData::ToPixel(nHeightTwips, nPPTY); | ||||||
2155 | long nEndY = nScrY + nHeight - 1; | ||||||
2156 | long nScrX = aScrPos.X(); | ||||||
2157 | for (SCCOL nX=nX1; nX<=nLoopEndX; nX++) | ||||||
2158 | { | ||||||
2159 | long nWidth = rDoc.GetColWidth(nX, nTab); | ||||||
2160 | if (!bInPrintTwips) | ||||||
2161 | nWidth = ScViewData::ToPixel(nWidth, nPPTX); | ||||||
2162 | |||||||
2163 | if ( nWidth > 0 ) | ||||||
2164 | { | ||||||
2165 | long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign; | ||||||
2166 | |||||||
2167 | SCROW nThisY = nY; | ||||||
2168 | const ScPatternAttr* pPattern = rDoc.GetPattern( nX, nY, nTab ); | ||||||
2169 | const ScMergeFlagAttr* pMergeFlag = &pPattern->GetItem(ATTR_MERGE_FLAG); | ||||||
2170 | if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) | ||||||
2171 | { | ||||||
2172 | while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && | ||||||
2173 | (rDoc.RowHidden(nThisY-1, nTab) || bFirstRow) ) | ||||||
2174 | { | ||||||
2175 | --nThisY; | ||||||
2176 | pPattern = rDoc.GetPattern( nX, nThisY, nTab ); | ||||||
2177 | pMergeFlag = &pPattern->GetItem(ATTR_MERGE_FLAG); | ||||||
2178 | } | ||||||
2179 | } | ||||||
2180 | |||||||
2181 | // only the rest of the merged is seen ? | ||||||
2182 | SCCOL nThisX = nX; | ||||||
2183 | if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 ) | ||||||
2184 | { | ||||||
2185 | while ( pMergeFlag->IsHorOverlapped() ) | ||||||
2186 | { | ||||||
2187 | --nThisX; | ||||||
2188 | pPattern = rDoc.GetPattern( nThisX, nThisY, nTab ); | ||||||
2189 | pMergeFlag = &pPattern->GetItem(ATTR_MERGE_FLAG); | ||||||
2190 | } | ||||||
2191 | } | ||||||
2192 | |||||||
2193 | if ( aMultiMark.IsCellMarked( nThisX, nThisY, true ) ) | ||||||
2194 | { | ||||||
2195 | if ( !pMergeFlag->IsOverlapped() ) | ||||||
2196 | { | ||||||
2197 | const ScMergeAttr* pMerge = &pPattern->GetItem(ATTR_MERGE); | ||||||
2198 | if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0) | ||||||
2199 | { | ||||||
2200 | const SCCOL nEndColMerge = nThisX + pMerge->GetColMerge(); | ||||||
2201 | const SCROW nEndRowMerge = nThisY + pMerge->GetRowMerge(); | ||||||
2202 | Point aEndPos = bInPrintTwips ? | ||||||
2203 | mrViewData.GetPrintTwipsPos(nEndColMerge, nEndRowMerge) : | ||||||
2204 | mrViewData.GetScrPos(nEndColMerge, nEndRowMerge, eWhich); | ||||||
2205 | if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY ) | ||||||
2206 | { | ||||||
2207 | aInvert.AddRect( tools::Rectangle( nScrX,nScrY, | ||||||
2208 | aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) ); | ||||||
2209 | } | ||||||
2210 | } | ||||||
2211 | else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) | ||||||
2212 | { | ||||||
2213 | aInvert.AddRect( tools::Rectangle( nScrX,nScrY,nEndX,nEndY ) ); | ||||||
2214 | } | ||||||
2215 | } | ||||||
2216 | } | ||||||
2217 | |||||||
2218 | nScrX = nEndX + nLayoutSign; | ||||||
2219 | } | ||||||
2220 | } | ||||||
2221 | nScrY = nEndY + 1; | ||||||
2222 | } | ||||||
2223 | } | ||||||
2224 | } | ||||||
2225 | |||||||
2226 | void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt ) | ||||||
2227 | { | ||||||
2228 | Window::DataChanged(rDCEvt); | ||||||
2229 | |||||||
2230 | if ( !((rDCEvt.GetType() == DataChangedEventType::PRINTER) || | ||||||
2231 | (rDCEvt.GetType() == DataChangedEventType::DISPLAY) || | ||||||
2232 | (rDCEvt.GetType() == DataChangedEventType::FONTS) || | ||||||
2233 | (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) || | ||||||
2234 | ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) && | ||||||
2235 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))) ) | ||||||
2236 | return; | ||||||
2237 | |||||||
2238 | if ( rDCEvt.GetType() == DataChangedEventType::FONTS && eWhich == mrViewData.GetActivePart() ) | ||||||
2239 | mrViewData.GetDocShell()->UpdateFontList(); | ||||||
2240 | |||||||
2241 | if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && | ||||||
2242 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) | ||||||
2243 | { | ||||||
2244 | if ( eWhich == mrViewData.GetActivePart() ) // only once for the view | ||||||
2245 | { | ||||||
2246 | ScTabView* pView = mrViewData.GetView(); | ||||||
2247 | |||||||
2248 | pView->RecalcPPT(); | ||||||
2249 | |||||||
2250 | // RepeatResize in case scroll bar sizes have changed | ||||||
2251 | pView->RepeatResize(); | ||||||
2252 | pView->UpdateAllOverlays(); | ||||||
2253 | |||||||
2254 | // invalidate cell attribs in input handler, in case the | ||||||
2255 | // EditEngine BackgroundColor has to be changed | ||||||
2256 | if ( mrViewData.IsActive() ) | ||||||
2257 | { | ||||||
2258 | ScInputHandler* pHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl(); | ||||||
2259 | if (pHdl) | ||||||
2260 | pHdl->ForgetLastPattern(); | ||||||
2261 | } | ||||||
2262 | } | ||||||
2263 | } | ||||||
2264 | |||||||
2265 | Invalidate(); | ||||||
2266 | } | ||||||
2267 | |||||||
2268 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |