1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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
;
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()));
44 css::uno::Reference
<css::frame::XController
>& LokChartHelper::GetXController()
46 if(!mxController
.is() && mpViewShell
)
48 SfxInPlaceClient
* pIPClient
= mpViewShell
->GetIPClient();
51 const css::uno::Reference
< ::css::embed::XEmbeddedObject
>& xEmbObj
= pIPClient
->GetObject();
54 ::css::uno::Reference
< ::css::chart2::XChartDocument
> xChart( xEmbObj
->getComponent(), uno::UNO_QUERY
);
57 ::css::uno::Reference
< ::css::frame::XController
> xChartController
= xChart
->getCurrentController();
58 if( xChartController
.is() )
60 mxController
= xChartController
;
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
;
88 vcl::Window
* LokChartHelper::GetWindow()
92 ::css::uno::Reference
< ::css::frame::XController
>& xChartController
= GetXController();
93 if( xChartController
.is() )
95 ::css::uno::Reference
< ::css::frame::XFrame
> xFrame
= xChartController
->getFrame();
98 ::css::uno::Reference
< ::css::awt::XWindow
> xDockerWin
= xFrame
->getContainerWindow();
99 vcl::Window
* pParent
= VCLUnoHelper::GetWindow( xDockerWin
).get();
102 sal_uInt16 nTotChildren
= pParent
->GetChildCount();
103 while (nTotChildren
--)
105 vcl::Window
* pChildWin
= pParent
->GetChild(nTotChildren
);
106 if (pChildWin
&& pChildWin
->IsChart())
108 mpWindow
= pChildWin
;
117 return mpWindow
.get();
120 tools::Rectangle
LokChartHelper::GetChartBoundingBox()
122 tools::Rectangle aBBox
;
125 SfxInPlaceClient
* pIPClient
= mpViewShell
->GetIPClient();
128 vcl::Window
* pRootWin
= pIPClient
->GetEditWin();
131 vcl::Window
* pWindow
= GetWindow();
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
);
153 void LokChartHelper::Invalidate()
156 mxDispatcher
.clear();
157 mxController
.clear();
160 bool LokChartHelper::Hit(const Point
& aPos
)
164 vcl::Window
* pChartWindow
= GetWindow();
167 tools::Rectangle rChartBBox
= GetChartBoundingBox();
168 return rChartBBox
.IsInside(aPos
);
174 bool LokChartHelper::HitAny(const Point
& aPos
)
176 SfxViewShell
* pCurView
= SfxViewShell::Current();
177 int nPartForCurView
= pCurView
? pCurView
->getPart() : -1;
178 SfxViewShell
* pViewShell
= SfxViewShell::GetFirst();
181 if (pViewShell
->GetDocId() == pCurView
->GetDocId() && pViewShell
->getPart() == nPartForCurView
)
183 LokChartHelper
aChartHelper(pViewShell
);
184 if (aChartHelper
.Hit(aPos
))
187 pViewShell
= SfxViewShell::GetNext(*pViewShell
);
192 void LokChartHelper::PaintTile(VirtualDevice
& rRenderContext
, const tools::Rectangle
& rTileRect
)
197 vcl::Window
* pChartWindow
= GetWindow();
201 tools::Rectangle aChartRect
= GetChartBoundingBox();
202 tools::Rectangle aTestRect
= rTileRect
;
203 aTestRect
.Intersection( aChartRect
);
204 if (aTestRect
.IsEmpty())
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);
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())
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();
264 if (pCurView
&& pViewShell
->GetDocId() == pCurView
->GetDocId() && pViewShell
->getPart() == nPartForCurView
)
266 LokChartHelper
aChartHelper(pViewShell
);
267 aChartHelper
.PaintTile(rDevice
, aTileRect
);
269 pViewShell
= SfxViewShell::GetNext(*pViewShell
);
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();
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
);
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
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
);
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
);
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
);
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
);
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */