Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / view / lokcharthelper.cxx
blobd5995e33ba8d9e9d79c5acb671b8efaf29119fbd
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/lokcharthelper.hxx>
12 #include <comphelper/lok.hxx>
13 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
14 #include <sfx2/ipclient.hxx>
15 #include <sfx2/lokhelper.hxx>
16 #include <toolkit/helper/vclunohelper.hxx>
17 #include <tools/fract.hxx>
18 #include <tools/mapunit.hxx>
19 #include <tools/UnitConversion.hxx>
20 #include <vcl/virdev.hxx>
22 #include <com/sun/star/embed/XEmbeddedObject.hpp>
23 #include <com/sun/star/frame/XDispatch.hpp>
24 #include <com/sun/star/chart2/XChartDocument.hpp>
26 #define TWIPS_PER_PIXEL 15
28 using namespace com::sun::star;
30 namespace {
32 Point lcl_TwipsToHMM( const Point& rPoint )
34 return Point(convertTwipToMm100(rPoint.getX()), convertTwipToMm100(rPoint.getY()));
37 Size lcl_TwipsToHMM( const Size& rSize )
39 return Size(convertTwipToMm100(rSize.getWidth()), convertTwipToMm100(rSize.getHeight()));
42 } // end anonymous ns
44 css::uno::Reference<css::frame::XController>& LokChartHelper::GetXController()
46 if(!mxController.is() && mpViewShell)
48 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
49 if (pIPClient)
51 const css::uno::Reference< ::css::embed::XEmbeddedObject >& xEmbObj = pIPClient->GetObject();
52 if( xEmbObj.is() )
54 ::css::uno::Reference< ::css::chart2::XChartDocument > xChart( xEmbObj->getComponent(), uno::UNO_QUERY );
55 if( xChart.is() )
57 ::css::uno::Reference< ::css::frame::XController > xChartController = xChart->getCurrentController();
58 if( xChartController.is() )
60 mxController = xChartController;
67 return mxController;
70 css::uno::Reference<css::frame::XDispatch>& LokChartHelper::GetXDispatcher()
72 if( !mxDispatcher.is() )
74 ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
75 if( xChartController.is() )
77 ::css::uno::Reference< ::css::frame::XDispatch > xDispatcher( xChartController, uno::UNO_QUERY );
78 if( xDispatcher.is() )
80 mxDispatcher = xDispatcher;
85 return mxDispatcher;
88 vcl::Window* LokChartHelper::GetWindow()
90 if (!mpWindow)
92 ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
93 if( xChartController.is() )
95 ::css::uno::Reference< ::css::frame::XFrame > xFrame = xChartController->getFrame();
96 if (xFrame.is())
98 ::css::uno::Reference< ::css::awt::XWindow > xDockerWin = xFrame->getContainerWindow();
99 vcl::Window* pParent = VCLUnoHelper::GetWindow( xDockerWin ).get();
100 if (pParent)
102 sal_uInt16 nTotChildren = pParent->GetChildCount();
103 while (nTotChildren--)
105 vcl::Window* pChildWin = pParent->GetChild(nTotChildren);
106 if (pChildWin && pChildWin->IsChart())
108 mpWindow = pChildWin;
109 break;
117 return mpWindow.get();
120 tools::Rectangle LokChartHelper::GetChartBoundingBox()
122 tools::Rectangle aBBox;
123 if (mpViewShell)
125 SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
126 if (pIPClient)
128 vcl::Window* pRootWin = pIPClient->GetEditWin();
129 if (pRootWin)
131 vcl::Window* pWindow = GetWindow();
132 if (pWindow)
134 // In all cases, the following code fragment
135 // returns the chart bounding box in twips.
136 const MapMode& aCWMapMode = pWindow->GetMapMode();
137 double fXScale( aCWMapMode.GetScaleX() );
138 double fYScale( aCWMapMode.GetScaleY() );
139 Point aOffset = pWindow->GetOffsetPixelFrom(*pRootWin);
140 aOffset.setX( aOffset.X() * (TWIPS_PER_PIXEL / fXScale) );
141 aOffset.setY( aOffset.Y() * (TWIPS_PER_PIXEL / fYScale) );
142 Size aSize = pWindow->GetSizePixel();
143 aSize.setWidth( aSize.Width() * (TWIPS_PER_PIXEL / fXScale) );
144 aSize.setHeight( aSize.Height() * (TWIPS_PER_PIXEL / fYScale) );
145 aBBox = tools::Rectangle(aOffset, aSize);
150 return aBBox;
153 void LokChartHelper::Invalidate()
155 mpWindow = nullptr;
156 mxDispatcher.clear();
157 mxController.clear();
160 bool LokChartHelper::Hit(const Point& aPos)
162 if (mpViewShell)
164 vcl::Window* pChartWindow = GetWindow();
165 if (pChartWindow)
167 tools::Rectangle rChartBBox = GetChartBoundingBox();
168 return rChartBBox.IsInside(aPos);
171 return false;
174 bool LokChartHelper::HitAny(const Point& aPos)
176 SfxViewShell* pCurView = SfxViewShell::Current();
177 int nPartForCurView = pCurView ? pCurView->getPart() : -1;
178 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
179 while (pViewShell)
181 if (pViewShell->GetDocId() == pCurView->GetDocId() && pViewShell->getPart() == nPartForCurView)
183 LokChartHelper aChartHelper(pViewShell);
184 if (aChartHelper.Hit(aPos))
185 return true;
187 pViewShell = SfxViewShell::GetNext(*pViewShell);
189 return false;
192 void LokChartHelper::PaintTile(VirtualDevice& rRenderContext, const tools::Rectangle& rTileRect)
194 if (!mpViewShell)
195 return;
197 vcl::Window* pChartWindow = GetWindow();
198 if (!pChartWindow)
199 return;
201 tools::Rectangle aChartRect = GetChartBoundingBox();
202 tools::Rectangle aTestRect = rTileRect;
203 aTestRect.Intersection( aChartRect );
204 if (aTestRect.IsEmpty())
205 return;
207 Point aOffset( aChartRect.Left() - rTileRect.Left(), aChartRect.Top() - rTileRect.Top() );
208 Point aOffsetFromTile = lcl_TwipsToHMM(aOffset);
209 Size aSize = lcl_TwipsToHMM(aChartRect.GetSize());
210 tools::Rectangle aRectangle(Point(0,0), aSize);
212 bool bEnableMapMode = !pChartWindow->IsMapModeEnabled();
213 pChartWindow->EnableMapMode();
214 bool bRenderContextEnableMapMode = !rRenderContext.IsMapModeEnabled();
215 rRenderContext.EnableMapMode();
217 rRenderContext.Push(PushFlags::MAPMODE);
219 MapMode aCWMapMode = pChartWindow->GetMapMode();
220 aCWMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
221 aCWMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
223 aCWMapMode.SetOrigin(aOffsetFromTile);
224 rRenderContext.SetMapMode(aCWMapMode);
226 pChartWindow->Paint(rRenderContext, aRectangle);
228 rRenderContext.Pop();
230 if (bRenderContextEnableMapMode)
231 rRenderContext.EnableMapMode(false);
232 if (bEnableMapMode)
233 pChartWindow->EnableMapMode(false);
236 void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice,
237 int nOutputWidth, int nOutputHeight,
238 int nTilePosX, int nTilePosY,
239 tools::Long nTileWidth, tools::Long nTileHeight)
241 if (comphelper::LibreOfficeKit::isTiledAnnotations())
242 return;
244 // Resizes the virtual device so to contain the entries context
245 rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
247 rDevice.Push(PushFlags::MAPMODE);
248 MapMode aMapMode(rDevice.GetMapMode());
250 // Scaling. Must convert from pixels to twips. We know
251 // that VirtualDevices use a DPI of 96.
252 Fraction scaleX = Fraction(nOutputWidth, 96) * Fraction(1440) / Fraction(nTileWidth);
253 Fraction scaleY = Fraction(nOutputHeight, 96) * Fraction(1440) / Fraction(nTileHeight);
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::Rectangle aTileRect(Point(nTilePosX, 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);
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.IsInside(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.IsInside(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(3);
318 aArgs[0].Value <<= static_cast<sal_Int32>(nType);
319 aArgs[1].Value <<= static_cast<sal_Int32>(nChartWinX);
320 aArgs[2].Value <<= static_cast<sal_Int32>(nChartWinY);
321 xDispatcher->dispatch(aURL, aArgs);
323 return true;
325 return false;
328 bool LokChartHelper::setGraphicSelection(int nType, int nX, int nY,
329 double fScaleX, double fScaleY)
331 tools::Rectangle rChartBBox = GetChartBoundingBox();
332 if (rChartBBox.IsInside(Point(nX, nY)))
334 int nChartWinX = nX - rChartBBox.Left();
335 int nChartWinY = nY - rChartBBox.Top();
337 vcl::Window* pChartWindow = GetWindow();
339 Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
340 switch (nType)
342 case LOK_SETGRAPHICSELECTION_START:
344 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
345 pChartWindow->MouseButtonDown(aClickEvent);
346 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
347 pChartWindow->MouseMove(aMoveEvent);
349 break;
350 case LOK_SETGRAPHICSELECTION_END:
352 MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
353 pChartWindow->MouseMove(aMoveEvent);
354 MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
355 pChartWindow->MouseButtonUp(aClickEvent);
357 break;
358 default:
359 assert(false);
360 break;
362 return true;
364 return false;
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */