1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
21 #include <com/sun/star/container/XChild.hpp>
22 #include <com/sun/star/embed/XEmbedPersist.hpp>
23 #include <com/sun/star/embed/XLinkageSupport.hpp>
24 #include <com/sun/star/embed/Aspects.hpp>
25 #include <com/sun/star/embed/EmbedMisc.hpp>
26 #include <com/sun/star/embed/EmbedStates.hpp>
27 #include <com/sun/star/util/XCloseable.hpp>
28 #include <com/sun/star/util/XModifiable.hpp>
29 #include <com/sun/star/document/XEventBroadcaster.hpp>
30 #include <cppuhelper/implbase1.hxx>
32 #include <cppuhelper/implbase2.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <hintids.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/app.hxx>
37 #include <sfx2/linkmgr.hxx>
38 #include <unotools/configitem.hxx>
39 #include <vcl/outdev.hxx>
40 #include <fmtanchr.hxx>
45 #include <section.hxx>
50 #include <comphelper/classids.hxx>
51 #include <vcl/graph.hxx>
52 #include <sot/formats.hxx>
53 #include <unotools/ucbstreamhelper.hxx>
54 #include <vcl/graphicfilter.hxx>
55 #include <comcore.hrc>
59 using namespace com::sun::star::uno
;
60 using namespace com::sun::star
;
63 : private utl::ConfigItem
66 typedef std::deque
<SwOLEObj
*> OleObjects_t
;
67 OleObjects_t m_OleObjects
;
68 sal_Int32 m_nLRU_InitSize
;
69 uno::Sequence
< rtl::OUString
> GetPropertyNames();
74 virtual void Notify( const uno::Sequence
<
75 rtl::OUString
>& aPropertyNames
);
76 virtual void Commit();
79 void InsertObj( SwOLEObj
& rObj
);
80 void RemoveObj( SwOLEObj
& rObj
);
82 void RemovePtr( SwOLEObj
* pObj
)
84 OleObjects_t::iterator
const it
=
85 std::find(m_OleObjects
.begin(), m_OleObjects
.end(), pObj
);
86 if (it
!= m_OleObjects
.end())
88 m_OleObjects
.erase(it
);
93 SwOLELRUCache
* pOLELRU_Cache
= 0;
95 class SwOLEListener_Impl
: public ::cppu::WeakImplHelper1
< embed::XStateChangeListener
>
99 SwOLEListener_Impl( SwOLEObj
* pObj
);
101 virtual void SAL_CALL
changingState( const lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (embed::WrongStateException
, uno::RuntimeException
);
102 virtual void SAL_CALL
stateChanged( const lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (uno::RuntimeException
);
103 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) throw (uno::RuntimeException
);
106 SwOLEListener_Impl::SwOLEListener_Impl( SwOLEObj
* pObj
)
109 if ( mpObj
->IsOleRef() && mpObj
->GetOleRef()->getCurrentState() == embed::EmbedStates::RUNNING
)
111 pOLELRU_Cache
->InsertObj( *mpObj
);
115 void SAL_CALL
SwOLEListener_Impl::changingState( const lang::EventObject
&, ::sal_Int32
, ::sal_Int32
) throw (embed::WrongStateException
, uno::RuntimeException
)
119 void SAL_CALL
SwOLEListener_Impl::stateChanged( const lang::EventObject
&, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (uno::RuntimeException
)
121 if ( mpObj
&& nOldState
== embed::EmbedStates::LOADED
&& nNewState
== embed::EmbedStates::RUNNING
)
124 pOLELRU_Cache
= new SwOLELRUCache
;
125 pOLELRU_Cache
->InsertObj( *mpObj
);
127 else if ( mpObj
&& nNewState
== embed::EmbedStates::LOADED
&& nOldState
== embed::EmbedStates::RUNNING
)
130 pOLELRU_Cache
->RemoveObj( *mpObj
);
134 void SwOLEListener_Impl::Release()
136 if ( mpObj
&& pOLELRU_Cache
)
137 pOLELRU_Cache
->RemoveObj( *mpObj
);
142 void SAL_CALL
SwOLEListener_Impl::disposing( const lang::EventObject
& ) throw (uno::RuntimeException
)
144 if ( mpObj
&& pOLELRU_Cache
)
145 pOLELRU_Cache
->RemoveObj( *mpObj
);
148 // --------------------
150 // --------------------
151 // TODO/LATER: actually SwEmbedObjectLink should be used here, but because different objects are used to control
152 // embedded object different link objects with the same functionality had to be implemented
154 class SwEmbedObjectLink
: public sfx2::SvBaseLink
159 SwEmbedObjectLink(SwOLENode
* pNode
);
160 virtual ~SwEmbedObjectLink();
162 virtual void Closed();
163 virtual ::sfx2::SvBaseLink::UpdateResult
DataChanged(
164 const String
& rMimeType
, const ::com::sun::star::uno::Any
& rValue
);
166 bool Connect() { return GetRealObject() != NULL
; }
169 // -----------------------------------------------------------------------------
171 SwEmbedObjectLink::SwEmbedObjectLink(SwOLENode
* pNode
):
172 ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL
, SOT_FORMATSTR_ID_SVXB
),
175 SetSynchron( sal_False
);
178 // -----------------------------------------------------------------------------
180 SwEmbedObjectLink::~SwEmbedObjectLink()
184 // -----------------------------------------------------------------------------
186 ::sfx2::SvBaseLink::UpdateResult
SwEmbedObjectLink::DataChanged(
187 const String
&, const uno::Any
& )
189 if ( !pOleNode
->UpdateLinkURL_Impl() )
191 // the link URL was not changed
192 uno::Reference
< embed::XEmbeddedObject
> xObject
= pOleNode
->GetOLEObj().GetOleRef();
193 OSL_ENSURE( xObject
.is(), "The object must exist always!\n" );
196 // let the object reload the link
197 // TODO/LATER: reload call could be used for this case
201 sal_Int32 nState
= xObject
->getCurrentState();
202 if ( nState
!= embed::EmbedStates::LOADED
)
204 // in some cases the linked file probably is not locked so it could be changed
205 xObject
->changeState( embed::EmbedStates::LOADED
);
206 xObject
->changeState( nState
);
209 catch ( uno::Exception
& )
215 pOleNode
->GetNewReplacement();
219 // -----------------------------------------------------------------------------
221 void SwEmbedObjectLink::Closed()
223 pOleNode
->BreakFileLink_Impl();
224 SvBaseLink::Closed();
228 // --------------------
230 // --------------------
232 SwOLENode::SwOLENode( const SwNodeIndex
&rWhere
,
233 const svt::EmbeddedObjectRef
& xObj
,
234 SwGrfFmtColl
*pGrfColl
,
235 SwAttrSet
* pAutoAttr
) :
236 SwNoTxtNode( rWhere
, ND_OLENODE
, pGrfColl
, pAutoAttr
),
239 bOLESizeInvalid( sal_False
),
242 aOLEObj
.SetNode( this );
245 SwOLENode::SwOLENode( const SwNodeIndex
&rWhere
,
246 const String
&rString
,
248 SwGrfFmtColl
*pGrfColl
,
249 SwAttrSet
* pAutoAttr
) :
250 SwNoTxtNode( rWhere
, ND_OLENODE
, pGrfColl
, pAutoAttr
),
251 aOLEObj( rString
, nAspect
),
253 bOLESizeInvalid( sal_False
),
256 aOLEObj
.SetNode( this );
259 SwOLENode::~SwOLENode()
261 DisconnectFileLink_Impl();
265 Graphic
* SwOLENode::GetGraphic()
267 if ( aOLEObj
.GetOleRef().is() )
268 return aOLEObj
.xOLERef
.GetGraphic();
272 SwCntntNode
*SwOLENode::SplitCntntNode( const SwPosition
& )
274 // OLE-Objecte vervielfaeltigen ??
275 OSL_FAIL( "OleNode: can't split." );
279 // Laden eines in den Undo-Bereich verschobenen OLE-Objekts
281 sal_Bool
SwOLENode::RestorePersistentData()
283 OSL_ENSURE( aOLEObj
.GetOleRef().is(), "No object to restore!" );
284 if ( aOLEObj
.xOLERef
.is() )
286 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
287 SfxObjectShell
* p
= GetDoc()->GetPersist();
290 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
292 OSL_ENSURE( !this, "warum wird hier eine DocShell angelegt?" );
293 p
= new SwDocShell( GetDoc(), SFX_CREATE_MODE_INTERNAL
);
294 p
->DoInitNew( NULL
);
297 uno::Reference
< container::XChild
> xChild( aOLEObj
.xOLERef
.GetObject(), uno::UNO_QUERY
);
299 xChild
->setParent( p
->GetModel() );
301 OSL_ENSURE( aOLEObj
.aName
.Len(), "No object name!" );
302 ::rtl::OUString aObjName
;
303 if ( !p
->GetEmbeddedObjectContainer().InsertEmbeddedObject( aOLEObj
.xOLERef
.GetObject(), aObjName
) )
306 xChild
->setParent( 0 );
307 OSL_FAIL( "InsertObject failed" );
311 aOLEObj
.aName
= aObjName
;
312 aOLEObj
.xOLERef
.AssignToContainer( &p
->GetEmbeddedObjectContainer(), aObjName
);
313 CheckFileLink_Impl();
320 // OLE object is transported into UNDO area
321 sal_Bool
SwOLENode::SavePersistentData()
323 if( aOLEObj
.xOLERef
.is() )
325 comphelper::EmbeddedObjectContainer
* pCnt
= aOLEObj
.xOLERef
.GetContainer();
327 #if OSL_DEBUG_LEVEL > 0
328 SfxObjectShell
* p
= GetDoc()->GetPersist();
329 OSL_ENSURE( p
, "No document!" );
332 comphelper::EmbeddedObjectContainer
& rCnt
= p
->GetEmbeddedObjectContainer();
333 OSL_ENSURE( !pCnt
|| &rCnt
== pCnt
, "The helper is assigned to unexpected container!\n" );
337 if ( pCnt
&& pCnt
->HasEmbeddedObject( aOLEObj
.aName
) )
339 uno::Reference
< container::XChild
> xChild( aOLEObj
.xOLERef
.GetObject(), uno::UNO_QUERY
);
341 xChild
->setParent( 0 );
343 pCnt
->RemoveEmbeddedObject( aOLEObj
.aName
, sal_False
);
345 // TODO/LATER: aOLEObj.aName has no meaning here, since the undo container contains the object
346 // by different name, in future it might makes sence that the name is transported here.
347 aOLEObj
.xOLERef
.AssignToContainer( 0, aOLEObj
.aName
);
351 aOLEObj
.xOLERef
->changeState( embed::EmbedStates::LOADED
);
353 catch ( uno::Exception
& )
359 DisconnectFileLink_Impl();
365 SwOLENode
* SwNodes::MakeOLENode( const SwNodeIndex
& rWhere
,
366 const svt::EmbeddedObjectRef
& xObj
,
367 SwGrfFmtColl
* pGrfColl
,
368 SwAttrSet
* pAutoAttr
)
370 OSL_ENSURE( pGrfColl
,"SwNodes::MakeOLENode: Formatpointer ist 0." );
373 new SwOLENode( rWhere
, xObj
, pGrfColl
, pAutoAttr
);
375 // set parent if XChild is supported
376 //!! needed to supply Math objects with a valid reference device
377 uno::Reference
< container::XChild
> xChild( pNode
->GetOLEObj().GetObject().GetObject(), UNO_QUERY
);
380 SwDocShell
*pDocSh
= GetDoc()->GetDocShell();
382 xChild
->setParent( pDocSh
->GetModel() );
389 SwOLENode
* SwNodes::MakeOLENode( const SwNodeIndex
& rWhere
,
390 const String
&rName
, sal_Int64 nAspect
, SwGrfFmtColl
* pGrfColl
, SwAttrSet
* pAutoAttr
)
392 OSL_ENSURE( pGrfColl
,"SwNodes::MakeOLENode: Formatpointer ist 0." );
395 new SwOLENode( rWhere
, rName
, nAspect
, pGrfColl
, pAutoAttr
);
397 // set parent if XChild is supported
398 //!! needed to supply Math objects with a valid reference device
399 uno::Reference
< container::XChild
> xChild( pNode
->GetOLEObj().GetObject().GetObject(), UNO_QUERY
);
402 SwDocShell
*pDocSh
= GetDoc()->GetDocShell();
404 xChild
->setParent( pDocSh
->GetModel() );
410 Size
SwOLENode::GetTwipSize() const
412 MapMode
aMapMode( MAP_TWIP
);
413 return ((SwOLENode
*)this)->aOLEObj
.GetObject().GetSize( &aMapMode
);
416 SwCntntNode
* SwOLENode::MakeCopy( SwDoc
* pDoc
, const SwNodeIndex
& rIdx
) const
418 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
419 SfxObjectShell
* pPersistShell
= pDoc
->GetPersist();
422 // TODO/LATER: is EmbeddedObjectContainer not enough?
423 // the created document will be closed by pDoc ( should use SfxObjectShellLock )
424 pPersistShell
= new SwDocShell( pDoc
, SFX_CREATE_MODE_INTERNAL
);
425 pDoc
->SetTmpDocShell( pPersistShell
);
426 pPersistShell
->DoInitNew( NULL
);
429 // Wir hauen das Ding auf SvPersist-Ebene rein
430 // TODO/LATER: check if using the same naming scheme for all apps works here
431 ::rtl::OUString aNewName
/*( Sw3Io::UniqueName( p->GetStorage(), "Obj" ) )*/;
432 SfxObjectShell
* pSrc
= GetDoc()->GetPersist();
434 pPersistShell
->GetEmbeddedObjectContainer().CopyAndGetEmbeddedObject(
435 pSrc
->GetEmbeddedObjectContainer(),
436 pSrc
->GetEmbeddedObjectContainer().GetEmbeddedObject( aOLEObj
.aName
),
439 SwOLENode
* pOLENd
= pDoc
->GetNodes().MakeOLENode( rIdx
, aNewName
, GetAspect(),
440 (SwGrfFmtColl
*)pDoc
->GetDfltGrfFmtColl(),
441 (SwAttrSet
*)GetpSwAttrSet() );
443 pOLENd
->SetChartTblName( GetChartTblName() );
444 pOLENd
->SetTitle( GetTitle() );
445 pOLENd
->SetDescription( GetDescription() );
446 pOLENd
->SetContour( HasContour(), HasAutomaticContour() );
447 pOLENd
->SetAspect( GetAspect() ); // the replacement image must be already copied
449 pOLENd
->SetOLESizeInvalid( sal_True
);
450 pDoc
->SetOLEPrtNotifyPending();
455 sal_Bool
SwOLENode::IsInGlobalDocSection() const
457 // suche den "Body Anchor"
458 sal_uLong nEndExtraIdx
= GetNodes().GetEndOfExtras().GetIndex();
459 const SwNode
* pAnchorNd
= this;
461 SwFrmFmt
* pFlyFmt
= pAnchorNd
->GetFlyFmt();
465 const SwFmtAnchor
& rAnchor
= pFlyFmt
->GetAnchor();
466 if( !rAnchor
.GetCntntAnchor() )
469 pAnchorNd
= &rAnchor
.GetCntntAnchor()->nNode
.GetNode();
470 } while( pAnchorNd
->GetIndex() < nEndExtraIdx
);
472 const SwSectionNode
* pSectNd
= pAnchorNd
->FindSectionNode();
479 pSectNd
= pAnchorNd
->StartOfSectionNode()->FindSectionNode();
482 // in pAnchorNd steht der zuletzt gefundene Section Node. Der muss
483 // jetzt die Bedingung fuers GlobalDoc erfuellen.
484 pSectNd
= (SwSectionNode
*)pAnchorNd
;
485 return FILE_LINK_SECTION
== pSectNd
->GetSection().GetType() &&
486 pSectNd
->GetIndex() > nEndExtraIdx
;
489 sal_Bool
SwOLENode::IsOLEObjectDeleted() const
491 sal_Bool bRet
= sal_False
;
492 if( aOLEObj
.xOLERef
.is() )
494 SfxObjectShell
* p
= GetDoc()->GetPersist();
495 if( p
) // muss da sein
497 return !p
->GetEmbeddedObjectContainer().HasEmbeddedObject( aOLEObj
.aName
);
503 void SwOLENode::GetNewReplacement()
505 if ( aOLEObj
.xOLERef
.is() )
506 aOLEObj
.xOLERef
.UpdateReplacement();
509 sal_Bool
SwOLENode::UpdateLinkURL_Impl()
511 sal_Bool bResult
= sal_False
;
516 GetDoc()->GetLinkManager().GetDisplayNames( mpObjectLink
, 0, &aNewLinkURL
, 0, 0 );
517 if ( !aNewLinkURL
.EqualsIgnoreCaseAscii( maLinkURL
) )
519 if ( !aOLEObj
.xOLERef
.is() )
522 uno::Reference
< embed::XEmbeddedObject
> xObj
= aOLEObj
.xOLERef
.GetObject();
523 uno::Reference
< embed::XCommonEmbedPersist
> xPersObj( xObj
, uno::UNO_QUERY
);
524 OSL_ENSURE( xPersObj
.is(), "The object must exist!\n" );
529 sal_Int32 nCurState
= xObj
->getCurrentState();
530 if ( nCurState
!= embed::EmbedStates::LOADED
)
531 xObj
->changeState( embed::EmbedStates::LOADED
);
533 // TODO/LATER: there should be possible to get current mediadescriptor settings from the object
534 uno::Sequence
< beans::PropertyValue
> aArgs( 1 );
535 aArgs
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
536 aArgs
[0].Value
<<= ::rtl::OUString( aNewLinkURL
);
537 xPersObj
->reload( aArgs
, uno::Sequence
< beans::PropertyValue
>() );
539 maLinkURL
= aNewLinkURL
;
542 if ( nCurState
!= embed::EmbedStates::LOADED
)
543 xObj
->changeState( nCurState
);
545 catch( uno::Exception
& )
551 // TODO/LATER: return the old name to the link manager, is it possible?
559 void SwOLENode::BreakFileLink_Impl()
561 SfxObjectShell
* pPers
= GetDoc()->GetPersist();
565 uno::Reference
< embed::XStorage
> xStorage
= pPers
->GetStorage();
570 uno::Reference
< embed::XLinkageSupport
> xLinkSupport( aOLEObj
.GetOleRef(), uno::UNO_QUERY_THROW
);
571 xLinkSupport
->breakLink( xStorage
, aOLEObj
.GetCurrentPersistName() );
572 DisconnectFileLink_Impl();
573 maLinkURL
= String();
575 catch( uno::Exception
& )
582 void SwOLENode::DisconnectFileLink_Impl()
586 GetDoc()->GetLinkManager().Remove( mpObjectLink
);
591 void SwOLENode::CheckFileLink_Impl()
593 if ( aOLEObj
.xOLERef
.GetObject().is() && !mpObjectLink
)
597 uno::Reference
< embed::XLinkageSupport
> xLinkSupport( aOLEObj
.xOLERef
.GetObject(), uno::UNO_QUERY_THROW
);
598 if ( xLinkSupport
->isLink() )
600 String aLinkURL
= xLinkSupport
->getLinkURL();
601 if ( aLinkURL
.Len() )
603 // this is a file link so the model link manager should handle it
604 mpObjectLink
= new SwEmbedObjectLink( this );
605 maLinkURL
= aLinkURL
;
606 GetDoc()->GetLinkManager().InsertFileLink( *mpObjectLink
, OBJECT_CLIENT_OLE
, aLinkURL
, NULL
, NULL
);
607 mpObjectLink
->Connect();
611 catch( uno::Exception
& )
618 bool SwOLENode::IsChart() const
620 bool bIsChart( false );
622 const uno::Reference
< embed::XEmbeddedObject
> xEmbObj
=
623 const_cast<SwOLEObj
&>(GetOLEObj()).GetOleRef();
626 SvGlobalName
aClassID( xEmbObj
->getClassID() );
627 bIsChart
= SotExchange::IsChart( aClassID
);
633 SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef
& xObj
) :
638 xOLERef
.Lock( sal_True
);
641 pListener
= new SwOLEListener_Impl( this );
642 pListener
->acquire();
643 xObj
->addStateChangeListener( pListener
);
648 SwOLEObj::SwOLEObj( const String
&rString
, sal_Int64 nAspect
) :
653 xOLERef
.Lock( sal_True
);
654 xOLERef
.SetViewAspect( nAspect
);
658 SwOLEObj::~SwOLEObj()
663 xOLERef
->removeStateChangeListener( pListener
);
664 pListener
->Release();
667 if( pOLENd
&& !pOLENd
->GetDoc()->IsInDtor() )
669 // if the model is not currently in destruction it means that this object should be removed from the model
670 comphelper::EmbeddedObjectContainer
* pCnt
= xOLERef
.GetContainer();
672 #if OSL_DEBUG_LEVEL > 0
673 SfxObjectShell
* p
= pOLENd
->GetDoc()->GetPersist();
674 OSL_ENSURE( p
, "No document!" );
677 comphelper::EmbeddedObjectContainer
& rCnt
= p
->GetEmbeddedObjectContainer();
678 OSL_ENSURE( !pCnt
|| &rCnt
== pCnt
, "The helper is assigned to unexpected container!\n" );
682 if ( pCnt
&& pCnt
->HasEmbeddedObject( aName
) )
684 uno::Reference
< container::XChild
> xChild( xOLERef
.GetObject(), uno::UNO_QUERY
);
686 xChild
->setParent( 0 );
688 // not already removed by deleting the object
689 xOLERef
.AssignToContainer( 0, aName
);
691 // unlock object so that object can be closed in RemoveEmbeddedObject
692 // successful closing of the object will automatically clear the reference then
693 xOLERef
.Lock(sal_False
);
695 // Always remove object from conteiner it is connected to
698 pCnt
->RemoveEmbeddedObject( aName
);
700 catch ( uno::Exception
& )
708 // in case the object wasn't closed: release it
709 // in case the object was not in the container: it's still locked, try to close
714 void SwOLEObj::SetNode( SwOLENode
* pNode
)
719 SwDoc
* pDoc
= pNode
->GetDoc();
721 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
722 SfxObjectShell
* p
= pDoc
->GetPersist();
725 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
727 OSL_ENSURE( !this, "warum wird hier eine DocShell angelegt?" );
728 p
= new SwDocShell( pDoc
, SFX_CREATE_MODE_INTERNAL
);
729 p
->DoInitNew( NULL
);
732 ::rtl::OUString aObjName
;
733 uno::Reference
< container::XChild
> xChild( xOLERef
.GetObject(), uno::UNO_QUERY
);
734 if ( xChild
.is() && xChild
->getParent() != p
->GetModel() )
735 // it is possible that the parent was set already
736 xChild
->setParent( p
->GetModel() );
737 if (!p
->GetEmbeddedObjectContainer().InsertEmbeddedObject( xOLERef
.GetObject(), aObjName
) )
739 OSL_FAIL( "InsertObject failed" );
741 xChild
->setParent( 0 );
744 xOLERef
.AssignToContainer( &p
->GetEmbeddedObjectContainer(), aObjName
);
746 ( (SwOLENode
*)pOLENd
)->CheckFileLink_Impl(); // for this notification nonconst access is required
752 sal_Bool
SwOLEObj::IsOleRef() const
757 const uno::Reference
< embed::XEmbeddedObject
> SwOLEObj::GetOleRef()
761 SfxObjectShell
* p
= pOLENd
->GetDoc()->GetPersist();
762 OSL_ENSURE( p
, "kein SvPersist vorhanden" );
764 uno::Reference
< embed::XEmbeddedObject
> xObj
= p
->GetEmbeddedObjectContainer().GetEmbeddedObject( aName
);
765 OSL_ENSURE( !xOLERef
.is(), "rekursiver Aufruf von GetOleRef() ist nicht erlaubt" );
769 //Das Teil konnte nicht geladen werden (wahrsch. Kaputt).
771 SwFrm
*pFrm
= pOLENd
->getLayoutFrm(0);
774 Size
aSz( pFrm
->Frm().SSize() );
775 const MapMode
aSrc ( MAP_TWIP
);
776 const MapMode
aDest( MAP_100TH_MM
);
777 aSz
= OutputDevice::LogicToLogic( aSz
, aSrc
, aDest
);
778 aArea
.SetSize( aSz
);
781 aArea
.SetSize( Size( 5000, 5000 ) );
782 // TODO/LATER: set replacement graphic for dead object
783 // It looks as if it should work even without the object, because the replace will be generated automatically
784 ::rtl::OUString aTmpName
;
785 xObj
= p
->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_DUMMY_CLASSID
).GetByteSequence(), aTmpName
);
789 xOLERef
.Assign( xObj
, xOLERef
.GetViewAspect() );
790 xOLERef
.AssignToContainer( &p
->GetEmbeddedObjectContainer(), aName
);
791 pListener
= new SwOLEListener_Impl( this );
792 pListener
->acquire();
793 xObj
->addStateChangeListener( pListener
);
796 ( (SwOLENode
*)pOLENd
)->CheckFileLink_Impl(); // for this notification nonconst access is required
798 else if ( xOLERef
->getCurrentState() == embed::EmbedStates::RUNNING
)
800 // move object to first position in cache
802 pOLELRU_Cache
= new SwOLELRUCache
;
803 pOLELRU_Cache
->InsertObj( *this );
806 return xOLERef
.GetObject();
809 svt::EmbeddedObjectRef
& SwOLEObj::GetObject()
815 sal_Bool
SwOLEObj::UnloadObject()
817 sal_Bool bRet
= sal_True
;
820 const SwDoc
* pDoc
= pOLENd
->GetDoc();
821 bRet
= UnloadObject( xOLERef
.GetObject(), pDoc
, xOLERef
.GetViewAspect() );
827 sal_Bool
SwOLEObj::UnloadObject( uno::Reference
< embed::XEmbeddedObject
> xObj
, const SwDoc
* pDoc
, sal_Int64 nAspect
)
832 sal_Bool bRet
= sal_True
;
833 sal_Int32 nState
= xObj
.is() ? xObj
->getCurrentState() : embed::EmbedStates::LOADED
;
834 bool bIsActive
= ( nState
!= embed::EmbedStates::LOADED
&& nState
!= embed::EmbedStates::RUNNING
);
835 sal_Int64 nMiscStatus
= xObj
->getStatus( nAspect
);
837 if( nState
!= embed::EmbedStates::LOADED
&& !pDoc
->IsInDtor() && !bIsActive
&&
838 embed::EmbedMisc::MS_EMBED_ALWAYSRUN
!= ( nMiscStatus
& embed::EmbedMisc::MS_EMBED_ALWAYSRUN
) &&
839 embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY
!= ( nMiscStatus
& embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY
) )
841 SfxObjectShell
* p
= pDoc
->GetPersist();
844 if( pDoc
->get(IDocumentSettingAccess::PURGE_OLE
) )
848 uno::Reference
< util::XModifiable
> xMod( xObj
->getComponent(), uno::UNO_QUERY
);
849 if( xMod
.is() && xMod
->isModified() )
851 uno::Reference
< embed::XEmbedPersist
> xPers( xObj
, uno::UNO_QUERY
);
855 OSL_FAIL("Modified object without persistance in cache!");
859 // setting object to loaded state will remove it from cache
860 xObj
->changeState( embed::EmbedStates::LOADED
);
862 catch ( uno::Exception
& )
875 String
SwOLEObj::GetDescription()
878 uno::Reference
< embed::XEmbeddedObject
> xEmbObj
= GetOleRef();
881 SvGlobalName
aClassID( xEmbObj
->getClassID() );
882 if ( SotExchange::IsMath( aClassID
) )
883 aResult
= SW_RESSTR(STR_MATH_FORMULA
);
884 else if ( SotExchange::IsChart( aClassID
) )
885 aResult
= SW_RESSTR(STR_CHART
);
887 aResult
= SW_RESSTR(STR_OLE
);
894 SwOLELRUCache::SwOLELRUCache()
895 : utl::ConfigItem(OUString("Office.Common/Cache"))
896 , m_nLRU_InitSize( 20 )
898 EnableNotification( GetPropertyNames() );
902 uno::Sequence
< rtl::OUString
> SwOLELRUCache::GetPropertyNames()
904 Sequence
< OUString
> aNames( 1 );
905 OUString
* pNames
= aNames
.getArray();
906 pNames
[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("Writer/OLE_Objects"));
910 void SwOLELRUCache::Notify( const uno::Sequence
< rtl::OUString
>& )
915 void SwOLELRUCache::Commit()
919 void SwOLELRUCache::Load()
921 Sequence
< OUString
> aNames( GetPropertyNames() );
922 Sequence
< Any
> aValues
= GetProperties( aNames
);
923 const Any
* pValues
= aValues
.getConstArray();
924 OSL_ENSURE( aValues
.getLength() == aNames
.getLength(), "GetProperties failed" );
925 if( aValues
.getLength() == aNames
.getLength() && pValues
->hasValue() )
931 if (nVal
< m_nLRU_InitSize
)
933 // size of cache has been changed
934 sal_Int32 nCount
= m_OleObjects
.size();
935 sal_Int32 nPos
= nCount
;
937 // try to remove the last entries until new maximum size is reached
938 while( nCount
> nVal
)
940 SwOLEObj
*const pObj
= m_OleObjects
[ --nPos
];
941 if ( pObj
->UnloadObject() )
949 m_nLRU_InitSize
= nVal
;
953 void SwOLELRUCache::InsertObj( SwOLEObj
& rObj
)
955 SwOLEObj
* pObj
= &rObj
;
956 OleObjects_t::iterator it
=
957 std::find(m_OleObjects
.begin(), m_OleObjects
.end(), pObj
);
958 if (it
!= m_OleObjects
.end() && it
!= m_OleObjects
.begin())
960 // object in cache but is currently not the first in cache
961 m_OleObjects
.erase(it
);
962 it
= m_OleObjects
.end();
964 if (it
== m_OleObjects
.end())
966 m_OleObjects
.push_front( pObj
);
968 // try to remove objects if necessary
969 // (of course not the freshly inserted one at nPos=0)
970 sal_Int32 nCount
= m_OleObjects
.size();
971 sal_Int32 nPos
= nCount
-1;
972 while (nPos
&& nCount
> m_nLRU_InitSize
)
974 pObj
= m_OleObjects
[ nPos
-- ];
975 if ( pObj
->UnloadObject() )
981 void SwOLELRUCache::RemoveObj( SwOLEObj
& rObj
)
983 OleObjects_t::iterator
const it
=
984 std::find(m_OleObjects
.begin(), m_OleObjects
.end(), &rObj
);
985 if (it
!= m_OleObjects
.end())
987 m_OleObjects
.erase(it
);
989 if (m_OleObjects
.empty())
991 DELETEZ( pOLELRU_Cache
);
995 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */