summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/drawfunc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sc/source/ui/drawfunc
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sc/source/ui/drawfunc')
-rw-r--r--sc/source/ui/drawfunc/chartsh.cxx155
-rw-r--r--sc/source/ui/drawfunc/drawsh.cxx626
-rw-r--r--sc/source/ui/drawfunc/drawsh2.cxx564
-rw-r--r--sc/source/ui/drawfunc/drawsh4.cxx65
-rw-r--r--sc/source/ui/drawfunc/drawsh5.cxx721
-rw-r--r--sc/source/ui/drawfunc/drformsh.cxx55
-rw-r--r--sc/source/ui/drawfunc/drtxtob.cxx1238
-rw-r--r--sc/source/ui/drawfunc/drtxtob1.cxx124
-rw-r--r--sc/source/ui/drawfunc/drtxtob2.cxx229
-rw-r--r--sc/source/ui/drawfunc/fuconarc.cxx154
-rw-r--r--sc/source/ui/drawfunc/fuconcustomshape.cxx199
-rw-r--r--sc/source/ui/drawfunc/fuconpol.cxx288
-rw-r--r--sc/source/ui/drawfunc/fuconrec.cxx449
-rw-r--r--sc/source/ui/drawfunc/fuconstr.cxx252
-rw-r--r--sc/source/ui/drawfunc/fuconuno.cxx122
-rw-r--r--sc/source/ui/drawfunc/fudraw.cxx766
-rw-r--r--sc/source/ui/drawfunc/fuins1.cxx450
-rw-r--r--sc/source/ui/drawfunc/fuins2.cxx689
-rw-r--r--sc/source/ui/drawfunc/fupoor.cxx280
-rw-r--r--sc/source/ui/drawfunc/fusel.cxx546
-rw-r--r--sc/source/ui/drawfunc/fusel2.cxx159
-rw-r--r--sc/source/ui/drawfunc/futext.cxx687
-rw-r--r--sc/source/ui/drawfunc/futext2.cxx46
-rw-r--r--sc/source/ui/drawfunc/futext3.cxx182
-rw-r--r--sc/source/ui/drawfunc/graphsh.cxx380
-rw-r--r--sc/source/ui/drawfunc/mediash.cxx65
-rw-r--r--sc/source/ui/drawfunc/oleobjsh.cxx51
27 files changed, 9542 insertions, 0 deletions
diff --git a/sc/source/ui/drawfunc/chartsh.cxx b/sc/source/ui/drawfunc/chartsh.cxx
new file mode 100644
index 000000000..ac54c435e
--- /dev/null
+++ b/sc/source/ui/drawfunc/chartsh.cxx
@@ -0,0 +1,155 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdoole2.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/graphichelper.hxx>
+
+#include <sfx2/objface.hxx>
+#include <vcl/EnumContext.hxx>
+
+#include <chartsh.hxx>
+#include <sc.hrc>
+#include <viewdata.hxx>
+#include <drawview.hxx>
+#include <gridwin.hxx>
+#include <sfx2/sidebar/SidebarController.hxx>
+#include <tabvwsh.hxx>
+
+#define ShellClass_ScChartShell
+#include <scslots.hxx>
+
+using namespace css::uno;
+using namespace sfx2::sidebar;
+
+namespace drawing = com::sun::star::drawing;
+
+namespace {
+
+bool inChartContext(const ScTabViewShell* pViewShell)
+{
+ SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(pViewShell);
+ if (pSidebar)
+ return pSidebar->hasChartContextCurrently();
+
+ return false;
+}
+
+} // anonymous namespace
+
+SFX_IMPL_INTERFACE(ScChartShell, ScDrawShell)
+
+void ScChartShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
+ ToolbarId::Draw_Objectbar);
+
+ GetStaticInterface()->RegisterPopupMenu("oleobject");
+}
+
+void ScChartShell::Activate(bool bMDI)
+{
+ if(!inChartContext(GetViewData().GetViewShell()))
+ ScDrawShell::Activate(bMDI);
+ else
+ {
+ // Avoid context changes for chart during activation / deactivation.
+ const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false));
+
+ SfxShell::Activate(bMDI);
+
+ SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled);
+ }
+}
+
+void ScChartShell::Deactivate(bool bMDI)
+{
+ if(!inChartContext(GetViewData().GetViewShell()))
+ ScDrawShell::Deactivate(bMDI);
+ else
+ {
+ // Avoid context changes for chart during activation / deactivation.
+ const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false));
+
+ SfxShell::Deactivate(bMDI);
+
+ SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled);
+ }
+}
+
+ScChartShell::ScChartShell(ScViewData& rData) :
+ ScDrawShell(rData)
+{
+ SetName( "ChartObject" );
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Chart));
+}
+
+ScChartShell::~ScChartShell()
+{
+}
+
+void ScChartShell::GetExportAsGraphicState( SfxItemSet& rSet )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( dynamic_cast<const SdrOle2Obj*>( pObj) )
+ bEnable = true;
+ }
+
+ if (GetObjectShell()->isExportLocked())
+ bEnable = false;
+
+ if( !bEnable )
+ rSet.DisableItem( SID_EXPORT_AS_GRAPHIC );
+}
+
+void ScChartShell::ExecuteExportAsGraphic( SfxRequest& )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObject = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( dynamic_cast<const SdrOle2Obj*>( pObject) )
+ {
+ vcl::Window* pWin = GetViewData().GetActiveWin();
+ css::uno::Reference<css::lang::XComponent> xComponent;
+ const SfxObjectShell* pShell = GetObjectShell();
+ if (pShell)
+ {
+ xComponent = pShell->GetModel();
+ }
+ Reference< drawing::XShape > xSourceDoc( pObject->getUnoShape() );
+ GraphicHelper::SaveShapeAsGraphic(pWin ? pWin->GetFrameWeld() : nullptr, xComponent,
+ xSourceDoc);
+ }
+ }
+
+ Invalidate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drawsh.cxx b/sc/source/ui/drawfunc/drawsh.cxx
new file mode 100644
index 000000000..53273c77c
--- /dev/null
+++ b/sc/source/ui/drawfunc/drawsh.cxx
@@ -0,0 +1,626 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svxdlg.hxx>
+#include <svx/dialogs.hrc>
+#include <sc.hrc>
+
+#include <editeng/eeitem.hxx>
+#include <svx/fontwork.hxx>
+#include <svx/svdpage.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/whiter.hxx>
+
+#include <drawsh.hxx>
+#include <drwlayer.hxx>
+#include <strings.hrc>
+#include <viewdata.hxx>
+#include <document.hxx>
+#include <drawview.hxx>
+#include <scresid.hxx>
+#include <svx/svdobj.hxx>
+#include <tabvwsh.hxx>
+#include <gridwin.hxx>
+#include <sfx2/bindings.hxx>
+
+#define ShellClass_ScDrawShell
+#include <scslots.hxx>
+
+#include <userdat.hxx>
+#include <svl/macitem.hxx>
+#include <sfx2/evntconf.hxx>
+#include <sfx2/viewsh.hxx>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <memory>
+#include <svx/xlnwtit.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <tools/UnitConversion.hxx>
+#include <comphelper/lok.hxx>
+#include <vcl/unohelp2.hxx>
+
+using namespace css;
+
+SFX_IMPL_INTERFACE(ScDrawShell, SfxShell)
+
+namespace
+{
+ void lcl_convertStringArguments(sal_uInt16 nSlot, SfxItemSet& rArgs)
+ {
+ Color aColor;
+
+ if (const SvxDoubleItem* pWidthItem = rArgs.GetItemIfSet(SID_ATTR_LINE_WIDTH_ARG, false))
+ {
+ double fValue = pWidthItem->GetValue();
+ // FIXME: different units...
+ int nPow = 100;
+ int nValue = fValue * nPow;
+
+ XLineWidthItem aItem(nValue);
+ rArgs.Put(aItem);
+ }
+ else if (const SfxStringItem* pColorItem = rArgs.GetItemIfSet(SID_ATTR_COLOR_STR, false))
+ {
+ OUString sColor = pColorItem->GetValue();
+
+ if (sColor == "transparent")
+ aColor = COL_TRANSPARENT;
+ else
+ aColor = Color(ColorTransparency, sColor.toInt32(16));
+
+ switch (nSlot)
+ {
+ case SID_ATTR_LINE_COLOR:
+ {
+ XLineColorItem aLineColorItem(OUString(), aColor);
+ rArgs.Put(aLineColorItem);
+ break;
+ }
+
+ case SID_ATTR_FILL_COLOR:
+ {
+ XFillColorItem aFillColorItem(OUString(), aColor);
+ rArgs.Put(aFillColorItem);
+ break;
+ }
+
+ case SID_ATTR_SHADOW_COLOR:
+ {
+ XColorItem aItem(SDRATTR_SHADOWCOLOR, aColor);
+ rArgs.Put(aItem);
+ break;
+ }
+ }
+ }
+ if (const SfxStringItem* pJSON = rArgs.GetItemIfSet(SID_FILL_GRADIENT_JSON, false))
+ {
+ XGradient aGradient = XGradient::fromJSON(pJSON->GetValue());
+ XFillGradientItem aItem(aGradient);
+ rArgs.Put(aItem);
+ }
+ }
+}
+
+void ScDrawShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
+ ToolbarId::Draw_Objectbar);
+
+ GetStaticInterface()->RegisterPopupMenu("draw");
+
+ GetStaticInterface()->RegisterChildWindow(SvxFontWorkChildWindow::GetChildWindowId());
+}
+
+// disable the unwanted Accelerators
+
+void ScDrawShell::StateDisableItems( SfxItemSet &rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void ScDrawShell::setModified()
+{
+ const SfxObjectShell* pShell = GetObjectShell();
+ if ( pShell )
+ {
+ css::uno::Reference< css::util::XModifiable > xModif( pShell->GetModel(), css::uno::UNO_QUERY );
+ if ( xModif.is() )
+ xModif->setModified( true );
+ }
+}
+
+static void lcl_invalidateTransformAttr(const ScTabViewShell* pViewShell)
+{
+ SfxBindings& rBindings=pViewShell->GetViewFrame()->GetBindings();
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH);
+ rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT);
+}
+
+void ScDrawShell::ExecDrawAttr( SfxRequest& rReq )
+{
+ sal_uInt16 nSlot = rReq.GetSlot();
+ vcl::Window* pWin = rViewData.GetActiveWin();
+ ScDrawView* pView = rViewData.GetScDrawView();
+ SdrModel* pDoc = rViewData.GetDocument().GetDrawLayer();
+
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ const size_t nMarkCount = rMarkList.GetMarkCount();
+ SdrObject* pSingleSelectedObj = nullptr;
+ if ( nMarkCount > 0 )
+ pSingleSelectedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ switch ( nSlot )
+ {
+ case SID_ASSIGNMACRO:
+ {
+ if ( pSingleSelectedObj )
+ ExecuteMacroAssign(pSingleSelectedObj, pWin ? pWin->GetFrameWeld() : nullptr);
+ }
+ break;
+
+ case SID_TEXT_STANDARD: // delete hard text attributes
+ {
+ SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aEmptyAttr(GetPool());
+ pView->SetAttributes(aEmptyAttr, true);
+ }
+ break;
+ case SID_MOVE_SHAPE_HANDLE:
+ {
+ const SfxItemSet *pArgs = rReq.GetArgs ();
+ if (pArgs && pArgs->Count () >= 3)
+ {
+ const SfxUInt32Item* handleNumItem = rReq.GetArg<SfxUInt32Item>(FN_PARAM_1);
+ const SfxUInt32Item* newPosXTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_2);
+ const SfxUInt32Item* newPosYTwips = rReq.GetArg<SfxUInt32Item>(FN_PARAM_3);
+ const SfxInt32Item* OrdNum = rReq.GetArg<SfxInt32Item>(FN_PARAM_4);
+
+ const sal_uLong handleNum = handleNumItem->GetValue();
+ const sal_uLong newPosX = convertTwipToMm100(newPosXTwips->GetValue());
+ const sal_uLong newPosY = convertTwipToMm100(newPosYTwips->GetValue());
+
+ bool bNegateX = comphelper::LibreOfficeKit::isActive() && rViewData.GetDocument().IsLayoutRTL(rViewData.GetTabNo());
+ pView->MoveShapeHandle(handleNum, Point(bNegateX ? -static_cast<tools::Long>(newPosX) : newPosX, newPosY), OrdNum ? OrdNum->GetValue() : -1);
+ }
+ }
+ break;
+
+ case SID_ATTR_LINE_STYLE:
+ case SID_ATTR_LINEEND_STYLE:
+ case SID_ATTR_LINE_START:
+ case SID_ATTR_LINE_END:
+ case SID_ATTR_LINE_DASH:
+ case SID_ATTR_LINE_WIDTH:
+ case SID_ATTR_LINE_COLOR:
+ case SID_ATTR_LINE_TRANSPARENCE:
+ case SID_ATTR_LINE_JOINT:
+ case SID_ATTR_LINE_CAP:
+ case SID_ATTR_FILL_STYLE:
+ case SID_ATTR_FILL_COLOR:
+ case SID_ATTR_FILL_GRADIENT:
+ case SID_ATTR_FILL_HATCH:
+ case SID_ATTR_FILL_BITMAP:
+ case SID_ATTR_FILL_TRANSPARENCE:
+ case SID_ATTR_FILL_FLOATTRANSPARENCE:
+
+ // #i25616#
+ case SID_ATTR_FILL_SHADOW:
+ case SID_ATTR_SHADOW_TRANSPARENCE:
+ case SID_ATTR_SHADOW_COLOR:
+ case SID_ATTR_SHADOW_XDISTANCE:
+ case SID_ATTR_SHADOW_YDISTANCE:
+ {
+ // if toolbar is vertical :
+ if ( !rReq.GetArgs() )
+ {
+ switch ( nSlot )
+ {
+ case SID_ATTR_LINE_STYLE:
+ case SID_ATTR_LINE_DASH:
+ case SID_ATTR_LINE_WIDTH:
+ case SID_ATTR_LINE_COLOR:
+ case SID_ATTR_LINE_TRANSPARENCE:
+ case SID_ATTR_LINE_JOINT:
+ case SID_ATTR_LINE_CAP:
+ ExecuteLineDlg( rReq );
+ break;
+
+ case SID_ATTR_FILL_STYLE:
+ case SID_ATTR_FILL_COLOR:
+ case SID_ATTR_FILL_GRADIENT:
+ case SID_ATTR_FILL_HATCH:
+ case SID_ATTR_FILL_BITMAP:
+ case SID_ATTR_FILL_TRANSPARENCE:
+ case SID_ATTR_FILL_FLOATTRANSPARENCE:
+
+ // #i25616#
+ case SID_ATTR_FILL_SHADOW:
+ case SID_ATTR_SHADOW_TRANSPARENCE:
+ case SID_ATTR_SHADOW_COLOR:
+ case SID_ATTR_SHADOW_XDISTANCE:
+ case SID_ATTR_SHADOW_YDISTANCE:
+ ExecuteAreaDlg( rReq );
+ break;
+
+ default:
+ break;
+ }
+
+ return;
+
+ }
+
+ if( pView->AreObjectsMarked() )
+ {
+ SfxItemSet aNewArgs = rReq.GetArgs()->CloneAsValue();
+ lcl_convertStringArguments( rReq.GetSlot(), aNewArgs );
+ pView->SetAttrToMarked( aNewArgs, false );
+ }
+ else
+ pView->SetDefaultAttr( *rReq.GetArgs(), false);
+ pView->InvalidateAttribs();
+ }
+ break;
+
+ case SID_ATTRIBUTES_LINE:
+ ExecuteLineDlg( rReq );
+ break;
+
+ case SID_ATTRIBUTES_AREA:
+ ExecuteAreaDlg( rReq );
+ break;
+
+ case SID_MEASURE_DLG:
+ ExecuteMeasureDlg( rReq );
+ break;
+
+ case SID_DRAWTEXT_ATTR_DLG:
+ ExecuteTextAttrDlg( rReq );
+ break;
+
+ case SID_EDIT_HYPERLINK:
+ if ( pSingleSelectedObj )
+ rViewData.GetDispatcher().Execute( SID_HYPERLINK_DIALOG );
+ break;
+
+ case SID_REMOVE_HYPERLINK:
+ if ( pSingleSelectedObj )
+ {
+ pSingleSelectedObj->setHyperlink(OUString());
+ setModified();
+ }
+ break;
+
+ case SID_OPEN_HYPERLINK:
+ case SID_COPY_HYPERLINK_LOCATION:
+ if ( nMarkCount == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if ( pObj->IsGroupObject() )
+ {
+ SdrPageView* pPV = nullptr;
+ SdrObject* pHit = pView->PickObj(pWin->PixelToLogic(rViewData.GetMousePosPixel()), pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
+ if (pHit)
+ pObj = pHit;
+ }
+
+ if (!pObj->getHyperlink().isEmpty())
+ {
+ if (nSlot == SID_OPEN_HYPERLINK)
+ {
+ ScGlobal::OpenURL(pObj->getHyperlink(), OUString(), true);
+ }
+ else if (nSlot == SID_COPY_HYPERLINK_LOCATION)
+ {
+ uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
+ = GetViewShell()->GetWindow()->GetClipboard();
+ vcl::unohelper::TextDataObject::CopyStringTo(pObj->getHyperlink(), xClipboard);
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_TRANSFORM:
+ {
+ if ( pView->AreObjectsMarked() )
+ {
+ const SfxItemSet* pArgs = rReq.GetArgs();
+
+ if( !pArgs )
+ {
+ if( rMarkList.GetMark(0) != nullptr )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ std::shared_ptr<SfxRequest> pRequest = std::make_shared<SfxRequest>(rReq);
+
+ if( pObj->GetObjIdentifier() == SdrObjKind::Caption )
+ {
+ // Caption Itemset
+ SfxItemSet aNewAttr(pDoc->GetItemPool());
+ pView->GetAttributes(aNewAttr);
+ // Size and Position Itemset
+ SfxItemSet aNewGeoAttr(pView->GetGeoAttrFromMarked());
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateCaptionDialog(pWin ? pWin->GetFrameWeld() : nullptr, pView));
+
+ const WhichRangesContainer& pRange = pDlg->GetInputRanges( *aNewAttr.GetPool() );
+ SfxItemSet aCombSet( *aNewAttr.GetPool(), pRange );
+ aCombSet.Put( aNewAttr );
+ aCombSet.Put( aNewGeoAttr );
+ pDlg->SetInputSet( &aCombSet );
+
+ pDlg->StartExecuteAsync([pDlg, pRequest, pView, this](
+ sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ pRequest->Done(*(pDlg->GetOutputItemSet()));
+ pView->SetAttributes(*pDlg->GetOutputItemSet());
+ pView->SetGeoAttrToMarked(*pDlg->GetOutputItemSet());
+ }
+
+ lcl_invalidateTransformAttr(rViewData.GetViewShell());
+ pDlg->disposeOnce();
+ });
+ }
+ else
+ {
+ SfxItemSet aNewAttr(pView->GetGeoAttrFromMarked());
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSvxTransformTabDialog(pWin ? pWin->GetFrameWeld() : nullptr, &aNewAttr, pView));
+
+ pDlg->StartExecuteAsync([pDlg, pRequest, pView, this](
+ sal_Int32 nResult){
+ if (nResult == RET_OK)
+ {
+ pRequest->Done(*(pDlg->GetOutputItemSet()));
+ pView->SetGeoAttrToMarked(*pDlg->GetOutputItemSet());
+ }
+
+ lcl_invalidateTransformAttr(rViewData.GetViewShell());
+ pDlg->disposeOnce();
+ });
+ }
+ }
+
+ }
+ else
+ pView->SetGeoAttrToMarked( *pArgs );
+ }
+
+ lcl_invalidateTransformAttr(rViewData.GetViewShell());
+ }
+ break;
+
+ case SID_ATTR_GLOW_COLOR:
+ case SID_ATTR_GLOW_RADIUS:
+ case SID_ATTR_GLOW_TRANSPARENCY:
+ case SID_ATTR_SOFTEDGE_RADIUS:
+ case SID_ATTR_TEXTCOLUMNS_NUMBER:
+ case SID_ATTR_TEXTCOLUMNS_SPACING:
+ if (const SfxItemSet* pNewArgs = rReq.GetArgs())
+ pView->SetAttrToMarked(*pNewArgs, false);
+ rReq.Done();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void ScDrawShell::ExecuteMacroAssign(SdrObject* pObj, weld::Window* pWin)
+{
+ SvxMacroItem aItem ( SfxGetpApp()->GetPool().GetWhich( SID_ATTR_MACROITEM ) );
+ ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, true );
+ if ( !pInfo->GetMacro().isEmpty() )
+ {
+ SvxMacroTableDtor aTab;
+ const OUString& sMacro = pInfo->GetMacro();
+ aTab.Insert(SvMacroItemId::OnClick, SvxMacro(sMacro, OUString()));
+ aItem.SetMacroTable( aTab );
+ }
+
+ // create empty itemset for macro-dlg
+ SfxItemSetFixed<SID_ATTR_MACROITEM, SID_ATTR_MACROITEM, SID_EVENTCONFIG, SID_EVENTCONFIG> aItemSet(SfxGetpApp()->GetPool() );
+ aItemSet.Put ( aItem );
+
+ SfxEventNamesItem aNamesItem(SID_EVENTCONFIG);
+ aNamesItem.AddEvent( ScResId(RID_SCSTR_ONCLICK), OUString(), SvMacroItemId::OnClick );
+ aItemSet.Put( aNamesItem );
+
+ css::uno::Reference < css::frame::XFrame > xFrame;
+ if (GetViewShell())
+ xFrame = GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pMacroDlg(pFact->CreateEventConfigDialog( pWin, aItemSet, xFrame ));
+ if ( pMacroDlg->Execute() != RET_OK )
+ return;
+
+ const SfxItemSet* pOutSet = pMacroDlg->GetOutputItemSet();
+ const SvxMacroItem* pItem = pOutSet->GetItemIfSet( SID_ATTR_MACROITEM, false );
+ if( !pItem )
+ return;
+
+ OUString sMacro;
+ const SvxMacro* pMacro = pItem->GetMacroTable().Get( SvMacroItemId::OnClick );
+ if ( pMacro )
+ sMacro = pMacro->GetMacName();
+
+ if ( pObj->IsGroupObject() )
+ {
+ SdrObjList* pOL = pObj->GetSubList();
+ const size_t nObj = pOL->GetObjCount();
+ for ( size_t index=0; index<nObj; ++index )
+ {
+ pInfo = ScDrawLayer::GetMacroInfo( pOL->GetObj(index), true );
+ pInfo->SetMacro( sMacro );
+ }
+ }
+ else
+ pInfo->SetMacro( sMacro );
+ setModified();
+}
+
+void ScDrawShell::ExecuteLineDlg( const SfxRequest& rReq )
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ bool bHasMarked = pView->AreObjectsMarked();
+ const SdrObject* pObj = nullptr;
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ std::shared_ptr<SfxRequest> pRequest = std::make_shared<SfxRequest>(rReq);
+
+ if( rMarkList.GetMarkCount() == 1 )
+ pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ SfxItemSet aNewAttr( pView->GetDefaultAttr() );
+ if( bHasMarked )
+ pView->MergeAttrFromMarked( aNewAttr, false );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSvxLineTabDialog( rViewData.GetDialogParent(),
+ &aNewAttr,
+ rViewData.GetDocument().GetDrawLayer(),
+ pObj,
+ bHasMarked));
+
+ pDlg->StartExecuteAsync([=](sal_Int32 nResult){
+ if ( nResult == RET_OK )
+ {
+ if( bHasMarked )
+ pView->SetAttrToMarked( *pDlg->GetOutputItemSet(), false );
+ else
+ pView->SetDefaultAttr( *pDlg->GetOutputItemSet(), false );
+
+ pView->InvalidateAttribs();
+ pRequest->Done();
+ }
+ pDlg->disposeOnce();
+ });
+}
+
+void ScDrawShell::ExecuteAreaDlg( const SfxRequest& rReq )
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ bool bHasMarked = pView->AreObjectsMarked();
+
+ std::shared_ptr<SfxRequest> pRequest = std::make_shared<SfxRequest>(rReq);
+
+ SfxItemSet aNewAttr( pView->GetDefaultAttr() );
+ if( bHasMarked )
+ pView->MergeAttrFromMarked( aNewAttr, false );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ weld::Window* pWin = rViewData.GetDialogParent();
+ VclPtr<AbstractSvxAreaTabDialog> pDlg(pFact->CreateSvxAreaTabDialog(
+ pWin, &aNewAttr,
+ rViewData.GetDocument().GetDrawLayer(), true, false));
+
+ pDlg->StartExecuteAsync([=](sal_Int32 nResult){
+ if ( nResult == RET_OK )
+ {
+ if( bHasMarked )
+ pView->SetAttrToMarked( *pDlg->GetOutputItemSet(), false );
+ else
+ pView->SetDefaultAttr( *pDlg->GetOutputItemSet(), false );
+
+ pView->InvalidateAttribs();
+ pRequest->Done();
+ }
+ pDlg->disposeOnce();
+ });
+}
+
+void ScDrawShell::ExecuteTextAttrDlg( SfxRequest& rReq )
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ bool bHasMarked = pView->AreObjectsMarked();
+ SfxItemSet aNewAttr ( pView->GetDefaultAttr() );
+
+ if( bHasMarked )
+ pView->MergeAttrFromMarked( aNewAttr, false );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ weld::Window* pWin = rViewData.GetDialogParent();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateTextTabDialog(pWin, &aNewAttr, pView));
+
+ sal_uInt16 nResult = pDlg->Execute();
+
+ if ( RET_OK == nResult )
+ {
+ if ( bHasMarked )
+ pView->SetAttributes( *pDlg->GetOutputItemSet() );
+ else
+ pView->SetDefaultAttr( *pDlg->GetOutputItemSet(), false );
+
+ pView->InvalidateAttribs();
+ rReq.Done();
+ }
+}
+
+void ScDrawShell::ExecuteMeasureDlg( SfxRequest& rReq )
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ bool bHasMarked = pView->AreObjectsMarked();
+ SfxItemSet aNewAttr ( pView->GetDefaultAttr() );
+
+ if( bHasMarked )
+ pView->MergeAttrFromMarked( aNewAttr, false );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ weld::Window* pWin = rViewData.GetDialogParent();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSfxDialog(pWin, aNewAttr, pView, RID_SVXPAGE_MEASURE));
+
+ sal_uInt16 nResult = pDlg->Execute();
+
+ if ( RET_OK == nResult )
+ {
+ if ( bHasMarked )
+ pView->SetAttrToMarked( *pDlg->GetOutputItemSet(), false );
+ else
+ pView->SetDefaultAttr( *pDlg->GetOutputItemSet(), false );
+
+ pView->InvalidateAttribs();
+ rReq.Done();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drawsh2.cxx b/sc/source/ui/drawfunc/drawsh2.cxx
new file mode 100644
index 000000000..806216137
--- /dev/null
+++ b/sc/source/ui/drawfunc/drawsh2.cxx
@@ -0,0 +1,564 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+
+#include <editeng/eeitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/xdef.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/ptitem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <svx/sidebar/SelectionChangeHandler.hxx>
+#include <svx/sidebar/SelectionAnalyzer.hxx>
+#include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
+#include <svx/unomid.hxx>
+
+#include <drawsh.hxx>
+#include <drawview.hxx>
+#include <viewdata.hxx>
+#include <sc.hrc>
+#include <tabvwsh.hxx>
+#include <document.hxx>
+#include <drwlayer.hxx>
+#include <drtxtob.hxx>
+#include <gridwin.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/xflgrit.hxx>
+#include <comphelper/lok.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <svx/xflclit.hxx>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <sfx2/ipclient.hxx>
+
+using namespace com::sun::star::drawing;
+using namespace com::sun::star;
+
+
+ScDrawShell::ScDrawShell( ScViewData& rData ) :
+ SfxShell(rData.GetViewShell()),
+ rViewData( rData ),
+ mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
+ [this] () { return this->GetSidebarContextName(); },
+ GetFrame()->GetFrame().GetController(),
+ vcl::EnumContext::Context::Cell))
+{
+ SetPool( &rViewData.GetScDrawView()->GetModel()->GetItemPool() );
+ SfxUndoManager* pMgr = rViewData.GetSfxDocShell()->GetUndoManager();
+ SetUndoManager( pMgr );
+ if ( !rViewData.GetDocument().IsUndoEnabled() )
+ {
+ pMgr->SetMaxUndoActionCount( 0 );
+ }
+ SetName("Drawing");
+
+ mpSelectionChangeHandler->Connect();
+}
+
+ScDrawShell::~ScDrawShell()
+{
+ mpSelectionChangeHandler->Disconnect();
+}
+
+void ScDrawShell::GetState( SfxItemSet& rSet ) // Conditions / Toggles
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ SdrDragMode eMode = pView->GetDragMode();
+
+ rSet.Put( SfxBoolItem( SID_OBJECT_ROTATE, eMode == SdrDragMode::Rotate ) );
+ rSet.Put( SfxBoolItem( SID_OBJECT_MIRROR, eMode == SdrDragMode::Mirror ) );
+ rSet.Put( SfxBoolItem( SID_BEZIER_EDIT, !pView->IsFrameDragSingles() ) );
+
+ sal_uInt16 nFWId = ScGetFontWorkId();
+ SfxViewFrame* pViewFrm = rViewData.GetViewShell()->GetViewFrame();
+ rSet.Put(SfxBoolItem(SID_FONTWORK, pViewFrm->HasChildWindow(nFWId)));
+
+ // Notes always default to Page anchor.
+ bool bDisableAnchor = false;
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if ( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( ScDrawLayer::IsNoteCaption( pObj ) )
+ {
+ bDisableAnchor = true;
+ rSet.DisableItem( SID_ANCHOR_PAGE );
+ rSet.DisableItem( SID_ANCHOR_CELL );
+ rSet.DisableItem( SID_ANCHOR_CELL_RESIZE );
+ }
+ }
+
+ if ( bDisableAnchor )
+ return;
+
+ switch( pView->GetAnchorType() )
+ {
+ case SCA_PAGE:
+ rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, true ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, false ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, false ) );
+ break;
+
+ case SCA_CELL:
+ rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, false ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, true ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, false ) );
+ break;
+
+ case SCA_CELL_RESIZE:
+ rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, false ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, false ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, true ) );
+ break;
+
+ default:
+ rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, false ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, false ) );
+ rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, false ) );
+ break;
+ }
+}
+
+void ScDrawShell::GetDrawFuncState( SfxItemSet& rSet ) // disable functions
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+
+ // call IsMirrorAllowed first to make sure ForcePossibilities (and thus CheckMarked)
+ // is called before GetMarkCount, so the nMarkCount value is valid for the rest of this method.
+ if (!pView->IsMirrorAllowed(true,true))
+ {
+ rSet.DisableItem( SID_MIRROR_HORIZONTAL );
+ rSet.DisableItem( SID_MIRROR_VERTICAL );
+ rSet.DisableItem( SID_FLIP_HORIZONTAL );
+ rSet.DisableItem( SID_FLIP_VERTICAL );
+ }
+
+
+ if (GetObjectShell()->isContentExtractionLocked())
+ {
+ rSet.DisableItem(SID_COPY);
+ rSet.DisableItem(SID_CUT);
+ }
+
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ const size_t nMarkCount = rMarkList.GetMarkCount();
+
+ if ( nMarkCount <= 1 || !pView->IsGroupPossible() )
+ rSet.DisableItem( SID_GROUP );
+ if ( nMarkCount == 0 || !pView->IsUnGroupPossible() )
+ rSet.DisableItem( SID_UNGROUP );
+ if ( nMarkCount != 1 || !pView->IsGroupEnterPossible() )
+ rSet.DisableItem( SID_ENTER_GROUP );
+ if ( !pView->IsGroupEntered() )
+ rSet.DisableItem( SID_LEAVE_GROUP );
+
+ if ( nMarkCount <= 1 ) // Nothing or only one object selected
+ {
+ // alignment
+ rSet.DisableItem( SID_OBJECT_ALIGN_LEFT ); // no alignment on the side
+ rSet.DisableItem( SID_OBJECT_ALIGN_CENTER );
+ rSet.DisableItem( SID_OBJECT_ALIGN_RIGHT );
+ rSet.DisableItem( SID_OBJECT_ALIGN_UP );
+ rSet.DisableItem( SID_OBJECT_ALIGN_MIDDLE );
+ rSet.DisableItem( SID_OBJECT_ALIGN_DOWN );
+ rSet.DisableItem( SID_OBJECT_ALIGN );
+
+ // pseudo slots for Format menu
+ rSet.DisableItem( SID_ALIGN_ANY_LEFT );
+ rSet.DisableItem( SID_ALIGN_ANY_HCENTER );
+ rSet.DisableItem( SID_ALIGN_ANY_RIGHT );
+ rSet.DisableItem( SID_ALIGN_ANY_TOP );
+ rSet.DisableItem( SID_ALIGN_ANY_VCENTER );
+ rSet.DisableItem( SID_ALIGN_ANY_BOTTOM );
+ }
+
+ // do not change layer of form controls
+ // #i83729# do not change layer of cell notes (on internal layer)
+ if ( !nMarkCount || pView->HasMarkedControl() || pView->HasMarkedInternal() )
+ {
+ rSet.DisableItem( SID_OBJECT_HEAVEN );
+ rSet.DisableItem( SID_OBJECT_HELL );
+ }
+ else
+ {
+ if(AreAllObjectsOnLayer(SC_LAYER_FRONT,rMarkList))
+ {
+ rSet.DisableItem( SID_OBJECT_HEAVEN );
+ }
+ else if(AreAllObjectsOnLayer(SC_LAYER_BACK,rMarkList))
+ {
+ rSet.DisableItem( SID_OBJECT_HELL );
+ }
+ }
+
+ bool bCanRename = false;
+ if ( nMarkCount > 1 )
+ {
+ // no hyperlink options for a selected group
+ rSet.DisableItem( SID_EDIT_HYPERLINK );
+ rSet.DisableItem( SID_REMOVE_HYPERLINK );
+ rSet.DisableItem( SID_OPEN_HYPERLINK );
+ rSet.DisableItem( SID_COPY_HYPERLINK_LOCATION );
+ // Fit to cell only works with a single graphic
+ rSet.DisableItem( SID_FITCELLSIZE );
+ }
+ else if ( nMarkCount == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if (pObj->getHyperlink().isEmpty())
+ {
+ rSet.DisableItem( SID_EDIT_HYPERLINK );
+ rSet.DisableItem( SID_OPEN_HYPERLINK );
+ rSet.DisableItem( SID_REMOVE_HYPERLINK );
+ rSet.DisableItem( SID_COPY_HYPERLINK_LOCATION );
+ }
+ SdrLayerID nLayerID = pObj->GetLayer();
+ if ( nLayerID != SC_LAYER_INTERN )
+ bCanRename = true; // #i51351# anything except internal objects can be renamed
+
+ // #91929#; don't show original size entry if not possible
+ SdrObjKind nObjType = pObj->GetObjIdentifier();
+ if ( nObjType == SdrObjKind::OLE2 )
+ {
+ SdrOle2Obj* pOleObj = static_cast<SdrOle2Obj*>(rMarkList.GetMark( 0 )->GetMarkedSdrObj());
+ if (pOleObj->GetObjRef().is() &&
+ (pOleObj->GetObjRef()->getStatus( pOleObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) )
+ //TODO/LATER: why different slots in Draw and Calc?
+ rSet.DisableItem(SID_ORIGINALSIZE);
+ }
+ else if ( nObjType == SdrObjKind::Caption )
+ {
+ if ( nLayerID == SC_LAYER_INTERN )
+ {
+ // SdrCaptionObj() Notes cannot be cut/copy in isolation from
+ // their cells.
+ rSet.DisableItem( SID_CUT );
+ rSet.DisableItem( SID_COPY );
+ // Notes always default to Page anchor.
+ rSet.DisableItem( SID_ANCHOR_TOGGLE );
+ rSet.DisableItem( SID_ANCHOR_MENU );
+ }
+ }
+
+ // Fit to cell is only available for cell anchored graphics obviously
+ if (pView->GetAnchorType() != SCA_CELL &&
+ pView->GetAnchorType() != SCA_CELL_RESIZE)
+ rSet.DisableItem( SID_FITCELLSIZE );
+
+ // Support advanced DiagramHelper
+ if (!pObj->isDiagram())
+ {
+ rSet.DisableItem( SID_REGENERATE_DIAGRAM );
+ rSet.DisableItem( SID_EDIT_DIAGRAM );
+ }
+ }
+ if ( !bCanRename )
+ {
+ // #i68101#
+ rSet.DisableItem( SID_RENAME_OBJECT );
+ rSet.DisableItem( SID_TITLE_DESCRIPTION_OBJECT );
+ }
+
+ if ( !nMarkCount ) // nothing selected
+ {
+ // Arrangement
+ rSet.DisableItem( SID_FRAME_UP );
+ rSet.DisableItem( SID_FRAME_DOWN );
+ rSet.DisableItem( SID_FRAME_TO_TOP );
+ rSet.DisableItem( SID_FRAME_TO_BOTTOM );
+ // Clipboard / delete
+ rSet.DisableItem( SID_DELETE );
+ rSet.DisableItem( SID_DELETE_CONTENTS );
+ rSet.DisableItem( SID_CUT );
+ rSet.DisableItem( SID_COPY );
+ // other
+ rSet.DisableItem( SID_ANCHOR_TOGGLE );
+ rSet.DisableItem( SID_ANCHOR_MENU );
+ rSet.DisableItem( SID_ORIGINALSIZE );
+ rSet.DisableItem( SID_FITCELLSIZE );
+ rSet.DisableItem( SID_ATTR_TRANSFORM );
+ }
+
+ if ( rSet.GetItemState( SID_ENABLE_HYPHENATION ) != SfxItemState::UNKNOWN )
+ {
+ SfxItemSet aAttrs( pView->GetModel()->GetItemPool() );
+ pView->GetAttributes( aAttrs );
+ if( aAttrs.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT )
+ {
+ bool bValue = aAttrs.Get( EE_PARA_HYPHENATE ).GetValue();
+ rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) );
+ }
+ }
+
+ svx::ExtrusionBar::getState( pView, rSet );
+ svx::FontworkBar::getState( pView, rSet );
+}
+
+static void setupFillColorForChart(const SfxViewShell* pShell, SfxItemSet& rSet)
+{
+ if (!pShell)
+ return;
+
+ SfxInPlaceClient* pIPClient = pShell->GetIPClient();
+ if (!pIPClient)
+ return;
+
+ const css::uno::Reference<::css::embed::XEmbeddedObject>& xEmbObj = pIPClient->GetObject();
+ if( !xEmbObj.is() )
+ return;
+
+ ::css::uno::Reference<::css::chart2::XChartDocument> xChart( xEmbObj->getComponent(), uno::UNO_QUERY );
+ if( !xChart.is() )
+ return;
+
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = xChart->getPageBackground();
+ if (!xPropSet.is())
+ return;
+
+ css::uno::Reference<css::beans::XPropertySetInfo> xInfo(xPropSet->getPropertySetInfo());
+ if (!xInfo.is())
+ return;
+
+ if (xInfo->hasPropertyByName("FillColor"))
+ {
+ sal_uInt32 nFillColor = 0;
+ xPropSet->getPropertyValue("FillColor") >>= nFillColor;
+
+ XFillColorItem aFillColorItem("", Color(ColorTransparency, nFillColor));
+ rSet.Put(aFillColorItem);
+
+ if (comphelper::LibreOfficeKit::isActive())
+ pShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
+ (".uno:FillColor=" + std::to_string(nFillColor)).c_str());
+ }
+
+ if (!(comphelper::LibreOfficeKit::isActive() && xInfo->hasPropertyByName("FillGradientName")))
+ return;
+
+ OUString aGradientName;
+ xPropSet->getPropertyValue("FillGradientName") >>= aGradientName;
+
+ ::css::uno::Reference< ::css::frame::XController > xChartController = xChart->getCurrentController();
+ if( !xChartController.is() )
+ return;
+
+ css::uno::Reference<css::lang::XMultiServiceFactory> xFact(xChartController->getModel(), css::uno::UNO_QUERY);
+
+ if (!xFact.is())
+ return;
+
+ css::uno::Reference<css::container::XNameAccess> xNameAccess(
+ xFact->createInstance("com.sun.star.drawing.GradientTable"), css::uno::UNO_QUERY);
+
+ if (xNameAccess.is() && xNameAccess->hasByName(aGradientName))
+ {
+ css::uno::Any aAny = xNameAccess->getByName(aGradientName);
+
+ XFillGradientItem aItem;
+ aItem.SetName(aGradientName);
+ aItem.PutValue(aAny, MID_FILLGRADIENT);
+
+ rSet.Put(aItem);
+ }
+}
+
+// Attributes for Drawing-Objects
+
+void ScDrawShell::GetDrawAttrState( SfxItemSet& rSet )
+{
+ Point aMousePos = rViewData.GetMousePosPixel();
+ vcl::Window* pWindow = rViewData.GetActiveWin();
+ ScDrawView* pDrView = rViewData.GetScDrawView();
+ Point aPos = pWindow->PixelToLogic(aMousePos);
+ bool bHasMarked = pDrView->AreObjectsMarked();
+
+ if( bHasMarked )
+ {
+ SfxAllItemSet aSet(pDrView->GetAttrFromMarked(false));
+ if (const SfxPoolItem* pItem = nullptr;
+ aSet.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER, false, &pItem) >= SfxItemState::DEFAULT
+ && pItem)
+ {
+ aSet.Put(pItem->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_NUMBER));
+ }
+ if (const SfxPoolItem* pItem = nullptr;
+ aSet.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING, false, &pItem) >= SfxItemState::DEFAULT
+ && pItem)
+ {
+ aSet.Put(pItem->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_SPACING));
+ }
+ rSet.Put(aSet, false);
+ }
+ else
+ {
+ rSet.Put( pDrView->GetDefaultAttr() );
+ }
+
+ SdrPageView* pPV = pDrView->GetSdrPageView();
+ if ( !pPV )
+ return;
+
+ // #i52073# when a sheet with an active OLE object is deleted,
+ // the slot state is queried without an active page view
+
+ // Items for position and size (see ScGridWindow::UpdateStatusPosSize, #108137#)
+
+ // #i34458# The SvxSizeItem in SID_TABLE_CELL is no longer needed by
+ // SvxPosSizeStatusBarControl, it's enough to have it in SID_ATTR_SIZE.
+
+ bool bActionItem = false;
+ if ( pDrView->IsAction() ) // action rectangle
+ {
+ tools::Rectangle aRect;
+ pDrView->TakeActionRect( aRect );
+ if ( !aRect.IsEmpty() )
+ {
+ pPV->LogicToPagePos(aRect);
+ rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
+ Size aSize( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() );
+ rSet.Put( SvxSizeItem( SID_ATTR_SIZE, aSize ) );
+ bActionItem = true;
+ }
+
+ // Set correct colors for charts in sidebar
+ setupFillColorForChart(pDrView->GetSfxViewShell(), rSet);
+ }
+ if ( bActionItem )
+ return;
+
+ if ( pDrView->AreObjectsMarked() ) // selected objects
+ {
+ tools::Rectangle aRect = pDrView->GetAllMarkedRect();
+ pPV->LogicToPagePos(aRect);
+ rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
+ Size aSize( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() );
+ rSet.Put( SvxSizeItem( SID_ATTR_SIZE, aSize ) );
+ }
+ else // mouse position
+ {
+ // aPos is initialized above
+ pPV->LogicToPagePos(aPos);
+ rSet.Put( SfxPointItem( SID_ATTR_POSITION, aPos ) );
+ rSet.Put( SvxSizeItem( SID_ATTR_SIZE, Size( 0, 0 ) ) );
+ }
+}
+
+void ScDrawShell::GetAttrFuncState(SfxItemSet &rSet)
+{
+ // Disable dialogs for Draw-attributes if necessary
+
+ ScDrawView* pDrView = rViewData.GetScDrawView();
+ SfxItemSet aViewSet = pDrView->GetAttrFromMarked(false);
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+ const size_t nMarkCount = rMarkList.GetMarkCount();
+ bool bShowArea = true, bShowMeasure = true;
+
+ for ( size_t i = 0; i < nMarkCount && i < 50; ++i )
+ {
+ SdrObject* pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
+ SdrObjKind nObjType = pObj->GetObjIdentifier();
+
+ if ( nObjType != SdrObjKind::Measure )
+ bShowMeasure = false;
+
+ // If marked object is 2D, disable format area command.
+ if ( nObjType == SdrObjKind::PolyLine ||
+ nObjType == SdrObjKind::Line ||
+ nObjType == SdrObjKind::PathLine ||
+ nObjType == SdrObjKind::FreehandLine ||
+ nObjType == SdrObjKind::Edge ||
+ nObjType == SdrObjKind::CircleArc ||
+ bShowMeasure )
+ bShowArea = false;
+
+ if ( !bShowArea && !bShowMeasure )
+ break;
+ }
+
+ if ( !bShowArea )
+ rSet.DisableItem( SID_ATTRIBUTES_AREA );
+
+ if ( !bShowMeasure )
+ rSet.DisableItem( SID_MEASURE_DLG );
+
+ if ( aViewSet.GetItemState( XATTR_LINESTYLE ) == SfxItemState::DEFAULT )
+ {
+ rSet.DisableItem( SID_ATTRIBUTES_LINE );
+ rSet.DisableItem( SID_ATTR_LINEEND_STYLE ); // Tbx-Controller
+ }
+
+ if ( aViewSet.GetItemState( XATTR_FILLSTYLE ) == SfxItemState::DEFAULT )
+ rSet.DisableItem( SID_ATTRIBUTES_AREA );
+}
+
+bool ScDrawShell::AreAllObjectsOnLayer(SdrLayerID nLayerNo,const SdrMarkList& rMark)
+{
+ bool bResult=true;
+ const size_t nCount = rMark.GetMarkCount();
+ for (size_t i=0; i<nCount; ++i)
+ {
+ SdrObject* pObj = rMark.GetMark(i)->GetMarkedSdrObj();
+ if ( dynamic_cast<const SdrUnoObj*>( pObj) == nullptr )
+ {
+ if(nLayerNo!=pObj->GetLayer())
+ {
+ bResult=false;
+ break;
+ }
+ }
+ }
+ return bResult;
+}
+
+void ScDrawShell::GetDrawAttrStateForIFBX( SfxItemSet& rSet )
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMark(0) != nullptr )
+ {
+ SfxItemSet aNewAttr(pView->GetGeoAttrFromMarked());
+ rSet.Put(aNewAttr, false);
+ }
+}
+
+void ScDrawShell::Activate (const bool)
+{
+ ContextChangeEventMultiplexer::NotifyContextChange(
+ GetFrame()->GetFrame().GetController(),
+ vcl::EnumContext::GetContextEnum(
+ GetSidebarContextName()));
+}
+
+const OUString & ScDrawShell::GetSidebarContextName()
+{
+ return vcl::EnumContext::GetContextName(
+ svx::sidebar::SelectionAnalyzer::GetContextForSelection_SC(
+ GetDrawView()->GetMarkedObjectList()));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drawsh4.cxx b/sc/source/ui/drawfunc/drawsh4.cxx
new file mode 100644
index 000000000..fdb0efe91
--- /dev/null
+++ b/sc/source/ui/drawfunc/drawsh4.cxx
@@ -0,0 +1,65 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdotext.hxx>
+#include <svx/xdef.hxx>
+#include <svx/svdoashp.hxx>
+#include <drawsh.hxx>
+#include <drawview.hxx>
+#include <viewdata.hxx>
+
+void ScDrawShell::GetFormTextState(SfxItemSet& rSet)
+{
+ const SdrObject* pObj = nullptr;
+ ScDrawView* pDrView = rViewData.GetScDrawView();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+
+ if ( rMarkList.GetMarkCount() == 1 )
+ pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ const SdrTextObj* pTextObj = dynamic_cast< const SdrTextObj* >(pObj);
+ const bool bDeactivate(
+ !pObj ||
+ !pTextObj ||
+ !pTextObj->HasText() ||
+ dynamic_cast< const SdrObjCustomShape* >(pObj)); // #121538# no FontWork for CustomShapes
+
+ if(bDeactivate)
+ {
+ rSet.DisableItem(XATTR_FORMTXTSTYLE);
+ rSet.DisableItem(XATTR_FORMTXTADJUST);
+ rSet.DisableItem(XATTR_FORMTXTDISTANCE);
+ rSet.DisableItem(XATTR_FORMTXTSTART);
+ rSet.DisableItem(XATTR_FORMTXTMIRROR);
+ rSet.DisableItem(XATTR_FORMTXTHIDEFORM);
+ rSet.DisableItem(XATTR_FORMTXTOUTLINE);
+ rSet.DisableItem(XATTR_FORMTXTSHADOW);
+ rSet.DisableItem(XATTR_FORMTXTSHDWCOLOR);
+ rSet.DisableItem(XATTR_FORMTXTSHDWXVAL);
+ rSet.DisableItem(XATTR_FORMTXTSHDWYVAL);
+ }
+ else
+ {
+ SfxItemSet aViewAttr(pDrView->GetModel()->GetItemPool());
+ pDrView->GetAttributes(aViewAttr);
+ rSet.Set(aViewAttr);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drawsh5.cxx b/sc/source/ui/drawfunc/drawsh5.cxx
new file mode 100644
index 000000000..b95f77f93
--- /dev/null
+++ b/sc/source/ui/drawfunc/drawsh5.cxx
@@ -0,0 +1,721 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/eeitem.hxx>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/bindings.hxx>
+#include <tools/urlobj.hxx>
+#include <cliputil.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/extrusionbar.hxx>
+#include <svx/fontworkbar.hxx>
+#include <svx/svdogrp.hxx>
+#include <sfx2/docfile.hxx>
+#include <osl/diagnose.h>
+#include <svx/diagram/IDiagramHelper.hxx>
+
+#include <com/sun/star/form/FormButtonType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+
+#include <drawsh.hxx>
+#include <drawview.hxx>
+#include <viewdata.hxx>
+#include <tabvwsh.hxx>
+#include <docsh.hxx>
+#include <undotab.hxx>
+#include <drwlayer.hxx>
+#include <drtxtob.hxx>
+#include <memory>
+
+#include <sc.hrc>
+
+using namespace com::sun::star;
+
+void ScDrawShell::GetHLinkState( SfxItemSet& rSet ) // Hyperlink
+{
+ ScDrawView* pView = rViewData.GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ // Hyperlink
+
+ SvxHyperlinkItem aHLinkItem;
+
+ if ( rMarkList.GetMarkCount() == 1 ) // URL-Button marked ?
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ if ( pObj && !pObj->getHyperlink().isEmpty() )
+ {
+ aHLinkItem.SetURL( pObj->getHyperlink() );
+ aHLinkItem.SetInsertMode(HLINK_FIELD);
+ }
+ SdrUnoObj* pUnoCtrl = dynamic_cast<SdrUnoObj*>( pObj );
+ if (pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor())
+ {
+ const uno::Reference<awt::XControlModel>& xControlModel = pUnoCtrl->GetUnoControlModel();
+ OSL_ENSURE( xControlModel.is(), "UNO-Control without model" );
+ if( !xControlModel.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
+
+ OUString sPropButtonType( "ButtonType" );
+
+ if(xInfo->hasPropertyByName( sPropButtonType ))
+ {
+ uno::Any aAny = xPropSet->getPropertyValue( sPropButtonType );
+ form::FormButtonType eTmp;
+ if ( (aAny >>= eTmp) && eTmp == form::FormButtonType_URL )
+ {
+ OUString sTmp;
+ // Label
+ OUString sPropLabel( "Label" );
+ if(xInfo->hasPropertyByName( sPropLabel ))
+ {
+ aAny = xPropSet->getPropertyValue( sPropLabel );
+ if ( (aAny >>= sTmp) && !sTmp.isEmpty() )
+ {
+ aHLinkItem.SetName(sTmp);
+ }
+ }
+ // URL
+ OUString sPropTargetURL( "TargetURL" );
+ if(xInfo->hasPropertyByName( sPropTargetURL ))
+ {
+ aAny = xPropSet->getPropertyValue( sPropTargetURL );
+ if ( (aAny >>= sTmp) && !sTmp.isEmpty() )
+ {
+ aHLinkItem.SetURL(sTmp);
+ }
+ }
+ // Target
+ OUString sPropTargetFrame( "TargetFrame" );
+ if(xInfo->hasPropertyByName( sPropTargetFrame ))
+ {
+ aAny = xPropSet->getPropertyValue( sPropTargetFrame );
+ if ( (aAny >>= sTmp) && !sTmp.isEmpty() )
+ {
+ aHLinkItem.SetTargetFrame(sTmp);
+ }
+ }
+ aHLinkItem.SetInsertMode(HLINK_BUTTON);
+ }
+ }
+ }
+ }
+
+ rSet.Put(aHLinkItem);
+}
+
+void ScDrawShell::ExecuteHLink( const SfxRequest& rReq )
+{
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case SID_HYPERLINK_SETLINK:
+ if( pReqArgs )
+ {
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( SID_HYPERLINK_SETLINK, true, &pItem ) == SfxItemState::SET )
+ {
+ const SvxHyperlinkItem* pHyper = static_cast<const SvxHyperlinkItem*>(pItem);
+ const OUString& rName = pHyper->GetName();
+ const OUString& rURL = pHyper->GetURL();
+ const OUString& rTarget = pHyper->GetTargetFrame();
+ SvxLinkInsertMode eMode = pHyper->GetInsertMode();
+
+ bool bDone = false;
+ if ( eMode == HLINK_FIELD || eMode == HLINK_BUTTON )
+ {
+ ScDrawView* pView = rViewData.GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if ( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ SdrUnoObj* pUnoCtrl = dynamic_cast<SdrUnoObj*>( pObj );
+ if (pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor())
+ {
+ const uno::Reference<awt::XControlModel>& xControlModel =
+ pUnoCtrl->GetUnoControlModel();
+ OSL_ENSURE( xControlModel.is(), "UNO-Control without model" );
+ if( !xControlModel.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
+
+ OUString sPropTargetURL( "TargetURL" );
+
+ // Is it possible to set a URL in the object?
+ if (xInfo->hasPropertyByName( sPropTargetURL ))
+ {
+
+ OUString sPropButtonType( "ButtonType");
+ OUString sPropTargetFrame( "TargetFrame" );
+ OUString sPropLabel( "Label" );
+
+ if ( xInfo->hasPropertyByName( sPropLabel ) )
+ {
+ xPropSet->setPropertyValue( sPropLabel, uno::Any(rName) );
+ }
+
+ OUString aTmp = INetURLObject::GetAbsURL( rViewData.GetDocShell()->GetMedium()->GetBaseURL(), rURL );
+ xPropSet->setPropertyValue( sPropTargetURL, uno::Any(aTmp) );
+
+ if( !rTarget.isEmpty() && xInfo->hasPropertyByName( sPropTargetFrame ) )
+ {
+ xPropSet->setPropertyValue( sPropTargetFrame, uno::Any(rTarget) );
+ }
+
+ if ( xInfo->hasPropertyByName( sPropButtonType ) )
+ {
+ xPropSet->setPropertyValue( sPropButtonType, uno::Any(form::FormButtonType_URL) );
+ }
+
+ //! Undo ???
+ rViewData.GetDocShell()->SetDocumentModified();
+ bDone = true;
+ }
+ }
+ else
+ {
+ pObj->setHyperlink(rURL);
+ setModified();
+ bDone = true;
+ }
+ }
+ }
+
+ if (!bDone)
+ rViewData.GetViewShell()->
+ InsertURL( rName, rURL, rTarget, static_cast<sal_uInt16>(eMode) );
+
+ // If "text" is received by InsertURL of ViewShell, then the DrawShell is turned off !!!
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("wrong slot");
+ }
+}
+
+// Functions on Drawing-Objects
+
+void ScDrawShell::ExecDrawFunc( SfxRequest& rReq )
+{
+ SfxBindings& rBindings = rViewData.GetBindings();
+ ScTabView* pTabView = rViewData.GetView();
+ ScDrawView* pView = pTabView->GetScDrawView();
+ sal_uInt16 nSlotId = rReq.GetSlot();
+
+ switch (nSlotId)
+ {
+ case SID_OBJECT_HEAVEN:
+ pView->SetMarkedToLayer( SC_LAYER_FRONT );
+ rBindings.Invalidate(SID_OBJECT_HEAVEN);
+ rBindings.Invalidate(SID_OBJECT_HELL);
+ break;
+ case SID_OBJECT_HELL:
+ pView->SetMarkedToLayer( SC_LAYER_BACK );
+ rBindings.Invalidate(SID_OBJECT_HEAVEN);
+ rBindings.Invalidate(SID_OBJECT_HELL);
+ // leave draw shell if nothing selected (layer may be locked)
+ rViewData.GetViewShell()->UpdateDrawShell();
+ break;
+
+ case SID_FRAME_TO_TOP:
+ pView->PutMarkedToTop();
+ break;
+ case SID_FRAME_TO_BOTTOM:
+ pView->PutMarkedToBtm();
+ break;
+ case SID_FRAME_UP:
+ pView->MovMarkedToTop();
+ break;
+ case SID_FRAME_DOWN:
+ pView->MovMarkedToBtm();
+ break;
+
+ case SID_GROUP:
+ pView->GroupMarked();
+ break;
+ case SID_UNGROUP:
+ pView->UnGroupMarked();
+ break;
+ case SID_ENTER_GROUP:
+ pView->EnterMarkedGroup();
+ break;
+ case SID_LEAVE_GROUP:
+ pView->LeaveOneGroup();
+ break;
+
+ case SID_REGENERATE_DIAGRAM:
+ case SID_EDIT_DIAGRAM:
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if (1 == rMarkList.GetMarkCount())
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ // Support advanced DiagramHelper
+ if(nullptr != pObj && pObj->isDiagram())
+ {
+ if(SID_REGENERATE_DIAGRAM == nSlotId)
+ {
+ pView->UnmarkAll();
+ pObj->getDiagramHelper()->reLayout(*static_cast<SdrObjGroup*>(pObj));
+ pView->MarkObj(pObj, pView->GetSdrPageView());
+ }
+ else // SID_EDIT_DIAGRAM
+ {
+ VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+ vcl::Window* pWin = rViewData.GetActiveWin();
+ ScopedVclPtr<VclAbstractDialog> pDlg = pFact->CreateDiagramDialog(
+ pWin ? pWin->GetFrameWeld() : nullptr,
+ *static_cast<SdrObjGroup*>(pObj));
+ pDlg->Execute();
+ }
+ }
+ }
+
+ rReq.Done();
+ }
+ break;
+
+ case SID_MIRROR_HORIZONTAL:
+ case SID_FLIP_HORIZONTAL:
+ pView->MirrorAllMarkedHorizontal();
+ rBindings.Invalidate( SID_ATTR_TRANSFORM_ANGLE );
+ break;
+ case SID_MIRROR_VERTICAL:
+ case SID_FLIP_VERTICAL:
+ pView->MirrorAllMarkedVertical();
+ rBindings.Invalidate( SID_ATTR_TRANSFORM_ANGLE );
+ break;
+
+ case SID_OBJECT_ALIGN_LEFT:
+ case SID_ALIGN_ANY_LEFT:
+ if (pView->IsAlignPossible())
+ pView->AlignMarkedObjects(SdrHorAlign::Left, SdrVertAlign::NONE);
+ break;
+ case SID_OBJECT_ALIGN_CENTER:
+ case SID_ALIGN_ANY_HCENTER:
+ if (pView->IsAlignPossible())
+ pView->AlignMarkedObjects(SdrHorAlign::Center, SdrVertAlign::NONE);
+ break;
+ case SID_OBJECT_ALIGN_RIGHT:
+ case SID_ALIGN_ANY_RIGHT:
+ if (pView->IsAlignPossible())
+ pView->AlignMarkedObjects(SdrHorAlign::Right, SdrVertAlign::NONE);
+ break;
+ case SID_OBJECT_ALIGN_UP:
+ case SID_ALIGN_ANY_TOP:
+ if (pView->IsAlignPossible())
+ pView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Top);
+ break;
+ case SID_OBJECT_ALIGN_MIDDLE:
+ case SID_ALIGN_ANY_VCENTER:
+ if (pView->IsAlignPossible())
+ pView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Center);
+ break;
+ case SID_OBJECT_ALIGN_DOWN:
+ case SID_ALIGN_ANY_BOTTOM:
+ if (pView->IsAlignPossible())
+ pView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Bottom);
+ break;
+
+ case SID_DELETE:
+ case SID_DELETE_CONTENTS:
+ pView->DeleteMarked();
+ rViewData.GetViewShell()->UpdateDrawShell();
+ break;
+
+ case SID_CUT:
+ pView->DoCut();
+ rViewData.GetViewShell()->UpdateDrawShell();
+ break;
+
+ case SID_COPY:
+ pView->DoCopy();
+ break;
+
+ case SID_PASTE:
+ ScClipUtil::PasteFromClipboard(GetViewData(), GetViewData().GetViewShell(), true);
+ break;
+
+ case SID_SELECTALL:
+ pView->MarkAll();
+ break;
+
+ case SID_ANCHOR_PAGE:
+ pView->SetPageAnchored();
+ rBindings.Invalidate( SID_ANCHOR_PAGE );
+ rBindings.Invalidate( SID_ANCHOR_CELL );
+ rBindings.Invalidate( SID_ANCHOR_CELL_RESIZE );
+ break;
+
+ case SID_ANCHOR_CELL:
+ pView->SetCellAnchored(false);
+ rBindings.Invalidate( SID_ANCHOR_PAGE );
+ rBindings.Invalidate( SID_ANCHOR_CELL );
+ rBindings.Invalidate( SID_ANCHOR_CELL_RESIZE );
+ break;
+
+ case SID_ANCHOR_CELL_RESIZE:
+ pView->SetCellAnchored(true);
+ rBindings.Invalidate( SID_ANCHOR_PAGE );
+ rBindings.Invalidate( SID_ANCHOR_CELL );
+ rBindings.Invalidate( SID_ANCHOR_CELL_RESIZE );
+ break;
+
+ case SID_ANCHOR_TOGGLE:
+ {
+ switch( pView->GetAnchorType() )
+ {
+ case SCA_CELL:
+ case SCA_CELL_RESIZE:
+ pView->SetPageAnchored();
+ break;
+ default:
+ pView->SetCellAnchored(false);
+ break;
+ }
+ }
+ rBindings.Invalidate( SID_ANCHOR_PAGE );
+ rBindings.Invalidate( SID_ANCHOR_CELL );
+ rBindings.Invalidate( SID_ANCHOR_CELL_RESIZE );
+ break;
+
+ case SID_OBJECT_ROTATE:
+ {
+ SdrDragMode eMode;
+ if (pView->GetDragMode() == SdrDragMode::Rotate)
+ eMode = SdrDragMode::Move;
+ else
+ eMode = SdrDragMode::Rotate;
+ pView->SetDragMode( eMode );
+ rBindings.Invalidate( SID_OBJECT_ROTATE );
+ rBindings.Invalidate( SID_OBJECT_MIRROR );
+ if (eMode == SdrDragMode::Rotate && !pView->IsFrameDragSingles())
+ {
+ pView->SetFrameDragSingles();
+ rBindings.Invalidate( SID_BEZIER_EDIT );
+ }
+ }
+ break;
+ case SID_OBJECT_MIRROR:
+ {
+ SdrDragMode eMode;
+ if (pView->GetDragMode() == SdrDragMode::Mirror)
+ eMode = SdrDragMode::Move;
+ else
+ eMode = SdrDragMode::Mirror;
+ pView->SetDragMode( eMode );
+ rBindings.Invalidate( SID_OBJECT_ROTATE );
+ rBindings.Invalidate( SID_OBJECT_MIRROR );
+ if (eMode == SdrDragMode::Mirror && !pView->IsFrameDragSingles())
+ {
+ pView->SetFrameDragSingles();
+ rBindings.Invalidate( SID_BEZIER_EDIT );
+ }
+ }
+ break;
+ case SID_BEZIER_EDIT:
+ {
+ bool bOld = pView->IsFrameDragSingles();
+ pView->SetFrameDragSingles( !bOld );
+ rBindings.Invalidate( SID_BEZIER_EDIT );
+ if (bOld && pView->GetDragMode() != SdrDragMode::Move)
+ {
+ pView->SetDragMode( SdrDragMode::Move );
+ rBindings.Invalidate( SID_OBJECT_ROTATE );
+ rBindings.Invalidate( SID_OBJECT_MIRROR );
+ }
+ }
+ break;
+
+ case SID_FONTWORK:
+ {
+ sal_uInt16 nId = ScGetFontWorkId();
+ SfxViewFrame* pViewFrm = rViewData.GetViewShell()->GetViewFrame();
+
+ if ( rReq.GetArgs() )
+ pViewFrm->SetChildWindow( nId,
+ static_cast<const SfxBoolItem&>(
+ (rReq.GetArgs()->Get(SID_FONTWORK))).
+ GetValue() );
+ else
+ pViewFrm->ToggleChildWindow( nId );
+
+ rBindings.Invalidate( SID_FONTWORK );
+ rReq.Done();
+ }
+ break;
+
+ case SID_ORIGINALSIZE:
+ pView->SetMarkedOriginalSize();
+ break;
+
+ case SID_FITCELLSIZE:
+ pView->FitToCellSize();
+ break;
+
+ case SID_ENABLE_HYPHENATION:
+ {
+ const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(SID_ENABLE_HYPHENATION);
+ if( pItem )
+ {
+ SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aSet( GetPool() );
+ bool bValue = pItem->GetValue();
+ aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, bValue ) );
+ pView->SetAttributes( aSet );
+ }
+ rReq.Done();
+ }
+ break;
+
+ case SID_RENAME_OBJECT:
+ {
+ if(1 == pView->GetMarkedObjectCount())
+ {
+ // #i68101#
+ SdrObject* pSelected = pView->GetMarkedObjectByIndex(0);
+ OSL_ENSURE(pSelected, "ScDrawShell::ExecDrawFunc: nMarkCount, but no object (!)");
+
+ if(SC_LAYER_INTERN != pSelected->GetLayer())
+ {
+ OUString aName = pSelected->GetName();
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ vcl::Window* pWin = rViewData.GetActiveWin();
+ ScopedVclPtr<AbstractSvxObjectNameDialog> pDlg(pFact->CreateSvxObjectNameDialog(pWin ? pWin->GetFrameWeld() : nullptr, aName));
+
+ pDlg->SetCheckNameHdl(LINK(this, ScDrawShell, NameObjectHdl));
+
+ if(RET_OK == pDlg->Execute())
+ {
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+ pDlg->GetName(aName);
+
+ if (aName != pSelected->GetName())
+ {
+ // handle name change
+ const SdrObjKind nObjType(pSelected->GetObjIdentifier());
+
+ if (SdrObjKind::Graphic == nObjType && aName.isEmpty())
+ {
+ // graphics objects must have names
+ // (all graphics are supposed to be in the navigator)
+ ScDrawLayer* pModel = rViewData.GetDocument().GetDrawLayer();
+
+ if(pModel)
+ {
+ aName = pModel->GetNewGraphicName();
+ }
+ }
+
+ // An undo action for renaming is missing in svdraw (99363).
+ // For OLE objects (which can be identified using the persist name),
+ // ScUndoRenameObject can be used until there is a common action for all objects.
+ if(SdrObjKind::OLE2 == nObjType)
+ {
+ const OUString aPersistName = static_cast<SdrOle2Obj*>(pSelected)->GetPersistName();
+
+ if(!aPersistName.isEmpty())
+ {
+ pDocSh->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoRenameObject>(pDocSh, aPersistName, pSelected->GetName(), aName));
+ }
+ }
+
+ // set new name
+ pSelected->SetName(aName);
+ }
+
+ // ChartListenerCollectionNeedsUpdate is needed for Navigator update
+ pDocSh->GetDocument().SetChartListenerCollectionNeedsUpdate( true );
+ pDocSh->SetDrawModified();
+ }
+ }
+ }
+ break;
+ }
+
+ // #i68101#
+ case SID_TITLE_DESCRIPTION_OBJECT:
+ {
+ if(1 == pView->GetMarkedObjectCount())
+ {
+ SdrObject* pSelected = pView->GetMarkedObjectByIndex(0);
+ OSL_ENSURE(pSelected, "ScDrawShell::ExecDrawFunc: nMarkCount, but no object (!)");
+
+ if(SC_LAYER_INTERN != pSelected->GetLayer())
+ {
+ OUString aTitle(pSelected->GetTitle());
+ OUString aDescription(pSelected->GetDescription());
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ vcl::Window* pWin = rViewData.GetActiveWin();
+ ScopedVclPtr<AbstractSvxObjectTitleDescDialog> pDlg(pFact->CreateSvxObjectTitleDescDialog(
+ pWin ? pWin->GetFrameWeld() : nullptr, aTitle, aDescription));
+
+ if(RET_OK == pDlg->Execute())
+ {
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+
+ // handle Title and Description
+ pDlg->GetTitle(aTitle);
+ pDlg->GetDescription(aDescription);
+ pSelected->SetTitle(aTitle);
+ pSelected->SetDescription(aDescription);
+
+ // ChartListenerCollectionNeedsUpdate is needed for Navigator update
+ pDocSh->GetDocument().SetChartListenerCollectionNeedsUpdate( true );
+ pDocSh->SetDrawModified();
+ }
+ }
+ }
+ break;
+ }
+
+ case SID_EXTRUSION_TOGGLE:
+ case SID_EXTRUSION_TILT_DOWN:
+ case SID_EXTRUSION_TILT_UP:
+ case SID_EXTRUSION_TILT_LEFT:
+ case SID_EXTRUSION_TILT_RIGHT:
+ case SID_EXTRUSION_3D_COLOR:
+ case SID_EXTRUSION_DEPTH:
+ case SID_EXTRUSION_DIRECTION:
+ case SID_EXTRUSION_PROJECTION:
+ case SID_EXTRUSION_LIGHTING_DIRECTION:
+ case SID_EXTRUSION_LIGHTING_INTENSITY:
+ case SID_EXTRUSION_SURFACE:
+ case SID_EXTRUSION_DEPTH_FLOATER:
+ case SID_EXTRUSION_DIRECTION_FLOATER:
+ case SID_EXTRUSION_LIGHTING_FLOATER:
+ case SID_EXTRUSION_SURFACE_FLOATER:
+ case SID_EXTRUSION_DEPTH_DIALOG:
+ svx::ExtrusionBar::execute( pView, rReq, rBindings );
+ rReq.Ignore ();
+ break;
+
+ case SID_FONTWORK_SHAPE:
+ case SID_FONTWORK_SHAPE_TYPE:
+ case SID_FONTWORK_ALIGNMENT:
+ case SID_FONTWORK_SAME_LETTER_HEIGHTS:
+ case SID_FONTWORK_CHARACTER_SPACING:
+ case SID_FONTWORK_KERN_CHARACTER_PAIRS:
+ case SID_FONTWORK_CHARACTER_SPACING_FLOATER:
+ case SID_FONTWORK_ALIGNMENT_FLOATER:
+ case SID_FONTWORK_CHARACTER_SPACING_DIALOG:
+ svx::FontworkBar::execute( *pView, rReq, rBindings );
+ rReq.Ignore ();
+ break;
+
+ default:
+ break;
+ }
+}
+
+IMPL_LINK( ScDrawShell, NameObjectHdl, AbstractSvxObjectNameDialog&, rDialog, bool )
+{
+ OUString aName;
+ rDialog.GetName( aName );
+
+ ScDrawLayer* pModel = rViewData.GetDocument().GetDrawLayer();
+ if ( !aName.isEmpty() && pModel )
+ {
+ SCTAB nDummyTab;
+ if ( pModel->GetNamedObject( aName, SdrObjKind::NONE, nDummyTab ) )
+ {
+ // existing object found -> name invalid
+ return false;
+ }
+ }
+
+ return true; // name is valid
+}
+
+void ScDrawShell::ExecFormText(const SfxRequest& rReq)
+{
+ ScDrawView* pDrView = rViewData.GetScDrawView();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+
+ if ( rMarkList.GetMarkCount() == 1 && rReq.GetArgs() )
+ {
+ const SfxItemSet& rSet = *rReq.GetArgs();
+
+ if ( pDrView->IsTextEdit() )
+ pDrView->ScEndTextEdit();
+
+ pDrView->SetAttributes(rSet);
+ }
+}
+
+void ScDrawShell::ExecFormatPaintbrush( const SfxRequest& rReq )
+{
+ ScViewFunc* pView = rViewData.GetView();
+ if ( pView->HasPaintBrush() )
+ {
+ // cancel paintbrush mode
+ pView->ResetBrushDocument();
+ }
+ else
+ {
+ bool bLock = false;
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ if( pArgs && pArgs->Count() >= 1 )
+ bLock = pArgs->Get(SID_FORMATPAINTBRUSH).GetValue();
+
+ ScDrawView* pDrawView = rViewData.GetScDrawView();
+ if ( pDrawView && pDrawView->AreObjectsMarked() )
+ {
+ std::unique_ptr<SfxItemSet> pItemSet(new SfxItemSet( pDrawView->GetAttrFromMarked(true/*bOnlyHardAttr*/) ));
+ pView->SetDrawBrushSet( std::move(pItemSet), bLock );
+ }
+ }
+}
+
+void ScDrawShell::StateFormatPaintbrush( SfxItemSet& rSet )
+{
+ ScDrawView* pDrawView = rViewData.GetScDrawView();
+ bool bSelection = pDrawView && pDrawView->AreObjectsMarked();
+ bool bHasPaintBrush = rViewData.GetView()->HasPaintBrush();
+
+ if ( !bHasPaintBrush && !bSelection )
+ rSet.DisableItem( SID_FORMATPAINTBRUSH );
+ else
+ rSet.Put( SfxBoolItem( SID_FORMATPAINTBRUSH, bHasPaintBrush ) );
+}
+
+ScDrawView* ScDrawShell::GetDrawView()
+{
+ return rViewData.GetView()->GetScDrawView();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drformsh.cxx b/sc/source/ui/drawfunc/drformsh.cxx
new file mode 100644
index 000000000..b91e08646
--- /dev/null
+++ b/sc/source/ui/drawfunc/drformsh.cxx
@@ -0,0 +1,55 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+#include <sfx2/msg.hxx>
+#include <sfx2/toolbarids.hxx>
+#include <sfx2/shell.hxx>
+
+#include <drawsh.hxx>
+#include <drformsh.hxx>
+#include <vcl/EnumContext.hxx>
+
+#define ShellClass_ScDrawFormShell
+#include <scslots.hxx>
+
+SFX_IMPL_INTERFACE(ScDrawFormShell, ScDrawShell)
+
+void ScDrawFormShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
+ ToolbarId::Objectbar_Format);
+
+ GetStaticInterface()->RegisterPopupMenu("form");
+}
+
+
+ScDrawFormShell::ScDrawFormShell(ScViewData& rData) :
+ ScDrawShell(rData)
+{
+ SetName("DrawForm");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Form));
+}
+
+ScDrawFormShell::~ScDrawFormShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drtxtob.cxx b/sc/source/ui/drawfunc/drtxtob.cxx
new file mode 100644
index 000000000..12968c9d2
--- /dev/null
+++ b/sc/source/ui/drawfunc/drtxtob.cxx
@@ -0,0 +1,1238 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/string.hxx>
+#include <scitems.hxx>
+
+#include <i18nutil/transliteration.hxx>
+#include <editeng/adjustitem.hxx>
+#include <svx/clipfmtitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/urlfieldhelper.hxx>
+#include <svx/hlnkitem.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/sdooitm.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/writingmodeitem.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svtools/cliplistener.hxx>
+#include <vcl/transfer.hxx>
+#include <svl/stritem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/languageoptions.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+
+#include <svx/svxdlg.hxx>
+#include <vcl/EnumContext.hxx>
+#include <vcl/unohelp2.hxx>
+
+#include <sc.hrc>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <scmod.hxx>
+#include <drtxtob.hxx>
+#include <viewdata.hxx>
+#include <document.hxx>
+#include <drawview.hxx>
+#include <viewutil.hxx>
+#include <tabvwsh.hxx>
+#include <gridwin.hxx>
+
+#define ShellClass_ScDrawTextObjectBar
+#include <scslots.hxx>
+
+using namespace ::com::sun::star;
+
+SFX_IMPL_INTERFACE(ScDrawTextObjectBar, SfxShell)
+
+void ScDrawTextObjectBar::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
+ ToolbarId::Text_Toolbox_Sc);
+
+ GetStaticInterface()->RegisterPopupMenu("drawtext");
+
+ GetStaticInterface()->RegisterChildWindow(ScGetFontWorkId());
+}
+
+
+// disable not wanted accelerators
+
+void ScDrawTextObjectBar::StateDisableItems( SfxItemSet &rSet )
+{
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+}
+
+ScDrawTextObjectBar::ScDrawTextObjectBar(ScViewData& rData) :
+ SfxShell(rData.GetViewShell()),
+ mrViewData(rData),
+ bPastePossible(false)
+{
+ SetPool( mrViewData.GetScDrawView()->GetDefaultAttr().GetPool() );
+
+ // At the switching-over the UndoManager is changed to edit mode
+ SfxUndoManager* pMgr = mrViewData.GetSfxDocShell()->GetUndoManager();
+ SetUndoManager( pMgr );
+ if ( !mrViewData.GetDocument().IsUndoEnabled() )
+ {
+ pMgr->SetMaxUndoActionCount( 0 );
+ }
+
+ SetName("DrawText");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::DrawText));
+}
+
+ScDrawTextObjectBar::~ScDrawTextObjectBar()
+{
+ if ( mxClipEvtLstnr.is() )
+ {
+ mxClipEvtLstnr->RemoveListener( mrViewData.GetActiveWin() );
+
+ // The listener may just now be waiting for the SolarMutex and call the link
+ // afterwards, in spite of RemoveListener. So the link has to be reset, too.
+ mxClipEvtLstnr->ClearCallbackLink();
+ }
+}
+
+// Functions
+
+void ScDrawTextObjectBar::Execute( SfxRequest &rReq )
+{
+ ScDrawView* pView = mrViewData.GetScDrawView();
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+ Outliner* pOutliner = pView->GetTextEditOutliner();
+
+ if (!pOutView || !pOutliner)
+ {
+ ExecuteGlobal( rReq ); // on whole objects
+ return;
+ }
+
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case SID_COPY:
+ pOutView->Copy();
+ break;
+
+ case SID_CUT:
+ pOutView->Cut();
+ break;
+
+ case SID_PASTE:
+ pOutView->PasteSpecial();
+ break;
+
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ {
+ SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
+ const SfxPoolItem* pItem;
+ if ( pReqArgs && pReqArgs->GetItemState(nSlot, true, &pItem) == SfxItemState::SET )
+ if (auto pIntItem = dynamic_cast<const SfxUInt32Item*>( pItem))
+ nFormat = static_cast<SotClipboardFormatId>(pIntItem->GetValue());
+
+ if ( nFormat != SotClipboardFormatId::NONE )
+ {
+ if (nFormat == SotClipboardFormatId::STRING)
+ pOutView->Paste();
+ else
+ pOutView->PasteSpecial();
+ }
+ }
+ break;
+
+ case SID_PASTE_SPECIAL:
+ ExecutePasteContents( rReq );
+ break;
+
+ case SID_PASTE_UNFORMATTED:
+ pOutView->Paste();
+ break;
+
+ case SID_SELECTALL:
+ {
+ sal_Int32 nCount = pOutliner->GetParagraphCount();
+ ESelection aSel( 0,0,nCount,0 );
+ pOutView->SetSelection( aSel );
+ }
+ break;
+
+ case SID_CHARMAP:
+ {
+ const SvxFontItem& rItem = pOutView->GetAttribs().Get(EE_CHAR_FONTINFO);
+
+ OUString aString;
+ std::shared_ptr<SvxFontItem> aNewItem(std::make_shared<SvxFontItem>(EE_CHAR_FONTINFO));
+
+ const SfxItemSet *pArgs = rReq.GetArgs();
+ const SfxPoolItem* pItem = nullptr;
+ if( pArgs )
+ pArgs->GetItemState(SID_CHARMAP, false, &pItem);
+
+ if ( pItem )
+ {
+ aString = static_cast<const SfxStringItem*>(pItem)->GetValue();
+ const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false);
+ if ( pFontItem )
+ {
+ const OUString& aFontName(pFontItem->GetValue());
+ vcl::Font aFont(aFontName, Size(1,1)); // Size only because of CTOR
+ aNewItem = std::make_shared<SvxFontItem>(
+ aFont.GetFamilyType(), aFont.GetFamilyName(),
+ aFont.GetStyleName(), aFont.GetPitch(),
+ aFont.GetCharSet(), ATTR_FONT);
+ }
+ else
+ {
+ aNewItem.reset(rItem.Clone());
+ }
+ }
+ else
+ ScViewUtil::ExecuteCharMap(rItem, *mrViewData.GetViewShell());
+
+ if ( !aString.isEmpty() )
+ {
+ SfxItemSet aSet( pOutliner->GetEmptyItemSet() );
+ // tdf#125054
+ // checked against original, indeed aNewItem looks as if it can have
+ // either WhichID EE_CHAR_FONTINFO or ATTR_FONT when it was reset
+ // above, original uses '= SvxFontItem(..., ATTR_FONT).
+ // BUT beware: the operator=() did not copy the WhichID when resetting,
+ // so it indeed has WhichID of EE_CHAR_FONTINFO despite copying an Item
+ // that was constructed using ATTR_FONT as WhichID (!)
+ aSet.Put( *aNewItem, EE_CHAR_FONTINFO );
+
+ // If nothing is selected, then SetAttribs of the View selects a word
+ pOutView->GetOutliner()->QuickSetAttribs( aSet, pOutView->GetSelection() );
+ pOutView->InsertText(aString);
+ }
+
+ Invalidate( SID_ATTR_CHAR_FONT );
+ }
+ break;
+
+ case SID_HYPERLINK_SETLINK:
+ if( pReqArgs )
+ {
+ if ( const SvxHyperlinkItem* pHyper = pReqArgs->GetItemIfSet( SID_HYPERLINK_SETLINK) )
+ {
+ const OUString& rName = pHyper->GetName();
+ const OUString& rURL = pHyper->GetURL();
+ const OUString& rTarget = pHyper->GetTargetFrame();
+ SvxLinkInsertMode eMode = pHyper->GetInsertMode();
+
+ bool bDone = false;
+ if (eMode == HLINK_DEFAULT || eMode == HLINK_FIELD)
+ {
+ pOutView->SelectFieldAtCursor();
+
+ // insert new field
+ SvxURLField aURLField( rURL, rName, SvxURLFormat::Repr );
+ aURLField.SetTargetFrame( rTarget );
+ SvxFieldItem aURLItem( aURLField, EE_FEATURE_FIELD );
+ pOutView->InsertField( aURLItem );
+
+ bDone = true;
+ }
+
+ if (!bDone)
+ ExecuteGlobal( rReq ); // normal at View
+
+ // If "text" is received by InsertURL of ViewShell, then the DrawShell is turned off !!!
+ }
+ }
+ break;
+
+ case SID_OPEN_HYPERLINK:
+ if (const SvxFieldData* pField = pOutView->GetFieldAtCursor())
+ {
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
+ {
+ ScGlobal::OpenURL(pURLField->GetURL(), pURLField->GetTargetFrame(), true);
+ }
+ }
+ break;
+
+ case SID_EDIT_HYPERLINK:
+ {
+ // Ensure the field is selected first
+ pOutView->SelectFieldAtCursor();
+ mrViewData.GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(SID_HYPERLINK_DIALOG);
+ }
+ break;
+
+ case SID_COPY_HYPERLINK_LOCATION:
+ {
+ const SvxFieldData* pField = pOutView->GetFieldAtCursor();
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
+ {
+ uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
+ = pOutView->GetWindow()->GetClipboard();
+ vcl::unohelper::TextDataObject::CopyStringTo(pURLField->GetURL(), xClipboard);
+ }
+ }
+ break;
+
+ case SID_REMOVE_HYPERLINK:
+ {
+ // Ensure the field is selected first
+ URLFieldHelper::RemoveURLField(pOutView->GetEditView());
+ }
+ break;
+
+ case SID_ENABLE_HYPHENATION:
+ case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
+ case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
+ pView->ScEndTextEdit(); // end text edit before switching direction
+ ExecuteGlobal( rReq );
+ // restore consistent state between shells and functions:
+ mrViewData.GetDispatcher().Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
+ break;
+
+ case SID_THES:
+ {
+ OUString aReplaceText;
+ const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
+ if (pItem2)
+ aReplaceText = pItem2->GetValue();
+ if (!aReplaceText.isEmpty())
+ ReplaceTextWithSynonym( pOutView->GetEditView(), aReplaceText );
+ }
+ break;
+
+ case SID_THESAURUS:
+ {
+ pOutView->StartThesaurus(rReq.GetFrameWeld());
+ }
+ break;
+ }
+}
+
+void ScDrawTextObjectBar::GetState( SfxItemSet& rSet )
+{
+ SfxViewFrame* pViewFrm = mrViewData.GetViewShell()->GetViewFrame();
+ bool bHasFontWork = pViewFrm->HasChildWindow(SID_FONTWORK);
+ bool bDisableFontWork = false;
+
+ if (IsNoteEdit())
+ {
+ // #i21255# notes now support rich text formatting (#i74140# but not fontwork)
+ bDisableFontWork = true;
+ }
+
+ if ( bDisableFontWork )
+ rSet.DisableItem( SID_FONTWORK );
+ else
+ rSet.Put(SfxBoolItem(SID_FONTWORK, bHasFontWork));
+
+ if ( rSet.GetItemState( SID_HYPERLINK_GETLINK ) != SfxItemState::UNKNOWN )
+ {
+ SvxHyperlinkItem aHLinkItem;
+ SdrView* pView = mrViewData.GetScDrawView();
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+ if ( pOutView )
+ {
+ bool bField = false;
+ const SvxFieldData* pField = pOutView->GetFieldAtCursor();
+ if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
+ {
+ aHLinkItem.SetName( pURLField->GetRepresentation() );
+ aHLinkItem.SetURL( pURLField->GetURL() );
+ aHLinkItem.SetTargetFrame( pURLField->GetTargetFrame() );
+ bField = true;
+ }
+
+ if (!bField)
+ {
+ // use selected text as name for urls
+ OUString sReturn = pOutView->GetSelected();
+ sal_Int32 nLen = std::min<sal_Int32>(sReturn.getLength(), 255);
+ sReturn = sReturn.copy(0, nLen);
+ aHLinkItem.SetName(comphelper::string::stripEnd(sReturn, ' '));
+ }
+ }
+ rSet.Put(aHLinkItem);
+ }
+
+ if (rSet.GetItemState(SID_OPEN_HYPERLINK) != SfxItemState::UNKNOWN
+ || rSet.GetItemState(SID_EDIT_HYPERLINK) != SfxItemState::UNKNOWN
+ || rSet.GetItemState(SID_COPY_HYPERLINK_LOCATION) != SfxItemState::UNKNOWN
+ || rSet.GetItemState(SID_REMOVE_HYPERLINK) != SfxItemState::UNKNOWN)
+ {
+ SdrView* pView = mrViewData.GetScDrawView();
+ if( !URLFieldHelper::IsCursorAtURLField(pView->GetTextEditOutlinerView()) )
+ {
+ rSet.DisableItem( SID_OPEN_HYPERLINK );
+ rSet.DisableItem( SID_EDIT_HYPERLINK );
+ rSet.DisableItem( SID_COPY_HYPERLINK_LOCATION );
+ rSet.DisableItem( SID_REMOVE_HYPERLINK );
+ }
+ }
+
+ if( rSet.GetItemState( SID_TRANSLITERATE_HALFWIDTH ) != SfxItemState::UNKNOWN )
+ ScViewUtil::HideDisabledSlot( rSet, pViewFrm->GetBindings(), SID_TRANSLITERATE_HALFWIDTH );
+ if( rSet.GetItemState( SID_TRANSLITERATE_FULLWIDTH ) != SfxItemState::UNKNOWN )
+ ScViewUtil::HideDisabledSlot( rSet, pViewFrm->GetBindings(), SID_TRANSLITERATE_FULLWIDTH );
+ if( rSet.GetItemState( SID_TRANSLITERATE_HIRAGANA ) != SfxItemState::UNKNOWN )
+ ScViewUtil::HideDisabledSlot( rSet, pViewFrm->GetBindings(), SID_TRANSLITERATE_HIRAGANA );
+ if( rSet.GetItemState( SID_TRANSLITERATE_KATAKANA ) != SfxItemState::UNKNOWN )
+ ScViewUtil::HideDisabledSlot( rSet, pViewFrm->GetBindings(), SID_TRANSLITERATE_KATAKANA );
+
+ if ( rSet.GetItemState( SID_ENABLE_HYPHENATION ) != SfxItemState::UNKNOWN )
+ {
+ SdrView* pView = mrViewData.GetScDrawView();
+ SfxItemSet aAttrs( pView->GetModel()->GetItemPool() );
+ pView->GetAttributes( aAttrs );
+ if( aAttrs.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT )
+ {
+ bool bValue = aAttrs.Get( EE_PARA_HYPHENATE ).GetValue();
+ rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) );
+ }
+ }
+
+ if ( rSet.GetItemState( SID_THES ) != SfxItemState::UNKNOWN ||
+ rSet.GetItemState( SID_THESAURUS ) != SfxItemState::UNKNOWN )
+ {
+ SdrView * pView = mrViewData.GetScDrawView();
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+
+ OUString aStatusVal;
+ LanguageType nLang = LANGUAGE_NONE;
+ bool bIsLookUpWord = false;
+ if ( pOutView )
+ {
+ EditView& rEditView = pOutView->GetEditView();
+ bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, rEditView );
+ }
+ rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
+
+ // disable thesaurus main menu and context menu entry if there is nothing to look up
+ bool bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang );
+ if (!bIsLookUpWord || !bCanDoThesaurus)
+ rSet.DisableItem( SID_THES );
+ if (!bCanDoThesaurus)
+ rSet.DisableItem( SID_THESAURUS );
+ }
+
+ if (GetObjectShell()->isContentExtractionLocked())
+ {
+ rSet.DisableItem(SID_COPY);
+ rSet.DisableItem(SID_CUT);
+ }
+}
+
+IMPL_LINK( ScDrawTextObjectBar, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
+{
+ bPastePossible = ( pDataHelper->HasFormat( SotClipboardFormatId::STRING ) || pDataHelper->HasFormat( SotClipboardFormatId::RTF )
+ || pDataHelper->HasFormat( SotClipboardFormatId::RICHTEXT ) );
+
+ SfxBindings& rBindings = mrViewData.GetBindings();
+ rBindings.Invalidate( SID_PASTE );
+ rBindings.Invalidate( SID_PASTE_SPECIAL );
+ rBindings.Invalidate( SID_PASTE_UNFORMATTED );
+ rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
+}
+
+void ScDrawTextObjectBar::GetClipState( SfxItemSet& rSet )
+{
+ SdrView* pView = mrViewData.GetScDrawView();
+ if ( !pView->GetTextEditOutlinerView() )
+ {
+ GetGlobalClipState( rSet );
+ return;
+ }
+
+ if ( !mxClipEvtLstnr.is() )
+ {
+ // create listener
+ mxClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScDrawTextObjectBar, ClipboardChanged ) );
+ vcl::Window* pWin = mrViewData.GetActiveWin();
+ mxClipEvtLstnr->AddListener( pWin );
+
+ // get initial state
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mrViewData.GetActiveWin() ) );
+ bPastePossible = ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) || aDataHelper.HasFormat( SotClipboardFormatId::RTF )
+ || aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) );
+ }
+
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while (nWhich)
+ {
+ switch (nWhich)
+ {
+ case SID_PASTE:
+ case SID_PASTE_SPECIAL:
+ case SID_PASTE_UNFORMATTED:
+ if( !bPastePossible )
+ rSet.DisableItem( nWhich );
+ break;
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ if ( bPastePossible )
+ {
+ SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard( mrViewData.GetActiveWin() ) );
+
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::STRING );
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::RTF );
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) )
+ aFormats.AddClipbrdFormat( SotClipboardFormatId::RICHTEXT );
+
+ rSet.Put( aFormats );
+ }
+ else
+ rSet.DisableItem( nWhich );
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+// Attributes
+
+void ScDrawTextObjectBar::ExecuteToggle( SfxRequest &rReq )
+{
+ // Underline
+
+ SdrView* pView = mrViewData.GetScDrawView();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+
+ SfxItemSet aSet( pView->GetDefaultAttr() );
+
+ SfxItemSet aViewAttr(pView->GetModel()->GetItemPool());
+ pView->GetAttributes(aViewAttr);
+
+ // Underline
+ FontLineStyle eOld = aViewAttr.Get(EE_CHAR_UNDERLINE).GetLineStyle();
+ FontLineStyle eNew = eOld;
+ switch (nSlot)
+ {
+ case SID_ULINE_VAL_NONE:
+ eNew = LINESTYLE_NONE;
+ break;
+ case SID_ULINE_VAL_SINGLE:
+ eNew = ( eOld == LINESTYLE_SINGLE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
+ break;
+ case SID_ULINE_VAL_DOUBLE:
+ eNew = ( eOld == LINESTYLE_DOUBLE ) ? LINESTYLE_NONE : LINESTYLE_DOUBLE;
+ break;
+ case SID_ULINE_VAL_DOTTED:
+ eNew = ( eOld == LINESTYLE_DOTTED ) ? LINESTYLE_NONE : LINESTYLE_DOTTED;
+ break;
+ default:
+ break;
+ }
+ aSet.Put( SvxUnderlineItem( eNew, EE_CHAR_UNDERLINE ) );
+
+ pView->SetAttributes( aSet );
+ rReq.Done();
+ mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
+}
+
+static void lcl_RemoveFields( OutlinerView& rOutView )
+{
+ //! Outliner should have RemoveFields with a selection
+
+ Outliner* pOutliner = rOutView.GetOutliner();
+ if (!pOutliner) return;
+
+ ESelection aOldSel = rOutView.GetSelection();
+ ESelection aSel = aOldSel;
+ aSel.Adjust();
+ sal_Int32 nNewEnd = aSel.nEndPos;
+
+ bool bUpdate = pOutliner->IsUpdateLayout();
+ bool bChanged = false;
+
+ //! GetPortions and GetAttribs should be const!
+ EditEngine& rEditEng = const_cast<EditEngine&>(pOutliner->GetEditEngine());
+
+ sal_Int32 nParCount = pOutliner->GetParagraphCount();
+ for (sal_Int32 nPar=0; nPar<nParCount; nPar++)
+ if ( nPar >= aSel.nStartPara && nPar <= aSel.nEndPara )
+ {
+ std::vector<sal_Int32> aPortions;
+ rEditEng.GetPortions( nPar, aPortions );
+
+ for ( size_t nPos = aPortions.size(); nPos; )
+ {
+ --nPos;
+ sal_Int32 nEnd = aPortions[ nPos ];
+ sal_Int32 nStart = nPos ? aPortions[ nPos - 1 ] : 0;
+ // fields are single characters
+ if ( nEnd == nStart+1 &&
+ ( nPar > aSel.nStartPara || nStart >= aSel.nStartPos ) &&
+ ( nPar < aSel.nEndPara || nEnd <= aSel.nEndPos ) )
+ {
+ ESelection aFieldSel( nPar, nStart, nPar, nEnd );
+ SfxItemSet aSet = rEditEng.GetAttribs( aFieldSel );
+ if ( aSet.GetItemState( EE_FEATURE_FIELD ) == SfxItemState::SET )
+ {
+ if (!bChanged)
+ {
+ if (bUpdate)
+ pOutliner->SetUpdateLayout( false );
+ OUString aName = ScResId( STR_UNDO_DELETECONTENTS );
+ ViewShellId nViewShellId(-1);
+ if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
+ nViewShellId = pViewSh->GetViewShellId();
+ pOutliner->GetUndoManager().EnterListAction( aName, aName, 0, nViewShellId );
+ bChanged = true;
+ }
+
+ OUString aFieldText = rEditEng.GetText( aFieldSel );
+ pOutliner->QuickInsertText( aFieldText, aFieldSel );
+ if ( nPar == aSel.nEndPara )
+ {
+ nNewEnd = nNewEnd + aFieldText.getLength();
+ --nNewEnd;
+ }
+ }
+ }
+ }
+ }
+
+ if (bUpdate && bChanged)
+ {
+ pOutliner->GetUndoManager().LeaveListAction();
+ pOutliner->SetUpdateLayout( true );
+ }
+
+ if ( aOldSel == aSel ) // aSel is adjusted
+ aOldSel.nEndPos = nNewEnd;
+ else
+ aOldSel.nStartPos = nNewEnd; // if aOldSel is backwards
+ rOutView.SetSelection( aOldSel );
+}
+
+void ScDrawTextObjectBar::ExecuteAttr( SfxRequest &rReq )
+{
+ SdrView* pView = mrViewData.GetScDrawView();
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ sal_uInt16 nSlot = rReq.GetSlot();
+
+ SfxItemSet aEditAttr( pView->GetModel()->GetItemPool() );
+ pView->GetAttributes( aEditAttr );
+ SfxItemSet aNewAttr( *aEditAttr.GetPool(), aEditAttr.GetRanges() );
+
+ bool bSet = true;
+ switch ( nSlot )
+ {
+ case SID_ALIGNLEFT:
+ case SID_ALIGN_ANY_LEFT:
+ case SID_ATTR_PARA_ADJUST_LEFT:
+ aNewAttr.Put( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
+ break;
+
+ case SID_ALIGNCENTERHOR:
+ case SID_ALIGN_ANY_HCENTER:
+ case SID_ATTR_PARA_ADJUST_CENTER:
+ aNewAttr.Put( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) );
+ break;
+
+ case SID_ALIGNRIGHT:
+ case SID_ALIGN_ANY_RIGHT:
+ case SID_ATTR_PARA_ADJUST_RIGHT:
+ aNewAttr.Put( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
+ break;
+
+ case SID_ALIGNBLOCK:
+ case SID_ALIGN_ANY_JUSTIFIED:
+ case SID_ATTR_PARA_ADJUST_BLOCK:
+ aNewAttr.Put( SvxAdjustItem( SvxAdjust::Block, EE_PARA_JUST ) );
+ break;
+
+ case SID_ATTR_PARA_LINESPACE_10:
+ {
+ SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL );
+ aItem.SetPropLineSpace( 100 );
+ aNewAttr.Put( aItem );
+ }
+ break;
+
+ case SID_ATTR_PARA_LINESPACE_15:
+ {
+ SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL );
+ aItem.SetPropLineSpace( 150 );
+ aNewAttr.Put( aItem );
+ }
+ break;
+
+ case SID_ATTR_PARA_LINESPACE_20:
+ {
+ SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL );
+ aItem.SetPropLineSpace( 200 );
+ aNewAttr.Put( aItem );
+ }
+ break;
+
+ case SID_SET_SUPER_SCRIPT:
+ {
+ SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aEditAttr.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+
+ if( eEsc == SvxEscapement::Superscript )
+ aItem.SetEscapement( SvxEscapement::Off );
+ else
+ aItem.SetEscapement( SvxEscapement::Superscript );
+ aNewAttr.Put( aItem );
+ }
+ break;
+
+ case SID_SET_SUB_SCRIPT:
+ {
+ SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aEditAttr.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+
+ if( eEsc == SvxEscapement::Subscript )
+ aItem.SetEscapement( SvxEscapement::Off );
+ else
+ aItem.SetEscapement( SvxEscapement::Subscript );
+ aNewAttr.Put( aItem );
+ }
+ break;
+
+ case SID_TABLE_VERT_NONE:
+ case SID_TABLE_VERT_CENTER:
+ case SID_TABLE_VERT_BOTTOM:
+ {
+ SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_TOP;
+ if (nSlot == SID_TABLE_VERT_CENTER)
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ else if (nSlot == SID_TABLE_VERT_BOTTOM)
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ aNewAttr.Put(SdrTextVertAdjustItem(eTVA));
+ }
+ break;
+
+ case SID_PARASPACE_INCREASE:
+ case SID_PARASPACE_DECREASE:
+ {
+ SvxULSpaceItem aULSpace( aEditAttr.Get( EE_PARA_ULSPACE ) );
+ sal_uInt16 nUpper = aULSpace.GetUpper();
+ sal_uInt16 nLower = aULSpace.GetLower();
+
+ if ( nSlot == SID_PARASPACE_INCREASE )
+ {
+ nUpper += 100;
+ nLower += 100;
+ }
+ else
+ {
+ nUpper = std::max< sal_Int16 >( nUpper - 100, 0 );
+ nLower = std::max< sal_Int16 >( nLower - 100, 0 );
+ }
+
+ aULSpace.SetUpper( nUpper );
+ aULSpace.SetLower( nLower );
+ aNewAttr.Put( aULSpace );
+ }
+ break;
+
+ default:
+ bSet = false;
+ }
+
+ bool bDone = true;
+ bool bArgsInReq = ( pArgs != nullptr );
+
+ if ( !bArgsInReq )
+ {
+ switch ( nSlot )
+ {
+ case SID_TEXT_STANDARD: // delete hard text attributes
+ {
+ OutlinerView* pOutView = pView->IsTextEdit() ?
+ pView->GetTextEditOutlinerView() : nullptr;
+ if ( pOutView )
+ pOutView->Paint( tools::Rectangle() );
+
+ SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aEmptyAttr( *aEditAttr.GetPool() );
+ pView->SetAttributes( aEmptyAttr, true );
+
+ if ( pOutView )
+ {
+ lcl_RemoveFields( *pOutView );
+ pOutView->ShowCursor();
+ }
+
+ rReq.Done( aEmptyAttr );
+ mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
+ bDone = false; // already happened here
+ }
+ break;
+
+ case SID_GROW_FONT_SIZE:
+ case SID_SHRINK_FONT_SIZE:
+ {
+ OutlinerView* pOutView = pView->IsTextEdit() ?
+ pView->GetTextEditOutlinerView() : nullptr;
+ if ( pOutView )
+ {
+ if (SfxObjectShell* pObjSh = SfxObjectShell::Current())
+ {
+ const SvxFontListItem* pFontListItem = static_cast< const SvxFontListItem* >
+ ( pObjSh->GetItem( SID_ATTR_CHAR_FONTLIST ) );
+ const FontList* pFontList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
+ pOutView->GetEditView().ChangeFontSize( nSlot == SID_GROW_FONT_SIZE, pFontList );
+ mrViewData.GetBindings().Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
+ }
+ bDone = false;
+ }
+ }
+ break;
+
+ case SID_CHAR_DLG_EFFECT:
+ case SID_CHAR_DLG: // dialog button
+ case SID_ATTR_CHAR_FONT: // Controller not shown
+ case SID_ATTR_CHAR_FONTHEIGHT:
+ bDone = ExecuteCharDlg( aEditAttr, aNewAttr , nSlot);
+ break;
+
+ case SID_PARA_DLG:
+ bDone = ExecuteParaDlg( aEditAttr, aNewAttr );
+ break;
+
+ case SID_ATTR_CHAR_WEIGHT:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_WEIGHT ) );
+ break;
+
+ case SID_ATTR_CHAR_POSTURE:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_ITALIC ) );
+ break;
+
+ case SID_ATTR_CHAR_UNDERLINE:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_UNDERLINE ) );
+ break;
+
+ case SID_ATTR_CHAR_OVERLINE:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_OVERLINE ) );
+ break;
+
+ case SID_ATTR_CHAR_CONTOUR:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_OUTLINE ) );
+ break;
+
+ case SID_ATTR_CHAR_SHADOWED:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_SHADOW ) );
+ break;
+
+ case SID_ATTR_CHAR_STRIKEOUT:
+ aNewAttr.Put( aEditAttr.Get( EE_CHAR_STRIKEOUT ) );
+ break;
+
+ case SID_DRAWTEXT_ATTR_DLG:
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateTextTabDialog(mrViewData.GetDialogParent(), &aEditAttr, pView));
+
+ bDone = ( RET_OK == pDlg->Execute() );
+
+ if ( bDone )
+ aNewAttr.Put( *pDlg->GetOutputItemSet() );
+
+ pDlg.disposeAndClear();
+
+ SfxBindings& rBindings = mrViewData.GetBindings();
+ rBindings.Invalidate( SID_TABLE_VERT_NONE );
+ rBindings.Invalidate( SID_TABLE_VERT_CENTER );
+ rBindings.Invalidate( SID_TABLE_VERT_BOTTOM );
+ }
+ break;
+ }
+ }
+
+ if ( bSet || bDone )
+ {
+ rReq.Done( aNewAttr );
+ pArgs = rReq.GetArgs();
+ }
+
+ if ( !pArgs )
+ return;
+
+ if ( bArgsInReq &&
+ ( nSlot == SID_ATTR_CHAR_FONT || nSlot == SID_ATTR_CHAR_FONTHEIGHT ||
+ nSlot == SID_ATTR_CHAR_WEIGHT || nSlot == SID_ATTR_CHAR_POSTURE ) )
+ {
+ // font items from toolbox controller have to be applied for the right script type
+
+ // #i78017 establish the same behaviour as in Writer
+ SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
+ if (nSlot == SID_ATTR_CHAR_FONT)
+ nScript = pView->GetScriptType();
+
+ SfxItemPool& rPool = GetPool();
+ SvxScriptSetItem aSetItem( nSlot, rPool );
+ sal_uInt16 nWhich = rPool.GetWhich( nSlot );
+ aSetItem.PutItemForScriptType( nScript, pArgs->Get( nWhich ) );
+
+ pView->SetAttributes( aSetItem.GetItemSet() );
+ }
+ else if( nSlot == SID_ATTR_PARA_LRSPACE )
+ {
+ sal_uInt16 nId = SID_ATTR_PARA_LRSPACE;
+ const SvxLRSpaceItem& rItem = static_cast<const SvxLRSpaceItem&>(
+ pArgs->Get( nId ));
+ SfxItemSetFixed<EE_PARA_LRSPACE, EE_PARA_LRSPACE> aAttr( GetPool() );
+ nId = EE_PARA_LRSPACE;
+ SvxLRSpaceItem aLRSpaceItem( rItem.GetLeft(),
+ rItem.GetRight(), rItem.GetTextLeft(),
+ rItem.GetTextFirstLineOffset(), nId );
+ aAttr.Put( aLRSpaceItem );
+ pView->SetAttributes( aAttr );
+ }
+ else if( nSlot == SID_ATTR_PARA_LINESPACE )
+ {
+ SvxLineSpacingItem aLineSpaceItem = static_cast<const SvxLineSpacingItem&>(pArgs->Get(
+ GetPool().GetWhich(nSlot)));
+ SfxItemSetFixed<EE_PARA_SBL, EE_PARA_SBL> aAttr( GetPool() );
+ aAttr.Put( aLineSpaceItem );
+ pView->SetAttributes( aAttr );
+ }
+ else if( nSlot == SID_ATTR_PARA_ULSPACE )
+ {
+ SvxULSpaceItem aULSpaceItem = static_cast<const SvxULSpaceItem&>(pArgs->Get(
+ GetPool().GetWhich(nSlot)));
+ SfxItemSetFixed<EE_PARA_ULSPACE, EE_PARA_ULSPACE> aAttr( GetPool() );
+ aULSpaceItem.SetWhich(EE_PARA_ULSPACE);
+ aAttr.Put( aULSpaceItem );
+ pView->SetAttributes( aAttr );
+ }
+ else
+ {
+ // use args directly
+ pView->SetAttributes( *pArgs );
+ }
+ mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
+}
+
+void ScDrawTextObjectBar::GetAttrState( SfxItemSet& rDestSet )
+{
+ if ( IsNoteEdit() )
+ {
+ // issue 21255 - Notes now support rich text formatting.
+ }
+
+ bool bDisableCTLFont = !SvtCTLOptions().IsCTLFontEnabled();
+ bool bDisableVerticalText = !SvtCJKOptions::IsVerticalTextEnabled();
+
+ SdrView* pView = mrViewData.GetScDrawView();
+ SfxItemSet aAttrSet(pView->GetModel()->GetItemPool());
+ pView->GetAttributes(aAttrSet);
+
+ // direct attributes
+
+ rDestSet.Put( aAttrSet );
+
+ // choose font info according to selection script type
+
+ SvtScriptType nScript = pView->GetScriptType();
+
+ // #i55929# input-language-dependent script type (depends on input language if nothing selected)
+ SvtScriptType nInputScript = nScript;
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+ if (pOutView && !pOutView->GetSelection().HasRange())
+ {
+ LanguageType nInputLang = mrViewData.GetActiveWin()->GetInputLanguage();
+ if (nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM)
+ nInputScript = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang );
+ }
+
+ // #i55929# according to spec, nInputScript is used for font and font height only
+ if ( rDestSet.GetItemState( EE_CHAR_FONTINFO ) != SfxItemState::UNKNOWN )
+ ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_FONTINFO, nInputScript );
+ if ( rDestSet.GetItemState( EE_CHAR_FONTHEIGHT ) != SfxItemState::UNKNOWN )
+ ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_FONTHEIGHT, nInputScript );
+ if ( rDestSet.GetItemState( EE_CHAR_WEIGHT ) != SfxItemState::UNKNOWN )
+ ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_WEIGHT, nScript );
+ if ( rDestSet.GetItemState( EE_CHAR_ITALIC ) != SfxItemState::UNKNOWN )
+ ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_ITALIC, nScript );
+ // Alignment
+
+ SvxAdjust eAdj = aAttrSet.Get(EE_PARA_JUST).GetAdjust();
+ switch( eAdj )
+ {
+ case SvxAdjust::Left:
+ {
+ rDestSet.Put( SfxBoolItem( SID_ALIGNLEFT, true ) );
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_LEFT, true ) );
+ }
+ break;
+ case SvxAdjust::Center:
+ {
+ rDestSet.Put( SfxBoolItem( SID_ALIGNCENTERHOR, true ) );
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_CENTER, true ) );
+ }
+ break;
+ case SvxAdjust::Right:
+ {
+ rDestSet.Put( SfxBoolItem( SID_ALIGNRIGHT, true ) );
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_RIGHT, true ) );
+ }
+ break;
+ case SvxAdjust::Block:
+ {
+ rDestSet.Put( SfxBoolItem( SID_ALIGNBLOCK, true ) );
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_BLOCK, true ) );
+ }
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ // pseudo slots for Format menu
+ rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_LEFT, eAdj == SvxAdjust::Left ) );
+ rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_HCENTER, eAdj == SvxAdjust::Center ) );
+ rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_RIGHT, eAdj == SvxAdjust::Right ) );
+ rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_JUSTIFIED, eAdj == SvxAdjust::Block ) );
+
+ SvxLRSpaceItem aLR = aAttrSet.Get( EE_PARA_LRSPACE );
+ aLR.SetWhich(SID_ATTR_PARA_LRSPACE);
+ rDestSet.Put(aLR);
+ Invalidate( SID_ATTR_PARA_LRSPACE );
+ SfxItemState eState = aAttrSet.GetItemState( EE_PARA_LRSPACE );
+ if ( eState == SfxItemState::DONTCARE )
+ rDestSet.InvalidateItem(SID_ATTR_PARA_LRSPACE);
+ //xuxu for Line Space
+ SvxLineSpacingItem aLineSP = aAttrSet.Get( EE_PARA_SBL );
+ aLineSP.SetWhich(SID_ATTR_PARA_LINESPACE);
+ rDestSet.Put(aLineSP);
+ Invalidate(SID_ATTR_PARA_LINESPACE);
+ eState = aAttrSet.GetItemState( EE_PARA_SBL );
+ if ( eState == SfxItemState::DONTCARE )
+ rDestSet.InvalidateItem(SID_ATTR_PARA_LINESPACE);
+ //xuxu for UL Space
+ SvxULSpaceItem aULSP = aAttrSet.Get( EE_PARA_ULSPACE );
+ aULSP.SetWhich(SID_ATTR_PARA_ULSPACE);
+ rDestSet.Put(aULSP);
+ Invalidate(SID_ATTR_PARA_ULSPACE);
+ Invalidate(SID_PARASPACE_INCREASE);
+ Invalidate(SID_PARASPACE_DECREASE);
+ eState = aAttrSet.GetItemState( EE_PARA_ULSPACE );
+ if( eState >= SfxItemState::DEFAULT )
+ {
+ if ( !aULSP.GetUpper() && !aULSP.GetLower() )
+ rDestSet.DisableItem( SID_PARASPACE_DECREASE );
+ }
+ else
+ {
+ rDestSet.DisableItem( SID_PARASPACE_INCREASE );
+ rDestSet.DisableItem( SID_PARASPACE_DECREASE );
+ rDestSet.InvalidateItem(SID_ATTR_PARA_ULSPACE);
+ }
+
+ // Line spacing
+
+ sal_uInt16 nLineSpace = aAttrSet.Get( EE_PARA_SBL ).GetPropLineSpace();
+ switch( nLineSpace )
+ {
+ case 100:
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LINESPACE_10, true ) );
+ break;
+ case 150:
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LINESPACE_15, true ) );
+ break;
+ case 200:
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LINESPACE_20, true ) );
+ break;
+ }
+
+ // super-/subscript
+ SvxEscapement eEsc = static_cast<SvxEscapement>(aAttrSet.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
+ rDestSet.Put(SfxBoolItem(SID_SET_SUPER_SCRIPT, eEsc == SvxEscapement::Superscript));
+ rDestSet.Put(SfxBoolItem(SID_SET_SUB_SCRIPT, eEsc == SvxEscapement::Subscript));
+
+ // Underline
+ eState = aAttrSet.GetItemState( EE_CHAR_UNDERLINE );
+ if ( eState == SfxItemState::DONTCARE )
+ {
+ rDestSet.InvalidateItem( SID_ULINE_VAL_NONE );
+ rDestSet.InvalidateItem( SID_ULINE_VAL_SINGLE );
+ rDestSet.InvalidateItem( SID_ULINE_VAL_DOUBLE );
+ rDestSet.InvalidateItem( SID_ULINE_VAL_DOTTED );
+ }
+ else
+ {
+ FontLineStyle eUnderline = aAttrSet.Get(EE_CHAR_UNDERLINE).GetLineStyle();
+ rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_SINGLE, eUnderline == LINESTYLE_SINGLE));
+ rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_DOUBLE, eUnderline == LINESTYLE_DOUBLE));
+ rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_DOTTED, eUnderline == LINESTYLE_DOTTED));
+ rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_NONE, eUnderline == LINESTYLE_NONE));
+ }
+
+ // horizontal / vertical
+
+ bool bLeftToRight = true;
+
+ SdrOutliner* pOutl = pView->GetTextEditOutliner();
+ if( pOutl )
+ {
+ if( pOutl->IsVertical() )
+ bLeftToRight = false;
+ }
+ else
+ bLeftToRight = aAttrSet.Get( SDRATTR_TEXTDIRECTION ).GetValue() == css::text::WritingMode_LR_TB;
+
+ if ( bDisableVerticalText )
+ {
+ rDestSet.DisableItem( SID_TEXTDIRECTION_LEFT_TO_RIGHT );
+ rDestSet.DisableItem( SID_TEXTDIRECTION_TOP_TO_BOTTOM );
+ }
+ else
+ {
+ rDestSet.Put( SfxBoolItem( SID_TEXTDIRECTION_LEFT_TO_RIGHT, bLeftToRight ) );
+ rDestSet.Put( SfxBoolItem( SID_TEXTDIRECTION_TOP_TO_BOTTOM, !bLeftToRight ) );
+ }
+
+ // left-to-right or right-to-left
+
+ if ( !bLeftToRight || bDisableCTLFont )
+ {
+ // disabled if vertical
+ rDestSet.DisableItem( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ rDestSet.DisableItem( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+ else if ( aAttrSet.GetItemState( EE_PARA_WRITINGDIR ) == SfxItemState::DONTCARE )
+ {
+ rDestSet.InvalidateItem( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ rDestSet.InvalidateItem( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ }
+ else
+ {
+ SvxFrameDirection eAttrDir = aAttrSet.Get( EE_PARA_WRITINGDIR ).GetValue();
+ if ( eAttrDir == SvxFrameDirection::Environment )
+ {
+ // get "environment" direction from page style
+ if ( mrViewData.GetDocument().GetEditTextDirection( mrViewData.GetTabNo() ) == EEHorizontalTextDirection::R2L )
+ eAttrDir = SvxFrameDirection::Horizontal_RL_TB;
+ else
+ eAttrDir = SvxFrameDirection::Horizontal_LR_TB;
+ }
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LEFT_TO_RIGHT, ( eAttrDir == SvxFrameDirection::Horizontal_LR_TB ) ) );
+ rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_RIGHT_TO_LEFT, ( eAttrDir == SvxFrameDirection::Horizontal_RL_TB ) ) );
+ }
+}
+
+void ScDrawTextObjectBar::ExecuteTrans( const SfxRequest& rReq )
+{
+ TransliterationFlags nType = ScViewUtil::GetTransliterationType( rReq.GetSlot() );
+ if ( nType == TransliterationFlags::NONE )
+ return;
+
+ ScDrawView* pView = mrViewData.GetScDrawView();
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+ if ( pOutView )
+ {
+ // change selected text in object
+ pOutView->TransliterateText( nType );
+ }
+ else
+ {
+ //! apply to whole objects?
+ }
+}
+
+void ScDrawTextObjectBar::GetStatePropPanelAttr(SfxItemSet &rSet)
+{
+ SfxWhichIter aIter( rSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ SdrView* pView = mrViewData.GetScDrawView();
+
+ SfxItemSet aEditAttr(pView->GetModel()->GetItemPool());
+ pView->GetAttributes(aEditAttr);
+ //SfxItemSet aAttrs( *aEditAttr.GetPool(), aEditAttr.GetRanges() );
+
+ while ( nWhich )
+ {
+ sal_uInt16 nSlotId = SfxItemPool::IsWhich(nWhich)
+ ? GetPool().GetSlotId(nWhich)
+ : nWhich;
+ switch ( nSlotId )
+ {
+ case SID_TABLE_VERT_NONE:
+ case SID_TABLE_VERT_CENTER:
+ case SID_TABLE_VERT_BOTTOM:
+ bool bContour = false;
+ SfxItemState eConState = aEditAttr.GetItemState( SDRATTR_TEXT_CONTOURFRAME );
+ if( eConState != SfxItemState::DONTCARE )
+ {
+ bContour = aEditAttr.Get( SDRATTR_TEXT_CONTOURFRAME ).GetValue();
+ }
+ if (bContour) break;
+
+ SfxItemState eVState = aEditAttr.GetItemState( SDRATTR_TEXT_VERTADJUST );
+ //SfxItemState eHState = aAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST );
+
+ //if(SfxItemState::DONTCARE != eVState && SfxItemState::DONTCARE != eHState)
+ if(SfxItemState::DONTCARE != eVState)
+ {
+ SdrTextVertAdjust eTVA = aEditAttr.Get(SDRATTR_TEXT_VERTADJUST).GetValue();
+ bool bSet = (nSlotId == SID_TABLE_VERT_NONE && eTVA == SDRTEXTVERTADJUST_TOP) ||
+ (nSlotId == SID_TABLE_VERT_CENTER && eTVA == SDRTEXTVERTADJUST_CENTER) ||
+ (nSlotId == SID_TABLE_VERT_BOTTOM && eTVA == SDRTEXTVERTADJUST_BOTTOM);
+ rSet.Put(SfxBoolItem(nSlotId, bSet));
+ }
+ else
+ {
+ rSet.Put(SfxBoolItem(nSlotId, false));
+ }
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drtxtob1.cxx b/sc/source/ui/drawfunc/drtxtob1.cxx
new file mode 100644
index 000000000..63dc62dae
--- /dev/null
+++ b/sc/source/ui/drawfunc/drtxtob1.cxx
@@ -0,0 +1,124 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/eeitem.hxx>
+
+#include <svx/svxdlg.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/editids.hrc>
+#include <svx/svxids.hrc>
+#include <vcl/transfer.hxx>
+
+#include <drtxtob.hxx>
+#include <drawview.hxx>
+#include <viewdata.hxx>
+#include <gridwin.hxx>
+
+#include <scabstdlg.hxx>
+
+bool ScDrawTextObjectBar::ExecuteCharDlg( const SfxItemSet& rArgs,
+ SfxItemSet& rOutSet , sal_uInt16 nSlot)
+{
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScCharDlg(
+ mrViewData.GetDialogParent(), &rArgs,
+ mrViewData.GetSfxDocShell(), true));
+ if (nSlot == SID_CHAR_DLG_EFFECT)
+ {
+ pDlg->SetCurPageId("fonteffects");
+ }
+ bool bRet = ( pDlg->Execute() == RET_OK );
+
+ if ( bRet )
+ {
+ const SfxItemSet* pNewAttrs = pDlg->GetOutputItemSet();
+ if ( pNewAttrs )
+ rOutSet.Put( *pNewAttrs );
+ }
+
+ return bRet;
+}
+
+bool ScDrawTextObjectBar::ExecuteParaDlg( const SfxItemSet& rArgs,
+ SfxItemSet& rOutSet )
+{
+ SfxItemPool* pArgPool = rArgs.GetPool();
+ SfxItemSetFixed<
+ EE_ITEMS_START, EE_ITEMS_END,
+ SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_WIDOWS> aNewAttr(*pArgPool);
+ aNewAttr.Put( rArgs );
+
+ // Values have been taken over once to show the dialog.
+ // Has to be changed
+ // aNewAttr.Put( SvxParaDlgLimitsItem( 567 * 50, 5670) );
+
+ aNewAttr.Put( SvxHyphenZoneItem( false, SID_ATTR_PARA_HYPHENZONE ) );
+ aNewAttr.Put( SvxFormatBreakItem( SvxBreak::NONE, SID_ATTR_PARA_PAGEBREAK ) );
+ aNewAttr.Put( SvxFormatSplitItem( true, SID_ATTR_PARA_SPLIT) );
+ aNewAttr.Put( SvxWidowsItem( 0, SID_ATTR_PARA_WIDOWS) );
+ aNewAttr.Put( SvxOrphansItem( 0, SID_ATTR_PARA_ORPHANS) );
+
+ ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
+
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScParagraphDlg(
+ mrViewData.GetDialogParent(), &aNewAttr));
+ bool bRet = ( pDlg->Execute() == RET_OK );
+
+ if ( bRet )
+ {
+ const SfxItemSet* pNewAttrs = pDlg->GetOutputItemSet();
+ if ( pNewAttrs )
+ rOutSet.Put( *pNewAttrs );
+ }
+
+ return bRet;
+}
+
+void ScDrawTextObjectBar::ExecutePasteContents( SfxRequest & /* rReq */ )
+{
+ SdrView* pView = mrViewData.GetScDrawView();
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(mrViewData.GetDialogParent()));
+
+ pDlg->Insert( SotClipboardFormatId::STRING, OUString() );
+ pDlg->Insert( SotClipboardFormatId::RTF, OUString() );
+ pDlg->Insert( SotClipboardFormatId::RICHTEXT, OUString() );
+
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mrViewData.GetActiveWin() ) );
+
+ SotClipboardFormatId nFormat = pDlg->GetFormat( aDataHelper.GetTransferable() );
+
+ //! test if outliner view is still valid
+
+ if (nFormat != SotClipboardFormatId::NONE)
+ {
+ if (nFormat == SotClipboardFormatId::STRING)
+ pOutView->Paste();
+ else
+ pOutView->PasteSpecial();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/drtxtob2.cxx b/sc/source/ui/drawfunc/drtxtob2.cxx
new file mode 100644
index 000000000..a5b4a7394
--- /dev/null
+++ b/sc/source/ui/drawfunc/drtxtob2.cxx
@@ -0,0 +1,229 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/adjustitem.hxx>
+#include <svx/fontwork.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/writingmodeitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/request.hxx>
+#include <svl/whiter.hxx>
+#include <svx/svdoashp.hxx>
+#include <sc.hrc>
+#include <drtxtob.hxx>
+#include <viewdata.hxx>
+#include <drawview.hxx>
+#include <tabvwsh.hxx>
+#include <drwlayer.hxx>
+
+sal_uInt16 ScGetFontWorkId()
+{
+ return SvxFontWorkChildWindow::GetChildWindowId();
+}
+
+bool ScDrawTextObjectBar::IsNoteEdit() const
+{
+ return ScDrawLayer::IsNoteCaption( mrViewData.GetView()->GetScDrawView()->GetTextEditObject() );
+}
+
+// if no text edited, functions like in drawsh
+
+void ScDrawTextObjectBar::ExecuteGlobal( SfxRequest &rReq )
+{
+ ScTabView* pTabView = mrViewData.GetView();
+ ScDrawView* pView = pTabView->GetScDrawView();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case SID_COPY:
+ pView->DoCopy();
+ break;
+
+ case SID_CUT:
+ pView->DoCut();
+ mrViewData.GetViewShell()->UpdateDrawShell();
+ break;
+
+ case SID_PASTE:
+ case SID_PASTE_SPECIAL:
+ case SID_PASTE_UNFORMATTED:
+ case SID_CLIPBOARD_FORMAT_ITEMS:
+ case SID_HYPERLINK_SETLINK:
+ {
+ // cell methods are at cell shell, which is not available if
+ // ScDrawTextObjectBar is active
+ //! move paste etc. to view shell?
+ }
+ break;
+
+ case SID_SELECTALL:
+ pView->MarkAll();
+ break;
+
+ case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
+ case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
+ {
+ SfxItemSetFixed<SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION> aAttr( pView->GetModel()->GetItemPool() );
+ aAttr.Put( SvxWritingModeItem(
+ nSlot == SID_TEXTDIRECTION_LEFT_TO_RIGHT ?
+ css::text::WritingMode_LR_TB : css::text::WritingMode_TB_RL,
+ SDRATTR_TEXTDIRECTION ) );
+ pView->SetAttributes( aAttr );
+ mrViewData.GetScDrawView()->InvalidateDrawTextAttrs(); // Bidi slots may be disabled
+ rReq.Done( aAttr );
+ }
+ break;
+
+ case SID_ENABLE_HYPHENATION:
+ {
+ const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(SID_ENABLE_HYPHENATION);
+ if( pItem )
+ {
+ SfxItemSetFixed<EE_PARA_HYPHENATE, EE_PARA_HYPHENATE> aSet( GetPool() );
+ bool bValue = pItem->GetValue();
+ aSet.Put( SfxBoolItem( EE_PARA_HYPHENATE, bValue ) );
+ pView->SetAttributes( aSet );
+ }
+ rReq.Done();
+ }
+ break;
+ }
+}
+
+void ScDrawTextObjectBar::GetGlobalClipState( SfxItemSet& rSet )
+{
+ // cell methods are at cell shell, which is not available if
+ // ScDrawTextObjectBar is active -> disable everything
+ //! move paste etc. to view shell?
+
+ SfxWhichIter aIter(rSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while (nWhich)
+ {
+ rSet.DisableItem( nWhich );
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void ScDrawTextObjectBar::ExecuteExtra( SfxRequest &rReq )
+{
+ ScTabView* pTabView = mrViewData.GetView();
+ ScDrawView* pView = pTabView->GetScDrawView();
+
+ sal_uInt16 nSlot = rReq.GetSlot();
+ switch ( nSlot )
+ {
+ case SID_FONTWORK:
+ {
+ sal_uInt16 nId = SvxFontWorkChildWindow::GetChildWindowId();
+ SfxViewFrame* pViewFrm = mrViewData.GetViewShell()->GetViewFrame();
+
+ if ( rReq.GetArgs() )
+ pViewFrm->SetChildWindow( nId,
+ static_cast<const SfxBoolItem&>(
+ (rReq.GetArgs()->Get(SID_FONTWORK))).
+ GetValue() );
+ else
+ pViewFrm->ToggleChildWindow( nId );
+
+ pViewFrm->GetBindings().Invalidate( SID_FONTWORK );
+ rReq.Done();
+ }
+ break;
+
+ case SID_ATTR_PARA_LEFT_TO_RIGHT:
+ case SID_ATTR_PARA_RIGHT_TO_LEFT:
+ {
+ SfxItemSetFixed<EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR,
+ EE_PARA_JUST, EE_PARA_JUST> aAttr( pView->GetModel()->GetItemPool() );
+ bool bLeft = ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT );
+ aAttr.Put( SvxFrameDirectionItem(
+ bLeft ? SvxFrameDirection::Horizontal_LR_TB : SvxFrameDirection::Horizontal_RL_TB,
+ EE_PARA_WRITINGDIR ) );
+ aAttr.Put( SvxAdjustItem(
+ bLeft ? SvxAdjust::Left : SvxAdjust::Right,
+ EE_PARA_JUST ) );
+ pView->SetAttributes( aAttr );
+ mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
+ rReq.Done(); //! Done(aAttr) ?
+
+ }
+ break;
+ }
+}
+
+void ScDrawTextObjectBar::ExecFormText(const SfxRequest& rReq)
+{
+ ScTabView* pTabView = mrViewData.GetView();
+ ScDrawView* pDrView = pTabView->GetScDrawView();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+
+ if ( rMarkList.GetMarkCount() == 1 && rReq.GetArgs() )
+ {
+ const SfxItemSet& rSet = *rReq.GetArgs();
+
+ if ( pDrView->IsTextEdit() )
+ pDrView->ScEndTextEdit();
+
+ pDrView->SetAttributes(rSet);
+ }
+}
+
+void ScDrawTextObjectBar::GetFormTextState(SfxItemSet& rSet)
+{
+ const SdrObject* pObj = nullptr;
+ ScDrawView* pDrView = mrViewData.GetView()->GetScDrawView();
+ const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
+
+ if ( rMarkList.GetMarkCount() == 1 )
+ pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ const SdrTextObj* pTextObj = dynamic_cast< const SdrTextObj* >(pObj);
+ const bool bDeactivate(
+ !pObj ||
+ !pTextObj ||
+ !pTextObj->HasText() ||
+ dynamic_cast< const SdrObjCustomShape* >(pObj)); // #121538# no FontWork for CustomShapes
+
+ if(bDeactivate)
+ {
+ rSet.DisableItem(XATTR_FORMTXTSTYLE);
+ rSet.DisableItem(XATTR_FORMTXTADJUST);
+ rSet.DisableItem(XATTR_FORMTXTDISTANCE);
+ rSet.DisableItem(XATTR_FORMTXTSTART);
+ rSet.DisableItem(XATTR_FORMTXTMIRROR);
+ rSet.DisableItem(XATTR_FORMTXTHIDEFORM);
+ rSet.DisableItem(XATTR_FORMTXTOUTLINE);
+ rSet.DisableItem(XATTR_FORMTXTSHADOW);
+ rSet.DisableItem(XATTR_FORMTXTSHDWCOLOR);
+ rSet.DisableItem(XATTR_FORMTXTSHDWXVAL);
+ rSet.DisableItem(XATTR_FORMTXTSHDWYVAL);
+ }
+ else
+ {
+ SfxItemSet aViewAttr(pDrView->GetModel()->GetItemPool());
+ pDrView->GetAttributes(aViewAttr);
+ rSet.Set(aViewAttr);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuconarc.cxx b/sc/source/ui/drawfunc/fuconarc.cxx
new file mode 100644
index 000000000..ef9b2c0fd
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuconarc.cxx
@@ -0,0 +1,154 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fuconarc.hxx>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+
+// Create default drawing objects via keyboard
+#include <svx/svdocirc.hxx>
+#include <svx/svxids.hrc>
+#include <svx/sxciaitm.hxx>
+#include <osl/diagnose.h>
+
+FuConstArc::FuConstArc(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuConstruct(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+}
+
+FuConstArc::~FuConstArc()
+{
+}
+
+bool FuConstArc::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuConstruct::MouseButtonDown( rMEvt );
+
+ if ( rMEvt.IsLeft() && !pView->IsAction() )
+ {
+ Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ pWindow->CaptureMouse();
+ pView->BegCreateObj( aPnt );
+ bReturn = true;
+ }
+ return bReturn;
+}
+
+bool FuConstArc::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = false;
+
+ if ( pView->IsCreateObj() && rMEvt.IsLeft() )
+ {
+ pView->EndCreateObj( SdrCreateCmd::NextPoint );
+ bReturn = true;
+ }
+ return (FuConstruct::MouseButtonUp(rMEvt) || bReturn);
+}
+
+void FuConstArc::Activate()
+{
+ SdrObjKind aObjKind;
+
+ switch (aSfxRequest.GetSlot() )
+ {
+ case SID_DRAW_ARC:
+ aNewPointer = PointerStyle::DrawArc;
+ aObjKind = SdrObjKind::CircleArc;
+ break;
+
+ case SID_DRAW_PIE:
+ aNewPointer = PointerStyle::DrawPie;
+ aObjKind = SdrObjKind::CircleSection;
+ break;
+
+ case SID_DRAW_CIRCLECUT:
+ aNewPointer = PointerStyle::DrawCircleCut;
+ aObjKind = SdrObjKind::CircleCut;
+ break;
+
+ default:
+ aNewPointer = PointerStyle::Cross;
+ aObjKind = SdrObjKind::CircleArc;
+ break;
+ }
+
+ pView->SetCurrentObj(aObjKind);
+
+ aOldPointer = pWindow->GetPointer();
+ rViewShell.SetActivePointer( aNewPointer );
+
+ FuDraw::Activate();
+}
+
+void FuConstArc::Deactivate()
+{
+ FuDraw::Deactivate();
+ rViewShell.SetActivePointer( aOldPointer );
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuConstArc::CreateDefaultObject(const sal_uInt16 nID, const tools::Rectangle& rRectangle)
+{
+ // case SID_DRAW_ARC:
+ // case SID_DRAW_PIE:
+ // case SID_DRAW_CIRCLECUT:
+
+ SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject(
+ *pDrDoc,
+ pView->GetCurrentObjInventor(),
+ pView->GetCurrentObjIdentifier()));
+
+ if(pObj)
+ {
+ if(dynamic_cast<const SdrCircObj*>( pObj.get() ) != nullptr)
+ {
+ tools::Rectangle aRect(rRectangle);
+
+ if(SID_DRAW_ARC == nID || SID_DRAW_CIRCLECUT == nID)
+ {
+ // force quadratic
+ ImpForceQuadratic(aRect);
+ }
+
+ pObj->SetLogicRect(aRect);
+
+ SfxItemSet aAttr(pDrDoc->GetItemPool());
+ aAttr.Put(makeSdrCircStartAngleItem(9000_deg100));
+ aAttr.Put(makeSdrCircEndAngleItem(0_deg100));
+
+ pObj->SetMergedItemSet(aAttr);
+ }
+ else
+ {
+ OSL_FAIL("Object is NO circle object");
+ }
+ }
+
+ return pObj;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuconcustomshape.cxx b/sc/source/ui/drawfunc/fuconcustomshape.cxx
new file mode 100644
index 000000000..ec2e7f083
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuconcustomshape.cxx
@@ -0,0 +1,199 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fuconcustomshape.hxx>
+#include <editeng/svxenum.hxx>
+#include <svx/gallery.hxx>
+#include <sfx2/request.hxx>
+#include <svx/fmmodel.hxx>
+#include <svl/itempool.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/xfillit0.hxx>
+#include <editeng/eeitem.hxx>
+#include <svx/sdtagitm.hxx>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+#include <editeng/adjustitem.hxx>
+
+using namespace com::sun::star;
+
+FuConstCustomShape::FuConstCustomShape(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP, SdrModel* pDoc, const SfxRequest& rReq )
+ : FuConstruct(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+ const SfxItemSet* pArgs = rReq.GetArgs();
+ if ( pArgs )
+ {
+ const SfxStringItem& rItm = static_cast<const SfxStringItem&>(pArgs->Get( rReq.GetSlot() ));
+ aCustomShape = rItm.GetValue();
+ }
+}
+
+FuConstCustomShape::~FuConstCustomShape()
+{
+}
+
+bool FuConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuConstruct::MouseButtonDown(rMEvt);
+ if ( rMEvt.IsLeft() && !pView->IsAction() )
+ {
+ Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ pWindow->CaptureMouse();
+ pView->BegCreateObj(aPnt);
+
+ SdrObject* pObj = pView->GetCreateObj();
+ if ( pObj )
+ {
+ SetAttributes( pObj );
+ bool bForceNoFillStyle = false;
+ if ( static_cast<SdrObjCustomShape*>(pObj)->UseNoFillStyle() )
+ bForceNoFillStyle = true;
+ if ( bForceNoFillStyle )
+ pObj->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
+ }
+
+ bReturn = true;
+ }
+ return bReturn;
+}
+
+bool FuConstCustomShape::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = false;
+
+ if ( pView->IsCreateObj() && rMEvt.IsLeft() )
+ {
+ pView->EndCreateObj(SdrCreateCmd::ForceEnd);
+ bReturn = true;
+ }
+ return (FuConstruct::MouseButtonUp(rMEvt) || bReturn);
+}
+
+void FuConstCustomShape::Activate()
+{
+ pView->SetCurrentObj( SdrObjKind::CustomShape );
+
+ aNewPointer = PointerStyle::DrawRect;
+ aOldPointer = pWindow->GetPointer();
+ rViewShell.SetActivePointer( aNewPointer );
+
+ FuConstruct::Activate();
+}
+
+void FuConstCustomShape::Deactivate()
+{
+ FuConstruct::Deactivate();
+
+ rViewShell.SetActivePointer( aOldPointer );
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuConstCustomShape::CreateDefaultObject(const sal_uInt16 /* nID */, const tools::Rectangle& rRectangle)
+{
+ SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject(
+ *pDrDoc,
+ pView->GetCurrentObjInventor(),
+ pView->GetCurrentObjIdentifier()));
+
+ if( pObj )
+ {
+ tools::Rectangle aRectangle( rRectangle );
+ SetAttributes( pObj.get() );
+ if ( SdrObjCustomShape::doConstructOrthogonal( aCustomShape ) )
+ ImpForceQuadratic( aRectangle );
+ pObj->SetLogicRect( aRectangle );
+ }
+
+ return pObj;
+}
+
+void FuConstCustomShape::SetAttributes( SdrObject* pObj )
+{
+ bool bAttributesAppliedFromGallery = false;
+
+ if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) )
+ {
+ std::vector< OUString > aObjList;
+ if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) )
+ {
+ for ( std::vector<OUString>::size_type i = 0; i < aObjList.size(); i++ )
+ {
+ if ( aObjList[ i ].equalsIgnoreAsciiCase( aCustomShape ) )
+ {
+ FmFormModel aFormModel;
+ SfxItemPool& rPool(aFormModel.GetItemPool());
+ rPool.FreezeIdRanges();
+
+ if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aFormModel ) )
+ {
+ const SdrObject* pSourceObj = aFormModel.GetPage( 0 )->GetObj( 0 );
+ if( pSourceObj )
+ {
+ const SfxItemSet& rSource = pSourceObj->GetMergedItemSet();
+ SfxItemSetFixed<
+ // Ranges from SdrAttrObj:
+ SDRATTR_START, SDRATTR_SHADOW_LAST,
+ SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
+ SDRATTR_TEXTDIRECTION,
+ SDRATTR_TEXTDIRECTION,
+ // Graphic attributes, 3D properties,
+ // CustomShape properties:
+ SDRATTR_GRAF_FIRST,
+ SDRATTR_CUSTOMSHAPE_LAST,
+ // Range from SdrTextObj:
+ EE_ITEMS_START, EE_ITEMS_END> aDest(
+ pObj->getSdrModelFromSdrObject().GetItemPool());
+ aDest.Set( rSource );
+ pObj->SetMergedItemSet( aDest );
+ Degree100 nAngle = pSourceObj->GetRotateAngle();
+ if ( nAngle )
+ pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle );
+ bAttributesAppliedFromGallery = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if ( !bAttributesAppliedFromGallery )
+ {
+ pObj->SetMergedItem( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) );
+ pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
+ pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
+ pObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
+ static_cast<SdrObjCustomShape*>(pObj)->MergeDefaultAttributes( &aCustomShape );
+ }
+}
+
+// #i33136#
+bool FuConstCustomShape::doConstructOrthogonal() const
+{
+ return SdrObjCustomShape::doConstructOrthogonal(aCustomShape);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuconpol.cxx b/sc/source/ui/drawfunc/fuconpol.cxx
new file mode 100644
index 000000000..6ce044ad9
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuconpol.cxx
@@ -0,0 +1,288 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fuconpol.hxx>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+
+// Create default drawing objects via keyboard
+#include <svx/svdopath.hxx>
+#include <svx/svxids.hrc>
+#include <osl/diagnose.h>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+FuConstPolygon::FuConstPolygon(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuConstruct(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+}
+
+FuConstPolygon::~FuConstPolygon()
+{
+}
+
+bool FuConstPolygon::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuConstruct::MouseButtonDown(rMEvt);
+
+ SdrViewEvent aVEvt;
+ (void)pView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
+ if (aVEvt.meEvent == SdrEventKind::BeginTextEdit)
+ {
+ // Text input not allowed here
+ aVEvt.meEvent = SdrEventKind::BeginDragObj;
+ pView->EnableExtendedMouseEventDispatcher(false);
+ }
+ else
+ {
+ pView->EnableExtendedMouseEventDispatcher(true);
+ }
+
+ if ( pView->MouseButtonDown(rMEvt, pWindow->GetOutDev()) )
+ bReturn = true;
+
+ return bReturn;
+}
+
+bool FuConstPolygon::MouseMove(const MouseEvent& rMEvt)
+{
+ pView->MouseMove(rMEvt, pWindow->GetOutDev());
+ return FuConstruct::MouseMove(rMEvt);
+}
+
+bool FuConstPolygon::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = false;
+ bool bSimple = false;
+
+ SdrViewEvent aVEvt;
+ (void)pView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aVEvt);
+
+ pView->MouseButtonUp(rMEvt, pWindow->GetOutDev());
+
+ if (aVEvt.meEvent == SdrEventKind::EndCreate)
+ {
+ bReturn = true;
+ bSimple = true; // Do not pass on double-click
+ }
+
+ bool bParent;
+ if (bSimple)
+ bParent = FuConstruct::SimpleMouseButtonUp(rMEvt);
+ else
+ bParent = FuConstruct::MouseButtonUp(rMEvt);
+
+ return (bParent || bReturn);
+}
+
+void FuConstPolygon::Activate()
+{
+ pView->EnableExtendedMouseEventDispatcher(true);
+
+ SdrObjKind eKind;
+
+ switch (GetSlotID())
+ {
+ case SID_DRAW_POLYGON_NOFILL:
+ case SID_DRAW_XPOLYGON_NOFILL:
+ {
+ eKind = SdrObjKind::PolyLine;
+ }
+ break;
+
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_XPOLYGON:
+ {
+ eKind = SdrObjKind::Polygon;
+ }
+ break;
+
+ case SID_DRAW_BEZIER_NOFILL:
+ {
+ eKind = SdrObjKind::PathLine;
+ }
+ break;
+
+ case SID_DRAW_BEZIER_FILL:
+ {
+ eKind = SdrObjKind::PathFill;
+ }
+ break;
+
+ case SID_DRAW_FREELINE_NOFILL:
+ {
+ eKind = SdrObjKind::FreehandLine;
+ }
+ break;
+
+ case SID_DRAW_FREELINE:
+ {
+ eKind = SdrObjKind::FreehandFill;
+ }
+ break;
+
+ default:
+ {
+ eKind = SdrObjKind::PathLine;
+ }
+ break;
+ }
+
+ pView->SetCurrentObj(eKind);
+
+ pView->SetEditMode(SdrViewEditMode::Create);
+
+ FuConstruct::Activate();
+
+ aNewPointer = PointerStyle::DrawPolygon;
+ aOldPointer = pWindow->GetPointer();
+ rViewShell.SetActivePointer( aNewPointer );
+}
+
+void FuConstPolygon::Deactivate()
+{
+ pView->SetEditMode(SdrViewEditMode::Edit);
+
+ pView->EnableExtendedMouseEventDispatcher(false);
+
+ FuConstruct::Deactivate();
+
+ rViewShell.SetActivePointer( aOldPointer );
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuConstPolygon::CreateDefaultObject(const sal_uInt16 nID, const tools::Rectangle& rRectangle)
+{
+ // case SID_DRAW_XPOLYGON:
+ // case SID_DRAW_XPOLYGON_NOFILL:
+ // case SID_DRAW_POLYGON:
+ // case SID_DRAW_POLYGON_NOFILL:
+ // case SID_DRAW_BEZIER_FILL:
+ // case SID_DRAW_BEZIER_NOFILL:
+ // case SID_DRAW_FREELINE:
+ // case SID_DRAW_FREELINE_NOFILL:
+
+ SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject(
+ *pDrDoc,
+ pView->GetCurrentObjInventor(),
+ pView->GetCurrentObjIdentifier()));
+
+ if(pObj)
+ {
+ if(dynamic_cast<const SdrPathObj*>( pObj.get() ) != nullptr)
+ {
+ basegfx::B2DPolyPolygon aPoly;
+
+ switch(nID)
+ {
+ case SID_DRAW_BEZIER_FILL:
+ case SID_DRAW_BEZIER_NOFILL:
+ {
+ basegfx::B2DPolygon aInnerPoly;
+
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
+
+ const basegfx::B2DPoint aCenterBottom(rRectangle.Center().X(), rRectangle.Bottom());
+ aInnerPoly.appendBezierSegment(
+ aCenterBottom,
+ aCenterBottom,
+ basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()));
+
+ const basegfx::B2DPoint aCenterTop(rRectangle.Center().X(), rRectangle.Top());
+ aInnerPoly.appendBezierSegment(
+ aCenterTop,
+ aCenterTop,
+ basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
+
+ aPoly.append(aInnerPoly);
+ break;
+ }
+ case SID_DRAW_FREELINE:
+ case SID_DRAW_FREELINE_NOFILL:
+ {
+ basegfx::B2DPolygon aInnerPoly;
+
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
+
+ aInnerPoly.appendBezierSegment(
+ basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()),
+ basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Top()),
+ basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()));
+
+ aInnerPoly.appendBezierSegment(
+ basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom()),
+ basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()),
+ basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
+
+ aPoly.append(aInnerPoly);
+ break;
+ }
+ case SID_DRAW_XPOLYGON:
+ case SID_DRAW_XPOLYGON_NOFILL:
+ case SID_DRAW_POLYGON:
+ case SID_DRAW_POLYGON_NOFILL:
+ {
+ basegfx::B2DPolygon aInnerPoly;
+ const sal_Int32 nWdt(rRectangle.GetWidth());
+ const sal_Int32 nHgt(rRectangle.GetHeight());
+
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 30) / 100, rRectangle.Top() + (nHgt * 70) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top() + (nHgt * 15) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 65) / 100, rRectangle.Top()));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + nWdt, rRectangle.Top() + (nHgt * 30) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 80) / 100, rRectangle.Top() + (nHgt * 50) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 80) / 100, rRectangle.Top() + (nHgt * 75) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Bottom(), rRectangle.Right()));
+
+ if(SID_DRAW_POLYGON_NOFILL == nID)
+ {
+ aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom()));
+ }
+ else
+ {
+ aInnerPoly.setClosed(true);
+ }
+
+ aPoly.append(aInnerPoly);
+ break;
+ }
+ }
+
+ static_cast<SdrPathObj*>(pObj.get())->SetPathPoly(aPoly);
+ }
+ else
+ {
+ OSL_FAIL("Object is NO path object");
+ }
+
+ pObj->SetLogicRect(rRectangle);
+ }
+
+ return pObj;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuconrec.cxx b/sc/source/ui/drawfunc/fuconrec.cxx
new file mode 100644
index 000000000..8e31015e8
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuconrec.cxx
@@ -0,0 +1,449 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fuconrec.hxx>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+
+#include <editeng/outlobj.hxx>
+// Create default drawing objects via keyboard
+#include <svx/svdopath.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svxids.hrc>
+#include <svx/strings.hrc>
+#include <svx/xlnwtit.hxx>
+#include <svx/xlnstwit.hxx>
+#include <svx/xlnedwit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/svdomeas.hxx>
+#include <osl/diagnose.h>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+FuConstRectangle::FuConstRectangle(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuConstruct(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+}
+
+FuConstRectangle::~FuConstRectangle()
+{
+}
+
+/**
+ * set line starts and ends for the object to be created
+ */
+
+namespace {
+
+::basegfx::B2DPolyPolygon getPolygon(TranslateId pResId, const SdrModel& rModel)
+{
+ ::basegfx::B2DPolyPolygon aRetval;
+ XLineEndListRef pLineEndList(rModel.GetLineEndList());
+
+ if( pLineEndList.is() )
+ {
+ OUString aArrowName( SvxResId(pResId) );
+ tools::Long nCount = pLineEndList->Count();
+ tools::Long nIndex;
+ for( nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nIndex);
+ if( pEntry->GetName() == aArrowName )
+ {
+ aRetval = pEntry->GetLineEnd();
+ break;
+ }
+ }
+ }
+
+ return aRetval;
+}
+
+}
+
+bool FuConstRectangle::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuConstruct::MouseButtonDown(rMEvt);
+
+ if ( rMEvt.IsLeft() && !pView->IsAction() )
+ {
+ Point aPos( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ pWindow->CaptureMouse();
+
+ if ( pView->GetCurrentObjIdentifier() == SdrObjKind::Caption )
+ {
+ Size aCaptionSize ( 2268, 1134 ); // 4x2cm
+
+ bReturn = pView->BegCreateCaptionObj( aPos, aCaptionSize );
+
+ // How do you set the font for writing
+ }
+ else
+ bReturn = pView->BegCreateObj(aPos);
+
+ SdrObject* pObj = pView->GetCreateObj();
+
+ if (pObj)
+ {
+ SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool());
+ SetLineEnds(aAttr, *pObj, aSfxRequest.GetSlot());
+ pObj->SetMergedItemSet(aAttr);
+ }
+ }
+ return bReturn;
+}
+
+bool FuConstRectangle::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = false;
+
+ if ( pView->IsCreateObj() && rMEvt.IsLeft() )
+ {
+ pView->EndCreateObj(SdrCreateCmd::ForceEnd);
+
+ if (aSfxRequest.GetSlot() == SID_DRAW_CAPTION_VERTICAL)
+ {
+ // set vertical flag for caption object
+
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if (rMarkList.GetMark(0))
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ // create OutlinerParaObject now so it can be set to vertical
+ if ( auto pSdrTextObj = dynamic_cast<SdrTextObj*>( pObj) )
+ pSdrTextObj->ForceOutlinerParaObject();
+ OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
+ if( pOPO && !pOPO->IsEffectivelyVertical() )
+ pOPO->SetVertical( true );
+ }
+ }
+
+ bReturn = true;
+ }
+ return (FuConstruct::MouseButtonUp(rMEvt) || bReturn);
+}
+
+void FuConstRectangle::Activate()
+{
+ SdrObjKind aObjKind;
+
+ switch (aSfxRequest.GetSlot() )
+ {
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ aNewPointer = PointerStyle::DrawLine;
+ aObjKind = SdrObjKind::Line;
+ break;
+
+ case SID_DRAW_MEASURELINE:
+ aNewPointer = PointerStyle::DrawLine;
+ aObjKind = SdrObjKind::Measure;
+ break;
+
+ case SID_DRAW_RECT:
+ aNewPointer = PointerStyle::DrawRect;
+ aObjKind = SdrObjKind::Rectangle;
+ break;
+
+ case SID_DRAW_ELLIPSE:
+ aNewPointer = PointerStyle::DrawEllipse;
+ aObjKind = SdrObjKind::CircleOrEllipse;
+ break;
+
+ case SID_DRAW_CAPTION:
+ case SID_DRAW_CAPTION_VERTICAL:
+ aNewPointer = PointerStyle::DrawCaption;
+ aObjKind = SdrObjKind::Caption;
+ break;
+
+ default:
+ aNewPointer = PointerStyle::Cross;
+ aObjKind = SdrObjKind::Rectangle;
+ break;
+ }
+
+ pView->SetCurrentObj(aObjKind);
+
+ aOldPointer = pWindow->GetPointer();
+ rViewShell.SetActivePointer( aNewPointer );
+
+ FuConstruct::Activate();
+}
+
+void FuConstRectangle::SetLineEnds(SfxItemSet& rAttr, const SdrObject& rObj, sal_uInt16 nSlotId)
+{
+ SdrModel& rModel(rObj.getSdrModelFromSdrObject());
+
+ if ( !(nSlotId == SID_LINE_ARROW_START ||
+ nSlotId == SID_LINE_ARROW_END ||
+ nSlotId == SID_LINE_ARROWS ||
+ nSlotId == SID_LINE_ARROW_CIRCLE ||
+ nSlotId == SID_LINE_CIRCLE_ARROW ||
+ nSlotId == SID_LINE_ARROW_SQUARE ||
+ nSlotId == SID_LINE_SQUARE_ARROW ||
+ nSlotId == SID_DRAW_MEASURELINE) )
+ return;
+
+
+ // set attributes of line start and ends
+
+ // arrowhead
+ ::basegfx::B2DPolyPolygon aArrow( getPolygon( RID_SVXSTR_ARROW, rModel ) );
+ if( !aArrow.count() )
+ {
+ ::basegfx::B2DPolygon aNewArrow;
+ aNewArrow.append(::basegfx::B2DPoint(10.0, 0.0));
+ aNewArrow.append(::basegfx::B2DPoint(0.0, 30.0));
+ aNewArrow.append(::basegfx::B2DPoint(20.0, 30.0));
+ aNewArrow.setClosed(true);
+ aArrow.append(aNewArrow);
+ }
+
+ // Circles
+ ::basegfx::B2DPolyPolygon aCircle( getPolygon( RID_SVXSTR_CIRCLE, rModel ) );
+ if( !aCircle.count() )
+ {
+ ::basegfx::B2DPolygon aNewCircle = ::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(0.0, 0.0), 250.0, 250.0);
+ aNewCircle.setClosed(true);
+ aCircle.append(aNewCircle);
+ }
+
+ // Square
+ ::basegfx::B2DPolyPolygon aSquare( getPolygon( RID_SVXSTR_SQUARE, rModel ) );
+ if( !aSquare.count() )
+ {
+ ::basegfx::B2DPolygon aNewSquare;
+ aNewSquare.append(::basegfx::B2DPoint(0.0, 0.0));
+ aNewSquare.append(::basegfx::B2DPoint(10.0, 0.0));
+ aNewSquare.append(::basegfx::B2DPoint(10.0, 10.0));
+ aNewSquare.append(::basegfx::B2DPoint(0.0, 10.0));
+ aNewSquare.setClosed(true);
+ aSquare.append(aNewSquare);
+ }
+
+ SfxItemSet aSet( rModel.GetItemPool() );
+ tools::Long nWidth = 200; // (1/100th mm)
+
+ // determine line width and calculate with it the line end width
+ if( aSet.GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE )
+ {
+ tools::Long nValue = aSet.Get( XATTR_LINEWIDTH ).GetValue();
+ if( nValue > 0 )
+ nWidth = nValue * 3;
+ }
+
+ switch (nSlotId)
+ {
+ case SID_LINE_ARROWS:
+ case SID_DRAW_MEASURELINE:
+ {
+ // connector with arrow ends
+ rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
+ rAttr.Put(XLineStartWidthItem(nWidth));
+ rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
+ rAttr.Put(XLineEndWidthItem(nWidth));
+ }
+ break;
+
+ case SID_LINE_ARROW_START:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ {
+ // connector with arrow start
+ rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
+ rAttr.Put(XLineStartWidthItem(nWidth));
+ }
+ break;
+
+ case SID_LINE_ARROW_END:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ {
+ // connector with arrow end
+ rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
+ rAttr.Put(XLineEndWidthItem(nWidth));
+ }
+ break;
+ }
+
+ // and again, for the still missing ends
+ switch (nSlotId)
+ {
+ case SID_LINE_ARROW_CIRCLE:
+ {
+ // circle end
+ rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle));
+ rAttr.Put(XLineEndWidthItem(nWidth));
+ }
+ break;
+
+ case SID_LINE_CIRCLE_ARROW:
+ {
+ // circle start
+ rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle));
+ rAttr.Put(XLineStartWidthItem(nWidth));
+ }
+ break;
+
+ case SID_LINE_ARROW_SQUARE:
+ {
+ // square end
+ rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_SQUARE), aSquare));
+ rAttr.Put(XLineEndWidthItem(nWidth));
+ }
+ break;
+
+ case SID_LINE_SQUARE_ARROW:
+ {
+ // square start
+ rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_SQUARE), aSquare));
+ rAttr.Put(XLineStartWidthItem(nWidth));
+ }
+ break;
+ }
+}
+
+void FuConstRectangle::Deactivate()
+{
+ FuConstruct::Deactivate();
+ rViewShell.SetActivePointer( aOldPointer );
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuConstRectangle::CreateDefaultObject(const sal_uInt16 nID, const tools::Rectangle& rRectangle)
+{
+ SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject(
+ *pDrDoc,
+ pView->GetCurrentObjInventor(),
+ pView->GetCurrentObjIdentifier()));
+
+ if(pObj)
+ {
+ tools::Rectangle aRect(rRectangle);
+ Point aStart = aRect.TopLeft();
+ Point aEnd = aRect.BottomRight();
+
+ switch(nID)
+ {
+ case SID_DRAW_LINE:
+ case SID_DRAW_XLINE:
+ case SID_LINE_ARROW_END:
+ case SID_LINE_ARROW_CIRCLE:
+ case SID_LINE_ARROW_SQUARE:
+ case SID_LINE_ARROW_START:
+ case SID_LINE_CIRCLE_ARROW:
+ case SID_LINE_SQUARE_ARROW:
+ case SID_LINE_ARROWS:
+ {
+ if(auto pPathObj = dynamic_cast<SdrPathObj*>( pObj.get() ))
+ {
+ sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
+ basegfx::B2DPolygon aPoly;
+ aPoly.append(basegfx::B2DPoint(aStart.X(), nYMiddle));
+ aPoly.append(basegfx::B2DPoint(aEnd.X(), nYMiddle));
+ pPathObj->SetPathPoly(basegfx::B2DPolyPolygon(aPoly));
+ }
+ else
+ {
+ OSL_FAIL("Object is NO line object");
+ }
+
+ break;
+ }
+
+ case SID_DRAW_MEASURELINE:
+ {
+ if(auto pMeasureObj = dynamic_cast<SdrMeasureObj*>( pObj.get() ))
+ {
+ sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
+ pMeasureObj->SetPoint(Point(aStart.X(), nYMiddle), 0);
+ pMeasureObj->SetPoint(Point(aEnd.X(), nYMiddle), 1);
+ }
+
+ break;
+ }
+
+ case SID_DRAW_CAPTION:
+ case SID_DRAW_CAPTION_VERTICAL:
+ {
+ if(auto pCaptionObj = dynamic_cast<SdrCaptionObj*>( pObj.get() ))
+ {
+ bool bIsVertical(SID_DRAW_CAPTION_VERTICAL == nID);
+
+ pCaptionObj->SetVerticalWriting(bIsVertical);
+
+ if(bIsVertical)
+ {
+ SfxItemSet aSet(pObj->GetMergedItemSet());
+ aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
+ aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
+ pObj->SetMergedItemSet(aSet);
+ }
+
+ // don't set default text, start edit mode instead
+ // (Edit mode is started in ScTabViewShell::ExecDraw, because
+ // it must be handled by FuText)
+
+ pCaptionObj->SetLogicRect(aRect);
+ pCaptionObj->SetTailPos(
+ aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2));
+ }
+ else
+ {
+ OSL_FAIL("Object is NO caption object");
+ }
+
+ break;
+ }
+
+ default:
+ {
+ pObj->SetLogicRect(aRect);
+
+ break;
+ }
+ }
+
+ SfxItemSet aAttr(pDrDoc->GetItemPool());
+ SetLineEnds(aAttr, *pObj, nID);
+ pObj->SetMergedItemSet(aAttr);
+ }
+
+ return pObj;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuconstr.cxx b/sc/source/ui/drawfunc/fuconstr.cxx
new file mode 100644
index 000000000..1064a30e1
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuconstr.cxx
@@ -0,0 +1,252 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/outlobj.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/svxids.hrc>
+#include <sfx2/dispatch.hxx>
+
+#include <fuconstr.hxx>
+#include <fudraw.hxx>
+#include <tabvwsh.hxx>
+#include <futext.hxx>
+#include <drawview.hxx>
+
+// maximal permitted mouse movement to start Drag&Drop
+//! fusel,fuconstr,futext - combine them!
+#define SC_MAXDRAGMOVE 3
+
+FuConstruct::FuConstruct(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuDraw(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+}
+
+FuConstruct::~FuConstruct()
+{
+}
+
+bool FuConstruct::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuDraw::MouseButtonDown(rMEvt);
+
+ if ( pView->IsAction() )
+ {
+ if ( rMEvt.IsRight() )
+ pView->BckAction();
+ return true;
+ }
+
+ aDragTimer.Start();
+
+ aMDPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
+
+ if ( rMEvt.IsLeft() )
+ {
+ pWindow->CaptureMouse();
+
+ SdrHdl* pHdl = pView->PickHandle(aMDPos);
+
+ if ( pHdl != nullptr || pView->IsMarkedHit(aMDPos) )
+ {
+ pView->BegDragObj(aMDPos, nullptr, pHdl, 1);
+ bReturn = true;
+ }
+ else if ( pView->AreObjectsMarked() )
+ {
+ pView->UnmarkAll();
+ bReturn = true;
+ }
+ }
+
+ bIsInDragMode = false;
+
+ return bReturn;
+}
+
+bool FuConstruct::MouseMove(const MouseEvent& rMEvt)
+{
+ FuDraw::MouseMove(rMEvt);
+
+ if (aDragTimer.IsActive() )
+ {
+ Point aOldPixel = pWindow->LogicToPixel( aMDPos );
+ Point aNewPixel = rMEvt.GetPosPixel();
+ if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
+ std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
+ aDragTimer.Stop();
+ }
+
+ Point aPix(rMEvt.GetPosPixel());
+ Point aPnt( pWindow->PixelToLogic(aPix) );
+
+ if ( pView->IsAction() )
+ {
+ ForceScroll(aPix);
+ pView->MovAction(aPnt);
+ }
+ else
+ {
+ SdrHdl* pHdl=pView->PickHandle(aPnt);
+
+ if ( pHdl != nullptr )
+ {
+ rViewShell.SetActivePointer(pHdl->GetPointer());
+ }
+ else if ( pView->IsMarkedHit(aPnt) )
+ {
+ rViewShell.SetActivePointer(PointerStyle::Move);
+ }
+ else
+ {
+ rViewShell.SetActivePointer( aNewPointer );
+ }
+ }
+ return true;
+}
+
+bool FuConstruct::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = SimpleMouseButtonUp( rMEvt );
+
+ // Double-click on text object? (->fusel)
+
+ sal_uInt16 nClicks = rMEvt.GetClicks();
+ if ( nClicks == 2 && rMEvt.IsLeft() )
+ {
+ if ( pView->AreObjectsMarked() )
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if (rMarkList.GetMarkCount() == 1)
+ {
+ SdrMark* pMark = rMarkList.GetMark(0);
+ SdrObject* pObj = pMark->GetMarkedSdrObj();
+
+ // if Uno-Controls no text mode
+ if ( dynamic_cast<const SdrTextObj*>( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) == nullptr )
+ {
+ OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
+ bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() );
+ sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
+
+ rViewShell.GetViewData().GetDispatcher().
+ Execute(nTextSlotId, SfxCallMode::SLOT | SfxCallMode::RECORD);
+
+ // Get the created FuText now and change into EditMode
+ FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
+ if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // has no RTTI
+ {
+ FuText* pText = static_cast<FuText*>(pPoor);
+ Point aMousePixel = rMEvt.GetPosPixel();
+ pText->SetInEditMode( pObj, &aMousePixel );
+ }
+ bReturn = true;
+ }
+ }
+ }
+ }
+
+ FuDraw::MouseButtonUp(rMEvt);
+
+ return bReturn;
+}
+
+// SimpleMouseButtonUp - no test on double-click
+
+bool FuConstruct::SimpleMouseButtonUp(const MouseEvent& rMEvt)
+{
+ bool bReturn = true;
+
+ if (aDragTimer.IsActive() )
+ {
+ aDragTimer.Stop();
+ }
+
+ Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+
+ if ( pView->IsDragObj() )
+ pView->EndDragObj( rMEvt.IsMod1() );
+
+ else if ( pView->IsMarkObj() )
+ pView->EndMarkObj();
+
+ else bReturn = false;
+
+ if ( !pView->IsAction() )
+ {
+ pWindow->ReleaseMouse();
+
+ if ( !pView->AreObjectsMarked() && rMEvt.GetClicks() < 2 )
+ {
+ pView->MarkObj(aPnt, -2, false, rMEvt.IsMod1());
+
+ SfxDispatcher& rDisp = rViewShell.GetViewData().GetDispatcher();
+ if ( pView->AreObjectsMarked() )
+ rDisp.Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
+ else
+ rDisp.Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ }
+ }
+
+ return bReturn;
+}
+
+// If we handle a KeyEvent, then the return value is sal_True else FALSE.
+bool FuConstruct::KeyInput(const KeyEvent& rKEvt)
+{
+ bool bReturn = false;
+
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_ESCAPE:
+ if ( pView->IsAction() )
+ {
+ pView->BrkAction();
+ pWindow->ReleaseMouse();
+ bReturn = true;
+ }
+ else // end drawing mode
+ {
+ rViewShell.GetViewData().GetDispatcher().
+ Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ }
+ break;
+
+ case KEY_DELETE:
+ pView->DeleteMarked();
+ bReturn = true;
+ break;
+ }
+
+ if ( !bReturn )
+ {
+ bReturn = FuDraw::KeyInput(rKEvt);
+ }
+
+ return bReturn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuconuno.cxx b/sc/source/ui/drawfunc/fuconuno.cxx
new file mode 100644
index 000000000..e4e3c3e37
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuconuno.cxx
@@ -0,0 +1,122 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <fuconuno.hxx>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+
+#include <svx/svxids.hrc>
+
+FuConstUnoControl::FuConstUnoControl(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuConstruct(rViewSh, pWin, pViewP, pDoc, rReq)
+ , nInventor(SdrInventor::Unknown)
+ , nIdentifier(SdrObjKind::NONE)
+{
+ const SfxUInt32Item* pInventorItem = rReq.GetArg<SfxUInt32Item>(SID_FM_CONTROL_INVENTOR);
+ const SfxUInt16Item* pIdentifierItem = rReq.GetArg<SfxUInt16Item>(SID_FM_CONTROL_IDENTIFIER);
+ if( pInventorItem )
+ nInventor = static_cast<SdrInventor>(pInventorItem->GetValue());
+ if( pIdentifierItem )
+ nIdentifier = static_cast<SdrObjKind>(pIdentifierItem->GetValue());
+}
+
+FuConstUnoControl::~FuConstUnoControl()
+{
+}
+
+bool FuConstUnoControl::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuConstruct::MouseButtonDown(rMEvt);
+
+ if ( rMEvt.IsLeft() && !pView->IsAction() )
+ {
+ Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ pWindow->CaptureMouse();
+ pView->BegCreateObj(aPnt);
+ bReturn = true;
+ }
+ return bReturn;
+}
+
+bool FuConstUnoControl::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = false;
+
+ if ( pView->IsCreateObj() && rMEvt.IsLeft() )
+ {
+ pView->EndCreateObj(SdrCreateCmd::ForceEnd);
+ bReturn = true;
+ }
+ return (FuConstruct::MouseButtonUp(rMEvt) || bReturn);
+}
+
+void FuConstUnoControl::Activate()
+{
+ pView->SetCurrentObj( nIdentifier, nInventor );
+
+ aNewPointer = PointerStyle::DrawRect;
+ aOldPointer = pWindow->GetPointer();
+ rViewShell.SetActivePointer( aNewPointer );
+
+ SdrLayer* pLayer = pView->GetModel()->GetLayerAdmin().GetLayerPerID(SC_LAYER_CONTROLS);
+ if (pLayer)
+ pView->SetActiveLayer( pLayer->GetName() );
+
+ FuConstruct::Activate();
+}
+
+void FuConstUnoControl::Deactivate()
+{
+ FuConstruct::Deactivate();
+
+ SdrLayer* pLayer = pView->GetModel()->GetLayerAdmin().GetLayerPerID(SC_LAYER_FRONT);
+ if (pLayer)
+ pView->SetActiveLayer( pLayer->GetName() );
+
+ rViewShell.SetActivePointer( aOldPointer );
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuConstUnoControl::CreateDefaultObject(const sal_uInt16 /* nID */, const tools::Rectangle& rRectangle)
+{
+ // case SID_FM_CREATE_CONTROL:
+
+ SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject(
+ *pDrDoc,
+ pView->GetCurrentObjInventor(),
+ pView->GetCurrentObjIdentifier()));
+
+ if(pObj)
+ {
+ pObj->SetLogicRect(rRectangle);
+ // tdf#140252 Controls are always on layer "controls"
+ pObj->NbcSetLayer(SC_LAYER_CONTROLS);
+ }
+
+ return pObj;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fudraw.cxx b/sc/source/ui/drawfunc/fudraw.cxx
new file mode 100644
index 000000000..ee9090765
--- /dev/null
+++ b/sc/source/ui/drawfunc/fudraw.cxx
@@ -0,0 +1,766 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/editeng.hxx>
+#include <editeng/outlobj.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/ImageMapInfo.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/uitest/logger.hxx>
+#include <vcl/uitest/eventdescription.hxx>
+
+#include <sc.hrc>
+#include <fudraw.hxx>
+#include <futext.hxx>
+#include <tabvwsh.hxx>
+#include <drwlayer.hxx>
+#include <userdat.hxx>
+#include <docsh.hxx>
+#include <drawview.hxx>
+#include <comphelper/lok.hxx>
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+
+namespace
+{
+
+void collectUIInformation( const OUString& aevent )
+{
+ EventDescription aDescription;
+ aDescription.aID = "grid_window";
+ aDescription.aParameters = {{ aevent , ""}};
+ aDescription.aAction = "COMMENT";
+ aDescription.aParent = "MainWindow";
+ aDescription.aKeyWord = "ScGridWinUIObject";
+ UITestLogger::getInstance().logEvent(aDescription);
+}
+
+}
+
+// base class for draw module specific functions
+FuDraw::FuDraw(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
+ , aNewPointer(PointerStyle::Arrow)
+ , aOldPointer(PointerStyle::Arrow)
+{
+}
+
+FuDraw::~FuDraw()
+{
+}
+
+void FuDraw::DoModifiers(const MouseEvent& rMEvt)
+{
+ // Shift = Ortho and AngleSnap
+ // Control = Snap (Toggle)
+ // Alt = centric
+
+ bool bShift = rMEvt.IsShift();
+ bool bAlt = rMEvt.IsMod2();
+
+ bool bOrtho = bShift;
+ bool bAngleSnap = bShift;
+ bool bCenter = bAlt;
+
+ // #i33136#
+ if(doConstructOrthogonal())
+ {
+ bOrtho = !bShift;
+ }
+
+ if (pView->IsOrtho() != bOrtho)
+ pView->SetOrtho(bOrtho);
+ if (pView->IsAngleSnapEnabled() != bAngleSnap)
+ pView->SetAngleSnapEnabled(bAngleSnap);
+
+ if (pView->IsCreate1stPointAsCenter() != bCenter)
+ pView->SetCreate1stPointAsCenter(bCenter);
+ if (pView->IsResizeAtCenter() != bCenter)
+ pView->SetResizeAtCenter(bCenter);
+
+}
+
+void FuDraw::ResetModifiers()
+{
+ if (!pView)
+ return;
+
+ ScViewData& rViewData = rViewShell.GetViewData();
+ const ScViewOptions& rOpt = rViewData.GetOptions();
+ const ScGridOptions& rGrid = rOpt.GetGridOptions();
+ bool bGridOpt = rGrid.GetUseGridSnap();
+
+ if (pView->IsOrtho())
+ pView->SetOrtho(false);
+ if (pView->IsAngleSnapEnabled())
+ pView->SetAngleSnapEnabled(false);
+
+ if (pView->IsGridSnap() != bGridOpt)
+ pView->SetGridSnap(bGridOpt);
+ if (pView->IsSnapEnabled() != bGridOpt)
+ pView->SetSnapEnabled(bGridOpt);
+
+ if (pView->IsCreate1stPointAsCenter())
+ pView->SetCreate1stPointAsCenter(false);
+ if (pView->IsResizeAtCenter())
+ pView->SetResizeAtCenter(false);
+}
+
+bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ DoModifiers( rMEvt );
+ return false;
+}
+
+bool FuDraw::MouseMove(const MouseEvent& rMEvt)
+{
+ // evaluate modifiers only if in a drawing layer action
+ // (don't interfere with keyboard shortcut handling)
+ if (pView->IsAction())
+ DoModifiers( rMEvt );
+
+ return false;
+}
+
+bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ ResetModifiers();
+ return false;
+}
+
+// Process Keyboard events. Return true if an event is being handled
+static bool lcl_KeyEditMode( SdrObject* pObj, ScTabViewShell& rViewShell, const KeyEvent* pInitialKey )
+{
+ bool bReturn = false;
+ if ( dynamic_cast<const SdrTextObj*>( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) == nullptr )
+ {
+ // start text edit - like FuSelection::MouseButtonUp,
+ // but with bCursorToEnd instead of mouse position
+
+ OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
+ bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() );
+ sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
+
+ // don't switch shells if text shell is already active
+ FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
+ if ( !pPoor || pPoor->GetSlotID() != nTextSlotId )
+ {
+ rViewShell.GetViewData().GetDispatcher().
+ Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
+ }
+
+ // get the resulting FuText and set in edit mode
+ pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
+ if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // no RTTI
+ {
+ FuText* pText = static_cast<FuText*>(pPoor);
+ pText->SetInEditMode( pObj, nullptr, true, pInitialKey );
+ //! set cursor to end of text
+ }
+ bReturn = true;
+ }
+ return bReturn;
+}
+
+bool FuDraw::KeyInput(const KeyEvent& rKEvt)
+{
+ bool bReturn = false;
+ ScViewData& rViewData = rViewShell.GetViewData();
+
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_ESCAPE:
+ if ( rViewShell.IsDrawTextShell() || aSfxRequest.GetSlot() == SID_DRAW_NOTEEDIT )
+ {
+ collectUIInformation("CLOSE");
+ // if object selected -> normal draw-shell, else turn off drawing
+ rViewData.GetDispatcher().Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ bReturn = true;
+ }
+ else if ( rViewShell.IsDrawSelMode() )
+ {
+ pView->UnmarkAll();
+ rViewData.GetDispatcher().Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
+ bReturn = true;
+ }
+ else if ( pView->AreObjectsMarked() )
+ {
+ // III
+ SdrHdlList& rHdlList = const_cast< SdrHdlList& >( pView->GetHdlList() );
+ if( rHdlList.GetFocusHdl() )
+ rHdlList.ResetFocusHdl();
+ else
+ pView->UnmarkAll();
+
+ // while bezier editing, object is selected
+ if (!pView->AreObjectsMarked())
+ rViewShell.SetDrawShell( false );
+
+ bReturn = true;
+ }
+ break;
+
+ case KEY_DELETE: //! via accelerator
+ pView->DeleteMarked();
+ bReturn = true;
+ break;
+
+ case KEY_RETURN:
+ {
+ if( rKEvt.GetKeyCode().GetModifier() == 0 )
+ {
+ // activate OLE object on RETURN for selected object
+ // put selected text object in edit mode
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
+ {
+ bool bOle = rViewShell.GetViewFrame()->GetFrame().IsInPlace();
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ auto pOleObj = dynamic_cast<SdrOle2Obj*>(pObj);
+ if( pOleObj && !bOle )
+ {
+ rViewShell.ActivateObject(pOleObj, css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
+
+ // consumed
+ bReturn = true;
+ }
+ else if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) ) // start text edit for suitable object
+ bReturn = true;
+ }
+ }
+ }
+ break;
+
+ case KEY_F2:
+ {
+ if( rKEvt.GetKeyCode().GetModifier() == 0 )
+ {
+ // put selected text object in edit mode
+ // (this is not SID_SETINPUTMODE, but F2 hardcoded, like in Writer)
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ bool isMobilePhone = comphelper::LibreOfficeKit::isActive() && rViewShell.isLOKMobilePhone();
+ // Double tapping on charts on phone may result in activating the edit mode which is not wanted.
+ // It happens due to the delay of selection message of the object from kit to javascript
+ // in that case F2 is sent instead of double click
+ if (isMobilePhone && ScDocument::IsChart(pObj))
+ {
+ rViewShell.ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
+ break;
+ }
+ if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) ) // start text edit for suitable object
+ bReturn = true;
+ }
+ }
+ }
+ break;
+
+ case KEY_TAB:
+ {
+ // in calc do NOT start draw object selection using TAB/SHIFT-TAB when
+ // there is not yet an object selected
+ if(pView->AreObjectsMarked())
+ {
+ vcl::KeyCode aCode = rKEvt.GetKeyCode();
+
+ if ( !aCode.IsMod1() && !aCode.IsMod2() )
+ {
+ // changeover to the next object
+ if(!pView->MarkNextObj( !aCode.IsShift() ))
+ {
+ //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
+ if ( pView->HasMultipleMarkableObjects() && pView->HasMarkableObj() )
+ {
+ // No next object: go over open end and
+ // get first from the other side
+ pView->UnmarkAllObj();
+ pView->MarkNextObj(!aCode.IsShift());
+ }
+ }
+
+ // II
+ if(pView->AreObjectsMarked())
+ pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
+
+ bReturn = true;
+ }
+
+ // handle Mod1 and Mod2 to get travelling running on different systems
+ if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
+ {
+ // II do something with a selected handle?
+ const SdrHdlList& rHdlList = pView->GetHdlList();
+ bool bForward(!rKEvt.GetKeyCode().IsShift());
+
+ const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
+
+ // guarantee visibility of focused handle
+ SdrHdl* pHdl = rHdlList.GetFocusHdl();
+
+ if(pHdl)
+ {
+ Point aHdlPosition(pHdl->GetPos());
+ tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
+ pView->MakeVisible(aVisRect, *pWindow);
+ }
+
+ // consumed
+ bReturn = true;
+ }
+ }
+ }
+ break;
+
+ case KEY_END:
+ {
+ // in calc do NOT select the last draw object when
+ // there is not yet an object selected
+ if(pView->AreObjectsMarked())
+ {
+ vcl::KeyCode aCode = rKEvt.GetKeyCode();
+
+ if ( aCode.IsMod1() )
+ {
+ // mark last object
+ pView->UnmarkAllObj();
+ pView->MarkNextObj();
+
+ // II
+ if(pView->AreObjectsMarked())
+ pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
+
+ bReturn = true;
+ }
+ }
+ }
+ break;
+
+ case KEY_HOME:
+ {
+ // in calc do NOT select the first draw object when
+ // there is not yet an object selected
+ if(pView->AreObjectsMarked())
+ {
+ vcl::KeyCode aCode = rKEvt.GetKeyCode();
+
+ if ( aCode.IsMod1() )
+ {
+ // mark first object
+ pView->UnmarkAllObj();
+ pView->MarkNextObj(true);
+
+ // II
+ if(pView->AreObjectsMarked())
+ pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
+
+ bReturn = true;
+ }
+ }
+ }
+ break;
+
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ {
+ // in calc do cursor travelling of draw objects only when
+ // there is an object selected yet
+ if(pView->AreObjectsMarked())
+ {
+
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if(rMarkList.GetMarkCount() == 1)
+ {
+ // disable cursor travelling on note objects as the tail connector position
+ // must not move.
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( ScDrawLayer::IsNoteCaption( pObj ) )
+ break;
+ }
+
+ tools::Long nX = 0;
+ tools::Long nY = 0;
+ sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
+
+ if (nCode == KEY_UP)
+ {
+ // scroll up
+ nX = 0;
+ nY =-1;
+ }
+ else if (nCode == KEY_DOWN)
+ {
+ // scroll down
+ nX = 0;
+ nY = 1;
+ }
+ else if (nCode == KEY_LEFT)
+ {
+ // scroll left
+ nX =-1;
+ nY = 0;
+ }
+ else if (nCode == KEY_RIGHT)
+ {
+ // scroll right
+ nX = 1;
+ nY = 0;
+ }
+
+ bool bReadOnly = rViewData.GetDocShell()->IsReadOnly();
+
+ if(!rKEvt.GetKeyCode().IsMod1() && !bReadOnly)
+ {
+ if(rKEvt.GetKeyCode().IsMod2())
+ {
+ // move in 1 pixel distance
+ Size aLogicSizeOnePixel = pWindow ? pWindow->PixelToLogic(Size(1,1)) : Size(100, 100);
+ nX *= aLogicSizeOnePixel.Width();
+ nY *= aLogicSizeOnePixel.Height();
+ }
+ else if(rKEvt.GetKeyCode().IsShift()) // #i121236# Support for shift key in calc
+ {
+ nX *= 1000;
+ nY *= 1000;
+ }
+ else
+ {
+ // old, fixed move distance
+ nX *= 100;
+ nY *= 100;
+ }
+
+ // is there a movement to do?
+ if(0 != nX || 0 != nY)
+ {
+ // II
+ const SdrHdlList& rHdlList = pView->GetHdlList();
+ SdrHdl* pHdl = rHdlList.GetFocusHdl();
+
+ if(nullptr == pHdl)
+ {
+ // only take action when move is allowed
+ if(pView->IsMoveAllowed())
+ {
+ // restrict movement to WorkArea
+ const tools::Rectangle& rWorkArea = pView->GetWorkArea();
+
+ if(!rWorkArea.IsEmpty())
+ {
+ tools::Rectangle aMarkRect(pView->GetMarkedObjRect());
+ aMarkRect.Move(nX, nY);
+
+ if(!aMarkRect.Contains(rWorkArea))
+ {
+ if(aMarkRect.Left() < rWorkArea.Left())
+ {
+ nX += rWorkArea.Left() - aMarkRect.Left();
+ }
+
+ if(aMarkRect.Right() > rWorkArea.Right())
+ {
+ nX -= aMarkRect.Right() - rWorkArea.Right();
+ }
+
+ if(aMarkRect.Top() < rWorkArea.Top())
+ {
+ nY += rWorkArea.Top() - aMarkRect.Top();
+ }
+
+ if(aMarkRect.Bottom() > rWorkArea.Bottom())
+ {
+ nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
+ }
+ }
+ }
+
+ // now move the selected draw objects
+ pView->MoveAllMarked(Size(nX, nY));
+
+ // II
+ pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
+
+ bReturn = true;
+ }
+ }
+ else
+ {
+ // move handle with index nHandleIndex
+ if (nX || nY)
+ {
+ // now move the Handle (nX, nY)
+ Point aStartPoint(pHdl->GetPos());
+ Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
+ const SdrDragStat& rDragStat = pView->GetDragStat();
+
+ // start dragging
+ pView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
+
+ if(pView->IsDragObj())
+ {
+ bool bWasNoSnap = rDragStat.IsNoSnap();
+ bool bWasSnapEnabled = pView->IsSnapEnabled();
+
+ // switch snapping off
+ if(!bWasNoSnap)
+ const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
+ if(bWasSnapEnabled)
+ pView->SetSnapEnabled(false);
+
+ pView->MovAction(aEndPoint);
+ pView->EndDragObj();
+
+ // restore snap
+ if(!bWasNoSnap)
+ const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
+ if(bWasSnapEnabled)
+ pView->SetSnapEnabled(bWasSnapEnabled);
+ }
+
+ // make moved handle visible
+ tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200));
+ pView->MakeVisible(aVisRect, *pWindow);
+
+ bReturn = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case KEY_SPACE:
+ {
+ // in calc do only something when draw objects are selected
+ if(pView->AreObjectsMarked())
+ {
+ const SdrHdlList& rHdlList = pView->GetHdlList();
+ SdrHdl* pHdl = rHdlList.GetFocusHdl();
+
+ if(pHdl)
+ {
+ if(pHdl->GetKind() == SdrHdlKind::Poly)
+ {
+ // rescue ID of point with focus
+ sal_uInt32 nPol(pHdl->GetPolyNum());
+ sal_uInt32 nPnt(pHdl->GetPointNum());
+
+ if(pView->IsPointMarked(*pHdl))
+ {
+ if(rKEvt.GetKeyCode().IsShift())
+ {
+ pView->UnmarkPoint(*pHdl);
+ }
+ }
+ else
+ {
+ if(!rKEvt.GetKeyCode().IsShift())
+ {
+ pView->UnmarkAllPoints();
+ }
+
+ pView->MarkPoint(*pHdl);
+ }
+
+ if(nullptr == rHdlList.GetFocusHdl())
+ {
+ // restore point with focus
+ SdrHdl* pNewOne = nullptr;
+
+ for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
+ {
+ SdrHdl* pAct = rHdlList.GetHdl(a);
+
+ if(pAct
+ && pAct->GetKind() == SdrHdlKind::Poly
+ && pAct->GetPolyNum() == nPol
+ && pAct->GetPointNum() == nPnt)
+ {
+ pNewOne = pAct;
+ }
+ }
+
+ if(pNewOne)
+ {
+ const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
+ }
+ }
+
+ bReturn = true;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ if (!bReturn)
+ {
+ bReturn = FuPoor::KeyInput(rKEvt);
+ }
+
+ if (!bReturn)
+ {
+ // allow direct typing into a selected text object
+
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() && EditEngine::IsSimpleCharInput(rKEvt) )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ // start text edit for suitable object, pass key event to OutlinerView
+ if ( lcl_KeyEditMode( pObj, rViewShell, &rKEvt ) )
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+// toggle mouse-pointer
+static bool lcl_UrlHit( const SdrView* pView, const Point& rPosPixel, const vcl::Window* pWindow )
+{
+ SdrViewEvent aVEvt;
+ MouseEvent aMEvt( rPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT );
+ SdrHitKind eHit = pView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
+
+ if (eHit != SdrHitKind::NONE && aVEvt.mpObj != nullptr)
+ {
+ if ( SvxIMapInfo::GetIMapInfo(aVEvt.mpObj) && SvxIMapInfo::GetHitIMapObject(
+ aVEvt.mpObj, pWindow->PixelToLogic(rPosPixel), pWindow->GetOutDev() ) )
+ return true;
+
+ if (aVEvt.meEvent == SdrEventKind::ExecuteUrl)
+ return true;
+ }
+
+ return false;
+}
+
+void FuDraw::ForcePointer(const MouseEvent* pMEvt)
+{
+ if ( pView->IsAction() )
+ return;
+
+ Point aPosPixel = pWindow->GetPointerPosPixel();
+ bool bAlt = pMEvt && pMEvt->IsMod2();
+ Point aPnt = pWindow->PixelToLogic( aPosPixel );
+ SdrHdl* pHdl = pView->PickHandle(aPnt);
+ SdrPageView* pPV;
+ SdrObject* pMacroPickObj;
+
+ ScMacroInfo* pInfo = nullptr;
+ SdrObject* pObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
+ if (pObj)
+ {
+ if ( pObj->IsGroupObject() )
+ {
+ SdrObject* pHit = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
+ if (pHit)
+ pObj = pHit;
+ }
+ pInfo = ScDrawLayer::GetMacroInfo( pObj );
+ }
+
+ if ( pView->IsTextEdit() )
+ {
+ rViewShell.SetActivePointer(PointerStyle::Text); // can't be ?
+ }
+ else if ( pHdl )
+ {
+ rViewShell.SetActivePointer(
+ pView->GetPreferredPointer( aPnt, pWindow->GetOutDev() ) );
+ }
+ else if ( pView->IsMarkedHit(aPnt) )
+ {
+ rViewShell.SetActivePointer( PointerStyle::Move );
+ }
+ else if ( !bAlt && ( !pMEvt || !pMEvt->GetButtons() )
+ && lcl_UrlHit( pView, aPosPixel, pWindow ) )
+ {
+ // could be suppressed with ALT
+ pWindow->SetPointer( PointerStyle::RefHand ); // Text-URL / ImageMap
+ }
+ else if ( !bAlt && (pMacroPickObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO)) )
+ {
+ // could be suppressed with ALT
+ SdrObjMacroHitRec aHitRec; //! something missing ????
+ rViewShell.SetActivePointer(pMacroPickObj->GetMacroPointer(aHitRec));
+ }
+ else if ( !bAlt && pInfo && (!pInfo->GetMacro().isEmpty() || !pObj->getHyperlink().isEmpty()) )
+ pWindow->SetPointer( PointerStyle::RefHand );
+ else if ( IsDetectiveHit( aPnt ) )
+ rViewShell.SetActivePointer( PointerStyle::Detective );
+ else
+ {
+ const bool bIsThemed = rViewShell.GetViewData().IsThemedCursor();
+ rViewShell.SetActivePointer( bIsThemed ? PointerStyle::FatCross : PointerStyle::Arrow ); //! in Gridwin?
+ }
+}
+
+bool FuDraw::IsEditingANote() const
+{
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ const size_t backval=rMarkList.GetMarkCount();
+ for (size_t nlv1=0; nlv1<backval; ++nlv1)
+ {
+ SdrObject* pObj = rMarkList.GetMark( nlv1 )->GetMarkedSdrObj();
+ if ( ScDrawLayer::IsNoteCaption( pObj ) )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool FuDraw::IsSizingOrMovingNote( const MouseEvent& rMEvt ) const
+{
+ bool bIsSizingOrMoving = false;
+ if ( rMEvt.IsLeft() )
+ {
+ const SdrMarkList& rNoteMarkList = pView->GetMarkedObjectList();
+ if(rNoteMarkList.GetMarkCount() == 1)
+ {
+ SdrObject* pObj = rNoteMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if ( ScDrawLayer::IsNoteCaption( pObj ) )
+ {
+ Point aMPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
+ bIsSizingOrMoving =
+ pView->PickHandle( aMPos ) || // handles to resize the note
+ pView->IsTextEditFrameHit( aMPos ); // frame for moving the note
+ }
+ }
+ }
+ return bIsSizingOrMoving;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuins1.cxx b/sc/source/ui/drawfunc/fuins1.cxx
new file mode 100644
index 000000000..c6f2f69da
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuins1.cxx
@@ -0,0 +1,450 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <officecfg/Office/Common.hxx>
+#include <editeng/sizeitem.hxx>
+#include <sal/log.hxx>
+#include <sfx2/opengrf.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdomedia.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdview.hxx>
+#include <svx/linkwarn.hxx>
+#include <svx/svxids.hrc>
+#include <vcl/graphicfilter.hxx>
+#include <svl/stritem.hxx>
+#include <avmedia/mediawindow.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/GraphicNativeTransform.hxx>
+#include <vcl/GraphicNativeMetadata.hxx>
+#include <fuinsert.hxx>
+#include <tabvwsh.hxx>
+#include <drwlayer.hxx>
+#include <drawview.hxx>
+#include <document.hxx>
+#include <scresid.hxx>
+#include <strings.hrc>
+#include <globstr.hrc>
+#include <comphelper/lok.hxx>
+
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/media/XPlayer.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+using namespace css;
+using namespace css::uno;
+
+void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage )
+{
+ if ( !rPage.Width() || !rPage.Height() )
+ return;
+
+ Size aPageSize = rPage;
+ bool bNegative = aPageSize.Width() < 0;
+ if ( bNegative )
+ {
+ // make everything positive temporarily
+ aPageSize.setWidth( -aPageSize.Width() );
+ rPos.setX( -rPos.X() - rSize.Width() );
+ }
+
+ if ( rSize.Width() > aPageSize.Width() || rSize.Height() > aPageSize.Height() )
+ {
+ double fX = aPageSize.Width() / static_cast<double>(rSize.Width());
+ double fY = aPageSize.Height() / static_cast<double>(rSize.Height());
+
+ if ( fX < fY )
+ {
+ rSize.setWidth( aPageSize.Width() );
+ rSize.setHeight( static_cast<tools::Long>( rSize.Height() * fX ) );
+ }
+ else
+ {
+ rSize.setHeight( aPageSize.Height() );
+ rSize.setWidth( static_cast<tools::Long>( rSize.Width() * fY ) );
+ }
+
+ if (!rSize.Width())
+ rSize.setWidth( 1 );
+ if (!rSize.Height())
+ rSize.setHeight( 1 );
+ }
+
+ if ( rPos.X() + rSize.Width() > aPageSize.Width() )
+ rPos.setX( aPageSize.Width() - rSize.Width() );
+ if ( rPos.Y() + rSize.Height() > aPageSize.Height() )
+ rPos.setY( aPageSize.Height() - rSize.Height() );
+
+ if ( bNegative )
+ rPos.setX( -rPos.X() - rSize.Width() ); // back to real position
+}
+
+static void lcl_InsertGraphic( const Graphic& rGraphic,
+ const OUString& rFileName, bool bAsLink, bool bApi,
+ ScTabViewShell& rViewSh, const vcl::Window* pWindow, SdrView* pView,
+ ScAnchorType aAnchorType = SCA_CELL )
+{
+ Graphic& rGraphic1 = const_cast<Graphic &>(rGraphic);
+ GraphicNativeMetadata aMetadata;
+ if ( aMetadata.read(rGraphic1) )
+ {
+ const Degree10 aRotation = aMetadata.getRotation();
+ if (aRotation)
+ {
+ GraphicNativeTransform aTransform( rGraphic1 );
+ aTransform.rotate( aRotation );
+ }
+ }
+ ScDrawView* pDrawView = rViewSh.GetScDrawView();
+
+ // #i123922# check if an existing object is selected; if yes, evtl. replace
+ // the graphic for a SdrGraphObj (including link state updates) or adapt the fill
+ // style for other objects
+ if(pDrawView && 1 == pDrawView->GetMarkedObjectCount())
+ {
+ SdrObject* pPickObj = pDrawView->GetMarkedObjectByIndex(0);
+
+ if(pPickObj)
+ {
+ //sal_Int8 nAction(DND_ACTION_MOVE);
+ //Point aPos;
+ const OUString aBeginUndo(ScResId(STR_UNDO_DRAGDROP));
+
+ SdrObject* pResult = pDrawView->ApplyGraphicToObject(
+ *pPickObj,
+ rGraphic1,
+ aBeginUndo,
+ bAsLink ? rFileName : OUString());
+
+ if(pResult)
+ {
+ // we are done; mark the modified/new object
+ pDrawView->MarkObj(pResult, pDrawView->GetSdrPageView());
+ return;
+ }
+ }
+ }
+
+ // set the size so the graphic has its original pixel size
+ // at 100% view scale (as in SetMarkedOriginalSize),
+ // instead of respecting the current view scale
+ MapMode aSourceMap = rGraphic.GetPrefMapMode();
+ MapMode aDestMap( MapUnit::Map100thMM );
+ if ( aSourceMap.GetMapUnit() == MapUnit::MapPixel && pDrawView )
+ {
+ Fraction aScaleX, aScaleY;
+ pDrawView->CalcNormScale( aScaleX, aScaleY );
+ aDestMap.SetScaleX(aScaleX);
+ aDestMap.SetScaleY(aScaleY);
+ }
+ Size aLogicSize = pWindow->LogicToLogic(
+ rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
+
+ // Limit size
+
+ SdrPageView* pPV = pView->GetSdrPageView();
+ SdrPage* pPage = pPV->GetPage();
+ Point aInsertPos = rViewSh.GetInsertPos();
+
+ ScViewData& rData = rViewSh.GetViewData();
+ if ( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
+ aInsertPos.AdjustX( -(aLogicSize.Width()) ); // move position to left edge
+
+ ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
+
+ tools::Rectangle aRect ( aInsertPos, aLogicSize );
+
+ SdrGrafObj* pObj = new SdrGrafObj(
+ pView->getSdrModelFromSdrView(), // TTTT pView should be reference
+ rGraphic1,
+ aRect);
+
+ // calling SetGraphicLink here doesn't work
+ // Yes, due to the SdrObject had no SdrModel
+ // Path is no longer used as name for the graphics object
+
+ ScDrawLayer* pLayer = static_cast<ScDrawLayer*>(pView->GetModel());
+ OUString aName = pLayer->GetNewGraphicName(); // "Graphics"
+ pObj->SetName(aName);
+
+ if (aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
+ ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rData.GetDocument(), rData.GetTabNo(),
+ aAnchorType == SCA_CELL_RESIZE);
+
+ // don't select if from (dispatch) API, to allow subsequent cell operations
+ SdrInsertFlags nInsOptions = (bApi && !comphelper::LibreOfficeKit::isActive()) ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE;
+ bool bSuccess = pView->InsertObjectAtView( pObj, *pPV, nInsOptions );
+
+ // SetGraphicLink has to be used after inserting the object,
+ // otherwise an empty graphic is swapped in and the contact stuff crashes.
+ // See #i37444#.
+ if (bSuccess && bAsLink)
+ pObj->SetGraphicLink( rFileName );
+}
+
+static void lcl_InsertMedia( const OUString& rMediaURL, bool bApi,
+ ScTabViewShell* pViewSh, const vcl::Window* pWindow, SdrView* pView,
+ const Size& rPrefSize, bool const bLink )
+{
+ SdrPageView* pPV = pView->GetSdrPageView();
+ SdrPage* pPage = pPV->GetPage();
+ ScViewData& rData = pViewSh->GetViewData();
+ Point aInsertPos( pViewSh->GetInsertPos() );
+ Size aSize;
+
+ if( rPrefSize.Width() && rPrefSize.Height() )
+ {
+ if( pWindow )
+ aSize = pWindow->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
+ else
+ aSize = Application::GetDefaultDevice()->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
+ }
+ else
+ aSize = Size( 5000, 5000 );
+
+ ScLimitSizeOnDrawPage( aSize, aInsertPos, pPage->GetSize() );
+
+ if( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
+ aInsertPos.AdjustX( -(aSize.Width()) );
+
+ OUString realURL;
+ if (bLink)
+ {
+ realURL = rMediaURL;
+ }
+ else
+ {
+ uno::Reference<frame::XModel> const xModel(
+ rData.GetDocument().GetDocumentShell()->GetModel());
+#if HAVE_FEATURE_AVMEDIA
+ bool const bRet = ::avmedia::EmbedMedia(xModel, rMediaURL, realURL);
+ if (!bRet) { return; }
+#else
+ return;
+#endif
+ }
+
+ SdrMediaObj* pObj = new SdrMediaObj(
+ *rData.GetDocument().GetDrawLayer(),
+ tools::Rectangle(aInsertPos, aSize));
+
+ pObj->setURL( realURL, ""/*TODO?*/ );
+ pView->InsertObjectAtView( pObj, *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE );
+}
+
+FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh,
+ vcl::Window* pWin,
+ ScDrawView* pViewP,
+ SdrModel* pDoc,
+ SfxRequest& rReq )
+ : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ const SfxStringItem* pGraphicItem;
+ if ( pReqArgs &&
+ (pGraphicItem = pReqArgs->GetItemIfSet( SID_INSERT_GRAPHIC, true )) )
+ {
+ OUString aFileName = pGraphicItem->GetValue();
+
+ OUString aFilterName;
+ if ( const SfxStringItem* pFilterItem = pReqArgs->GetItemIfSet( FN_PARAM_FILTER ) )
+ aFilterName = pFilterItem->GetValue();
+
+ bool bAsLink = false;
+ const SfxPoolItem* pItem;
+ if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
+ bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+
+ Graphic aGraphic;
+ ErrCode nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() );
+ if ( nError == ERRCODE_NONE )
+ {
+ lcl_InsertGraphic( aGraphic, aFileName, bAsLink, true, rViewSh, pWindow, pView );
+ }
+ }
+ else
+ {
+ SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr,
+ ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR);
+
+ Reference<ui::dialogs::XFilePickerControlAccess> xCtrlAcc = aDlg.GetFilePickerControlAccess();
+ sal_Int16 nSelect = 0;
+ Sequence<OUString> aListBoxEntries {
+ ScResId(STR_ANCHOR_TO_CELL),
+ ScResId(STR_ANCHOR_TO_CELL_RESIZE),
+ ScResId(STR_ANCHOR_TO_PAGE)
+ };
+ try
+ {
+ Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
+
+ xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
+ ui::dialogs::ListboxControlActions::ADD_ITEMS, aTemplates);
+
+ Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
+ xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
+ ui::dialogs::ListboxControlActions::SET_SELECT_ITEM, aSelectPos);
+ }
+ catch (const Exception&)
+ {
+ SAL_WARN("sc", "control access failed");
+ }
+
+ if( aDlg.Execute() == ERRCODE_NONE )
+ {
+ Graphic aGraphic;
+ ErrCode nError = aDlg.GetGraphic(aGraphic);
+ if( nError == ERRCODE_NONE )
+ {
+ OUString aFileName = aDlg.GetPath();
+ const OUString& aFilterName = aDlg.GetDetectedFilter();
+ bool bAsLink = aDlg.IsAsLink();
+
+ // really store as link only?
+ if( bAsLink && officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() )
+ {
+ SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName);
+ if (aWarnDlg.run() != RET_OK)
+ bAsLink = false; // don't store as link
+ }
+
+ // Anchor to cell or to page?
+ Any aAnchorValue = xCtrlAcc->getValue(
+ ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
+ ui::dialogs::ListboxControlActions::GET_SELECTED_ITEM );
+ OUString sAnchor;
+ aAnchorValue >>= sAnchor;
+
+ ScAnchorType aAnchorType;
+ if (sAnchor == ScResId(STR_ANCHOR_TO_CELL))
+ aAnchorType = SCA_CELL;
+ else if (sAnchor == ScResId(STR_ANCHOR_TO_CELL_RESIZE))
+ aAnchorType = SCA_CELL_RESIZE;
+ else if (sAnchor == ScResId(STR_ANCHOR_TO_PAGE))
+ aAnchorType = SCA_PAGE;
+ else
+ aAnchorType = SCA_DONTKNOW;
+
+ lcl_InsertGraphic( aGraphic, aFileName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType );
+
+ // append items for recording
+ rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
+ rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
+ rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
+ rReq.Done();
+ }
+ else
+ {
+ // error is handled in SvxOpenGraphicDialog::GetGraphic
+ }
+ }
+ }
+}
+
+FuInsertGraphic::~FuInsertGraphic()
+{
+}
+
+FuInsertMedia::FuInsertMedia( ScTabViewShell& rViewSh,
+ vcl::Window* pWin,
+ ScDrawView* pViewP,
+ SdrModel* pDoc,
+ const SfxRequest& rReq ) :
+ FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+#if HAVE_FEATURE_AVMEDIA
+ OUString aURL;
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+ bool bAPI = false;
+
+ const SvxSizeItem* pSizeItem = rReq.GetArg<SvxSizeItem>(FN_PARAM_1);
+ const SfxBoolItem* pLinkItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
+ const bool bSizeUnknown = !pSizeItem;
+ Size aPrefSize;
+
+ if( pReqArgs )
+ {
+ const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) );
+
+ if( pStringItem )
+ {
+ aURL = pStringItem->GetValue();
+ bAPI = aURL.getLength();
+ }
+ }
+
+ bool bLink(pLinkItem ? pLinkItem->GetValue() : true);
+ bool bInsertMedia = bAPI;
+ if (!bInsertMedia)
+ bInsertMedia = ::avmedia::MediaWindow::executeMediaURLDialog(pWin ? pWin->GetFrameWeld() : nullptr, aURL, &bLink);
+ if (!bInsertMedia)
+ return;
+
+ if (!bSizeUnknown)
+ {
+ aPrefSize = pSizeItem->GetSize();
+ }
+ else
+ {
+ if( pWin )
+ pWin->EnterWait();
+
+ css::uno::Reference<css::frame::XDispatchProvider> xDispatchProvider(rViewShell.GetViewFrame()->GetFrame().GetFrameInterface(), css::uno::UNO_QUERY);
+
+ rtl::Reference<avmedia::PlayerListener> xPlayerListener(new avmedia::PlayerListener(
+ [xDispatchProvider, aURL, bLink](const css::uno::Reference<css::media::XPlayer>& rPlayer){
+ css::awt::Size aSize = rPlayer->getPreferredPlayerWindowSize();
+ avmedia::MediaWindow::dispatchInsertAVMedia(xDispatchProvider, aSize, aURL, bLink);
+ }));
+
+ const bool bIsMediaURL = ::avmedia::MediaWindow::isMediaURL(aURL, ""/*TODO?*/, true, xPlayerListener);
+
+ if( pWin )
+ pWin->LeaveWait();
+
+ if (!bIsMediaURL && !bAPI)
+ ::avmedia::MediaWindow::executeFormatErrorBox(pWindow ? pWindow->GetFrameWeld() : nullptr);
+
+ return;
+ }
+
+ if (pWin)
+ pWin->EnterWait();
+
+ lcl_InsertMedia(aURL, bAPI, &rViewSh, pWindow, pView, aPrefSize, bLink);
+
+ if (pWin)
+ pWin->LeaveWait();
+#endif
+}
+
+FuInsertMedia::~FuInsertMedia()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fuins2.cxx b/sc/source/ui/drawfunc/fuins2.cxx
new file mode 100644
index 000000000..380a5b9ca
--- /dev/null
+++ b/sc/source/ui/drawfunc/fuins2.cxx
@@ -0,0 +1,689 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sot/exchange.hxx>
+#include <svl/globalnameitem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <svx/svdoole2.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <svtools/insdlg.hxx>
+#include <svtools/embedhlp.hxx>
+#include <svx/svxdlg.hxx>
+#include <comphelper/classids.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdundo.hxx>
+#include <sfx2/msgpool.hxx>
+#include <sfx2/msg.hxx>
+#include <scmod.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <cppuhelper/bootstrap.hxx>
+#include <svtools/dialogclosedlistener.hxx>
+
+#include <PivotTableDataProvider.hxx>
+#include <chart2uno.hxx>
+#include <fuinsert.hxx>
+#include <tabvwsh.hxx>
+#include <sc.hrc>
+#include <chartpos.hxx>
+#include <docsh.hxx>
+#include <document.hxx>
+#include <undotab.hxx>
+#include <uiitems.hxx>
+#include <drawview.hxx>
+#include <markdata.hxx>
+#include <dpobject.hxx>
+#include <memory>
+
+using namespace css;
+
+namespace
+{
+
+void lcl_ChartInit(const uno::Reference <embed::XEmbeddedObject>& xObj, ScViewData* pViewData,
+ const OUString& rRangeParam, bool bRangeIsPivotTable)
+{
+ ScDocShell* pDocShell = pViewData->GetDocShell();
+ ScDocument& rScDoc = pDocShell->GetDocument();
+
+ OUString aRangeString(rRangeParam);
+
+ if (aRangeString.isEmpty() && !bRangeIsPivotTable)
+ {
+ SCCOL nCol1 = 0;
+ SCROW nRow1 = 0;
+ SCTAB nTab1 = 0;
+ SCCOL nCol2 = 0;
+ SCROW nRow2 = 0;
+ SCTAB nTab2 = 0;
+
+ ScMarkData& rMark = pViewData->GetMarkData();
+ if ( !rMark.IsMarked() )
+ pViewData->GetView()->MarkDataArea();
+
+ if ( pViewData->GetSimpleArea( nCol1,nRow1,nTab1, nCol2,nRow2,nTab2 ) == SC_MARK_SIMPLE )
+ {
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ if (nCol2 >= nCol1 || nRow2 >= nRow1)
+ {
+ ScDocument& rDoc = pViewData->GetDocument();
+ rDoc.LimitChartArea( nTab1, nCol1,nRow1, nCol2,nRow2 );
+
+ ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ aRangeString = aRange.Format(rScDoc, ScRefFlags::RANGE_ABS_3D, rScDoc.GetAddressConvention());
+ }
+ }
+ }
+
+ if (aRangeString.isEmpty())
+ return;
+
+ // connect to Calc data (if no range string, leave chart alone, with its own data)
+
+ uno::Reference< css::chart2::data::XDataReceiver > xReceiver;
+ if( xObj.is())
+ xReceiver.set( xObj->getComponent(), uno::UNO_QUERY );
+ OSL_ASSERT( xReceiver.is());
+ if( !xReceiver.is() )
+ return;
+
+ uno::Reference<chart2::data::XDataProvider> xDataProvider;
+ if (bRangeIsPivotTable)
+ {
+ rtl::Reference<sc::PivotTableDataProvider> pPivotTableDataProvider(new sc::PivotTableDataProvider(rScDoc));
+ pPivotTableDataProvider->setPivotTableName(aRangeString);
+ xDataProvider = pPivotTableDataProvider;
+ }
+ else
+ {
+ xDataProvider.set(new ScChart2DataProvider(&rScDoc));
+ }
+
+ xReceiver->attachDataProvider(xDataProvider);
+
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pDocShell->GetModel(), uno::UNO_QUERY );
+ xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
+
+ // Same behavior as with old chart: Always assume data series in columns
+ chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
+ bool bHasCategories = false;
+ bool bFirstCellAsLabel = false;
+
+ // use ScChartPositioner to auto-detect column/row headers (like ScChartArray in old version)
+ ScRangeListRef aRangeListRef( new ScRangeList );
+ aRangeListRef->Parse( aRangeString, rScDoc, rScDoc.GetAddressConvention() );
+ if ( !aRangeListRef->empty() )
+ {
+ rScDoc.LimitChartIfAll( aRangeListRef ); // limit whole columns/rows to used area
+
+ // update string from modified ranges. The ranges must be in the current formula syntax.
+ OUString aTmpStr;
+ aRangeListRef->Format( aTmpStr, ScRefFlags::RANGE_ABS_3D, rScDoc, rScDoc.GetAddressConvention() );
+ aRangeString = aTmpStr;
+
+ ScChartPositioner aChartPositioner( rScDoc, aRangeListRef );
+ const ScChartPositionMap* pPositionMap( aChartPositioner.GetPositionMap() );
+ if( pPositionMap )
+ {
+ SCSIZE nRowCount = pPositionMap->GetRowCount();
+ if( 1==nRowCount )
+ eDataRowSource = chart::ChartDataRowSource_ROWS;
+ }
+ if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
+ {
+ bHasCategories = aChartPositioner.HasRowHeaders();
+ bFirstCellAsLabel = aChartPositioner.HasColHeaders();
+ }
+ else // in case the default is changed
+ {
+ bHasCategories = aChartPositioner.HasColHeaders();
+ bFirstCellAsLabel = aChartPositioner.HasRowHeaders();
+ }
+ }
+
+ uno::Sequence< beans::PropertyValue > aArgs{
+ beans::PropertyValue(
+ "CellRangeRepresentation", -1,
+ uno::Any( aRangeString ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "HasCategories", -1,
+ uno::Any( bHasCategories ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "FirstCellAsLabel", -1,
+ uno::Any( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "DataRowSource", -1,
+ uno::Any( eDataRowSource ), beans::PropertyState_DIRECT_VALUE )
+ };
+
+ try
+ {
+ xReceiver->setArguments( aArgs );
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ // Can happen for invalid aRangeString, in which case a Chart
+ // will be created nevertheless and the range string can be
+ // edited.
+ TOOLS_WARN_EXCEPTION("sc.ui",
+ "lcl_ChartInit - caught IllegalArgumentException might be due to aRangeString: " << aRangeString);
+ }
+
+ // don't create chart listener here (range may be modified in chart dialog)
+}
+
+}
+
+FuInsertOLE::FuInsertOLE(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, SfxRequest& rReq)
+ : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+ if( ! rReq.IsAPI() )
+ rReq.Done();
+
+ //! initialize DLLs here, so that the factories exist?
+
+ uno::Reference < embed::XEmbeddedObject > xObj;
+ uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
+ bool bIsFromFile = false;
+ OUString aName;
+
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+ OUString aIconMediaType;
+ uno::Reference< io::XInputStream > xIconMetaFile;
+
+ const sal_uInt16 nSlot = rReq.GetSlot();
+ const SfxGlobalNameItem* pNameItem = rReq.GetArg<SfxGlobalNameItem>(SID_INSERT_OBJECT);
+ if ( nSlot == SID_INSERT_OBJECT && pNameItem )
+ {
+ const SvGlobalName& aClassName = pNameItem->GetValue();
+ xObj = rViewShell.GetViewFrame()->GetObjectShell()->GetEmbeddedObjectContainer().CreateEmbeddedObject( aClassName.GetByteSequence(), aName );
+ }
+ else if ( nSlot == SID_INSERT_SMATH )
+ {
+ if ( SvtModuleOptions().IsMath() )
+ {
+ xObj = rViewShell.GetViewFrame()->GetObjectShell()->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_SM_CLASSID_60 ).GetByteSequence(), aName );
+ rReq.AppendItem( SfxGlobalNameItem( SID_INSERT_OBJECT, SvGlobalName( SO3_SM_CLASSID_60 ) ) );
+ }
+ }
+ else
+ {
+ SvObjectServerList aServerLst;
+ switch ( nSlot )
+ {
+ case SID_INSERT_OBJECT :
+ aServerLst.FillInsertObjects();
+ aServerLst.Remove( ScDocShell::Factory().GetClassId() ); // Do not show Starcalc
+ //TODO/LATER: currently no inserting of ClassId into SfxRequest!
+ [[fallthrough]]; //TODO ???
+ case SID_INSERT_FLOATINGFRAME :
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(
+ pFact->CreateInsertObjectDialog( rViewShell.GetFrameWeld(), SC_MOD()->GetSlotPool()->GetSlot(nSlot)->GetCommandString(),
+ xStorage, &aServerLst ));
+ if ( pDlg )
+ {
+ pDlg->Execute();
+ xObj = pDlg->GetObject();
+
+ xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
+ if ( xIconMetaFile.is() )
+ nAspect = embed::Aspects::MSOLE_ICON;
+
+ if ( xObj.is() )
+ rViewSh.GetObjectShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aName );
+ // to activate DrawShell (no need to activate Object)
+ bIsFromFile = !pDlg->IsCreateNew();
+ }
+
+ break;
+ }
+ }
+ }
+
+ // SvInsertObjectDialog (everything in one Dialog) are not used anymore
+ if (xObj.is())
+ {
+ pView->UnmarkAll();
+
+ try
+ {
+ ::svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
+ Size aSize;
+ MapMode aMap100( MapUnit::Map100thMM );
+ MapUnit aMapUnit = MapUnit::Map100thMM;
+
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ {
+ aObjRef.SetGraphicStream( xIconMetaFile, aIconMediaType );
+ aSize = aObjRef.GetSize( &aMap100 );
+ }
+ else
+ {
+ awt::Size aSz;
+ try
+ {
+ aSz = xObj->getVisualAreaSize( nAspect );
+ }
+ catch( embed::NoVisualAreaSizeException& )
+ {
+ // the default size will be set later
+ }
+
+ aSize = Size( aSz.Width, aSz.Height );
+
+ aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+ if (aSize.IsEmpty())
+ {
+ // rectangle with balanced edge ratio
+ aSize.setWidth( 5000 );
+ aSize.setHeight( 5000 );
+ Size aTmp = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aMapUnit));
+ aSz.Width = aTmp.Width();
+ aSz.Height = aTmp.Height();
+ xObj->setVisualAreaSize( nAspect, aSz );
+
+ // re-convert aSize to 1/100th mm to avoid rounding errors in comparison below
+ aSize = OutputDevice::LogicToLogic( aTmp,
+ MapMode( aMapUnit ), aMap100 );
+ }
+ else
+ aSize = OutputDevice::LogicToLogic( aSize,
+ MapMode( aMapUnit ), aMap100 );
+ }
+
+ // initialize chart ?
+ if ( SvtModuleOptions().IsChart() && SotExchange::IsChart( SvGlobalName( xObj->getClassID() ) ) )
+ lcl_ChartInit(xObj, &rViewSh.GetViewData(), OUString(), false);
+
+ ScViewData& rData = rViewSh.GetViewData();
+
+ Point aPnt = rViewSh.GetInsertPos();
+ if ( rData.GetDocument().IsNegativePage( rData.GetTabNo() ) )
+ aPnt.AdjustX( -(aSize.Width()) ); // move position to left edge
+ tools::Rectangle aRect (aPnt, aSize);
+ SdrOle2Obj* pObj = new SdrOle2Obj(
+ *pDoc, // TTTT should be reference
+ aObjRef,
+ aName,
+ aRect);
+ SdrPageView* pPV = pView->GetSdrPageView();
+ bool bSuccess = pView->InsertObjectAtView(pObj, *pPV);
+
+ if (bSuccess && nAspect != embed::Aspects::MSOLE_ICON)
+ {
+ // Math objects change their object size during InsertObject.
+ // New size must be set in SdrObject, or a wrong scale will be set at
+ // ActivateObject.
+
+ try
+ {
+ awt::Size aSz = xObj->getVisualAreaSize( nAspect );
+
+ Size aNewSize( aSz.Width, aSz.Height );
+ aNewSize = OutputDevice::LogicToLogic(aNewSize, MapMode(aMapUnit), MapMode(MapUnit::Map100thMM));
+
+ if ( aNewSize != aSize )
+ {
+ aRect.SetSize( aNewSize );
+ pObj->SetLogicRect( aRect );
+ }
+ }
+ catch( embed::NoVisualAreaSizeException& )
+ {}
+ }
+
+ if ( !rReq.IsAPI() )
+ {
+ // XXX Activate from macro is deadly !!! ???
+ if (bIsFromFile)
+ {
+ // Object selected, activate Draw-Shell
+ rViewShell.SetDrawShell( true );
+ }
+ else if (bSuccess)
+ {
+ rViewShell.ActivateObject(pObj, embed::EmbedVerbs::MS_OLEVERB_SHOW);
+ }
+ }
+
+ rReq.Done();
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( "May need error handling here!" );
+ }
+ }
+ else
+ rReq.Ignore();
+}
+
+FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, SfxRequest& rReq, const Link<css::ui::dialogs::DialogClosedEvent*, void>& rLink)
+ : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+ const SfxItemSet* pReqArgs = rReq.GetArgs();
+
+ if( ! rReq.IsAPI() )
+ rReq.Done();
+
+ if (!SvtModuleOptions().IsChart())
+ return;
+
+ // BM/IHA --
+
+ // get range
+ OUString aRangeString;
+ bool bRangeIsPivotTable = false;
+ ScRange aPositionRange; // cell range for chart positioning
+ ScMarkData aMark = rViewSh.GetViewData().GetMarkData();
+ if( pReqArgs )
+ {
+ const SfxPoolItem* pItem;
+ if( pReqArgs->HasItem( FN_PARAM_5, &pItem ) )
+ aRangeString = static_cast<const SfxStringItem*>(pItem)->GetValue();
+
+ aPositionRange = rViewSh.GetViewData().GetCurPos();
+ }
+ else
+ {
+ ScDocument& rDocument = rViewSh.GetViewData().GetDocument();
+ ScDPObject* pObject = rDocument.GetDPAtCursor(rViewSh.GetViewData().GetCurX(),
+ rViewSh.GetViewData().GetCurY(),
+ rViewSh.GetViewData().GetTabNo());
+ if (pObject)
+ {
+ aRangeString = pObject->GetName();
+ bRangeIsPivotTable = true;
+ }
+ else
+ {
+ bool bAutomaticMark = false;
+ if ( !aMark.IsMarked() && !aMark.IsMultiMarked() )
+ {
+ rViewSh.GetViewData().GetView()->MarkDataArea();
+ bAutomaticMark = true;
+ }
+
+ ScMarkData aMultiMark( aMark );
+ aMultiMark.MarkToMulti();
+
+ ScRangeList aRanges;
+ aMultiMark.FillRangeListWithMarks( &aRanges, false );
+ OUString aStr;
+ aRanges.Format( aStr, ScRefFlags::RANGE_ABS_3D, rDocument, rDocument.GetAddressConvention() );
+ aRangeString = aStr;
+
+ // get "total" range for positioning
+ if ( !aRanges.empty() )
+ {
+ aPositionRange = aRanges[ 0 ];
+ for ( size_t i = 1, nCount = aRanges.size(); i < nCount; ++i )
+ {
+ aPositionRange.ExtendTo( aRanges[ i ] );
+ }
+ }
+
+ if(bAutomaticMark)
+ rViewSh.GetViewData().GetView()->Unmark();
+ }
+ }
+
+ // adapted old code
+ pView->UnmarkAll();
+
+ OUString aName;
+ const sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+
+ uno::Reference < embed::XEmbeddedObject > xObj =
+ rViewShell.GetObjectShell()->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID_60 ).GetByteSequence(), aName );
+
+ uno::Reference< css::chart2::data::XDataReceiver > xReceiver;
+ if( xObj.is())
+ xReceiver.set( xObj->getComponent(), uno::UNO_QUERY );
+
+ uno::Reference<chart2::XChartDocument> xChartDoc(xReceiver, uno::UNO_QUERY);
+ if (xChartDoc.is())
+ xChartDoc->createDefaultChart();
+
+ // lock the model to suppress any internal updates
+ uno::Reference< frame::XModel > xChartModel( xReceiver, uno::UNO_QUERY );
+ if( xChartModel.is() )
+ xChartModel->lockControllers();
+
+ // object size
+ awt::Size aSz = xObj->getVisualAreaSize( nAspect );
+ Size aSize( aSz.Width, aSz.Height );
+
+ MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+
+ bool bSizeCh = false;
+ if (aSize.IsEmpty())
+ {
+ aSize.setWidth( 5000 );
+ aSize.setHeight( 5000 );
+ bSizeCh = true;
+ }
+ if (bSizeCh)
+ {
+ aSize = OutputDevice::LogicToLogic( aSize, MapMode( MapUnit::Map100thMM ), MapMode( aMapUnit ) );
+ aSz.Width = aSize.Width();
+ aSz.Height = aSize.Height();
+ xObj->setVisualAreaSize( nAspect, aSz );
+ }
+
+ ScViewData& rData = rViewSh.GetViewData();
+ ScDocShell* pScDocSh = rData.GetDocShell();
+ ScDocument& rScDoc = pScDocSh->GetDocument();
+ bool bUndo (rScDoc.IsUndoEnabled());
+
+ if( pReqArgs )
+ {
+ const SfxPoolItem* pItem;
+ sal_uInt16 nToTable = 0;
+
+ if( pReqArgs->HasItem( FN_PARAM_4, &pItem ) )
+ {
+ if ( auto pUInt16Item = dynamic_cast<const SfxUInt16Item*>( pItem) )
+ nToTable = pUInt16Item->GetValue();
+ else if ( auto pBoolItem = dynamic_cast<const SfxBoolItem*>( pItem) )
+ {
+ // In IDL for Basic FN_PARAM_4 means SfxBoolItem
+ // -> if set new table, else current table
+
+ if ( pBoolItem->GetValue() )
+ nToTable = static_cast<sal_uInt16>(rScDoc.GetTableCount());
+ else
+ nToTable = static_cast<sal_uInt16>(rData.GetTabNo());
+ }
+ }
+ else
+ {
+ rReq.AppendItem( SfxUInt16Item( FN_PARAM_4, nToTable ) );
+ }
+
+ // Output on new table?
+ if ( nToTable == rScDoc.GetTableCount() )
+ {
+ // Let's go...
+ OUString aTabName;
+ SCTAB nNewTab = rScDoc.GetTableCount();
+
+ rScDoc.CreateValidTabName( aTabName );
+
+ if ( rScDoc.InsertTab( nNewTab, aTabName ) )
+ {
+ if (bUndo)
+ {
+ pScDocSh->GetUndoManager()->AddUndoAction(
+ std::make_unique<ScUndoInsertTab>( pScDocSh, nNewTab,
+ true/*bAppend*/, aTabName ) );
+ }
+
+ pScDocSh->Broadcast( ScTablesHint( SC_TAB_INSERTED, nNewTab ) );
+ rViewSh.SetTabNo( nNewTab, true );
+ pScDocSh->PostPaintExtras(); //! done afterwards ???
+ }
+ else
+ {
+ OSL_FAIL( "Could not create new table :-/" );
+ }
+ }
+ else if ( nToTable != rData.GetTabNo() )
+ {
+ rViewSh.SetTabNo( nToTable, true );
+ }
+ }
+
+ lcl_ChartInit(xObj, &rData, aRangeString, bRangeIsPivotTable); // set source range, auto-detect column/row headers
+
+ // object position
+
+ // get chart position (from window size and data range)
+ Point aStart = rViewSh.GetChartInsertPos( aSize, aPositionRange );
+
+ tools::Rectangle aRect (aStart, aSize);
+ SdrOle2Obj* pObj = new SdrOle2Obj(
+ *pDoc, // TTTT should be reference
+ svt::EmbeddedObjectRef(xObj, nAspect),
+ aName,
+ aRect);
+ SdrPageView* pPV = pView->GetSdrPageView();
+
+ // #i121334# This call will change the chart's default background fill from white to transparent.
+ // Add here again if this is wanted (see task description for details)
+ // ChartHelper::AdaptDefaultsForChart( xObj );
+
+// pView->InsertObjectAtView(pObj, *pPV);//this call leads to an immediate redraw and asks the chart for a visual representation
+
+ // use the page instead of the view to insert, so no undo action is created yet
+ SdrPage* pPage = pPV->GetPage();
+ pPage->InsertObject( pObj );
+ pView->UnmarkAllObj();
+ pView->MarkObj( pObj, pPV );
+
+ if (rReq.IsAPI())
+ {
+ if( xChartModel.is() )
+ xChartModel->unlockControllers();
+ }
+ else if (!rViewSh.isLOKMobilePhone())
+ {
+ //the controller will be unlocked by the dialog when the dialog is told to do so
+
+ // only activate object if not called via API (e.g. macro)
+ if (!comphelper::LibreOfficeKit::isActive())
+ rViewShell.ActivateObject(pObj, embed::EmbedVerbs::MS_OLEVERB_SHOW);
+
+ //open wizard
+ //@todo get context from calc if that has one
+ uno::Reference< uno::XComponentContext > xContext(
+ ::cppu::defaultBootstrap_InitialComponentContext() );
+ if(xContext.is())
+ {
+ uno::Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
+ if(xMCF.is())
+ {
+ css::uno::Reference<css::ui::dialogs::XAsynchronousExecutableDialog> xDialog(
+ xMCF->createInstanceWithContext(
+ "com.sun.star.comp.chart2.WizardDialog"
+ , xContext), uno::UNO_QUERY);
+ uno::Reference< lang::XInitialization > xInit( xDialog, uno::UNO_QUERY );
+ if( xChartModel.is() && xInit.is() )
+ {
+ uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
+ {
+ {"ParentWindow", uno::Any(uno::Reference< awt::XWindow >())},
+ {"ChartModel", uno::Any(xChartModel)}
+ }));
+ xInit->initialize( aSeq );
+
+ // try to set the dialog's position so it doesn't hide the chart
+ uno::Reference < beans::XPropertySet > xDialogProps( xDialog, uno::UNO_QUERY );
+ if ( xDialogProps.is() )
+ {
+ try
+ {
+ //get dialog size:
+ awt::Size aDialogAWTSize;
+ if( xDialogProps->getPropertyValue("Size")
+ >>= aDialogAWTSize )
+ {
+ Size aDialogSize( aDialogAWTSize.Width, aDialogAWTSize.Height );
+ if ( !aDialogSize.IsEmpty() )
+ {
+ //calculate and set new position
+ Point aDialogPos = rViewShell.GetChartDialogPos( aDialogSize, aRect );
+ xDialogProps->setPropertyValue("Position",
+ uno::Any( awt::Point(aDialogPos.getX(),aDialogPos.getY()) ) );
+ }
+ }
+ //tell the dialog to unlock controller
+ xDialogProps->setPropertyValue("UnlockControllersOnExecute",
+ uno::Any( true ) );
+
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( "Chart wizard couldn't be positioned automatically" );
+ }
+ }
+
+ pView->AddUndo(std::make_unique<SdrUndoNewObj>(*pObj));
+ rtl::Reference<::svt::DialogClosedListener> pListener = new ::svt::DialogClosedListener();
+ pListener->SetDialogClosedLink( rLink );
+
+ xDialog->startExecuteModal( pListener );
+ }
+ else
+ {
+ uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY );
+ if( xComponent.is())
+ xComponent->dispose();
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fupoor.cxx b/sc/source/ui/drawfunc/fupoor.cxx
new file mode 100644
index 000000000..decfacebe
--- /dev/null
+++ b/sc/source/ui/drawfunc/fupoor.cxx
@@ -0,0 +1,280 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/outliner.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svxids.hrc>
+
+#include <fupoor.hxx>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+#include <detfunc.hxx>
+#include <document.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/sdrhittesthelper.hxx>
+
+FuPoor::FuPoor(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq) :
+ pView(pViewP),
+ rViewShell(rViewSh),
+ pWindow(pWin),
+ pDrDoc(pDoc),
+ aSfxRequest(rReq),
+ aScrollTimer("sc FuPoor aScrollTimer"),
+ aDragTimer("sc FuPoor aDragTimer"),
+ bIsInDragMode(false),
+ // remember MouseButton state
+ mnCode(0)
+{
+ aScrollTimer.SetInvokeHandler( LINK(this, FuPoor, ScrollHdl) );
+ aScrollTimer.SetTimeout(SELENG_AUTOREPEAT_INTERVAL);
+
+ aDragTimer.SetInvokeHandler( LINK(this, FuPoor, DragTimerHdl) );
+ aDragTimer.SetTimeout(SELENG_DRAGDROP_TIMEOUT);
+}
+
+FuPoor::~FuPoor()
+{
+ aDragTimer.Stop();
+ aScrollTimer.Stop();
+}
+
+void FuPoor::Activate()
+{
+}
+
+void FuPoor::Deactivate()
+{
+ aDragTimer.Stop();
+ aScrollTimer.Stop();
+}
+
+// Scroll when reached the window border; is called from MouseMove
+void FuPoor::ForceScroll(const Point& aPixPos)
+{
+ aScrollTimer.Stop();
+
+ Size aSize = pWindow->GetSizePixel();
+ SCCOL dx = 0;
+ SCROW dy = 0;
+
+ if ( aPixPos.X() <= 0 ) dx = -1;
+ if ( aPixPos.X() >= aSize.Width() ) dx = 1;
+ if ( aPixPos.Y() <= 0 ) dy = -1;
+ if ( aPixPos.Y() >= aSize.Height() ) dy = 1;
+
+ ScViewData& rViewData = rViewShell.GetViewData();
+ if ( rViewData.GetDocument().IsNegativePage( rViewData.GetTabNo() ) )
+ dx = -dx;
+
+ ScSplitPos eWhich = rViewData.GetActivePart();
+ if ( dx > 0 && rViewData.GetHSplitMode() == SC_SPLIT_FIX && WhichH(eWhich) == SC_SPLIT_LEFT )
+ {
+ rViewShell.ActivatePart( ( eWhich == SC_SPLIT_TOPLEFT ) ?
+ SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT );
+ dx = 0;
+ }
+ if ( dy > 0 && rViewData.GetVSplitMode() == SC_SPLIT_FIX && WhichV(eWhich) == SC_SPLIT_TOP )
+ {
+ rViewShell.ActivatePart( ( eWhich == SC_SPLIT_TOPLEFT ) ?
+ SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT );
+ dy = 0;
+ }
+
+ if ( dx != 0 || dy != 0 )
+ {
+ rViewShell.ScrollLines(2*dx, 4*dy);
+ aScrollTimer.Start();
+ }
+}
+
+// Timer handler for window scrolling
+IMPL_LINK_NOARG(FuPoor, ScrollHdl, Timer *, void)
+{
+ Point aPosPixel = pWindow->GetPointerPosPixel();
+
+ // use remembered MouseButton state to create correct
+ // MouseEvents for this artificial MouseMove.
+ MouseMove(MouseEvent(aPosPixel, 1, MouseEventModifiers::NONE, GetMouseButtonCode()));
+}
+
+bool FuPoor::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ return false;
+}
+
+bool FuPoor::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ return false;
+}
+
+// If we handle a KeyEvent, then the return value is sal_True else FALSE.
+bool FuPoor::KeyInput(const KeyEvent& /* rKEvt */)
+{
+ return false;
+}
+
+sal_uInt8 FuPoor::Command(const CommandEvent& rCEvt)
+{
+ if ( CommandEventId::StartDrag == rCEvt.GetCommand() )
+ {
+ // Only if a selection is in Outliner, then Command is allowed
+ // to return sal_True
+
+ OutlinerView* pOutView = pView->GetTextEditOutlinerView();
+
+ if ( pOutView )
+ return pOutView->HasSelection() ? (pView->Command(rCEvt,pWindow) ? 1 : 0) : SC_CMD_NONE;
+ else
+ return pView->Command(rCEvt,pWindow) ? 1 : 0;
+ }
+ else
+ return pView->Command(rCEvt,pWindow) ? 1 : 0;
+}
+
+// Timer-Handler for Drag&Drop
+IMPL_LINK_NOARG(FuPoor, DragTimerHdl, Timer *, void)
+{
+ // Calling ExecuteDrag (and that associated reschedule) directly from
+ // the Timer, will confuse the VCL-Timer-Management, if (e.g during Drop)
+ // a new timer is started (e.g ComeBack-Timer of DrawView for
+ // Solid Handles / ModelHasChanged) - the new timer will end with a delay
+ // of the duration of the Drag&Drop.
+ // Therefore Drag&Drop from own event:
+
+ Application::PostUserEvent( LINK( this, FuPoor, DragHdl ) );
+}
+
+IMPL_LINK_NOARG(FuPoor, DragHdl, void*, void)
+{
+ SdrHdl* pHdl = pView->PickHandle(aMDPos);
+
+ if ( pHdl==nullptr && pView->IsMarkedHit(aMDPos) )
+ {
+ pWindow->ReleaseMouse();
+ bIsInDragMode = true;
+ rViewShell.GetScDrawView()->BeginDrag(pWindow, aMDPos);
+ }
+}
+
+// Detective-line
+bool FuPoor::IsDetectiveHit( const Point& rLogicPos )
+{
+ SdrPageView* pPV = pView->GetSdrPageView();
+ if (!pPV)
+ return false;
+
+ bool bFound = false;
+ SdrObjListIter aIter( pPV->GetObjList(), SdrIterMode::Flat );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if (ScDetectiveFunc::IsNonAlienArrow( pObject ))
+ {
+ sal_uInt16 nHitLog = static_cast<sal_uInt16>(pWindow->PixelToLogic(
+ Size(pView->GetHitTolerancePixel(),0)).Width());
+ if(SdrObjectPrimitiveHit(*pObject, rLogicPos, nHitLog, *pPV, nullptr, false))
+ {
+ bFound = true;
+ }
+ }
+
+ pObject = aIter.Next();
+ }
+ return bFound;
+}
+
+void FuPoor::StopDragTimer()
+{
+ if (aDragTimer.IsActive() )
+ aDragTimer.Stop();
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuPoor::CreateDefaultObject(const sal_uInt16 /* nID */, const tools::Rectangle& /* rRectangle */)
+{
+ // empty base implementation
+ return nullptr;
+}
+
+void FuPoor::ImpForceQuadratic(tools::Rectangle& rRect)
+{
+ if(rRect.GetWidth() > rRect.GetHeight())
+ {
+ rRect = tools::Rectangle(
+ Point(rRect.Left() + ((rRect.GetWidth() - rRect.GetHeight()) / 2), rRect.Top()),
+ Size(rRect.GetHeight(), rRect.GetHeight()));
+ }
+ else
+ {
+ rRect = tools::Rectangle(
+ Point(rRect.Left(), rRect.Top() + ((rRect.GetHeight() - rRect.GetWidth()) / 2)),
+ Size(rRect.GetWidth(), rRect.GetWidth()));
+ }
+}
+
+// #i33136# fdo#88339
+bool FuPoor::doConstructOrthogonal() const
+{
+ // Detect whether we're moving an object or resizing.
+ if (pView->IsDragObj())
+ {
+ const SdrHdl* pHdl = pView->GetDragStat().GetHdl();
+ if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
+ {
+ return false;
+ }
+ }
+
+ // Detect image/media and resize proportionally, but don't constrain movement by default
+ if (pView->AreObjectsMarked())
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if (rMarkList.GetMarkCount() == 1)
+ {
+ SdrObjKind aObjIdentifier = rMarkList.GetMark(0)->GetMarkedSdrObj()->GetObjIdentifier();
+ bool bIsMediaSelected = aObjIdentifier == SdrObjKind::Graphic ||
+ aObjIdentifier == SdrObjKind::Media ||
+ aObjIdentifier == SdrObjKind::OLE2;
+
+ SdrHdl* pHdl = pView->PickHandle(aMDPos);
+ // Resize proportionally when media is selected and the user drags on a corner
+ if (pHdl)
+ return bIsMediaSelected && pHdl->IsCornerHdl();
+ return bIsMediaSelected;
+ }
+ }
+ else if (aSfxRequest.GetSlot() == SID_DRAW_XPOLYGON
+ || aSfxRequest.GetSlot() == SID_DRAW_XPOLYGON_NOFILL
+ || aSfxRequest.GetSlot() == SID_DRAW_XLINE)
+ return true;
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fusel.cxx b/sc/source/ui/drawfunc/fusel.cxx
new file mode 100644
index 000000000..46b7fc47d
--- /dev/null
+++ b/sc/source/ui/drawfunc/fusel.cxx
@@ -0,0 +1,546 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/EmbedVerbs.hpp>
+#include <editeng/flditem.hxx>
+#include <svx/svddrgmt.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdotext.hxx>
+#include <sfx2/dispatch.hxx>
+#include <vcl/imapobj.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/svdomedia.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/ImageMapInfo.hxx>
+#include <editeng/outlobj.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/ipclient.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <comphelper/lok.hxx>
+
+#include <fusel.hxx>
+#include <sc.hrc>
+#include <fudraw.hxx>
+#include <futext.hxx>
+#include <drawview.hxx>
+#include <tabvwsh.hxx>
+#include <drwlayer.hxx>
+#include <userdat.hxx>
+#include <scmod.hxx>
+#include <charthelper.hxx>
+#include <docuno.hxx>
+#include <docsh.hxx>
+
+// maximal permitted mouse movement to start Drag&Drop
+//! fusel,fuconstr,futext - combine them!
+#define SC_MAXDRAGMOVE 3
+// Min necessary mouse motion for normal dragging
+#define SC_MINDRAGMOVE 2
+
+using namespace com::sun::star;
+
+FuSelection::FuSelection(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuDraw(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+}
+
+FuSelection::~FuSelection()
+{
+}
+
+bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+ const bool bSelectionOnly = rMEvt.IsRight();
+ if ( pView->IsAction() )
+ {
+ if ( bSelectionOnly )
+ pView->BckAction();
+ return true;
+ }
+
+ bIsInDragMode = false; // somewhere it has to be reset (#50033#)
+
+ bool bReturn = FuDraw::MouseButtonDown(rMEvt);
+ auto aLogicPosition = rMEvt.getLogicPosition();
+ if (aLogicPosition)
+ aMDPos = *aLogicPosition;
+ else
+ aMDPos = pWindow->PixelToLogic(rMEvt.GetPosPixel());
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ ScViewData& rViewData = rViewShell.GetViewData();
+ ScDocument& rDocument = rViewData.GetDocument();
+ if (rDocument.IsNegativePage(rViewData.GetTabNo()))
+ aMDPos.setX(-aMDPos.X());
+ }
+
+ if ( rMEvt.IsLeft() )
+ {
+ SdrHdl* pHdl = pView->PickHandle(aMDPos);
+
+ if ( pHdl!=nullptr || pView->IsMarkedHit(aMDPos) )
+ {
+ // Determine if this is the tail of a SdrCaptionObj i.e.
+ // we need to disable the drag option on the tail of a note
+ // object. Also, disable the ability to use the circular
+ // drag of a note object.
+ bool bDrag = false;
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
+ {
+ // move using the valid caption handles for note text box.
+ if(pHdl && (pHdl->GetKind() != SdrHdlKind::Poly && pHdl->GetKind() != SdrHdlKind::Circle))
+ bDrag = true;
+ // move the complete note box.
+ else if(!pHdl)
+ bDrag = true;
+ }
+ else
+ bDrag = true; // different object
+ }
+ else
+ bDrag = true; // several objects
+
+ if ( bDrag )
+ {
+ aDragTimer.Start();
+ if (pView->BegDragObj(aMDPos, nullptr, pHdl))
+ pView->GetDragMethod()->SetShiftPressed( rMEvt.IsShift() );
+ bReturn = true;
+ }
+ }
+ else
+ {
+ SdrPageView* pPV = nullptr;
+ bool bAlt = rMEvt.IsMod2();
+ SdrObject* pObj = !bAlt ? pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) : nullptr;
+ if (pObj)
+ {
+ pView->BegMacroObj(aMDPos, pObj, pPV, pWindow);
+ bReturn = true;
+ }
+ else
+ {
+ OUString sURL, sTarget;
+ pObj = !bAlt ? pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
+ if (pObj)
+ {
+ // Support for imported Excel docs
+ // Excel is of course not consistent and allows
+ // a hyperlink to be assigned for an object group
+ // and even though the hyperlink is exported in the Escher layer
+ // its never used, when dealing with a group object the link
+ // associated with the clicked object is used only
+
+ // additionally you can also select a macro in Excel for a grouped
+ // objects and this *usually* results in the macro being set
+ // for the elements in the group and no macro is exported
+ // for the group itself ( this however is not always true )
+ // if a macro and hlink are defined favour the hlink
+ // If a group object has no hyperlink use the hyperlink of the
+ // object clicked
+
+ if ( pObj->IsGroupObject() )
+ {
+ ScMacroInfo* pTmpInfo = ScDrawLayer::GetMacroInfo( pObj );
+ if ( !pTmpInfo || pTmpInfo->GetMacro().isEmpty() )
+ {
+ SdrObject* pHit = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
+ if (pHit)
+ pObj = pHit;
+ }
+ }
+
+ ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, true );
+ // For interoperability favour links over macros if both are defined
+ if ( !pObj->getHyperlink().isEmpty() )
+ {
+ sURL = pObj->getHyperlink();
+ }
+ else if ( !pInfo->GetMacro().isEmpty() )
+ {
+ SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ if ( pObjSh && SfxApplication::IsXScriptURL( pInfo->GetMacro() ) )
+ {
+ uno::Reference< beans::XPropertySet > xProps( pObj->getUnoShape(), uno::UNO_QUERY );
+ uno::Any aCaller;
+ if ( xProps.is() )
+ {
+ try
+ {
+ aCaller = xProps->getPropertyValue("Name");
+ }
+ catch( uno::Exception& ) {}
+ }
+ uno::Any aRet;
+ uno::Sequence< sal_Int16 > aOutArgsIndex;
+ uno::Sequence< uno::Any > aOutArgs;
+ uno::Sequence< uno::Any > aInArgs;
+ pObjSh->CallXScript( pInfo->GetMacro(),
+ aInArgs, aRet, aOutArgsIndex, aOutArgs, true, &aCaller );
+ rViewShell.FakeButtonUp( rViewShell.GetViewData().GetActivePart() );
+ return true; // no CaptureMouse etc.
+ }
+ }
+ }
+
+ // URL / ImageMap
+
+ SdrViewEvent aVEvt;
+ if ( !bAlt &&
+ pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) != SdrHitKind::NONE &&
+ aVEvt.mpObj != nullptr )
+ {
+ if ( SvxIMapInfo::GetIMapInfo( aVEvt.mpObj ) ) // ImageMap
+ {
+ const IMapObject* pIMapObj =
+ SvxIMapInfo::GetHitIMapObject( aVEvt.mpObj, aMDPos, pWindow->GetOutDev() );
+ if ( pIMapObj && !pIMapObj->GetURL().isEmpty() )
+ {
+ sURL = pIMapObj->GetURL();
+ sTarget = pIMapObj->GetTarget();
+ }
+ }
+ if ( aVEvt.meEvent == SdrEventKind::ExecuteUrl && aVEvt.mpURLField ) // URL
+ {
+ sURL = aVEvt.mpURLField->GetURL();
+ sTarget = aVEvt.mpURLField->GetTargetFrame();
+ }
+ }
+
+ // open hyperlink, if found at object or in object's text
+ // Fragments pointing into the current document should be always opened.
+ if ( !sURL.isEmpty() && (ScGlobal::ShouldOpenURL() || sURL.startsWith("#")) )
+ {
+ ScGlobal::OpenURL( sURL, sTarget );
+ rViewShell.FakeButtonUp( rViewShell.GetViewData().GetActivePart() );
+ return true; // no CaptureMouse etc.
+ }
+
+ // Is another object being edited in this view?
+ // (Editing is ended in MarkListHasChanged - test before UnmarkAll)
+ SfxInPlaceClient* pClient = rViewShell.GetIPClient();
+ bool bWasOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
+
+ // Selection
+
+ // do not allow multiselection with note caption
+ bool bCaptionClicked = IsNoteCaptionClicked( aMDPos );
+ if ( !rMEvt.IsShift() || bCaptionClicked || IsNoteCaptionMarked() )
+ pView->UnmarkAll();
+
+ /* Unlock internal layer, if a note caption is clicked. The
+ layer will be relocked in ScDrawView::MarkListHasChanged(). */
+ if( bCaptionClicked )
+ pView->UnlockInternalLayer();
+
+ // try to select the clicked object
+ if ( pView->MarkObj( aMDPos, -2, false, rMEvt.IsMod1() ) )
+ {
+
+ // move object
+
+ if (pView->IsMarkedHit(aMDPos))
+ {
+ // Don't start drag timer if inplace editing of an OLE object
+ // was just ended with this mouse click - the view will be moved
+ // (different tool bars) and the object that was clicked on would
+ // be moved unintentionally.
+ if ( !bWasOleActive )
+ aDragTimer.Start();
+
+ pHdl=pView->PickHandle(aMDPos);
+ pView->BegDragObj(aMDPos, nullptr, pHdl);
+ bReturn = true;
+ }
+ else // object at the edge
+ if (rViewShell.IsDrawSelMode())
+ bReturn = true;
+ }
+ else
+ {
+ if (rViewShell.IsDrawSelMode())
+ {
+
+ // select object
+
+ pView->BegMarkObj(aMDPos);
+ bReturn = true;
+ }
+ }
+ }
+ }
+
+ }
+
+ if (!bIsInDragMode)
+ {
+ // VC calls CaptureMouse itself
+ pWindow->CaptureMouse();
+ ForcePointer(&rMEvt);
+ }
+
+ return bReturn;
+}
+
+bool FuSelection::MouseMove(const MouseEvent& rMEvt)
+{
+ bool bReturn = FuDraw::MouseMove(rMEvt);
+
+ if (aDragTimer.IsActive() )
+ {
+ Point aOldPixel = pWindow->LogicToPixel( aMDPos );
+ Point aNewPixel = rMEvt.GetPosPixel();
+ if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
+ std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
+ aDragTimer.Stop();
+ }
+
+ if ( pView->IsAction() )
+ {
+ Point aPix(rMEvt.GetPosPixel());
+ Point aPnt(pWindow->PixelToLogic(aPix));
+
+ ForceScroll(aPix);
+ pView->MovAction(aPnt);
+ bReturn = true;
+ }
+
+ ForcePointer(&rMEvt);
+
+ return bReturn;
+}
+
+bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ bool bReturn = FuDraw::MouseButtonUp(rMEvt);
+ bool bOle = rViewShell.GetViewFrame()->GetFrame().IsInPlace();
+
+ SdrObject* pObj = nullptr;
+ if (aDragTimer.IsActive() )
+ {
+ aDragTimer.Stop();
+ }
+
+ sal_uInt16 nDrgLog = sal_uInt16 ( pWindow->PixelToLogic(Size(SC_MINDRAGMOVE,0)).Width() );
+ auto aLogicPosition = rMEvt.getLogicPosition();
+ Point aPnt(aLogicPosition ? *aLogicPosition : pWindow->PixelToLogic(rMEvt.GetPosPixel()));
+
+ bool bCopy = false;
+ ScViewData& rViewData = rViewShell.GetViewData();
+ ScDocument& rDocument = rViewData.GetDocument();
+ SdrPageView* pPageView = ( pView ? pView->GetSdrPageView() : nullptr );
+ SdrPage* pPage = ( pPageView ? pPageView->GetPage() : nullptr );
+ ::std::vector< OUString > aExcludedChartNames;
+ ScRangeListVector aProtectedChartRangesVector;
+
+ if (comphelper::LibreOfficeKit::isActive() && rDocument.IsNegativePage(rViewData.GetTabNo()))
+ aPnt.setX(-aPnt.X());
+
+ if (pView && rMEvt.IsLeft())
+ {
+ if ( pView->IsDragObj() )
+ {
+ // object was moved
+ if ( rMEvt.IsMod1() )
+ {
+ if ( pPage )
+ {
+ ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
+ }
+ if ( pView )
+ {
+ const SdrMarkList& rSdrMarkList = pView->GetMarkedObjectList();
+ const size_t nMarkCount = rSdrMarkList.GetMarkCount();
+ for ( size_t i = 0; i < nMarkCount; ++i )
+ {
+ SdrMark* pMark = rSdrMarkList.GetMark( i );
+ pObj = ( pMark ? pMark->GetMarkedSdrObj() : nullptr );
+ if ( pObj )
+ {
+ ScChartHelper::AddRangesIfProtectedChart( aProtectedChartRangesVector, rDocument, pObj );
+ }
+ }
+ }
+ bCopy = true;
+ }
+
+ if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() &&
+ std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
+ std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
+ {
+ /* If a user wants to click on an object in front of a marked
+ one, he releases the mouse button immediately */
+ SdrPageView* pPV = nullptr;
+ pObj = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK);
+ if (pObj)
+ {
+ pView->UnmarkAllObj();
+ pView->MarkObj(pObj,pPV);
+ return true;
+ }
+ }
+ pView->EndDragObj( rMEvt.IsMod1() );
+ pView->ForceMarkedToAnotherPage();
+
+ bReturn = true;
+ }
+ else if (pView->IsAction() )
+ {
+ // unlock internal layer to include note captions
+ pView->UnlockInternalLayer();
+ pView->EndAction();
+ if ( pView->AreObjectsMarked() )
+ {
+ bReturn = true;
+
+ /* if multi-selection contains a note caption object, remove
+ all other objects from selection. */
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ const size_t nCount = rMarkList.GetMarkCount();
+ if( nCount > 1 )
+ {
+ bool bFound = false;
+ for( size_t nIdx = 0; !bFound && (nIdx < nCount); ++nIdx )
+ {
+ pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj();
+ bFound = ScDrawLayer::IsNoteCaption( pObj );
+ if( bFound )
+ {
+ pView->UnMarkAll();
+ pView->MarkObj( pObj, pView->GetSdrPageView() );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // maybe consider OLE object
+ SfxInPlaceClient* pIPClient = rViewShell.GetIPClient();
+
+ if (pIPClient)
+ {
+ ScModule* pScMod = SC_MOD();
+ bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
+
+ if ( pIPClient->IsObjectInPlaceActive() && !bUnoRefDialog )
+ pIPClient->DeactivateObject();
+ }
+
+ sal_uInt16 nClicks = rMEvt.GetClicks();
+ if (pView && nClicks == 2 && rMEvt.IsLeft())
+ {
+ if ( pView->AreObjectsMarked() )
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if (rMarkList.GetMarkCount() == 1)
+ {
+ SdrMark* pMark = rMarkList.GetMark(0);
+ pObj = pMark->GetMarkedSdrObj();
+
+ // only activate, when the mouse also is over the selected object
+
+ SdrViewEvent aVEvt;
+ SdrHitKind eHit = pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
+ if (eHit != SdrHitKind::NONE && aVEvt.mpObj == pObj)
+ {
+ SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
+
+ // OLE: activate
+
+ if (nSdrObjKind == SdrObjKind::OLE2)
+ {
+ if (!bOle)
+ {
+ if (static_cast<SdrOle2Obj*>(pObj)->GetObjRef().is())
+ {
+ rViewShell.ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
+ }
+ }
+ }
+
+ // Edit text
+ // not in UNO controls
+ // #i32352# not in media objects
+
+ else if ( dynamic_cast<const SdrTextObj*>( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) == nullptr && dynamic_cast<const SdrMediaObj*>( pObj) == nullptr )
+ {
+ OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
+ bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() );
+ sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
+
+ rViewShell.GetViewData().GetDispatcher().
+ Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
+
+ // Get the created FuText now and change into EditMode
+ FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
+ if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // has no RTTI
+ {
+ FuText* pText = static_cast<FuText*>(pPoor);
+ Point aMousePixel = rMEvt.GetPosPixel();
+ pText->SetInEditMode( pObj, &aMousePixel );
+ }
+ bReturn = true;
+ }
+ }
+ }
+ }
+ else if ( TestDetective( pView->GetSdrPageView(), aPnt ) )
+ bReturn = true;
+ }
+
+ ForcePointer(&rMEvt);
+
+ if (pWindow->IsMouseCaptured())
+ pWindow->ReleaseMouse();
+
+ // command handler for context menu follows after MouseButtonUp,
+ // therefore here the hard IsLeft call
+ if ( !bReturn && rMEvt.IsLeft() )
+ if (rViewShell.IsDrawSelMode())
+ rViewShell.GetViewData().GetDispatcher().
+ Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
+
+ if ( bCopy && pPage )
+ {
+ ScDocShell* pDocShell = rViewData.GetDocShell();
+ ScModelObj* pModelObj = ( pDocShell ? comphelper::getFromUnoTunnel<ScModelObj>( pDocShell->GetModel() ) : nullptr );
+ if ( pModelObj )
+ {
+ SCTAB nTab = rViewData.GetTabNo();
+ ScChartHelper::CreateProtectedChartListenersAndNotify( rDocument, pPage, pModelObj, nTab,
+ aProtectedChartRangesVector, aExcludedChartNames );
+ }
+ }
+
+ return bReturn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/fusel2.cxx b/sc/source/ui/drawfunc/fusel2.cxx
new file mode 100644
index 000000000..0d18fea87
--- /dev/null
+++ b/sc/source/ui/drawfunc/fusel2.cxx
@@ -0,0 +1,159 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svditer.hxx>
+#include <svx/svdpagv.hxx>
+
+#include <fusel.hxx>
+#include <tabvwsh.hxx>
+#include <document.hxx>
+#include <detfunc.hxx>
+#include <attrib.hxx>
+#include <scitems.hxx>
+#include <userdat.hxx>
+#include <drwlayer.hxx>
+#include <docsh.hxx>
+#include <drawview.hxx>
+#include <svx/sdrhittesthelper.hxx>
+
+static tools::Long Diff( const Point& rP1, const Point& rP2 )
+{
+ tools::Long nX = rP1.X() - rP2.X();
+ if (nX<0) nX = -nX;
+ tools::Long nY = rP1.Y() - rP2.Y();
+ if (nY<0) nY = -nY;
+ return nX+nY;
+}
+
+bool FuSelection::TestDetective( const SdrPageView* pPV, const Point& rPos )
+{
+ if (!pPV)
+ return false;
+
+ bool bFound = false;
+ SdrObjListIter aIter( pPV->GetObjList(), SdrIterMode::Flat );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if (ScDetectiveFunc::IsNonAlienArrow( pObject ))
+ {
+ sal_uInt16 nHitLog = static_cast<sal_uInt16>(pWindow->PixelToLogic(
+ Size(pView->GetHitTolerancePixel(),0)).Width());
+ if (SdrObjectPrimitiveHit(*pObject, rPos, nHitLog, *pPV, nullptr, false))
+ {
+ ScViewData& rViewData = rViewShell.GetViewData();
+ ScSplitPos ePos = rViewShell.FindWindow( pWindow );
+ Point aLineStart = pObject->GetPoint(0);
+ Point aLineEnd = pObject->GetPoint(1);
+ Point aPixel = pWindow->LogicToPixel( aLineStart );
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ rViewData.GetPosFromPixel( aPixel.X(), aPixel.Y(), ePos, nStartCol, nStartRow );
+ aPixel = pWindow->LogicToPixel( aLineEnd );
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ rViewData.GetPosFromPixel( aPixel.X(), aPixel.Y(), ePos, nEndCol, nEndRow );
+ SCCOL nCurX = rViewData.GetCurX();
+ SCROW nCurY = rViewData.GetCurY();
+ bool bStart = ( Diff( rPos,aLineStart ) > Diff( rPos,aLineEnd ) );
+ if ( nCurX == nStartCol && nCurY == nStartRow )
+ bStart = false;
+ else if ( nCurX == nEndCol && nCurY == nEndRow )
+ bStart = true;
+
+ SCCOL nDifX;
+ SCROW nDifY;
+ if ( bStart )
+ {
+ nDifX = nStartCol - nCurX;
+ nDifY = nStartRow - nCurY;
+ }
+ else
+ {
+ nDifX = nEndCol - nCurX;
+ nDifY = nEndRow - nCurY;
+ }
+ rViewShell.MoveCursorRel( nDifX, nDifY, SC_FOLLOW_JUMP, false );
+
+ bFound = true;
+ }
+ }
+
+ pObject = aIter.Next();
+ }
+ return bFound;
+}
+
+bool FuSelection::IsNoteCaptionMarked() const
+{
+ if( pView )
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ return ScDrawLayer::IsNoteCaption( pObj );
+ }
+ }
+ return false;
+}
+
+bool FuSelection::IsNoteCaptionClicked( const Point& rPos ) const
+{
+ SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr;
+ if( pPageView )
+ {
+ const ScViewData& rViewData = rViewShell.GetViewData();
+ ScDocument& rDoc = rViewData.GetDocument();
+ SCTAB nTab = rViewData.GetTabNo();
+ ScDocShell* pDocSh = rViewData.GetDocShell();
+ bool bProtectDoc = rDoc.IsTabProtected( nTab ) || (pDocSh && pDocSh->IsReadOnly());
+
+ // search the last object (on top) in the object list
+ SdrObjListIter aIter( pPageView->GetObjList(), SdrIterMode::DeepNoGroups, true );
+ for( SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next() )
+ {
+ if( pObj->GetLogicRect().Contains( rPos ) )
+ {
+ if( const ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObj, nTab ) )
+ {
+ const ScAddress& rNotePos = pCaptData->maStart;
+ // skip caption objects of notes in protected cells
+ const ScProtectionAttr* pProtAttr = rDoc.GetAttr( rNotePos.Col(), rNotePos.Row(), nTab, ATTR_PROTECTION );
+ bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell();
+ if( !bProtectAttr || !bProtectDoc )
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void FuSelection::ActivateNoteHandles(SdrObject* pObject)
+{
+ if( pView && ScDrawLayer::IsNoteCaption( pObject ) )
+ {
+ // Leave the internal layer unlocked - relock in ScDrawView::MarkListHasChanged()
+ pView->UnlockInternalLayer();
+ pView->MarkObj( pObject, pView->GetSdrPageView() );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/futext.cxx b/sc/source/ui/drawfunc/futext.cxx
new file mode 100644
index 000000000..d907a0a72
--- /dev/null
+++ b/sc/source/ui/drawfunc/futext.cxx
@@ -0,0 +1,687 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svddef.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/outlobj.hxx>
+#include <svx/sdtaaitm.hxx>
+#include <svx/sdtacitm.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/sdtagitm.hxx>
+#include <editeng/unolingu.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svx/svxids.hrc>
+#include <editeng/eeitem.hxx>
+#include <svl/itemset.hxx>
+#include <osl/diagnose.h>
+
+#include <futext.hxx>
+#include <drwlayer.hxx>
+#include <sc.hrc>
+#include <tabvwsh.hxx>
+#include <drawview.hxx>
+
+// maximum of mouse movement which allows to start Drag&Drop
+//! fusel,fuconstr,futext - combined!
+#define SC_MAXDRAGMOVE 3
+
+static void lcl_InvalidateAttribs( SfxBindings& rBindings )
+{
+ rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT );
+ rBindings.Invalidate( SID_ATTR_CHAR_POSTURE );
+ rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
+ rBindings.Invalidate( SID_ULINE_VAL_NONE );
+ rBindings.Invalidate( SID_ULINE_VAL_SINGLE );
+ rBindings.Invalidate( SID_ULINE_VAL_DOUBLE );
+ rBindings.Invalidate( SID_ULINE_VAL_DOTTED );
+ rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE );
+ rBindings.Invalidate( SID_ATTR_CHAR_COLOR );
+ rBindings.Invalidate( SID_ATTR_CHAR_BACK_COLOR );
+ rBindings.Invalidate( SID_ATTR_CHAR_FONT );
+ rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
+ rBindings.Invalidate( SID_ATTR_PARA_ADJUST_LEFT );
+ rBindings.Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
+ rBindings.Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
+ rBindings.Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
+ rBindings.Invalidate( SID_ALIGNLEFT );
+ rBindings.Invalidate( SID_ALIGNCENTERHOR );
+ rBindings.Invalidate( SID_ALIGNRIGHT );
+ rBindings.Invalidate( SID_ALIGNBLOCK );
+ rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_10 );
+ rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_15 );
+ rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_20 );
+ rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
+ rBindings.Invalidate( SID_SET_SUB_SCRIPT );
+ rBindings.Invalidate( SID_HYPERLINK_GETLINK );
+ rBindings.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT );
+ rBindings.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM );
+ rBindings.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
+ rBindings.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
+ rBindings.Invalidate( SID_TABLE_VERT_NONE );
+ rBindings.Invalidate( SID_TABLE_VERT_CENTER );
+ rBindings.Invalidate( SID_TABLE_VERT_BOTTOM );
+ // pseudo slots for Format menu
+ rBindings.Invalidate( SID_ALIGN_ANY_LEFT );
+ rBindings.Invalidate( SID_ALIGN_ANY_HCENTER );
+ rBindings.Invalidate( SID_ALIGN_ANY_RIGHT );
+ rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED );
+ rBindings.Invalidate( SID_ATTR_CHAR_KERNING );
+ rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
+ rBindings.Invalidate( SID_SET_SUB_SCRIPT );
+ rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT );
+ rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED );
+}
+
+static void lcl_UpdateHyphenator( Outliner& rOutliner, const SdrObject* pObj )
+{
+ // use hyphenator only if hyphenation attribute is set
+ if ( pObj && pObj->GetMergedItem(EE_PARA_HYPHENATE).GetValue() ) {
+ css::uno::Reference<css::linguistic2::XHyphenator> xHyphenator( LinguMgr::GetHyphenator() );
+ rOutliner.SetHyphenator( xHyphenator );
+ }
+}
+
+FuText::FuText(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
+ SdrModel* pDoc, const SfxRequest& rReq)
+ : FuConstruct(rViewSh, pWin, pViewP, pDoc, rReq)
+{
+}
+
+FuText::~FuText()
+{
+// StopEditMode(); // in Deactivate !
+}
+
+bool FuText::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+ bool bStraightEnter = true;
+
+ if ( pView->MouseButtonDown(rMEvt, pWindow->GetOutDev()) )
+ return true; // event handled from SdrView
+
+ if ( pView->IsTextEdit() )
+ {
+ if ( IsEditingANote() )
+ {
+ if( !IsSizingOrMovingNote(rMEvt) )
+ {
+ StopEditMode(); // Clicked outside, ending edit
+ bStraightEnter = false;
+ }
+ }
+ else
+ {
+ StopEditMode(); // Clicked outside, ending edit
+ pView->UnmarkAll();
+ bStraightEnter = false;
+ }
+ pView->SetCreateMode();
+ }
+
+ aMDPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
+
+ if ( rMEvt.IsLeft() )
+ {
+ SdrHdl* pHdl = pView->PickHandle(aMDPos);
+ const size_t nHdlNum = pView->GetHdlNum(pHdl);
+ if (pHdl != nullptr)
+ {
+ if (pView->HasMarkablePoints() && pView->IsPointMarkable(*pHdl))
+ {
+ bool bPointMarked=pView->IsPointMarked(*pHdl);
+
+ if ( rMEvt.IsShift() )
+ {
+ if (!bPointMarked)
+ {
+ pView->MarkPoint(*pHdl);
+ }
+ else
+ {
+ pView->UnmarkPoint(*pHdl);
+ }
+ }
+ else
+ {
+ if (!bPointMarked)
+ {
+ pView->UnmarkAllPoints();
+ pView->MarkPoint(*pHdl);
+ }
+ }
+ pHdl=pView->GetHdl(nHdlNum);
+ }
+ }
+
+ SdrPageView* pPV = nullptr;
+
+ if ( pHdl != nullptr || pView->IsMarkedHit(aMDPos) )
+ {
+ SdrObject* pObj = (pHdl == nullptr) ?
+ pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKTEXTEDIT) :
+ nullptr;
+ if (pObj)
+ {
+ std::unique_ptr<SdrOutliner> pO = MakeOutliner();
+ lcl_UpdateHyphenator( *pO, pObj );
+
+ // vertical flag:
+ // deduced from slot ids only if text object has no content
+ sal_uInt16 nSlotID = aSfxRequest.GetSlot();
+ bool bVertical = ( nSlotID == SID_DRAW_TEXT_VERTICAL );
+ OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
+ if ( pOPO )
+ bVertical = pOPO->IsEffectivelyVertical(); // content wins
+ pO->SetVertical( bVertical );
+
+ //!?? the default values are not correct when result is without outliner ???!?
+ auto pOTemp = pO.get();
+ if ( pView->SdrBeginTextEdit(pObj, pPV, pWindow, true, pO.release()) )
+ {
+ // subscribe EditEngine-UndoManager
+ rViewShell.SetDrawTextUndo( &pOTemp->GetUndoManager() );
+
+ OutlinerView* pOLV = pView->GetTextEditOutlinerView();
+ if ( pOLV->MouseButtonDown(rMEvt) )
+ return true; // Event to the Outliner
+ }
+ }
+ else
+ {
+ // disable tail & circular move for caption objects.
+ bool bDrag = false;
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
+ {
+ if(pHdl->GetKind() != SdrHdlKind::Poly && pHdl->GetKind() != SdrHdlKind::Circle)
+ bDrag = true;
+ }
+ else
+ bDrag = true; // different object
+ }
+ else
+ bDrag = true; // several objects
+
+ if ( bDrag )
+ {
+ aDragTimer.Start();
+ pView->BegDragObj(aMDPos, nullptr, pHdl);
+ }
+ }
+ }
+ else
+ {
+ if (pView->IsEditMode())
+ {
+ bool bPointMode=pView->HasMarkablePoints();
+
+ if (!rMEvt.IsShift())
+ {
+ if (bPointMode)
+ {
+ pView->UnmarkAllPoints();
+ }
+ else
+ {
+ pView->UnmarkAll();
+ }
+
+ pView->SetDragMode(SdrDragMode::Move);
+ SfxBindings& rBindings = rViewShell.GetViewFrame()->GetBindings();
+ rBindings.Invalidate( SID_OBJECT_ROTATE );
+ rBindings.Invalidate( SID_OBJECT_MIRROR );
+ }
+
+ if ( pView->MarkObj(aMDPos, -2, false, rMEvt.IsMod1()) )
+ {
+ aDragTimer.Start();
+
+ pHdl=pView->PickHandle(aMDPos);
+
+ if (pHdl!=nullptr)
+ {
+ pView->MarkPoint(*pHdl);
+ pHdl=pView->GetHdl(nHdlNum);
+ }
+
+ pView->BegDragObj(aMDPos, nullptr, pHdl);
+ }
+ else
+ {
+ if (bPointMode)
+ {
+ pView->BegMarkPoints(aMDPos);
+ }
+ else
+ {
+ pView->BegMarkObj(aMDPos);
+ }
+ }
+ }
+ else if (aSfxRequest.GetSlot() == SID_DRAW_NOTEEDIT )
+ {
+ // Edit notes -> create no new text objects
+ // and leave text mode
+ rViewShell.GetViewData().GetDispatcher().
+ Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ }
+ else
+ {
+ if (bStraightEnter)//Hack for that silly idea that creating text fields is inside the text routine
+ {
+ // create object
+ pView->BegCreateObj(aMDPos);
+ }
+ else if (SdrObject* pObj = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK))
+ {
+ pView->UnmarkAllObj();
+ ScViewData& rViewData = rViewShell.GetViewData();
+ rViewData.GetDispatcher().Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ pView->MarkObj(pObj,pPV);
+
+ pHdl=pView->PickHandle(aMDPos);
+ pView->BegDragObj(aMDPos, nullptr, pHdl);
+ return true;
+ }
+ }
+ }
+ }
+
+ if (!bIsInDragMode)
+ {
+ pWindow->CaptureMouse();
+// ForcePointer(&rMEvt);
+ lcl_InvalidateAttribs( rViewShell.GetViewFrame()->GetBindings() );
+ }
+
+ rViewShell.SetActivePointer(pView->GetPreferredPointer(
+ pWindow->PixelToLogic(rMEvt.GetPosPixel()), pWindow->GetOutDev() ));
+ if (!bStraightEnter)
+ {
+ pView->UnmarkAll();
+ ScViewData& rViewData = rViewShell.GetViewData();
+ rViewData.GetDispatcher().Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ }
+
+ return true;
+}
+
+bool FuText::MouseMove(const MouseEvent& rMEvt)
+{
+ rViewShell.SetActivePointer(pView->GetPreferredPointer(
+ pWindow->PixelToLogic(rMEvt.GetPosPixel()), pWindow->GetOutDev() ));
+
+ if (aDragTimer.IsActive() )
+ {
+ Point aOldPixel = pWindow->LogicToPixel( aMDPos );
+ Point aNewPixel = rMEvt.GetPosPixel();
+ if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
+ std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
+ aDragTimer.Stop();
+ }
+
+ Point aPix(rMEvt.GetPosPixel());
+ Point aPnt(pWindow->PixelToLogic(aPix));
+
+ if ( pView->MouseMove(rMEvt, pWindow->GetOutDev()) )
+ return true; // event handled from SdrView
+
+ if ( pView->IsAction() )
+ {
+ ForceScroll(aPix);
+ pView->MovAction(aPnt);
+ }
+
+ return false;
+}
+
+bool FuText::MouseButtonUp(const MouseEvent& rMEvt)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode(rMEvt.GetButtons());
+
+ if (aDragTimer.IsActive() )
+ {
+ aDragTimer.Stop();
+ }
+
+ lcl_InvalidateAttribs( rViewShell.GetViewFrame()->GetBindings() );
+
+ Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+
+ if ( pView->MouseButtonUp(rMEvt, pWindow->GetOutDev()) )
+ return true; // Event evaluated by SdrView
+
+ if ( pView->IsDragObj() )
+ {
+ pView->EndDragObj( rMEvt.IsShift() );
+ pView->ForceMarkedToAnotherPage();
+ }
+ else if ( pView->IsCreateObj() )
+ {
+ if (rMEvt.IsLeft())
+ {
+ pView->EndCreateObj(SdrCreateCmd::ForceEnd);
+ if (aSfxRequest.GetSlot() == SID_DRAW_TEXT_MARQUEE)
+ {
+ // create marquee-object?
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if (rMarkList.GetMark(0))
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+
+ // set needed attributes for scrolling
+ SfxItemSetFixed<SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST> aItemSet( pDrDoc->GetItemPool());
+
+ aItemSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
+ aItemSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
+ aItemSet.Put( SdrTextAniKindItem( SdrTextAniKind::Slide ) );
+ aItemSet.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left ) );
+ aItemSet.Put( SdrTextAniCountItem( 1 ) );
+ aItemSet.Put( SdrTextAniAmountItem(
+ static_cast<sal_Int16>(pWindow->PixelToLogic(Size(2,1)).Width())) );
+ pObj->SetMergedItemSetAndBroadcast(aItemSet);
+ }
+ }
+
+ // init object different when vertical writing
+ sal_uInt16 nSlotID(aSfxRequest.GetSlot());
+ bool bVertical = (SID_DRAW_TEXT_VERTICAL == nSlotID);
+ if(bVertical)
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if(rMarkList.GetMark(0))
+ {
+ SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ if(auto pText = dynamic_cast<SdrTextObj*>( pObj))
+ {
+ SfxItemSet aSet(pDrDoc->GetItemPool());
+
+ pText->SetVerticalWriting(true);
+
+ aSet.Put(makeSdrTextAutoGrowWidthItem(true));
+ aSet.Put(makeSdrTextAutoGrowHeightItem(false));
+ aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
+ aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
+
+ pText->SetMergedItemSet(aSet);
+ }
+ }
+ }
+
+ SetInEditMode();
+
+ // leave mode when sole click (-> fuconstr)
+ if ( !pView->AreObjectsMarked() )
+ {
+ pView->MarkObj(aPnt, -2, false, rMEvt.IsMod1());
+
+ SfxDispatcher& rDisp = rViewShell.GetViewData().GetDispatcher();
+ if ( pView->AreObjectsMarked() )
+ rDisp.Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
+ else
+ rDisp.Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ }
+ }
+ }
+ else if ( pView->IsAction() )
+ {
+ pView->EndAction();
+ }
+ else if( !pView->IsAction() )
+ {
+ pWindow->ReleaseMouse();
+
+ if ( !pView->AreObjectsMarked() && rMEvt.GetClicks() < 2 )
+ {
+ pView->MarkObj(aPnt, -2, false, rMEvt.IsMod1());
+
+ SfxDispatcher& rDisp = rViewShell.GetViewData().GetDispatcher();
+ if ( pView->AreObjectsMarked() )
+ rDisp.Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
+ else
+ rDisp.Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
+ }
+ }
+
+ return false;
+}
+
+// switch mouse-pointer
+void FuText::ForcePointer(const MouseEvent* /* pMEvt */)
+{
+ rViewShell.SetActivePointer( aNewPointer );
+}
+
+// modify keyboard events
+// if a KeyEvent is being processed, then the return value is sal_True, else FALSE.
+bool FuText::KeyInput(const KeyEvent& rKEvt)
+{
+ bool bReturn = false;
+
+ if ( pView->KeyInput(rKEvt, pWindow) )
+ {
+ bReturn = true;
+ lcl_InvalidateAttribs( rViewShell.GetViewFrame()->GetBindings() );
+ }
+ else
+ {
+ bReturn = FuDraw::KeyInput(rKEvt);
+ }
+
+ return bReturn;
+}
+
+void FuText::Activate()
+{
+ pView->SetDragMode(SdrDragMode::Move);
+ SfxBindings& rBindings = rViewShell.GetViewFrame()->GetBindings();
+ rBindings.Invalidate( SID_OBJECT_ROTATE );
+ rBindings.Invalidate( SID_OBJECT_MIRROR );
+
+// instant set the edit mode
+// SetInEditMode();
+
+// if (!pTextObj)
+ {
+ // no text object in EditMode, therefore set CreateMode
+
+ pView->SetCurrentObj(SdrObjKind::Text);
+
+ pView->SetCreateMode();
+ }
+
+ aNewPointer = PointerStyle::Text;
+
+ aOldPointer = pWindow->GetPointer();
+ rViewShell.SetActivePointer( aNewPointer );
+
+ FuConstruct::Activate();
+}
+
+void FuText::Deactivate()
+{
+ FuConstruct::Deactivate();
+ rViewShell.SetActivePointer( aOldPointer );
+ StopEditMode();
+}
+
+// switch object to Edit-Mode
+void FuText::SetInEditMode(SdrObject* pObj, const Point* pMousePixel,
+ bool bCursorToEnd, const KeyEvent* pInitialKey)
+{
+ /* It is possible to pass a special (unselected) object in pObj, e.g. the
+ caption object of a cell note. If pObj is 0, then the selected object
+ is used. The layer will be relocked in FuText::StopEditMode(). */
+ if ( pObj && (pObj->GetLayer() == SC_LAYER_INTERN) )
+ pView->UnlockInternalLayer();
+
+ if ( !pObj && pView->AreObjectsMarked() )
+ {
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if (rMarkList.GetMarkCount() == 1)
+ {
+ SdrMark* pMark = rMarkList.GetMark(0);
+ pObj = pMark->GetMarkedSdrObj();
+ }
+ }
+
+ if ( !pObj )
+ return;
+
+ SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
+
+ if (!(nSdrObjKind == SdrObjKind::Text ||
+ nSdrObjKind == SdrObjKind::TitleText ||
+ nSdrObjKind == SdrObjKind::OutlineText ||
+ dynamic_cast<const SdrTextObj*>( pObj) != nullptr))
+ return;
+
+ SdrPageView* pPV = pView->GetSdrPageView();
+
+ if ( !pObj->HasTextEdit() )
+ return;
+
+ std::unique_ptr<SdrOutliner> pO = MakeOutliner();
+ lcl_UpdateHyphenator( *pO, pObj );
+
+ // vertical flag:
+ // deduced from slot ids only if text object has no content
+
+ sal_uInt16 nSlotID = aSfxRequest.GetSlot();
+ bool bVertical = ( nSlotID == SID_DRAW_TEXT_VERTICAL );
+ OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
+ if ( pOPO )
+ bVertical = pOPO->IsEffectivelyVertical(); // content wins
+ pO->SetVertical( bVertical );
+
+ //!?? without returned Outliner the defaults are not correct ???!?
+ auto pOTemp = pO.get();
+ if ( !pView->SdrBeginTextEdit(pObj, pPV, pWindow, true, pO.release()) )
+ return;
+
+ // Toggle out of paste mode if we are in it, otherwise
+ // pressing return in this object will instead go to the
+ // sheet and be considered an overwrite-cell instruction
+ rViewShell.GetViewData().SetPasteMode(ScPasteFlags::NONE);
+ rViewShell.UpdateCopySourceOverlay();
+
+ // EditEngine-UndoManager anmelden
+ rViewShell.SetDrawTextUndo( &pOTemp->GetUndoManager() );
+
+ pView->SetEditMode();
+
+ // set text cursor to click position or to end,
+ // pass initial key event to outliner view
+ if ( !(pMousePixel || bCursorToEnd || pInitialKey) )
+ return;
+
+ OutlinerView* pOLV = pView->GetTextEditOutlinerView();
+ if (!pOLV)
+ return;
+
+ if ( pMousePixel )
+ {
+ MouseEvent aEditEvt( *pMousePixel, 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0 );
+ pOLV->MouseButtonDown(aEditEvt);
+ pOLV->MouseButtonUp(aEditEvt);
+ }
+ else if ( bCursorToEnd )
+ {
+ ESelection aNewSelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
+ pOLV->SetSelection(aNewSelection);
+ }
+
+ if ( pInitialKey )
+ pOLV->PostKeyEvent( *pInitialKey );
+}
+
+// Create default drawing objects via keyboard
+SdrObjectUniquePtr FuText::CreateDefaultObject(const sal_uInt16 nID, const tools::Rectangle& rRectangle)
+{
+ // case SID_DRAW_TEXT:
+ // case SID_DRAW_TEXT_VERTICAL:
+ // case SID_DRAW_TEXT_MARQUEE:
+ // case SID_DRAW_NOTEEDIT:
+
+ SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject(
+ *pDrDoc,
+ pView->GetCurrentObjInventor(),
+ pView->GetCurrentObjIdentifier()));
+
+ if(pObj)
+ {
+ if(auto pText = dynamic_cast<SdrTextObj*>( pObj.get() ))
+ {
+ pText->SetLogicRect(rRectangle);
+
+ // don't set default text, start edit mode instead
+ // String aText(ScResId(STR_CAPTION_DEFAULT_TEXT));
+ // pText->SetText(aText);
+
+ bool bVertical = (SID_DRAW_TEXT_VERTICAL == nID);
+ bool bMarquee = (SID_DRAW_TEXT_MARQUEE == nID);
+
+ pText->SetVerticalWriting(bVertical);
+
+ if(bVertical)
+ {
+ SfxItemSet aSet(pDrDoc->GetItemPool());
+
+ aSet.Put(makeSdrTextAutoGrowWidthItem(true));
+ aSet.Put(makeSdrTextAutoGrowHeightItem(false));
+ aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
+ aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
+
+ pText->SetMergedItemSet(aSet);
+ }
+
+ if(bMarquee)
+ {
+ SfxItemSetFixed<SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST> aSet(pDrDoc->GetItemPool());
+
+ aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
+ aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
+ aSet.Put( SdrTextAniKindItem( SdrTextAniKind::Slide ) );
+ aSet.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left ) );
+ aSet.Put( SdrTextAniCountItem( 1 ) );
+ aSet.Put( SdrTextAniAmountItem( static_cast<sal_Int16>(pWindow->PixelToLogic(Size(2,1)).Width())) );
+
+ pObj->SetMergedItemSetAndBroadcast(aSet);
+ }
+
+ SetInEditMode( pObj.get() ); // start edit mode
+ }
+ else
+ {
+ OSL_FAIL("Object is NO text object");
+ }
+ }
+
+ return pObj;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/futext2.cxx b/sc/source/ui/drawfunc/futext2.cxx
new file mode 100644
index 000000000..8f30cb4a6
--- /dev/null
+++ b/sc/source/ui/drawfunc/futext2.cxx
@@ -0,0 +1,46 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdmodel.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svdetc.hxx>
+
+#include <futext.hxx>
+#include <tabvwsh.hxx>
+
+std::unique_ptr<SdrOutliner> FuText::MakeOutliner()
+{
+ ScViewData& rViewData = rViewShell.GetViewData();
+ std::unique_ptr<SdrOutliner> pOutl = SdrMakeOutliner(OutlinerMode::OutlineObject, *pDrDoc);
+
+ rViewData.UpdateOutlinerFlags(*pOutl);
+
+ // The EditEngine uses during RTF export (Clipboard / Drag&Drop)
+ // the MapMode of RefDevice to set the font size
+
+ // #i10426# The ref device isn't set to the EditEngine before SdrBeginTextEdit now,
+ // so the device must be taken from the model here.
+ OutputDevice* pRef = pDrDoc->GetRefDevice();
+ if (pRef && pRef != pWindow->GetOutDev())
+ pRef->SetMapMode(MapMode(MapUnit::Map100thMM));
+
+ return pOutl;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/futext3.cxx b/sc/source/ui/drawfunc/futext3.cxx
new file mode 100644
index 000000000..df601ea0d
--- /dev/null
+++ b/sc/source/ui/drawfunc/futext3.cxx
@@ -0,0 +1,182 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/svdocapt.hxx>
+#include <svx/svdundo.hxx>
+#include <vcl/cursor.hxx>
+#include <osl/diagnose.h>
+
+#include <global.hxx>
+#include <drwlayer.hxx>
+#include <userdat.hxx>
+#include <tabvwsh.hxx>
+#include <document.hxx>
+#include <futext.hxx>
+#include <docsh.hxx>
+#include <postit.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <drawview.hxx>
+#include <undocell.hxx>
+
+// Editing of Note-Key-Objects has to be stopped always via StopEditMode,
+// so that changes are taken over into the document!
+// (Fontwork-Execute in drawsh and drtxtob does not happen for Key-Objects)
+
+void FuText::StopEditMode()
+{
+ SdrObject* pObject = pView->GetTextEditObject();
+ if( !pObject ) return;
+
+ // relock the internal layer that has been unlocked in FuText::SetInEditMode()
+ if ( pObject->GetLayer() == SC_LAYER_INTERN )
+ pView->LockInternalLayer();
+
+ ScViewData& rViewData = rViewShell.GetViewData();
+ ScDocument& rDoc = rViewData.GetDocument();
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ OSL_ENSURE( pDrawLayer && (pDrawLayer == pDrDoc), "FuText::StopEditMode - missing or different drawing layers" );
+
+ ScAddress aNotePos;
+ ScPostIt* pNote = nullptr;
+ if( const ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObject, rViewData.GetTabNo() ) )
+ {
+ aNotePos = pCaptData->maStart;
+ pNote = rDoc.GetNote( aNotePos );
+ OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "FuText::StopEditMode - missing or invalid cell note" );
+ }
+
+ ScDocShell* pDocShell = rViewData.GetDocShell();
+ SfxUndoManager* pUndoMgr = rDoc.IsUndoEnabled() ? pDocShell->GetUndoManager() : nullptr;
+ bool bNewNote = false;
+ if( pNote && pUndoMgr )
+ {
+ /* Put all undo actions already collected (e.g. create caption object)
+ and all following undo actions (text changed) together into a ListAction. */
+ std::unique_ptr<SdrUndoGroup> pCalcUndo = pDrawLayer->GetCalcUndo();
+
+ if(pCalcUndo)
+ {
+ const OUString aUndoStr = ScResId( STR_UNDO_EDITNOTE );
+ pUndoMgr->EnterListAction( aUndoStr, aUndoStr, 0, rViewShell.GetViewShellId() );
+
+ /* Note has been created before editing, if first undo action is
+ an insert action. Needed below to decide whether to drop the
+ undo if editing a new note has been cancelled. */
+ bNewNote = (pCalcUndo->GetActionCount() > 0) && dynamic_cast< SdrUndoNewObj* >(pCalcUndo->GetAction( 0 ));
+
+ // create a "insert note" undo action if needed
+ if( bNewNote )
+ pUndoMgr->AddUndoAction( std::make_unique<ScUndoReplaceNote>( *pDocShell, aNotePos, pNote->GetNoteData(), true, std::move(pCalcUndo) ) );
+ else
+ pUndoMgr->AddUndoAction( std::move(pCalcUndo) );
+ }
+ }
+
+ if( pNote )
+ rDoc.LockStreamValid(true); // only the affected sheet is invalidated below
+
+ /* SdrObjEditView::SdrEndTextEdit() may try to delete the entire drawing
+ object, if it does not contain text and has invisible border and fill.
+ This must not happen for note caption objects. They will be removed
+ below together with the cell note if the text is empty (independent of
+ border and area formatting). It is possible to prevent automatic
+ deletion by passing sal_True to this function. The return value changes
+ from SdrEndTextEditKind::Deleted to SdrEndTextEditKind::ShouldBeDeleted in this
+ case. */
+ /*SdrEndTextEditKind eResult =*/ pView->SdrEndTextEdit( pNote != nullptr );
+
+ // or ScEndTextEdit (with drawview.hxx)
+ rViewShell.SetDrawTextUndo( nullptr );
+
+ vcl::Cursor* pCur = pWindow->GetCursor();
+ if( pCur && pCur->IsVisible() )
+ pCur->Hide();
+
+ if( !pNote )
+ return;
+
+ ScTabView::OnLOKNoteStateChanged( pNote );
+
+ // hide the caption object if it is in hidden state
+ pNote->ShowCaptionTemp( aNotePos, false );
+
+ // update author and date
+ pNote->AutoStamp();
+
+ /* If the entire text has been cleared, the cell note and its caption
+ object have to be removed. */
+ SdrTextObj* pTextObject = dynamic_cast< SdrTextObj* >( pObject );
+ bool bDeleteNote = !pTextObject || !pTextObject->HasText();
+ if( bDeleteNote )
+ {
+ if( pUndoMgr )
+ {
+ // collect the "remove object" drawing undo action created by DeleteNote()
+ pDrawLayer->BeginCalcUndo(false);
+ // rescue note data before deletion
+ ScNoteData aNoteData( pNote->GetNoteData() );
+ // delete note from document (removes caption, but does not delete it)
+ rDoc.ReleaseNote(aNotePos);
+ // create undo action for removed note
+ pUndoMgr->AddUndoAction( std::make_unique<ScUndoReplaceNote>( *pDocShell, aNotePos, aNoteData, false, pDrawLayer->GetCalcUndo() ) );
+ }
+ else
+ {
+ rDoc.ReleaseNote(aNotePos);
+ }
+ // ScDocument::DeleteNote has deleted the note that pNote points to
+ pNote = nullptr;
+ }
+
+ // finalize the undo list action
+ if( pUndoMgr )
+ {
+ pUndoMgr->LeaveListAction();
+
+ /* #i94039# Update the default name "Edit Note" of the undo action
+ if the note has been created before editing or is deleted due
+ to deleted text. If the note has been created *and* is deleted,
+ the last undo action can be removed completely. Note: The
+ function LeaveListAction() removes the last action by itself,
+ if it is empty (when result is SdrEndTextEditKind::Unchanged). */
+ if( bNewNote && bDeleteNote )
+ {
+ pUndoMgr->RemoveLastUndoAction();
+
+ // Make sure the former area of the note anchor is invalidated.
+ ScRangeList aRangeList(aNotePos);
+ ScMarkData aMarkData(rDoc.GetSheetLimits(), aRangeList);
+ rViewShell.UpdateSelectionArea(aMarkData);
+ }
+ else if( bNewNote || bDeleteNote )
+ {
+ SfxListUndoAction* pAction = dynamic_cast< SfxListUndoAction* >( pUndoMgr->GetUndoAction() );
+ OSL_ENSURE( pAction, "FuText::StopEditMode - list undo action expected" );
+ if( pAction )
+ pAction->SetComment( ScResId( bNewNote ? STR_UNDO_INSERTNOTE : STR_UNDO_DELETENOTE ) );
+ }
+ }
+
+ // invalidate stream positions only for the affected sheet
+ rDoc.LockStreamValid(false);
+ rDoc.SetStreamValid(aNotePos.Tab(), false);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/graphsh.cxx b/sc/source/ui/drawfunc/graphsh.cxx
new file mode 100644
index 000000000..c4487d45d
--- /dev/null
+++ b/sc/source/ui/drawfunc/graphsh.cxx
@@ -0,0 +1,380 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+#include <vcl/EnumContext.hxx>
+#include <sfx2/opengrf.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/grfflt.hxx>
+#include <svx/grafctrl.hxx>
+#include <svx/compressgraphicdialog.hxx>
+#include <svx/graphichelper.hxx>
+#include <svx/svxids.hrc>
+
+#include <graphsh.hxx>
+#include <strings.hrc>
+#include <viewdata.hxx>
+#include <drawview.hxx>
+#include <gridwin.hxx>
+#include <scresid.hxx>
+#include <svx/extedit.hxx>
+
+#define ShellClass_ScGraphicShell
+#include <scslots.hxx>
+
+SFX_IMPL_INTERFACE(ScGraphicShell, ScDrawShell)
+
+void ScGraphicShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
+ ToolbarId::Graphic_Objectbar);
+
+ GetStaticInterface()->RegisterPopupMenu("graphic");
+}
+
+
+ScGraphicShell::ScGraphicShell(ScViewData& rData) :
+ ScDrawShell(rData)
+{
+ SetName("GraphicObject");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Graphic));
+}
+
+ScGraphicShell::~ScGraphicShell()
+{
+}
+
+void ScGraphicShell::GetAttrState( SfxItemSet& rSet )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+
+ if( pView )
+ SvxGrafAttrHelper::GetGrafAttrState( rSet, *pView );
+}
+
+void ScGraphicShell::Execute( SfxRequest& rReq )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+
+ if( pView )
+ {
+ SvxGrafAttrHelper::ExecuteGrafAttr( rReq, *pView );
+ Invalidate();
+ }
+}
+
+void ScGraphicShell::GetFilterState( SfxItemSet& rSet )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ bEnable = true;
+ }
+
+ if( !bEnable )
+ SvxGraphicFilter::DisableGraphicFilterSlots( rSet );
+}
+
+void ScGraphicShell::ExecuteFilter( const SfxRequest& rReq )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ {
+ GraphicObject aFilterObj( pGraphicObj->GetGraphicObject() );
+
+ if( SvxGraphicFilterResult::NONE ==
+ SvxGraphicFilter::ExecuteGrfFilterSlot( rReq, aFilterObj ) )
+ {
+ SdrPageView* pPageView = pView->GetSdrPageView();
+
+ if( pPageView )
+ {
+ SdrGrafObj* pFilteredObj(static_cast<SdrGrafObj*>(pObj->CloneSdrObject(pObj->getSdrModelFromSdrObject())));
+ OUString aStr = pView->GetDescriptionOfMarkedObjects() + " " + ScResId(SCSTR_UNDO_GRAFFILTER);
+ pView->BegUndo( aStr );
+ pFilteredObj->SetGraphicObject( aFilterObj );
+ pView->ReplaceObjectAtView( pObj, *pPageView, pFilteredObj );
+ pView->EndUndo();
+ }
+ }
+ }
+ }
+
+ Invalidate();
+}
+
+void ScGraphicShell::GetExternalEditState( SfxItemSet& rSet )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ bEnable = true;
+ }
+
+ if (GetObjectShell()->isExportLocked())
+ bEnable = false;
+
+ if( !bEnable )
+ rSet.DisableItem( SID_EXTERNAL_EDIT );
+}
+
+void ScGraphicShell::ExecuteExternalEdit( SAL_UNUSED_PARAMETER SfxRequest& )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ {
+ GraphicObject aGraphicObject( pGraphicObj->GetGraphicObject() );
+ m_ExternalEdits.push_back( std::make_unique<SdrExternalToolEdit>(
+ pView, pObj));
+ m_ExternalEdits.back()->Edit( &aGraphicObject );
+ }
+ }
+
+ Invalidate();
+}
+
+void ScGraphicShell::GetCompressGraphicState( SfxItemSet& rSet )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<const SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ bEnable = true;
+ }
+
+ if( !bEnable )
+ rSet.DisableItem( SID_COMPRESS_GRAPHIC );
+}
+
+void ScGraphicShell::ExecuteCompressGraphic( SAL_UNUSED_PARAMETER SfxRequest& )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ {
+ CompressGraphicsDialog dialog(GetViewData().GetDialogParent(), pGraphicObj, GetViewData().GetBindings());
+ if (dialog.run() == RET_OK)
+ {
+ SdrGrafObj* pNewObject = dialog.GetCompressedSdrGrafObj();
+ SdrPageView* pPageView = pView->GetSdrPageView();
+ OUString aUndoString = pView->GetDescriptionOfMarkedObjects() + " Compress";
+ pView->BegUndo( aUndoString );
+ pView->ReplaceObjectAtView( pObj, *pPageView, pNewObject );
+ pView->EndUndo();
+ }
+ }
+ }
+
+ Invalidate();
+}
+
+void ScGraphicShell::GetCropGraphicState( SfxItemSet& rSet )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<const SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ bEnable = true;
+ }
+
+ if( !bEnable )
+ rSet.DisableItem( SID_OBJECT_CROP );
+}
+
+void ScGraphicShell::ExecuteCropGraphic( SAL_UNUSED_PARAMETER SfxRequest& )
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<const SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ {
+ pView->SetEditMode(SdrViewEditMode::Edit);
+ pView->SetDragMode(SdrDragMode::Crop);
+ }
+ }
+
+ Invalidate();
+}
+
+void ScGraphicShell::ExecuteSaveGraphic( SAL_UNUSED_PARAMETER SfxRequest& /*rReq*/)
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ const SdrGrafObj* pObj = dynamic_cast<const SdrGrafObj*>(rMarkList.GetMark( 0 )->GetMarkedSdrObj());
+ if( pObj && pObj->GetGraphicType() == GraphicType::Bitmap )
+ {
+ GraphicAttr aGraphicAttr = pObj->GetGraphicAttr();
+ short nState = RET_CANCEL;
+ vcl::Window* pWin = GetViewData().GetActiveWin();
+ weld::Window* pWinFrame = pWin ? pWin->GetFrameWeld() : nullptr;
+ if (aGraphicAttr != GraphicAttr()) // the image has been modified
+ {
+ if (pWin)
+ {
+ nState = GraphicHelper::HasToSaveTransformedImage(pWinFrame);
+ }
+ }
+ else
+ {
+ nState = RET_NO;
+ }
+
+ if (nState == RET_YES)
+ {
+ GraphicHelper::ExportGraphic(pWinFrame, pObj->GetTransformedGraphic(), "");
+ }
+ else if (nState == RET_NO)
+ {
+ const GraphicObject& aGraphicObject(pObj->GetGraphicObject());
+ GraphicHelper::ExportGraphic(pWinFrame, aGraphicObject.GetGraphic(), "");
+ }
+ }
+ }
+
+ Invalidate();
+}
+
+void ScGraphicShell::GetSaveGraphicState(SfxItemSet &rSet)
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<const SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ bEnable = true;
+ }
+
+ if (GetObjectShell()->isExportLocked())
+ bEnable = false;
+
+ if( !bEnable )
+ rSet.DisableItem( SID_SAVE_GRAPHIC );
+}
+
+void ScGraphicShell::ExecuteChangePicture( SAL_UNUSED_PARAMETER SfxRequest& /*rReq*/)
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGraphicObj = dynamic_cast<SdrGrafObj*>( pObj) )
+ if( pGraphicObj->GetGraphicType() == GraphicType::Bitmap )
+ {
+ vcl::Window* pWin = GetViewData().GetActiveWin();
+ SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr);
+
+ if( aDlg.Execute() == ERRCODE_NONE )
+ {
+ Graphic aGraphic;
+ ErrCode nError = aDlg.GetGraphic(aGraphic);
+ if( nError == ERRCODE_NONE )
+ {
+ SdrGrafObj* pNewObject(pGraphicObj->CloneSdrObject(pGraphicObj->getSdrModelFromSdrObject()));
+ pNewObject->SetGraphic( aGraphic );
+ SdrPageView* pPageView = pView->GetSdrPageView();
+ OUString aUndoString = pView->GetDescriptionOfMarkedObjects() + " Change";
+ pView->BegUndo( aUndoString );
+ pView->ReplaceObjectAtView( pObj, *pPageView, pNewObject );
+ pView->EndUndo();
+ }
+ }
+ }
+ }
+
+ Invalidate();
+}
+
+void ScGraphicShell::GetChangePictureState(SfxItemSet &rSet)
+{
+ ScDrawView* pView = GetViewData().GetScDrawView();
+ const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
+ bool bEnable = false;
+ if( rMarkList.GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ if( auto pGrafObj = dynamic_cast<const SdrGrafObj*>( pObj) )
+ if( pGrafObj->GetGraphicType() == GraphicType::Bitmap )
+ bEnable = true;
+ }
+
+ if( !bEnable )
+ rSet.DisableItem( SID_CHANGE_PICTURE );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/mediash.cxx b/sc/source/ui/drawfunc/mediash.cxx
new file mode 100644
index 000000000..f5b3350ba
--- /dev/null
+++ b/sc/source/ui/drawfunc/mediash.cxx
@@ -0,0 +1,65 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+#include <vcl/EnumContext.hxx>
+#include <svx/MediaShellHelpers.hxx>
+
+#include <mediash.hxx>
+#include <strings.hrc>
+#include <viewdata.hxx>
+#include <drawview.hxx>
+#include <scresid.hxx>
+
+#define ShellClass_ScMediaShell
+#include <scslots.hxx>
+
+using namespace svx;
+
+SFX_IMPL_INTERFACE(ScMediaShell, ScDrawShell)
+
+void ScMediaShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible,
+ ToolbarId::Media_Objectbar);
+
+ GetStaticInterface()->RegisterPopupMenu("media");
+}
+
+ScMediaShell::ScMediaShell(ScViewData& rData)
+ : ScDrawShell(rData)
+{
+ SetName(ScResId(SCSTR_MEDIASHELL));
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Media));
+}
+
+ScMediaShell::~ScMediaShell() {}
+
+void ScMediaShell::GetMediaState(SfxItemSet& rSet)
+{
+ MediaShellHelpers::GetState(GetViewData().GetScDrawView(), rSet);
+}
+
+void ScMediaShell::ExecuteMedia(const SfxRequest& rReq)
+{
+ MediaShellHelpers::Execute(GetViewData().GetScDrawView(), rReq);
+ Invalidate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/drawfunc/oleobjsh.cxx b/sc/source/ui/drawfunc/oleobjsh.cxx
new file mode 100644
index 000000000..0e9f0075d
--- /dev/null
+++ b/sc/source/ui/drawfunc/oleobjsh.cxx
@@ -0,0 +1,51 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/objface.hxx>
+
+#include <oleobjsh.hxx>
+#include <vcl/EnumContext.hxx>
+
+#define ShellClass_ScOleObjectShell
+#include <scslots.hxx>
+
+SFX_IMPL_INTERFACE(ScOleObjectShell, ScDrawShell)
+
+void ScOleObjectShell::InitInterface_Impl()
+{
+ GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
+ SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
+ ToolbarId::Draw_Objectbar);
+
+ GetStaticInterface()->RegisterPopupMenu("oleobject");
+}
+
+
+ScOleObjectShell::ScOleObjectShell(ScViewData& rData) :
+ ScDrawShell(rData)
+{
+ SetName("OleObject");
+ SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::OLE));
+}
+
+ScOleObjectShell::~ScOleObjectShell()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */