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