summaryrefslogtreecommitdiffstats
path: root/include/sfx2/LokControlHandler.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'include/sfx2/LokControlHandler.hxx')
-rw-r--r--include/sfx2/LokControlHandler.hxx195
1 files changed, 195 insertions, 0 deletions
diff --git a/include/sfx2/LokControlHandler.hxx b/include/sfx2/LokControlHandler.hxx
new file mode 100644
index 0000000000..d8ff381124
--- /dev/null
+++ b/include/sfx2/LokControlHandler.hxx
@@ -0,0 +1,195 @@
+/* -*- 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/lokhelper.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/svditer.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/DocWindow.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>
+#include <tools/UnitConversion.hxx>
+
+#include <optional>
+
+class LokControlHandler
+{
+public:
+ static bool postMouseEvent(const SdrPage* pPage, const SdrView* pDrawView,
+ vcl::DocWindow& rMainWindow, int nType, Point aPointHmm, int nCount,
+ int nButtons, int nModifier)
+ {
+ static std::optional<PointerStyle> eDocPointerStyle;
+
+ o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit());
+ SdrObjListIter aIterator(pPage, SdrIterMode::Flat);
+ while (aIterator.IsMore())
+ {
+ SdrObject* pObject = aIterator.Next();
+ SdrUnoObj* pUnoObect = dynamic_cast<SdrUnoObj*>(pObject);
+ if (pUnoObect)
+ {
+ tools::Rectangle aControlRect = pUnoObect->GetLogicRect();
+ tools::Rectangle aControlRectHMM
+ = o3tl::convert(aControlRect, eControlUnitLength, o3tl::Length::mm100);
+
+ if (aControlRectHMM.Contains(aPointHmm))
+ {
+ css::uno::Reference<css::awt::XControl> xControl
+ = pUnoObect->GetUnoControl(*pDrawView, *rMainWindow.GetOutDev());
+ 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)
+ {
+ tools::Rectangle aControlRectPx
+ = o3tl::convert(aControlRectHMM, o3tl::Length::mm100, o3tl::Length::px);
+ // used by Control::LogicInvalidate
+ pWindow->SetPosPixel(aControlRectPx.TopLeft());
+
+ // when entering into control area save current pointer style
+ // and set pointer style to arrow
+ if (!eDocPointerStyle)
+ {
+ eDocPointerStyle = rMainWindow.GetPointer();
+ rMainWindow.SetPointer(pWindow->GetPointer());
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+
+ // when exiting from control area restore document pointer style
+ if (eDocPointerStyle)
+ {
+ rMainWindow.SetPointer(*eDocPointerStyle);
+ eDocPointerStyle.reset();
+ }
+ return false;
+ }
+
+ static void drawUnoControl(const SdrView* pDrawView, const 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.GetOutDev());
+ 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;
+
+ o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit());
+ tools::Rectangle aControlRect = pUnoObect->GetLogicRect();
+ tools::Rectangle aObjectRectHMM
+ = o3tl::convert(aControlRect, eControlUnitLength, o3tl::Length::mm100);
+ tools::Rectangle aControltRectPx
+ = o3tl::convert(aObjectRectHMM, o3tl::Length::mm100, o3tl::Length::px);
+
+ 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(aControltRectPx.Left(), aControltRectPx.Top(),
+ aRectanglePx.GetWidth(), aRectanglePx.GetHeight(),
+ css::awt::PosSize::POSSIZE);
+
+ xControlView->setGraphics(xGraphics);
+ // required for getting text label rendered with the correct scale
+ xControlView->setZoom(1, 1);
+
+ xControlView->draw(aRectanglePx.Left() * scaleX, aRectanglePx.Top() * scaleY);
+ }
+
+ static void paintControlTile(const SdrPage* pPage, const 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(vcl::PushFlags::MAPMODE);
+ MapMode aDeviceMapMode(rDevice.GetMapMode());
+
+ const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip);
+ Fraction scaleX = Fraction(aOutputSize.Width(), rTileRect.GetWidth()) * scale;
+ Fraction scaleY = Fraction(aOutputSize.Height(), rTileRect.GetHeight()) * scale;
+ aDeviceMapMode.SetScaleX(scaleX);
+ aDeviceMapMode.SetScaleY(scaleY);
+ aDeviceMapMode.SetMapUnit(MapUnit::MapPixel);
+ rDevice.SetMapMode(aDeviceMapMode);
+
+ o3tl::Length eControlUnitLength = MapToO3tlLength(rMainWindow.GetMapMode().GetMapUnit());
+ SdrObjListIter aIterator(pPage, SdrIterMode::Flat);
+
+ while (aIterator.IsMore())
+ {
+ SdrObject* pObject = aIterator.Next();
+ SdrUnoObj* pUnoObect = dynamic_cast<SdrUnoObj*>(pObject);
+ if (pUnoObect)
+ {
+ tools::Rectangle aControlRect = pUnoObect->GetLogicRect();
+ tools::Rectangle aObjectRectHMM
+ = o3tl::convert(aControlRect, eControlUnitLength, o3tl::Length::mm100);
+
+ // Check if we intersect with the tile rectangle and we
+ // need to draw the control.
+ if (aObjectRectHMM.Overlaps(aTileRectHMM))
+ {
+ drawUnoControl(pDrawView, pUnoObect, rMainWindow, rDevice, aTileRectHMM,
+ double(scaleX), double(scaleY));
+ }
+ }
+ }
+
+ rDevice.Pop();
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */