diff options
Diffstat (limited to 'sc/source/ui/drawfunc')
27 files changed, 9393 insertions, 0 deletions
diff --git a/sc/source/ui/drawfunc/chartsh.cxx b/sc/source/ui/drawfunc/chartsh.cxx new file mode 100644 index 0000000000..e6378a5fa9 --- /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 inChartOrMathContext(const ScTabViewShell* pViewShell) +{ + SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(pViewShell); + if (pSidebar) + return pSidebar->hasChartOrMathContextCurrently(); + + 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(!inChartOrMathContext(GetViewData().GetViewShell())) + ScDrawShell::Activate(bMDI); + else + { + // Avoid context changes for chart/math during activation / deactivation. + const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false)); + + SfxShell::Activate(bMDI); + + SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled); + } +} + +void ScChartShell::Deactivate(bool bMDI) +{ + if(!inChartOrMathContext(GetViewData().GetViewShell())) + ScDrawShell::Deactivate(bMDI); + else + { + // Avoid context changes for chart/math 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 0000000000..837cf4bc02 --- /dev/null +++ b/sc/source/ui/drawfunc/drawsh.cxx @@ -0,0 +1,596 @@ +/* -*- 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(SfxItemSet& rArgs) + { + 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); + } + if (const SfxStringItem* pJSON = rArgs.GetItemIfSet(SID_FILL_GRADIENT_JSON, false)) + { + basegfx::BGradient aGradient = basegfx::BGradient::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_CELL_FORMAT_RESET: + case SID_TEXT_STANDARD: + { + SfxItemSetFixed<SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_MINFRAMEHEIGHT, + SDRATTR_TEXT_MAXFRAMEHEIGHT, SDRATTR_TEXT_MAXFRAMEWIDTH> aEmptyAttr(GetPool()); + + if (ScDrawLayer::IsNoteCaption(pSingleSelectedObj)) + aEmptyAttr.Put(pView->GetAttrFromMarked(true)); + + 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() ) + { + std::unique_ptr<SfxItemSet> pNewArgs = rReq.GetArgs()->Clone(); + lcl_convertStringArguments(*pNewArgs); + pView->SetAttrToMarked(*pNewArgs, 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(); + for (const rtl::Reference<SdrObject>& pChildObj : *pOL) + { + pInfo = ScDrawLayer::GetMacroInfo( pChildObj.get(), 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 0000000000..8556c18e6b --- /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& rViewFrm = rViewData.GetViewShell()->GetViewFrame(); + rSet.Put(SfxBoolItem(SID_FONTWORK, rViewFrm.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=" + OString::number(nFillColor))); + } + + 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 + { + pDrView->GetAttributes(rSet); + } + + 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 0000000000..5c9b8cf926 --- /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 = DynCastSdrTextObj(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 0000000000..7c39afc2de --- /dev/null +++ b/sc/source/ui/drawfunc/drawsh5.cxx @@ -0,0 +1,724 @@ +/* -*- 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& rViewFrm = rViewData.GetViewShell()->GetViewFrame(); + + if ( rReq.GetArgs() ) + rViewFrm.SetChildWindow( nId, + static_cast<const SfxBoolItem&>( + (rReq.GetArgs()->Get(SID_FONTWORK))). + GetValue() ); + else + rViewFrm.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()); + bool isDecorative(pSelected->IsDecorative()); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + vcl::Window* pWin = rViewData.GetActiveWin(); + ScopedVclPtr<AbstractSvxObjectTitleDescDialog> pDlg(pFact->CreateSvxObjectTitleDescDialog( + pWin ? pWin->GetFrameWeld() : nullptr, aTitle, aDescription, isDecorative)); + + if(RET_OK == pDlg->Execute()) + { + ScDocShell* pDocSh = rViewData.GetDocShell(); + + // handle Title and Description + pDlg->GetTitle(aTitle); + pDlg->GetDescription(aDescription); + pDlg->IsDecorative(isDecorative); + pSelected->SetTitle(aTitle); + pSelected->SetDescription(aDescription); + pSelected->SetDecorative(isDecorative); + + // 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 0000000000..b91e08646b --- /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 0000000000..189ae2793a --- /dev/null +++ b/sc/source/ui/drawfunc/drtxtob.cxx @@ -0,0 +1,1256 @@ +/* -*- 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 <editeng/editund2.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(nFormat); + } + } + 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: + { + auto const attribs = pOutView->GetAttribs(); + const SvxFontItem& rItem = attribs.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: + { + const SvxFieldItem* pFieldItem + = pOutView->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true); + const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr; + 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 SvxFieldItem* pFieldItem + = pOutView->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true); + const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr; + 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: + { + 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& rViewFrm = mrViewData.GetViewShell()->GetViewFrame(); + bool bHasFontWork = rViewFrm.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 SvxFieldItem* pFieldItem = pOutView->GetFieldAtSelection(); + const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr; + 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) + { + OutlinerView* pOutView = mrViewData.GetScDrawView()->GetTextEditOutlinerView(); + if (!URLFieldHelper::IsCursorAtURLField(pOutView, /*AlsoCheckBeforeCursor=*/true)) + { + 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, rViewFrm.GetBindings(), SID_TRANSLITERATE_HALFWIDTH ); + if( rSet.GetItemState( SID_TRANSLITERATE_FULLWIDTH ) != SfxItemState::UNKNOWN ) + ScViewUtil::HideDisabledSlot( rSet, rViewFrm.GetBindings(), SID_TRANSLITERATE_FULLWIDTH ); + if( rSet.GetItemState( SID_TRANSLITERATE_HIRAGANA ) != SfxItemState::UNKNOWN ) + ScViewUtil::HideDisabledSlot( rSet, rViewFrm.GetBindings(), SID_TRANSLITERATE_HIRAGANA ); + if( rSet.GetItemState( SID_TRANSLITERATE_KATAKANA ) != SfxItemState::UNKNOWN ) + ScViewUtil::HideDisabledSlot( rSet, rViewFrm.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 ); + if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE)) + aFormats.AddClipbrdFormat(SotClipboardFormatId::HTML_SIMPLE); + + 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_CELL_FORMAT_RESET: + case SID_TEXT_STANDARD: + { + OutlinerView* pOutView = pView->IsTextEdit() ? + pView->GetTextEditOutlinerView() : nullptr; + if ( pOutView ) + pOutView->Paint( tools::Rectangle() ); + + SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aEmptyAttr( *aEditAttr.GetPool() ); + SfxItemSetFixed<SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_MINFRAMEHEIGHT, + SDRATTR_TEXT_MAXFRAMEHEIGHT, SDRATTR_TEXT_MAXFRAMEWIDTH> aSizeAttr(*aEditAttr.GetPool()); + + aSizeAttr.Put(pView->GetAttrFromMarked(true)); + pView->SetAttributes( aEmptyAttr, true ); + + if (IsNoteEdit()) + { + pView->SetAttributes(aSizeAttr, false); + pView->GetTextEditObject()->AdjustTextFrameWidthAndHeight(); + } + + 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.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 0000000000..4810876a33 --- /dev/null +++ b/sc/source/ui/drawfunc/drtxtob1.cxx @@ -0,0 +1,125 @@ +/* -*- 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() ); + pDlg->Insert(SotClipboardFormatId::HTML_SIMPLE, 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(nFormat); + } +} + +/* 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 0000000000..37629721cf --- /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& rViewFrm = mrViewData.GetViewShell()->GetViewFrame(); + + if ( rReq.GetArgs() ) + rViewFrm.SetChildWindow( nId, + static_cast<const SfxBoolItem&>( + (rReq.GetArgs()->Get(SID_FONTWORK))). + GetValue() ); + else + rViewFrm.ToggleChildWindow( nId ); + + rViewFrm.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 = DynCastSdrTextObj(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 0000000000..77deb115fa --- /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 +rtl::Reference<SdrObject> FuConstArc::CreateDefaultObject(const sal_uInt16 nID, const tools::Rectangle& rRectangle) +{ + // case SID_DRAW_ARC: + // case SID_DRAW_PIE: + // case SID_DRAW_CIRCLECUT: + + rtl::Reference<SdrObject> 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 0000000000..2994187b36 --- /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 +rtl::Reference<SdrObject> FuConstCustomShape::CreateDefaultObject(const sal_uInt16 /* nID */, const tools::Rectangle& rRectangle) +{ + rtl::Reference<SdrObject> 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 0000000000..7290b5186a --- /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 +rtl::Reference<SdrObject> 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: + + rtl::Reference<SdrObject> 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 0000000000..0f06de3d82 --- /dev/null +++ b/sc/source/ui/drawfunc/fuconrec.cxx @@ -0,0 +1,290 @@ +/* -*- 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> +#include <svx/constructhelper.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() +{ +} + +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 = DynCastSdrTextObj( 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) +{ + ConstructHelper::SetLineEnds(rAttr, rObj, nSlotId, 200); +} + +void FuConstRectangle::Deactivate() +{ + FuConstruct::Deactivate(); + rViewShell.SetActivePointer( aOldPointer ); +} + +// Create default drawing objects via keyboard +rtl::Reference<SdrObject> FuConstRectangle::CreateDefaultObject(const sal_uInt16 nID, const tools::Rectangle& rRectangle) +{ + rtl::Reference<SdrObject> 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 0000000000..0ffb6e832d --- /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 ( DynCastSdrTextObj( 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 0000000000..e3c8f0b4d7 --- /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 +rtl::Reference<SdrObject> FuConstUnoControl::CreateDefaultObject(const sal_uInt16 /* nID */, const tools::Rectangle& rRectangle) +{ + // case SID_FM_CREATE_CONTROL: + + rtl::Reference<SdrObject> 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 0000000000..9076a75ada --- /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 ( DynCastSdrTextObj( 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 0000000000..72886789b4 --- /dev/null +++ b/sc/source/ui/drawfunc/fuins1.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 <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 ); + + rtl::Reference<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.get(), *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 ); +} + +#if HAVE_FEATURE_AVMEDIA + +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()); + bool const bRet = ::avmedia::EmbedMedia(xModel, rMediaURL, realURL); + if (!bRet) { return; } + } + + rtl::Reference<SdrMediaObj> pObj = new SdrMediaObj( + *rData.GetDocument().GetDrawLayer(), + tools::Rectangle(aInsertPos, aSize)); + + pObj->setURL( realURL, ""/*TODO?*/ ); + pView->InsertObjectAtView( pObj.get(), *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE ); +} +#endif + +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 0000000000..959424b40b --- /dev/null +++ b/sc/source/ui/drawfunc/fuins2.cxx @@ -0,0 +1,703 @@ +/* -*- 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 <svtools/strings.hrc> +#include <svtools/svtresid.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 <comphelper/diagnose_ex.hxx> +#include <vcl/weldutils.hxx> + +#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 <officecfg/Office/Common.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( getXWeak(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 : + if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()) + { + std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog( + nullptr, VclMessageType::Warning, VclButtonsType::Ok, + SvtResId(STR_WARNING_ACTIVE_CONTENT_DISABLED))); + xError->run(); + break; + } + 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)->GetCommand(), + 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); + rtl::Reference<SdrOle2Obj> pObj = new SdrOle2Obj( + *pDoc, // TTTT should be reference + aObjRef, + aName, + aRect); + SdrPageView* pPV = pView->GetSdrPageView(); + bool bSuccess = pView->InsertObjectAtView(pObj.get(), *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.get(), 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); + rtl::Reference<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.get() ); + pView->UnmarkAllObj(); + pView->MarkObj( pObj.get(), 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.get(), 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() ) + { + css::uno::Reference< css::awt::XWindow > xParent + = new weld::TransportAsXWindow(pWin->GetFrameWeld()); + uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", uno::Any(xParent)}, + {"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 0000000000..4299e02512 --- /dev/null +++ b/sc/source/ui/drawfunc/fupoor.cxx @@ -0,0 +1,279 @@ +/* -*- 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 )) + { + double fHitLog = pWindow->PixelToLogic(Size(pView->GetHitTolerancePixel(),0)).Width(); + if(SdrObjectPrimitiveHit(*pObject, rLogicPos, {fHitLog, fHitLog}, *pPV, nullptr, false)) + { + bFound = true; + } + } + + pObject = aIter.Next(); + } + return bFound; +} + +void FuPoor::StopDragTimer() +{ + if (aDragTimer.IsActive() ) + aDragTimer.Stop(); +} + +// Create default drawing objects via keyboard +rtl::Reference<SdrObject> 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 0000000000..d95f810308 --- /dev/null +++ b/sc/source/ui/drawfunc/fusel.cxx @@ -0,0 +1,558 @@ +/* -*- 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> +#include <stlpool.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() ); + } + } + } + } + } + + if (SC_MOD()->GetIsWaterCan()) + { + auto pStyleSheet = rViewData.GetDocument().GetStyleSheetPool()->GetActualStyleSheet(); + if (pStyleSheet && pStyleSheet->GetFamily() == SfxStyleFamily::Frame) + pView->SetStyleSheet(static_cast<SfxStyleSheet*>(pStyleSheet), false); + } + } + + // 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()) + { + // release so if ActivateObject launches a warning dialog, then that dialog + // can get mouse events + if (pWindow->IsMouseCaptured()) + pWindow->ReleaseMouse(); + 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 ( DynCastSdrTextObj( 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 ? 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 0000000000..cc9a1478ce --- /dev/null +++ b/sc/source/ui/drawfunc/fusel2.cxx @@ -0,0 +1,148 @@ +/* -*- 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 )) + { + double fHitLog = pWindow->PixelToLogic(Size(pView->GetHitTolerancePixel(),0)).Width(); + if (SdrObjectPrimitiveHit(*pObject, rPos, {fHitLog, fHitLog}, *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; +} + +/* 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 0000000000..0a26c7693b --- /dev/null +++ b/sc/source/ui/drawfunc/futext.cxx @@ -0,0 +1,688 @@ +/* -*- 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 <editeng/editund2.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 = DynCastSdrTextObj( 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 || + DynCastSdrTextObj( 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 +rtl::Reference<SdrObject> 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: + + rtl::Reference<SdrObject> pObj(SdrObjFactory::MakeNewObject( + *pDrDoc, + pView->GetCurrentObjInventor(), + pView->GetCurrentObjIdentifier())); + + if(pObj) + { + if(auto pText = DynCastSdrTextObj( 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 0000000000..8f30cb4a6f --- /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 0000000000..c7e59c5bea --- /dev/null +++ b/sc/source/ui/drawfunc/futext3.cxx @@ -0,0 +1,186 @@ +/* -*- 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; + if (pUndoMgr && !pUndoMgr->GetMaxUndoActionCount()) // tdf#134308 if max undo is 0, treat as if no undo + pUndoMgr = 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 + + /* Unset the outliner undo manager before the call to SdrEndTextEdit. + SdrObjEditView::SdrEndTextEdit destroys it, but then ScDrawView::SdrEndTextEdit + initiates some UI update which might try to access the now invalid pointer. */ + rViewShell.SetDrawTextUndo( nullptr ); + + /* 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 ); + + 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 = DynCastSdrTextObj( 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 0000000000..9252dffa76 --- /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 ) + { + rtl::Reference<SdrGrafObj> pFilteredObj = SdrObject::Clone(*pGraphicObj, pGraphicObj->getSdrModelFromSdrObject()); + OUString aStr = pView->GetDescriptionOfMarkedObjects() + " " + ScResId(SCSTR_UNDO_GRAFFILTER); + pView->BegUndo( aStr ); + pFilteredObj->SetGraphicObject( aFilterObj ); + pView->ReplaceObjectAtView( pObj, *pPageView, pFilteredObj.get() ); + 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, pGraphicObj)); + 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) + { + rtl::Reference<SdrGrafObj> pNewObject = dialog.GetCompressedSdrGrafObj(); + SdrPageView* pPageView = pView->GetSdrPageView(); + OUString aUndoString = pView->GetDescriptionOfMarkedObjects() + " Compress"; + pView->BegUndo( aUndoString ); + pView->ReplaceObjectAtView( pObj, *pPageView, pNewObject.get() ); + 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 ) + { + rtl::Reference<SdrGrafObj> pNewObject(SdrObject::Clone(*pGraphicObj, pGraphicObj->getSdrModelFromSdrObject())); + pNewObject->SetGraphic( aGraphic ); + SdrPageView* pPageView = pView->GetSdrPageView(); + OUString aUndoString = pView->GetDescriptionOfMarkedObjects() + " Change"; + pView->BegUndo( aUndoString ); + pView->ReplaceObjectAtView( pObj, *pPageView, pNewObject.get() ); + 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 0000000000..f5b3350ba6 --- /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 0000000000..0e9f0075d9 --- /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: */ |