LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / view / lokcharthelper.cxx
blobe319cd2ea0486e0e6f03e7fbbf3f512753481479
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 namespace {
31 Point lcl_TwipsToHMM( const Point& rPoint )
33 return Point(convertTwipToMm100(rPoint.getX()), convertTwipToMm100(rPoint.getY()));
36 Size lcl_TwipsToHMM( const Size& rSize )
38 return Size(convertTwipToMm100(rSize.getWidth()), convertTwipToMm100(rSize.getHeight()));
41 } // end anonymous ns
43 css::uno::Reference<css::frame::XController>& LokChartHelper::GetXController()
45 if(!mxController.is() && mpViewShell)
47 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
48 if (pIPClient)
50 const css::uno::Reference< ::css::embed::XEmbeddedObject >& xEmbObj = pIPClient->GetObject();
51 if( xEmbObj.is() )
53 ::css::uno::Reference< ::css::chart2::XChartDocument > xChart( xEmbObj->getComponent(), uno::UNO_QUERY );
54 if( xChart.is() )
56 ::css::uno::Reference< ::css::frame::XController > xChartController = xChart->getCurrentController();
57 if( xChartController.is() )
59 mxController = xChartController;
66 return mxController;
69 css::uno::Reference<css::frame::XDispatch>& LokChartHelper::GetXDispatcher()
71 if( !mxDispatcher.is() )
73 ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
74 if( xChartController.is() )
76 ::css::uno::Reference< ::css::frame::XDispatch > xDispatcher( xChartController, uno::UNO_QUERY );
77 if( xDispatcher.is() )
79 mxDispatcher = xDispatcher;
84 return mxDispatcher;
87 vcl::Window* LokChartHelper::GetWindow()
89 if (!mpWindow)
91 ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
92 if( xChartController.is() )
94 ::css::uno::Reference< ::css::frame::XFrame > xFrame = xChartController->getFrame();
95 if (xFrame.is())
97 ::css::uno::Reference< ::css::awt::XWindow > xDockerWin = xFrame->getContainerWindow();
98 vcl::Window* pParent = VCLUnoHelper::GetWindow( xDockerWin );
99 if (pParent)
101 sal_uInt16 nTotChildren = pParent->GetChildCount();
102 while (nTotChildren--)
104 vcl::Window* pChildWin = pParent->GetChild(nTotChildren);
105 if (pChildWin && pChildWin->IsChart())
107 mpWindow = pChildWin;
108 break;
116 return mpWindow.get();
119 tools::Rectangle LokChartHelper::GetChartBoundingBox()
121 tools::Rectangle aBBox;
122 if (mpViewShell)
124 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
125 if (pIPClient)
127 vcl::Window* pRootWin = pIPClient->GetEditWin();
128 if (pRootWin)
130 vcl::Window* pWindow = GetWindow();
131 if (pWindow)
133 // In all cases, the following code fragment
134 // returns the chart bounding box in twips.
135 const MapMode& aCWMapMode = pWindow->GetMapMode();
136 constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
137 const auto& scaleX = aCWMapMode.GetScaleX();
138 const auto& scaleY = aCWMapMode.GetScaleY();
139 const auto nXNum = p.first * scaleX.GetDenominator();
140 const auto nXDen = p.second * scaleX.GetNumerator();
141 const auto nYNum = p.first * scaleY.GetDenominator();
142 const auto nYDen = p.second * scaleY.GetNumerator();
144 Point aOffset = pWindow->GetOffsetPixelFrom(*pRootWin);
145 if (mbNegativeX && AllSettings::GetLayoutRTL())
147 // If global RTL flag is set, vcl-window X offset of chart window is
148 // mirrored w.r.t parent window rectangle. This needs to be reverted.
149 aOffset.setX(pRootWin->GetOutOffXPixel() + pRootWin->GetSizePixel().Width()
150 - pWindow->GetOutOffXPixel() - pWindow->GetSizePixel().Width());
154 aOffset = aOffset.scale(nXNum, nXDen, nYNum, nYDen);
155 Size aSize = pWindow->GetSizePixel().scale(nXNum, nXDen, nYNum, nYDen);
156 aBBox = tools::Rectangle(aOffset, aSize);
161 return aBBox;
164 void LokChartHelper::Invalidate()
166 mpWindow = nullptr;
167 mxDispatcher.clear();
168 mxController.clear();
171 bool LokChartHelper::Hit(const Point& aPos)
173 if (mpViewShell)
175 vcl::Window* pChartWindow = GetWindow();
176 if (pChartWindow)
178 tools::Rectangle rChartBBox = GetChartBoundingBox();
179 return rChartBBox.Contains(aPos);
182 return false;
185 bool LokChartHelper::HitAny(const Point& aPos, bool bNegativeX)
187 SfxViewShell* pCurView = SfxViewShell::Current();
188 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
189 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
190 while (pViewShell)
192 if (pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
194 LokChartHelper aChartHelper(pViewShell, bNegativeX);
195 if (aChartHelper.Hit(aPos))
196 return true;
198 pViewShell = SfxViewShell::GetNext(*pViewShell);
200 return false;
203 void LokChartHelper::PaintTile(VirtualDevice& rRenderContext, const tools::Rectangle& rTileRect)
205 if (!mpViewShell)
206 return;
208 vcl::Window* pChartWindow = GetWindow();
209 if (!pChartWindow)
210 return;
212 tools::Rectangle aChartRect = GetChartBoundingBox();
213 tools::Rectangle aTestRect = rTileRect;
214 aTestRect.Intersection( aChartRect );
215 if (aTestRect.IsEmpty())
216 return;
218 Point aOffset( aChartRect.Left() - rTileRect.Left(), aChartRect.Top() - rTileRect.Top() );
219 Point aOffsetFromTile = lcl_TwipsToHMM(aOffset);
220 Size aSize = lcl_TwipsToHMM(aChartRect.GetSize());
221 tools::Rectangle aRectangle(Point(0,0), aSize);
223 bool bEnableMapMode = !pChartWindow->IsMapModeEnabled();
224 pChartWindow->EnableMapMode();
225 bool bRenderContextEnableMapMode = !rRenderContext.IsMapModeEnabled();
226 rRenderContext.EnableMapMode();
228 rRenderContext.Push(vcl::PushFlags::MAPMODE);
230 MapMode aCWMapMode = pChartWindow->GetMapMode();
231 aCWMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
232 aCWMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
234 aCWMapMode.SetOrigin(aOffsetFromTile);
235 rRenderContext.SetMapMode(aCWMapMode);
237 pChartWindow->Paint(rRenderContext, aRectangle);
239 rRenderContext.Pop();
241 if (bRenderContextEnableMapMode)
242 rRenderContext.EnableMapMode(false);
243 if (bEnableMapMode)
244 pChartWindow->EnableMapMode(false);
247 void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice,
248 int nOutputWidth, int nOutputHeight,
249 int nTilePosX, int nTilePosY,
250 tools::Long nTileWidth, tools::Long nTileHeight,
251 bool bNegativeX)
253 if (comphelper::LibreOfficeKit::isTiledAnnotations())
254 return;
256 // Resizes the virtual device so to contain the entries context
257 rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
259 rDevice.Push(vcl::PushFlags::MAPMODE);
260 MapMode aMapMode(rDevice.GetMapMode());
262 // Scaling. Must convert from pixels to twips. We know
263 // that VirtualDevices use a DPI of 96.
264 const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
265 Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale;
266 Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale;
267 aMapMode.SetScaleX(scaleX);
268 aMapMode.SetScaleY(scaleY);
269 rDevice.SetMapMode(aMapMode);
271 SfxViewShell* pCurView = SfxViewShell::Current();
272 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
273 tools::Long nTileRectLeft = bNegativeX ? -nTilePosX - nTileWidth : nTilePosX;
274 tools::Rectangle aTileRect(Point(nTileRectLeft, nTilePosY), Size(nTileWidth, nTileHeight));
275 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
276 while (pViewShell)
278 if (pCurView && pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
280 LokChartHelper aChartHelper(pViewShell, bNegativeX);
281 aChartHelper.PaintTile(rDevice, aTileRect);
283 pViewShell = SfxViewShell::GetNext(*pViewShell);
285 rDevice.Pop();
288 bool LokChartHelper::postMouseEvent(int nType, int nX, int nY,
289 int nCount, int nButtons, int nModifier,
290 double fScaleX, double fScaleY)
292 Point aMousePos(nX, nY);
293 vcl::Window* pChartWindow = GetWindow();
294 if (pChartWindow)
296 tools::Rectangle rChartBBox = GetChartBoundingBox();
297 if (rChartBBox.Contains(aMousePos))
299 int nChartWinX = nX - rChartBBox.Left();
300 int nChartWinY = nY - rChartBBox.Top();
302 // chart window expects pixels, but the conversion factor
303 // can depend on the client zoom
304 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
306 LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK,
307 nButtons, nModifier);
308 SfxLokHelper::postMouseEventAsync(pChartWindow, aMouseEventData);
310 return true;
313 return false;
316 bool LokChartHelper::setTextSelection(int nType, int nX, int nY)
318 tools::Rectangle rChartBBox = GetChartBoundingBox();
319 if (rChartBBox.Contains(Point(nX, nY)))
321 css::uno::Reference<css::frame::XDispatch> xDispatcher = GetXDispatcher();
322 if (xDispatcher.is())
324 int nChartWinX = nX - rChartBBox.Left();
325 int nChartWinY = nY - rChartBBox.Top();
327 // no scale here the chart controller expects twips
328 // that are converted to hmm
329 util::URL aURL;
330 aURL.Path = "LOKSetTextSelection";
331 uno::Sequence< beans::PropertyValue > aArgs{
332 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nType)), // Why no name?
333 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nChartWinX)),
334 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nChartWinY))
336 xDispatcher->dispatch(aURL, aArgs);
338 return true;
340 return false;
343 bool LokChartHelper::setGraphicSelection(int nType, int nX, int nY,
344 double fScaleX, double fScaleY)
346 tools::Rectangle rChartBBox = GetChartBoundingBox();
347 if (rChartBBox.Contains(Point(nX, nY)))
349 int nChartWinX = nX - rChartBBox.Left();
350 int nChartWinY = nY - rChartBBox.Top();
352 vcl::Window* pChartWindow = GetWindow();
354 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
355 switch (nType)
357 case LOK_SETGRAPHICSELECTION_START:
359 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
360 pChartWindow->MouseButtonDown(aClickEvent);
361 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
362 pChartWindow->MouseMove(aMoveEvent);
364 break;
365 case LOK_SETGRAPHICSELECTION_END:
367 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
368 pChartWindow->MouseMove(aMoveEvent);
369 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
370 pChartWindow->MouseButtonUp(aClickEvent);
372 break;
373 default:
374 assert(false);
375 break;
377 return true;
379 return false;
383 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */