diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2022-01-17 17:15:46 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2022-07-27 08:30:38 +0200 |
commit | a333479f014286129a79fbca2386f6a82df9fddc (patch) | |
tree | d778760de377ad47256188e95f83a2bfb2265525 /sfx2 | |
parent | ff09dd0bdcd64503c15f4b9ee4cdf6238426437c (diff) |
lok: enable in-place editing of math equations
Change-Id: Ic4d187d1e2ee92eab74a6bb43e47bb4f3d47ebd2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128506
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137460
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Diffstat (limited to 'sfx2')
-rw-r--r-- | sfx2/Library_sfx.mk | 1 | ||||
-rw-r--r-- | sfx2/source/view/lokcharthelper.cxx | 2 | ||||
-rw-r--r-- | sfx2/source/view/lokstarmathhelper.cxx | 169 |
3 files changed, 171 insertions, 1 deletions
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk index d5f1c28ed436..9dc334ac0f12 100644 --- a/sfx2/Library_sfx.mk +++ b/sfx2/Library_sfx.mk @@ -300,6 +300,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\ sfx2/source/view/frmload \ sfx2/source/view/ipclient \ sfx2/source/view/lokcharthelper \ + sfx2/source/view/lokstarmathhelper \ sfx2/source/view/lokhelper \ sfx2/source/view/printer \ sfx2/source/view/sfxbasecontroller \ diff --git a/sfx2/source/view/lokcharthelper.cxx b/sfx2/source/view/lokcharthelper.cxx index ebd0ba14c0fc..e319cd2ea048 100644 --- a/sfx2/source/view/lokcharthelper.cxx +++ b/sfx2/source/view/lokcharthelper.cxx @@ -7,7 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <sfx2/lokcharthelper.hxx> +#include <sfx2/lokcomponenthelpers.hxx> #include <comphelper/lok.hxx> #include <comphelper/propertyvalue.hxx> diff --git a/sfx2/source/view/lokstarmathhelper.cxx b/sfx2/source/view/lokstarmathhelper.cxx new file mode 100644 index 000000000000..fedd931b08fd --- /dev/null +++ b/sfx2/source/view/lokstarmathhelper.cxx @@ -0,0 +1,169 @@ +/* -*- 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* FindSmGraphicWidgetWindow(vcl::Window* pWin) +{ + return FindChildSmGraphicWidgetWindow(FindSmGraphicWindow(pWin)); +} +} + +vcl::Window* LokStarMathHelper::GetWindow() +{ + if (!mpWindow) + { + 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(); + mpWindow.set(FindSmGraphicWidgetWindow(VCLUnoHelper::GetWindow(xDockerWin))); + } + } + } + + return mpWindow.get(); +} + +tools::Rectangle LokStarMathHelper::GetBoundingBox() +{ + if (mpViewShell) + { + if (SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient()) + { + if (vcl::Window* pRootWin = pIPClient->GetEditWin()) + { + if (vcl::Window* pWindow = GetWindow()) + { + // In all cases, the following code fragment + // returns the bounding box in twips. + const MapMode& aMapMode = pWindow->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 = GetWindow()) + { + 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: */ |