1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
23 #include <osl/file.hxx>
24 #include <editeng/outlobj.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/request.hxx>
27 #include <sfx2/docfilt.hxx>
28 #include <sfx2/fcontnr.hxx>
29 #include <sfx2/docfile.hxx>
30 #include <sfx2/sfxsids.hrc>
31 #include <vcl/svapp.hxx>
32 #include <vcl/weld.hxx>
33 #include <svx/svdpagv.hxx>
34 #include <svx/xbtmpit.hxx>
35 #include <svx/svdundo.hxx>
36 #include <svx/xfillit0.hxx>
37 #include <svx/svdograf.hxx>
38 #include <svx/svdomedia.hxx>
39 #include <svx/svdoole2.hxx>
40 #include <svx/ImageMapInfo.hxx>
41 #include <sfx2/app.hxx>
42 #include <avmedia/mediawindow.hxx>
43 #include <svtools/ehdl.hxx>
44 #include <svtools/sfxecode.hxx>
45 #include <svtools/embedhlp.hxx>
46 #include <vcl/graphicfilter.hxx>
49 #include <DrawDocShell.hxx>
50 #include <DrawViewShell.hxx>
51 #include <fuinsfil.hxx>
52 #include <drawdoc.hxx>
53 #include <sdresid.hxx>
54 #include <strings.hrc>
56 #include <view/SlideSorterView.hxx>
57 #include <com/sun/star/embed/XEmbedPersist.hpp>
58 #include <com/sun/star/embed/Aspects.hpp>
59 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
60 #include <com/sun/star/embed/XEmbeddedObject.hpp>
61 #include <svtools/soerr.hxx>
62 #include <sfx2/ipclient.hxx>
63 #include <tools/debug.hxx>
64 #include <tools/UnitConversion.hxx>
66 using namespace com::sun::star
;
71 * If an empty graphic object is provided, we fill it. Otherwise we fill an
72 * existing object at the specified position. If there is no object at the
73 * position, we create a new object and return a pointer to it.
75 SdrGrafObj
* View::InsertGraphic( const Graphic
& rGraphic
, sal_Int8
& rAction
,
76 const Point
& rPos
, SdrObject
* pObj
, ImageMap
const * pImageMap
)
81 // Is there an object at the position rPos?
82 SdrGrafObj
* pNewGrafObj
= nullptr;
83 SdrPageView
* pPV
= GetSdrPageView();
84 SdrObject
* pPickObj
= pObj
;
85 const bool bOnMaster
= pPV
&& pPV
->GetPage() && pPV
->GetPage()->IsMasterPage();
87 if(pPV
&& dynamic_cast< const ::sd::slidesorter::view::SlideSorterView
* >(this) != nullptr)
89 if(!pPV
->GetPageRect().IsInside(rPos
))
93 if( !pPickObj
&& pPV
)
95 SdrPageView
* pPageView
= pPV
;
96 pPickObj
= PickObj(rPos
, getHitTolLog(), pPageView
);
99 const bool bIsGraphic(dynamic_cast< const SdrGrafObj
* >(pPickObj
) != nullptr);
101 if (DND_ACTION_LINK
== mnAction
104 && (bIsGraphic
|| (pPickObj
->IsEmptyPresObj() && !bOnMaster
))) // #121603# Do not use pObj, it may be NULL
106 // hit on SdrGrafObj with wanted new linked graphic (or PresObj placeholder hit)
107 if( IsUndoEnabled() )
108 BegUndo(SdResId(STR_INSERTGRAPHIC
));
110 SdPage
* pPage
= static_cast<SdPage
*>( pPickObj
->getSdrPageFromSdrObject() );
114 // We fill the object with the Bitmap
115 pNewGrafObj
= static_cast<SdrGrafObj
*>( pPickObj
->CloneSdrObject(pPickObj
->getSdrModelFromSdrObject()) );
116 pNewGrafObj
->SetGraphic(rGraphic
);
120 pNewGrafObj
= new SdrGrafObj(
121 getSdrModelFromSdrView(),
123 pPickObj
->GetLogicRect());
124 pNewGrafObj
->SetEmptyPresObj(true);
127 if ( pNewGrafObj
->IsEmptyPresObj() )
129 ::tools::Rectangle
aRect( pNewGrafObj
->GetLogicRect() );
130 pNewGrafObj
->AdjustToMaxRect( aRect
);
131 pNewGrafObj
->SetOutlinerParaObject(nullptr);
132 pNewGrafObj
->SetEmptyPresObj(false);
135 if (pPage
&& pPage
->IsPresObj(pPickObj
))
137 // Insert new PresObj into the list
138 pPage
->InsertPresObj( pNewGrafObj
, PresObjKind::Graphic
);
139 pNewGrafObj
->SetUserCall(pPickObj
->GetUserCall());
143 pNewGrafObj
->AppendUserData(std::unique_ptr
<SdrObjUserData
>(new SvxIMapInfo(*pImageMap
)));
145 ReplaceObjectAtView(pPickObj
, *pPV
, pNewGrafObj
); // maybe ReplaceObjectAtView
147 if( IsUndoEnabled() )
150 else if (DND_ACTION_LINK
== mnAction
153 && pPickObj
->IsClosedObj()
154 && !dynamic_cast< const SdrOle2Obj
* >(pPickObj
))
156 // fill style change (fill object with graphic), independent of mnAction
157 // and thus of DND_ACTION_LINK or DND_ACTION_MOVE
158 if( IsUndoEnabled() )
160 BegUndo(SdResId(STR_UNDO_DRAGDROP
));
161 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pPickObj
));
165 SfxItemSet
aSet(mpDocSh
->GetPool(), svl::Items
<XATTR_FILLSTYLE
, XATTR_FILLBITMAP
>{});
167 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
168 aSet
.Put(XFillBitmapItem(rGraphic
));
169 pPickObj
->SetMergedItemSetAndBroadcast(aSet
);
174 Size aSizePixel
= rGraphic
.GetSizePixel();
179 if ( rGraphic
.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
181 ::OutputDevice
* pOutDev
= nullptr;
183 pOutDev
= mpViewSh
->GetActiveWindow();
186 pOutDev
= Application::GetDefaultDevice();
189 aSize
= pOutDev
->PixelToLogic(rGraphic
.GetPrefSize(), MapMode(MapUnit::Map100thMM
));
193 aSize
= OutputDevice::LogicToLogic( rGraphic
.GetPrefSize(),
194 rGraphic
.GetPrefMapMode(),
195 MapMode( MapUnit::Map100thMM
) );
198 sal_Int32 nPreferredDPI
= mrDoc
.getImagePreferredDPI();
199 if (nPreferredDPI
> 0)
201 constexpr double fTwipsInAnInch
= 1444.0;
202 auto nWidth
= (aSizePixel
.Width() / double(nPreferredDPI
)) * fTwipsInAnInch
;
203 auto nHeight
= (aSizePixel
.Height() / double(nPreferredDPI
)) * fTwipsInAnInch
;
204 nWidth
= convertTwipToMm100(nWidth
);
205 nHeight
= convertTwipToMm100(nHeight
);
207 if (nWidth
> 0 && nHeight
> 0)
208 aSize
= Size(nWidth
, nHeight
);
211 pNewGrafObj
= new SdrGrafObj(getSdrModelFromSdrView(), rGraphic
, ::tools::Rectangle(rPos
, aSize
));
213 if (nPreferredDPI
> 0)
215 // move to the center of insertion point
216 pNewGrafObj
->NbcMove(Size(-aSize
.Width() / 2, -aSize
.Height() / 2));
220 SdrPage
* pPage
= pPV
->GetPage();
221 Size
aPageSize( pPage
->GetSize() );
222 aPageSize
.AdjustWidth( -(pPage
->GetLeftBorder() + pPage
->GetRightBorder()) );
223 aPageSize
.AdjustHeight( -(pPage
->GetUpperBorder() + pPage
->GetLowerBorder()) );
224 pNewGrafObj
->AdjustToMaxRect( ::tools::Rectangle( Point(), aPageSize
), true );
227 SdrInsertFlags nOptions
= SdrInsertFlags::SETDEFLAYER
;
228 bool bIsPresTarget
= false;
231 && mpViewSh
->GetViewShell()!=nullptr
232 && mpViewSh
->GetViewShell()->GetIPClient()
233 && mpViewSh
->GetViewShell()->GetIPClient()->IsObjectInPlaceActive())
234 || dynamic_cast<const ::sd::slidesorter::view::SlideSorterView
* >(this))
235 nOptions
|= SdrInsertFlags::DONTMARK
;
237 if( ( mnAction
& DND_ACTION_MOVE
) && pPickObj
&& (pPickObj
->IsEmptyPresObj() || pPickObj
->GetUserCall()) )
239 SdPage
* pP
= static_cast< SdPage
* >( pPickObj
->getSdrPageFromSdrObject() );
241 if ( pP
&& pP
->IsMasterPage() )
242 bIsPresTarget
= pP
->IsPresObj(pPickObj
);
245 if( ( mnAction
& DND_ACTION_MOVE
) && pPickObj
&& !bIsPresTarget
)
249 pNewGrafObj
->AppendUserData(std::unique_ptr
<SdrObjUserData
>(new SvxIMapInfo(*pImageMap
)));
251 ::tools::Rectangle
aPickObjRect(pPickObj
->GetCurrentBoundRect());
252 Size
aPickObjSize(aPickObjRect
.GetSize());
253 ::tools::Rectangle
aObjRect(pNewGrafObj
->GetCurrentBoundRect());
254 Size
aObjSize(aObjRect
.GetSize());
256 Fraction
aScaleWidth(aPickObjSize
.Width(), aObjSize
.Width());
257 Fraction
aScaleHeight(aPickObjSize
.Height(), aObjSize
.Height());
258 pNewGrafObj
->NbcResize(aObjRect
.TopLeft(), aScaleWidth
, aScaleHeight
);
260 Point aVec
= aPickObjRect
.TopLeft() - aObjRect
.TopLeft();
261 pNewGrafObj
->NbcMove(Size(aVec
.X(), aVec
.Y()));
263 const bool bUndo
= IsUndoEnabled();
266 BegUndo(SdResId(STR_UNDO_DRAGDROP
));
267 pNewGrafObj
->NbcSetLayer(pPickObj
->GetLayer());
268 SdrPage
* pP
= pPV
->GetPage();
269 pP
->InsertObject(pNewGrafObj
);
272 AddUndo(mrDoc
.GetSdrUndoFactory().CreateUndoNewObject(*pNewGrafObj
));
273 AddUndo(mrDoc
.GetSdrUndoFactory().CreateUndoDeleteObject(*pPickObj
));
275 pP
->RemoveObject(pPickObj
->GetOrdNum());
283 SdrObject::Free(pPickObj
);
285 mnAction
= DND_ACTION_COPY
;
289 bool bSuccess
= InsertObjectAtView(pNewGrafObj
, *pPV
, nOptions
);
291 pNewGrafObj
= nullptr;
293 pNewGrafObj
->AppendUserData(std::unique_ptr
<SdrObjUserData
>(new SvxIMapInfo(*pImageMap
)));
302 void View::InsertMediaURL( const OUString
& rMediaURL
, sal_Int8
& rAction
,
303 const Point
& rPos
, const Size
& rSize
,
313 uno::Reference
<frame::XModel
> const xModel(
314 GetDoc().GetObjectShell()->GetModel());
315 #if HAVE_FEATURE_AVMEDIA
316 bool const bRet
= ::avmedia::EmbedMedia(xModel
, rMediaURL
, realURL
);
317 if (!bRet
) { return; }
323 InsertMediaObj( realURL
, "application/vnd.sun.star.media", rAction
, rPos
, rSize
);
326 SdrMediaObj
* View::InsertMediaObj( const OUString
& rMediaURL
, const OUString
& rMimeType
, sal_Int8
& rAction
,
327 const Point
& rPos
, const Size
& rSize
)
332 SdrMediaObj
* pNewMediaObj
= nullptr;
333 SdrPageView
* pPV
= GetSdrPageView();
334 SdrObject
* pPickObj
= GetEmptyPresentationObject( PresObjKind::Media
);
336 if(pPV
&& dynamic_cast<const ::sd::slidesorter::view::SlideSorterView
* >(this) )
338 if(!pPV
->GetPageRect().IsInside(rPos
))
342 if( mnAction
== DND_ACTION_LINK
&& pPV
&& dynamic_cast< SdrMediaObj
*>( pPickObj
) )
344 pNewMediaObj
= static_cast< SdrMediaObj
* >( pPickObj
->CloneSdrObject(pPickObj
->getSdrModelFromSdrObject()) );
345 pNewMediaObj
->setURL( rMediaURL
, ""/*TODO?*/, rMimeType
);
347 BegUndo(SdResId(STR_UNDO_DRAGDROP
));
348 ReplaceObjectAtView(pPickObj
, *pPV
, pNewMediaObj
);
353 ::tools::Rectangle
aRect( rPos
, rSize
);
354 SdrObjUserCall
* pUserCall
= nullptr;
357 aRect
= pPickObj
->GetLogicRect();
358 pUserCall
= pPickObj
->GetUserCall(); // ReplaceObjectAtView can free pPickObj
361 pNewMediaObj
= new SdrMediaObj(
362 getSdrModelFromSdrView(),
365 bool bIsPres
= false;
368 SdPage
* pPage
= static_cast< SdPage
* >(pPickObj
->getSdrPageFromSdrObject());
369 bIsPres
= pPage
&& pPage
->IsPresObj(pPickObj
);
372 pPage
->InsertPresObj( pNewMediaObj
, PresObjKind::Media
);
377 ReplaceObjectAtView(pPickObj
, *pPV
, pNewMediaObj
);
380 if (!InsertObjectAtView(pNewMediaObj
, *pPV
, SdrInsertFlags::SETDEFLAYER
))
381 pNewMediaObj
= nullptr;
385 DrawDocShell
* sh
= GetDocSh();
386 if (sh
!= nullptr && sh
->HasName()) {
387 referer
= sh
->GetMedium()->GetName();
392 pNewMediaObj
->setURL( rMediaURL
, referer
, rMimeType
);
396 pNewMediaObj
->AdjustToMaxRect( aRect
);
398 pNewMediaObj
->SetUserCall( pUserCall
);
409 * Timer handler for InsertFile at Drop()
411 IMPL_LINK_NOARG(View
, DropInsertFileHdl
, Timer
*, void)
413 DBG_ASSERT( mpViewSh
, "sd::View::DropInsertFileHdl(), I need a view shell to work!" );
417 SfxErrorContext
aEc( ERRCTX_ERROR
, mpViewSh
->GetFrameWeld(), RID_SO_ERRCTX
);
418 ErrCode nError
= ERRCODE_NONE
;
420 ::std::vector
< OUString
>::const_iterator
aIter( maDropFileVector
.begin() );
422 while( (aIter
!= maDropFileVector
.end()) && !nError
)
424 OUString
aCurrentDropFile( *aIter
);
425 INetURLObject
aURL( aCurrentDropFile
);
428 if( aURL
.GetProtocol() == INetProtocol::NotValid
)
431 osl::FileBase::getFileURLFromSystemPath( aCurrentDropFile
, aURLStr
);
432 aURL
= INetURLObject( aURLStr
);
435 GraphicFilter
& rGraphicFilter
= GraphicFilter::GetGraphicFilter();
438 aCurrentDropFile
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
440 #if HAVE_FEATURE_AVMEDIA
441 if( !::avmedia::MediaWindow::isMediaURL( aCurrentDropFile
, ""/*TODO?*/ ) )
445 if( !rGraphicFilter
.ImportGraphic( aGraphic
, aURL
) )
447 sal_Int8 nTempAction
= ( aIter
== maDropFileVector
.begin() ) ? mnAction
: 0;
448 const bool bLink
= ( ( nTempAction
& DND_ACTION_LINK
) != 0 );
449 SdrGrafObj
* pGrafObj
= InsertGraphic( aGraphic
, nTempAction
, maDropPos
, nullptr, nullptr );
450 if(pGrafObj
&& bLink
)
452 pGrafObj
->SetGraphicLink( aCurrentDropFile
);
455 // return action from first inserted graphic
456 if( aIter
== maDropFileVector
.begin() )
457 mnAction
= nTempAction
;
463 std::shared_ptr
<const SfxFilter
> pFoundFilter
;
464 SfxMedium
aSfxMedium( aCurrentDropFile
, StreamMode::READ
| StreamMode::SHARE_DENYNONE
);
465 ErrCode nErr
= SfxGetpApp()->GetFilterMatcher().GuessFilter( aSfxMedium
, pFoundFilter
);
467 if( pFoundFilter
&& !nErr
)
469 ::std::vector
< OUString
> aFilterVector
;
470 OUString aFilterName
= pFoundFilter
->GetFilterName();
471 OUString aLowerAsciiFileName
= aCurrentDropFile
.toAsciiLowerCase();
473 FuInsertFile::GetSupportedFilterVector( aFilterVector
);
475 if( ( ::std::find( aFilterVector
.begin(), aFilterVector
.end(), pFoundFilter
->GetMimeType() ) != aFilterVector
.end() ) ||
476 aFilterName
.indexOf( "Text" ) != -1 ||
477 aFilterName
.indexOf( "Rich" ) != -1 ||
478 aFilterName
.indexOf( "RTF" ) != -1 ||
479 aFilterName
.indexOf( "HTML" ) != -1 ||
480 aLowerAsciiFileName
.indexOf(".sdd") != -1 ||
481 aLowerAsciiFileName
.indexOf(".sda") != -1 ||
482 aLowerAsciiFileName
.indexOf(".sxd") != -1 ||
483 aLowerAsciiFileName
.indexOf(".sxi") != -1 ||
484 aLowerAsciiFileName
.indexOf(".std") != -1 ||
485 aLowerAsciiFileName
.indexOf(".sti") != -1 )
487 ::sd::Window
* pWin
= mpViewSh
->GetActiveWindow();
488 SfxRequest
aReq(SID_INSERTFILE
, ::SfxCallMode::SLOT
, mrDoc
.GetItemPool());
489 SfxStringItem
aItem1( ID_VAL_DUMMY0
, aCurrentDropFile
), aItem2( ID_VAL_DUMMY1
, pFoundFilter
->GetFilterName() );
491 aReq
.AppendItem( aItem1
);
492 aReq
.AppendItem( aItem2
);
493 FuInsertFile::Create( mpViewSh
, pWin
, this, &mrDoc
, aReq
);
502 #if HAVE_FEATURE_AVMEDIA
505 if( ::avmedia::MediaWindow::isMediaURL( aCurrentDropFile
, ""/*TODO?*/ ) &&
506 ::avmedia::MediaWindow::isMediaURL( aCurrentDropFile
, ""/*TODO?*/, true, &aPrefSize
) )
508 if( aPrefSize
.Width() && aPrefSize
.Height() )
510 ::sd::Window
* pWin
= mpViewSh
->GetActiveWindow();
513 aPrefSize
= pWin
->PixelToLogic(aPrefSize
, MapMode(MapUnit::Map100thMM
));
515 aPrefSize
= Application::GetDefaultDevice()->PixelToLogic(aPrefSize
, MapMode(MapUnit::Map100thMM
));
518 aPrefSize
= Size( 5000, 5000 );
520 InsertMediaURL( aCurrentDropFile
, mnAction
, maDropPos
, aPrefSize
, true ) ;
524 if( mnAction
& DND_ACTION_LINK
)
525 static_cast< DrawViewShell
* >( mpViewSh
)->InsertURLButton( aCurrentDropFile
, aCurrentDropFile
, OUString(), &maDropPos
);
534 uno::Sequence
< beans::PropertyValue
> aMedium(1);
535 aMedium
[0].Name
= "URL" ;
536 aMedium
[0].Value
<<= aCurrentDropFile
;
538 uno::Reference
< embed::XEmbeddedObject
> xObj
= mpDocSh
->GetEmbeddedObjectContainer().
539 InsertEmbeddedObject( aMedium
, aName
);
541 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
544 // TODO/LEAN: VisualArea access can switch the object to running state
545 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
;
547 xPersist
->storeOwn();
552 aSz
= xObj
->getVisualAreaSize( nAspect
);
554 catch( embed::NoVisualAreaSizeException
& )
556 // the default size will be set later
559 Size
aSize( aSz
.Width
, aSz
.Height
);
560 ::tools::Rectangle aRect
;
562 if (!aSize
.Width() || !aSize
.Height())
564 aSize
.setWidth( 1410 );
565 aSize
.setHeight( 1000 );
568 aRect
= ::tools::Rectangle( maDropPos
, aSize
);
570 SdrOle2Obj
* pOleObj
= new SdrOle2Obj(
571 getSdrModelFromSdrView(),
572 svt::EmbeddedObjectRef(xObj
, nAspect
),
575 SdrInsertFlags nOptions
= SdrInsertFlags::SETDEFLAYER
;
577 if (mpViewSh
!= nullptr)
579 OSL_ASSERT (mpViewSh
->GetViewShell()!=nullptr);
580 SfxInPlaceClient
* pIpClient
=
581 mpViewSh
->GetViewShell()->GetIPClient();
582 if (pIpClient
!=nullptr && pIpClient
->IsObjectInPlaceActive())
583 nOptions
|= SdrInsertFlags::DONTMARK
;
586 if (InsertObjectAtView( pOleObj
, *GetSdrPageView(), nOptions
))
587 pOleObj
->SetLogicRect( aRect
);
588 aSz
.Width
= aRect
.GetWidth();
589 aSz
.Height
= aRect
.GetHeight();
590 xObj
->setVisualAreaSize( nAspect
,aSz
);
593 catch( uno::Exception
& )
595 nError
= ERRCODE_IO_GENERAL
;
596 // TODO/LATER: better error handling
606 ErrorHandler::HandleError( nError
);
610 * Timer handler for Errorhandling at Drop()
612 IMPL_LINK_NOARG(View
, DropErrorHdl
, Timer
*, void)
614 vcl::Window
* pWin
= mpViewSh
? mpViewSh
->GetActiveWindow() : nullptr;
615 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(pWin
? pWin
->GetFrameWeld() : nullptr,
616 VclMessageType::Info
, VclButtonsType::Ok
,
617 SdResId(STR_ACTION_NOTPOSSIBLE
)));
622 * @returns StyleSheet from selection
624 SfxStyleSheet
* View::GetStyleSheet() const
626 return SdrView::GetStyleSheet();
629 } // end of namespace sd
631 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */