File: | home/maarten/src/libreoffice/core/include/rtl/ref.hxx |
Warning: | line 192, column 9 Use of memory after it is freed |
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
| ||||||||||||||||
464 | nX1 = maVisibleRange.mnCol1; | ||||||||||||||||
465 | if (nY1
| ||||||||||||||||
466 | nY1 = maVisibleRange.mnRow1; | ||||||||||||||||
467 | |||||||||||||||||
468 | if (nX1 > maVisibleRange.mnCol2 || nY1 > maVisibleRange.mnRow2) | ||||||||||||||||
469 | return; | ||||||||||||||||
470 | |||||||||||||||||
471 | if (nX2
| ||||||||||||||||
472 | nX2 = maVisibleRange.mnCol2; | ||||||||||||||||
473 | if (nY2
| ||||||||||||||||
474 | nY2 = maVisibleRange.mnRow2; | ||||||||||||||||
475 | |||||||||||||||||
476 | if ( eMode
| ||||||||||||||||
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
| ||||||||||||||||
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 && (bGrid || bPage) && !bNoBackgroundAndGrid) | ||||||||||||||||
801 | aOutputData.DrawGrid(*pContentDev, bGrid, bPage); | ||||||||||||||||
802 | |||||||||||||||||
803 | aOutputData.DrawBackground(*pContentDev); | ||||||||||||||||
804 | |||||||||||||||||
805 | if (!bGridFirst && (bGrid || bPage) && !bNoBackgroundAndGrid) | ||||||||||||||||
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 || bHasScenario || !rHigh.empty() ) | ||||||||||||||||
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: */ |
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 | #ifndef INCLUDED_VCL_PTR_HXX |
21 | #define INCLUDED_VCL_PTR_HXX |
22 | |
23 | #include <sal/config.h> |
24 | |
25 | #include <rtl/ref.hxx> |
26 | |
27 | #include <utility> |
28 | #include <type_traits> |
29 | |
30 | #ifdef DBG_UTIL |
31 | #ifndef _WIN32 |
32 | #include <vcl/vclmain.hxx> |
33 | #endif |
34 | #endif |
35 | |
36 | class VclReferenceBase; |
37 | |
38 | namespace vcl::detail { |
39 | |
40 | template<typename> |
41 | constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; } |
42 | |
43 | template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase( |
44 | int (*)[sizeof(T)]) |
45 | { return std::is_base_of<VclReferenceBase, T>::value; } |
46 | |
47 | } // namespace vcl::detail |
48 | |
49 | /** |
50 | * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses. |
51 | * |
52 | * For more details on the design please see vcl/README.lifecycle |
53 | * |
54 | * @param reference_type must be a subclass of vcl::Window |
55 | */ |
56 | template <class reference_type> |
57 | class VclPtr |
58 | { |
59 | static_assert( |
60 | vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>( |
61 | nullptr), |
62 | "template argument type must be derived from VclReferenceBase"); |
63 | |
64 | ::rtl::Reference<reference_type> m_rInnerRef; |
65 | |
66 | public: |
67 | /** Constructor... |
68 | */ |
69 | VclPtr() |
70 | : m_rInnerRef() |
71 | {} |
72 | |
73 | /** Constructor... |
74 | */ |
75 | VclPtr (reference_type * pBody) |
76 | : m_rInnerRef(pBody) |
77 | {} |
78 | |
79 | /** Constructor... that doesn't take a ref. |
80 | */ |
81 | VclPtr (reference_type * pBody, __sal_NoAcquire) |
82 | : m_rInnerRef(pBody, SAL_NO_ACQUIRE) |
83 | {} |
84 | |
85 | /** Up-casting conversion constructor: Copies interface reference. |
86 | |
87 | Does not work for up-casts to ambiguous bases. For the special case of |
88 | up-casting to Reference< XInterface >, see the corresponding conversion |
89 | operator. |
90 | |
91 | @param rRef another reference |
92 | */ |
93 | template< class derived_type > |
94 | VclPtr( |
95 | const VclPtr< derived_type > & rRef, |
96 | typename std::enable_if< |
97 | std::is_base_of<reference_type, derived_type>::value, int>::type |
98 | = 0 ) |
99 | : m_rInnerRef( static_cast<reference_type*>(rRef) ) |
100 | { |
101 | } |
102 | |
103 | #if defined(DBG_UTIL) && !defined(_WIN32) |
104 | virtual ~VclPtr() |
105 | { |
106 | assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain ::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 106, __extension__ __PRETTY_FUNCTION__)); |
107 | // We can be one of the intermediate counts, but if we are the last |
108 | // VclPtr keeping this object alive, then something forgot to call dispose(). |
109 | assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)) |
110 | && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)); |
111 | } |
112 | VclPtr(VclPtr const &) = default; |
113 | VclPtr(VclPtr &&) = default; |
114 | VclPtr & operator =(VclPtr const &) = default; |
115 | VclPtr & operator =(VclPtr &&) = default; |
116 | #endif |
117 | |
118 | /** |
119 | * A construction helper for VclPtr. Since VclPtr types are created |
120 | * with a reference-count of one - to help fit into the existing |
121 | * code-flow; this helps us to construct them easily. |
122 | * |
123 | * For more details on the design please see vcl/README.lifecycle |
124 | * |
125 | * @tparam reference_type must be a subclass of vcl::Window |
126 | */ |
127 | template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg) |
128 | { |
129 | return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ); |
130 | } |
131 | |
132 | /** Probably most common used: handle->someBodyOp(). |
133 | */ |
134 | reference_type * operator->() const |
135 | { |
136 | return m_rInnerRef.get(); |
137 | } |
138 | |
139 | /** Get the body. Can be used instead of operator->(). |
140 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() |
141 | are the same. |
142 | */ |
143 | reference_type * get() const |
144 | { |
145 | return m_rInnerRef.get(); |
146 | } |
147 | |
148 | void set(reference_type *pBody) |
149 | { |
150 | m_rInnerRef.set(pBody); |
151 | } |
152 | |
153 | void reset(reference_type *pBody) |
154 | { |
155 | m_rInnerRef.set(pBody); |
156 | } |
157 | |
158 | /** Up-casting copy assignment operator. |
159 | |
160 | Does not work for up-casts to ambiguous bases. |
161 | |
162 | @param rRef another reference |
163 | */ |
164 | template<typename derived_type> |
165 | typename std::enable_if< |
166 | std::is_base_of<reference_type, derived_type>::value, |
167 | VclPtr &>::type |
168 | operator =(VclPtr<derived_type> const & rRef) |
169 | { |
170 | m_rInnerRef.set(rRef.get()); |
171 | return *this; |
172 | } |
173 | |
174 | VclPtr & operator =(reference_type * pBody) |
175 | { |
176 | m_rInnerRef.set(pBody); |
177 | return *this; |
178 | } |
179 | |
180 | operator reference_type * () const |
181 | { |
182 | return m_rInnerRef.get(); |
183 | } |
184 | |
185 | explicit operator bool () const |
186 | { |
187 | return m_rInnerRef.get() != nullptr; |
188 | } |
189 | |
190 | void clear() |
191 | { |
192 | m_rInnerRef.clear(); |
193 | } |
194 | |
195 | void reset() |
196 | { |
197 | m_rInnerRef.clear(); |
198 | } |
199 | |
200 | void disposeAndClear() |
201 | { |
202 | // hold it alive for the lifetime of this method |
203 | ::rtl::Reference<reference_type> aTmp(m_rInnerRef); |
204 | m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-) |
205 | if (aTmp.get()) { |
206 | aTmp->disposeOnce(); |
207 | } |
208 | } |
209 | |
210 | /** Needed to place VclPtr's into STL collection. |
211 | */ |
212 | bool operator< (const VclPtr<reference_type> & handle) const |
213 | { |
214 | return (m_rInnerRef < handle.m_rInnerRef); |
215 | } |
216 | }; // class VclPtr |
217 | |
218 | template<typename T1, typename T2> |
219 | inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
220 | return p1.get() == p2.get(); |
221 | } |
222 | |
223 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2) |
224 | { |
225 | return p1.get() == p2; |
226 | } |
227 | |
228 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) { |
229 | return p1.get() == p2; |
230 | } |
231 | |
232 | template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2) |
233 | { |
234 | return p1 == p2.get(); |
235 | } |
236 | |
237 | template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) { |
238 | return p1 == p2.get(); |
239 | } |
240 | |
241 | template<typename T1, typename T2> |
242 | inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
243 | return !(p1 == p2); |
244 | } |
245 | |
246 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2) |
247 | { |
248 | return !(p1 == p2); |
249 | } |
250 | |
251 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) { |
252 | return !(p1 == p2); |
253 | } |
254 | |
255 | template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2) |
256 | { |
257 | return !(p1 == p2); |
258 | } |
259 | |
260 | template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) { |
261 | return !(p1 == p2); |
262 | } |
263 | |
264 | /** |
265 | * A construction helper for a temporary VclPtr. Since VclPtr types |
266 | * are created with a reference-count of one - to help fit into |
267 | * the existing code-flow; this helps us to construct them easily. |
268 | * see also VclPtr::Create and ScopedVclPtr |
269 | * |
270 | * For more details on the design please see vcl/README.lifecycle |
271 | * |
272 | * @param reference_type must be a subclass of vcl::Window |
273 | */ |
274 | template <class reference_type> |
275 | class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type> |
276 | { |
277 | public: |
278 | template<typename... Arg> VclPtrInstance(Arg &&... arg) |
279 | : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
280 | { |
281 | } |
282 | |
283 | /** |
284 | * Override and disallow this, to prevent people accidentally calling it and actually |
285 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
286 | */ |
287 | template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete; |
288 | }; |
289 | |
290 | template <class reference_type> |
291 | class ScopedVclPtr : public VclPtr<reference_type> |
292 | { |
293 | public: |
294 | /** Constructor... |
295 | */ |
296 | ScopedVclPtr() |
297 | : VclPtr<reference_type>() |
298 | {} |
299 | |
300 | /** Constructor |
301 | */ |
302 | ScopedVclPtr (reference_type * pBody) |
303 | : VclPtr<reference_type>(pBody) |
304 | {} |
305 | |
306 | /** Copy constructor... |
307 | */ |
308 | ScopedVclPtr (const VclPtr<reference_type> & handle) |
309 | : VclPtr<reference_type>(handle) |
310 | {} |
311 | |
312 | /** |
313 | Assignment that releases the last reference. |
314 | */ |
315 | void disposeAndReset(reference_type *pBody) |
316 | { |
317 | if (pBody != this->get()) { |
318 | VclPtr<reference_type>::disposeAndClear(); |
319 | VclPtr<reference_type>::set(pBody); |
320 | } |
321 | } |
322 | |
323 | /** |
324 | Assignment that releases the last reference. |
325 | */ |
326 | ScopedVclPtr<reference_type>& operator = (reference_type * pBody) |
327 | { |
328 | disposeAndReset(pBody); |
329 | return *this; |
330 | } |
331 | |
332 | /** Up-casting conversion constructor: Copies interface reference. |
333 | |
334 | Does not work for up-casts to ambiguous bases. For the special case of |
335 | up-casting to Reference< XInterface >, see the corresponding conversion |
336 | operator. |
337 | |
338 | @param rRef another reference |
339 | */ |
340 | template< class derived_type > |
341 | ScopedVclPtr( |
342 | const VclPtr< derived_type > & rRef, |
343 | typename std::enable_if< |
344 | std::is_base_of<reference_type, derived_type>::value, int>::type |
345 | = 0 ) |
346 | : VclPtr<reference_type>( rRef ) |
347 | { |
348 | } |
349 | |
350 | /** Up-casting assignment operator. |
351 | |
352 | Does not work for up-casts to ambiguous bases. |
353 | |
354 | @param rRef another VclPtr |
355 | */ |
356 | template<typename derived_type> |
357 | typename std::enable_if< |
358 | std::is_base_of<reference_type, derived_type>::value, |
359 | ScopedVclPtr &>::type |
360 | operator =(VclPtr<derived_type> const & rRef) |
361 | { |
362 | disposeAndReset(rRef.get()); |
363 | return *this; |
364 | } |
365 | |
366 | /** |
367 | * Override and disallow this, to prevent people accidentally calling it and actually |
368 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
369 | */ |
370 | template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete; |
371 | |
372 | ~ScopedVclPtr() |
373 | { |
374 | VclPtr<reference_type>::disposeAndClear(); |
375 | assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get( ) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 375, __extension__ __PRETTY_FUNCTION__)); // make sure there are no lingering references |
376 | } |
377 | |
378 | private: |
379 | // Most likely we don't want this default copy-constructor. |
380 | ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete; |
381 | // And certainly we don't want a default assignment operator. |
382 | ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete; |
383 | // And disallow reset as that doesn't call disposeAndClear on the original reference |
384 | void reset() = delete; |
385 | void reset(reference_type *pBody) = delete; |
386 | |
387 | protected: |
388 | ScopedVclPtr (reference_type * pBody, __sal_NoAcquire) |
389 | : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE) |
390 | {} |
391 | }; |
392 | |
393 | /** |
394 | * A construction helper for ScopedVclPtr. Since VclPtr types are created |
395 | * with a reference-count of one - to help fit into the existing |
396 | * code-flow; this helps us to construct them easily. |
397 | * |
398 | * For more details on the design please see vcl/README.lifecycle |
399 | * |
400 | * @param reference_type must be a subclass of vcl::Window |
401 | */ |
402 | #if defined _MSC_VER |
403 | #pragma warning(push) |
404 | #pragma warning(disable: 4521) // " multiple copy constructors specified" |
405 | #endif |
406 | template <class reference_type> |
407 | class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type> |
408 | { |
409 | public: |
410 | template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg) |
411 | : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
412 | { |
413 | } |
414 | |
415 | /** |
416 | * Override and disallow this, to prevent people accidentally calling it and actually |
417 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
418 | */ |
419 | template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete; |
420 | |
421 | private: |
422 | // Prevent the above perfect forwarding ctor from hijacking (accidental) |
423 | // attempts at ScopedVclPtrInstance copy construction (where the hijacking |
424 | // would typically lead to somewhat obscure error messages); both non-const |
425 | // and const variants are needed here, as the ScopedVclPtr base class has a |
426 | // const--variant copy ctor, so the implicitly declared copy ctor for |
427 | // ScopedVclPtrInstance would also be the const variant, so non-const copy |
428 | // construction attempts would be hijacked by the perfect forwarding ctor; |
429 | // but if we only declared a non-const variant here, the const variant would |
430 | // no longer be implicitly declared (as there would already be an explicitly |
431 | // declared copy ctor), so const copy construction attempts would then be |
432 | // hijacked by the perfect forwarding ctor: |
433 | ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete; |
434 | ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete; |
435 | }; |
436 | #if defined _MSC_VER |
437 | #pragma warning(pop) |
438 | #endif |
439 | |
440 | #endif // INCLUDED_VCL_PTR_HXX |
441 | |
442 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_RTL_REF_HXX | ||||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||||
22 | |||||||||
23 | #include "sal/config.h" | ||||||||
24 | |||||||||
25 | #include <cassert> | ||||||||
26 | #include <cstddef> | ||||||||
27 | #include <functional> | ||||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||
29 | #include <type_traits> | ||||||||
30 | #endif | ||||||||
31 | |||||||||
32 | #include "sal/types.h" | ||||||||
33 | |||||||||
34 | namespace rtl | ||||||||
35 | { | ||||||||
36 | |||||||||
37 | /** Template reference class for reference type. | ||||||||
38 | */ | ||||||||
39 | template <class reference_type> | ||||||||
40 | class Reference | ||||||||
41 | { | ||||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||||
43 | */ | ||||||||
44 | reference_type * m_pBody; | ||||||||
45 | |||||||||
46 | |||||||||
47 | public: | ||||||||
48 | /** Constructor... | ||||||||
49 | */ | ||||||||
50 | Reference() | ||||||||
51 | : m_pBody (NULL__null) | ||||||||
52 | {} | ||||||||
53 | |||||||||
54 | |||||||||
55 | /** Constructor... | ||||||||
56 | */ | ||||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||||
58 | : m_pBody (pBody) | ||||||||
59 | { | ||||||||
60 | } | ||||||||
61 | |||||||||
62 | /** Constructor... | ||||||||
63 | */ | ||||||||
64 | Reference (reference_type * pBody) | ||||||||
65 | : m_pBody (pBody) | ||||||||
66 | { | ||||||||
67 | if (m_pBody) | ||||||||
68 | m_pBody->acquire(); | ||||||||
69 | } | ||||||||
70 | |||||||||
71 | /** Copy constructor... | ||||||||
72 | */ | ||||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||||
74 | : m_pBody (handle.m_pBody) | ||||||||
75 | { | ||||||||
76 | if (m_pBody) | ||||||||
77 | m_pBody->acquire(); | ||||||||
78 | } | ||||||||
79 | |||||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||
81 | /** Move constructor... | ||||||||
82 | */ | ||||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||||
84 | : m_pBody (handle.m_pBody) | ||||||||
85 | { | ||||||||
86 | handle.m_pBody = nullptr; | ||||||||
87 | } | ||||||||
88 | #endif | ||||||||
89 | |||||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||||
92 | |||||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||||
94 | |||||||||
95 | @param rRef another reference | ||||||||
96 | */ | ||||||||
97 | template< class derived_type > | ||||||||
98 | inline Reference( | ||||||||
99 | const Reference< derived_type > & rRef, | ||||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||||
101 | : m_pBody (rRef.get()) | ||||||||
102 | { | ||||||||
103 | if (m_pBody) | ||||||||
104 | m_pBody->acquire(); | ||||||||
105 | } | ||||||||
106 | #endif | ||||||||
107 | |||||||||
108 | /** Destructor... | ||||||||
109 | */ | ||||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||||
111 | { | ||||||||
112 | if (m_pBody
| ||||||||
113 | m_pBody->release(); | ||||||||
114 | } | ||||||||
115 | |||||||||
116 | /** Set... | ||||||||
117 | Similar to assignment. | ||||||||
118 | */ | ||||||||
119 | Reference<reference_type> & | ||||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||||
121 | { | ||||||||
122 | if (pBody) | ||||||||
123 | pBody->acquire(); | ||||||||
124 | reference_type * const pOld = m_pBody; | ||||||||
125 | m_pBody = pBody; | ||||||||
126 | if (pOld) | ||||||||
127 | pOld->release(); | ||||||||
128 | return *this; | ||||||||
129 | } | ||||||||
130 | |||||||||
131 | /** Assignment. | ||||||||
132 | Unbinds this instance from its body (if bound) and | ||||||||
133 | bind it to the body represented by the handle. | ||||||||
134 | */ | ||||||||
135 | Reference<reference_type> & | ||||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||||
137 | { | ||||||||
138 | return set( handle.m_pBody ); | ||||||||
139 | } | ||||||||
140 | |||||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||
142 | /** Assignment. | ||||||||
143 | * Unbinds this instance from its body (if bound), | ||||||||
144 | * bind it to the body represented by the handle, and | ||||||||
145 | * set the body represented by the handle to nullptr. | ||||||||
146 | */ | ||||||||
147 | Reference<reference_type> & | ||||||||
148 | operator= (Reference<reference_type> && handle) | ||||||||
149 | { | ||||||||
150 | // self-movement guts ourself | ||||||||
151 | if (m_pBody) | ||||||||
152 | m_pBody->release(); | ||||||||
153 | m_pBody = handle.m_pBody; | ||||||||
154 | handle.m_pBody = nullptr; | ||||||||
155 | return *this; | ||||||||
156 | } | ||||||||
157 | #endif | ||||||||
158 | |||||||||
159 | /** Assignment... | ||||||||
160 | */ | ||||||||
161 | Reference<reference_type> & | ||||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||||
163 | { | ||||||||
164 | return set( pBody ); | ||||||||
165 | } | ||||||||
166 | |||||||||
167 | /** Unbind the body from this handle. | ||||||||
168 | Note that for a handle representing a large body, | ||||||||
169 | "handle.clear().set(new body());" _might_ | ||||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||||
171 | since in the second case two large objects exist in memory | ||||||||
172 | (the old body and the new body). | ||||||||
173 | */ | ||||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||||
175 | { | ||||||||
176 | if (m_pBody) | ||||||||
177 | { | ||||||||
178 | reference_type * const pOld = m_pBody; | ||||||||
179 | m_pBody = NULL__null; | ||||||||
180 | pOld->release(); | ||||||||
181 | } | ||||||||
182 | return *this; | ||||||||
183 | } | ||||||||
184 | |||||||||
185 | |||||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||||
188 | are the same. | ||||||||
189 | */ | ||||||||
190 | reference_type * SAL_CALL get() const | ||||||||
191 | { | ||||||||
192 | return m_pBody; | ||||||||
| |||||||||
193 | } | ||||||||
194 | |||||||||
195 | |||||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||||
197 | */ | ||||||||
198 | reference_type * SAL_CALL operator->() const | ||||||||
199 | { | ||||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||||
201 | return m_pBody; | ||||||||
202 | } | ||||||||
203 | |||||||||
204 | |||||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||||
206 | */ | ||||||||
207 | reference_type & SAL_CALL operator*() const | ||||||||
208 | { | ||||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||||
210 | return *m_pBody; | ||||||||
211 | } | ||||||||
212 | |||||||||
213 | |||||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||||
215 | */ | ||||||||
216 | bool SAL_CALL is() const | ||||||||
217 | { | ||||||||
218 | return (m_pBody != NULL__null); | ||||||||
219 | } | ||||||||
220 | |||||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||||
223 | */ | ||||||||
224 | explicit operator bool() const | ||||||||
225 | { | ||||||||
226 | return is(); | ||||||||
227 | } | ||||||||
228 | #endif | ||||||||
229 | |||||||||
230 | /** Returns True if this points to pBody. | ||||||||
231 | */ | ||||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||||
233 | { | ||||||||
234 | return (m_pBody == pBody); | ||||||||
235 | } | ||||||||
236 | |||||||||
237 | |||||||||
238 | /** Returns True if handle points to the same body. | ||||||||
239 | */ | ||||||||
240 | bool | ||||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||||
242 | { | ||||||||
243 | return (m_pBody == handle.m_pBody); | ||||||||
244 | } | ||||||||
245 | |||||||||
246 | |||||||||
247 | /** Needed to place References into STL collection. | ||||||||
248 | */ | ||||||||
249 | bool | ||||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||||
251 | { | ||||||||
252 | return (m_pBody != handle.m_pBody); | ||||||||
253 | } | ||||||||
254 | |||||||||
255 | |||||||||
256 | /** Needed to place References into STL collection. | ||||||||
257 | */ | ||||||||
258 | bool | ||||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||||
260 | { | ||||||||
261 | return (m_pBody < handle.m_pBody); | ||||||||
262 | } | ||||||||
263 | |||||||||
264 | |||||||||
265 | /** Needed to place References into STL collection. | ||||||||
266 | */ | ||||||||
267 | bool | ||||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||||
269 | { | ||||||||
270 | return (m_pBody > handle.m_pBody); | ||||||||
271 | } | ||||||||
272 | }; | ||||||||
273 | |||||||||
274 | } // namespace rtl | ||||||||
275 | |||||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||
277 | namespace std | ||||||||
278 | { | ||||||||
279 | |||||||||
280 | /// @cond INTERNAL | ||||||||
281 | /** | ||||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||||
283 | |||||||||
284 | @since LibreOffice 6.3 | ||||||||
285 | */ | ||||||||
286 | template<typename T> | ||||||||
287 | struct hash<::rtl::Reference<T>> | ||||||||
288 | { | ||||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||||
290 | { return std::size_t(s.get()); } | ||||||||
291 | }; | ||||||||
292 | /// @endcond | ||||||||
293 | |||||||||
294 | } | ||||||||
295 | |||||||||
296 | #endif | ||||||||
297 | |||||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||||
299 | |||||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |