Bump version to 5.0-14
[LibreOffice.git] / svtools / source / misc / embedhlp.cxx
blob5785701f0e89801f459e11577ac89882c0dd94c0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <svtools/embedhlp.hxx>
22 #include <vcl/graphicfilter.hxx>
23 #include <svtools/svtools.hrc>
24 #include <svtools/svtresid.hxx>
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>
55 using namespace com::sun::star;
57 namespace svt {
59 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener,
60 document::XEventListener,
61 util::XModifyListener,
62 util::XCloseListener >
64 public:
65 EmbeddedObjectRef* pObject;
66 sal_Int32 nState;
68 EmbedEventListener_Impl( EmbeddedObjectRef* p ) :
69 pObject(p)
70 , nState(-1)
73 static EmbedEventListener_Impl* Create( EmbeddedObjectRef* );
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;
87 EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p )
89 EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p );
90 xRet->acquire();
92 if ( p->GetObject().is() )
94 p->GetObject()->addStateChangeListener( xRet );
96 uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY );
97 DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" );
98 if ( xClose.is() )
99 xClose->addCloseListener( xRet );
101 uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY );
102 if ( xBrd.is() )
103 xBrd->addEventListener( xRet );
105 xRet->nState = p->GetObject()->getCurrentState();
106 if ( xRet->nState == embed::EmbedStates::RUNNING )
108 uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY );
109 if ( xMod.is() )
110 // listen for changes in running state (update replacements in case of changes)
111 xMod->addModifyListener( xRet );
115 return xRet;
118 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&,
119 ::sal_Int32,
120 ::sal_Int32 )
121 throw ( embed::WrongStateException,
122 uno::RuntimeException, std::exception )
126 void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&,
127 ::sal_Int32 nOldState,
128 ::sal_Int32 nNewState )
129 throw ( uno::RuntimeException, std::exception )
131 SolarMutexGuard aGuard;
132 nState = nNewState;
133 if ( !pObject )
134 return;
136 uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY );
137 if ( nNewState == embed::EmbedStates::RUNNING )
139 // TODO/LATER: container must be set before!
140 // When is this event created? Who sets the new container when it changed?
141 if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() )
142 // get new replacement after deactivation
143 pObject->UpdateReplacement();
145 if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE )
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 if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow
150 pObject->UpdateReplacementOnDemand();
153 if ( xMod.is() && nOldState == embed::EmbedStates::LOADED )
154 // listen for changes (update replacements in case of changes)
155 xMod->addModifyListener( this );
157 else if ( nNewState == embed::EmbedStates::LOADED )
159 // in loaded state we can't listen
160 if ( xMod.is() )
161 xMod->removeModifyListener( this );
165 void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException, std::exception)
167 SolarMutexGuard aGuard;
168 if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON )
170 if ( nState == embed::EmbedStates::RUNNING )
172 // updates only necessary in non-active states
173 if( pObject->IsChart() )
174 pObject->UpdateReplacementOnDemand();
175 else
176 pObject->UpdateReplacement();
178 else if ( nState == embed::EmbedStates::ACTIVE ||
179 nState == embed::EmbedStates::UI_ACTIVE ||
180 nState == embed::EmbedStates::INPLACE_ACTIVE )
182 // in case the object is inplace or UI active the replacement image should be updated on demand
183 pObject->UpdateReplacementOnDemand();
188 void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
190 SolarMutexGuard aGuard;
192 if ( pObject && aEvent.EventName == "OnVisAreaChanged" && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() )
194 pObject->UpdateReplacement();
198 void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, sal_Bool )
199 throw ( util::CloseVetoException, uno::RuntimeException, std::exception)
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 if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() )
205 throw util::CloseVetoException();
208 void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException, std::exception)
210 if ( pObject && Source.Source == pObject->GetObject() )
212 pObject->Clear();
213 pObject = 0;
217 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
219 if ( pObject && aEvent.Source == pObject->GetObject() )
221 pObject->Clear();
222 pObject = 0;
226 struct EmbeddedObjectRef_Impl
228 uno::Reference <embed::XEmbeddedObject> mxObj;
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;
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
243 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 aDefaultSizeForChart_In_100TH_MM(awt::Size(8000,7000))
254 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 aDefaultSizeForChart_In_100TH_MM(r.aDefaultSizeForChart_In_100TH_MM)
267 if (r.pGraphic && !r.bNeedUpdate)
268 pGraphic = new Graphic(*r.pGraphic);
271 ~EmbeddedObjectRef_Impl()
273 delete pGraphic;
277 const uno::Reference <embed::XEmbeddedObject>& EmbeddedObjectRef::operator->() const
279 return mpImpl->mxObj;
282 const uno::Reference <embed::XEmbeddedObject>& EmbeddedObjectRef::GetObject() const
284 return mpImpl->mxObj;
287 EmbeddedObjectRef::EmbeddedObjectRef() : mpImpl(new EmbeddedObjectRef_Impl) {}
289 EmbeddedObjectRef::EmbeddedObjectRef( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) :
290 mpImpl(new EmbeddedObjectRef_Impl)
292 mpImpl->nViewAspect = nAspect;
293 mpImpl->mxObj = xObj;
294 mpImpl->xListener = EmbedEventListener_Impl::Create( this );
297 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj ) :
298 mpImpl(new EmbeddedObjectRef_Impl(*rObj.mpImpl))
300 mpImpl->xListener = EmbedEventListener_Impl::Create( this );
303 EmbeddedObjectRef::~EmbeddedObjectRef()
305 Clear();
306 delete mpImpl;
309 void EmbeddedObjectRef::Assign( const uno::Reference < embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
311 DBG_ASSERT(!mpImpl->mxObj.is(), "Never assign an already assigned object!");
313 Clear();
314 mpImpl->nViewAspect = nAspect;
315 mpImpl->mxObj = xObj;
316 mpImpl->xListener = EmbedEventListener_Impl::Create( this );
318 //#i103460#
319 if ( IsChart() )
321 uno::Reference < chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY );
322 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
323 if( xSizeTransmitter.is() )
324 xSizeTransmitter->setDefaultSize( mpImpl->aDefaultSizeForChart_In_100TH_MM );
328 void EmbeddedObjectRef::Clear()
330 if (mpImpl->mxObj.is() && mpImpl->xListener)
332 mpImpl->mxObj->removeStateChangeListener(mpImpl->xListener);
334 uno::Reference<util::XCloseable> xClose(mpImpl->mxObj, uno::UNO_QUERY);
335 if ( xClose.is() )
336 xClose->removeCloseListener( mpImpl->xListener );
338 uno::Reference<document::XEventBroadcaster> xBrd(mpImpl->mxObj, uno::UNO_QUERY);
339 if ( xBrd.is() )
340 xBrd->removeEventListener( mpImpl->xListener );
342 if ( mpImpl->bIsLocked )
344 if ( xClose.is() )
348 mpImpl->mxObj->changeState(embed::EmbedStates::LOADED);
349 xClose->close( true );
351 catch (const util::CloseVetoException&)
353 // there's still someone who needs the object!
355 catch (const uno::Exception&)
357 OSL_FAIL( "Error on switching of the object to loaded state and closing!\n" );
362 if ( mpImpl->xListener )
364 mpImpl->xListener->pObject = 0;
365 mpImpl->xListener->release();
366 mpImpl->xListener = 0;
369 mpImpl->mxObj = NULL;
370 mpImpl->bNeedUpdate = false;
373 mpImpl->pContainer = 0;
374 mpImpl->bIsLocked = false;
375 mpImpl->bNeedUpdate = false;
378 bool EmbeddedObjectRef::is() const
380 return mpImpl->mxObj.is();
383 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const OUString& rPersistName )
385 mpImpl->pContainer = pContainer;
386 mpImpl->aPersistName = rPersistName;
388 if ( mpImpl->pGraphic && !mpImpl->bNeedUpdate && pContainer )
389 SetGraphicToContainer( *mpImpl->pGraphic, *pContainer, mpImpl->aPersistName, OUString() );
392 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const
394 return mpImpl->pContainer;
397 sal_Int64 EmbeddedObjectRef::GetViewAspect() const
399 return mpImpl->nViewAspect;
402 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect )
404 mpImpl->nViewAspect = nAspect;
407 void EmbeddedObjectRef::Lock( bool bLock )
409 mpImpl->bIsLocked = bLock;
412 bool EmbeddedObjectRef::IsLocked() const
414 return mpImpl->bIsLocked;
417 void EmbeddedObjectRef::GetReplacement( bool bUpdate )
419 if ( bUpdate )
421 DELETEZ( mpImpl->pGraphic );
422 (mpImpl->aMediaType).clear();
423 mpImpl->pGraphic = new Graphic;
424 mpImpl->mnGraphicVersion++;
426 else if ( !mpImpl->pGraphic )
428 mpImpl->pGraphic = new Graphic;
429 mpImpl->mnGraphicVersion++;
431 else
433 OSL_FAIL("No update, but replacement exists already!");
434 return;
437 boost::scoped_ptr<SvStream> pGraphicStream(GetGraphicStream( bUpdate ));
438 if ( pGraphicStream )
440 GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
441 if( mpImpl->pGraphic )
442 rGF.ImportGraphic( *mpImpl->pGraphic, OUString(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
443 mpImpl->mnGraphicVersion++;
447 const Graphic* EmbeddedObjectRef::GetGraphic( OUString* pMediaType ) const
451 if ( mpImpl->bNeedUpdate )
452 // bNeedUpdate will be set to false while retrieving new replacement
453 const_cast < EmbeddedObjectRef* >(this)->GetReplacement(true);
454 else if ( !mpImpl->pGraphic )
455 const_cast < EmbeddedObjectRef* >(this)->GetReplacement(false);
457 catch( const uno::Exception& ex )
459 SAL_WARN("svtools.misc", "Something went wrong on getting the graphic: " << ex.Message);
462 if ( mpImpl->pGraphic && pMediaType )
463 *pMediaType = mpImpl->aMediaType;
464 return mpImpl->pGraphic;
467 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const
469 MapMode aSourceMapMode( MAP_100TH_MM );
470 Size aResult;
472 if ( mpImpl->nViewAspect == embed::Aspects::MSOLE_ICON )
474 const Graphic* pGraphic = GetGraphic();
475 if ( pGraphic )
477 aSourceMapMode = pGraphic->GetPrefMapMode();
478 aResult = pGraphic->GetPrefSize();
480 else
481 aResult = Size( 2500, 2500 );
483 else
485 awt::Size aSize;
487 if (mpImpl->mxObj.is())
491 aSize = mpImpl->mxObj->getVisualAreaSize(mpImpl->nViewAspect);
493 catch(const embed::NoVisualAreaSizeException&)
496 catch(const uno::Exception&)
498 OSL_FAIL( "Something went wrong on getting of the size of the object!" );
503 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit(mpImpl->mxObj->getMapUnit(mpImpl->nViewAspect));
505 catch(const uno::Exception&)
507 OSL_FAIL( "Can not get the map mode!" );
511 if ( !aSize.Height && !aSize.Width )
513 aSize.Width = 5000;
514 aSize.Height = 5000;
517 aResult = Size( aSize.Width, aSize.Height );
520 if ( pTargetMapMode )
521 aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode );
523 return aResult;
526 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream,
527 const OUString& rMediaType )
529 if ( mpImpl->pGraphic )
530 delete mpImpl->pGraphic;
531 mpImpl->pGraphic = new Graphic();
532 mpImpl->aMediaType = rMediaType;
533 mpImpl->mnGraphicVersion++;
535 boost::scoped_ptr<SvStream> pGraphicStream(::utl::UcbStreamHelper::CreateStream( xInGrStream ));
537 if ( pGraphicStream )
539 GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
540 rGF.ImportGraphic( *mpImpl->pGraphic, "", *pGraphicStream, GRFILTER_FORMAT_DONTKNOW );
541 mpImpl->mnGraphicVersion++;
543 if ( mpImpl->pContainer )
545 pGraphicStream->Seek( 0 );
546 uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream.get() );
548 mpImpl->pContainer->InsertGraphicStream( xInSeekGrStream, mpImpl->aPersistName, rMediaType );
552 mpImpl->bNeedUpdate = false;
556 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const OUString& rMediaType )
558 if ( mpImpl->pGraphic )
559 delete mpImpl->pGraphic;
560 mpImpl->pGraphic = new Graphic( rGraphic );
561 mpImpl->aMediaType = rMediaType;
562 mpImpl->mnGraphicVersion++;
564 if ( mpImpl->pContainer )
565 SetGraphicToContainer( rGraphic, *mpImpl->pContainer, mpImpl->aPersistName, rMediaType );
567 mpImpl->bNeedUpdate = false;
570 SvStream* EmbeddedObjectRef::GetGraphicStream( bool bUpdate ) const
572 DBG_ASSERT( bUpdate || mpImpl->pContainer, "Can't retrieve current graphic!" );
573 uno::Reference < io::XInputStream > xStream;
574 if ( mpImpl->pContainer && !bUpdate )
576 SAL_INFO( "svtools.misc", "getting stream from container" );
577 // try to get graphic stream from container storage
578 xStream = mpImpl->pContainer->GetGraphicStream(mpImpl->mxObj, &mpImpl->aMediaType);
579 if ( xStream.is() )
581 const sal_Int32 nConstBufferSize = 32000;
582 SvStream *pStream = new SvMemoryStream( 32000, 32000 );
585 sal_Int32 nRead=0;
586 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
589 nRead = xStream->readBytes ( aSequence, nConstBufferSize );
590 pStream->Write( aSequence.getConstArray(), nRead );
592 while ( nRead == nConstBufferSize );
593 pStream->Seek(0);
594 return pStream;
596 catch (const uno::Exception& ex)
598 SAL_WARN("svtools.misc", "discarding broken embedded object preview: " << ex.Message);
599 delete pStream;
600 xStream.clear();
605 if ( !xStream.is() )
607 SAL_INFO( "svtools.misc", "getting stream from object" );
608 bool bUpdateAllowed(true);
609 const comphelper::EmbeddedObjectContainer* pContainer = GetContainer();
611 if(pContainer)
613 uno::Reference<embed::XLinkageSupport> const xLinkage(
614 mpImpl->mxObj, uno::UNO_QUERY);
615 if (xLinkage.is() && xLinkage->isLink())
617 bUpdateAllowed = pContainer->getUserAllowsLinkUpdate();
622 if (bUpdateAllowed)
624 // update wanted or no stream in container storage available
625 xStream = GetGraphicReplacementStream(mpImpl->nViewAspect, mpImpl->mxObj, &mpImpl->aMediaType);
627 if(xStream.is())
629 if (mpImpl->pContainer)
630 mpImpl->pContainer->InsertGraphicStream(xStream,mpImpl->aPersistName,mpImpl->aMediaType);
632 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream );
633 if (pResult && bUpdate)
634 mpImpl->bNeedUpdate = false;
636 return pResult;
641 return NULL;
644 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const OUString &rText, OutputDevice *pOut )
646 MapMode aMM( MAP_APPFONT );
647 Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL );
648 vcl::Font aFnt( OUString("Helvetica"), aAppFontSz );
649 aFnt.SetTransparent( true );
650 aFnt.SetColor( Color( COL_LIGHTRED ) );
651 aFnt.SetWeight( WEIGHT_BOLD );
652 aFnt.SetFamily( FAMILY_SWISS );
654 pOut->Push();
655 pOut->SetBackground();
656 pOut->SetFont( aFnt );
658 Point aPt;
660 // Now scale text such that it fits in the rectangle
661 // We start with the default size and decrease 1-AppFont
662 for( sal_uInt16 i = 8; i > 2; i-- )
664 aPt.X() = (rRect.GetWidth() - pOut->GetTextWidth( rText )) / 2;
665 aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2;
667 bool bTiny = false;
668 if( aPt.X() < 0 ) bTiny = true, aPt.X() = 0;
669 if( aPt.Y() < 0 ) bTiny = true, aPt.Y() = 0;
670 if( bTiny )
672 // decrease for small images
673 aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) );
674 pOut->SetFont( aFnt );
676 else
677 break;
680 Bitmap aBmp( SvtResId( BMP_PLUGIN ) );
681 long nHeight = rRect.GetHeight() - pOut->GetTextHeight();
682 long nWidth = rRect.GetWidth();
683 if(nHeight > 0 && nWidth > 0 && aBmp.GetSizePixel().Width() > 0)
685 aPt.Y() = nHeight;
686 Point aP = rRect.TopLeft();
687 Size aBmpSize = aBmp.GetSizePixel();
688 // fit bitmap in
689 if( nHeight * 10 / nWidth
690 > aBmpSize.Height() * 10 / aBmpSize.Width() )
692 // adjust to the width
693 // keep proportions
694 long nH = nWidth * aBmpSize.Height() / aBmpSize.Width();
695 // center
696 aP.Y() += (nHeight - nH) / 2;
697 nHeight = nH;
699 else
701 // adjust to the height
702 // keep proportions
703 long nW = nHeight * aBmpSize.Width() / aBmpSize.Height();
704 // center
705 aP.X() += (nWidth - nW) / 2;
706 nWidth = nW;
709 pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp );
712 pOut->IntersectClipRegion( rRect );
713 aPt += rRect.TopLeft();
714 pOut->DrawText( aPt, rText );
715 pOut->Pop();
718 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut )
720 GDIMetaFile * pMtf = pOut->GetConnectMetaFile();
721 if( pMtf && pMtf->IsRecord() )
722 return;
724 pOut->Push();
725 pOut->SetLineColor( Color( COL_BLACK ) );
727 Size aPixSize = pOut->LogicToPixel( rRect.GetSize() );
728 aPixSize.Width() -= 1;
729 aPixSize.Height() -= 1;
730 Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() );
731 sal_Int32 nMax = aPixSize.Width() + aPixSize.Height();
732 for( sal_Int32 i = 5; i < nMax; i += 5 )
734 Point a1( aPixViewPos ), a2( aPixViewPos );
735 if( i > aPixSize.Width() )
736 a1 += Point( aPixSize.Width(), i - aPixSize.Width() );
737 else
738 a1 += Point( i, 0 );
739 if( i > aPixSize.Height() )
740 a2 += Point( i - aPixSize.Height(), aPixSize.Height() );
741 else
742 a2 += Point( 0, i );
744 pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) );
747 pOut->Pop();
751 bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj )
753 if ( !xEmbObj.is() )
754 return false;
758 if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED )
759 xEmbObj->changeState( embed::EmbedStates::RUNNING );
761 catch (const uno::Exception&)
763 return false;
766 return true;
769 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic,
770 comphelper::EmbeddedObjectContainer& aContainer,
771 const OUString& aName,
772 const OUString& aMediaType )
774 SvMemoryStream aStream;
775 aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
776 if ( rGraphic.ExportNative( aStream ) )
778 aStream.Seek( 0 );
780 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream );
781 aContainer.InsertGraphicStream( xStream, aName, aMediaType );
783 else
784 OSL_FAIL( "Export of graphic is failed!\n" );
787 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream(
788 sal_Int64 nViewAspect,
789 const uno::Reference< embed::XEmbeddedObject >& xObj,
790 OUString* pMediaType )
791 throw()
793 return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType);
796 bool EmbeddedObjectRef::IsChart(const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj)
798 SvGlobalName aObjClsId(xObj->getClassID());
800 SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId
801 || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId
802 || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId
803 || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId)
805 return true;
808 return false;
811 bool EmbeddedObjectRef::IsGLChart(const ::com::sun::star::uno::Reference < ::com::sun::star::embed::XEmbeddedObject >& xObj)
813 static const char* env = getenv("CHART_DUMMY_FACTORY");
814 if (IsChart(xObj))
816 if (env)
817 return true;
819 uno::Reference< chart2::XChartDocument > xChartDoc(xObj->getComponent(), uno::UNO_QUERY);
820 if (!xChartDoc.is())
821 return false;
823 return xChartDoc->isOpenGLChart();
825 return false;
828 void EmbeddedObjectRef::UpdateReplacement()
830 GetReplacement( true );
833 void EmbeddedObjectRef::UpdateReplacementOnDemand()
835 DELETEZ( mpImpl->pGraphic );
836 mpImpl->bNeedUpdate = true;
837 mpImpl->mnGraphicVersion++;
839 if( mpImpl->pContainer )
841 //remove graphic from container thus a new up to date one is requested on save
842 mpImpl->pContainer->RemoveGraphicStream( mpImpl->aPersistName );
846 bool EmbeddedObjectRef::IsChart() const
848 //todo maybe for 3.0:
849 //if the changes work good for chart
850 //we should apply them for all own ole objects
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
855 if (!mpImpl->mxObj.is())
856 return false;
858 return EmbeddedObjectRef::IsChart(mpImpl->mxObj);
861 bool EmbeddedObjectRef::IsGLChart() const
863 if (!mpImpl->mxObj.is())
864 return false;
866 return EmbeddedObjectRef::IsGLChart(mpImpl->mxObj);
869 // MT: Only used for getting accessible attributes, which are not localized
870 OUString EmbeddedObjectRef::GetChartType()
872 OUString Style;
873 if ( mpImpl->mxObj.is() )
875 if ( IsChart() )
877 if ( svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObj ) )
879 uno::Reference< chart2::XChartDocument > xChart( mpImpl->mxObj->getComponent(), uno::UNO_QUERY );
880 if (xChart.is())
882 uno::Reference< chart2::XDiagram > xDiagram( xChart->getFirstDiagram());
883 if( ! xDiagram.is())
884 return OUString();
885 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
886 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems());
887 // IA2 CWS. Unused: int nCoordinateCount = aCooSysSeq.getLength();
888 bool bGetChartType = false;
889 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
891 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
892 uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes());
893 int nDimesionCount = aCooSysSeq[nCooSysIdx]->getDimension();
894 if( nDimesionCount == 3 )
895 Style += "3D ";
896 else
897 Style += "2D ";
898 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
900 OUString strChartType = aChartTypes[nCTIdx]->getChartType();
901 if (strChartType == "com.sun.star.chart2.AreaChartType")
903 Style += "Areas";
904 bGetChartType = true;
906 else if (strChartType == "com.sun.star.chart2.BarChartType")
908 Style += "Bars";
909 bGetChartType = true;
911 else if (strChartType == "com.sun.star.chart2.ColumnChartType")
913 uno::Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY );
914 if( xProp.is())
916 bool bCurrent = false;
917 if( xProp->getPropertyValue( OUString("SwapXAndYAxis") ) >>= bCurrent )
919 if (bCurrent)
920 Style += "Bars";
921 else
922 Style += "Columns";
923 bGetChartType = true;
927 else if (strChartType == "com.sun.star.chart2.LineChartType")
929 Style += "Lines";
930 bGetChartType = true;
932 else if (strChartType == "com.sun.star.chart2.ScatterChartType")
934 Style += "XY Chart";
935 bGetChartType = true;
937 else if (strChartType == "com.sun.star.chart2.PieChartType")
939 Style += "Pies";
940 bGetChartType = true;
942 else if (strChartType == "com.sun.star.chart2.NetChartType")
944 Style += "Radar";
945 bGetChartType = true;
947 else if (strChartType == "com.sun.star.chart2.CandleStickChartType")
949 Style += "Candle Stick Chart";
950 bGetChartType = true;
952 if (bGetChartType)
953 return Style;
960 return Style;
963 // #i104867#
964 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const
966 return mpImpl->mnGraphicVersion;
969 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM )
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
975 mpImpl->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() );
977 uno::Reference<chart2::XDefaultSizeTransmitter> xSizeTransmitter(mpImpl->mxObj, uno::UNO_QUERY);
978 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" );
979 if( xSizeTransmitter.is() )
980 xSizeTransmitter->setDefaultSize( mpImpl->aDefaultSizeForChart_In_100TH_MM );
983 } // namespace svt
985 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */