LibreOffice Module sfx2 (master) 1
lokstarmathhelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
10#include <sal/config.h>
11
12#include <sfx2/ipclient.hxx>
14#include <sfx2/lokhelper.hxx>
15#include <sfx2/objsh.hxx>
16
18#include <comphelper/lok.hxx>
20#include <tools/fract.hxx>
22#include <vcl/layout.hxx>
23#include <vcl/virdev.hxx>
24#include <vcl/window.hxx>
25
26#include <com/sun/star/embed/XEmbeddedObject.hpp>
27#include <com/sun/star/frame/XModel.hpp>
28#include <com/sun/star/lang/XServiceInfo.hpp>
29
31 : mpViewShell(pViewShell)
32{
33 if (mpViewShell)
34 {
35 if (const SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient())
36 {
37 if (const auto& xEmbObj = pIPClient->GetObject())
38 {
39 css::uno::Reference<css::lang::XServiceInfo> xComp(xEmbObj->getComponent(),
40 css::uno::UNO_QUERY);
41 if (xComp && xComp->supportsService("com.sun.star.formula.FormulaProperties"))
42 {
43 if (css::uno::Reference<css::frame::XModel> xModel{ xComp,
44 css::uno::UNO_QUERY })
45 {
46 if (auto xController = xModel->getCurrentController())
47 {
48 mpIPClient = pIPClient;
49 mxFrame = xController->getFrame();
50 }
51 }
52 }
53 }
54 }
55 }
56}
57
59 const OUString& cmd, const css::uno::Sequence<css::beans::PropertyValue>& rArguments) const
60{
61 if (mxFrame)
62 comphelper::dispatchCommand(cmd, mxFrame, rArguments);
63}
64
65namespace
66{
67// Find a child SmGraphicWindow*
68vcl::Window* FindSmGraphicWindow(vcl::Window* pWin)
69{
70 if (!pWin)
71 return nullptr;
72
73 if (pWin->IsStarMath())
74 return pWin;
75
76 pWin = pWin->GetWindow(GetWindowType::FirstChild);
77 while (pWin)
78 {
79 if (vcl::Window* pSmGraphicWindow = FindSmGraphicWindow(pWin))
80 return pSmGraphicWindow;
81 pWin = pWin->GetWindow(GetWindowType::Next);
82 }
83 return nullptr;
84}
85
86// Find a child window that corresponds to SmGraphicWidget
87vcl::Window* FindChildSmGraphicWidgetWindow(vcl::Window* pWin)
88{
89 if (!pWin)
90 return nullptr;
91
92 // The needed window is a VclDrawingArea
93 if (dynamic_cast<VclDrawingArea*>(pWin))
94 return pWin;
95
96 pWin = pWin->GetWindow(GetWindowType::FirstChild);
97 while (pWin)
98 {
99 if (vcl::Window* pSmGraphicWidgetWindow = FindChildSmGraphicWidgetWindow(pWin))
100 return pSmGraphicWidgetWindow;
101 pWin = pWin->GetWindow(GetWindowType::Next);
102 }
103 return nullptr;
104}
105}
106
108{
109 if (!mpGraphicWindow)
110 {
111 if (mxFrame)
112 {
113 css::uno::Reference<css::awt::XWindow> xDockerWin = mxFrame->getContainerWindow();
114 mpGraphicWindow.set(FindSmGraphicWindow(VCLUnoHelper::GetWindow(xDockerWin)));
115 }
116 }
117
118 return mpGraphicWindow.get();
119}
120
122{
123 if (!mpWidgetWindow)
124 mpWidgetWindow.set(FindChildSmGraphicWidgetWindow(GetGraphicWindow()));
125
126 return mpWidgetWindow.get();
127}
128
130{
131 if (vcl::Window* pGraphWindow = GetGraphicWindow())
132 {
133 return SfxViewShell::GetFirst(false, [pGraphWindow](const SfxViewShell* shell) {
134 return shell->GetWindow() && shell->GetWindow()->IsChild(pGraphWindow);
135 });
136 }
137 return nullptr;
138}
139
141{
142 if (mpIPClient)
143 {
145 if (SfxObjectShell* pObjShell = const_cast<SfxViewShell*>(mpViewShell)->GetObjectShell())
146 {
147 const o3tl::Length unit = MapToO3tlLength(pObjShell->GetMapUnit());
148 if (unit != o3tl::Length::twip && unit != o3tl::Length::invalid)
149 r = o3tl::convert(r, unit, o3tl::Length::twip);
150 }
151 return r;
152 }
153 return {};
154}
155
156bool LokStarMathHelper::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons,
157 int nModifier, double fPPTScaleX, double fPPTScaleY)
158{
159 const tools::Rectangle rBBox = GetBoundingBox();
160 if (Point aMousePos(nX, nY); rBBox.Contains(aMousePos))
161 {
162 if (vcl::Window* pWindow = GetWidgetWindow())
163 {
164 aMousePos -= rBBox.TopLeft();
165
166 // In lok, Math does not convert coordinates (see SmGraphicWidget::SetDrawingArea,
167 // which disables MapMode), and uses twips internally (see SmDocShell ctor and
168 // SmMapUnit), but the conversion factor can depend on the client zoom.
169 // 1. Remove the twip->pixel factor in the passed scales
170 double fScaleX = o3tl::convert(fPPTScaleX, o3tl::Length::px, o3tl::Length::twip);
171 double fScaleY = o3tl::convert(fPPTScaleY, o3tl::Length::px, o3tl::Length::twip);
172 // 2. Adjust the position according to the scales
173 aMousePos
174 = Point(std::round(aMousePos.X() * fScaleX), std::round(aMousePos.Y() * fScaleY));
175 // 3. Take window own scaling into account (reverses the conversion done in
176 // SmGraphicWidget::MouseButtonDown, albeit incompletely - it does not handle
177 // GetFormulaDrawPos; hopefully, in lok/in-place case, it's always [ 0, 0 ]?)
178 aMousePos = pWindow->LogicToPixel(aMousePos);
179
180 LokMouseEventData aMouseEventData(
181 nType, aMousePos, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
182 SfxLokHelper::postMouseEventAsync(pWindow, aMouseEventData);
183
184 return true;
185 }
186 }
187 return false;
188}
189
191{
192 const tools::Rectangle aMathRect = GetBoundingBox();
193 if (rTileRect.GetIntersection(aMathRect).IsEmpty())
194 return;
195
196 vcl::Window* pWidgetWindow = GetWidgetWindow();
197 if (!pWidgetWindow)
198 return;
199
200 Point aOffset(aMathRect.Left() - rTileRect.Left(), aMathRect.Top() - rTileRect.Top());
201
202 MapMode newMode = rDevice.GetMapMode();
203 newMode.SetOrigin(aOffset);
204 rDevice.SetMapMode(newMode); // Push/Pop is done in PaintAllInPlaceOnTile
205
206 pWidgetWindow->Paint(rDevice, {}); // SmGraphicWidget::Paint does not use the passed rectangle
207}
208
210 int nOutputHeight, int nTilePosX, int nTilePosY,
211 tools::Long nTileWidth, tools::Long nTileHeight)
212{
214 return;
215
217 if (!pCurView)
218 return;
219 const ViewShellDocId nDocId = pCurView->GetDocId();
220 const int nPartForCurView = pCurView->getPart();
221
222 // Resizes the virtual device to contain the entries context
223 rDevice.SetOutputSizePixel({ nOutputWidth, nOutputHeight });
224
226 MapMode aMapMode(rDevice.GetMapMode());
227
228 // Scaling. Must convert from pixels to twips. We know that VirtualDevices use a DPI of 96.
230 const Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale;
231 const Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale;
232 aMapMode.SetScaleX(scaleX);
233 aMapMode.SetScaleY(scaleY);
234 aMapMode.SetMapUnit(MapUnit::MapTwip);
235 rDevice.SetMapMode(aMapMode);
236
237 const tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
238
239 for (SfxViewShell* pViewShell = SfxViewShell::GetFirst(); pViewShell;
240 pViewShell = SfxViewShell::GetNext(*pViewShell))
241 if (pViewShell->GetDocId() == nDocId && pViewShell->getPart() == nPartForCurView)
242 LokStarMathHelper(pViewShell).PaintTile(rDevice, aTileRect);
243
244 rDevice.Pop();
245}
246
247/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
Fraction conversionFract(o3tl::Length from, o3tl::Length to)
constexpr o3tl::Length MapToO3tlLength(MapUnit eU, o3tl::Length ePixelValue=o3tl::Length::px)
const SfxViewShell * mpViewShell
vcl::Window * GetWidgetWindow()
void PaintTile(VirtualDevice &rDevice, const tools::Rectangle &rTileRect)
VclPtr< vcl::Window > mpGraphicWindow
const SfxViewShell * GetSmViewShell()
vcl::Window * GetGraphicWindow()
bool postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier, double fPPTScaleX, double fPPTScaleY)
VclPtr< vcl::Window > mpWidgetWindow
static void PaintAllInPlaceOnTile(VirtualDevice &rDevice, int nOutputWidth, int nOutputHeight, int nTilePosX, int nTilePosY, tools::Long nTileWidth, tools::Long nTileHeight)
LokStarMathHelper(const SfxViewShell *pViewShell)
void Dispatch(const OUString &cmd, const css::uno::Sequence< css::beans::PropertyValue > &rArguments) const
css::uno::Reference< css::frame::XFrame > mxFrame
tools::Rectangle GetBoundingBox() const
const SfxInPlaceClient * mpIPClient
void SetOrigin(const Point &rOrigin)
void SetScaleY(const Fraction &rScaleY)
void SetMapUnit(MapUnit eUnit)
void SetScaleX(const Fraction &rScaleX)
void SetMapMode()
const MapMode & GetMapMode() const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
const tools::Rectangle & GetObjArea() const
Definition: ipclient.cxx:772
static void postMouseEventAsync(const VclPtr< vcl::Window > &xWindow, LokMouseEventData const &rLokMouseEventData)
Helper for posting async mouse event.
Definition: lokhelper.cxx:929
One SfxViewShell more or less represents one edit window for a document, there can be multiple ones f...
Definition: viewsh.hxx:165
ViewShellDocId GetDocId() const override
Get the DocId used by Mobile LOKit to load multiple documents.
Definition: viewsh.cxx:2436
static SAL_WARN_UNUSED_RESULT SfxViewShell * GetNext(const SfxViewShell &rPrev, bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
Definition: viewsh.cxx:2046
static SAL_WARN_UNUSED_RESULT SfxViewShell * GetFirst(bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
Definition: viewsh.cxx:2017
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
Definition: viewsh.cxx:1848
SfxInPlaceClient * GetIPClient() const
Definition: viewsh.cxx:1494
virtual int getPart() const
See lok::Document::getPart().
Definition: viewsh.cxx:2416
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
void set(reference_type *pBody)
reference_type * get() const
bool SetOutputSizePixel(const Size &rNewSize, bool bErase=true, bool bAlphaMaskTransparent=false)
bool Contains(const Point &rPOINT) const
tools::Rectangle GetIntersection(const tools::Rectangle &rRect) const
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr tools::Long Left() const
constexpr bool IsEmpty() const
vcl::Window * GetWindow(GetWindowType nType) const
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
virtual bool IsStarMath() const
int nCount
bool dispatchCommand(const OUString &rCommand, const uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Sequence< css::beans::PropertyValue > &rArguments, const uno::Reference< css::frame::XDispatchResultListener > &rListener)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
long Long
sal_Int32 scale
QPRO_FUNC_TYPE nType
Reference< XController > xController
Reference< XModel > xModel