Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sfx2 / source / view / lokcharthelper.cxx
blobc7941e6aa2acd8ae83a46f00c5c25367b32e643e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sfx2/lokcomponenthelpers.hxx>
12 #include <comphelper/lok.hxx>
13 #include <comphelper/propertyvalue.hxx>
14 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
15 #include <sfx2/ipclient.hxx>
16 #include <sfx2/lokhelper.hxx>
17 #include <toolkit/helper/vclunohelper.hxx>
18 #include <tools/fract.hxx>
19 #include <tools/UnitConversion.hxx>
20 #include <vcl/virdev.hxx>
21 #include <vcl/window.hxx>
23 #include <com/sun/star/embed/XEmbeddedObject.hpp>
24 #include <com/sun/star/frame/XDispatch.hpp>
25 #include <com/sun/star/chart2/XChartDocument.hpp>
27 using namespace com::sun::star;
29 css::uno::Reference<css::frame::XController>& LokChartHelper::GetXController()
31 if(!mxController.is() && mpViewShell)
33 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
34 if (pIPClient)
36 const css::uno::Reference< ::css::embed::XEmbeddedObject >& xEmbObj = pIPClient->GetObject();
37 if( xEmbObj.is() )
39 ::css::uno::Reference< ::css::chart2::XChartDocument > xChart( xEmbObj->getComponent(), uno::UNO_QUERY );
40 if( xChart.is() )
42 ::css::uno::Reference< ::css::frame::XController > xChartController = xChart->getCurrentController();
43 if( xChartController.is() )
45 mxController = xChartController;
52 return mxController;
55 css::uno::Reference<css::frame::XDispatch>& LokChartHelper::GetXDispatcher()
57 if( !mxDispatcher.is() )
59 ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
60 if( xChartController.is() )
62 ::css::uno::Reference< ::css::frame::XDispatch > xDispatcher( xChartController, uno::UNO_QUERY );
63 if( xDispatcher.is() )
65 mxDispatcher = xDispatcher;
70 return mxDispatcher;
73 vcl::Window* LokChartHelper::GetWindow()
75 if (!mpWindow)
77 ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
78 if( xChartController.is() )
80 ::css::uno::Reference< ::css::frame::XFrame > xFrame = xChartController->getFrame();
81 if (xFrame.is())
83 ::css::uno::Reference< ::css::awt::XWindow > xDockerWin = xFrame->getContainerWindow();
84 vcl::Window* pParent = VCLUnoHelper::GetWindow( xDockerWin );
85 if (pParent)
87 sal_uInt16 nTotChildren = pParent->GetChildCount();
88 while (nTotChildren--)
90 vcl::Window* pChildWin = pParent->GetChild(nTotChildren);
91 if (pChildWin && pChildWin->IsChart())
93 mpWindow = pChildWin;
94 break;
102 return mpWindow.get();
105 tools::Rectangle LokChartHelper::GetChartBoundingBox()
107 tools::Rectangle aBBox;
108 if (mpViewShell)
110 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
111 if (pIPClient)
113 vcl::Window* pRootWin = pIPClient->GetEditWin();
114 if (pRootWin)
116 vcl::Window* pWindow = GetWindow();
117 if (pWindow)
119 // In all cases, the following code fragment
120 // returns the chart bounding box in twips.
121 const MapMode& aCWMapMode = pWindow->GetMapMode();
122 constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
123 const auto& scaleX = aCWMapMode.GetScaleX();
124 const auto& scaleY = aCWMapMode.GetScaleY();
125 const auto nXNum = p.first * scaleX.GetDenominator();
126 const auto nXDen = p.second * scaleX.GetNumerator();
127 const auto nYNum = p.first * scaleY.GetDenominator();
128 const auto nYDen = p.second * scaleY.GetNumerator();
130 Point aOffset = pWindow->GetOffsetPixelFrom(*pRootWin);
131 if (mbNegativeX && AllSettings::GetLayoutRTL())
133 // If global RTL flag is set, vcl-window X offset of chart window is
134 // mirrored w.r.t parent window rectangle. This needs to be reverted.
135 aOffset.setX(pRootWin->GetOutOffXPixel() + pRootWin->GetSizePixel().Width()
136 - pWindow->GetOutOffXPixel() - pWindow->GetSizePixel().Width());
140 aOffset = aOffset.scale(nXNum, nXDen, nYNum, nYDen);
141 Size aSize = pWindow->GetSizePixel().scale(nXNum, nXDen, nYNum, nYDen);
142 aBBox = tools::Rectangle(aOffset, aSize);
147 return aBBox;
150 void LokChartHelper::Invalidate()
152 mpWindow = nullptr;
153 mxDispatcher.clear();
154 mxController.clear();
157 bool LokChartHelper::Hit(const Point& aPos)
159 if (mpViewShell)
161 vcl::Window* pChartWindow = GetWindow();
162 if (pChartWindow)
164 tools::Rectangle rChartBBox = GetChartBoundingBox();
165 return rChartBBox.Contains(aPos);
168 return false;
171 bool LokChartHelper::HitAny(const Point& aPos, bool bNegativeX)
173 SfxViewShell* pCurView = SfxViewShell::Current();
174 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
175 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
176 while (pViewShell)
178 if (pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
180 LokChartHelper aChartHelper(pViewShell, bNegativeX);
181 if (aChartHelper.Hit(aPos))
182 return true;
184 pViewShell = SfxViewShell::GetNext(*pViewShell);
186 return false;
189 void LokChartHelper::PaintTile(VirtualDevice& rRenderContext, const tools::Rectangle& rTileRect)
191 if (!mpViewShell)
192 return;
194 vcl::Window* pChartWindow = GetWindow();
195 if (!pChartWindow)
196 return;
198 tools::Rectangle aChartRect = GetChartBoundingBox();
199 tools::Rectangle aTestRect = rTileRect;
200 aTestRect.Intersection( aChartRect );
201 if (aTestRect.IsEmpty())
202 return;
204 Point aOffset( aChartRect.Left() - rTileRect.Left(), aChartRect.Top() - rTileRect.Top() );
205 Point aOffsetFromTile = convertTwipToMm100(aOffset);
206 Size aSize = convertTwipToMm100(aChartRect.GetSize());
207 tools::Rectangle aRectangle(Point(0,0), aSize);
209 bool bEnableMapMode = !pChartWindow->IsMapModeEnabled();
210 pChartWindow->EnableMapMode();
211 bool bRenderContextEnableMapMode = !rRenderContext.IsMapModeEnabled();
212 rRenderContext.EnableMapMode();
214 rRenderContext.Push(vcl::PushFlags::MAPMODE);
216 MapMode aCWMapMode = pChartWindow->GetMapMode();
217 aCWMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
218 aCWMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
220 aCWMapMode.SetOrigin(aOffsetFromTile);
221 rRenderContext.SetMapMode(aCWMapMode);
223 pChartWindow->Paint(rRenderContext, aRectangle);
225 rRenderContext.Pop();
227 if (bRenderContextEnableMapMode)
228 rRenderContext.EnableMapMode(false);
229 if (bEnableMapMode)
230 pChartWindow->EnableMapMode(false);
233 void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice,
234 int nOutputWidth, int nOutputHeight,
235 int nTilePosX, int nTilePosY,
236 tools::Long nTileWidth, tools::Long nTileHeight,
237 bool bNegativeX)
239 if (comphelper::LibreOfficeKit::isTiledAnnotations())
240 return;
242 // Resizes the virtual device so to contain the entries context
243 rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
245 rDevice.Push(vcl::PushFlags::MAPMODE);
246 MapMode aMapMode(rDevice.GetMapMode());
248 // Scaling. Must convert from pixels to twips. We know
249 // that VirtualDevices use a DPI of 96.
250 const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
251 Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale;
252 Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale;
253 aMapMode.SetScaleX(scaleX);
254 aMapMode.SetScaleY(scaleY);
255 rDevice.SetMapMode(aMapMode);
257 SfxViewShell* pCurView = SfxViewShell::Current();
258 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
259 tools::Long nTileRectLeft = bNegativeX ? -nTilePosX - nTileWidth : nTilePosX;
260 tools::Rectangle aTileRect(Point(nTileRectLeft, nTilePosY), Size(nTileWidth, nTileHeight));
261 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
262 while (pViewShell)
264 if (pCurView && pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
266 LokChartHelper aChartHelper(pViewShell, bNegativeX);
267 aChartHelper.PaintTile(rDevice, aTileRect);
269 pViewShell = SfxViewShell::GetNext(*pViewShell);
271 rDevice.Pop();
274 bool LokChartHelper::postMouseEvent(int nType, int nX, int nY,
275 int nCount, int nButtons, int nModifier,
276 double fScaleX, double fScaleY)
278 Point aMousePos(nX, nY);
279 vcl::Window* pChartWindow = GetWindow();
280 if (pChartWindow)
282 tools::Rectangle rChartBBox = GetChartBoundingBox();
283 if (rChartBBox.Contains(aMousePos))
285 int nChartWinX = nX - rChartBBox.Left();
286 int nChartWinY = nY - rChartBBox.Top();
288 // chart window expects pixels, but the conversion factor
289 // can depend on the client zoom
290 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
292 LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK,
293 nButtons, nModifier);
294 SfxLokHelper::postMouseEventAsync(pChartWindow, aMouseEventData);
296 return true;
299 return false;
302 bool LokChartHelper::setTextSelection(int nType, int nX, int nY)
304 tools::Rectangle rChartBBox = GetChartBoundingBox();
305 if (rChartBBox.Contains(Point(nX, nY)))
307 css::uno::Reference<css::frame::XDispatch> xDispatcher = GetXDispatcher();
308 if (xDispatcher.is())
310 int nChartWinX = nX - rChartBBox.Left();
311 int nChartWinY = nY - rChartBBox.Top();
313 // no scale here the chart controller expects twips
314 // that are converted to hmm
315 util::URL aURL;
316 aURL.Path = "LOKSetTextSelection";
317 uno::Sequence< beans::PropertyValue > aArgs{
318 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nType)), // Why no name?
319 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nChartWinX)),
320 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nChartWinY))
322 xDispatcher->dispatch(aURL, aArgs);
324 return true;
326 return false;
329 bool LokChartHelper::setGraphicSelection(int nType, int nX, int nY,
330 double fScaleX, double fScaleY)
332 tools::Rectangle rChartBBox = GetChartBoundingBox();
333 if (rChartBBox.Contains(Point(nX, nY)))
335 int nChartWinX = nX - rChartBBox.Left();
336 int nChartWinY = nY - rChartBBox.Top();
338 vcl::Window* pChartWindow = GetWindow();
340 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
341 switch (nType)
343 case LOK_SETGRAPHICSELECTION_START:
345 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
346 pChartWindow->MouseButtonDown(aClickEvent);
347 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
348 pChartWindow->MouseMove(aMoveEvent);
350 break;
351 case LOK_SETGRAPHICSELECTION_END:
353 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
354 pChartWindow->MouseMove(aMoveEvent);
355 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
356 pChartWindow->MouseButtonUp(aClickEvent);
358 break;
359 default:
360 assert(false);
361 break;
363 return true;
365 return false;
369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */