xref: /aoo41x/main/svtools/source/misc/embedhlp.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <svtools/embedhlp.hxx>
32 #include <svtools/filter.hxx>
33 #include <svtools/svtools.hrc>
34 #include <svtools/svtdata.hxx>
35 
36 #include <comphelper/embeddedobjectcontainer.hxx>
37 #include <comphelper/seqstream.hxx>
38 #include <toolkit/helper/vclunohelper.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <unotools/streamwrap.hxx>
41 
42 #include <tools/globname.hxx>
43 #include <sot/clsids.hxx>
44 #include <com/sun/star/util/XModifyListener.hpp>
45 #ifndef _COM_SUN_STAR_UTIL_XMODIFYiBLE_HPP_
46 #include <com/sun/star/util/XModifiable.hpp>
47 #endif
48 #include <com/sun/star/embed/EmbedStates.hpp>
49 #include <com/sun/star/embed/EmbedMisc.hpp>
50 #include <com/sun/star/embed/XStateChangeListener.hpp>
51 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
52 #include <com/sun/star/util/XModifiable.hpp>
53 #include <com/sun/star/datatransfer/XTransferable.hpp>
54 #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
55 #include <cppuhelper/implbase4.hxx>
56 #include "vcl/svapp.hxx"
57 #include <rtl/logfile.hxx>
58 #include <vos/mutex.hxx>
59 
60 using namespace com::sun::star;
61 
62 namespace svt
63 {
64 
65 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
66 																 document::XEventListener,
67                                                                  util::XModifyListener,
68 																 util::XCloseListener >
69 {
70 public:
71     EmbeddedObjectRef*          pObject;
72     sal_Int32                   nState;
73 
74                                 EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
75                                     pObject(p)
76                                     , nState(-1)
77                                 {}
78 
79     static EmbedEventListener_Impl* Create( EmbeddedObjectRef* );
80 
81     virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
82 									throw (embed::WrongStateException, uno::RuntimeException);
83     virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
84 									throw (uno::RuntimeException);
85     virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership )
86                                     throw (util::CloseVetoException, uno::RuntimeException);
87     virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
88     virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException );
89     virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException );
90     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
91 };
92 
93 EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
94 {
95     EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
96     xRet->acquire();
97 
98 	if ( p->GetObject().is() )
99 	{
100         p->GetObject()->addStateChangeListener( xRet );
101 
102     	uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
103     	DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
104     	if ( xClose.is() )
105             xClose->addCloseListener( xRet );
106 
107     	uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
108     	if ( xBrd.is() )
109         	xBrd->addEventListener( xRet );
110 
111         xRet->nState = p->GetObject()->getCurrentState();
112         if ( xRet->nState == embed::EmbedStates::RUNNING )
113         {
114             uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
115             if ( xMod.is() )
116                 // listen for changes in running state (update replacements in case of changes)
117                 xMod->addModifyListener( xRet );
118         }
119 	}
120 
121     return xRet;
122 }
123 
124 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
125 													::sal_Int32,
126 													::sal_Int32 )
127 	throw ( embed::WrongStateException,
128 			uno::RuntimeException )
129 {
130 }
131 
132 void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
133 													::sal_Int32 nOldState,
134 													::sal_Int32 nNewState )
135 	throw ( uno::RuntimeException )
136 {
137 	::vos::OGuard aGuard( Application::GetSolarMutex() );
138     nState = nNewState;
139     if ( !pObject )
140         return;
141 
142     uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
143     if ( nNewState == embed::EmbedStates::RUNNING )
144     {
145         // TODO/LATER: container must be set before!
146         // When is this event created? Who sets the new container when it changed?
147         if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() )
148             // get new replacement after deactivation
149             pObject->UpdateReplacement();
150 
151         if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE )
152         {
153             //create a new metafile replacement when leaving the edit mode
154             //for buggy documents where the old image looks different from the correct one
155             if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow
156                 pObject->UpdateReplacementOnDemand();
157         }
158 
159         if ( xMod.is() && nOldState == embed::EmbedStates::LOADED )
160             // listen for changes (update replacements in case of changes)
161             xMod->addModifyListener( this );
162     }
163     else if ( nNewState == embed::EmbedStates::LOADED )
164     {
165         // in loaded state we can't listen
166         if ( xMod.is() )
167             xMod->removeModifyListener( this );
168     }
169 }
170 
171 void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException)
172 {
173 	::vos::OGuard aGuard( Application::GetSolarMutex() );
174     if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
175     {
176         if ( nState == embed::EmbedStates::RUNNING )
177         {
178             // updates only necessary in non-active states
179             if( pObject->IsChart() )
180                 pObject->UpdateReplacementOnDemand();
181             else
182                 pObject->UpdateReplacement();
183         }
184         else if ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE )
185         {
186             // in case the object is inplace or UI active the replacement image should be updated on demand
187             pObject->UpdateReplacementOnDemand();
188         }
189     }
190 }
191 
192 void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException )
193 {
194 	::vos::OGuard aGuard( Application::GetSolarMutex() );
195 
196 #if 0
197     if ( pObject && aEvent.EventName.equalsAscii("OnSaveDone") || aEvent.EventName.equalsAscii("OnSaveAsDone") )
198     {
199         // TODO/LATER: container must be set before!
200         // When is this event created? Who sets the new container when it changed?
201         pObject->UpdateReplacement();
202     }
203     else
204 #endif
205     if ( pObject && aEvent.EventName.equalsAscii("OnVisAreaChanged") && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
206     {
207         pObject->UpdateReplacement();
208     }
209 }
210 
211 void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, ::sal_Bool )
212         throw ( util::CloseVetoException, uno::RuntimeException)
213 {
214     // An embedded object can be shared between several objects (f.e. for undo purposes)
215     // the object will not be closed before the last "customer" is destroyed
216     // Now the EmbeddedObjectRef helper class works like a "lock" on the object
217     if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
218         throw util::CloseVetoException();
219 }
220 
221 void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException)
222 {
223     if ( pObject && Source.Source == pObject->GetObject() )
224     {
225         pObject->Clear();
226         pObject = 0;
227     }
228 }
229 
230 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
231 {
232     if ( pObject && aEvent.Source == pObject->GetObject() )
233     {
234         pObject->Clear();
235         pObject = 0;
236     }
237 }
238 
239 struct EmbeddedObjectRef_Impl
240 {
241     EmbedEventListener_Impl*                    xListener;
242     ::rtl::OUString                             aPersistName;
243     ::rtl::OUString                             aMediaType;
244     comphelper::EmbeddedObjectContainer*        pContainer;
245     Graphic*                                    pGraphic;
246     Graphic*                                    pHCGraphic;
247     sal_Int64                                   nViewAspect;
248     sal_Bool                                        bIsLocked;
249     sal_Bool                                    bNeedUpdate;
250 
251     // #i104867#
252     sal_uInt32                                  mnGraphicVersion;
253     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
254 };
255 
256 void EmbeddedObjectRef::Construct_Impl()
257 {
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 = sal_False;
264     mpImp->bNeedUpdate = sal_False;
265     mpImp->mnGraphicVersion = 0;
266     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size(8000,7000);
267 }
268 
269 EmbeddedObjectRef::EmbeddedObjectRef()
270 {
271     Construct_Impl();
272 }
273 
274 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
275 {
276     Construct_Impl();
277     mpImp->nViewAspect = nAspect;
278     mxObj = xObj;
279     mpImp->xListener = EmbedEventListener_Impl::Create( this );
280 }
281 
282 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj )
283 {
284     mpImp = new EmbeddedObjectRef_Impl;
285     mpImp->pContainer = rObj.mpImp->pContainer;
286     mpImp->nViewAspect = rObj.mpImp->nViewAspect;
287     mpImp->bIsLocked = rObj.mpImp->bIsLocked;
288     mxObj = rObj.mxObj;
289     mpImp->xListener = EmbedEventListener_Impl::Create( this );
290     mpImp->aPersistName = rObj.mpImp->aPersistName;
291     mpImp->aMediaType = rObj.mpImp->aMediaType;
292     mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
293     mpImp->aDefaultSizeForChart_In_100TH_MM = rObj.mpImp->aDefaultSizeForChart_In_100TH_MM;
294 
295     if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
296         mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
297     else
298         mpImp->pGraphic = 0;
299 
300     mpImp->pHCGraphic = 0;
301     mpImp->mnGraphicVersion = 0;
302 }
303 
304 EmbeddedObjectRef::~EmbeddedObjectRef()
305 {
306     delete mpImp->pGraphic;
307 	if ( mpImp->pHCGraphic )
308         DELETEZ( mpImp->pHCGraphic );
309     Clear();
310 }
311 /*
312 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj )
313 {
314     DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
315 
316     delete mpImp->pGraphic;
317 	if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic );
318     Clear();
319 
320     mpImp->nViewAspect = rObj.mpImp->nViewAspect;
321     mpImp->bIsLocked = rObj.mpImp->bIsLocked;
322     mxObj = rObj.mxObj;
323     mpImp->xListener = EmbedEventListener_Impl::Create( this );
324     mpImp->pContainer = rObj.mpImp->pContainer;
325     mpImp->aPersistName = rObj.mpImp->aPersistName;
326     mpImp->aMediaType = rObj.mpImp->aMediaType;
327     mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate;
328 
329     if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate )
330         mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic );
331     else
332         mpImp->pGraphic = 0;
333     return *this;
334 }
335 */
336 void EmbeddedObjectRef::Assign( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect )
337 {
338     DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" );
339 
340     Clear();
341     mpImp->nViewAspect = nAspect;
342     mxObj = xObj;
343     mpImp->xListener = EmbedEventListener_Impl::Create( this );
344 
345     //#i103460#
346     if ( IsChart() )
347     {
348         ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY );
349         DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
350         if( xSizeTransmitter.is() )
351             xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
352     }
353 }
354 
355 void EmbeddedObjectRef::Clear()
356 {
357     if ( mxObj.is() && mpImp->xListener )
358     {
359         mxObj->removeStateChangeListener( mpImp->xListener );
360 
361         uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY );
362         if ( xClose.is() )
363             xClose->removeCloseListener( mpImp->xListener );
364 
365         uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY );
366         if ( xBrd.is() )
367             xBrd->removeEventListener( mpImp->xListener );
368 
369         if ( mpImp->bIsLocked )
370         {
371             if ( xClose.is() )
372             {
373                 try
374                 {
375                     mxObj->changeState( embed::EmbedStates::LOADED );
376                     xClose->close( sal_True );
377                 }
378                 catch ( util::CloseVetoException& )
379                 {
380                     // there's still someone who needs the object!
381                 }
382 				catch ( uno::Exception& )
383 				{
384 					OSL_ENSURE( sal_False, "Error on switching of the object to loaded state and closing!\n" );
385 				}
386             }
387         }
388 
389         if ( mpImp->xListener )
390         {
391             mpImp->xListener->pObject = 0;
392             mpImp->xListener->release();
393             mpImp->xListener = 0;
394         }
395 
396         mxObj = 0;
397         mpImp->bNeedUpdate = sal_False;
398     }
399 
400     mpImp->pContainer = 0;
401     mpImp->bIsLocked = sal_False;
402     mpImp->bNeedUpdate = sal_False;
403 }
404 
405 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName )
406 {
407     mpImp->pContainer = pContainer;
408     mpImp->aPersistName = rPersistName;
409 
410     if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer )
411 		SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() );
412 }
413 
414 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
415 {
416 	return mpImp->pContainer;
417 }
418 
419 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const
420 {
421 	return mpImp->aPersistName;
422 }
423 
424 MapUnit EmbeddedObjectRef::GetMapUnit() const
425 {
426 	if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT )
427 		return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
428 	else
429 		// TODO/LATER: currently only CONTENT aspect requires communication with the object
430 		return MAP_100TH_MM;
431 }
432 
433 sal_Int64 EmbeddedObjectRef::GetViewAspect() const
434 {
435     return mpImp->nViewAspect;
436 }
437 
438 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
439 {
440     mpImp->nViewAspect = nAspect;
441 }
442 
443 void EmbeddedObjectRef::Lock( sal_Bool bLock )
444 {
445     mpImp->bIsLocked = bLock;
446 }
447 
448 sal_Bool EmbeddedObjectRef::IsLocked() const
449 {
450     return mpImp->bIsLocked;
451 }
452 
453 void EmbeddedObjectRef::GetReplacement( sal_Bool bUpdate )
454 {
455     if ( bUpdate )
456     {
457         DELETEZ( mpImp->pGraphic );
458         mpImp->aMediaType = ::rtl::OUString();
459         mpImp->pGraphic = new Graphic;
460 		if ( mpImp->pHCGraphic )
461             DELETEZ( mpImp->pHCGraphic );
462         mpImp->mnGraphicVersion++;
463     }
464     else if ( !mpImp->pGraphic )
465     {
466         mpImp->pGraphic = new Graphic;
467         mpImp->mnGraphicVersion++;
468     }
469     else
470     {
471         DBG_ERROR("No update, but replacement exists already!");
472         return;
473     }
474 
475     SvStream* pGraphicStream = GetGraphicStream( bUpdate );
476     if ( pGraphicStream )
477     {
478         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
479         if( mpImp->pGraphic )
480             pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
481         mpImp->mnGraphicVersion++;
482         delete pGraphicStream;
483     }
484 }
485 
486 Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const
487 {
488     if ( mpImp->bNeedUpdate )
489         // bNeedUpdate will be set to false while retrieving new replacement
490         const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True );
491     else if ( !mpImp->pGraphic )
492         const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False );
493 
494     if ( mpImp->pGraphic && pMediaType )
495         *pMediaType = mpImp->aMediaType;
496     return mpImp->pGraphic;
497 }
498 
499 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
500 {
501 	MapMode aSourceMapMode( MAP_100TH_MM );
502 	Size aResult;
503 
504 	if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON )
505 	{
506 		Graphic* pGraphic = GetGraphic();
507 		if ( pGraphic )
508 		{
509 			aSourceMapMode = pGraphic->GetPrefMapMode();
510 			aResult = pGraphic->GetPrefSize();
511 		}
512 		else
513 			aResult = Size( 2500, 2500 );
514 	}
515 	else
516 	{
517 		awt::Size aSize;
518 
519 		if ( mxObj.is() )
520 		{
521 			try
522 			{
523 				aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect );
524 			}
525 			catch( embed::NoVisualAreaSizeException& )
526 			{
527 			}
528 			catch( uno::Exception& )
529 			{
530 				OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" );
531 			}
532 
533 			try
534 			{
535 				aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) );
536 			}
537 			catch( uno::Exception )
538 			{
539 				OSL_ENSURE( sal_False, "Can not get the map mode!" );
540 			}
541 		}
542 
543 		if ( !aSize.Height && !aSize.Width )
544 		{
545 			aSize.Width = 5000;
546 			aSize.Height = 5000;
547 		}
548 
549 		aResult = Size( aSize.Width, aSize.Height );
550 	}
551 
552 	if ( pTargetMapMode )
553 		aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
554 
555 	return aResult;
556 }
557 
558 Graphic* EmbeddedObjectRef::GetHCGraphic() const
559 {
560 	if ( !mpImp->pHCGraphic )
561 	{
562 		uno::Reference< io::XInputStream > xInStream;
563 		try
564 		{
565 			// if the object needs size on load, that means that it is not our object
566 			// currently the HC mode is supported only for OOo own objects so the following
567 			// check is used as an optimization
568 			// TODO/LATER: shouldn't there be a special status flag to detect alien implementation?
569 			if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT
570 			  && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) )
571 			{
572 				// TODO/LATER: optimization, it makes no sence to do it for OLE objects
573 				if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED )
574 					mxObj->changeState( embed::EmbedStates::RUNNING );
575 
576 				// TODO: return for the aspect of the document
577 				embed::VisualRepresentation aVisualRepresentation;
578     			uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY );
579 				if ( !xTransferable.is() )
580 					throw uno::RuntimeException();
581 
582 				datatransfer::DataFlavor aDataFlavor(
583             			::rtl::OUString::createFromAscii(
584 								"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
585 						::rtl::OUString::createFromAscii( "GDIMetaFile" ),
586 						::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
587 
588 				uno::Sequence < sal_Int8 > aSeq;
589 				if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() )
590 					xInStream = new ::comphelper::SequenceInputStream( aSeq );
591 			}
592 		}
593 		catch ( uno::Exception& )
594 		{
595 		}
596 
597 		if ( xInStream.is() )
598 		{
599 			SvStream* pStream = NULL;
600 			pStream = ::utl::UcbStreamHelper::CreateStream( xInStream );
601 			if ( pStream )
602 			{
603 				if ( !pStream->GetError() )
604 				{
605         			GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
606 					Graphic* pGraphic = new Graphic();
607         			if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 )
608 						mpImp->pHCGraphic = pGraphic;
609 					else
610 						delete pGraphic;
611                     mpImp->mnGraphicVersion++;
612 				}
613 
614         		delete pStream;
615 			}
616 		}
617 	}
618 
619 	return mpImp->pHCGraphic;
620 }
621 
622 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
623 											const ::rtl::OUString& rMediaType )
624 {
625     if ( mpImp->pGraphic )
626         delete mpImp->pGraphic;
627     mpImp->pGraphic = new Graphic();
628     mpImp->aMediaType = rMediaType;
629 	if ( mpImp->pHCGraphic )
630         DELETEZ( mpImp->pHCGraphic );
631     mpImp->mnGraphicVersion++;
632 
633     SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream );
634 
635     if ( pGraphicStream )
636     {
637         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
638         pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
639         mpImp->mnGraphicVersion++;
640 
641 		if ( mpImp->pContainer )
642 		{
643 			pGraphicStream->Seek( 0 );
644 			uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream );
645 
646     		mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType );
647 		}
648 
649         delete pGraphicStream;
650 	}
651 
652     mpImp->bNeedUpdate = sal_False;
653 
654 }
655 
656 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
657 {
658     if ( mpImp->pGraphic )
659         delete mpImp->pGraphic;
660     mpImp->pGraphic = new Graphic( rGraphic );
661     mpImp->aMediaType = rMediaType;
662 	if ( mpImp->pHCGraphic )
663         DELETEZ( mpImp->pHCGraphic );
664     mpImp->mnGraphicVersion++;
665 
666     if ( mpImp->pContainer )
667 		SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
668 
669     mpImp->bNeedUpdate = sal_False;
670 }
671 
672 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const
673 {
674 	RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
675     DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" );
676     uno::Reference < io::XInputStream > xStream;
677     if ( mpImp->pContainer && !bUpdate )
678     {
679 		RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" );
680         // try to get graphic stream from container storage
681         xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
682         if ( xStream.is() )
683         {
684             const sal_Int32 nConstBufferSize = 32000;
685             SvStream *pStream = new SvMemoryStream( 32000, 32000 );
686             sal_Int32 nRead=0;
687             uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
688             do
689             {
690                 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
691                 pStream->Write( aSequence.getConstArray(), nRead );
692             }
693             while ( nRead == nConstBufferSize );
694             pStream->Seek(0);
695             return pStream;
696         }
697     }
698 
699     if ( !xStream.is() )
700     {
701 		RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" );
702         // update wanted or no stream in container storage available
703 		xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType );
704 
705 		if ( xStream.is() )
706 		{
707 			if ( mpImp->pContainer )
708             	mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType );
709 
710             SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
711             if ( pResult && bUpdate )
712                 mpImp->bNeedUpdate = sal_False;
713 
714             return pResult;
715         }
716     }
717 
718     return NULL;
719 }
720 
721 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut )
722 {
723 	MapMode aMM( MAP_APPFONT );
724 	Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
725 	Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz );
726 	aFnt.SetTransparent( sal_True );
727 	aFnt.SetColor( Color( COL_LIGHTRED ) );
728 	aFnt.SetWeight( WEIGHT_BOLD );
729 	aFnt.SetFamily( FAMILY_SWISS );
730 
731 	pOut->Push();
732 	pOut->SetBackground();
733 	pOut->SetFont( aFnt );
734 
735 	Point aPt;
736 	// Nun den Text so skalieren, dass er in das Rect passt.
737 	// Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
738 	for( sal_uInt16 i = 8; i > 2; i-- )
739 	{
740 		aPt.X() = (rRect.GetWidth()  - pOut->GetTextWidth( rText )) / 2;
741 		aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
742 
743 		sal_Bool bTiny = sal_False;
744 		if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0;
745 		if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0;
746 		if( bTiny )
747 		{
748 			// heruntergehen bei kleinen Bildern
749 			aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
750 			pOut->SetFont( aFnt );
751 		}
752 		else
753 			break;
754 	}
755 
756     Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
757 	long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
758 	long nWidth = rRect.GetWidth();
759 	if( nHeight > 0 )
760 	{
761 		aPt.Y() = nHeight;
762 		Point	aP = rRect.TopLeft();
763 		Size	aBmpSize = aBmp.GetSizePixel();
764 		// Bitmap einpassen
765 		if( nHeight * 10 / nWidth
766 		  > aBmpSize.Height() * 10 / aBmpSize.Width() )
767 		{
768 			// nach der Breite ausrichten
769 			// Proportion beibehalten
770 			long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
771 			// zentrieren
772 			aP.Y() += (nHeight - nH) / 2;
773 			nHeight = nH;
774 		}
775 		else
776 		{
777 			// nach der H"ohe ausrichten
778 			// Proportion beibehalten
779 			long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
780 			// zentrieren
781 			aP.X() += (nWidth - nW) / 2;
782 			nWidth = nW;
783 		}
784 
785 		pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
786 	}
787 
788 	pOut->IntersectClipRegion( rRect );
789 	aPt += rRect.TopLeft();
790 	pOut->DrawText( aPt, rText );
791 	pOut->Pop();
792 }
793 
794 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
795 {
796 	GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
797 	if( pMtf && pMtf->IsRecord() )
798 		return;
799 
800 	pOut->Push();
801 	pOut->SetLineColor( Color( COL_BLACK ) );
802 
803 	Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
804 	aPixSize.Width() -= 1;
805 	aPixSize.Height() -= 1;
806 	Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
807 	sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
808 	for( sal_Int32 i = 5; i < nMax; i += 5 )
809 	{
810 		Point a1( aPixViewPos ), a2( aPixViewPos );
811 		if( i > aPixSize.Width() )
812 			a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
813 		else
814 			a1 += Point( i, 0 );
815 		if( i > aPixSize.Height() )
816 			a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
817 		else
818 			a2 += Point( 0, i );
819 
820 		pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
821 	}
822 
823 	pOut->Pop();
824 
825 }
826 
827 sal_Bool EmbeddedObjectRef::TryRunningState()
828 {
829     return TryRunningState( mxObj );
830 }
831 
832 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
833 {
834 	if ( !xEmbObj.is() )
835 		return sal_False;
836 
837     try
838     {
839         if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
840             xEmbObj->changeState( embed::EmbedStates::RUNNING );
841     }
842     catch ( uno::Exception& )
843     {
844         return sal_False;
845     }
846 
847     return sal_True;
848 }
849 
850 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
851                                                 comphelper::EmbeddedObjectContainer& aContainer,
852                                                 const ::rtl::OUString& aName,
853 												const ::rtl::OUString& aMediaType )
854 {
855     SvMemoryStream aStream;
856     aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
857     if ( rGraphic.ExportNative( aStream ) )
858 	{
859 		aStream.Seek( 0 );
860 
861        	uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
862        	aContainer.InsertGraphicStream( xStream, aName, aMediaType );
863 	}
864     else
865         OSL_ENSURE( sal_False, "Export of graphic is failed!\n" );
866 }
867 
868 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj )
869 	throw( uno::Exception )
870 {
871 	sal_Bool bResult = sal_False;
872 
873 	sal_Int32 nState = xObj->getCurrentState();
874 	if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING )
875 	{
876 		// the object is active so if the model is modified the replacement
877 		// should be retrieved from the object
878 		uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
879 		if ( xModifiable.is() )
880 			bResult = xModifiable->isModified();
881 	}
882 
883 	return bResult;
884 }
885 
886 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
887 																sal_Int64 nViewAspect,
888 																const uno::Reference< embed::XEmbeddedObject >& xObj,
889 																::rtl::OUString* pMediaType )
890 	throw()
891 {
892     return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
893 }
894 
895 void EmbeddedObjectRef::UpdateReplacementOnDemand()
896 {
897     DELETEZ( mpImp->pGraphic );
898     mpImp->bNeedUpdate = sal_True;
899 	if ( mpImp->pHCGraphic )
900         DELETEZ( mpImp->pHCGraphic );
901     mpImp->mnGraphicVersion++;
902 
903     if( mpImp->pContainer )
904     {
905         //remove graphic from container thus a new up to date one is requested on save
906         mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
907     }
908 }
909 
910 sal_Bool EmbeddedObjectRef::IsChart() const
911 {
912     //todo maybe for 3.0:
913     //if the changes work good for chart
914     //we should apply them for all own ole objects
915 
916     //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
917     //as this call can be very expensive and does block the user interface as long at it takes
918 
919     if ( !mxObj.is() )
920         return false;
921 
922     SvGlobalName aObjClsId( mxObj->getClassID() );
923     if(
924         SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
925         || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
926         || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
927         || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
928     {
929         return sal_True;
930     }
931 
932     return sal_False;
933 }
934 
935 // #i104867#
936 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
937 {
938     return mpImp->mnGraphicVersion;
939 }
940 
941 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
942 {
943     //#i103460# charts do not necessaryly have an own size within ODF files,
944     //for this case they need to use the size settings from the surrounding frame,
945     //which is made available with this method
946 
947     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
948 
949     ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY );
950     DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
951     if( xSizeTransmitter.is() )
952         xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
953 }
954 
955 } // namespace svt
956 
957