xref: /aoo41x/main/svtools/source/misc/embedhlp.cxx (revision d321cf2f)
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 									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 
Create(EmbeddedObjectRef * p)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 
changingState(const lang::EventObject &,::sal_Int32,::sal_Int32)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 
stateChanged(const lang::EventObject &,::sal_Int32 nOldState,::sal_Int32 nNewState)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 
modified(const lang::EventObject &)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 
notifyEvent(const document::EventObject & aEvent)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 
queryClosing(const lang::EventObject & Source,::sal_Bool)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 
notifyClosing(const lang::EventObject & Source)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 
disposing(const lang::EventObject & aEvent)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 
Construct_Impl()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 
EmbeddedObjectRef()270 EmbeddedObjectRef::EmbeddedObjectRef()
271 {
272     Construct_Impl();
273 }
274 
EmbeddedObjectRef(const NS_UNO::Reference<NS_EMBED::XEmbeddedObject> & xObj,sal_Int64 nAspect)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 
EmbeddedObjectRef(const EmbeddedObjectRef & rObj)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 
~EmbeddedObjectRef()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 */
Assign(const NS_UNO::Reference<NS_EMBED::XEmbeddedObject> & xObj,sal_Int64 nAspect)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 
Clear()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 
AssignToContainer(comphelper::EmbeddedObjectContainer * pContainer,const::rtl::OUString & rPersistName)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 
GetContainer() const416 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
417 {
418 	return mpImp->pContainer;
419 }
420 
GetPersistName() const421 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const
422 {
423 	return mpImp->aPersistName;
424 }
425 
GetMapUnit() const426 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 
GetViewAspect() const435 sal_Int64 EmbeddedObjectRef::GetViewAspect() const
436 {
437     return mpImp->nViewAspect;
438 }
439 
SetViewAspect(sal_Int64 nAspect)440 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
441 {
442     mpImp->nViewAspect = nAspect;
443 }
444 
Lock(sal_Bool bLock)445 void EmbeddedObjectRef::Lock( sal_Bool bLock )
446 {
447     mpImp->bIsLocked = bLock;
448 }
449 
IsLocked() const450 sal_Bool EmbeddedObjectRef::IsLocked() const
451 {
452     return mpImp->bIsLocked;
453 }
454 
GetReplacement(sal_Bool bUpdate)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 
GetGraphic(::rtl::OUString * pMediaType) const488 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 
GetSize(MapMode * pTargetMapMode) const508 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 
GetHCGraphic() const567 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 
SetGraphicStream(const uno::Reference<io::XInputStream> & xInGrStream,const::rtl::OUString & rMediaType)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;
655             xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream );
656 
657     		mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType );
658 		}
659 
660         delete pGraphicStream;
661 	}
662 
663     mpImp->bNeedUpdate = sal_False;
664 
665 }
666 
SetGraphic(const Graphic & rGraphic,const::rtl::OUString & rMediaType)667 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType )
668 {
669     if ( mpImp->pGraphic )
670         delete mpImp->pGraphic;
671     mpImp->pGraphic = new Graphic( rGraphic );
672     mpImp->aMediaType = rMediaType;
673 	if ( mpImp->pHCGraphic )
674         DELETEZ( mpImp->pHCGraphic );
675     mpImp->mnGraphicVersion++;
676 
677     if ( mpImp->pContainer )
678 		SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType );
679 
680     mpImp->bNeedUpdate = sal_False;
681 }
682 
GetGraphicStream(sal_Bool bUpdate) const683 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const
684 {
685 	RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" );
686     DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" );
687     uno::Reference < io::XInputStream > xStream;
688     if ( mpImp->pContainer && !bUpdate )
689     {
690 		RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" );
691         // try to get graphic stream from container storage
692         xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType );
693         if ( xStream.is() )
694         {
695             const sal_Int32 nConstBufferSize = 32000;
696             SvStream *pStream = new SvMemoryStream( 32000, 32000 );
697             sal_Int32 nRead=0;
698             uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
699             do
700             {
701                 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
702                 pStream->Write( aSequence.getConstArray(), nRead );
703             }
704             while ( nRead == nConstBufferSize );
705             pStream->Seek(0);
706             return pStream;
707         }
708     }
709 
710     if ( !xStream.is() )
711     {
712 		RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" );
713         bool bUserAllowsLinkUpdate(true);
714         const comphelper::EmbeddedObjectContainer* pContainer = GetContainer();
715 
716         if(pContainer)
717         {
718             bUserAllowsLinkUpdate = pContainer->getUserAllowsLinkUpdate();
719         }
720 
721         if(bUserAllowsLinkUpdate)
722         {
723             // update wanted or no stream in container storage available
724             xStream = GetGraphicReplacementStream(mpImp->nViewAspect,mxObj,&mpImp->aMediaType);
725 
726             if(xStream.is())
727             {
728                 if(mpImp->pContainer)
729                     mpImp->pContainer->InsertGraphicStream(xStream,mpImp->aPersistName,mpImp->aMediaType);
730 
731                 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
732                 if ( pResult && bUpdate )
733                     mpImp->bNeedUpdate = sal_False;
734 
735                 return pResult;
736             }
737         }
738     }
739 
740     return NULL;
741 }
742 
DrawPaintReplacement(const Rectangle & rRect,const String & rText,OutputDevice * pOut)743 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut )
744 {
745 	MapMode aMM( MAP_APPFONT );
746 	Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
747 	Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz );
748 	aFnt.SetTransparent( sal_True );
749 	aFnt.SetColor( Color( COL_LIGHTRED ) );
750 	aFnt.SetWeight( WEIGHT_BOLD );
751 	aFnt.SetFamily( FAMILY_SWISS );
752 
753 	pOut->Push();
754 	pOut->SetBackground();
755 	pOut->SetFont( aFnt );
756 
757 	Point aPt;
758 	// Nun den Text so skalieren, dass er in das Rect passt.
759 	// Wir fangen mit der Defaultsize an und gehen 1-AppFont runter
760 	for( sal_uInt16 i = 8; i > 2; i-- )
761 	{
762 		aPt.X() = (rRect.GetWidth()  - pOut->GetTextWidth( rText )) / 2;
763 		aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
764 
765 		sal_Bool bTiny = sal_False;
766 		if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0;
767 		if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0;
768 		if( bTiny )
769 		{
770 			// heruntergehen bei kleinen Bildern
771 			aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
772 			pOut->SetFont( aFnt );
773 		}
774 		else
775 			break;
776 	}
777 
778     Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
779 	long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
780 	long nWidth = rRect.GetWidth();
781 	if( nHeight > 0 )
782 	{
783 		aPt.Y() = nHeight;
784 		Point	aP = rRect.TopLeft();
785 		Size	aBmpSize = aBmp.GetSizePixel();
786 		// Bitmap einpassen
787 		if( nHeight * 10 / nWidth
788 		  > aBmpSize.Height() * 10 / aBmpSize.Width() )
789 		{
790 			// nach der Breite ausrichten
791 			// Proportion beibehalten
792 			long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
793 			// zentrieren
794 			aP.Y() += (nHeight - nH) / 2;
795 			nHeight = nH;
796 		}
797 		else
798 		{
799 			// nach der H"ohe ausrichten
800 			// Proportion beibehalten
801 			long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
802 			// zentrieren
803 			aP.X() += (nWidth - nW) / 2;
804 			nWidth = nW;
805 		}
806 
807 		pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
808 	}
809 
810 	pOut->IntersectClipRegion( rRect );
811 	aPt += rRect.TopLeft();
812 	pOut->DrawText( aPt, rText );
813 	pOut->Pop();
814 }
815 
DrawShading(const Rectangle & rRect,OutputDevice * pOut)816 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
817 {
818 	GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
819 	if( pMtf && pMtf->IsRecord() )
820 		return;
821 
822 	pOut->Push();
823 	pOut->SetLineColor( Color( COL_BLACK ) );
824 
825 	Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
826 	aPixSize.Width() -= 1;
827 	aPixSize.Height() -= 1;
828 	Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
829 	sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
830 	for( sal_Int32 i = 5; i < nMax; i += 5 )
831 	{
832 		Point a1( aPixViewPos ), a2( aPixViewPos );
833 		if( i > aPixSize.Width() )
834 			a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
835 		else
836 			a1 += Point( i, 0 );
837 		if( i > aPixSize.Height() )
838 			a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
839 		else
840 			a2 += Point( 0, i );
841 
842 		pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
843 	}
844 
845 	pOut->Pop();
846 
847 }
848 
TryRunningState()849 sal_Bool EmbeddedObjectRef::TryRunningState()
850 {
851     return TryRunningState( mxObj );
852 }
853 
TryRunningState(const uno::Reference<embed::XEmbeddedObject> & xEmbObj)854 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
855 {
856 	if ( !xEmbObj.is() )
857 		return sal_False;
858 
859     try
860     {
861         if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
862             xEmbObj->changeState( embed::EmbedStates::RUNNING );
863     }
864     catch ( uno::Exception& )
865     {
866         return sal_False;
867     }
868 
869     return sal_True;
870 }
871 
SetGraphicToContainer(const Graphic & rGraphic,comphelper::EmbeddedObjectContainer & aContainer,const::rtl::OUString & aName,const::rtl::OUString & aMediaType)872 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
873                                                 comphelper::EmbeddedObjectContainer& aContainer,
874                                                 const ::rtl::OUString& aName,
875 												const ::rtl::OUString& aMediaType )
876 {
877     SvMemoryStream aStream;
878     aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
879     if ( rGraphic.ExportNative( aStream ) )
880 	{
881 		aStream.Seek( 0 );
882 
883        	uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
884        	aContainer.InsertGraphicStream( xStream, aName, aMediaType );
885 	}
886     else
887         OSL_ENSURE( sal_False, "Export of graphic is failed!\n" );
888 }
889 
ObjectIsModified(const uno::Reference<embed::XEmbeddedObject> & xObj)890 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj )
891 	throw( uno::Exception )
892 {
893 	sal_Bool bResult = sal_False;
894 
895 	sal_Int32 nState = xObj->getCurrentState();
896 	if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING )
897 	{
898 		// the object is active so if the model is modified the replacement
899 		// should be retrieved from the object
900 		uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
901 		if ( xModifiable.is() )
902 			bResult = xModifiable->isModified();
903 	}
904 
905 	return bResult;
906 }
907 
GetGraphicReplacementStream(sal_Int64 nViewAspect,const uno::Reference<embed::XEmbeddedObject> & xObj,::rtl::OUString * pMediaType)908 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
909 																sal_Int64 nViewAspect,
910 																const uno::Reference< embed::XEmbeddedObject >& xObj,
911 																::rtl::OUString* pMediaType )
912 	throw()
913 {
914     return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
915 }
916 
UpdateReplacementOnDemand()917 void EmbeddedObjectRef::UpdateReplacementOnDemand()
918 {
919     DELETEZ( mpImp->pGraphic );
920     mpImp->bNeedUpdate = sal_True;
921 	if ( mpImp->pHCGraphic )
922         DELETEZ( mpImp->pHCGraphic );
923     mpImp->mnGraphicVersion++;
924 
925     if( mpImp->pContainer )
926     {
927         //remove graphic from container thus a new up to date one is requested on save
928         mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName );
929     }
930 }
931 
IsChart() const932 sal_Bool EmbeddedObjectRef::IsChart() const
933 {
934     //todo maybe for 3.0:
935     //if the changes work good for chart
936     //we should apply them for all own ole objects
937 
938     //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
939     //as this call can be very expensive and does block the user interface as long at it takes
940 
941     if ( !mxObj.is() )
942         return false;
943 
944     SvGlobalName aObjClsId( mxObj->getClassID() );
945     if(
946         SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
947         || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
948         || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
949         || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
950     {
951         return sal_True;
952     }
953 
954     return sal_False;
955 }
956 
957 // MT: Only used for getting accessible attributes, which are not localized
GetChartType()958 rtl::OUString EmbeddedObjectRef::GetChartType()
959 {
960 	rtl::OUString Style;
961 	if ( mxObj.is() )
962 	{
963 		if ( IsChart() )
964 		{
965 			if ( svt::EmbeddedObjectRef::TryRunningState( mxObj ) )
966 			{
967 				uno::Reference< chart2::XChartDocument > xChart( mxObj->getComponent(), uno::UNO_QUERY );
968 				if (xChart.is())
969 				{
970 					uno::Reference< chart2::XDiagram > xDiagram( xChart->getFirstDiagram());
971 					if( ! xDiagram.is())
972 						return String();
973 					uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
974 					uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
975 					// IA2 CWS. Unused: int nCoordinateCount = aCooSysSeq.getLength();
976 					sal_Bool bGetChartType = sal_False;
977 					for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
978 					{
979 						uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
980 						uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
981 						int nDimesionCount = aCooSysSeq[nCooSysIdx]->getDimension();
982 						if( nDimesionCount == 3 )
983 							Style += rtl::OUString::createFromAscii("3D ");
984 						else
985 							Style += rtl::OUString::createFromAscii("2D ");
986 						for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
987 						{
988 							rtl::OUString strChartType = aChartTypes[nCTIdx]->getChartType();
989 							if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.AreaChartType")))
990 							{
991 								Style += rtl::OUString::createFromAscii("Areas");
992 								bGetChartType = sal_True;
993 							}
994 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.BarChartType")))
995 							{
996 								Style += rtl::OUString::createFromAscii("Bars");
997 								bGetChartType = sal_True;
998 							}
999 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.ColumnChartType")))
1000 							{
1001 								uno::Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
1002 								if( xProp.is())
1003 								{
1004 									bool bCurrent = false;
1005 									if( xProp->getPropertyValue( rtl::OUString::createFromAscii("SwapXAndYAxis") ) >>= bCurrent )
1006 									{
1007 										if (bCurrent)
1008 											Style += rtl::OUString::createFromAscii("Bars");
1009 										else
1010 											Style += rtl::OUString::createFromAscii("Columns");
1011 										bGetChartType = sal_True;
1012 									}
1013 								}
1014 							}
1015 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.LineChartType")))
1016 							{
1017 								Style += rtl::OUString::createFromAscii("Lines");
1018 								bGetChartType = sal_True;
1019 							}
1020 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.ScatterChartType")))
1021 							{
1022 								Style += rtl::OUString::createFromAscii("XY Chart");
1023 								bGetChartType = sal_True;
1024 							}
1025 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.PieChartType")))
1026 							{
1027 								Style += rtl::OUString::createFromAscii("Pies");
1028 								bGetChartType = sal_True;
1029 							}
1030 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.NetChartType")))
1031 							{
1032 								Style += rtl::OUString::createFromAscii("Radar");
1033 								bGetChartType = sal_True;
1034 							}
1035 							else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.CandleStickChartType")))
1036 							{
1037 								Style += rtl::OUString::createFromAscii("Candle Stick Chart");
1038 								bGetChartType = sal_True;
1039 							}
1040 							if (bGetChartType)
1041 								return Style;
1042 						}
1043 					}
1044 				}
1045 			}
1046 		}
1047 	}
1048 	return Style;
1049 }
1050 
1051 // #i104867#
getGraphicVersion() const1052 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
1053 {
1054     return mpImp->mnGraphicVersion;
1055 }
1056 
SetDefaultSizeForChart(const Size & rSizeIn_100TH_MM)1057 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
1058 {
1059     //#i103460# charts do not necessaryly have an own size within ODF files,
1060     //for this case they need to use the size settings from the surrounding frame,
1061     //which is made available with this method
1062 
1063     mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
1064 
1065     ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY );
1066     DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
1067     if( xSizeTransmitter.is() )
1068         xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM );
1069 }
1070 
1071 } // namespace svt
1072 
1073