summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Cecchetti <marco.cecchetti@collabora.com>2017-06-27 23:35:08 +0200
committerMarco Cecchetti <mrcekets@gmail.com>2017-08-03 10:58:59 +0200
commiteba883c8a2ce045fc7bd3848d796ca10b7f4ba51 (patch)
treea6a5684a36725e67a24eab86fa984c38252cb2d9
parent166f13ef65b4a0eb9927eff2ffe5bac319785ee7 (diff)
lok - add support for in place chart editing
This commit add a minimal support for editing chart embedded in a spreadsheet or a text document or a presentation. Graphic objects can be moved and resized, text objects can be edited. Change-Id: I8e637dabf328a94bd6bb0e309a245302cff421d8 Reviewed-on: https://gerrit.libreoffice.org/39342 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Marco Cecchetti <mrcekets@gmail.com>
-rw-r--r--chart2/source/controller/inc/ChartController.hxx2
-rw-r--r--chart2/source/controller/inc/ChartWindow.hxx9
-rw-r--r--chart2/source/controller/main/ChartController.cxx15
-rw-r--r--chart2/source/controller/main/ChartController_Tools.cxx35
-rw-r--r--chart2/source/controller/main/ChartController_Window.cxx5
-rw-r--r--chart2/source/controller/main/ChartWindow.cxx110
-rw-r--r--editeng/source/editeng/impedit.cxx26
-rw-r--r--include/editeng/outliner.hxx1
-rw-r--r--include/sfx2/lokcharthelper.hxx60
-rw-r--r--include/sfx2/viewsh.hxx3
-rw-r--r--include/vcl/window.hxx4
-rw-r--r--sc/source/ui/unoobj/docuno.cxx55
-rw-r--r--sd/source/ui/unoidl/unomodel.cxx60
-rw-r--r--sfx2/Library_sfx.mk1
-rw-r--r--sfx2/source/view/ipclient.cxx56
-rw-r--r--sfx2/source/view/lokcharthelper.cxx373
-rw-r--r--sfx2/source/view/viewsh.cxx15
-rw-r--r--svx/source/svdraw/svdmrkv.cxx37
-rw-r--r--svx/source/svdraw/svdpntv.cxx9
-rw-r--r--sw/inc/unotxdoc.hxx2
-rw-r--r--sw/source/core/view/viewsh.cxx29
-rw-r--r--sw/source/uibase/uno/unotxdoc.cxx89
-rw-r--r--vcl/source/window/stacking.cxx5
-rw-r--r--vcl/source/window/window2.cxx5
24 files changed, 977 insertions, 29 deletions
diff --git a/chart2/source/controller/inc/ChartController.hxx b/chart2/source/controller/inc/ChartController.hxx
index 29f74ad358e2..145939f1b947 100644
--- a/chart2/source/controller/inc/ChartController.hxx
+++ b/chart2/source/controller/inc/ChartController.hxx
@@ -488,6 +488,8 @@ private:
void executeDispatch_ToggleGridHorizontal();
void executeDispatch_ToggleGridVertical();
+ void executeDispatch_LOKSetTextSelection(int nType, int nX, int nY);
+
void sendPopupRequest(OUString const & rCID, tools::Rectangle aRectangle);
void impl_ShapeControllerDispatch( const css::util::URL& rURL,
diff --git a/chart2/source/controller/inc/ChartWindow.hxx b/chart2/source/controller/inc/ChartWindow.hxx
index 95a029698e9c..db9044970247 100644
--- a/chart2/source/controller/inc/ChartWindow.hxx
+++ b/chart2/source/controller/inc/ChartWindow.hxx
@@ -58,6 +58,7 @@ public:
virtual void Invalidate( InvalidateFlags nFlags = InvalidateFlags::NONE ) override;
virtual void Invalidate( const tools::Rectangle& rRect, InvalidateFlags nFlags = InvalidateFlags::NONE ) override;
virtual void Invalidate( const vcl::Region& rRegion, InvalidateFlags nFlags = InvalidateFlags::NONE ) override;
+ virtual void LogicInvalidate( const tools::Rectangle* pRectangle ) override;
virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
@@ -65,9 +66,17 @@ public:
ChartController* GetController();
+ virtual bool IsChart() const override { return true; }
+ vcl::Window* GetParentEditWin();
+
+private:
+ // returns the chart bounding box in twips
+ tools::Rectangle GetBoundingBox();
+
private:
ChartController* m_pWindowController;
bool m_bInPaint;
+ VclPtr<vcl::Window> m_pViewShellWindow;
VclPtr<vcl::Window> m_pOpenGLWindow;
void adjustHighContrastMode();
diff --git a/chart2/source/controller/main/ChartController.cxx b/chart2/source/controller/main/ChartController.cxx
index 2e822ceea120..e660dfb24be7 100644
--- a/chart2/source/controller/main/ChartController.cxx
+++ b/chart2/source/controller/main/ChartController.cxx
@@ -1091,7 +1091,20 @@ void SAL_CALL ChartController::dispatch(
{
OUString aCommand = rURL.Path;
- if(aCommand == "Paste")
+ if(aCommand == "LOKSetTextSelection")
+ {
+ if (rArgs.getLength() == 3)
+ {
+ sal_Int32 nType = -1;
+ rArgs[0].Value >>= nType;
+ sal_Int32 nX = 0;
+ rArgs[1].Value >>= nX;
+ sal_Int32 nY = 0;
+ rArgs[2].Value >>= nY;
+ executeDispatch_LOKSetTextSelection(nType, nX, nY);
+ }
+ }
+ else if(aCommand == "Paste")
this->executeDispatch_Paste();
else if(aCommand == "Copy" )
this->executeDispatch_Copy();
diff --git a/chart2/source/controller/main/ChartController_Tools.cxx b/chart2/source/controller/main/ChartController_Tools.cxx
index 36c6a569985e..61144839e995 100644
--- a/chart2/source/controller/main/ChartController_Tools.cxx
+++ b/chart2/source/controller/main/ChartController_Tools.cxx
@@ -52,6 +52,8 @@
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <editeng/editview.hxx>
+#include <editeng/outliner.hxx>
#include <svx/ActionDescriptionProvider.hxx>
#include <svtools/transfer.hxx>
#include <sot/storage.hxx>
@@ -70,6 +72,8 @@
#include <svx/unoapi.hxx>
#include <svx/unopage.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
#include <memory>
using namespace ::com::sun::star;
@@ -923,6 +927,37 @@ void ChartController::executeDispatch_ToggleGridVertical()
}
}
+void ChartController::executeDispatch_LOKSetTextSelection(int nType, int nX, int nY)
+{
+ if (m_pDrawViewWrapper)
+ {
+ if (m_pDrawViewWrapper->IsTextEdit())
+ {
+ OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
+ if (pOutlinerView)
+ {
+ EditView& rEditView = pOutlinerView->GetEditView();
+ Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
+ switch (nType)
+ {
+ case LOK_SETTEXTSELECTION_START:
+ rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
+ break;
+ case LOK_SETTEXTSELECTION_END:
+ rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
+ break;
+ case LOK_SETTEXTSELECTION_RESET:
+ rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+ }
+ }
+}
+
void ChartController::impl_ShapeControllerDispatch( const util::URL& rURL, const Sequence< beans::PropertyValue >& rArgs )
{
Reference< frame::XDispatch > xDispatch( m_aDispatchContainer.getShapeController() );
diff --git a/chart2/source/controller/main/ChartController_Window.cxx b/chart2/source/controller/main/ChartController_Window.cxx
index c05c56af059d..f5d31525cc24 100644
--- a/chart2/source/controller/main/ChartController_Window.cxx
+++ b/chart2/source/controller/main/ChartController_Window.cxx
@@ -888,7 +888,10 @@ void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt )
else
m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured();
}
- else if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
+ // In tiled rendering drag mode could be not yet over on the call
+ // that should handle the double-click, so better to perform this check
+ // always.
+ if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
{
Point aMousePixel = rMEvt.GetPosPixel();
execute_DoubleClick( &aMousePixel );
diff --git a/chart2/source/controller/main/ChartWindow.cxx b/chart2/source/controller/main/ChartWindow.cxx
index b03f10164b17..717704fcda27 100644
--- a/chart2/source/controller/main/ChartWindow.cxx
+++ b/chart2/source/controller/main/ChartWindow.cxx
@@ -28,6 +28,13 @@
#include <config_features.h>
#include <com/sun/star/chart2/X3DChartWindowProvider.hpp>
+#include <sfx2/ipclient.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <comphelper/lok.hxx>
+
+#define TWIPS_PER_PIXEL 15
+
using namespace ::com::sun::star;
namespace
@@ -50,6 +57,7 @@ ChartWindow::ChartWindow( ChartController* pController, vcl::Window* pParent, Wi
: Window(pParent, nStyle)
, m_pWindowController( pController )
, m_bInPaint(false)
+ , m_pViewShellWindow( nullptr )
#if HAVE_FEATURE_OPENGL
, m_pOpenGLWindow(VclPtr<OpenGLWindow>::Create(this, false))
#else
@@ -94,6 +102,7 @@ void ChartWindow::dispose()
xUpdatable->update();
}
m_pOpenGLWindow.disposeAndClear();
+ m_pViewShellWindow.clear();
vcl::Window::dispose();
}
@@ -108,6 +117,10 @@ void ChartWindow::PrePaint(vcl::RenderContext& )
void ChartWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
{
+ if (comphelper::LibreOfficeKit::isActive()
+ && rRenderContext.GetOutDevType() != OutDevType::OUTDEV_VIRDEV)
+ return;
+
m_bInPaint = true;
if (m_pOpenGLWindow && m_pOpenGLWindow->IsVisible())
{
@@ -301,6 +314,56 @@ void ChartWindow::Invalidate( const vcl::Region& rRegion, InvalidateFlags nFlags
}
}
+void ChartWindow::LogicInvalidate(const tools::Rectangle* pRectangle)
+{
+ OString sRectangle;
+ if (!pRectangle)
+ {
+ // we have to invalidate the whole chart area not the whole document
+ sRectangle = GetBoundingBox().toString();
+ }
+ else
+ {
+ tools::Rectangle aRectangle(*pRectangle);
+ // When dragging shapes the map mode is disabled.
+ if (IsMapModeEnabled())
+ {
+ if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
+ aRectangle = OutputDevice::LogicToLogic(aRectangle, MapUnit::Map100thMM, MapUnit::MapTwip);
+ }
+ else
+ {
+ aRectangle = PixelToLogic(aRectangle, MapMode(MapUnit::MapTwip));
+ }
+
+ vcl::Window* pEditWin = GetParentEditWin();
+ if (pEditWin)
+ {
+ MapMode aCWMapMode = GetMapMode();
+ double fXScale = aCWMapMode.GetScaleX();
+ double fYScale = aCWMapMode.GetScaleY();
+
+ if (!IsMapModeEnabled())
+ {
+ aRectangle.Left() /= fXScale;
+ aRectangle.Right() /= fXScale;
+ aRectangle.Top() /= fYScale;
+ aRectangle.Bottom() /= fYScale;
+ }
+
+ Point aOffset = this->GetOffsetPixelFrom(*pEditWin);
+ aOffset.X() *= (TWIPS_PER_PIXEL / fXScale);
+ aOffset.Y() *= (TWIPS_PER_PIXEL / fYScale);
+
+ aRectangle = tools::Rectangle(aRectangle.TopLeft() + aOffset, aRectangle.GetSize());
+ }
+
+ sRectangle = aRectangle.toString();
+ }
+ SfxViewShell* pCurrentShell = SfxViewShell::Current();
+ SfxLokHelper::notifyInvalidation(pCurrentShell, sRectangle);
+}
+
FactoryFunction ChartWindow::GetUITestFactory() const
{
return ChartWindowUIObject::create;
@@ -311,6 +374,53 @@ ChartController* ChartWindow::GetController()
return m_pWindowController;
}
+vcl::Window* ChartWindow::GetParentEditWin()
+{
+ if (m_pViewShellWindow)
+ return m_pViewShellWindow.get();
+
+ // So, you are thinking, why do not invoke pCurrentShell->GetWindow() ?
+ // Because in Impress the parent edit win is not view shell window.
+ SfxViewShell* pCurrentShell = SfxViewShell::Current();
+ if( pCurrentShell )
+ {
+ SfxInPlaceClient* pIPClient = pCurrentShell->GetIPClient();
+ if (pIPClient)
+ {
+ vcl::Window* pRootWin = pIPClient->GetEditWin();
+ if(pRootWin && pRootWin->IsAncestorOf(*this))
+ {
+ m_pViewShellWindow = pRootWin;
+ return m_pViewShellWindow.get();
+ }
+ }
+ }
+ return nullptr;
+}
+
+tools::Rectangle ChartWindow::GetBoundingBox()
+{
+ tools::Rectangle aBBox;
+
+ vcl::Window* pRootWin = GetParentEditWin();
+ if (pRootWin)
+ {
+ // In all cases, the following code fragment
+ // returns the chart bounding box in twips.
+ MapMode aCWMapMode = GetMapMode();
+ double fXScale = aCWMapMode.GetScaleX();
+ double fYScale = aCWMapMode.GetScaleY();
+ Point aOffset = GetOffsetPixelFrom(*pRootWin);
+ aOffset.X() *= (TWIPS_PER_PIXEL / fXScale);
+ aOffset.Y() *= (TWIPS_PER_PIXEL / fYScale);
+ Size aSize = GetSizePixel();
+ aSize.Width() *= (TWIPS_PER_PIXEL / fXScale);
+ aSize.Height() *= (TWIPS_PER_PIXEL / fYScale);
+ aBBox = tools::Rectangle(aOffset, aSize);
+ }
+ return aBBox;
+}
+
} //namespace chart
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index 4f35f97227ce..22efd056dbee 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -376,6 +376,17 @@ void ImpEditView::DrawSelection( EditSelection aTmpSel, vcl::Region* pRegion, Ou
{
std::vector<tools::Rectangle> aRectangles;
pRegion->GetRegionRectangles(aRectangles);
+ if (pOutWin->IsChart())
+ {
+ const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj();
+ if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin))
+ {
+ Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow);
+ Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx);
+ for (tools::Rectangle& rRect : aRectangles)
+ rRect.Move(aLogicOffset.getX(), aLogicOffset.getY());
+ }
+ }
if (!aRectangles.empty())
{
@@ -1017,8 +1028,19 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
if (comphelper::LibreOfficeKit::isActive() && mpViewShell)
{
- const Point& rPos = GetCursor()->GetPos();
- tools::Rectangle aRect(rPos.getX(), rPos.getY(), rPos.getX() + GetCursor()->GetWidth(), rPos.getY() + GetCursor()->GetHeight());
+ Point aPos = GetCursor()->GetPos();
+ if (pOutWin->IsChart())
+ {
+ const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj();
+ if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin))
+ {
+ Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow);
+ Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx);
+ aPos.Move(aLogicOffset.getX(), aLogicOffset.getY());
+ }
+ }
+
+ tools::Rectangle aRect(aPos.getX(), aPos.getY(), aPos.getX() + GetCursor()->GetWidth(), aPos.getY() + GetCursor()->GetHeight());
// LOK output is always in twips, convert from mm100 if necessary.
if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index 3e7e889064d1..1cc38d50263e 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -384,6 +384,7 @@ public:
virtual void NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) = 0;
/// Wrapper around SfxLokHelper::notifyOtherView().
virtual void NotifyOtherView(OutlinerViewShell* pOtherShell, int nType, const OString& rKey, const OString& rPayload) = 0;
+ virtual vcl::Window* GetEditWindowForActiveOLEObj() const = 0;
protected:
~OutlinerViewShell() throw () {}
diff --git a/include/sfx2/lokcharthelper.hxx b/include/sfx2/lokcharthelper.hxx
new file mode 100644
index 000000000000..deb2c43f0556
--- /dev/null
+++ b/include/sfx2/lokcharthelper.hxx
@@ -0,0 +1,60 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_SFX2_LOKCHARTHELPER_HXX
+#define INCLUDED_SFX2_LOKCHARTHELPER_HXX
+
+#include <sfx2/dllapi.h>
+#include <tools/gen.hxx>
+#include <vcl/window.hxx>
+
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+
+class SfxViewShell;
+class VirtualDevice;
+
+class SFX2_DLLPUBLIC LokChartHelper
+{
+private:
+ SfxViewShell* mpViewShell;
+ css::uno::Reference<css::frame::XController> mxController;
+ css::uno::Reference<css::frame::XDispatch> mxDispatcher;
+ VclPtr<vcl::Window> mpWindow;
+
+public:
+ LokChartHelper(SfxViewShell* pViewShell)
+ : mpViewShell(pViewShell)
+ , mpWindow(nullptr)
+ {}
+
+ css::uno::Reference<css::frame::XController>& GetXController();
+ css::uno::Reference<css::frame::XDispatch>& GetXDispatcher();
+ vcl::Window* GetWindow();
+ tools::Rectangle GetChartBoundingBox();
+ void Invalidate();
+
+ bool Hit(const Point& aPos);
+ static bool HitAny(const Point& aPos);
+ void PaintTile(VirtualDevice& rRenderContext, const tools::Rectangle& rTileRect);
+ static void PaintAllChartsOnTile(VirtualDevice& rDevice,
+ int nOutputWidth, int nOutputHeight,
+ int nTilePosX, int nTilePosY,
+ long nTileWidth, long nTileHeight);
+ bool postMouseEvent(int nType, int nX, int nY,
+ int nCount, int nButtons, int nModifier,
+ double fScaleX = 1.0, double fScaleY = 1.0);
+ bool setTextSelection(int nType, int nX, int nY);
+ bool setGraphicSelection(int nType, int nX, int nY,
+ double fScaleX = 1.0, double fScaleY = 1.0);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index 89bb429aa41b..f186f8d4135a 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -336,6 +336,9 @@ public:
virtual void NotifyCursor(SfxViewShell* /*pViewShell*/) const;
/// Where a new view can perform some update/initialization soon after the callback has been registered.
virtual void afterCallbackRegistered();
+ /// See OutlinerViewShell::GetEditWindowForActiveOLEObj().
+ virtual vcl::Window* GetEditWindowForActiveOLEObj() const override;
+
};
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 7c2aa534fa69..3b8a42ac5d0b 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -931,6 +931,7 @@ public:
vcl::Window* GetParent() const;
// return the dialog we are contained in or NULL if un-contained
Dialog* GetParentDialog() const;
+ bool IsAncestorOf( const vcl::Window& rWindow ) const;
void Show( bool bVisible = true, ShowFlags nFlags = ShowFlags::NONE );
void Hide() { Show( false ); }
@@ -1030,6 +1031,7 @@ public:
virtual void SetOutputSizePixel( const Size& rNewSize );
bool IsDefaultPos() const;
bool IsDefaultSize() const;
+ Point GetOffsetPixelFrom(const vcl::Window& rWindow) const;
// those conversion routines might deliver different results during UI mirroring
Point OutputToScreenPixel( const Point& rPos ) const;
@@ -1540,6 +1542,8 @@ public:
virtual Selection GetSurroundingTextSelection() const;
virtual FactoryFunction GetUITestFactory() const;
+
+ virtual bool IsChart() const { return false; }
};
}
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index b6eeca6fc39a..8b70fa9f44e9 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -48,6 +48,7 @@
#include <unotools/charclass.hxx>
#include <tools/multisel.hxx>
#include <toolkit/awt/vclxdevice.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
#include <unotools/saveopt.hxx>
#include <float.h>
@@ -75,6 +76,7 @@
#include <opencl/platforminfo.hxx>
#endif
#include <sfx2/lokhelper.hxx>
+#include <sfx2/lokcharthelper.hxx>
#include "cellsuno.hxx"
#include <columnspanset.hxx>
@@ -503,6 +505,9 @@ void ScModelObj::paintTile( VirtualDevice& rDevice,
pGridWindow->PaintTile( rDevice, nOutputWidth, nOutputHeight,
nTilePosX, nTilePosY, nTileWidth, nTileHeight );
+
+ LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
+ nTilePosX, nTilePosY, nTileWidth, nTileHeight);
}
void ScModelObj::setPart( int nPart )
@@ -570,20 +575,28 @@ void ScModelObj::postKeyEvent(int nType, int nCharCode, int nKeyCode)
// There seems to be no clear way of getting the grid window for this
// particular document, hence we need to hope we get the right window.
ScViewData* pViewData = ScDocShell::GetViewData();
- ScGridWindow* pGridWindow = pViewData->GetActiveWin();
+ vcl::Window* pWindow = pViewData->GetActiveWin();
- if (!pGridWindow)
+ if (!pWindow)
return;
KeyEvent aEvent(nCharCode, nKeyCode, 0);
+ ScTabViewShell * pTabViewShell = pViewData->GetViewShell();
+ LokChartHelper aChartHelper(pTabViewShell);
+ vcl::Window* pChartWindow = aChartHelper.GetWindow();
+ if (pChartWindow)
+ {
+ pWindow = pChartWindow;
+ }
+
switch (nType)
{
case LOK_KEYEVENT_KEYINPUT:
- pGridWindow->KeyInput(aEvent);
+ pWindow->KeyInput(aEvent);
break;
case LOK_KEYEVENT_KEYUP:
- pGridWindow->KeyUp(aEvent);
+ pWindow->KeyUp(aEvent);
break;
default:
assert(false);
@@ -607,6 +620,23 @@ void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButt
pViewData->SetZoom(Fraction(mnTilePixelWidth * TWIPS_PER_PIXEL, mnTileTwipWidth),
Fraction(mnTilePixelHeight * TWIPS_PER_PIXEL, mnTileTwipHeight), true);
+ // check if user hit a chart which is being edited by him
+ ScTabViewShell * pTabViewShell = pViewData->GetViewShell();
+ LokChartHelper aChartHelper(pTabViewShell);
+ if (aChartHelper.postMouseEvent(nType, nX, nY,
+ nCount, nButtons, nModifier,
+ pViewData->GetPPTX(), pViewData->GetPPTY()))
+ return;
+
+ // 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)))
+ return;
+ }
+
+
// Calc operates in pixels...
Point aPos(nX * pViewData->GetPPTX(), nY * pViewData->GetPPTY());
MouseEvent aEvent(aPos, nCount,
@@ -645,9 +675,13 @@ void ScModelObj::postMouseEvent(int nType, int nX, int nY, int nCount, int nButt
void ScModelObj::setTextSelection(int nType, int nX, int nY)
{
SolarMutexGuard aGuard;
-
ScViewData* pViewData = ScDocShell::GetViewData();
ScTabViewShell* pViewShell = pViewData->GetViewShell();
+
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.setTextSelection(nType, nX, nY))
+ return;
+
ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewShell);
ScDrawView* pDrawView = pViewData->GetScDrawView();
@@ -822,9 +856,16 @@ void ScModelObj::setGraphicSelection(int nType, int nX, int nY)
// update the aLogicMode in ScViewData to something predictable
pViewData->SetZoom(Fraction(mnTilePixelWidth * TWIPS_PER_PIXEL, mnTileTwipWidth),
Fraction(mnTilePixelHeight * TWIPS_PER_PIXEL, mnTileTwipHeight), true);
+ double fPPTX = pViewData->GetPPTX();
+ double fPPTY = pViewData->GetPPTY();
+
+ ScTabViewShell* pViewShell = pViewData->GetViewShell();
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.setGraphicSelection(nType, nX, nY, fPPTX, fPPTY))
+ return;
- int nPixelX = nX * pViewData->GetPPTX();
- int nPixelY = nY * pViewData->GetPPTY();
+ int nPixelX = nX * fPPTX;
+ int nPixelY = nY * fPPTY;
switch (nType)
{
diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx
index 352994d067da..a7c4d0663734 100644
--- a/sd/source/ui/unoidl/unomodel.cxx
+++ b/sd/source/ui/unoidl/unomodel.cxx
@@ -119,6 +119,10 @@
#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
+#include <sfx2/lokcharthelper.hxx>
+
+#define TWIPS_PER_PIXEL 15
+
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::sd;
@@ -2250,15 +2254,15 @@ void SdXImpressDocument::paintTile( VirtualDevice& rDevice,
// 100th mm rather than TWIP. It makes most sense just to
// convert here and in getDocumentSize, and leave the tiled
// rendering API working in TWIPs.
- nTileWidth = convertTwipToMm100( nTileWidth );
- nTileHeight = convertTwipToMm100( nTileHeight );
- nTilePosX = convertTwipToMm100( nTilePosX );
- nTilePosY = convertTwipToMm100( nTilePosY );
+ long nTileWidthHMM = convertTwipToMm100( nTileWidth );
+ long nTileHeightHMM = convertTwipToMm100( nTileHeight );
+ int nTilePosXHMM = convertTwipToMm100( nTilePosX );
+ int nTilePosYHMM = convertTwipToMm100( nTilePosY );
MapMode aMapMode = rDevice.GetMapMode();
aMapMode.SetMapUnit( MapUnit::Map100thMM );
- aMapMode.SetOrigin( Point( -nTilePosX,
- -nTilePosY) );
+ aMapMode.SetOrigin( Point( -nTilePosXHMM,
+ -nTilePosYHMM) );
aMapMode.SetScaleX( scaleX );
aMapMode.SetScaleY( scaleY );
@@ -2266,11 +2270,14 @@ void SdXImpressDocument::paintTile( VirtualDevice& rDevice,
rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight) );
- Point aPoint(nTilePosX, nTilePosY);
- Size aSize(nTileWidth, nTileHeight);
+ Point aPoint(nTilePosXHMM, nTilePosYHMM);
+ Size aSize(nTileWidthHMM, nTileHeightHMM);
::tools::Rectangle aRect(aPoint, aSize);
pViewSh->GetView()->CompleteRedraw(&rDevice, vcl::Region(aRect));
+
+ LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
+ nTilePosX, nTilePosY, nTileWidth, nTileHeight);
}
void SdXImpressDocument::setPart( int nPart )
@@ -2449,10 +2456,17 @@ void SdXImpressDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode)
if (!pViewShell)
return;
- sd::Window* pWindow = pViewShell->GetActiveWindow();
+ vcl::Window* pWindow = pViewShell->GetActiveWindow();
if (!pWindow)
return;
+ LokChartHelper aChartHelper(pViewShell->GetViewShell());
+ vcl::Window* pChartWindow = aChartHelper.GetWindow();
+ if (pChartWindow)
+ {
+ pWindow = pChartWindow;
+ }
+
KeyEvent aEvent(nCharCode, nKeyCode, 0);
switch (nType)
@@ -2476,6 +2490,24 @@ void SdXImpressDocument::postMouseEvent(int nType, int nX, int nY, int nCount, i
DrawViewShell* pViewShell = GetViewShell();
if (!pViewShell)
return;
+
+ double fScale = 1.0/TWIPS_PER_PIXEL;
+
+ // check if user hit a chart which is being edited by him
+ LokChartHelper aChartHelper(pViewShell->GetViewShell());
+ if (aChartHelper.postMouseEvent(nType, nX, nY,
+ nCount, nButtons, nModifier,
+ fScale, fScale))
+ return;
+
+ // 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)))
+ return;
+ }
+
Window* pWindow = pViewShell->GetActiveWindow();
Point aPos(Point(convertTwipToMm100(nX), convertTwipToMm100(nY)));
@@ -2513,6 +2545,10 @@ void SdXImpressDocument::setTextSelection(int nType, int nX, int nY)
if (!pViewShell)
return;
+ LokChartHelper aChartHelper(pViewShell->GetViewShell());
+ if (aChartHelper.setTextSelection(nType, nX, nY))
+ return;
+
Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
switch (nType)
{
@@ -2550,6 +2586,12 @@ void SdXImpressDocument::setGraphicSelection(int nType, int nX, int nY)
if (!pViewShell)
return;
+ double fScale = 1.0/TWIPS_PER_PIXEL;
+
+ LokChartHelper aChartHelper(pViewShell->GetViewShell());
+ if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale))
+ return;
+
Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
switch (nType)
{
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk
index 201a106d0738..c0913939f31e 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/frame2 \
sfx2/source/view/frmload \
sfx2/source/view/ipclient \
+ sfx2/source/view/lokcharthelper \
sfx2/source/view/lokhelper \
sfx2/source/view/printer \
sfx2/source/view/sfxbasecontroller \
diff --git a/sfx2/source/view/ipclient.cxx b/sfx2/source/view/ipclient.cxx
index a70bb145cd2a..21f5de28970e 100644
--- a/sfx2/source/view/ipclient.cxx
+++ b/sfx2/source/view/ipclient.cxx
@@ -64,6 +64,8 @@
#include <svtools/soerr.hxx>
#include <comphelper/processfactory.hxx>
+#include <sfx2/lokhelper.hxx>
+
#define SFX_CLIENTACTIVATE_TIMEOUT 100
using namespace com::sun::star;
@@ -394,7 +396,27 @@ awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getPlacement()
aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
- aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
+ // In Writer and Impress the map mode is disabled. So when a chart is
+ // activated (for in place editing) we get the chart win size in 100th mm
+ // and any method that should return pixels returns 100th mm and the chart
+ // window map mode has a ~26.485 scale factor.
+ // All that does not fit with current implementation for handling chart
+ // editing in LOK.
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ vcl::Window* pEditWin = m_pClient->GetEditWin();
+ bool bMapModeEnabled = pEditWin->IsMapModeEnabled();
+ if (!bMapModeEnabled)
+ pEditWin->EnableMapMode();
+ aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
+ if (!bMapModeEnabled && pEditWin->IsMapModeEnabled())
+ pEditWin->EnableMapMode(false);
+ }
+ else
+ {
+ aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
+ }
+
return AWTRectangle( aRealObjArea );
}
@@ -409,7 +431,22 @@ awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getClipRectangle()
aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
- aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
+ // See comment for SfxInPlaceClient_Impl::getPlacement.
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ vcl::Window* pEditWin = m_pClient->GetEditWin();
+ bool bMapModeEnabled = pEditWin->IsMapModeEnabled();
+ if (!bMapModeEnabled)
+ pEditWin->EnableMapMode();
+ aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
+ if (!bMapModeEnabled && pEditWin->IsMapModeEnabled())
+ pEditWin->EnableMapMode(false);
+ }
+ else
+ {
+ aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
+ }
+
return AWTRectangle( aRealObjArea );
}
@@ -878,7 +915,13 @@ ErrCode SfxInPlaceClient::DoVerb( long nVerb )
if ( !nError )
{
-
+ // See comment for SfxInPlaceClient_Impl::getPlacement.
+ vcl::Window* pEditWin = GetEditWin();
+ bool bMapModeEnabled = pEditWin->IsMapModeEnabled();
+ if (comphelper::LibreOfficeKit::isActive() && !bMapModeEnabled)
+ {
+ pEditWin->EnableMapMode();
+ }
m_pViewSh->GetViewFrame()->GetFrame().LockResize_Impl(true);
try
{
@@ -929,8 +972,13 @@ ErrCode SfxInPlaceClient::DoVerb( long nVerb )
" exception caught: " << e.Message);
nError = ERRCODE_SO_GENERALERROR;
//TODO/LATER: better error handling
- }
+ }
+ if (comphelper::LibreOfficeKit::isActive() && !bMapModeEnabled
+ && pEditWin->IsMapModeEnabled())
+ {
+ pEditWin->EnableMapMode(false);
+ }
SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
pFrame->GetFrame().LockResize_Impl(false);
pFrame->GetFrame().Resize();
diff --git a/sfx2/source/view/lokcharthelper.cxx b/sfx2/source/view/lokcharthelper.cxx
new file mode 100644
index 000000000000..fffbc3efa58e
--- /dev/null
+++ b/sfx2/source/view/lokcharthelper.cxx
@@ -0,0 +1,373 @@
+/* -*- 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/.
+ */
+
+#include <sfx2/lokcharthelper.hxx>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sfx2/ipclient.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/fract.hxx>
+#include <tools/mapunit.hxx>
+#include <vcl/virdev.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+
+
+#define TWIPS_PER_PIXEL 15
+
+using namespace com::sun::star;
+
+namespace {
+
+inline Point lcl_TwipsToHMM( const Point& rPoint )
+{
+ return Point(convertTwipToMm100(rPoint.getX()), convertTwipToMm100(rPoint.getY()));
+}
+
+inline Size lcl_TwipsToHMM( const Size& rSize )
+{
+ return Size(convertTwipToMm100(rSize.getWidth()), convertTwipToMm100(rSize.getHeight()));
+}
+
+} // end anonymous ns
+
+css::uno::Reference<css::frame::XController>& LokChartHelper::GetXController()
+{
+ if(!mxController.is() )
+ {
+ if (mpViewShell)
+ {
+ SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
+ if (pIPClient)
+ {
+ css::uno::Reference< ::css::embed::XEmbeddedObject > xEmbObj = pIPClient->GetObject();
+ if( xEmbObj.is() )
+ {
+ ::css::uno::Reference< ::css::chart2::XChartDocument > xChart( xEmbObj->getComponent(), uno::UNO_QUERY );
+ if( xChart.is() )
+ {
+ ::css::uno::Reference< ::css::frame::XController > xChartController = xChart->getCurrentController();
+ if( xChartController.is() )
+ {
+ mxController = xChartController;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return mxController;
+}
+
+css::uno::Reference<css::frame::XDispatch>& LokChartHelper::GetXDispatcher()
+{
+ if( !mxDispatcher.is() )
+ {
+ ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
+ if( xChartController.is() )
+ {
+ ::css::uno::Reference< ::css::frame::XDispatch > xDispatcher( xChartController, uno::UNO_QUERY );
+ if( xDispatcher.is() )
+ {
+ mxDispatcher = xDispatcher;
+ }
+ }
+ }
+
+ return mxDispatcher;
+}
+
+vcl::Window* LokChartHelper::GetWindow()
+{
+ if (!mpWindow)
+ {
+ ::css::uno::Reference< ::css::frame::XController >& xChartController = GetXController();
+ if( xChartController.is() )
+ {
+ ::css::uno::Reference< ::css::frame::XFrame > xFrame = xChartController->getFrame();
+ if (xFrame.is())
+ {
+ ::css::uno::Reference< ::css::awt::XWindow > xDockerWin = xFrame->getContainerWindow();
+ vcl::Window* pParent = VCLUnoHelper::GetWindow( xDockerWin ).get();
+ if (pParent)
+ {
+ sal_uInt16 nTotChildren = pParent->GetChildCount();
+ while (nTotChildren--)
+ {
+ vcl::Window* pChildWin = pParent->GetChild(nTotChildren);
+ if (pChildWin && pChildWin->IsChart())
+ {
+ mpWindow = pChildWin;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return mpWindow.get();
+}
+
+tools::Rectangle LokChartHelper::GetChartBoundingBox()
+{
+ tools::Rectangle aBBox;
+ if (mpViewShell)
+ {
+ SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient();
+ if (pIPClient)
+ {
+ vcl::Window* pRootWin = pIPClient->GetEditWin();
+ if (pRootWin)
+ {
+ vcl::Window* pWindow = GetWindow();
+ if (pWindow)
+ {
+ // In all cases, the following code fragment
+ // returns the chart bounding box in twips.
+ MapMode aCWMapMode = pWindow->GetMapMode();
+ double fXScale = aCWMapMode.GetScaleX();
+ double fYScale = aCWMapMode.GetScaleY();
+ Point aOffset = pWindow->GetOffsetPixelFrom(*pRootWin);
+ aOffset.X() *= (TWIPS_PER_PIXEL / fXScale);
+ aOffset.Y() *= (TWIPS_PER_PIXEL / fYScale);
+ Size aSize = pWindow->GetSizePixel();
+ aSize.Width() *= (TWIPS_PER_PIXEL / fXScale);
+ aSize.Height() *= (TWIPS_PER_PIXEL / fYScale);
+ aBBox = tools::Rectangle(aOffset, aSize);
+ }
+ }
+ }
+ }
+ return aBBox;
+}
+
+void LokChartHelper::Invalidate()
+{
+ mpWindow = nullptr;
+ mxDispatcher.clear();
+ mxController.clear();
+}
+
+bool LokChartHelper::Hit(const Point& aPos)
+{
+ if (mpViewShell)
+ {
+ vcl::Window* pChartWindow = GetWindow();
+ if (pChartWindow)
+ {
+ tools::Rectangle rChartBBox = GetChartBoundingBox();
+ return rChartBBox.IsInside(aPos);
+ }
+ }
+ return false;
+}
+
+bool LokChartHelper::HitAny(const Point& aPos)
+{
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while (pViewShell)
+ {
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.Hit(aPos))
+ return true;
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+ return false;
+}
+
+void LokChartHelper::PaintTile(VirtualDevice& rRenderContext, const tools::Rectangle& rTileRect)
+{
+ if (mpViewShell)
+ {
+ vcl::Window* pChartWindow = GetWindow();
+ if (pChartWindow)
+ {
+ tools::Rectangle aChartRect = GetChartBoundingBox();
+ tools::Rectangle aTestRect = rTileRect;
+ aTestRect.Intersection( aChartRect );
+ if (!aTestRect.IsEmpty())
+ {
+ Point aOffset( aChartRect.Left() - rTileRect.Left(), aChartRect.Top() - rTileRect.Top() );
+ Point aOffsetFromTile = lcl_TwipsToHMM(aOffset);
+ Size aSize = lcl_TwipsToHMM(aChartRect.GetSize());
+ tools::Rectangle aRectangle(Point(0,0), aSize);
+
+ bool bEnableMapMode = !pChartWindow->IsMapModeEnabled();
+ pChartWindow->EnableMapMode();
+ bool bRenderContextEnableMapMode = !rRenderContext.IsMapModeEnabled();
+ rRenderContext.EnableMapMode();
+
+ rRenderContext.Push(PushFlags::MAPMODE);
+
+ MapMode aCWMapMode = pChartWindow->GetMapMode();
+ aCWMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX());
+ aCWMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY());
+
+ aCWMapMode.SetOrigin(aOffsetFromTile);
+ rRenderContext.SetMapMode(aCWMapMode);
+
+ pChartWindow->Paint(rRenderContext, aRectangle);
+
+ rRenderContext.Pop();
+
+ if (bRenderContextEnableMapMode)
+ rRenderContext.EnableMapMode(false);
+ if (bEnableMapMode)
+ pChartWindow->EnableMapMode(false);
+ }
+ }
+ }
+}
+
+void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice,
+ int nOutputWidth, int nOutputHeight,
+ int nTilePosX, int nTilePosY,
+ long nTileWidth, long nTileHeight)
+{
+ // Resizes the virtual device so to contain the entries context
+ rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
+
+ rDevice.Push(PushFlags::MAPMODE);
+ MapMode aMapMode(rDevice.GetMapMode());
+
+ // Scaling. Must convert from pixels to twips. We know
+ // that VirtualDevices use a DPI of 96.
+ Fraction scaleX = Fraction(nOutputWidth, 96) * Fraction(1440L) / Fraction(nTileWidth);
+ Fraction scaleY = Fraction(nOutputHeight, 96) * Fraction(1440L) / Fraction(nTileHeight);
+ aMapMode.SetScaleX(scaleX);
+ aMapMode.SetScaleY(scaleY);
+ rDevice.SetMapMode(aMapMode);
+
+ tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight));
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ while (pViewShell)
+ {
+ LokChartHelper aChartHelper(pViewShell);
+ aChartHelper.PaintTile(rDevice, aTileRect);
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+ rDevice.Pop();
+}
+
+bool LokChartHelper::postMouseEvent(int nType, int nX, int nY,
+ int nCount, int nButtons, int nModifier,
+ double fScaleX, double fScaleY)
+{
+ Point aMousePos(nX, nY);
+ vcl::Window* pChartWindow = GetWindow();
+ if (pChartWindow)
+ {
+ tools::Rectangle rChartBBox = GetChartBoundingBox();
+ if (rChartBBox.IsInside(aMousePos))
+ {
+ int nChartWinX = nX - rChartBBox.Left();
+ int nChartWinY = nY - rChartBBox.Top();
+
+ // chart window expects pixels, but the conversion factor
+ // can depend on the client zoom
+ Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
+ MouseEvent aEvent(aPos, nCount,
+ MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
+
+ switch (nType)
+ {
+ case LOK_MOUSEEVENT_MOUSEBUTTONDOWN:
+ pChartWindow->MouseButtonDown(aEvent);
+ break;
+ case LOK_MOUSEEVENT_MOUSEBUTTONUP:
+ pChartWindow->MouseButtonUp(aEvent);
+ if (pChartWindow->IsTracking())
+ pChartWindow->EndTracking(TrackingEventFlags::DontCallHdl);
+ break;
+ case LOK_MOUSEEVENT_MOUSEMOVE:
+ pChartWindow->MouseMove(aEvent);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LokChartHelper::setTextSelection(int nType, int nX, int nY)
+{
+ tools::Rectangle rChartBBox = GetChartBoundingBox();
+ if (rChartBBox.IsInside(Point(nX, nY)))
+ {
+ css::uno::Reference<css::frame::XDispatch> xDispatcher = GetXDispatcher();
+ if (xDispatcher.is())
+ {
+ int nChartWinX = nX - rChartBBox.Left();
+ int nChartWinY = nY - rChartBBox.Top();
+
+ // no scale here the chart controller expects twips
+ // that are converted to hmm
+ util::URL aURL;
+ aURL.Path = "LOKSetTextSelection";
+ uno::Sequence< beans::PropertyValue > aArgs(3);
+ aArgs[0].Value <<= static_cast<sal_Int32>(nType);
+ aArgs[1].Value <<= static_cast<sal_Int32>(nChartWinX);
+ aArgs[2].Value <<= static_cast<sal_Int32>(nChartWinY);
+ xDispatcher->dispatch(aURL, aArgs);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool LokChartHelper::setGraphicSelection(int nType, int nX, int nY,
+ double fScaleX, double fScaleY)
+{
+ tools::Rectangle rChartBBox = GetChartBoundingBox();
+ if (rChartBBox.IsInside(Point(nX, nY)))
+ {
+ int nChartWinX = nX - rChartBBox.Left();
+ int nChartWinY = nY - rChartBBox.Top();
+
+ vcl::Window* pChartWindow = GetWindow();
+
+ Point aPos(nChartWinX * fScaleX, nChartWinY * fScaleY);
+ switch (nType)
+ {
+ case LOK_SETGRAPHICSELECTION_START:
+ {
+ MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
+ pChartWindow->MouseButtonDown(aClickEvent);
+ MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
+ pChartWindow->MouseMove(aMoveEvent);
+ }
+ break;
+ case LOK_SETGRAPHICSELECTION_END:
+ {
+ MouseEvent aMoveEvent(aPos, 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
+ pChartWindow->MouseMove(aMoveEvent);
+ MouseEvent aClickEvent(aPos, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
+ pChartWindow->MouseButtonUp(aClickEvent);
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ return true;
+ }
+ return false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index bfb0552d2d7d..80c91ef25b7c 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -832,9 +832,11 @@ SfxInPlaceClient* SfxViewShell::GetUIActiveClient() const
if ( !pClients )
return nullptr;
+ bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive();
+
for (SfxInPlaceClient* pIPClient : *pClients)
{
- if ( pIPClient->IsObjectUIActive() )
+ if ( pIPClient->IsObjectUIActive() || ( bIsTiledRendering && pIPClient->IsObjectInPlaceActive() ) )
return pIPClient;
}
@@ -1464,6 +1466,17 @@ void SfxViewShell::afterCallbackRegistered()
{
}
+vcl::Window* SfxViewShell::GetEditWindowForActiveOLEObj() const
+{
+ vcl::Window* pEditWin = nullptr;
+ SfxInPlaceClient* pIPClient = GetIPClient();
+ if (pIPClient)
+ {
+ pEditWin = pIPClient->GetEditWin();
+ }
+ return pEditWin;
+}
+
void SfxViewShell::NotifyCursor(SfxViewShell* /*pViewShell*/) const
{
}
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index ce62affb411c..938ce9e60370 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -207,6 +207,22 @@ void SdrMarkView::ModelHasChanged()
sSelection = "EMPTY";
else
{
+ sal_uInt32 nTotalPaintWindows = this->PaintWindowCount();
+ if (nTotalPaintWindows == 1)
+ {
+ const vcl::Window* pWin = dynamic_cast<const vcl::Window*>(this->GetFirstOutputDevice());
+ if (pWin && pWin->IsChart())
+ {
+ const vcl::Window* pViewShellWindow = GetSfxViewShell()->GetEditWindowForActiveOLEObj();
+ if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pWin))
+ {
+ Point aOffsetPx = pWin->GetOffsetPixelFrom(*pViewShellWindow);
+ Point aLogicOffset = pWin->PixelToLogic(aOffsetPx);
+ aSelection.Move(aLogicOffset.getX(), aLogicOffset.getY());
+ }
+ }
+ }
+
// In case the map mode is in 100th MM, then need to convert the coordinates over to twips for LOK.
if (mpMarkedPV)
{
@@ -732,10 +748,29 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
}
tools::Rectangle aRect(GetMarkedObjRect());
+ tools::Rectangle aSelection(aRect);
+
+ if (bTiledRendering && !aRect.IsEmpty())
+ {
+ sal_uInt32 nTotalPaintWindows = this->PaintWindowCount();
+ if (nTotalPaintWindows == 1)
+ {
+ const vcl::Window* pWin = dynamic_cast<const vcl::Window*>(this->GetFirstOutputDevice());
+ if (pWin && pWin->IsChart())
+ {
+ const vcl::Window* pViewShellWindow = GetSfxViewShell()->GetEditWindowForActiveOLEObj();
+ if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pWin))
+ {
+ Point aOffsetPx = pWin->GetOffsetPixelFrom(*pViewShellWindow);
+ Point aLogicOffset = pWin->PixelToLogic(aOffsetPx);
+ aSelection.Move(aLogicOffset.getX(), aLogicOffset.getY());
+ }
+ }
+ }
+ }
if (bTiledRendering)
{
- tools::Rectangle aSelection(aRect);
OString sSelection;
if (aSelection.IsEmpty())
sSelection = "EMPTY";
diff --git a/svx/source/svdraw/svdpntv.cxx b/svx/source/svdraw/svdpntv.cxx
index 7642a1ce2e7b..4ac29efb0e08 100644
--- a/svx/source/svdraw/svdpntv.cxx
+++ b/svx/source/svdraw/svdpntv.cxx
@@ -59,6 +59,8 @@
#include <comphelper/lok.hxx>
#include <svx/svdviter.hxx>
+#include <sfx2/lokhelper.hxx>
+
using namespace ::com::sun::star;
// interface to SdrPaintWindow
@@ -1115,6 +1117,13 @@ void SdrPaintView::ShowItemBrowser(bool bShow)
void SdrPaintView::MakeVisible(const tools::Rectangle& rRect, vcl::Window& rWin)
{
+ // TODO: handle when the text cursor goes out of the chart area
+ // However this hack avoids that the cursor gets misplaced wrt the text.
+ if (comphelper::LibreOfficeKit::isActive() && rWin.IsChart())
+ {
+ return;
+ }
+
MapMode aMap(rWin.GetMapMode());
Size aActualSize(rWin.GetOutputSize());
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index ccbfb62589cd..9316b919137e 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -415,6 +415,8 @@ public:
virtual bool isMimeTypeSupported() override;
/// @see vcl::ITiledRenderable::setClientVisibleArea().
virtual void setClientVisibleArea(const tools::Rectangle& rRectangle) override;
+ /// @see vcl::ITiledRenderable::setClientZoom.
+ virtual void setClientZoom(int nTilePixelWidth_, int nTilePixelHeight_, int nTileTwipWidth_, int nTileTwipHeight_) override;
/// @see vcl::ITiledRenderable::getPointer().
virtual Pointer getPointer() override;
/// @see vcl::ITiledRenderable::getTrackedChanges().
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 8a79a0896b60..2a2d46c95c39 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -25,6 +25,7 @@
#include <svx/srchdlg.hxx>
#include <svx/svdobj.hxx>
#include <sfx2/viewsh.hxx>
+#include <sfx2/ipclient.hxx>
#include <drawdoc.hxx>
#include <swwait.hxx>
#include <swmodule.hxx>
@@ -1885,10 +1886,12 @@ void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contex
rDevice.SetMapMode(aMapMode);
// Update scaling of SwEditWin and its sub-widgets, needed for comments.
+ sal_uInt16 nOldZoomValue = 0;
if (GetWin() && GetWin()->GetMapMode().GetScaleX() != scaleX)
{
double fScale = scaleX;
SwViewOption aOption(*GetViewOptions());
+ nOldZoomValue = aOption.GetZoom();
aOption.SetZoom(fScale * 100);
ApplyViewOptions(aOption);
// Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
@@ -1918,6 +1921,32 @@ void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contex
pPostItMgr->PaintTile(rDevice);
// SwViewShell's output device tear down
+
+ // A view shell can get a PaintTile call for a tile at a zoom level
+ // different from the one, the related client really is.
+ // In such a case it is better to reset the current scale value to
+ // the original one, since such a value should be in synchronous with
+ // the zoom level in the client (see setClientZoom).
+ // At present the zoom value returned by GetViewOptions()->GetZoom() is
+ // used in SwXTextDocument methods (postMouseEvent and setGraphicSelection)
+ // for passing the correct mouse position to an edited chart (if any).
+ if (nOldZoomValue !=0)
+ {
+ SwViewOption aOption(*GetViewOptions());
+ aOption.SetZoom(nOldZoomValue);
+ ApplyViewOptions(aOption);
+
+ // Changing the zoom value doesn't always trigger the updating of
+ // the client ole object area, so we call it directly.
+ SfxInPlaceClient* pIPClient = GetSfxViewShell()->GetIPClient();
+ if (pIPClient)
+ {
+ pIPClient->VisAreaChanged();
+ }
+ // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
+ GetWin()->EnableMapMode(false);
+ }
+
mpOut = pSaveOut;
comphelper::LibreOfficeKit::setTiledPainting(false);
}
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index aca79a13c678..1e2473fdc6f8 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -37,6 +37,8 @@
#include <toolkit/helper/vclunohelper.hxx>
#include <toolkit/awt/vclxdevice.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sfx2/lokcharthelper.hxx>
+#include <sfx2/ipclient.hxx>
#include <editeng/svxacorr.hxx>
#include <editeng/acorrcfg.hxx>
#include <cmdid.h>
@@ -166,6 +168,8 @@
#include <comphelper/servicehelper.hxx>
#include <memory>
+#define TWIPS_PER_PIXEL 15
+
using namespace ::com::sun::star;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::i18n;
@@ -3078,6 +3082,9 @@ void SwXTextDocument::paintTile( VirtualDevice &rDevice,
SwViewShell* pViewShell = pDocShell->GetWrtShell();
pViewShell->PaintTile(rDevice, nOutputWidth, nOutputHeight,
nTilePosX, nTilePosY, nTileWidth, nTileHeight);
+
+ LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight,
+ nTilePosX, nTilePosY, nTileWidth, nTileHeight);
}
Size SwXTextDocument::getDocumentSize()
@@ -3158,6 +3165,34 @@ void SwXTextDocument::setClientVisibleArea(const tools::Rectangle& rRectangle)
pView->ForcePageUpDownOffset(2 * rRectangle.GetHeight() / 3);
}
+void SwXTextDocument::setClientZoom(int nTilePixelWidth_, int /*nTilePixelHeight_*/,
+ int nTileTwipWidth_, int /*nTileTwipHeight_*/)
+{
+ // Here we set the zoom value as it has been set by the user in the client.
+ // This value is used in postMouseEvent and setGraphicSelection methods
+ // for in place chart editing. We assume that x and y scale is rougly
+ // the same.
+ // Indeed we could set mnTilePixelWidth, mnTilePixelHeight, mnTileTwipWidth,
+ // mnTileTwipHeight data members of this class but they are not very useful
+ // since we need to be able to retrieve the zoom value for each view shell.
+ SfxInPlaceClient* pIPClient = pDocShell->GetView()->GetIPClient();
+ if (pIPClient)
+ {
+ SwViewShell* pWrtViewShell = pDocShell->GetWrtShell();
+ double fScale = nTilePixelWidth_ * TWIPS_PER_PIXEL / (nTileTwipWidth_ * 1.0);
+ SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
+ if (aOption.GetZoom() != fScale * 100)
+ {
+ aOption.SetZoom(fScale * 100);
+ pWrtViewShell->ApplyViewOptions(aOption);
+
+ // Changing the zoom value doesn't always trigger the updating of
+ // the client ole object area, so we call it directly.
+ pIPClient->VisAreaChanged();
+ }
+ }
+}
+
Pointer SwXTextDocument::getPointer()
{
SolarMutexGuard aGuard;
@@ -3322,6 +3357,11 @@ void SwXTextDocument::initializeForTiledRendering(const css::uno::Sequence<css::
}
}
+ // Set the initial zoom value to 1; usually it is set in setClientZoom and
+ // SwViewShell::PaintTile; zoom value is used for chart in place
+ // editing, see postMouseEvent and setGraphicSelection methods.
+ aViewOption.SetZoom(1 * 100);
+
aViewOption.SetPostIts(comphelper::LibreOfficeKit::isTiledAnnotations());
pViewShell->ApplyViewOptions(aViewOption);
@@ -3354,16 +3394,25 @@ void SwXTextDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode)
{
SolarMutexGuard aGuard;
- SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin();
+ vcl::Window* pWindow = &(pDocShell->GetView()->GetEditWin());
+
+ SfxViewShell* pViewShell = pDocShell->GetView();
+ LokChartHelper aChartHelper(pViewShell);
+ vcl::Window* pChartWindow = aChartHelper.GetWindow();
+ if (pChartWindow)
+ {
+ pWindow = pChartWindow;
+ }
+
KeyEvent aEvent(nCharCode, nKeyCode, 0);
switch (nType)
{
case LOK_KEYEVENT_KEYINPUT:
- rEditWin.KeyInput(aEvent);
+ pWindow->KeyInput(aEvent);
break;
case LOK_KEYEVENT_KEYUP:
- rEditWin.KeyUp(aEvent);
+ pWindow->KeyUp(aEvent);
break;
default:
assert(false);
@@ -3375,6 +3424,26 @@ void SwXTextDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int
{
SolarMutexGuard aGuard;
+ SwViewShell* pWrtViewShell = pDocShell->GetWrtShell();
+ SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
+ double fScale = aOption.GetZoom() / (TWIPS_PER_PIXEL * 100.0);
+
+ // check if user hit a chart which is being edited by him
+ SfxViewShell* pViewShell = pDocShell->GetView();
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.postMouseEvent(nType, nX, nY,
+ nCount, nButtons, nModifier,
+ fScale, fScale))
+ return;
+
+ // 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)))
+ return;
+ }
+
SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin();
Point aPos(nX , nY);
MouseEvent aEvent(aPos, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
@@ -3406,6 +3475,11 @@ void SwXTextDocument::setTextSelection(int nType, int nX, int nY)
{
SolarMutexGuard aGuard;
+ SfxViewShell* pViewShell = pDocShell->GetView();
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.setTextSelection(nType, nX, nY))
+ return;
+
SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin();
switch (nType)
{
@@ -3504,6 +3578,15 @@ void SwXTextDocument::setGraphicSelection(int nType, int nX, int nY)
{
SolarMutexGuard aGuard;
+ SwViewShell* pWrtViewShell = pDocShell->GetWrtShell();
+ SwViewOption aOption(*(pWrtViewShell->GetViewOptions()));
+ double fScale = aOption.GetZoom() / (TWIPS_PER_PIXEL * 100.0);
+
+ SfxViewShell* pViewShell = pDocShell->GetView();
+ LokChartHelper aChartHelper(pViewShell);
+ if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale))
+ return;
+
SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin();
switch (nType)
{
diff --git a/vcl/source/window/stacking.cxx b/vcl/source/window/stacking.cxx
index 1aa805e0fdee..cb7c6ebf2b51 100644
--- a/vcl/source/window/stacking.cxx
+++ b/vcl/source/window/stacking.cxx
@@ -1005,6 +1005,11 @@ void Window::SetParent( vcl::Window* pNewParent )
Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
}
+bool Window::IsAncestorOf( const vcl::Window& rWindow ) const
+{
+ return ImplIsRealParentPath(&rWindow);
+}
+
sal_uInt16 Window::GetChildCount() const
{
if (!mpWindowImpl)
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
index 6f1282736c5f..de44129ab447 100644
--- a/vcl/source/window/window2.cxx
+++ b/vcl/source/window/window2.cxx
@@ -1207,6 +1207,11 @@ bool Window::IsDefaultSize() const
return mpWindowImpl->mbDefSize;
}
+Point Window::GetOffsetPixelFrom(const vcl::Window& rWindow) const
+{
+ return Point(GetOutOffXPixel() - rWindow.GetOutOffXPixel(), GetOutOffYPixel() - rWindow.GetOutOffYPixel());
+}
+
void Window::EnablePaint( bool bEnable )
{
mpWindowImpl->mbPaintDisabled = !bEnable;