summaryrefslogtreecommitdiffstats
path: root/sfx2/source/view/lokstarmathhelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/view/lokstarmathhelper.cxx')
-rw-r--r--sfx2/source/view/lokstarmathhelper.cxx174
1 files changed, 174 insertions, 0 deletions
diff --git a/sfx2/source/view/lokstarmathhelper.cxx b/sfx2/source/view/lokstarmathhelper.cxx
new file mode 100644
index 000000000..9df487595
--- /dev/null
+++ b/sfx2/source/view/lokstarmathhelper.cxx
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <sfx2/ipclient.hxx>
+#include <sfx2/lokcomponenthelpers.hxx>
+#include <sfx2/lokhelper.hxx>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/fract.hxx>
+#include <vcl/layout.hxx>
+#include <vcl/window.hxx>
+
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+css::uno::Reference<css::frame::XController>& LokStarMathHelper::GetXController()
+{
+ if (!mxController && mpViewShell)
+ {
+ if (const SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient())
+ {
+ if (const auto& xEmbObj = pIPClient->GetObject())
+ {
+ css::uno::Reference<css::lang::XServiceInfo> xComp(xEmbObj->getComponent(),
+ css::uno::UNO_QUERY);
+ if (xComp && xComp->supportsService("com.sun.star.formula.FormulaProperties"))
+ if (css::uno::Reference<css::frame::XModel> xModel{ xComp,
+ css::uno::UNO_QUERY })
+ mxController = xModel->getCurrentController();
+ }
+ }
+ }
+
+ return mxController;
+}
+
+namespace
+{
+// Find a child SmGraphicWindow*
+vcl::Window* FindSmGraphicWindow(vcl::Window* pWin)
+{
+ if (!pWin)
+ return nullptr;
+
+ if (pWin->IsStarMath())
+ return pWin;
+
+ pWin = pWin->GetWindow(GetWindowType::FirstChild);
+ while (pWin)
+ {
+ if (vcl::Window* pSmGraphicWindow = FindSmGraphicWindow(pWin))
+ return pSmGraphicWindow;
+ pWin = pWin->GetWindow(GetWindowType::Next);
+ }
+ return nullptr;
+}
+
+// Find a child window that corresponds to SmGraphicWidget
+vcl::Window* FindChildSmGraphicWidgetWindow(vcl::Window* pWin)
+{
+ if (!pWin)
+ return nullptr;
+
+ // The needed window is a VclDrawingArea
+ if (dynamic_cast<VclDrawingArea*>(pWin))
+ return pWin;
+
+ pWin = pWin->GetWindow(GetWindowType::FirstChild);
+ while (pWin)
+ {
+ if (vcl::Window* pSmGraphicWidgetWindow = FindChildSmGraphicWidgetWindow(pWin))
+ return pSmGraphicWidgetWindow;
+ pWin = pWin->GetWindow(GetWindowType::Next);
+ }
+ return nullptr;
+}
+}
+
+vcl::Window* LokStarMathHelper::GetGraphicWindow()
+{
+ if (!mpGraphicWindow)
+ {
+ if (const css::uno::Reference<css::frame::XController>& xController = GetXController())
+ {
+ if (const css::uno::Reference<css::frame::XFrame> xFrame = xController->getFrame())
+ {
+ css::uno::Reference<css::awt::XWindow> xDockerWin = xFrame->getContainerWindow();
+ mpGraphicWindow.set(FindSmGraphicWindow(VCLUnoHelper::GetWindow(xDockerWin)));
+ }
+ }
+ }
+
+ return mpGraphicWindow.get();
+}
+
+vcl::Window* LokStarMathHelper::GetWidgetWindow()
+{
+ if (!mpWidgetWindow)
+ mpWidgetWindow.set(FindChildSmGraphicWidgetWindow(GetGraphicWindow()));
+
+ return mpWidgetWindow.get();
+}
+
+tools::Rectangle LokStarMathHelper::GetBoundingBox()
+{
+ if (mpViewShell)
+ {
+ if (SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient())
+ {
+ if (vcl::Window* pRootWin = pIPClient->GetEditWin())
+ {
+ if (vcl::Window* pWindow = GetWidgetWindow())
+ {
+ // In all cases, the following code fragment
+ // returns the bounding box in twips.
+ // Note: the correct mapmode (representing document zoom) is provided by
+ // GraphicWindow, not WidgetWindow
+ const MapMode& aMapMode = GetGraphicWindow()->GetMapMode();
+ const auto & [ m, d ]
+ = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
+ const Fraction& scaleX = aMapMode.GetScaleX();
+ const Fraction& scaleY = aMapMode.GetScaleY();
+ const auto nXNum = m * scaleX.GetDenominator();
+ const auto nXDen = d * scaleX.GetNumerator();
+ const auto nYNum = m * scaleY.GetDenominator();
+ const auto nYDen = d * scaleY.GetNumerator();
+
+ Point aOffset
+ = pWindow->GetOffsetPixelFrom(*pRootWin).scale(nXNum, nXDen, nYNum, nYDen);
+ Size aSize = pWindow->GetSizePixel().scale(nXNum, nXDen, nYNum, nYDen);
+ return { aOffset, aSize };
+ }
+ }
+ }
+ }
+ return {};
+}
+
+bool LokStarMathHelper::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons,
+ int nModifier, double fScaleX, double fScaleY)
+{
+ if (vcl::Window* pWindow = GetWidgetWindow())
+ {
+ Point aMousePos(nX, nY);
+ tools::Rectangle rBBox = GetBoundingBox();
+ if (rBBox.Contains(aMousePos))
+ {
+ int nWinX = nX - rBBox.Left();
+ int nWinY = nY - rBBox.Top();
+
+ // window expects pixels, but the conversion factor
+ // can depend on the client zoom
+ Point aPos(nWinX * fScaleX, nWinY * fScaleY);
+
+ LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK,
+ nButtons, nModifier);
+ SfxLokHelper::postMouseEventAsync(pWindow, aMouseEventData);
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */