diff options
Diffstat (limited to 'sfx2/source/view/lokstarmathhelper.cxx')
-rw-r--r-- | sfx2/source/view/lokstarmathhelper.cxx | 174 |
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: */ |