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