tdf#144694 In direct SQL dialog, activate options 'Run SQL command
[LibreOffice.git] / sfx2 / source / view / lokcharthelper.cxx
blob0ae4d9ae8bf20753dfb5332eb5575d3fe916c344
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 = std::move(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 = std::move(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 > 0)
90 --nTotChildren;
91 vcl::Window* pChildWin = pParent->GetChild(nTotChildren);
92 if (pChildWin && pChildWin->IsChart())
94 mpWindow = pChildWin;
95 break;
103 return mpWindow.get();
106 tools::Rectangle LokChartHelper::GetChartBoundingBox()
108 tools::Rectangle aBBox;
109 if (mpViewShell)
111 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
112 if (pIPClient)
114 vcl::Window* pRootWin = pIPClient->GetEditWin();
115 if (pRootWin)
117 vcl::Window* pWindow = GetWindow();
118 if (pWindow)
120 // In all cases, the following code fragment
121 // returns the chart bounding box in twips.
122 const MapMode& aCWMapMode = pWindow->GetMapMode();
123 constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
124 const auto& scaleX = aCWMapMode.GetScaleX();
125 const auto& scaleY = aCWMapMode.GetScaleY();
126 const auto nXNum = p.first * scaleX.GetDenominator();
127 const auto nXDen = p.second * scaleX.GetNumerator();
128 const auto nYNum = p.first * scaleY.GetDenominator();
129 const auto nYDen = p.second * scaleY.GetNumerator();
131 Point aOffset = pWindow->GetOffsetPixelFrom(*pRootWin);
132 if (mbNegativeX && AllSettings::GetLayoutRTL())
134 // If global RTL flag is set, vcl-window X offset of chart window is
135 // mirrored w.r.t parent window rectangle. This needs to be reverted.
136 aOffset.setX(pRootWin->GetOutOffXPixel() + pRootWin->GetSizePixel().Width()
137 - pWindow->GetOutOffXPixel() - pWindow->GetSizePixel().Width());
141 aOffset = aOffset.scale(nXNum, nXDen, nYNum, nYDen);
142 Size aSize = pWindow->GetSizePixel().scale(nXNum, nXDen, nYNum, nYDen);
143 aBBox = tools::Rectangle(aOffset, aSize);
148 return aBBox;
151 void LokChartHelper::Invalidate()
153 mpWindow = nullptr;
154 mxDispatcher.clear();
155 mxController.clear();
158 bool LokChartHelper::Hit(const Point& aPos)
160 if (mpViewShell)
162 vcl::Window* pChartWindow = GetWindow();
163 if (pChartWindow)
165 tools::Rectangle rChartBBox = GetChartBoundingBox();
166 return rChartBBox.Contains(aPos);
169 return false;
172 bool LokChartHelper::HitAny(const Point& aPos, bool bNegativeX)
174 SfxViewShell* pCurView = SfxViewShell::Current();
175 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
176 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
177 while (pViewShell)
179 if (pCurView && pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
181 LokChartHelper aChartHelper(pViewShell, bNegativeX);
182 if (aChartHelper.Hit(aPos))
183 return true;
185 pViewShell = SfxViewShell::GetNext(*pViewShell);
187 return false;
190 void LokChartHelper::PaintTile(VirtualDevice& rRenderContext, const tools::Rectangle& rTileRect)
192 if (!mpViewShell)
193 return;
195 vcl::Window* pChartWindow = GetWindow();
196 if (!pChartWindow)
197 return;
199 tools::Rectangle aChartRect = GetChartBoundingBox();
200 tools::Rectangle aTestRect = rTileRect;
201 aTestRect.Intersection( aChartRect );
202 if (aTestRect.IsEmpty())
203 return;
205 Point aOffset( aChartRect.Left() - rTileRect.Left(), aChartRect.Top() - rTileRect.Top() );
206 Point aOffsetFromTile = convertTwipToMm100(aOffset);
207 Size aSize = convertTwipToMm100(aChartRect.GetSize());
208 tools::Rectangle aRectangle(Point(0,0), aSize);
210 bool bEnableMapMode = !pChartWindow->IsMapModeEnabled();
211 pChartWindow->EnableMapMode();
212 bool bRenderContextEnableMapMode = !rRenderContext.IsMapModeEnabled();
213 rRenderContext.EnableMapMode();
215 rRenderContext.Push(vcl::PushFlags::MAPMODE);
217 MapMode aCWMapMode = pChartWindow->GetMapMode();
218 aCWMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
219 aCWMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
221 aCWMapMode.SetOrigin(aOffsetFromTile);
222 rRenderContext.SetMapMode(aCWMapMode);
224 pChartWindow->Paint(rRenderContext, aRectangle);
226 rRenderContext.Pop();
228 if (bRenderContextEnableMapMode)
229 rRenderContext.EnableMapMode(false);
230 if (bEnableMapMode)
231 pChartWindow->EnableMapMode(false);
234 void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice,
235 int nOutputWidth, int nOutputHeight,
236 int nTilePosX, int nTilePosY,
237 tools::Long nTileWidth, tools::Long nTileHeight,
238 bool bNegativeX)
240 if (comphelper::LibreOfficeKit::isTiledAnnotations())
241 return;
243 // Resizes the virtual device so to contain the entries context
244 rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
246 rDevice.Push(vcl::PushFlags::MAPMODE);
247 MapMode aMapMode(rDevice.GetMapMode());
249 // Scaling. Must convert from pixels to twips. We know
250 // that VirtualDevices use a DPI of 96.
251 const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
252 Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale;
253 Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale;
254 aMapMode.SetScaleX(scaleX);
255 aMapMode.SetScaleY(scaleY);
256 rDevice.SetMapMode(aMapMode);
258 SfxViewShell* pCurView = SfxViewShell::Current();
259 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
260 tools::Long nTileRectLeft = bNegativeX ? -nTilePosX - nTileWidth : nTilePosX;
261 tools::Rectangle aTileRect(Point(nTileRectLeft, nTilePosY), Size(nTileWidth, nTileHeight));
262 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
263 while (pViewShell)
265 if (pCurView && pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
267 LokChartHelper aChartHelper(pViewShell, bNegativeX);
268 aChartHelper.PaintTile(rDevice, aTileRect);
270 pViewShell = SfxViewShell::GetNext(*pViewShell);
272 rDevice.Pop();
275 bool LokChartHelper::postMouseEvent(int nType, int nX, int nY,
276 int nCount, int nButtons, int nModifier,
277 double fScaleX, double fScaleY)
279 Point aMousePos(nX, nY);
280 vcl::Window* pChartWindow = GetWindow();
281 if (pChartWindow)
283 tools::Rectangle rChartBBox = GetChartBoundingBox();
284 if (rChartBBox.Contains(aMousePos))
286 int nChartWinX = nX - rChartBBox.Left();
287 int nChartWinY = nY - rChartBBox.Top();
289 // chart window expects pixels, but the conversion factor
290 // can depend on the client zoom
291 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
293 LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK,
294 nButtons, nModifier);
295 SfxLokHelper::postMouseEventAsync(pChartWindow, aMouseEventData);
297 return true;
300 return false;
303 bool LokChartHelper::setTextSelection(int nType, int nX, int nY)
305 tools::Rectangle rChartBBox = GetChartBoundingBox();
306 if (rChartBBox.Contains(Point(nX, nY)))
308 css::uno::Reference<css::frame::XDispatch> xDispatcher = GetXDispatcher();
309 if (xDispatcher.is())
311 int nChartWinX = nX - rChartBBox.Left();
312 int nChartWinY = nY - rChartBBox.Top();
314 // no scale here the chart controller expects twips
315 // that are converted to hmm
316 util::URL aURL;
317 aURL.Path = "LOKSetTextSelection";
318 uno::Sequence< beans::PropertyValue > aArgs{
319 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nType)), // Why no name?
320 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nChartWinX)),
321 comphelper::makePropertyValue({}, static_cast<sal_Int32>(nChartWinY))
323 xDispatcher->dispatch(aURL, aArgs);
325 return true;
327 return false;
330 bool LokChartHelper::setGraphicSelection(int nType, int nX, int nY,
331 double fScaleX, double fScaleY)
333 tools::Rectangle rChartBBox = GetChartBoundingBox();
334 if (rChartBBox.Contains(Point(nX, nY)))
336 int nChartWinX = nX - rChartBBox.Left();
337 int nChartWinY = nY - rChartBBox.Top();
339 vcl::Window* pChartWindow = GetWindow();
341 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
342 switch (nType)
344 case LOK_SETGRAPHICSELECTION_START:
346 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
347 pChartWindow->MouseButtonDown(aClickEvent);
348 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
349 pChartWindow->MouseMove(aMoveEvent);
351 break;
352 case LOK_SETGRAPHICSELECTION_END:
354 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
355 pChartWindow->MouseMove(aMoveEvent);
356 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
357 pChartWindow->MouseButtonUp(aClickEvent);
359 break;
360 default:
361 assert(false);
362 break;
364 return true;
366 return false;
370 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */