xref: /trunk/main/svtools/source/misc/embedhlp.cxx (revision a0d53b35b9c5a6bd9856ab272d521493ba628169)
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