1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: embedhlp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <svtools/embedhlp.hxx>
35 #include <svtools/filter.hxx>
36 #include <svtools/svtools.hrc>
37 #include <svtools/svtdata.hxx>
39 #include <comphelper/embeddedobjectcontainer.hxx>
40 #include <comphelper/seqstream.hxx>
41 #include <toolkit/helper/vclunohelper.hxx>
42 #include <unotools/ucbstreamhelper.hxx>
43 #include <unotools/streamwrap.hxx>
45 #include <tools/globname.hxx>
46 #include <sot/clsids.hxx>
47 #include <com/sun/star/util/XModifyListener.hpp>
48 #ifndef _COM_SUN_STAR_UTIL_XMODIFYiBLE_HPP_
49 #include <com/sun/star/util/XModifiable.hpp>
51 #include <com/sun/star/embed/EmbedStates.hpp>
52 #include <com/sun/star/embed/EmbedMisc.hpp>
53 #include <com/sun/star/embed/XStateChangeListener.hpp>
54 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
55 #include <com/sun/star/util/XModifiable.hpp>
56 #include <com/sun/star/datatransfer/XTransferable.hpp>
57 #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
58 #include <cppuhelper/implbase4.hxx>
59 #include "vcl/svapp.hxx"
60 #include <rtl/logfile.hxx>
62 using namespace com::sun::star
;
67 class EmbedEventListener_Impl
: public ::cppu::WeakImplHelper4
< embed::XStateChangeListener
,
68 document::XEventListener
,
69 util::XModifyListener
,
70 util::XCloseListener
>
73 EmbeddedObjectRef
* pObject
;
76 EmbedEventListener_Impl( EmbeddedObjectRef
* p
) :
81 static EmbedEventListener_Impl
* Create( EmbeddedObjectRef
* );
83 virtual void SAL_CALL
changingState( const lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
)
84 throw (embed::WrongStateException
, uno::RuntimeException
);
85 virtual void SAL_CALL
stateChanged( const lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
)
86 throw (uno::RuntimeException
);
87 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, ::sal_Bool GetsOwnership
)
88 throw (util::CloseVetoException
, uno::RuntimeException
);
89 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
90 virtual void SAL_CALL
notifyEvent( const document::EventObject
& aEvent
) throw( uno::RuntimeException
);
91 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) throw( uno::RuntimeException
);
92 virtual void SAL_CALL
modified( const ::com::sun::star::lang::EventObject
& aEvent
) throw (::com::sun::star::uno::RuntimeException
);
95 EmbedEventListener_Impl
* EmbedEventListener_Impl::Create( EmbeddedObjectRef
* p
)
97 EmbedEventListener_Impl
* xRet
= new EmbedEventListener_Impl( p
);
100 if ( p
->GetObject().is() )
102 p
->GetObject()->addStateChangeListener( xRet
);
104 uno::Reference
< util::XCloseable
> xClose( p
->GetObject(), uno::UNO_QUERY
);
105 DBG_ASSERT( xClose
.is(), "Object does not support XCloseable!" );
107 xClose
->addCloseListener( xRet
);
109 uno::Reference
< document::XEventBroadcaster
> xBrd( p
->GetObject(), uno::UNO_QUERY
);
111 xBrd
->addEventListener( xRet
);
113 xRet
->nState
= p
->GetObject()->getCurrentState();
114 if ( xRet
->nState
== embed::EmbedStates::RUNNING
)
116 uno::Reference
< util::XModifiable
> xMod( p
->GetObject()->getComponent(), uno::UNO_QUERY
);
118 // listen for changes in running state (update replacements in case of changes)
119 xMod
->addModifyListener( xRet
);
126 void SAL_CALL
EmbedEventListener_Impl::changingState( const lang::EventObject
&,
129 throw ( embed::WrongStateException
,
130 uno::RuntimeException
)
134 void SAL_CALL
EmbedEventListener_Impl::stateChanged( const lang::EventObject
&,
135 ::sal_Int32 nOldState
,
136 ::sal_Int32 nNewState
)
137 throw ( uno::RuntimeException
)
139 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
144 uno::Reference
< util::XModifiable
> xMod( pObject
->GetObject()->getComponent(), uno::UNO_QUERY
);
145 if ( nNewState
== embed::EmbedStates::RUNNING
)
147 // TODO/LATER: container must be set before!
148 // When is this event created? Who sets the new container when it changed?
149 if( ( pObject
->GetViewAspect() != embed::Aspects::MSOLE_ICON
) && nOldState
!= embed::EmbedStates::LOADED
&& !pObject
->IsChart() )
150 // get new replacement after deactivation
151 pObject
->UpdateReplacement();
153 if( pObject
->IsChart() && nOldState
== embed::EmbedStates::UI_ACTIVE
)
155 //create a new metafile replacement when leaving the edit mode
156 //for buggy documents where the old image looks different from the correct one
157 if( xMod
.is() && !xMod
->isModified() )//in case of modification a new replacement will be requested anyhow
158 pObject
->UpdateReplacementOnDemand();
161 if ( xMod
.is() && nOldState
== embed::EmbedStates::LOADED
)
162 // listen for changes (update replacements in case of changes)
163 xMod
->addModifyListener( this );
165 else if ( nNewState
== embed::EmbedStates::LOADED
)
167 // in loaded state we can't listen
169 xMod
->removeModifyListener( this );
173 void SAL_CALL
EmbedEventListener_Impl::modified( const lang::EventObject
& ) throw (uno::RuntimeException
)
175 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
176 if ( pObject
&& pObject
->GetViewAspect() != embed::Aspects::MSOLE_ICON
)
178 if ( nState
== embed::EmbedStates::RUNNING
)
180 // updates only necessary in non-active states
181 if( pObject
->IsChart() )
182 pObject
->UpdateReplacementOnDemand();
184 pObject
->UpdateReplacement();
186 else if ( nState
== embed::EmbedStates::ACTIVE
||
187 nState
== embed::EmbedStates::UI_ACTIVE
||
188 nState
== embed::EmbedStates::INPLACE_ACTIVE
)
190 // in case the object is inplace or UI active the replacement image should be updated on demand
191 pObject
->UpdateReplacementOnDemand();
197 void SAL_CALL
EmbedEventListener_Impl::notifyEvent( const document::EventObject
& aEvent
) throw( uno::RuntimeException
)
199 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
202 if ( pObject
&& aEvent
.EventName
.equalsAscii("OnSaveDone") || aEvent
.EventName
.equalsAscii("OnSaveAsDone") )
204 // TODO/LATER: container must be set before!
205 // When is this event created? Who sets the new container when it changed?
206 pObject
->UpdateReplacement();
210 if ( pObject
&& aEvent
.EventName
.equalsAscii("OnVisAreaChanged") && pObject
->GetViewAspect() != embed::Aspects::MSOLE_ICON
&& !pObject
->IsChart() )
212 pObject
->UpdateReplacement();
216 void SAL_CALL
EmbedEventListener_Impl::queryClosing( const lang::EventObject
& Source
, ::sal_Bool
)
217 throw ( util::CloseVetoException
, uno::RuntimeException
)
219 // An embedded object can be shared between several objects (f.e. for undo purposes)
220 // the object will not be closed before the last "customer" is destroyed
221 // Now the EmbeddedObjectRef helper class works like a "lock" on the object
222 if ( pObject
&& pObject
->IsLocked() && Source
.Source
== pObject
->GetObject() )
223 throw util::CloseVetoException();
226 void SAL_CALL
EmbedEventListener_Impl::notifyClosing( const lang::EventObject
& Source
) throw (::com::sun::star::uno::RuntimeException
)
228 if ( pObject
&& Source
.Source
== pObject
->GetObject() )
235 void SAL_CALL
EmbedEventListener_Impl::disposing( const lang::EventObject
& aEvent
) throw( uno::RuntimeException
)
237 if ( pObject
&& aEvent
.Source
== pObject
->GetObject() )
244 struct EmbeddedObjectRef_Impl
246 EmbedEventListener_Impl
* xListener
;
247 ::rtl::OUString aPersistName
;
248 ::rtl::OUString aMediaType
;
249 comphelper::EmbeddedObjectContainer
* pContainer
;
252 sal_Int64 nViewAspect
;
254 sal_Bool bNeedUpdate
;
255 awt::Size aDefaultSizeForChart_In_100TH_MM
;//#i103460# charts do not necessaryly have an own size within ODF files, in this case they need to use the size settings from the surrounding frame, which is made available with this member
258 void EmbeddedObjectRef::Construct_Impl()
260 mpImp
= new EmbeddedObjectRef_Impl
;
261 mpImp
->pContainer
= 0;
263 mpImp
->pHCGraphic
= 0;
264 mpImp
->nViewAspect
= embed::Aspects::MSOLE_CONTENT
;
265 mpImp
->bIsLocked
= FALSE
;
266 mpImp
->bNeedUpdate
= sal_False
;
267 mpImp
->aDefaultSizeForChart_In_100TH_MM
= awt::Size(8000,7000);
270 EmbeddedObjectRef::EmbeddedObjectRef()
275 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference
< NS_EMBED::XEmbeddedObject
>& xObj
, sal_Int64 nAspect
)
278 mpImp
->nViewAspect
= nAspect
;
280 mpImp
->xListener
= EmbedEventListener_Impl::Create( this );
283 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef
& rObj
)
285 mpImp
= new EmbeddedObjectRef_Impl
;
286 mpImp
->pContainer
= rObj
.mpImp
->pContainer
;
287 mpImp
->nViewAspect
= rObj
.mpImp
->nViewAspect
;
288 mpImp
->bIsLocked
= rObj
.mpImp
->bIsLocked
;
290 mpImp
->xListener
= EmbedEventListener_Impl::Create( this );
291 mpImp
->aPersistName
= rObj
.mpImp
->aPersistName
;
292 mpImp
->aMediaType
= rObj
.mpImp
->aMediaType
;
293 mpImp
->bNeedUpdate
= rObj
.mpImp
->bNeedUpdate
;
294 mpImp
->aDefaultSizeForChart_In_100TH_MM
= rObj
.mpImp
->aDefaultSizeForChart_In_100TH_MM
;
296 if ( rObj
.mpImp
->pGraphic
&& !rObj
.mpImp
->bNeedUpdate
)
297 mpImp
->pGraphic
= new Graphic( *rObj
.mpImp
->pGraphic
);
301 mpImp
->pHCGraphic
= 0;
304 EmbeddedObjectRef::~EmbeddedObjectRef()
306 delete mpImp
->pGraphic
;
307 if ( mpImp
->pHCGraphic
) DELETEZ( mpImp
->pHCGraphic
);
311 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj )
313 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
315 delete mpImp->pGraphic;
316 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
319 mpImp->nViewAspect = rObj.mpImp->nViewAspect;
320 mpImp->bIsLocked = rObj.mpImp->bIsLocked;
322 mpImp->xListener = EmbedEventListener_Impl::Create( this );
323 mpImp->pContainer = rObj.mpImp->pContainer;
324 mpImp->aPersistName = rObj.mpImp->aPersistName;
325 mpImp->aMediaType = rObj.mpImp->aMediaType;
326 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
328 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
329 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
335 void EmbeddedObjectRef::Assign( const NS_UNO::Reference
< NS_EMBED::XEmbeddedObject
>& xObj
, sal_Int64 nAspect
)
337 DBG_ASSERT( !mxObj
.is(), "Never assign an already assigned object!" );
340 mpImp
->nViewAspect
= nAspect
;
342 mpImp
->xListener
= EmbedEventListener_Impl::Create( this );
346 ::com::sun::star::uno::Reference
< ::com::sun::star::chart2::XDefaultSizeTransmitter
> xSizeTransmitter( xObj
, uno::UNO_QUERY
);
347 DBG_ASSERT( xSizeTransmitter
.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
348 if( xSizeTransmitter
.is() )
349 xSizeTransmitter
->setDefaultSize( mpImp
->aDefaultSizeForChart_In_100TH_MM
);
353 void EmbeddedObjectRef::Clear()
355 if ( mxObj
.is() && mpImp
->xListener
)
357 mxObj
->removeStateChangeListener( mpImp
->xListener
);
359 uno::Reference
< util::XCloseable
> xClose( mxObj
, uno::UNO_QUERY
);
361 xClose
->removeCloseListener( mpImp
->xListener
);
363 uno::Reference
< document::XEventBroadcaster
> xBrd( mxObj
, uno::UNO_QUERY
);
365 xBrd
->removeEventListener( mpImp
->xListener
);
367 if ( mpImp
->bIsLocked
)
373 mxObj
->changeState( embed::EmbedStates::LOADED
);
374 xClose
->close( sal_True
);
376 catch ( util::CloseVetoException
& )
378 // there's still someone who needs the object!
380 catch ( uno::Exception
& )
382 OSL_ENSURE( sal_False
, "Error on switching of the object to loaded state and closing!\n" );
387 if ( mpImp
->xListener
)
389 mpImp
->xListener
->pObject
= 0;
390 mpImp
->xListener
->release();
391 mpImp
->xListener
= 0;
395 mpImp
->bNeedUpdate
= sal_False
;
398 mpImp
->pContainer
= 0;
399 mpImp
->bIsLocked
= FALSE
;
400 mpImp
->bNeedUpdate
= sal_False
;
403 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer
* pContainer
, const ::rtl::OUString
& rPersistName
)
405 mpImp
->pContainer
= pContainer
;
406 mpImp
->aPersistName
= rPersistName
;
408 if ( mpImp
->pGraphic
&& !mpImp
->bNeedUpdate
&& pContainer
)
409 SetGraphicToContainer( *mpImp
->pGraphic
, *pContainer
, mpImp
->aPersistName
, ::rtl::OUString() );
412 comphelper::EmbeddedObjectContainer
* EmbeddedObjectRef::GetContainer() const
414 return mpImp
->pContainer
;
417 ::rtl::OUString
EmbeddedObjectRef::GetPersistName() const
419 return mpImp
->aPersistName
;
422 MapUnit
EmbeddedObjectRef::GetMapUnit() const
424 if ( mpImp
->nViewAspect
== embed::Aspects::MSOLE_CONTENT
)
425 return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj
->getMapUnit( mpImp
->nViewAspect
) );
427 // TODO/LATER: currently only CONTENT aspect requires communication with the object
431 sal_Int64
EmbeddedObjectRef::GetViewAspect() const
433 return mpImp
->nViewAspect
;
436 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect
)
438 mpImp
->nViewAspect
= nAspect
;
441 void EmbeddedObjectRef::Lock( BOOL bLock
)
443 mpImp
->bIsLocked
= bLock
;
446 BOOL
EmbeddedObjectRef::IsLocked() const
448 return mpImp
->bIsLocked
;
451 void EmbeddedObjectRef::GetReplacement( BOOL bUpdate
)
455 DELETEZ( mpImp
->pGraphic
);
456 mpImp
->aMediaType
= ::rtl::OUString();
457 mpImp
->pGraphic
= new Graphic
;
458 if ( mpImp
->pHCGraphic
) DELETEZ( mpImp
->pHCGraphic
);
460 else if ( !mpImp
->pGraphic
)
461 mpImp
->pGraphic
= new Graphic
;
464 DBG_ERROR("No update, but replacement exists already!");
468 SvStream
* pGraphicStream
= GetGraphicStream( bUpdate
);
469 if ( pGraphicStream
)
471 GraphicFilter
* pGF
= GraphicFilter::GetGraphicFilter();
472 if( mpImp
->pGraphic
)
473 pGF
->ImportGraphic( *mpImp
->pGraphic
, String(), *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
);
474 delete pGraphicStream
;
478 Graphic
* EmbeddedObjectRef::GetGraphic( ::rtl::OUString
* pMediaType
) const
480 if ( mpImp
->bNeedUpdate
)
481 // bNeedUpdate will be set to false while retrieving new replacement
482 const_cast < EmbeddedObjectRef
* >(this)->GetReplacement( sal_True
);
483 else if ( !mpImp
->pGraphic
)
484 const_cast < EmbeddedObjectRef
* >(this)->GetReplacement( FALSE
);
486 if ( mpImp
->pGraphic
&& pMediaType
)
487 *pMediaType
= mpImp
->aMediaType
;
488 return mpImp
->pGraphic
;
491 Size
EmbeddedObjectRef::GetSize( MapMode
* pTargetMapMode
) const
493 MapMode
aSourceMapMode( MAP_100TH_MM
);
496 if ( mpImp
->nViewAspect
== embed::Aspects::MSOLE_ICON
)
498 Graphic
* pGraphic
= GetGraphic();
501 aSourceMapMode
= pGraphic
->GetPrefMapMode();
502 aResult
= pGraphic
->GetPrefSize();
505 aResult
= Size( 2500, 2500 );
515 aSize
= mxObj
->getVisualAreaSize( mpImp
->nViewAspect
);
517 catch( embed::NoVisualAreaSizeException
& )
520 catch( uno::Exception
& )
522 OSL_ENSURE( sal_False
, "Something went wrong on getting of the size of the object!" );
527 aSourceMapMode
= VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj
->getMapUnit( mpImp
->nViewAspect
) );
529 catch( uno::Exception
)
531 OSL_ENSURE( sal_False
, "Can not get the map mode!" );
535 if ( !aSize
.Height
&& !aSize
.Width
)
541 aResult
= Size( aSize
.Width
, aSize
.Height
);
544 if ( pTargetMapMode
)
545 aResult
= OutputDevice::LogicToLogic( aResult
, aSourceMapMode
, *pTargetMapMode
);
550 Graphic
* EmbeddedObjectRef::GetHCGraphic() const
552 if ( !mpImp
->pHCGraphic
)
554 uno::Reference
< io::XInputStream
> xInStream
;
557 // if the object needs size on load, that means that it is not our object
558 // currently the HC mode is supported only for OOo own objects so the following
559 // check is used as an optimization
560 // TODO/LATER: shouldn't there be a special status flag to detect alien implementation?
561 if ( mpImp
->nViewAspect
== embed::Aspects::MSOLE_CONTENT
562 && mxObj
.is() && !( mxObj
->getStatus( mpImp
->nViewAspect
) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
) )
564 // TODO/LATER: optimization, it makes no sence to do it for OLE objects
565 if ( mxObj
->getCurrentState() == embed::EmbedStates::LOADED
)
566 mxObj
->changeState( embed::EmbedStates::RUNNING
);
568 // TODO: return for the aspect of the document
569 embed::VisualRepresentation aVisualRepresentation
;
570 uno::Reference
< datatransfer::XTransferable
> xTransferable( mxObj
->getComponent(), uno::UNO_QUERY
);
571 if ( !xTransferable
.is() )
572 throw uno::RuntimeException();
574 datatransfer::DataFlavor
aDataFlavor(
575 ::rtl::OUString::createFromAscii(
576 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
577 ::rtl::OUString::createFromAscii( "GDIMetaFile" ),
578 ::getCppuType( (const uno::Sequence
< sal_Int8
>*) NULL
) );
580 uno::Sequence
< sal_Int8
> aSeq
;
581 if ( ( xTransferable
->getTransferData( aDataFlavor
) >>= aSeq
) && aSeq
.getLength() )
582 xInStream
= new ::comphelper::SequenceInputStream( aSeq
);
585 catch ( uno::Exception
& )
589 if ( xInStream
.is() )
591 SvStream
* pStream
= NULL
;
592 pStream
= ::utl::UcbStreamHelper::CreateStream( xInStream
);
595 if ( !pStream
->GetError() )
597 GraphicFilter
* pGF
= GraphicFilter::GetGraphicFilter();
598 Graphic
* pGraphic
= new Graphic();
599 if ( pGF
->ImportGraphic( *pGraphic
, String(), *pStream
, GRFILTER_FORMAT_DONTKNOW
) == 0 )
600 mpImp
->pHCGraphic
= pGraphic
;
610 return mpImp
->pHCGraphic
;
613 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference
< io::XInputStream
>& xInGrStream
,
614 const ::rtl::OUString
& rMediaType
)
616 if ( mpImp
->pGraphic
)
617 delete mpImp
->pGraphic
;
618 mpImp
->pGraphic
= new Graphic();
619 mpImp
->aMediaType
= rMediaType
;
620 if ( mpImp
->pHCGraphic
) DELETEZ( mpImp
->pHCGraphic
);
622 SvStream
* pGraphicStream
= ::utl::UcbStreamHelper::CreateStream( xInGrStream
);
624 if ( pGraphicStream
)
626 GraphicFilter
* pGF
= GraphicFilter::GetGraphicFilter();
627 pGF
->ImportGraphic( *mpImp
->pGraphic
, String(), *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
);
629 if ( mpImp
->pContainer
)
631 pGraphicStream
->Seek( 0 );
632 uno::Reference
< io::XInputStream
> xInSeekGrStream
= new ::utl::OSeekableInputStreamWrapper( pGraphicStream
);
634 mpImp
->pContainer
->InsertGraphicStream( xInSeekGrStream
, mpImp
->aPersistName
, rMediaType
);
637 delete pGraphicStream
;
640 mpImp
->bNeedUpdate
= sal_False
;
644 void EmbeddedObjectRef::SetGraphic( const Graphic
& rGraphic
, const ::rtl::OUString
& rMediaType
)
646 if ( mpImp
->pGraphic
)
647 delete mpImp
->pGraphic
;
648 mpImp
->pGraphic
= new Graphic( rGraphic
);
649 mpImp
->aMediaType
= rMediaType
;
650 if ( mpImp
->pHCGraphic
) DELETEZ( mpImp
->pHCGraphic
);
652 if ( mpImp
->pContainer
)
653 SetGraphicToContainer( rGraphic
, *mpImp
->pContainer
, mpImp
->aPersistName
, rMediaType
);
655 mpImp
->bNeedUpdate
= sal_False
;
658 SvStream
* EmbeddedObjectRef::GetGraphicStream( BOOL bUpdate
) const
660 RTL_LOGFILE_CONTEXT( aLog
, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
661 DBG_ASSERT( bUpdate
|| mpImp
->pContainer
, "Can't retrieve current graphic!" );
662 uno::Reference
< io::XInputStream
> xStream
;
663 if ( mpImp
->pContainer
&& !bUpdate
)
665 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "getting stream from container" );
666 // try to get graphic stream from container storage
667 xStream
= mpImp
->pContainer
->GetGraphicStream( mxObj
, &mpImp
->aMediaType
);
670 const sal_Int32 nConstBufferSize
= 32000;
671 SvStream
*pStream
= new SvMemoryStream( 32000, 32000 );
673 uno::Sequence
< sal_Int8
> aSequence ( nConstBufferSize
);
676 nRead
= xStream
->readBytes ( aSequence
, nConstBufferSize
);
677 pStream
->Write( aSequence
.getConstArray(), nRead
);
679 while ( nRead
== nConstBufferSize
);
687 RTL_LOGFILE_CONTEXT_TRACE( aLog
, "getting stream from object" );
688 // update wanted or no stream in container storage available
689 xStream
= GetGraphicReplacementStream( mpImp
->nViewAspect
, mxObj
, &mpImp
->aMediaType
);
693 if ( mpImp
->pContainer
)
694 mpImp
->pContainer
->InsertGraphicStream( xStream
, mpImp
->aPersistName
, mpImp
->aMediaType
);
696 SvStream
* pResult
= ::utl::UcbStreamHelper::CreateStream( xStream
);
697 if ( pResult
&& bUpdate
)
698 mpImp
->bNeedUpdate
= sal_False
;
707 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle
&rRect
, const String
&rText
, OutputDevice
*pOut
)
709 MapMode
aMM( MAP_APPFONT
);
710 Size aAppFontSz
= pOut
->LogicToLogic( Size( 0, 8 ), &aMM
, NULL
);
711 Font
aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz
);
712 aFnt
.SetTransparent( TRUE
);
713 aFnt
.SetColor( Color( COL_LIGHTRED
) );
714 aFnt
.SetWeight( WEIGHT_BOLD
);
715 aFnt
.SetFamily( FAMILY_SWISS
);
718 pOut
->SetBackground();
719 pOut
->SetFont( aFnt
);
722 // Nun den Text so skalieren, dass er in das Rect passt.
723 // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
724 for( USHORT i
= 8; i
> 2; i
-- )
726 aPt
.X() = (rRect
.GetWidth() - pOut
->GetTextWidth( rText
)) / 2;
727 aPt
.Y() = (rRect
.GetHeight() - pOut
->GetTextHeight()) / 2;
730 if( aPt
.X() < 0 ) bTiny
= TRUE
, aPt
.X() = 0;
731 if( aPt
.Y() < 0 ) bTiny
= TRUE
, aPt
.Y() = 0;
734 // heruntergehen bei kleinen Bildern
735 aFnt
.SetSize( Size( 0, aAppFontSz
.Height() * i
/ 8 ) );
736 pOut
->SetFont( aFnt
);
742 Bitmap
aBmp( SvtResId( BMP_PLUGIN
) );
743 long nHeight
= rRect
.GetHeight() - pOut
->GetTextHeight();
744 long nWidth
= rRect
.GetWidth();
748 Point aP
= rRect
.TopLeft();
749 Size aBmpSize
= aBmp
.GetSizePixel();
751 if( nHeight
* 10 / nWidth
752 > aBmpSize
.Height() * 10 / aBmpSize
.Width() )
754 // nach der Breite ausrichten
755 // Proportion beibehalten
756 long nH
= nWidth
* aBmpSize
.Height() / aBmpSize
.Width();
758 aP
.Y() += (nHeight
- nH
) / 2;
763 // nach der H"ohe ausrichten
764 // Proportion beibehalten
765 long nW
= nHeight
* aBmpSize
.Width() / aBmpSize
.Height();
767 aP
.X() += (nWidth
- nW
) / 2;
771 pOut
->DrawBitmap( aP
, Size( nWidth
, nHeight
), aBmp
);
774 pOut
->IntersectClipRegion( rRect
);
775 aPt
+= rRect
.TopLeft();
776 pOut
->DrawText( aPt
, rText
);
780 void EmbeddedObjectRef::DrawShading( const Rectangle
&rRect
, OutputDevice
*pOut
)
782 GDIMetaFile
* pMtf
= pOut
->GetConnectMetaFile();
783 if( pMtf
&& pMtf
->IsRecord() )
787 pOut
->SetLineColor( Color( COL_BLACK
) );
789 Size aPixSize
= pOut
->LogicToPixel( rRect
.GetSize() );
790 aPixSize
.Width() -= 1;
791 aPixSize
.Height() -= 1;
792 Point aPixViewPos
= pOut
->LogicToPixel( rRect
.TopLeft() );
793 INT32 nMax
= aPixSize
.Width() + aPixSize
.Height();
794 for( INT32 i
= 5; i
< nMax
; i
+= 5 )
796 Point
a1( aPixViewPos
), a2( aPixViewPos
);
797 if( i
> aPixSize
.Width() )
798 a1
+= Point( aPixSize
.Width(), i
- aPixSize
.Width() );
801 if( i
> aPixSize
.Height() )
802 a2
+= Point( i
- aPixSize
.Height(), aPixSize
.Height() );
806 pOut
->DrawLine( pOut
->PixelToLogic( a1
), pOut
->PixelToLogic( a2
) );
813 BOOL
EmbeddedObjectRef::TryRunningState()
815 return TryRunningState( mxObj
);
818 BOOL
EmbeddedObjectRef::TryRunningState( const uno::Reference
< embed::XEmbeddedObject
>& xEmbObj
)
825 if ( xEmbObj
->getCurrentState() == embed::EmbedStates::LOADED
)
826 xEmbObj
->changeState( embed::EmbedStates::RUNNING
);
828 catch ( uno::Exception
& )
836 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic
& rGraphic
,
837 comphelper::EmbeddedObjectContainer
& aContainer
,
838 const ::rtl::OUString
& aName
,
839 const ::rtl::OUString
& aMediaType
)
841 SvMemoryStream aStream
;
842 aStream
.SetVersion( SOFFICE_FILEFORMAT_CURRENT
);
843 if ( rGraphic
.ExportNative( aStream
) )
847 uno::Reference
< io::XInputStream
> xStream
= new ::utl::OSeekableInputStreamWrapper( aStream
);
848 aContainer
.InsertGraphicStream( xStream
, aName
, aMediaType
);
851 OSL_ENSURE( sal_False
, "Export of graphic is failed!\n" );
854 sal_Bool
EmbeddedObjectRef::ObjectIsModified( const uno::Reference
< embed::XEmbeddedObject
>& xObj
)
855 throw( uno::Exception
)
857 sal_Bool bResult
= sal_False
;
859 sal_Int32 nState
= xObj
->getCurrentState();
860 if ( nState
!= embed::EmbedStates::LOADED
&& nState
!= embed::EmbedStates::RUNNING
)
862 // the object is active so if the model is modified the replacement
863 // should be retrieved from the object
864 uno::Reference
< util::XModifiable
> xModifiable( xObj
->getComponent(), uno::UNO_QUERY
);
865 if ( xModifiable
.is() )
866 bResult
= xModifiable
->isModified();
872 uno::Reference
< io::XInputStream
> EmbeddedObjectRef::GetGraphicReplacementStream(
873 sal_Int64 nViewAspect
,
874 const uno::Reference
< embed::XEmbeddedObject
>& xObj
,
875 ::rtl::OUString
* pMediaType
)
878 return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect
,xObj
,pMediaType
);
881 void EmbeddedObjectRef::UpdateReplacementOnDemand()
883 DELETEZ( mpImp
->pGraphic
);
884 mpImp
->bNeedUpdate
= sal_True
;
885 if ( mpImp
->pHCGraphic
) DELETEZ( mpImp
->pHCGraphic
);
887 if( mpImp
->pContainer
)
889 //remove graphic from container thus a new up to date one is requested on save
890 mpImp
->pContainer
->RemoveGraphicStream( mpImp
->aPersistName
);
894 BOOL
EmbeddedObjectRef::IsChart() const
896 //todo maybe for 3.0:
897 //if the changes work good for chart
898 //we should apply them for all own ole objects
900 //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
901 //as this call can be very expensive and does block the user interface as long at it takes
906 SvGlobalName
aObjClsId( mxObj
->getClassID() );
908 SvGlobalName(SO3_SCH_CLASSID_30
) == aObjClsId
909 || SvGlobalName(SO3_SCH_CLASSID_40
) == aObjClsId
910 || SvGlobalName(SO3_SCH_CLASSID_50
) == aObjClsId
911 || SvGlobalName(SO3_SCH_CLASSID_60
) == aObjClsId
)
919 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size
& rSizeIn_100TH_MM
)
921 //#i103460# charts do not necessaryly have an own size within ODF files,
922 //for this case they need to use the size settings from the surrounding frame,
923 //which is made available with this method
925 mpImp
->aDefaultSizeForChart_In_100TH_MM
= awt::Size( rSizeIn_100TH_MM
.getWidth(), rSizeIn_100TH_MM
.getHeight() );
927 ::com::sun::star::uno::Reference
< ::com::sun::star::chart2::XDefaultSizeTransmitter
> xSizeTransmitter( mxObj
, uno::UNO_QUERY
);
928 DBG_ASSERT( xSizeTransmitter
.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
929 if( xSizeTransmitter
.is() )
930 xSizeTransmitter
->setDefaultSize( mpImp
->aDefaultSizeForChart_In_100TH_MM
);