Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <svtools/embedhlp.hxx>
22 : #include <vcl/graphicfilter.hxx>
23 : #include <svtools/svtools.hrc>
24 : #include <svtools/svtresid.hxx>
25 :
26 : #include <comphelper/embeddedobjectcontainer.hxx>
27 : #include <comphelper/seqstream.hxx>
28 : #include <toolkit/helper/vclunohelper.hxx>
29 : #include <unotools/ucbstreamhelper.hxx>
30 : #include <unotools/streamwrap.hxx>
31 : #include <com/sun/star/chart2/XChartDocument.hpp>
32 : #include <com/sun/star/chart2/XCoordinateSystem.hpp>
33 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
34 : #include <com/sun/star/chart2/XDiagram.hpp>
35 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
36 : #include <com/sun/star/chart2/XChartType.hpp>
37 : #include <tools/globname.hxx>
38 : #include <comphelper/classids.hxx>
39 : #include <com/sun/star/util/XModifyListener.hpp>
40 : #include <com/sun/star/util/XModifiable.hpp>
41 : #include <com/sun/star/embed/Aspects.hpp>
42 : #include <com/sun/star/embed/EmbedMisc.hpp>
43 : #include <com/sun/star/embed/EmbedStates.hpp>
44 : #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
45 : #include <com/sun/star/embed/XEmbeddedObject.hpp>
46 : #include <com/sun/star/embed/XStateChangeListener.hpp>
47 : #include <com/sun/star/embed/XLinkageSupport.hpp>
48 : #include <com/sun/star/datatransfer/XTransferable.hpp>
49 : #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
50 : #include <cppuhelper/implbase4.hxx>
51 : #include <vcl/svapp.hxx>
52 : #include <osl/mutex.hxx>
53 : #include <boost/scoped_ptr.hpp>
54 :
55 : using namespace com::sun::star;
56 :
57 : namespace svt {
58 :
59 2474 : class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
60 : document::XEventListener,
61 : util::XModifyListener,
62 : util::XCloseListener >
63 : {
64 : public:
65 : EmbeddedObjectRef* pObject;
66 : sal_Int32 nState;
67 :
68 1252 : explicit EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
69 : pObject(p)
70 1252 : , nState(-1)
71 1252 : {}
72 :
73 : static EmbedEventListener_Impl* Create( EmbeddedObjectRef* );
74 :
75 : virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
76 : throw (embed::WrongStateException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
77 : virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
78 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
79 : virtual void SAL_CALL queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership )
80 : throw (util::CloseVetoException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
81 : virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
82 : virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
83 : virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
84 : virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
85 : };
86 :
87 1252 : EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
88 : {
89 1252 : EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
90 1252 : xRet->acquire();
91 :
92 1252 : if ( p->GetObject().is() )
93 : {
94 1237 : p->GetObject()->addStateChangeListener( xRet );
95 :
96 1237 : uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
97 : DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
98 1237 : if ( xClose.is() )
99 1237 : xClose->addCloseListener( xRet );
100 :
101 2474 : uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
102 1237 : if ( xBrd.is() )
103 1237 : xBrd->addEventListener( xRet );
104 :
105 1237 : xRet->nState = p->GetObject()->getCurrentState();
106 1237 : if ( xRet->nState == embed::EmbedStates::RUNNING )
107 : {
108 1086 : uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
109 1086 : if ( xMod.is() )
110 : // listen for changes in running state (update replacements in case of changes)
111 1084 : xMod->addModifyListener( xRet );
112 1237 : }
113 : }
114 :
115 1252 : return xRet;
116 : }
117 :
118 273 : void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
119 : ::sal_Int32,
120 : ::sal_Int32 )
121 : throw ( embed::WrongStateException,
122 : uno::RuntimeException, std::exception )
123 : {
124 273 : }
125 :
126 263 : void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
127 : ::sal_Int32 nOldState,
128 : ::sal_Int32 nNewState )
129 : throw ( uno::RuntimeException, std::exception )
130 : {
131 263 : SolarMutexGuard aGuard;
132 263 : nState = nNewState;
133 263 : if ( !pObject )
134 263 : return;
135 :
136 526 : uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
137 263 : if ( nNewState == embed::EmbedStates::RUNNING )
138 : {
139 : // TODO/LATER: container must be set before!
140 : // When is this event created? Who sets the new container when it changed?
141 85 : if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() )
142 : // get new replacement after deactivation
143 0 : pObject->UpdateReplacement();
144 :
145 85 : if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE )
146 : {
147 : //create a new metafile replacement when leaving the edit mode
148 : //for buggy documents where the old image looks different from the correct one
149 1 : if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow
150 0 : pObject->UpdateReplacementOnDemand();
151 : }
152 :
153 85 : if ( xMod.is() && nOldState == embed::EmbedStates::LOADED )
154 : // listen for changes (update replacements in case of changes)
155 84 : xMod->addModifyListener( this );
156 : }
157 178 : else if ( nNewState == embed::EmbedStates::LOADED )
158 : {
159 : // in loaded state we can't listen
160 177 : if ( xMod.is() )
161 0 : xMod->removeModifyListener( this );
162 263 : }
163 : }
164 :
165 6973 : void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException, std::exception)
166 : {
167 6973 : SolarMutexGuard aGuard;
168 6973 : if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
169 : {
170 5638 : if ( nState == embed::EmbedStates::RUNNING )
171 : {
172 : // updates only necessary in non-active states
173 5627 : if( pObject->IsChart() )
174 734 : pObject->UpdateReplacementOnDemand();
175 : else
176 4893 : pObject->UpdateReplacement();
177 : }
178 22 : else if ( nState == embed::EmbedStates::ACTIVE ||
179 11 : nState == embed::EmbedStates::UI_ACTIVE ||
180 0 : nState == embed::EmbedStates::INPLACE_ACTIVE )
181 : {
182 : // in case the object is inplace or UI active the replacement image should be updated on demand
183 11 : pObject->UpdateReplacementOnDemand();
184 : }
185 6973 : }
186 6973 : }
187 :
188 9374 : void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
189 : {
190 9374 : SolarMutexGuard aGuard;
191 :
192 9374 : if ( pObject && aEvent.EventName == "OnVisAreaChanged" && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
193 : {
194 10 : pObject->UpdateReplacement();
195 9374 : }
196 9374 : }
197 :
198 270 : void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, sal_Bool )
199 : throw ( util::CloseVetoException, uno::RuntimeException, std::exception)
200 : {
201 : // An embedded object can be shared between several objects (f.e. for undo purposes)
202 : // the object will not be closed before the last "customer" is destroyed
203 : // Now the EmbeddedObjectRef helper class works like a "lock" on the object
204 270 : if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
205 270 : throw util::CloseVetoException();
206 0 : }
207 :
208 0 : void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException, std::exception)
209 : {
210 0 : if ( pObject && Source.Source == pObject->GetObject() )
211 : {
212 0 : pObject->Clear();
213 0 : pObject = 0;
214 : }
215 0 : }
216 :
217 1170 : void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
218 : {
219 1170 : if ( pObject && aEvent.Source == pObject->GetObject() )
220 : {
221 0 : pObject->Clear();
222 0 : pObject = 0;
223 : }
224 1170 : }
225 :
226 : struct EmbeddedObjectRef_Impl
227 : {
228 : uno::Reference <embed::XEmbeddedObject> mxObj;
229 :
230 : EmbedEventListener_Impl* xListener;
231 : OUString aPersistName;
232 : OUString aMediaType;
233 : comphelper::EmbeddedObjectContainer* pContainer;
234 : Graphic* pGraphic;
235 : sal_Int64 nViewAspect;
236 : bool bIsLocked:1;
237 : bool bNeedUpdate:1;
238 :
239 : // #i104867#
240 : sal_uInt32 mnGraphicVersion;
241 : 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
242 :
243 808 : EmbeddedObjectRef_Impl() :
244 : xListener(0),
245 : pContainer(NULL),
246 : pGraphic(NULL),
247 : nViewAspect(embed::Aspects::MSOLE_CONTENT),
248 : bIsLocked(false),
249 : bNeedUpdate(false),
250 : mnGraphicVersion(0),
251 808 : aDefaultSizeForChart_In_100TH_MM(awt::Size(8000,7000))
252 808 : {}
253 :
254 438 : EmbeddedObjectRef_Impl( const EmbeddedObjectRef_Impl& r ) :
255 : mxObj(r.mxObj),
256 : xListener(0),
257 : aPersistName(r.aPersistName),
258 : aMediaType(r.aMediaType),
259 : pContainer(r.pContainer),
260 : pGraphic(NULL),
261 : nViewAspect(r.nViewAspect),
262 : bIsLocked(r.bIsLocked),
263 : bNeedUpdate(r.bNeedUpdate),
264 : mnGraphicVersion(0),
265 438 : aDefaultSizeForChart_In_100TH_MM(r.aDefaultSizeForChart_In_100TH_MM)
266 : {
267 438 : if (r.pGraphic && !r.bNeedUpdate)
268 286 : pGraphic = new Graphic(*r.pGraphic);
269 438 : }
270 :
271 1246 : ~EmbeddedObjectRef_Impl()
272 1246 : {
273 1246 : delete pGraphic;
274 1246 : }
275 : };
276 :
277 9661 : const uno::Reference <embed::XEmbeddedObject>& EmbeddedObjectRef::operator->() const
278 : {
279 9661 : return mpImpl->mxObj;
280 : }
281 :
282 22542 : const uno::Reference <embed::XEmbeddedObject>& EmbeddedObjectRef::GetObject() const
283 : {
284 22542 : return mpImpl->mxObj;
285 : }
286 :
287 680 : EmbeddedObjectRef::EmbeddedObjectRef() : mpImpl(new EmbeddedObjectRef_Impl) {}
288 :
289 128 : EmbeddedObjectRef::EmbeddedObjectRef( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) :
290 128 : mpImpl(new EmbeddedObjectRef_Impl)
291 : {
292 128 : mpImpl->nViewAspect = nAspect;
293 128 : mpImpl->mxObj = xObj;
294 128 : mpImpl->xListener = EmbedEventListener_Impl::Create( this );
295 128 : }
296 :
297 438 : EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj ) :
298 438 : mpImpl(new EmbeddedObjectRef_Impl(*rObj.mpImpl))
299 : {
300 438 : mpImpl->xListener = EmbedEventListener_Impl::Create( this );
301 438 : }
302 :
303 1246 : EmbeddedObjectRef::~EmbeddedObjectRef()
304 : {
305 1246 : Clear();
306 1246 : delete mpImpl;
307 1246 : }
308 :
309 686 : void EmbeddedObjectRef::Assign( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
310 : {
311 : DBG_ASSERT(!mpImpl->mxObj.is(), "Never assign an already assigned object!");
312 :
313 686 : Clear();
314 686 : mpImpl->nViewAspect = nAspect;
315 686 : mpImpl->mxObj = xObj;
316 686 : mpImpl->xListener = EmbedEventListener_Impl::Create( this );
317 :
318 : //#i103460#
319 686 : if ( IsChart() )
320 : {
321 294 : uno::Reference < chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY );
322 : DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
323 294 : if( xSizeTransmitter.is() )
324 294 : xSizeTransmitter->setDefaultSize( mpImpl->aDefaultSizeForChart_In_100TH_MM );
325 : }
326 686 : }
327 :
328 2416 : void EmbeddedObjectRef::Clear()
329 : {
330 2416 : if (mpImpl->mxObj.is() && mpImpl->xListener)
331 : {
332 1237 : mpImpl->mxObj->removeStateChangeListener(mpImpl->xListener);
333 :
334 1237 : uno::Reference<util::XCloseable> xClose(mpImpl->mxObj, uno::UNO_QUERY);
335 1237 : if ( xClose.is() )
336 1237 : xClose->removeCloseListener( mpImpl->xListener );
337 :
338 2474 : uno::Reference<document::XEventBroadcaster> xBrd(mpImpl->mxObj, uno::UNO_QUERY);
339 1237 : if ( xBrd.is() )
340 1237 : xBrd->removeEventListener( mpImpl->xListener );
341 :
342 1237 : if ( mpImpl->bIsLocked )
343 : {
344 633 : if ( xClose.is() )
345 : {
346 : try
347 : {
348 633 : mpImpl->mxObj->changeState(embed::EmbedStates::LOADED);
349 632 : xClose->close( true );
350 : }
351 86 : catch (const util::CloseVetoException&)
352 : {
353 : // there's still someone who needs the object!
354 : }
355 1 : catch (const uno::Exception&)
356 : {
357 : OSL_FAIL( "Error on switching of the object to loaded state and closing!\n" );
358 : }
359 : }
360 : }
361 :
362 1237 : if ( mpImpl->xListener )
363 : {
364 1237 : mpImpl->xListener->pObject = 0;
365 1237 : mpImpl->xListener->release();
366 1237 : mpImpl->xListener = 0;
367 : }
368 :
369 1237 : mpImpl->mxObj = NULL;
370 2474 : mpImpl->bNeedUpdate = false;
371 : }
372 :
373 2416 : mpImpl->pContainer = 0;
374 2416 : mpImpl->bIsLocked = false;
375 2416 : mpImpl->bNeedUpdate = false;
376 2416 : }
377 :
378 15751 : bool EmbeddedObjectRef::is() const
379 : {
380 15751 : return mpImpl->mxObj.is();
381 : }
382 :
383 1042 : void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const OUString& rPersistName )
384 : {
385 1042 : mpImpl->pContainer = pContainer;
386 1042 : mpImpl->aPersistName = rPersistName;
387 :
388 1042 : if ( mpImpl->pGraphic && !mpImpl->bNeedUpdate && pContainer )
389 283 : SetGraphicToContainer( *mpImpl->pGraphic, *pContainer, mpImpl->aPersistName, OUString() );
390 1042 : }
391 :
392 5238 : comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
393 : {
394 5238 : return mpImpl->pContainer;
395 : }
396 :
397 11311 : sal_Int64 EmbeddedObjectRef::GetViewAspect() const
398 : {
399 11311 : return mpImpl->nViewAspect;
400 : }
401 :
402 196 : void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
403 : {
404 196 : mpImpl->nViewAspect = nAspect;
405 196 : }
406 :
407 1081 : void EmbeddedObjectRef::Lock( bool bLock )
408 : {
409 1081 : mpImpl->bIsLocked = bLock;
410 1081 : }
411 :
412 270 : bool EmbeddedObjectRef::IsLocked() const
413 : {
414 270 : return mpImpl->bIsLocked;
415 : }
416 :
417 4911 : void EmbeddedObjectRef::GetReplacement( bool bUpdate )
418 : {
419 4911 : if ( bUpdate )
420 : {
421 4905 : DELETEZ( mpImpl->pGraphic );
422 4905 : (mpImpl->aMediaType).clear();
423 4905 : mpImpl->pGraphic = new Graphic;
424 4905 : mpImpl->mnGraphicVersion++;
425 : }
426 6 : else if ( !mpImpl->pGraphic )
427 : {
428 6 : mpImpl->pGraphic = new Graphic;
429 6 : mpImpl->mnGraphicVersion++;
430 : }
431 : else
432 : {
433 : OSL_FAIL("No update, but replacement exists already!");
434 4911 : return;
435 : }
436 :
437 4911 : boost::scoped_ptr<SvStream> pGraphicStream(GetGraphicStream( bUpdate ));
438 4911 : if ( pGraphicStream )
439 : {
440 4911 : GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
441 4911 : if( mpImpl->pGraphic )
442 4911 : rGF.ImportGraphic( *mpImpl->pGraphic, OUString(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
443 4911 : mpImpl->mnGraphicVersion++;
444 4911 : }
445 : }
446 :
447 91 : const Graphic* EmbeddedObjectRef::GetGraphic( OUString* pMediaType ) const
448 : {
449 : try
450 : {
451 91 : if ( mpImpl->bNeedUpdate )
452 : // bNeedUpdate will be set to false while retrieving new replacement
453 2 : const_cast < EmbeddedObjectRef* >(this)->GetReplacement(true);
454 89 : else if ( !mpImpl->pGraphic )
455 6 : const_cast < EmbeddedObjectRef* >(this)->GetReplacement(false);
456 : }
457 0 : catch( const uno::Exception& ex )
458 : {
459 : SAL_WARN("svtools.misc", "Something went wrong on getting the graphic: " << ex.Message);
460 : }
461 :
462 91 : if ( mpImpl->pGraphic && pMediaType )
463 0 : *pMediaType = mpImpl->aMediaType;
464 91 : return mpImpl->pGraphic;
465 : }
466 :
467 381 : Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
468 : {
469 381 : MapMode aSourceMapMode( MAP_100TH_MM );
470 381 : Size aResult;
471 :
472 381 : if ( mpImpl->nViewAspect == embed::Aspects::MSOLE_ICON )
473 : {
474 0 : const Graphic* pGraphic = GetGraphic();
475 0 : if ( pGraphic )
476 : {
477 0 : aSourceMapMode = pGraphic->GetPrefMapMode();
478 0 : aResult = pGraphic->GetPrefSize();
479 : }
480 : else
481 0 : aResult = Size( 2500, 2500 );
482 : }
483 : else
484 : {
485 381 : awt::Size aSize;
486 :
487 381 : if (mpImpl->mxObj.is())
488 : {
489 : try
490 : {
491 381 : aSize = mpImpl->mxObj->getVisualAreaSize(mpImpl->nViewAspect);
492 : }
493 20 : catch(const embed::NoVisualAreaSizeException&)
494 : {
495 : }
496 1 : catch(const uno::Exception&)
497 : {
498 : OSL_FAIL( "Something went wrong on getting of the size of the object!" );
499 : }
500 :
501 : try
502 : {
503 381 : aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit(mpImpl->mxObj->getMapUnit(mpImpl->nViewAspect));
504 : }
505 1 : catch(const uno::Exception&)
506 : {
507 : OSL_FAIL( "Can not get the map mode!" );
508 : }
509 : }
510 :
511 381 : if ( !aSize.Height && !aSize.Width )
512 : {
513 21 : aSize.Width = 5000;
514 21 : aSize.Height = 5000;
515 : }
516 :
517 381 : aResult = Size( aSize.Width, aSize.Height );
518 : }
519 :
520 381 : if ( pTargetMapMode )
521 381 : aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
522 :
523 381 : return aResult;
524 : }
525 :
526 0 : void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
527 : const OUString& rMediaType )
528 : {
529 0 : if ( mpImpl->pGraphic )
530 0 : delete mpImpl->pGraphic;
531 0 : mpImpl->pGraphic = new Graphic();
532 0 : mpImpl->aMediaType = rMediaType;
533 0 : mpImpl->mnGraphicVersion++;
534 :
535 0 : boost::scoped_ptr<SvStream> pGraphicStream(::utl::UcbStreamHelper::CreateStream( xInGrStream ));
536 :
537 0 : if ( pGraphicStream )
538 : {
539 0 : GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
540 0 : rGF.ImportGraphic( *mpImpl->pGraphic, "", *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
541 0 : mpImpl->mnGraphicVersion++;
542 :
543 0 : if ( mpImpl->pContainer )
544 : {
545 0 : pGraphicStream->Seek( 0 );
546 0 : uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream.get() );
547 :
548 0 : mpImpl->pContainer->InsertGraphicStream( xInSeekGrStream, mpImpl->aPersistName, rMediaType );
549 : }
550 : }
551 :
552 0 : mpImpl->bNeedUpdate = false;
553 :
554 0 : }
555 :
556 76 : void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const OUString& rMediaType )
557 : {
558 76 : if ( mpImpl->pGraphic )
559 5 : delete mpImpl->pGraphic;
560 76 : mpImpl->pGraphic = new Graphic( rGraphic );
561 76 : mpImpl->aMediaType = rMediaType;
562 76 : mpImpl->mnGraphicVersion++;
563 :
564 76 : if ( mpImpl->pContainer )
565 55 : SetGraphicToContainer( rGraphic, *mpImpl->pContainer, mpImpl->aPersistName, rMediaType );
566 :
567 76 : mpImpl->bNeedUpdate = false;
568 76 : }
569 :
570 4911 : SvStream* EmbeddedObjectRef::GetGraphicStream( bool bUpdate ) const
571 : {
572 : DBG_ASSERT( bUpdate || mpImpl->pContainer, "Can't retrieve current graphic!" );
573 4911 : uno::Reference < io::XInputStream > xStream;
574 4911 : if ( mpImpl->pContainer && !bUpdate )
575 : {
576 : SAL_INFO( "svtools.misc", "getting stream from container" );
577 : // try to get graphic stream from container storage
578 6 : xStream = mpImpl->pContainer->GetGraphicStream(mpImpl->mxObj, &mpImpl->aMediaType);
579 6 : if ( xStream.is() )
580 : {
581 6 : const sal_Int32 nConstBufferSize = 32000;
582 6 : SvStream *pStream = new SvMemoryStream( 32000, 32000 );
583 : try
584 : {
585 6 : sal_Int32 nRead=0;
586 6 : uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
587 6 : do
588 : {
589 6 : nRead = xStream->readBytes ( aSequence, nConstBufferSize );
590 6 : pStream->Write( aSequence.getConstArray(), nRead );
591 : }
592 : while ( nRead == nConstBufferSize );
593 6 : pStream->Seek(0);
594 6 : return pStream;
595 : }
596 0 : catch (const uno::Exception& ex)
597 : {
598 : SAL_WARN("svtools.misc", "discarding broken embedded object preview: " << ex.Message);
599 0 : delete pStream;
600 0 : xStream.clear();
601 : }
602 : }
603 : }
604 :
605 4905 : if ( !xStream.is() )
606 : {
607 : SAL_INFO( "svtools.misc", "getting stream from object" );
608 4905 : bool bUpdateAllowed(true);
609 4905 : const comphelper::EmbeddedObjectContainer* pContainer = GetContainer();
610 :
611 4905 : if(pContainer)
612 : {
613 : uno::Reference<embed::XLinkageSupport> const xLinkage(
614 796 : mpImpl->mxObj, uno::UNO_QUERY);
615 796 : if (xLinkage.is() && xLinkage->isLink())
616 : {
617 0 : bUpdateAllowed = pContainer->getUserAllowsLinkUpdate();
618 :
619 796 : }
620 : }
621 :
622 4905 : if (bUpdateAllowed)
623 : {
624 : // update wanted or no stream in container storage available
625 4905 : xStream = GetGraphicReplacementStream(mpImpl->nViewAspect, mpImpl->mxObj, &mpImpl->aMediaType);
626 :
627 4905 : if(xStream.is())
628 : {
629 4905 : if (mpImpl->pContainer)
630 796 : mpImpl->pContainer->InsertGraphicStream(xStream,mpImpl->aPersistName,mpImpl->aMediaType);
631 :
632 4905 : SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
633 4905 : if (pResult && bUpdate)
634 4905 : mpImpl->bNeedUpdate = false;
635 :
636 4905 : return pResult;
637 : }
638 : }
639 : }
640 :
641 0 : return NULL;
642 : }
643 :
644 0 : void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const OUString &rText, OutputDevice *pOut )
645 : {
646 0 : MapMode aMM( MAP_APPFONT );
647 0 : Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
648 0 : vcl::Font aFnt( OUString("Helvetica"), aAppFontSz );
649 0 : aFnt.SetTransparent( true );
650 0 : aFnt.SetColor( Color( COL_LIGHTRED ) );
651 0 : aFnt.SetWeight( WEIGHT_BOLD );
652 0 : aFnt.SetFamily( FAMILY_SWISS );
653 :
654 0 : pOut->Push();
655 0 : pOut->SetBackground();
656 0 : pOut->SetFont( aFnt );
657 :
658 0 : Point aPt;
659 :
660 : // Now scale text such that it fits in the rectangle
661 : // We start with the default size and decrease 1-AppFont
662 0 : for( sal_uInt16 i = 8; i > 2; i-- )
663 : {
664 0 : aPt.X() = (rRect.GetWidth() - pOut->GetTextWidth( rText )) / 2;
665 0 : aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
666 :
667 0 : bool bTiny = false;
668 0 : if( aPt.X() < 0 ) bTiny = true, aPt.X() = 0;
669 0 : if( aPt.Y() < 0 ) bTiny = true, aPt.Y() = 0;
670 0 : if( bTiny )
671 : {
672 : // decrease for small images
673 0 : aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
674 0 : pOut->SetFont( aFnt );
675 : }
676 : else
677 0 : break;
678 : }
679 :
680 0 : Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
681 0 : long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
682 0 : long nWidth = rRect.GetWidth();
683 0 : if(nHeight > 0 && nWidth > 0 && aBmp.GetSizePixel().Width() > 0)
684 : {
685 0 : aPt.Y() = nHeight;
686 0 : Point aP = rRect.TopLeft();
687 0 : Size aBmpSize = aBmp.GetSizePixel();
688 : // fit bitmap in
689 0 : if( nHeight * 10 / nWidth
690 0 : > aBmpSize.Height() * 10 / aBmpSize.Width() )
691 : {
692 : // adjust to the width
693 : // keep proportions
694 0 : long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
695 : // center
696 0 : aP.Y() += (nHeight - nH) / 2;
697 0 : nHeight = nH;
698 : }
699 : else
700 : {
701 : // adjust to the height
702 : // keep proportions
703 0 : long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
704 : // center
705 0 : aP.X() += (nWidth - nW) / 2;
706 0 : nWidth = nW;
707 : }
708 :
709 0 : pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
710 : }
711 :
712 0 : pOut->IntersectClipRegion( rRect );
713 0 : aPt += rRect.TopLeft();
714 0 : pOut->DrawText( aPt, rText );
715 0 : pOut->Pop();
716 0 : }
717 :
718 0 : void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
719 : {
720 0 : GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
721 0 : if( pMtf && pMtf->IsRecord() )
722 0 : return;
723 :
724 0 : pOut->Push();
725 0 : pOut->SetLineColor( Color( COL_BLACK ) );
726 :
727 0 : Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
728 0 : aPixSize.Width() -= 1;
729 0 : aPixSize.Height() -= 1;
730 0 : Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
731 0 : sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
732 0 : for( sal_Int32 i = 5; i < nMax; i += 5 )
733 : {
734 0 : Point a1( aPixViewPos ), a2( aPixViewPos );
735 0 : if( i > aPixSize.Width() )
736 0 : a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
737 : else
738 0 : a1 += Point( i, 0 );
739 0 : if( i > aPixSize.Height() )
740 0 : a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
741 : else
742 0 : a2 += Point( 0, i );
743 :
744 0 : pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
745 : }
746 :
747 0 : pOut->Pop();
748 :
749 : }
750 :
751 1557 : bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
752 : {
753 1557 : if ( !xEmbObj.is() )
754 0 : return false;
755 :
756 : try
757 : {
758 1557 : if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
759 75 : xEmbObj->changeState( embed::EmbedStates::RUNNING );
760 : }
761 30 : catch (const uno::Exception&)
762 : {
763 15 : return false;
764 : }
765 :
766 1542 : return true;
767 : }
768 :
769 353 : void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
770 : comphelper::EmbeddedObjectContainer& aContainer,
771 : const OUString& aName,
772 : const OUString& aMediaType )
773 : {
774 353 : SvMemoryStream aStream;
775 353 : aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
776 353 : if ( rGraphic.ExportNative( aStream ) )
777 : {
778 353 : aStream.Seek( 0 );
779 :
780 353 : uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
781 353 : aContainer.InsertGraphicStream( xStream, aName, aMediaType );
782 : }
783 : else
784 353 : OSL_FAIL( "Export of graphic is failed!\n" );
785 353 : }
786 :
787 4905 : uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
788 : sal_Int64 nViewAspect,
789 : const uno::Reference< embed::XEmbeddedObject >& xObj,
790 : OUString* pMediaType )
791 : throw()
792 : {
793 4905 : return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
794 : }
795 :
796 7483 : bool EmbeddedObjectRef::IsChart(const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj)
797 : {
798 7483 : SvGlobalName aObjClsId(xObj->getClassID());
799 14966 : if(
800 29932 : SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
801 14966 : || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
802 14966 : || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
803 37415 : || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
804 : {
805 2116 : return true;
806 : }
807 :
808 5367 : return false;
809 : }
810 :
811 84 : bool EmbeddedObjectRef::IsGLChart(const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj)
812 : {
813 84 : static const char* env = getenv("CHART_DUMMY_FACTORY");
814 84 : if (IsChart(xObj))
815 : {
816 65 : if (env)
817 0 : return true;
818 :
819 65 : uno::Reference< chart2::XChartDocument > xChartDoc(xObj->getComponent(), uno::UNO_QUERY);
820 65 : if (!xChartDoc.is())
821 0 : return false;
822 :
823 65 : return xChartDoc->isOpenGLChart();
824 : }
825 19 : return false;
826 : }
827 :
828 4903 : void EmbeddedObjectRef::UpdateReplacement()
829 : {
830 4903 : GetReplacement( true );
831 4903 : }
832 :
833 745 : void EmbeddedObjectRef::UpdateReplacementOnDemand()
834 : {
835 745 : DELETEZ( mpImpl->pGraphic );
836 745 : mpImpl->bNeedUpdate = true;
837 745 : mpImpl->mnGraphicVersion++;
838 :
839 745 : if( mpImpl->pContainer )
840 : {
841 : //remove graphic from container thus a new up to date one is requested on save
842 670 : mpImpl->pContainer->RemoveGraphicStream( mpImpl->aPersistName );
843 : }
844 745 : }
845 :
846 7571 : bool EmbeddedObjectRef::IsChart() const
847 : {
848 : //todo maybe for 3.0:
849 : //if the changes work good for chart
850 : //we should apply them for all own ole objects
851 :
852 : //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary
853 : //as this call can be very expensive and does block the user interface as long at it takes
854 :
855 7571 : if (!mpImpl->mxObj.is())
856 172 : return false;
857 :
858 7399 : return EmbeddedObjectRef::IsChart(mpImpl->mxObj);
859 : }
860 :
861 82 : bool EmbeddedObjectRef::IsGLChart() const
862 : {
863 82 : if (!mpImpl->mxObj.is())
864 0 : return false;
865 :
866 82 : return EmbeddedObjectRef::IsGLChart(mpImpl->mxObj);
867 : }
868 :
869 : // MT: Only used for getting accessible attributes, which are not localized
870 0 : OUString EmbeddedObjectRef::GetChartType()
871 : {
872 0 : OUString Style;
873 0 : if ( mpImpl->mxObj.is() )
874 : {
875 0 : if ( IsChart() )
876 : {
877 0 : if ( svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObj ) )
878 : {
879 0 : uno::Reference< chart2::XChartDocument > xChart( mpImpl->mxObj->getComponent(), uno::UNO_QUERY );
880 0 : if (xChart.is())
881 : {
882 0 : uno::Reference< chart2::XDiagram > xDiagram( xChart->getFirstDiagram());
883 0 : if( ! xDiagram.is())
884 0 : return OUString();
885 0 : uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
886 0 : uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
887 : // IA2 CWS. Unused: int nCoordinateCount = aCooSysSeq.getLength();
888 0 : bool bGetChartType = false;
889 0 : for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
890 : {
891 0 : uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
892 0 : uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
893 0 : int nDimesionCount = aCooSysSeq[nCooSysIdx]->getDimension();
894 0 : if( nDimesionCount == 3 )
895 0 : Style += "3D ";
896 : else
897 0 : Style += "2D ";
898 0 : for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
899 : {
900 0 : OUString strChartType = aChartTypes[nCTIdx]->getChartType();
901 0 : if (strChartType == "com.sun.star.chart2.AreaChartType")
902 : {
903 0 : Style += "Areas";
904 0 : bGetChartType = true;
905 : }
906 0 : else if (strChartType == "com.sun.star.chart2.BarChartType")
907 : {
908 0 : Style += "Bars";
909 0 : bGetChartType = true;
910 : }
911 0 : else if (strChartType == "com.sun.star.chart2.ColumnChartType")
912 : {
913 0 : uno::Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
914 0 : if( xProp.is())
915 : {
916 0 : bool bCurrent = false;
917 0 : if( xProp->getPropertyValue( OUString("SwapXAndYAxis") ) >>= bCurrent )
918 : {
919 0 : if (bCurrent)
920 0 : Style += "Bars";
921 : else
922 0 : Style += "Columns";
923 0 : bGetChartType = true;
924 : }
925 0 : }
926 : }
927 0 : else if (strChartType == "com.sun.star.chart2.LineChartType")
928 : {
929 0 : Style += "Lines";
930 0 : bGetChartType = true;
931 : }
932 0 : else if (strChartType == "com.sun.star.chart2.ScatterChartType")
933 : {
934 0 : Style += "XY Chart";
935 0 : bGetChartType = true;
936 : }
937 0 : else if (strChartType == "com.sun.star.chart2.PieChartType")
938 : {
939 0 : Style += "Pies";
940 0 : bGetChartType = true;
941 : }
942 0 : else if (strChartType == "com.sun.star.chart2.NetChartType")
943 : {
944 0 : Style += "Radar";
945 0 : bGetChartType = true;
946 : }
947 0 : else if (strChartType == "com.sun.star.chart2.CandleStickChartType")
948 : {
949 0 : Style += "Candle Stick Chart";
950 0 : bGetChartType = true;
951 : }
952 0 : if (bGetChartType)
953 0 : return Style;
954 0 : }
955 0 : }
956 0 : }
957 : }
958 : }
959 : }
960 0 : return Style;
961 : }
962 :
963 : // #i104867#
964 271 : sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
965 : {
966 271 : return mpImpl->mnGraphicVersion;
967 : }
968 :
969 37 : void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
970 : {
971 : //#i103460# charts do not necessaryly have an own size within ODF files,
972 : //for this case they need to use the size settings from the surrounding frame,
973 : //which is made available with this method
974 :
975 37 : mpImpl->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
976 :
977 37 : uno::Reference<chart2::XDefaultSizeTransmitter> xSizeTransmitter(mpImpl->mxObj, uno::UNO_QUERY);
978 : DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
979 37 : if( xSizeTransmitter.is() )
980 37 : xSizeTransmitter->setDefaultSize( mpImpl->aDefaultSizeForChart_In_100TH_MM );
981 37 : }
982 :
983 798 : } // namespace svt
984 :
985 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|