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