[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - include/sfx2 include/vcl sc/source vcl/source

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Tue May 11 06:47:00 UTC 2021


 include/sfx2/LokControlHandler.hxx |  179 +++++++++++++++++++++++++++++++++++++
 include/vcl/ctrl.hxx               |    4 
 sc/source/ui/unoobj/docuno.cxx     |   30 +++++-
 vcl/source/control/ctrl.cxx        |   15 +++
 4 files changed, 223 insertions(+), 5 deletions(-)

New commits:
commit f4e986730c3e750b0fb6db9371f2f42279ea3b5b
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Apr 26 10:43:11 2021 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Tue May 11 08:46:22 2021 +0200

    lok: add rendering and input for form controls in Calc
    
    Until now the form controls were nto rendered to a tile when
    drawing tiles for LOKit usage (online). This change adds
    LokControlHandler that is responsible for rendering of the
    form controls on the tiles (currently implemented only for Calc)
    and handles mouse input events that come through LOKit.
    
    Change-Id: Ifcecc9a320a7836b76b0a10771b06c15339baed2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114909
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/sfx2/LokControlHandler.hxx b/include/sfx2/LokControlHandler.hxx
new file mode 100644
index 000000000000..34547950643c
--- /dev/null
+++ b/include/sfx2/LokControlHandler.hxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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/.
+ */
+
+#pragma once
+
+#include <sfx2/dllapi.h>
+#include <svx/svdouno.hxx>
+#include <vcl/window.hxx>
+#include <tools/UnitConversion.hxx>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/XGraphics.hpp>
+#include <com/sun/star/awt/XView.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+
+class LokControlHandler
+{
+public:
+    static constexpr double convertMm100ToPixel(double fNumber) { return fNumber * 96.0 / 2540.0; }
+
+    static Point convertMm100ToPixel(const Point& rPoint)
+    {
+        return Point(convertMm100ToPixel(rPoint.getX()), convertMm100ToPixel(rPoint.getY()));
+    }
+
+    static tools::Rectangle convertMm100ToPixel(const tools::Rectangle& rRectangle)
+    {
+        return tools::Rectangle(convertMm100ToPixel(rRectangle.TopLeft()),
+                                Size(convertMm100ToPixel(rRectangle.GetWidth()),
+                                     convertMm100ToPixel(rRectangle.GetHeight())));
+    }
+
+    static Point convertTwipToMm100(const Point& rPoint)
+    {
+        return Point(::convertTwipToMm100(sal_Int64(rPoint.getX())),
+                     ::convertTwipToMm100(sal_Int64(rPoint.getY())));
+    }
+
+    static tools::Rectangle convertTwipToMm100(const tools::Rectangle& rRectangle)
+    {
+        return tools::Rectangle(convertTwipToMm100(rRectangle.TopLeft()),
+                                Size(::convertTwipToMm100(rRectangle.GetWidth()),
+                                     ::convertTwipToMm100(rRectangle.GetHeight())));
+    }
+
+    static bool postMouseEvent(SdrPage* pPage, SdrView* pDrawView, vcl::Window const& rMainWindow,
+                               int nType, Point aPointHmm, int nCount, int nButtons, int nModifier)
+    {
+        SdrObjListIter aIterator(pPage, SdrIterMode::Flat);
+        while (aIterator.IsMore())
+        {
+            SdrObject* pObject = aIterator.Next();
+            SdrUnoObj* pUnoObect = dynamic_cast<SdrUnoObj*>(pObject);
+            if (pUnoObect)
+            {
+                tools::Rectangle aControlRectHMM = pUnoObect->GetLogicRect();
+                if (aControlRectHMM.IsInside(aPointHmm))
+                {
+                    css::uno::Reference<css::awt::XControl> xControl
+                        = pUnoObect->GetUnoControl(*pDrawView, rMainWindow);
+                    if (!xControl.is())
+                        return false;
+
+                    css::uno::Reference<css::awt::XWindow> xControlWindow(xControl,
+                                                                          css::uno::UNO_QUERY);
+                    if (!xControlWindow.is())
+                        return false;
+
+                    css::uno::Reference<css::awt::XWindowPeer> xWindowPeer(xControl->getPeer());
+
+                    VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindowPeer);
+                    if (pWindow)
+                    {
+                        Point aControlRelativePositionHMM = aPointHmm - aControlRectHMM.TopLeft();
+                        Point aControlRelativePosition
+                            = convertMm100ToPixel(aControlRelativePositionHMM);
+
+                        LokMouseEventData aMouseEventData(nType, aControlRelativePosition, nCount,
+                                                          MouseEventModifiers::SIMPLECLICK,
+                                                          nButtons, nModifier);
+
+                        SfxLokHelper::postMouseEventAsync(pWindow, aMouseEventData);
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    static void drawUnoControl(SdrView* pDrawView, SdrUnoObj* pUnoObect,
+                               vcl::Window const& rMainWindow, VirtualDevice& rDevice,
+                               tools::Rectangle const& rTileRectHMM, double scaleX, double scaleY)
+    {
+        css::uno::Reference<css::awt::XControl> xControl
+            = pUnoObect->GetUnoControl(*pDrawView, rMainWindow);
+        if (!xControl.is())
+            return;
+
+        css::uno::Reference<css::awt::XWindow> xControlWindow(xControl, css::uno::UNO_QUERY);
+        if (!xControlWindow.is())
+            return;
+
+        css::uno::Reference<css::awt::XGraphics> xGraphics(rDevice.CreateUnoGraphics());
+        if (!xGraphics.is())
+            return;
+
+        css::uno::Reference<css::awt::XView> xControlView(xControl, css::uno::UNO_QUERY);
+        if (!xControlView.is())
+            return;
+
+        tools::Rectangle aObjectRectHMM = pUnoObect->GetLogicRect();
+        Point aOffsetFromTile = Point(aObjectRectHMM.Left() - rTileRectHMM.Left(),
+                                      aObjectRectHMM.Top() - rTileRectHMM.Top());
+        tools::Rectangle aRectangleHMM(aOffsetFromTile, aObjectRectHMM.GetSize());
+        tools::Rectangle aRectanglePx = convertMm100ToPixel(aRectangleHMM);
+
+        xControlWindow->setPosSize(0, 0, aRectanglePx.GetWidth(), aRectanglePx.GetHeight(),
+                                   css::awt::PosSize::POSSIZE);
+
+        xControlView->setGraphics(xGraphics);
+
+        xControlView->draw(aRectanglePx.Left() * scaleX, aRectanglePx.Top() * scaleY);
+    }
+
+    static void paintControlTile(SdrPage* pPage, SdrView* pDrawView, vcl::Window const& rMainWindow,
+                                 VirtualDevice& rDevice, Size aOutputSize,
+                                 tools::Rectangle const& rTileRect)
+    {
+        tools::Rectangle aTileRectHMM = convertTwipToMm100(rTileRect);
+
+        // Resizes the virtual device so to contain the entries context
+        rDevice.SetOutputSizePixel(aOutputSize);
+
+        rDevice.Push(PushFlags::MAPMODE);
+        MapMode aDeviceMapMode(rDevice.GetMapMode());
+
+        Fraction scaleX
+            = Fraction(aOutputSize.Width(), 96) * Fraction(1440) / Fraction(rTileRect.GetWidth());
+        Fraction scaleY
+            = Fraction(aOutputSize.Height(), 96) * Fraction(1440) / Fraction(rTileRect.GetHeight());
+
+        aDeviceMapMode.SetScaleX(scaleX);
+        aDeviceMapMode.SetScaleY(scaleY);
+        rDevice.SetMapMode(aDeviceMapMode);
+
+        SdrObjListIter aIterator(pPage, SdrIterMode::Flat);
+
+        while (aIterator.IsMore())
+        {
+            SdrObject* pObject = aIterator.Next();
+            SdrUnoObj* pUnoObect = dynamic_cast<SdrUnoObj*>(pObject);
+            if (pUnoObect)
+            {
+                tools::Rectangle aObjectRectHMM = pUnoObect->GetLogicRect();
+
+                // Check if we intersect with the tile rectangle and we
+                // need to draw the control.
+                if (aObjectRectHMM.IsOver(aTileRectHMM))
+                {
+                    drawUnoControl(pDrawView, pUnoObect, rMainWindow, rDevice, aTileRectHMM,
+                                   double(scaleX), double(scaleY));
+                }
+            }
+        }
+
+        rDevice.Pop();
+    }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/ctrl.hxx b/include/vcl/ctrl.hxx
index d3c5962741e0..cc5e82dd3f88 100644
--- a/include/vcl/ctrl.hxx
+++ b/include/vcl/ctrl.hxx
@@ -181,6 +181,10 @@ public:
 
     vcl::Font       GetUnzoomedControlPointFont() const;
     void            SetShowAccelerator (bool val);
+
+    void LogicMouseButtonDown(const MouseEvent& rMouseEvent) override;
+    void LogicMouseButtonUp(const MouseEvent& rMouseEvent) override;
+    void LogicMouseMove(const MouseEvent& rMouseEvent) override;
 };
 
 #endif // INCLUDED_VCL_CTRL_HXX
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index d67ad5b74632..8478211e2bca 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -78,6 +78,7 @@
 #endif
 #include <sfx2/lokhelper.hxx>
 #include <sfx2/lokcharthelper.hxx>
+#include <sfx2/LokControlHandler.hxx>
 
 #include <cellsuno.hxx>
 #include <columnspanset.hxx>
@@ -561,6 +562,14 @@ void ScModelObj::paintTile( VirtualDevice& rDevice,
 
     LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
                                          nTilePosX, nTilePosY, nTileWidth, nTileHeight);
+
+    // Draw Form controls
+    ScDrawLayer* pDrawLayer = pDocShell->GetDocument().GetDrawLayer();
+    SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(pViewData->GetTabNo()));
+    SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView();
+    tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
+    Size aOutputSize(nOutputWidth, nOutputHeight);
+    LokControlHandler::paintControlTile(pPage, pDrawView, *pGridWindow, rDevice, aOutputSize, aTileRect);
 }
 
 void ScModelObj::setPart( int nPart, bool /*bAllowChangeFocus*/ )
@@ -713,22 +722,33 @@ void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButt
     if (aChartHelper.postMouseEvent(nType, nX, nY,
                                     nCount, nButtons, nModifier,
                                     pViewData->GetPPTX(), pViewData->GetPPTY()))
+    {
         return;
+    }
+
+    Point aPointTwip(nX, nY);
 
     // check if the user hit a chart which is being edited by someone else
     // and, if so, skip current mouse event
     if (nType != LOK_MOUSEEVENT_MOUSEMOVE)
     {
-        if (LokChartHelper::HitAny(Point(nX, nY)))
+        if (LokChartHelper::HitAny(aPointTwip))
             return;
     }
 
-    // Calc operates in pixels...
-    const Point aPos(nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
+    // Check if a control is hit
+    Point aPointHMM = LokControlHandler::convertTwipToMm100(aPointTwip);
+    ScDrawLayer* pDrawLayer = pDocShell->GetDocument().GetDrawLayer();
+    SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(pViewData->GetTabNo()));
+    SdrView* pDrawView = pViewData->GetViewShell()->GetScDrawView();
+    if (LokControlHandler::postMouseEvent(pPage, pDrawView, *pGridWindow, nType, aPointHMM, nCount, nButtons, nModifier))
+        return;
 
-    LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK,
+    // Calc operates in pixels...
+    const Point aPosition(nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
+    LokMouseEventData aMouseEventData(nType, aPosition, nCount, MouseEventModifiers::SIMPLECLICK,
                                       nButtons, nModifier);
-    aMouseEventData.maLogicPosition = Point(convertTwipToMm100(nX), convertTwipToMm100(nY));
+    aMouseEventData.maLogicPosition = aPointHMM;
     SfxLokHelper::postMouseEventAsync(pGridWindow, aMouseEventData);
 }
 
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index 522446561a79..38db41b03126 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -492,4 +492,19 @@ Control::GetUnzoomedControlPointFont() const
     return aFont;
 }
 
+void Control::LogicMouseButtonDown(const MouseEvent& rEvent)
+{
+    MouseButtonDown(rEvent);
+}
+
+void Control::LogicMouseButtonUp(const MouseEvent& rEvent)
+{
+    MouseButtonUp(rEvent);
+}
+
+void Control::LogicMouseMove(const MouseEvent& rEvent)
+{
+    MouseMove(rEvent);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list