diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sd/source/ui/view/sdview2.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sd/source/ui/view/sdview2.cxx')
-rw-r--r-- | sd/source/ui/view/sdview2.cxx | 908 |
1 files changed, 908 insertions, 0 deletions
diff --git a/sd/source/ui/view/sdview2.cxx b/sd/source/ui/view/sdview2.cxx new file mode 100644 index 000000000..a5b3d4413 --- /dev/null +++ b/sd/source/ui/view/sdview2.cxx @@ -0,0 +1,908 @@ +/* -*- 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 <View.hxx> + +#include <vector> +#include <com/sun/star/embed/XEmbedPersist.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <comphelper/sequenceashashmap.hxx> +#include <tools/urlobj.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svxdlg.hxx> +#include <sfx2/docfile.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdpagv.hxx> +#include <svl/urlbmk.hxx> +#include <editeng/outliner.hxx> +#include <svx/xflclit.hxx> +#include <sot/formats.hxx> +#include <editeng/editeng.hxx> + +#include <svtools/embedtransfer.hxx> +#include <tools/debug.hxx> + +#include <anminfo.hxx> +#include <strings.hrc> +#include <sdxfer.hxx> +#include <sdresid.hxx> +#include <sdmod.hxx> +#include <sdtreelb.hxx> +#include <DrawViewShell.hxx> +#include <DrawDocShell.hxx> +#include <fudraw.hxx> +#include <drawdoc.hxx> +#include <Window.hxx> +#include <sdpage.hxx> +#include <unoaprms.hxx> +#include <helpids.h> +#include <vcl/svapp.hxx> + +#include <slideshow.hxx> +#include <memory> + +namespace sd { + +using namespace ::com::sun::star; + +namespace { + +struct SdNavigatorDropEvent : public ExecuteDropEvent +{ + VclPtr< ::sd::Window> mpTargetWindow; + + SdNavigatorDropEvent ( + const ExecuteDropEvent& rEvt, + ::sd::Window* pTargetWindow ) + : ExecuteDropEvent( rEvt ), + mpTargetWindow( pTargetWindow ) + {} +}; + +} + +css::uno::Reference< css::datatransfer::XTransferable > View::CreateClipboardDataObject() +{ + // since SdTransferable::CopyToClipboard is called, this + // dynamically created object is destroyed automatically + rtl::Reference<SdTransferable> pTransferable = new SdTransferable( &mrDoc, nullptr, false ); + + SD_MOD()->pTransferClip = pTransferable.get(); + + mrDoc.CreatingDataObj( pTransferable.get() ); + pTransferable->SetWorkDocument( static_cast<SdDrawDocument*>(CreateMarkedObjModel().release()) ); + mrDoc.CreatingDataObj( nullptr ); + + // #112978# need to use GetAllMarkedBoundRect instead of GetAllMarkedRect to get + // fat lines correctly + const ::tools::Rectangle aMarkRect( GetAllMarkedBoundRect() ); + std::unique_ptr<TransferableObjectDescriptor> pObjDesc(new TransferableObjectDescriptor); + SdrOle2Obj* pSdrOleObj = nullptr; + SdrPageView* pPgView = GetSdrPageView(); + SdPage* pOldPage = pPgView ? static_cast<SdPage*>( pPgView->GetPage() ) : nullptr; + SdPage* pNewPage = const_cast<SdPage*>(static_cast<const SdPage*>( pTransferable->GetWorkDocument()->GetPage( 0 ) )); + + if( pOldPage ) + { + pNewPage->SetSize( pOldPage->GetSize() ); + pNewPage->SetLayoutName( pOldPage->GetLayoutName() ); + } + + if( GetMarkedObjectCount() == 1 ) + { + SdrObject* pObj = GetMarkedObjectByIndex(0); + + if( auto pOle2Obj = dynamic_cast<SdrOle2Obj *>( pObj ) ) + if( pOle2Obj->GetObjRef() ) + { + // If object has no persistence it must be copied as part of the document + try + { + uno::Reference< embed::XEmbedPersist > xPersObj( pOle2Obj->GetObjRef(), uno::UNO_QUERY ); + if ( xPersObj.is() && xPersObj->hasEntry() ) + pSdrOleObj = pOle2Obj; + } + catch( uno::Exception& ) + {} + } + } + + if( pSdrOleObj ) + SvEmbedTransferHelper::FillTransferableObjectDescriptor( *pObjDesc, pSdrOleObj->GetObjRef(), pSdrOleObj->GetGraphic(), pSdrOleObj->GetAspect() ); + else + pTransferable->GetWorkDocument()->GetDocSh()->FillTransferableObjectDescriptor( *pObjDesc ); + + if( mpDocSh ) + pObjDesc->maDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + + pObjDesc->maSize = aMarkRect.GetSize(); + + pTransferable->SetStartPos( aMarkRect.TopLeft() ); + pTransferable->SetObjectDescriptor( std::move(pObjDesc) ); + pTransferable->CopyToClipboard( mpViewSh->GetActiveWindow() ); + + return pTransferable; +} + +css::uno::Reference< css::datatransfer::XTransferable > View::CreateDragDataObject( View* pWorkView, vcl::Window& rWindow, const Point& rDragPos ) +{ + rtl::Reference<SdTransferable> pTransferable = new SdTransferable( &mrDoc, pWorkView, false ); + + SD_MOD()->pTransferDrag = pTransferable.get(); + + std::unique_ptr<TransferableObjectDescriptor> pObjDesc(new TransferableObjectDescriptor); + OUString aDisplayName; + SdrOle2Obj* pSdrOleObj = nullptr; + + if( GetMarkedObjectCount() == 1 ) + { + SdrObject* pObj = GetMarkedObjectByIndex( 0 ); + + if( auto pOle2Obj = dynamic_cast<SdrOle2Obj *>( pObj ) ) + if( pOle2Obj->GetObjRef() ) + { + // If object has no persistence it must be copied as part of the document + try + { + uno::Reference< embed::XEmbedPersist > xPersObj( pOle2Obj->GetObjRef(), uno::UNO_QUERY ); + if ( xPersObj.is() && xPersObj->hasEntry() ) + pSdrOleObj = pOle2Obj; + } + catch( uno::Exception& ) + {} + } + } + + if( mpDocSh ) + aDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + + if( pSdrOleObj ) + SvEmbedTransferHelper::FillTransferableObjectDescriptor( *pObjDesc, pSdrOleObj->GetObjRef(), pSdrOleObj->GetGraphic(), pSdrOleObj->GetAspect() ); + else if (mpDocSh) + mpDocSh->FillTransferableObjectDescriptor( *pObjDesc ); + + pObjDesc->maSize = GetAllMarkedRect().GetSize(); + pObjDesc->maDragStartPos = rDragPos; + pObjDesc->maDisplayName = aDisplayName; + + pTransferable->SetStartPos( rDragPos ); + pTransferable->SetObjectDescriptor( std::move(pObjDesc) ); + pTransferable->StartDrag( &rWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK ); + + return pTransferable; +} + +css::uno::Reference< css::datatransfer::XTransferable > View::CreateSelectionDataObject( View* pWorkView ) +{ + rtl::Reference<SdTransferable> pTransferable = new SdTransferable( &mrDoc, pWorkView, true ); + std::unique_ptr<TransferableObjectDescriptor> pObjDesc(new TransferableObjectDescriptor); + const ::tools::Rectangle aMarkRect( GetAllMarkedRect() ); + + SD_MOD()->pTransferSelection = pTransferable.get(); + + if( mpDocSh ) + { + mpDocSh->FillTransferableObjectDescriptor( *pObjDesc ); + pObjDesc->maDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + } + + pObjDesc->maSize = aMarkRect.GetSize(); + + pTransferable->SetStartPos( aMarkRect.TopLeft() ); + pTransferable->SetObjectDescriptor( std::move(pObjDesc) ); + pTransferable->CopyToPrimarySelection(); + + return pTransferable; +} + +void View::UpdateSelectionClipboard() // false case +{ + if (!mpViewSh) + return; + if (!mpViewSh->GetActiveWindow()) + return; + if (GetMarkedObjectList().GetMarkCount()) + CreateSelectionDataObject( this ); + else + ClearSelectionClipboard(); +} + +void View::ClearSelectionClipboard() // true case +{ + if (!mpViewSh) + return; + if (!mpViewSh->GetActiveWindow()) + return; + if (SD_MOD()->pTransferSelection && SD_MOD()->pTransferSelection->GetView() == this) + { + TransferableHelper::ClearPrimarySelection(); + SD_MOD()->pTransferSelection = nullptr; + } +} + +void View::DoCut() +{ + const OutlinerView* pOLV = GetTextEditOutlinerView(); + + if( pOLV ) + const_cast<OutlinerView*>(pOLV)->Cut(); + else if( AreObjectsMarked() ) + { + OUString aStr(SdResId(STR_UNDO_CUT)); + + DoCopy(); + BegUndo(aStr + " " + GetDescriptionOfMarkedObjects()); + DeleteMarked(); + EndUndo(); + } +} + +void View::DoCopy() +{ + const OutlinerView* pOLV = GetTextEditOutlinerView(); + + if( pOLV ) + const_cast<OutlinerView*>(pOLV)->Copy(); + else if( AreObjectsMarked() ) + { + BrkAction(); + CreateClipboardDataObject(); + } +} + +void View::DoPaste (::sd::Window* pWindow) +{ + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewSh->GetActiveWindow() ) ); + if( !aDataHelper.GetTransferable().is() ) + return; // empty clipboard? + + const OutlinerView* pOLV = GetTextEditOutlinerView(); + + if( pOLV && EditEngine::HasValidData( aDataHelper.GetTransferable() ) ) + { + const_cast< OutlinerView* >(pOLV)->PasteSpecial(); + + SdrObject* pObj = GetTextEditObject(); + SdPage* pPage = static_cast<SdPage*>( pObj ? pObj->getSdrPageFromSdrObject() : nullptr ); + ::Outliner* pOutliner = pOLV->GetOutliner(); + + if( pOutliner) + { + if( pObj && pPage && pPage->GetPresObjKind(pObj) == PresObjKind::Title ) + { + // remove all hard linebreaks from the title + if (pOutliner->GetParagraphCount() > 1) + { + bool bOldUpdateMode = pOutliner->SetUpdateLayout( false ); + + const EditEngine& rEdit = pOutliner->GetEditEngine(); + const sal_Int32 nParaCount = rEdit.GetParagraphCount(); + + for( sal_Int32 nPara = nParaCount - 2; nPara >= 0; nPara-- ) + { + const sal_Int32 nParaLen = rEdit.GetTextLen( nPara ); + pOutliner->QuickDelete( ESelection( nPara, nParaLen, nPara+1, 0 ) ); + pOutliner->QuickInsertLineBreak( ESelection( nPara, nParaLen, nPara, nParaLen ) ); + } + + DBG_ASSERT( rEdit.GetParagraphCount() <= 1, "Titleobject contains hard line breaks" ); + pOutliner->SetUpdateLayout(bOldUpdateMode); + } + } + + if( !mrDoc.IsChanged() ) + { + if (pOutliner->IsModified()) + mrDoc.SetChanged(); + } + } + } + else + { + Point aPos = pWindow->GetVisibleCenter(); + DrawViewShell* pDrViewSh = static_cast<DrawViewShell*>( mpDocSh->GetViewShell() ); + + if (pDrViewSh != nullptr) + { + sal_Int8 nDnDAction = DND_ACTION_COPY; + if( !InsertData( aDataHelper, aPos, nDnDAction, false ) ) + { + INetBookmark aINetBookmark( "", "" ); + + if( ( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) || + ( aDataHelper.HasFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::FILEGRPDESCRIPTOR, aINetBookmark ) ) || + ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) + { + pDrViewSh->InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), "" ); + } + } + } + } +} + +void View::StartDrag( const Point& rStartPos, vcl::Window* pWindow ) +{ + if (!AreObjectsMarked() || !IsAction() || !mpViewSh || !pWindow) + return; + + BrkAction(); + + if( IsTextEdit() ) + SdrEndTextEdit(); + + if (DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(mpDocSh ? mpDocSh->GetViewShell() : nullptr)) + { + const rtl::Reference<FuPoor>& xFunction(pDrawViewShell->GetCurrentFunction()); + if (FuDraw* pFunction = dynamic_cast<FuDraw*>(xFunction.get())) + pFunction->ForcePointer(); + } + + mpDragSrcMarkList.reset( new SdrMarkList(GetMarkedObjectList()) ); + mnDragSrcPgNum = GetSdrPageView()->GetPage()->GetPageNum(); + + CreateDragDataObject( this, *pWindow, rStartPos ); +} + +void View::DragFinished( sal_Int8 nDropAction ) +{ + const bool bUndo = IsUndoEnabled(); + const bool bGroupUndo = bUndo && mpDragSrcMarkList; + if (bGroupUndo) + { + OUString aStr(SdResId(STR_UNDO_DRAGDROP)); + BegUndo(aStr + " " + mpDragSrcMarkList->GetMarkDescription()); + } + + SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + + if( pDragTransferable ) + pDragTransferable->SetView( nullptr ); + + if( ( nDropAction & DND_ACTION_MOVE ) && + pDragTransferable && !pDragTransferable->IsInternalMove() && + mpDragSrcMarkList && mpDragSrcMarkList->GetMarkCount() && + !IsPresObjSelected() ) + { + mpDragSrcMarkList->ForceSort(); + + if( bUndo ) + BegUndo(); + + const size_t nCnt = mpDragSrcMarkList->GetMarkCount(); + + for( size_t nm = nCnt; nm>0; ) + { + --nm; + SdrMark* pM=mpDragSrcMarkList->GetMark(nm); + if( bUndo ) + AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeleteObject(*pM->GetMarkedSdrObj())); + } + + mpDragSrcMarkList->GetMark(0)->GetMarkedSdrObj()->GetOrdNum(); + + for (size_t nm = nCnt; nm>0;) + { + --nm; + SdrMark* pM=mpDragSrcMarkList->GetMark(nm); + SdrObject* pObj=pM->GetMarkedSdrObj(); + + if( pObj && pObj->getSdrPageFromSdrObject() ) + { + const size_t nOrdNum = pObj->GetOrdNumDirect(); + SdrObject* pChkObj = pObj->getSdrPageFromSdrObject()->RemoveObject(nOrdNum); + DBG_ASSERT(pChkObj==pObj,"pChkObj!=pObj in RemoveObject()"); + } + } + + if( bUndo ) + EndUndo(); + } + + if( pDragTransferable ) + pDragTransferable->SetInternalMove( false ); + + if (bGroupUndo) + EndUndo(); + mnDragSrcPgNum = SDRPAGE_NOTFOUND; + mpDragSrcMarkList.reset(); +} + +sal_Int8 View::AcceptDrop( const AcceptDropEvent& rEvt, DropTargetHelper& rTargetHelper, + SdrLayerID nLayer ) +{ + OUString aLayerName = GetActiveLayer(); + SdrPageView* pPV = GetSdrPageView(); + sal_Int8 nDropAction = rEvt.mnAction; + sal_Int8 nRet = DND_ACTION_NONE; + + if( nLayer != SDRLAYER_NOTFOUND ) + { + SdrLayerAdmin& rLayerAdmin = mrDoc.GetLayerAdmin(); + aLayerName = rLayerAdmin.GetLayerPerID(nLayer)->GetName(); + } + + if( mbIsDropAllowed && !pPV->IsLayerLocked( aLayerName ) && pPV->IsLayerVisible( aLayerName ) ) + { + const OutlinerView* pOLV = GetTextEditOutlinerView(); + bool bIsInsideOutlinerView = false; + + if( pOLV ) + { + ::tools::Rectangle aRect( pOLV->GetOutputArea() ); + + if (GetMarkedObjectCount() == 1) + { + SdrMark* pMark = GetSdrMarkByIndex(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + aRect.Union( pObj->GetLogicRect() ); + } + + if( aRect.Contains( pOLV->GetWindow()->PixelToLogic( rEvt.maPosPixel ) ) ) + { + bIsInsideOutlinerView = true; + } + } + + if( !bIsInsideOutlinerView ) + { + SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + + if(pDragTransferable && (nDropAction & DND_ACTION_LINK)) + { + // suppress own data when it's intention is to use it as fill information + pDragTransferable = nullptr; + } + + if( pDragTransferable ) + { + const View* pSourceView = pDragTransferable->GetView(); + + if( pDragTransferable->IsPageTransferable() ) + { + nRet = DND_ACTION_COPY; + } + else if( pSourceView ) + { + if( !( nDropAction & DND_ACTION_LINK ) || + !pSourceView->GetDocSh()->GetMedium()->GetName().isEmpty() ) + { + nRet = nDropAction; + } + } + } + else + { + const bool bDrawing = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::DRAWING ); + const bool bGraphic = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SVXB ); + const bool bMtf = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::GDIMETAFILE ); + const bool bBitmap = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::BITMAP ); + bool bBookmark = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK ); + bool bXFillExchange = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::XFA ); + + // check handle insert + if ((bXFillExchange && (SdrDragMode::Gradient == GetDragMode())) + || (SdrDragMode::Transparence == GetDragMode())) + { + const SdrHdlList& rHdlList = GetHdlList(); + + for( size_t n = 0; n < rHdlList.GetHdlCount(); ++n ) + { + SdrHdl* pIAOHandle = rHdlList.GetHdl( n ); + + if( pIAOHandle && ( SdrHdlKind::Color == pIAOHandle->GetKind() ) ) + { + if(pIAOHandle->getOverlayObjectList().isHitPixel(rEvt.maPosPixel)) + { + nRet = nDropAction; + static_cast< SdrHdlColor* >( pIAOHandle )->SetSize( SDR_HANDLE_COLOR_SIZE_SELECTED ); + } + else + { + static_cast< SdrHdlColor* >( pIAOHandle )->SetSize( SDR_HANDLE_COLOR_SIZE_NORMAL ); + } + } + } + } + + // check object insert + if( !nRet && ( bXFillExchange || ( ( bDrawing || bGraphic || bMtf || bBitmap || bBookmark ) && ( nDropAction & DND_ACTION_LINK ) ) ) ) + { + SdrPageView* pPageView = nullptr; + ::sd::Window* pWindow = mpViewSh->GetActiveWindow(); + Point aPos( pWindow->PixelToLogic( rEvt.maPosPixel ) ); + SdrObject* pPickObj = PickObj(aPos, getHitTolLog(), pPageView); + bool bIsPresTarget = false; + + if (pPickObj && (pPickObj->IsEmptyPresObj() || pPickObj->GetUserCall())) + { + SdPage* pPage = static_cast<SdPage*>( pPickObj->getSdrPageFromSdrObject() ); + + if( pPage && pPage->IsMasterPage() ) + bIsPresTarget = pPage->IsPresObj( pPickObj ); + } + + if (pPickObj && !bIsPresTarget && (bGraphic || bMtf || bBitmap || bXFillExchange)) + { + if( mpDropMarkerObj != pPickObj ) + { + mpDropMarkerObj = pPickObj; + ImplClearDrawDropMarker(); + + if(mpDropMarkerObj) + { + mpDropMarker.reset( new SdrDropMarkerOverlay(*this, *mpDropMarkerObj) ); + } + } + + nRet = nDropAction; + } + else + bXFillExchange = false; + } + + // check normal insert + if( !nRet ) + { + const bool bSBAFormat = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SVX_FORMFIELDEXCH ); + const bool bEditEngineODF = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ); + const bool bString = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::STRING ); + const bool bRTF = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::RTF ); + const bool bFile = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ); + const bool bFileList = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::FILE_LIST ); + + if( mpDropMarker ) + { + ImplClearDrawDropMarker(); + mpDropMarkerObj = nullptr; + } + + if( bBookmark && bFile && ( nDropAction & DND_ACTION_MOVE ) && mpViewSh && SlideShow::IsRunning(mpViewSh->GetViewShellBase()) ) + bBookmark = false; + + if( bDrawing || bGraphic || bMtf || bBitmap || bBookmark || bFile || bFileList || bXFillExchange || bSBAFormat || bEditEngineODF || bString || bRTF ) + nRet = nDropAction; + + // For entries from the navigator, change action copy. + if (bBookmark + && rTargetHelper.IsDropFormatSupported( + SdPageObjsTLV::SdPageObjsTransferable::GetListBoxDropFormatId()) + && (nDropAction & DND_ACTION_MOVE)!=0) + { + nRet = DND_ACTION_COPY; + } + } + } + } + } + + // destroy drop marker if this is a leaving event + if( rEvt.mbLeaving && mpDropMarker ) + { + ImplClearDrawDropMarker(); + mpDropMarkerObj = nullptr; + } + + return nRet; +} + +sal_Int8 View::ExecuteDrop( const ExecuteDropEvent& rEvt, + ::sd::Window* pTargetWindow, sal_uInt16 nPage, SdrLayerID nLayer ) +{ + SdrPageView* pPV = GetSdrPageView(); + OUString aActiveLayer = GetActiveLayer(); + sal_Int8 nDropAction = rEvt.mnAction; + sal_Int8 nRet = DND_ACTION_NONE; + + // destroy drop marker if it is shown + if( mpDropMarker ) + { + ImplClearDrawDropMarker(); + mpDropMarkerObj = nullptr; + } + + if( !pPV->IsLayerLocked( aActiveLayer ) ) + { + const OutlinerView* pOLV = GetTextEditOutlinerView(); + bool bIsInsideOutlinerView = false; + + if( pOLV ) + { + ::tools::Rectangle aRect( pOLV->GetOutputArea() ); + + if( GetMarkedObjectCount() == 1 ) + { + SdrMark* pMark = GetSdrMarkByIndex(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + aRect.Union( pObj->GetLogicRect() ); + } + + Point aPos( pOLV->GetWindow()->PixelToLogic( rEvt.maPosPixel ) ); + + if( aRect.Contains( aPos ) ) + { + bIsInsideOutlinerView = true; + } + } + + if( !bIsInsideOutlinerView ) + { + Point aPos; + TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable ); + + if( pTargetWindow ) + aPos = pTargetWindow->PixelToLogic( rEvt.maPosPixel ); + + // handle insert? + if ((SdrDragMode::Gradient == GetDragMode()) + || ((SdrDragMode::Transparence == GetDragMode()) + && aDataHelper.HasFormat(SotClipboardFormatId::XFA))) + { + const SdrHdlList& rHdlList = GetHdlList(); + + for( size_t n = 0; !nRet && n < rHdlList.GetHdlCount(); ++n ) + { + SdrHdl* pIAOHandle = rHdlList.GetHdl( n ); + + if( pIAOHandle && ( SdrHdlKind::Color == pIAOHandle->GetKind() ) ) + { + if(pIAOHandle->getOverlayObjectList().isHitPixel(rEvt.maPosPixel)) + { + uno::Any const data(aDataHelper.GetAny(SotClipboardFormatId::XFA, "")); + uno::Sequence<beans::NamedValue> props; + if (data >>= props) + { + ::comphelper::SequenceAsHashMap const map(props); + Color aColor(COL_BLACK); + auto const it = map.find("FillColor"); + if (it != map.end()) + { + XFillColorItem color; + color.PutValue(it->second, 0); + aColor = color.GetColorValue(); + } + static_cast< SdrHdlColor* >( pIAOHandle )->SetColor( aColor, true ); + nRet = nDropAction; + } + } + } + } + } + + // standard insert? + if( !nRet && InsertData( aDataHelper, aPos, nDropAction, true, SotClipboardFormatId::NONE, nPage, nLayer ) ) + nRet = nDropAction; + + // special insert? + if( !nRet && mpViewSh ) + { + INetBookmark aINetBookmark( (OUString()), (OUString()) ); + + // insert bookmark + if( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) + { + SdPageObjsTLV::SdPageObjsTransferable* pPageObjsTransferable = SdPageObjsTLV::SdPageObjsTransferable::getImplementation( aDataHelper.GetXTransferable() ); + + if( pPageObjsTransferable && + ( NAVIGATOR_DRAGTYPE_LINK == pPageObjsTransferable->GetDragType() || + NAVIGATOR_DRAGTYPE_EMBEDDED == pPageObjsTransferable->GetDragType() ) ) + { + // insert bookmark from own navigator (handled async. due to possible message box ) + Application::PostUserEvent( LINK( this, View, ExecuteNavigatorDrop ), + new SdNavigatorDropEvent( rEvt, pTargetWindow ) ); + nRet = nDropAction; + } + else + { + SdrPageView* pPageView = nullptr; + + SdrObject* pPickObj = PickObj(aPos, getHitTolLog(), pPageView); + if (pPickObj) + { + // insert as clip action => jump + OUString aBookmark( aINetBookmark.GetURL() ); + SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo( pPickObj ); + + if( !aBookmark.isEmpty() ) + { + bool bCreated = false; + + presentation::ClickAction eClickAction = presentation::ClickAction_DOCUMENT; + + sal_Int32 nIndex = aBookmark.indexOf( '#' ); + if( nIndex != -1 ) + { + const std::u16string_view aDocName( aBookmark.subView( 0, nIndex ) ); + + if (mpDocSh->GetMedium()->GetName() == aDocName || aDocName == mpDocSh->GetName()) + { + // internal jump, only use the part after and including '#' + eClickAction = presentation::ClickAction_BOOKMARK; + aBookmark = aBookmark.copy( nIndex+1 ); + } + } + + if( !pInfo ) + { + pInfo = SdDrawDocument::GetShapeUserData( *pPickObj, true ); + bCreated = true; + } + + // create undo action with old and new sizes + std::unique_ptr<SdAnimationPrmsUndoAction> pAction(new SdAnimationPrmsUndoAction(&mrDoc, pPickObj, bCreated)); + pAction->SetActive(pInfo->mbActive, pInfo->mbActive); + pAction->SetEffect(pInfo->meEffect, pInfo->meEffect); + pAction->SetTextEffect(pInfo->meTextEffect, pInfo->meTextEffect); + pAction->SetSpeed(pInfo->meSpeed, pInfo->meSpeed); + pAction->SetDim(pInfo->mbDimPrevious, pInfo->mbDimPrevious); + pAction->SetDimColor(pInfo->maDimColor, pInfo->maDimColor); + pAction->SetDimHide(pInfo->mbDimHide, pInfo->mbDimHide); + pAction->SetSoundOn(pInfo->mbSoundOn, pInfo->mbSoundOn); + pAction->SetSound(pInfo->maSoundFile, pInfo->maSoundFile); + pAction->SetPlayFull(pInfo->mbPlayFull, pInfo->mbPlayFull); + pAction->SetClickAction(pInfo->meClickAction, eClickAction); + pAction->SetBookmark(pInfo->GetBookmark(), aBookmark); + pAction->SetVerb(pInfo->mnVerb, pInfo->mnVerb); + pAction->SetSecondEffect(pInfo->meSecondEffect, pInfo->meSecondEffect); + pAction->SetSecondSpeed(pInfo->meSecondSpeed, pInfo->meSecondSpeed); + pAction->SetSecondSoundOn(pInfo->mbSecondSoundOn, pInfo->mbSecondSoundOn); + pAction->SetSecondPlayFull(pInfo->mbSecondPlayFull, pInfo->mbSecondPlayFull); + + OUString aString(SdResId(STR_UNDO_ANIMATION)); + pAction->SetComment(aString); + mpDocSh->GetUndoManager()->AddUndoAction(std::move(pAction)); + pInfo->meClickAction = eClickAction; + pInfo->SetBookmark( aBookmark ); + mrDoc.SetChanged(); + + nRet = nDropAction; + } + } + else if( auto pDrawViewShell = dynamic_cast< DrawViewShell *>( mpViewSh ) ) + { + // insert as normal URL button + pDrawViewShell->InsertURLButton( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), OUString(), &aPos ); + nRet = nDropAction; + } + } + } + } + } + } + + return nRet; +} + +IMPL_LINK( View, ExecuteNavigatorDrop, void*, p, void ) +{ + SdNavigatorDropEvent* pSdNavigatorDropEvent = static_cast<SdNavigatorDropEvent*>(p); + TransferableDataHelper aDataHelper( pSdNavigatorDropEvent->maDropEvent.Transferable ); + SdPageObjsTLV::SdPageObjsTransferable* pPageObjsTransferable = SdPageObjsTLV::SdPageObjsTransferable::getImplementation( aDataHelper.GetXTransferable() ); + INetBookmark aINetBookmark; + + if( pPageObjsTransferable && aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) + { + Point aPos; + OUString aBookmark; + SdPage* pPage = static_cast<SdPage*>( GetSdrPageView()->GetPage() ); + sal_uInt16 nPgPos = 0xFFFF; + + if( pSdNavigatorDropEvent->mpTargetWindow ) + aPos = pSdNavigatorDropEvent->mpTargetWindow->PixelToLogic( pSdNavigatorDropEvent->maPosPixel ); + + const OUString& aURL( aINetBookmark.GetURL() ); + sal_Int32 nIndex = aURL.indexOf( '#' ); + if( nIndex != -1 ) + aBookmark = aURL.copy( nIndex+1 ); + + std::vector<OUString> aExchangeList; + std::vector<OUString> aBookmarkList(1,aBookmark); + + if( !pPage->IsMasterPage() ) + { + if( pPage->GetPageKind() == PageKind::Standard ) + nPgPos = pPage->GetPageNum() + 2; + else if( pPage->GetPageKind() == PageKind::Notes ) + nPgPos = pPage->GetPageNum() + 1; + } + + /* In order t ensure unique page names, we test the ones we want to + insert. If necessary. we put them into and replacement list (bNameOK + == sal_False -> User canceled). */ + bool bLink = pPageObjsTransferable->GetDragType() == NAVIGATOR_DRAGTYPE_LINK; + bool bNameOK = GetExchangeList( aExchangeList, aBookmarkList, 2 ); + + /* Since we don't know the type (page or object), we fill a list with + pages and objects. + Of course we have problems if there are pages and objects with the + same name!!! */ + if( bNameOK ) + { + mrDoc.InsertBookmark( aBookmarkList, aExchangeList, + bLink, nPgPos, + &pPageObjsTransferable->GetDocShell(), + &aPos ); + } + } + + delete pSdNavigatorDropEvent; +} + +bool View::GetExchangeList (std::vector<OUString> &rExchangeList, + std::vector<OUString> &rBookmarkList, + const sal_uInt16 nType) +{ + assert(rExchangeList.empty()); + + bool bListIdentical = true; ///< Bookmark list and exchange list are identical + bool bNameOK = true; ///< name is unique + + for ( const auto& rBookmark : rBookmarkList ) + { + OUString aNewName = rBookmark; + + if( nType == 0 || nType == 2 ) + bNameOK = mpDocSh->CheckPageName(mpViewSh->GetFrameWeld(), aNewName); + + if( bNameOK && ( nType == 1 || nType == 2 ) ) + { + if( mrDoc.GetObj( aNewName ) ) + { + OUString aTitle(SdResId(STR_TITLE_NAMEGROUP)); + OUString aDesc(SdResId(STR_DESC_NAMEGROUP)); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(mpViewSh->GetFrameWeld(), aNewName, aDesc)); + + pDlg->SetEditHelpId( HID_SD_NAMEDIALOG_OBJECT ); + + bNameOK = false; + pDlg->SetText( aTitle ); + + while( !bNameOK && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aNewName ); + + if( !mrDoc.GetObj( aNewName ) ) + bNameOK = true; + } + } + } + + bListIdentical = rBookmark == aNewName; + + rExchangeList.push_back(aNewName); + + if (!bNameOK) + break; + } + + // Exchange list is identical to bookmark list + if( !rExchangeList.empty() && bListIdentical ) + rExchangeList.clear(); + + return bNameOK; +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |