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