summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2021-04-26 10:43:11 +0900
committerTomaž Vajngerl <quikee@gmail.com>2021-04-26 10:14:59 +0200
commite0094d6fe58eaa9a79b546149cf67db521cd1230 (patch)
tree537d3033d0e9608f48876084684f5d192c2aa316
parent9c62b71cf59a043031a2e3bee13de43bf49e18bb (diff)
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/+/114635 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--include/sfx2/LokControlHandler.hxx151
-rw-r--r--include/vcl/ctrl.hxx4
-rw-r--r--sc/source/ui/unoobj/docuno.cxx30
-rw-r--r--vcl/source/control/ctrl.cxx15
4 files changed, 195 insertions, 5 deletions
diff --git a/include/sfx2/LokControlHandler.hxx b/include/sfx2/LokControlHandler.hxx
new file mode 100644
index 000000000000..5617dae4b2f8
--- /dev/null
+++ b/include/sfx2/LokControlHandler.hxx
@@ -0,0 +1,151 @@
+/* -*- 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 <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 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 = o3tl::convert(
+ aControlRelativePositionHMM, o3tl::Length::mm100, o3tl::Length::px);
+
+ 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(aObjectRectHMM.Left() - rTileRectHMM.Left(),
+ aObjectRectHMM.Top() - rTileRectHMM.Top());
+ tools::Rectangle aRectangleHMM(aOffsetFromTile, aObjectRectHMM.GetSize());
+ tools::Rectangle aRectanglePx
+ = o3tl::convert(aRectangleHMM, o3tl::Length::mm100, o3tl::Length::px);
+
+ 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
+ = o3tl::convert(rTileRect, o3tl::Length::twip, o3tl::Length::mm100);
+
+ // Resizes the virtual device so to contain the entries context
+ rDevice.SetOutputSizePixel(aOutputSize);
+
+ rDevice.Push(PushFlags::MAPMODE);
+ MapMode aDeviceMapMode(rDevice.GetMapMode());
+
+ const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::mm100);
+ Fraction scaleX = Fraction(aOutputSize.Width(), aTileRectHMM.GetWidth()) * scale;
+ Fraction scaleY = Fraction(aOutputSize.Height(), aTileRectHMM.GetHeight()) * scale;
+ 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 db285cba9054..87a15572d6c9 100644
--- a/include/vcl/ctrl.hxx
+++ b/include/vcl/ctrl.hxx
@@ -179,6 +179,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 5cd51ad148b1..371cb395e139 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -79,6 +79,7 @@
#endif
#include <sfx2/lokhelper.hxx>
#include <sfx2/lokcharthelper.hxx>
+#include <sfx2/LokControlHandler.hxx>
#include <cellsuno.hxx>
#include <columnspanset.hxx>
@@ -563,6 +564,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*/ )
@@ -715,22 +724,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 = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100);
+ 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 779b90927317..1e34777cf93b 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: */