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 .
21 #include <unotools/localfilehelper.hxx>
22 #include <sfx2/bindings.hxx>
23 #include <sfx2/request.hxx>
24 #include <sfx2/docfilt.hxx>
25 #include <sfx2/fcontnr.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <vcl/msgbox.hxx>
28 #include <svl/urlbmk.hxx>
29 #include <svx/svdpagv.hxx>
30 #include <svx/xfillit.hxx>
31 #include <svx/svdundo.hxx>
32 #include <svx/xoutbmp.hxx>
33 #include <svx/svdograf.hxx>
34 #include <svx/svdomedia.hxx>
35 #include <svx/svdoole2.hxx>
36 #include <sot/storage.hxx>
37 #include <sfx2/app.hxx>
38 #include <avmedia/mediawindow.hxx>
39 #include <avmedia/modeltools.hxx>
40 #include <svtools/ehdl.hxx>
41 #include <svtools/sfxecode.hxx>
42 #include <svtools/embedhlp.hxx>
43 #include <vcl/graphicfilter.hxx>
46 #include "DrawDocShell.hxx"
47 #include "DrawViewShell.hxx"
48 #include "fuinsfil.hxx"
49 #include "drawdoc.hxx"
50 #include "sdresid.hxx"
51 #include "strings.hrc"
52 #include "imapinfo.hxx"
54 #include "view/SlideSorterView.hxx"
55 #include "undo/undoobjects.hxx"
56 #include <comphelper/processfactory.hxx>
57 #include <com/sun/star/embed/ElementModes.hpp>
58 #include <com/sun/star/embed/XEmbedPersist.hpp>
59 #include <com/sun/star/embed/Aspects.hpp>
60 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
61 #include <svtools/soerr.hxx>
62 #include <sfx2/ipclient.hxx>
63 #include <svx/svdoashp.hxx>
66 #include <config_features.h>
68 using namespace com::sun::star
;
73 * If an empty graphic object is provided, we fill it. Otherwise we fill an
74 * existing object at the specified position. If there is no object at the
75 * position, we create a new object and return a pointer to it.
77 SdrGrafObj
* View::InsertGraphic( const Graphic
& rGraphic
, sal_Int8
& rAction
,
78 const Point
& rPos
, SdrObject
* pObj
, ImageMap
* pImageMap
)
83 // Is there a object at the position rPos?
84 SdrGrafObj
* pNewGrafObj
= NULL
;
85 SdrPageView
* pPV
= GetSdrPageView();
86 SdrObject
* pPickObj
= pObj
;
87 const bool bOnMaster
= pPV
&& pPV
->GetPage() && pPV
->GetPage()->IsMasterPage();
89 if(pPV
&& this->ISA(::sd::slidesorter::view::SlideSorterView
))
91 if(!pPV
->GetPageRect().IsInside(rPos
))
95 if( !pPickObj
&& pPV
)
97 SdrPageView
* pPageView
= pPV
;
98 PickObj(rPos
, getHitTolLog(), pPickObj
, pPageView
);
101 const bool bIsGraphic(0 != dynamic_cast< SdrGrafObj
* >(pPickObj
));
103 if (DND_ACTION_LINK
== mnAction
106 && (bIsGraphic
|| (pPickObj
->IsEmptyPresObj() && !bOnMaster
))) // #121603# Do not use pObj, it may be NULL
108 // hit on SdrGrafObj with wanted new linked graphic (or PresObj placeholder hit)
109 if( IsUndoEnabled() )
110 BegUndo(OUString(SdResId(STR_INSERTGRAPHIC
)));
112 SdPage
* pPage
= static_cast<SdPage
*>( pPickObj
->GetPage() );
116 // We fill the object with the Bitmap
117 pNewGrafObj
= static_cast<SdrGrafObj
*>( pPickObj
->Clone() );
118 pNewGrafObj
->SetGraphic(rGraphic
);
122 pNewGrafObj
= new SdrGrafObj( rGraphic
, pPickObj
->GetLogicRect() );
123 pNewGrafObj
->SetEmptyPresObj(true);
126 if ( pNewGrafObj
->IsEmptyPresObj() )
128 Rectangle
aRect( pNewGrafObj
->GetLogicRect() );
129 pNewGrafObj
->AdjustToMaxRect( aRect
, false );
130 pNewGrafObj
->SetOutlinerParaObject(NULL
);
131 pNewGrafObj
->SetEmptyPresObj(false);
134 if (pPage
&& pPage
->IsPresObj(pPickObj
))
136 // Insert new PresObj into the list
137 pPage
->InsertPresObj( pNewGrafObj
, PRESOBJ_GRAPHIC
);
138 pNewGrafObj
->SetUserCall(pPickObj
->GetUserCall());
142 pNewGrafObj
->AppendUserData(new SdIMapInfo(*pImageMap
));
144 ReplaceObjectAtView(pPickObj
, *pPV
, pNewGrafObj
); // maybe ReplaceObjectAtView
146 if( IsUndoEnabled() )
149 else if (DND_ACTION_LINK
== mnAction
152 && pPickObj
->IsClosedObj()
153 && !dynamic_cast< SdrOle2Obj
* >(pPickObj
))
155 // fill style change (fill object with graphic), independent of mnAction
156 // and thus of DND_ACTION_LINK or DND_ACTION_MOVE
157 if( IsUndoEnabled() )
159 BegUndo(OUString(SdResId(STR_UNDO_DRAGDROP
)));
160 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pPickObj
));
164 SfxItemSet
aSet(mpDocSh
->GetPool(), XATTR_FILLSTYLE
, XATTR_FILLBITMAP
);
166 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
167 aSet
.Put(XFillBitmapItem(&mpDocSh
->GetPool(), rGraphic
));
168 pPickObj
->SetMergedItemSetAndBroadcast(aSet
);
176 if ( rGraphic
.GetPrefMapMode().GetMapUnit() == MAP_PIXEL
)
178 ::OutputDevice
* pOutDev
= 0;
180 pOutDev
= mpViewSh
->GetActiveWindow();
183 pOutDev
= Application::GetDefaultDevice();
186 aSize
= pOutDev
->PixelToLogic( rGraphic
.GetPrefSize(), MAP_100TH_MM
);
190 aSize
= OutputDevice::LogicToLogic( rGraphic
.GetPrefSize(),
191 rGraphic
.GetPrefMapMode(),
192 MapMode( MAP_100TH_MM
) );
195 pNewGrafObj
= new SdrGrafObj( rGraphic
, Rectangle( rPos
, aSize
) );
196 SdrPage
* pPage
= pPV
->GetPage();
197 Size
aPageSize( pPage
->GetSize() );
198 aPageSize
.Width() -= pPage
->GetLftBorder() + pPage
->GetRgtBorder();
199 aPageSize
.Height() -= pPage
->GetUppBorder() + pPage
->GetLwrBorder();
200 pNewGrafObj
->AdjustToMaxRect( Rectangle( Point(), aPageSize
), true );
202 SdrInsertFlags nOptions
= SdrInsertFlags::SETDEFLAYER
;
203 bool bIsPresTarget
= false;
206 && mpViewSh
->GetViewShell()!=NULL
207 && mpViewSh
->GetViewShell()->GetIPClient()
208 && mpViewSh
->GetViewShell()->GetIPClient()->IsObjectInPlaceActive())
209 || this->ISA(::sd::slidesorter::view::SlideSorterView
))
210 nOptions
|= SdrInsertFlags::DONTMARK
;
212 if( ( mnAction
& DND_ACTION_MOVE
) && pPickObj
&& (pPickObj
->IsEmptyPresObj() || pPickObj
->GetUserCall()) )
214 SdPage
* pP
= static_cast< SdPage
* >( pPickObj
->GetPage() );
216 if ( pP
&& pP
->IsMasterPage() )
217 bIsPresTarget
= pP
->IsPresObj(pPickObj
);
220 if( ( mnAction
& DND_ACTION_MOVE
) && pPickObj
&& !bIsPresTarget
)
224 pNewGrafObj
->AppendUserData(new SdIMapInfo(*pImageMap
));
226 Rectangle
aPickObjRect(pPickObj
->GetCurrentBoundRect());
227 Size
aPickObjSize(aPickObjRect
.GetSize());
228 Rectangle
aObjRect(pNewGrafObj
->GetCurrentBoundRect());
229 Size
aObjSize(aObjRect
.GetSize());
231 Fraction
aScaleWidth(aPickObjSize
.Width(), aObjSize
.Width());
232 Fraction
aScaleHeight(aPickObjSize
.Height(), aObjSize
.Height());
233 pNewGrafObj
->NbcResize(aObjRect
.TopLeft(), aScaleWidth
, aScaleHeight
);
235 Point aVec
= aPickObjRect
.TopLeft() - aObjRect
.TopLeft();
236 pNewGrafObj
->NbcMove(Size(aVec
.X(), aVec
.Y()));
238 const bool bUndo
= IsUndoEnabled();
241 BegUndo(SD_RESSTR(STR_UNDO_DRAGDROP
));
242 pNewGrafObj
->NbcSetLayer(pPickObj
->GetLayer());
243 SdrPage
* pP
= pPV
->GetPage();
244 pP
->InsertObject(pNewGrafObj
);
247 AddUndo(mrDoc
.GetSdrUndoFactory().CreateUndoNewObject(*pNewGrafObj
));
248 AddUndo(mrDoc
.GetSdrUndoFactory().CreateUndoDeleteObject(*pPickObj
));
250 pP
->RemoveObject(pPickObj
->GetOrdNum());
258 SdrObject::Free(pPickObj
);
260 mnAction
= DND_ACTION_COPY
;
264 InsertObjectAtView(pNewGrafObj
, *pPV
, nOptions
);
267 pNewGrafObj
->AppendUserData(new SdIMapInfo(*pImageMap
));
276 SdrMediaObj
* View::InsertMediaURL( const OUString
& rMediaURL
, sal_Int8
& rAction
,
277 const Point
& rPos
, const Size
& rSize
,
287 uno::Reference
<frame::XModel
> const xModel(
288 GetDoc().GetObjectShell()->GetModel());
289 bool const bRet
= ::avmedia::EmbedMedia(xModel
, rMediaURL
, realURL
);
290 if (!bRet
) { return 0; }
293 return InsertMediaObj( realURL
, "application/vnd.sun.star.media", rAction
, rPos
, rSize
);
296 #if HAVE_FEATURE_GLTF
297 SdrMediaObj
* View::Insert3DModelURL(
298 const OUString
& rModelURL
, sal_Int8
& rAction
,
299 const Point
& rPos
, const Size
& rSize
,
305 sRealURL
= rModelURL
;
309 uno::Reference
<frame::XModel
> const xModel(
310 GetDoc().GetObjectShell()->GetModel());
311 bool const bRet
= ::avmedia::Embed3DModel(xModel
, rModelURL
, sRealURL
);
312 if (!bRet
) { return 0; }
315 SdrMediaObj
* pRetObject
= InsertMediaObj( sRealURL
, "model/vnd.gltf+json", rAction
, rPos
, rSize
);
316 avmedia::MediaItem aItem
= pRetObject
->getMediaProperties();
318 pRetObject
->setMediaProperties(aItem
);
323 SdrMediaObj
* View::InsertMediaObj( const OUString
& rMediaURL
, const OUString
& rMimeType
, sal_Int8
& rAction
,
324 const Point
& rPos
, const Size
& rSize
)
329 SdrMediaObj
* pNewMediaObj
= NULL
;
330 SdrPageView
* pPV
= GetSdrPageView();
331 SdrObject
* pPickObj
= GetEmptyPresentationObject( PRESOBJ_MEDIA
);
333 if(pPV
&& this->ISA(::sd::slidesorter::view::SlideSorterView
))
335 if(!pPV
->GetPageRect().IsInside(rPos
))
339 if( !pPickObj
&& pPV
)
341 SdrPageView
* pPageView
= pPV
;
342 PickObj(rPos
, getHitTolLog(), pPickObj
, pPageView
);
345 if( mnAction
== DND_ACTION_LINK
&& pPickObj
&& pPV
&& pPickObj
->ISA( SdrMediaObj
) )
347 pNewMediaObj
= static_cast< SdrMediaObj
* >( pPickObj
->Clone() );
348 pNewMediaObj
->setURL( rMediaURL
, ""/*TODO?*/, rMimeType
);
350 BegUndo(SD_RESSTR(STR_UNDO_DRAGDROP
));
351 ReplaceObjectAtView(pPickObj
, *pPV
, pNewMediaObj
);
356 Rectangle
aRect( rPos
, rSize
);
358 aRect
= pPickObj
->GetLogicRect();
360 pNewMediaObj
= new SdrMediaObj( aRect
);
362 bool bIsPres
= false;
365 SdPage
* pPage
= static_cast< SdPage
* >(pPickObj
->GetPage());
366 bIsPres
= pPage
&& pPage
->IsPresObj(pPickObj
);
369 pPage
->InsertPresObj( pNewMediaObj
, PRESOBJ_MEDIA
);
374 ReplaceObjectAtView(pPickObj
, *pPV
, pNewMediaObj
);
376 InsertObjectAtView( pNewMediaObj
, *pPV
, SdrInsertFlags::SETDEFLAYER
);
379 DrawDocShell
* sh
= GetDocSh();
380 if (sh
!= 0 && sh
->HasName()) {
381 referer
= sh
->GetMedium()->GetName();
383 pNewMediaObj
->setURL( rMediaURL
, referer
, rMimeType
);
387 pNewMediaObj
->AdjustToMaxRect( pPickObj
->GetLogicRect() );
389 pNewMediaObj
->SetUserCall(pPickObj
->GetUserCall());
399 * Timer handler for InsertFile at Drop()
401 IMPL_LINK_NOARG_TYPED(View
, DropInsertFileHdl
, Idle
*, void)
403 DBG_ASSERT( mpViewSh
, "sd::View::DropInsertFileHdl(), I need a view shell to work!" );
407 SfxErrorContext
aEc( ERRCTX_ERROR
, mpViewSh
->GetActiveWindow(), RID_SO_ERRCTX
);
410 ::std::vector
< OUString
>::const_iterator
aIter( maDropFileVector
.begin() );
412 while( (aIter
!= maDropFileVector
.end()) && !nError
)
414 OUString
aCurrentDropFile( *aIter
);
415 INetURLObject
aURL( aCurrentDropFile
);
418 if( aURL
.GetProtocol() == INetProtocol::NotValid
)
421 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aCurrentDropFile
, aURLStr
);
422 aURL
= INetURLObject( aURLStr
);
425 GraphicFilter
& rGraphicFilter
= GraphicFilter::GetGraphicFilter();
428 aCurrentDropFile
= aURL
.GetMainURL( INetURLObject::NO_DECODE
);
430 if( !::avmedia::MediaWindow::isMediaURL( aCurrentDropFile
, ""/*TODO?*/ ) )
432 if( !rGraphicFilter
.ImportGraphic( aGraphic
, aURL
) )
434 sal_Int8 nTempAction
= ( aIter
== maDropFileVector
.begin() ) ? mnAction
: 0;
435 const bool bLink
= ( ( nTempAction
& DND_ACTION_LINK
) != 0 );
436 SdrGrafObj
* pGrafObj
= InsertGraphic( aGraphic
, nTempAction
, maDropPos
, NULL
, NULL
);
437 if(pGrafObj
&& bLink
)
439 pGrafObj
->SetGraphicLink( aCurrentDropFile
, ""/*TODO?*/, OUString() );
442 // return action from first inserted graphic
443 if( aIter
== maDropFileVector
.begin() )
444 mnAction
= nTempAction
;
450 const SfxFilter
* pFoundFilter
= NULL
;
451 SfxMedium
aSfxMedium( aCurrentDropFile
, StreamMode::READ
| StreamMode::SHARE_DENYNONE
);
452 ErrCode nErr
= SfxGetpApp()->GetFilterMatcher().GuessFilter( aSfxMedium
, &pFoundFilter
, SfxFilterFlags::IMPORT
, SFX_FILTER_NOTINSTALLED
| SfxFilterFlags::EXECUTABLE
);
454 if( pFoundFilter
&& !nErr
)
456 ::std::vector
< OUString
> aFilterVector
;
457 OUString aFilterName
= pFoundFilter
->GetFilterName();
458 OUString aLowerAsciiFileName
= aCurrentDropFile
.toAsciiLowerCase();
460 FuInsertFile::GetSupportedFilterVector( aFilterVector
);
462 if( ( ::std::find( aFilterVector
.begin(), aFilterVector
.end(), pFoundFilter
->GetMimeType() ) != aFilterVector
.end() ) ||
463 aFilterName
.indexOf( "Text" ) != -1 ||
464 aFilterName
.indexOf( "Rich" ) != -1 ||
465 aFilterName
.indexOf( "RTF" ) != -1 ||
466 aFilterName
.indexOf( "HTML" ) != -1 ||
467 aLowerAsciiFileName
.indexOf(".sdd") != -1 ||
468 aLowerAsciiFileName
.indexOf(".sda") != -1 ||
469 aLowerAsciiFileName
.indexOf(".sxd") != -1 ||
470 aLowerAsciiFileName
.indexOf(".sxi") != -1 ||
471 aLowerAsciiFileName
.indexOf(".std") != -1 ||
472 aLowerAsciiFileName
.indexOf(".sti") != -1 )
474 ::sd::Window
* pWin
= mpViewSh
->GetActiveWindow();
475 SfxRequest
aReq(SID_INSERTFILE
, ::SfxCallMode::SLOT
, mrDoc
.GetItemPool());
476 SfxStringItem
aItem1( ID_VAL_DUMMY0
, aCurrentDropFile
), aItem2( ID_VAL_DUMMY1
, pFoundFilter
->GetFilterName() );
478 aReq
.AppendItem( aItem1
);
479 aReq
.AppendItem( aItem2
);
480 FuInsertFile::Create( mpViewSh
, pWin
, this, &mrDoc
, aReq
);
491 if( ::avmedia::MediaWindow::isMediaURL( aCurrentDropFile
, ""/*TODO?*/ ) &&
492 ::avmedia::MediaWindow::isMediaURL( aCurrentDropFile
, ""/*TODO?*/, true, &aPrefSize
) )
494 if( aPrefSize
.Width() && aPrefSize
.Height() )
496 ::sd::Window
* pWin
= mpViewSh
->GetActiveWindow();
499 aPrefSize
= pWin
->PixelToLogic( aPrefSize
, MAP_100TH_MM
);
501 aPrefSize
= Application::GetDefaultDevice()->PixelToLogic( aPrefSize
, MAP_100TH_MM
);
504 aPrefSize
= Size( 5000, 5000 );
506 InsertMediaURL( aCurrentDropFile
, mnAction
, maDropPos
, aPrefSize
, true ) ;
508 else if( mnAction
& DND_ACTION_LINK
)
509 static_cast< DrawViewShell
* >( mpViewSh
)->InsertURLButton( aCurrentDropFile
, aCurrentDropFile
, OUString(), &maDropPos
);
518 uno::Sequence
< beans::PropertyValue
> aMedium(1);
519 aMedium
[0].Name
= "URL" ;
520 aMedium
[0].Value
<<= aCurrentDropFile
;
522 uno::Reference
< embed::XEmbeddedObject
> xObj
= mpDocSh
->GetEmbeddedObjectContainer().
523 InsertEmbeddedObject( aMedium
, aName
);
525 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
528 // TODO/LEAN: VisualArea access can switch the object to running state
529 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
;
531 xPersist
->storeOwn();
536 aSz
= xObj
->getVisualAreaSize( nAspect
);
538 catch( embed::NoVisualAreaSizeException
& )
540 // the default size will be set later
543 Size
aSize( aSz
.Width
, aSz
.Height
);
546 if (!aSize
.Width() || !aSize
.Height())
548 aSize
.Width() = 1410;
549 aSize
.Height() = 1000;
552 aRect
= Rectangle( maDropPos
, aSize
);
554 SdrOle2Obj
* pOleObj
= new SdrOle2Obj( svt::EmbeddedObjectRef( xObj
, nAspect
), aName
, aRect
);
555 SdrInsertFlags nOptions
= SdrInsertFlags::SETDEFLAYER
;
557 if (mpViewSh
!= NULL
)
559 OSL_ASSERT (mpViewSh
->GetViewShell()!=NULL
);
560 SfxInPlaceClient
* pIpClient
=
561 mpViewSh
->GetViewShell()->GetIPClient();
562 if (pIpClient
!=NULL
&& pIpClient
->IsObjectInPlaceActive())
563 nOptions
|= SdrInsertFlags::DONTMARK
;
566 InsertObjectAtView( pOleObj
, *GetSdrPageView(), nOptions
);
567 pOleObj
->SetLogicRect( aRect
);
568 aSz
.Width
= aRect
.GetWidth();
569 aSz
.Height
= aRect
.GetHeight();
570 xObj
->setVisualAreaSize( nAspect
,aSz
);
573 catch( uno::Exception
& )
575 nError
= ERRCODE_IO_GENERAL
;
576 // TODO/LATER: better error handling
586 ErrorHandler::HandleError( nError
);
590 * Timer handler for Errorhandling at Drop()
592 IMPL_LINK_NOARG_TYPED(View
, DropErrorHdl
, Idle
*, void)
594 ScopedVclPtr
<InfoBox
>::Create( mpViewSh
? mpViewSh
->GetActiveWindow() : 0, SD_RESSTR(STR_ACTION_NOTPOSSIBLE
) )->Execute();
598 * @returns StyleSheet from selection
600 SfxStyleSheet
* View::GetStyleSheet() const
602 return SdrView::GetStyleSheet();
605 } // end of namespace sd
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */