Update ooo320-m1
[ooovba.git] / svtools / source / misc / embedhlp.cxx
blob837ff064697adba00acaa869b7ce29288c292343
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: embedhlp.cxx,v $
10 * $Revision: 1.28 $
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>
50 #endif
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;
64 namespace svt
67 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
68 document::XEventListener,
69 util::XModifyListener,
70 util::XCloseListener >
72 public:
73 EmbeddedObjectRef* pObject;
74 sal_Int32 nState;
76 EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
77 pObject(p)
78 , nState(-1)
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 );
98 xRet->acquire();
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!" );
106 if ( xClose.is() )
107 xClose->addCloseListener( xRet );
109 uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
110 if ( xBrd.is() )
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 );
117 if ( xMod.is() )
118 // listen for changes in running state (update replacements in case of changes)
119 xMod->addModifyListener( xRet );
123 return xRet;
126 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
127 ::sal_Int32,
128 ::sal_Int32 )
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() );
140 nState = nNewState;
141 if ( !pObject )
142 return;
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
168 if ( xMod.is() )
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();
183 else
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() );
201 #if 0
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();
208 else
209 #endif
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() )
230 pObject->Clear();
231 pObject = 0;
235 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
237 if ( pObject && aEvent.Source == pObject->GetObject() )
239 pObject->Clear();
240 pObject = 0;
244 struct EmbeddedObjectRef_Impl
246 EmbedEventListener_Impl* xListener;
247 ::rtl::OUString aPersistName;
248 ::rtl::OUString aMediaType;
249 comphelper::EmbeddedObjectContainer* pContainer;
250 Graphic* pGraphic;
251 Graphic* pHCGraphic;
252 sal_Int64 nViewAspect;
253 BOOL bIsLocked;
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;
262 mpImp->pGraphic = 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()
272 Construct_Impl();
275 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
277 Construct_Impl();
278 mpImp->nViewAspect = nAspect;
279 mxObj = xObj;
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;
289 mxObj = rObj.mxObj;
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 );
298 else
299 mpImp->pGraphic = 0;
301 mpImp->pHCGraphic = 0;
304 EmbeddedObjectRef::~EmbeddedObjectRef()
306 delete mpImp->pGraphic;
307 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
308 Clear();
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 );
317 Clear();
319 mpImp->nViewAspect = rObj.mpImp->nViewAspect;
320 mpImp->bIsLocked = rObj.mpImp->bIsLocked;
321 mxObj = rObj.mxObj;
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 );
330 else
331 mpImp->pGraphic = 0;
332 return *this;
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!" );
339 Clear();
340 mpImp->nViewAspect = nAspect;
341 mxObj = xObj;
342 mpImp->xListener = EmbedEventListener_Impl::Create( this );
344 //#i103460#
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 );
360 if ( xClose.is() )
361 xClose->removeCloseListener( mpImp->xListener );
363 uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY );
364 if ( xBrd.is() )
365 xBrd->removeEventListener( mpImp->xListener );
367 if ( mpImp->bIsLocked )
369 if ( xClose.is() )
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;
394 mxObj = 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 ) );
426 else
427 // TODO/LATER: currently only CONTENT aspect requires communication with the object
428 return MAP_100TH_MM;
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 )
453 if ( 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;
462 else
464 DBG_ERROR("No update, but replacement exists already!");
465 return;
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 );
494 Size aResult;
496 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON )
498 Graphic* pGraphic = GetGraphic();
499 if ( pGraphic )
501 aSourceMapMode = pGraphic->GetPrefMapMode();
502 aResult = pGraphic->GetPrefSize();
504 else
505 aResult = Size( 2500, 2500 );
507 else
509 awt::Size aSize;
511 if ( mxObj.is() )
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 )
537 aSize.Width = 5000;
538 aSize.Height = 5000;
541 aResult = Size( aSize.Width, aSize.Height );
544 if ( pTargetMapMode )
545 aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
547 return aResult;
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 );
593 if ( pStream )
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;
601 else
602 delete pGraphic;
605 delete pStream;
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 );
668 if ( xStream.is() )
670 const sal_Int32 nConstBufferSize = 32000;
671 SvStream *pStream = new SvMemoryStream( 32000, 32000 );
672 sal_Int32 nRead=0;
673 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
676 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
677 pStream->Write( aSequence.getConstArray(), nRead );
679 while ( nRead == nConstBufferSize );
680 pStream->Seek(0);
681 return pStream;
685 if ( !xStream.is() )
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 );
691 if ( xStream.is() )
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;
700 return pResult;
704 return NULL;
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 );
717 pOut->Push();
718 pOut->SetBackground();
719 pOut->SetFont( aFnt );
721 Point aPt;
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;
729 BOOL bTiny = FALSE;
730 if( aPt.X() < 0 ) bTiny = TRUE, aPt.X() = 0;
731 if( aPt.Y() < 0 ) bTiny = TRUE, aPt.Y() = 0;
732 if( bTiny )
734 // heruntergehen bei kleinen Bildern
735 aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
736 pOut->SetFont( aFnt );
738 else
739 break;
742 Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
743 long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
744 long nWidth = rRect.GetWidth();
745 if( nHeight > 0 )
747 aPt.Y() = nHeight;
748 Point aP = rRect.TopLeft();
749 Size aBmpSize = aBmp.GetSizePixel();
750 // Bitmap einpassen
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();
757 // zentrieren
758 aP.Y() += (nHeight - nH) / 2;
759 nHeight = nH;
761 else
763 // nach der H"ohe ausrichten
764 // Proportion beibehalten
765 long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
766 // zentrieren
767 aP.X() += (nWidth - nW) / 2;
768 nWidth = nW;
771 pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
774 pOut->IntersectClipRegion( rRect );
775 aPt += rRect.TopLeft();
776 pOut->DrawText( aPt, rText );
777 pOut->Pop();
780 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
782 GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
783 if( pMtf && pMtf->IsRecord() )
784 return;
786 pOut->Push();
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() );
799 else
800 a1 += Point( i, 0 );
801 if( i > aPixSize.Height() )
802 a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
803 else
804 a2 += Point( 0, i );
806 pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
809 pOut->Pop();
813 BOOL EmbeddedObjectRef::TryRunningState()
815 return TryRunningState( mxObj );
818 BOOL EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
820 if ( !xEmbObj.is() )
821 return FALSE;
825 if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
826 xEmbObj->changeState( embed::EmbedStates::RUNNING );
828 catch ( uno::Exception& )
830 return FALSE;
833 return TRUE;
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 ) )
845 aStream.Seek( 0 );
847 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
848 aContainer.InsertGraphicStream( xStream, aName, aMediaType );
850 else
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();
869 return bResult;
872 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
873 sal_Int64 nViewAspect,
874 const uno::Reference< embed::XEmbeddedObject >& xObj,
875 ::rtl::OUString* pMediaType )
876 throw()
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
903 if ( !mxObj.is() )
904 return false;
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)
913 return sal_True;
916 return sal_False;
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 );