update dev300-m57
[ooovba.git] / svtools / source / misc / embedhlp.cxx
blob972b54d9ef58d5c86a5eb0adede76c35e2f2e10a
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 <cppuhelper/implbase4.hxx>
58 #include "vcl/svapp.hxx"
59 #include <rtl/logfile.hxx>
61 using namespace com::sun::star;
63 namespace svt
66 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
67 document::XEventListener,
68 util::XModifyListener,
69 util::XCloseListener >
71 public:
72 EmbeddedObjectRef* pObject;
73 sal_Int32 nState;
75 EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
76 pObject(p)
77 , nState(-1)
80 static EmbedEventListener_Impl* Create( EmbeddedObjectRef* );
82 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
83 throw (embed::WrongStateException, uno::RuntimeException);
84 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
85 throw (uno::RuntimeException);
86 virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership )
87 throw (util::CloseVetoException, uno::RuntimeException);
88 virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
89 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException );
90 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException );
91 virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
94 EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
96 EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
97 xRet->acquire();
99 if ( p->GetObject().is() )
101 p->GetObject()->addStateChangeListener( xRet );
103 uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
104 DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
105 if ( xClose.is() )
106 xClose->addCloseListener( xRet );
108 uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
109 if ( xBrd.is() )
110 xBrd->addEventListener( xRet );
112 xRet->nState = p->GetObject()->getCurrentState();
113 if ( xRet->nState == embed::EmbedStates::RUNNING )
115 uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
116 if ( xMod.is() )
117 // listen for changes in running state (update replacements in case of changes)
118 xMod->addModifyListener( xRet );
122 return xRet;
125 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
126 ::sal_Int32,
127 ::sal_Int32 )
128 throw ( embed::WrongStateException,
129 uno::RuntimeException )
133 void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
134 ::sal_Int32 nOldState,
135 ::sal_Int32 nNewState )
136 throw ( uno::RuntimeException )
138 ::vos::OGuard aGuard( Application::GetSolarMutex() );
139 nState = nNewState;
140 if ( !pObject )
141 return;
143 uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
144 if ( nNewState == embed::EmbedStates::RUNNING )
146 // TODO/LATER: container must be set before!
147 // When is this event created? Who sets the new container when it changed?
148 if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() )
149 // get new replacement after deactivation
150 pObject->UpdateReplacement();
152 if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE )
154 //create a new metafile replacement when leaving the edit mode
155 //for buggy documents where the old image looks different from the correct one
156 if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow
157 pObject->UpdateReplacementOnDemand();
160 if ( xMod.is() && nOldState == embed::EmbedStates::LOADED )
161 // listen for changes (update replacements in case of changes)
162 xMod->addModifyListener( this );
164 else if ( nNewState == embed::EmbedStates::LOADED )
166 // in loaded state we can't listen
167 if ( xMod.is() )
168 xMod->removeModifyListener( this );
172 void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException)
174 ::vos::OGuard aGuard( Application::GetSolarMutex() );
175 if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
177 if ( nState == embed::EmbedStates::RUNNING )
179 // updates only necessary in non-active states
180 if( pObject->IsChart() )
181 pObject->UpdateReplacementOnDemand();
182 else
183 pObject->UpdateReplacement();
185 else if ( nState == embed::EmbedStates::ACTIVE ||
186 nState == embed::EmbedStates::UI_ACTIVE ||
187 nState == embed::EmbedStates::INPLACE_ACTIVE )
189 // in case the object is inplace or UI active the replacement image should be updated on demand
190 pObject->UpdateReplacementOnDemand();
196 void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException )
198 ::vos::OGuard aGuard( Application::GetSolarMutex() );
200 #if 0
201 if ( pObject && aEvent.EventName.equalsAscii("OnSaveDone") || aEvent.EventName.equalsAscii("OnSaveAsDone") )
203 // TODO/LATER: container must be set before!
204 // When is this event created? Who sets the new container when it changed?
205 pObject->UpdateReplacement();
207 else
208 #endif
209 if ( pObject && aEvent.EventName.equalsAscii("OnVisAreaChanged") && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
211 pObject->UpdateReplacement();
215 void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, ::sal_Bool )
216 throw ( util::CloseVetoException, uno::RuntimeException)
218 // An embedded object can be shared between several objects (f.e. for undo purposes)
219 // the object will not be closed before the last "customer" is destroyed
220 // Now the EmbeddedObjectRef helper class works like a "lock" on the object
221 if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
222 throw util::CloseVetoException();
225 void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException)
227 if ( pObject && Source.Source == pObject->GetObject() )
229 pObject->Clear();
230 pObject = 0;
234 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
236 if ( pObject && aEvent.Source == pObject->GetObject() )
238 pObject->Clear();
239 pObject = 0;
243 struct EmbeddedObjectRef_Impl
245 EmbedEventListener_Impl* xListener;
246 ::rtl::OUString aPersistName;
247 ::rtl::OUString aMediaType;
248 comphelper::EmbeddedObjectContainer* pContainer;
249 Graphic* pGraphic;
250 Graphic* pHCGraphic;
251 sal_Int64 nViewAspect;
252 BOOL bIsLocked;
253 sal_Bool bNeedUpdate;
256 void EmbeddedObjectRef::Construct_Impl()
258 mpImp = new EmbeddedObjectRef_Impl;
259 mpImp->pContainer = 0;
260 mpImp->pGraphic = 0;
261 mpImp->pHCGraphic = 0;
262 mpImp->nViewAspect = embed::Aspects::MSOLE_CONTENT;
263 mpImp->bIsLocked = FALSE;
264 mpImp->bNeedUpdate = sal_False;
267 EmbeddedObjectRef::EmbeddedObjectRef()
269 Construct_Impl();
272 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
274 Construct_Impl();
275 mpImp->nViewAspect = nAspect;
276 mxObj = xObj;
277 mpImp->xListener = EmbedEventListener_Impl::Create( this );
280 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj )
282 mpImp = new EmbeddedObjectRef_Impl;
283 mpImp->pContainer = rObj.mpImp->pContainer;
284 mpImp->nViewAspect = rObj.mpImp->nViewAspect;
285 mpImp->bIsLocked = rObj.mpImp->bIsLocked;
286 mxObj = rObj.mxObj;
287 mpImp->xListener = EmbedEventListener_Impl::Create( this );
288 mpImp->aPersistName = rObj.mpImp->aPersistName;
289 mpImp->aMediaType = rObj.mpImp->aMediaType;
290 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
292 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
293 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
294 else
295 mpImp->pGraphic = 0;
297 mpImp->pHCGraphic = 0;
300 EmbeddedObjectRef::~EmbeddedObjectRef()
302 delete mpImp->pGraphic;
303 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
304 Clear();
307 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj )
309 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
311 delete mpImp->pGraphic;
312 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
313 Clear();
315 mpImp->nViewAspect = rObj.mpImp->nViewAspect;
316 mpImp->bIsLocked = rObj.mpImp->bIsLocked;
317 mxObj = rObj.mxObj;
318 mpImp->xListener = EmbedEventListener_Impl::Create( this );
319 mpImp->pContainer = rObj.mpImp->pContainer;
320 mpImp->aPersistName = rObj.mpImp->aPersistName;
321 mpImp->aMediaType = rObj.mpImp->aMediaType;
322 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
324 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
325 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
326 else
327 mpImp->pGraphic = 0;
328 return *this;
331 void EmbeddedObjectRef::Assign( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
333 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
335 Clear();
336 mpImp->nViewAspect = nAspect;
337 mxObj = xObj;
338 mpImp->xListener = EmbedEventListener_Impl::Create( this );
341 void EmbeddedObjectRef::Clear()
343 if ( mxObj.is() && mpImp->xListener )
345 mxObj->removeStateChangeListener( mpImp->xListener );
347 uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY );
348 if ( xClose.is() )
349 xClose->removeCloseListener( mpImp->xListener );
351 uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY );
352 if ( xBrd.is() )
353 xBrd->removeEventListener( mpImp->xListener );
355 if ( mpImp->bIsLocked )
357 if ( xClose.is() )
361 mxObj->changeState( embed::EmbedStates::LOADED );
362 xClose->close( sal_True );
364 catch ( util::CloseVetoException& )
366 // there's still someone who needs the object!
368 catch ( uno::Exception& )
370 OSL_ENSURE( sal_False, "Error on switching of the object to loaded state and closing!\n" );
375 if ( mpImp->xListener )
377 mpImp->xListener->pObject = 0;
378 mpImp->xListener->release();
379 mpImp->xListener = 0;
382 mxObj = 0;
383 mpImp->bNeedUpdate = sal_False;
386 mpImp->pContainer = 0;
387 mpImp->bIsLocked = FALSE;
388 mpImp->bNeedUpdate = sal_False;
391 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName )
393 mpImp->pContainer = pContainer;
394 mpImp->aPersistName = rPersistName;
396 if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer )
397 SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() );
400 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
402 return mpImp->pContainer;
405 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const
407 return mpImp->aPersistName;
410 MapUnit EmbeddedObjectRef::GetMapUnit() const
412 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT )
413 return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
414 else
415 // TODO/LATER: currently only CONTENT aspect requires communication with the object
416 return MAP_100TH_MM;
419 sal_Int64 EmbeddedObjectRef::GetViewAspect() const
421 return mpImp->nViewAspect;
424 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
426 mpImp->nViewAspect = nAspect;
429 void EmbeddedObjectRef::Lock( BOOL bLock )
431 mpImp->bIsLocked = bLock;
434 BOOL EmbeddedObjectRef::IsLocked() const
436 return mpImp->bIsLocked;
439 void EmbeddedObjectRef::GetReplacement( BOOL bUpdate )
441 if ( bUpdate )
443 DELETEZ( mpImp->pGraphic );
444 mpImp->aMediaType = ::rtl::OUString();
445 mpImp->pGraphic = new Graphic;
446 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
448 else if ( !mpImp->pGraphic )
449 mpImp->pGraphic = new Graphic;
450 else
452 DBG_ERROR("No update, but replacement exists already!");
453 return;
456 SvStream* pGraphicStream = GetGraphicStream( bUpdate );
457 if ( pGraphicStream )
459 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
460 if( mpImp->pGraphic )
461 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
462 delete pGraphicStream;
466 Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const
468 if ( mpImp->bNeedUpdate )
469 // bNeedUpdate will be set to false while retrieving new replacement
470 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True );
471 else if ( !mpImp->pGraphic )
472 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( FALSE );
474 if ( mpImp->pGraphic && pMediaType )
475 *pMediaType = mpImp->aMediaType;
476 return mpImp->pGraphic;
479 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
481 MapMode aSourceMapMode( MAP_100TH_MM );
482 Size aResult;
484 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON )
486 Graphic* pGraphic = GetGraphic();
487 if ( pGraphic )
489 aSourceMapMode = pGraphic->GetPrefMapMode();
490 aResult = pGraphic->GetPrefSize();
492 else
493 aResult = Size( 2500, 2500 );
495 else
497 awt::Size aSize;
499 if ( mxObj.is() )
503 aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect );
505 catch( embed::NoVisualAreaSizeException& )
508 catch( uno::Exception& )
510 OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" );
515 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
517 catch( uno::Exception )
519 OSL_ENSURE( sal_False, "Can not get the map mode!" );
523 if ( !aSize.Height && !aSize.Width )
525 aSize.Width = 5000;
526 aSize.Height = 5000;
529 aResult = Size( aSize.Width, aSize.Height );
532 if ( pTargetMapMode )
533 aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
535 return aResult;
538 Graphic* EmbeddedObjectRef::GetHCGraphic() const
540 if ( !mpImp->pHCGraphic )
542 uno::Reference< io::XInputStream > xInStream;
545 // if the object needs size on load, that means that it is not our object
546 // currently the HC mode is supported only for OOo own objects so the following
547 // check is used as an optimization
548 // TODO/LATER: shouldn't there be a special status flag to detect alien implementation?
549 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT
550 && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) )
552 // TODO/LATER: optimization, it makes no sence to do it for OLE objects
553 if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED )
554 mxObj->changeState( embed::EmbedStates::RUNNING );
556 // TODO: return for the aspect of the document
557 embed::VisualRepresentation aVisualRepresentation;
558 uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY );
559 if ( !xTransferable.is() )
560 throw uno::RuntimeException();
562 datatransfer::DataFlavor aDataFlavor(
563 ::rtl::OUString::createFromAscii(
564 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
565 ::rtl::OUString::createFromAscii( "GDIMetaFile" ),
566 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
568 uno::Sequence < sal_Int8 > aSeq;
569 if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() )
570 xInStream = new ::comphelper::SequenceInputStream( aSeq );
573 catch ( uno::Exception& )
577 if ( xInStream.is() )
579 SvStream* pStream = NULL;
580 pStream = ::utl::UcbStreamHelper::CreateStream( xInStream );
581 if ( pStream )
583 if ( !pStream->GetError() )
585 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
586 Graphic* pGraphic = new Graphic();
587 if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 )
588 mpImp->pHCGraphic = pGraphic;
589 else
590 delete pGraphic;
593 delete pStream;
598 return mpImp->pHCGraphic;
601 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
602 const ::rtl::OUString& rMediaType )
604 if ( mpImp->pGraphic )
605 delete mpImp->pGraphic;
606 mpImp->pGraphic = new Graphic();
607 mpImp->aMediaType = rMediaType;
608 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
610 SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream );
612 if ( pGraphicStream )
614 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
615 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
617 if ( mpImp->pContainer )
619 pGraphicStream->Seek( 0 );
620 uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream );
622 mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType );
625 delete pGraphicStream;
628 mpImp->bNeedUpdate = sal_False;
632 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
634 if ( mpImp->pGraphic )
635 delete mpImp->pGraphic;
636 mpImp->pGraphic = new Graphic( rGraphic );
637 mpImp->aMediaType = rMediaType;
638 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
640 if ( mpImp->pContainer )
641 SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
643 mpImp->bNeedUpdate = sal_False;
646 SvStream* EmbeddedObjectRef::GetGraphicStream( BOOL bUpdate ) const
648 RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
649 DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" );
650 uno::Reference < io::XInputStream > xStream;
651 if ( mpImp->pContainer && !bUpdate )
653 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" );
654 // try to get graphic stream from container storage
655 xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
656 if ( xStream.is() )
658 const sal_Int32 nConstBufferSize = 32000;
659 SvStream *pStream = new SvMemoryStream( 32000, 32000 );
660 sal_Int32 nRead=0;
661 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
664 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
665 pStream->Write( aSequence.getConstArray(), nRead );
667 while ( nRead == nConstBufferSize );
668 pStream->Seek(0);
669 return pStream;
673 if ( !xStream.is() )
675 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" );
676 // update wanted or no stream in container storage available
677 xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType );
679 if ( xStream.is() )
681 if ( mpImp->pContainer )
682 mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType );
684 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
685 if ( pResult && bUpdate )
686 mpImp->bNeedUpdate = sal_False;
688 return pResult;
692 return NULL;
695 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut )
697 MapMode aMM( MAP_APPFONT );
698 Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
699 Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz );
700 aFnt.SetTransparent( TRUE );
701 aFnt.SetColor( Color( COL_LIGHTRED ) );
702 aFnt.SetWeight( WEIGHT_BOLD );
703 aFnt.SetFamily( FAMILY_SWISS );
705 pOut->Push();
706 pOut->SetBackground();
707 pOut->SetFont( aFnt );
709 Point aPt;
710 // Nun den Text so skalieren, dass er in das Rect passt.
711 // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
712 for( USHORT i = 8; i > 2; i-- )
714 aPt.X() = (rRect.GetWidth() - pOut->GetTextWidth( rText )) / 2;
715 aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
717 BOOL bTiny = FALSE;
718 if( aPt.X() < 0 ) bTiny = TRUE, aPt.X() = 0;
719 if( aPt.Y() < 0 ) bTiny = TRUE, aPt.Y() = 0;
720 if( bTiny )
722 // heruntergehen bei kleinen Bildern
723 aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
724 pOut->SetFont( aFnt );
726 else
727 break;
730 Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
731 long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
732 long nWidth = rRect.GetWidth();
733 if( nHeight > 0 )
735 aPt.Y() = nHeight;
736 Point aP = rRect.TopLeft();
737 Size aBmpSize = aBmp.GetSizePixel();
738 // Bitmap einpassen
739 if( nHeight * 10 / nWidth
740 > aBmpSize.Height() * 10 / aBmpSize.Width() )
742 // nach der Breite ausrichten
743 // Proportion beibehalten
744 long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
745 // zentrieren
746 aP.Y() += (nHeight - nH) / 2;
747 nHeight = nH;
749 else
751 // nach der H"ohe ausrichten
752 // Proportion beibehalten
753 long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
754 // zentrieren
755 aP.X() += (nWidth - nW) / 2;
756 nWidth = nW;
759 pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
762 pOut->IntersectClipRegion( rRect );
763 aPt += rRect.TopLeft();
764 pOut->DrawText( aPt, rText );
765 pOut->Pop();
768 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
770 GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
771 if( pMtf && pMtf->IsRecord() )
772 return;
774 pOut->Push();
775 pOut->SetLineColor( Color( COL_BLACK ) );
777 Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
778 aPixSize.Width() -= 1;
779 aPixSize.Height() -= 1;
780 Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
781 INT32 nMax = aPixSize.Width() + aPixSize.Height();
782 for( INT32 i = 5; i < nMax; i += 5 )
784 Point a1( aPixViewPos ), a2( aPixViewPos );
785 if( i > aPixSize.Width() )
786 a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
787 else
788 a1 += Point( i, 0 );
789 if( i > aPixSize.Height() )
790 a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
791 else
792 a2 += Point( 0, i );
794 pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
797 pOut->Pop();
801 BOOL EmbeddedObjectRef::TryRunningState()
803 return TryRunningState( mxObj );
806 BOOL EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
808 if ( !xEmbObj.is() )
809 return FALSE;
813 if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
814 xEmbObj->changeState( embed::EmbedStates::RUNNING );
816 catch ( uno::Exception& )
818 return FALSE;
821 return TRUE;
824 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
825 comphelper::EmbeddedObjectContainer& aContainer,
826 const ::rtl::OUString& aName,
827 const ::rtl::OUString& aMediaType )
829 SvMemoryStream aStream;
830 aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
831 if ( rGraphic.ExportNative( aStream ) )
833 aStream.Seek( 0 );
835 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
836 aContainer.InsertGraphicStream( xStream, aName, aMediaType );
838 else
839 OSL_ENSURE( sal_False, "Export of graphic is failed!\n" );
842 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj )
843 throw( uno::Exception )
845 sal_Bool bResult = sal_False;
847 sal_Int32 nState = xObj->getCurrentState();
848 if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING )
850 // the object is active so if the model is modified the replacement
851 // should be retrieved from the object
852 uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
853 if ( xModifiable.is() )
854 bResult = xModifiable->isModified();
857 return bResult;
860 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
861 sal_Int64 nViewAspect,
862 const uno::Reference< embed::XEmbeddedObject >& xObj,
863 ::rtl::OUString* pMediaType )
864 throw()
866 return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
869 void EmbeddedObjectRef::UpdateReplacementOnDemand()
871 DELETEZ( mpImp->pGraphic );
872 mpImp->bNeedUpdate = sal_True;
873 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
875 if( mpImp->pContainer )
877 //remove graphic from container thus a new up to date one is requested on save
878 mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
882 BOOL EmbeddedObjectRef::IsChart() const
884 //todo maybe for 3.0:
885 //if the changes work good for chart
886 //we should apply them for all own ole objects
888 //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
889 //as this call can be very expensive and does block the user interface as long at it takes
891 if ( !mxObj.is() )
892 return false;
894 SvGlobalName aObjClsId( mxObj->getClassID() );
896 SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
897 || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
898 || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
899 || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
901 return sal_True;
904 return sal_False;