Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / sw / source / core / ole / ndole.cxx
blob71775aa338539ce89fdebf3a65e145160a44be6e
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 .
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>
41 #include <frmfmt.hxx>
42 #include <doc.hxx>
43 #include <docsh.hxx>
44 #include <pam.hxx>
45 #include <section.hxx>
46 #include <cntfrm.hxx>
47 #include <frmatr.hxx>
48 #include <ndole.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>
57 using rtl::OUString;
58 using namespace utl;
59 using namespace com::sun::star::uno;
60 using namespace com::sun::star;
62 class SwOLELRUCache
63 : private utl::ConfigItem
65 private:
66 typedef std::deque<SwOLEObj *> OleObjects_t;
67 OleObjects_t m_OleObjects;
68 sal_Int32 m_nLRU_InitSize;
69 uno::Sequence< rtl::OUString > GetPropertyNames();
71 public:
72 SwOLELRUCache();
74 virtual void Notify( const uno::Sequence<
75 rtl::OUString>& aPropertyNames );
76 virtual void Commit();
77 void Load();
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 >
97 SwOLEObj* mpObj;
98 public:
99 SwOLEListener_Impl( SwOLEObj* pObj );
100 void Release();
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 )
107 : mpObj( 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 )
123 if( !pOLELRU_Cache )
124 pOLELRU_Cache = new SwOLELRUCache;
125 pOLELRU_Cache->InsertObj( *mpObj );
127 else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING )
129 if ( pOLELRU_Cache )
130 pOLELRU_Cache->RemoveObj( *mpObj );
134 void SwOLEListener_Impl::Release()
136 if ( mpObj && pOLELRU_Cache )
137 pOLELRU_Cache->RemoveObj( *mpObj );
138 mpObj=0;
139 release();
142 void SAL_CALL SwOLEListener_Impl::disposing( const lang::EventObject& ) throw (uno::RuntimeException)
144 if ( mpObj && pOLELRU_Cache )
145 pOLELRU_Cache->RemoveObj( *mpObj );
148 // --------------------
149 // SwEmbedObjectLink
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
156 SwOLENode* pOleNode;
158 public:
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 ),
173 pOleNode(pNode)
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" );
194 if ( xObject.is() )
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();
216 return SUCCESS;
219 // -----------------------------------------------------------------------------
221 void SwEmbedObjectLink::Closed()
223 pOleNode->BreakFileLink_Impl();
224 SvBaseLink::Closed();
228 // --------------------
229 // SwOLENode
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 ),
237 aOLEObj( xObj ),
238 pGraphic(0),
239 bOLESizeInvalid( sal_False ),
240 mpObjectLink( NULL )
242 aOLEObj.SetNode( this );
245 SwOLENode::SwOLENode( const SwNodeIndex &rWhere,
246 const String &rString,
247 sal_Int64 nAspect,
248 SwGrfFmtColl *pGrfColl,
249 SwAttrSet* pAutoAttr ) :
250 SwNoTxtNode( rWhere, ND_OLENODE, pGrfColl, pAutoAttr ),
251 aOLEObj( rString, nAspect ),
252 pGraphic(0),
253 bOLESizeInvalid( sal_False ),
254 mpObjectLink( NULL )
256 aOLEObj.SetNode( this );
259 SwOLENode::~SwOLENode()
261 DisconnectFileLink_Impl();
262 delete pGraphic;
265 Graphic* SwOLENode::GetGraphic()
267 if ( aOLEObj.GetOleRef().is() )
268 return aOLEObj.xOLERef.GetGraphic();
269 return pGraphic;
272 SwCntntNode *SwOLENode::SplitCntntNode( const SwPosition & )
274 // OLE-Objecte vervielfaeltigen ??
275 OSL_FAIL( "OleNode: can't split." );
276 return this;
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();
288 if( !p )
290 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
291 // diesem Dokument?
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 );
298 if ( xChild.is() )
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 ) )
305 if ( xChild.is() )
306 xChild->setParent( 0 );
307 OSL_FAIL( "InsertObject failed" );
309 else
311 aOLEObj.aName = aObjName;
312 aOLEObj.xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aObjName );
313 CheckFileLink_Impl();
317 return sal_True;
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!" );
330 if( p )
332 comphelper::EmbeddedObjectContainer& rCnt = p->GetEmbeddedObjectContainer();
333 OSL_ENSURE( !pCnt || &rCnt == pCnt, "The helper is assigned to unexpected container!\n" );
335 #endif
337 if ( pCnt && pCnt->HasEmbeddedObject( aOLEObj.aName ) )
339 uno::Reference < container::XChild > xChild( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY );
340 if ( xChild.is() )
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 );
350 // "unload" object
351 aOLEObj.xOLERef->changeState( embed::EmbedStates::LOADED );
353 catch ( uno::Exception& )
359 DisconnectFileLink_Impl();
361 return sal_True;
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." );
372 SwOLENode *pNode =
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 );
378 if (xChild.is())
380 SwDocShell *pDocSh = GetDoc()->GetDocShell();
381 if (pDocSh)
382 xChild->setParent( pDocSh->GetModel() );
385 return pNode;
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." );
394 SwOLENode *pNode =
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 );
400 if (xChild.is())
402 SwDocShell *pDocSh= GetDoc()->GetDocShell();
403 if (pDocSh)
404 xChild->setParent( pDocSh->GetModel() );
407 return pNode;
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();
420 if( !pPersistShell )
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 ),
437 aNewName );
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();
452 return pOLENd;
455 sal_Bool SwOLENode::IsInGlobalDocSection() const
457 // suche den "Body Anchor"
458 sal_uLong nEndExtraIdx = GetNodes().GetEndOfExtras().GetIndex();
459 const SwNode* pAnchorNd = this;
460 do {
461 SwFrmFmt* pFlyFmt = pAnchorNd->GetFlyFmt();
462 if( !pFlyFmt )
463 return sal_False;
465 const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
466 if( !rAnchor.GetCntntAnchor() )
467 return sal_False;
469 pAnchorNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
470 } while( pAnchorNd->GetIndex() < nEndExtraIdx );
472 const SwSectionNode* pSectNd = pAnchorNd->FindSectionNode();
473 if( !pSectNd )
474 return sal_False;
476 while( pSectNd )
478 pAnchorNd = pSectNd;
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 );
500 return bRet;
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;
513 if ( mpObjectLink )
515 String aNewLinkURL;
516 GetDoc()->GetLinkManager().GetDisplayNames( mpObjectLink, 0, &aNewLinkURL, 0, 0 );
517 if ( !aNewLinkURL.EqualsIgnoreCaseAscii( maLinkURL ) )
519 if ( !aOLEObj.xOLERef.is() )
520 aOLEObj.GetOleRef();
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" );
525 if ( xPersObj.is() )
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;
540 bResult = sal_True;
542 if ( nCurState != embed::EmbedStates::LOADED )
543 xObj->changeState( nCurState );
545 catch( uno::Exception& )
549 if ( !bResult )
551 // TODO/LATER: return the old name to the link manager, is it possible?
556 return bResult;
559 void SwOLENode::BreakFileLink_Impl()
561 SfxObjectShell* pPers = GetDoc()->GetPersist();
563 if ( pPers )
565 uno::Reference< embed::XStorage > xStorage = pPers->GetStorage();
566 if ( xStorage.is() )
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()
584 if ( mpObjectLink )
586 GetDoc()->GetLinkManager().Remove( mpObjectLink );
587 mpObjectLink = NULL;
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& )
617 // #i99665#
618 bool SwOLENode::IsChart() const
620 bool bIsChart( false );
622 const uno::Reference< embed::XEmbeddedObject > xEmbObj =
623 const_cast<SwOLEObj&>(GetOLEObj()).GetOleRef();
624 if ( xEmbObj.is() )
626 SvGlobalName aClassID( xEmbObj->getClassID() );
627 bIsChart = SotExchange::IsChart( aClassID );
630 return bIsChart;
633 SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
634 pOLENd( 0 ),
635 pListener( 0 ),
636 xOLERef( xObj )
638 xOLERef.Lock( sal_True );
639 if ( xObj.is() )
641 pListener = new SwOLEListener_Impl( this );
642 pListener->acquire();
643 xObj->addStateChangeListener( pListener );
648 SwOLEObj::SwOLEObj( const String &rString, sal_Int64 nAspect ) :
649 pOLENd( 0 ),
650 pListener( 0 ),
651 aName( rString )
653 xOLERef.Lock( sal_True );
654 xOLERef.SetViewAspect( nAspect );
658 SwOLEObj::~SwOLEObj()
660 if( pListener )
662 if ( xOLERef.is() )
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!" );
675 if( p )
677 comphelper::EmbeddedObjectContainer& rCnt = p->GetEmbeddedObjectContainer();
678 OSL_ENSURE( !pCnt || &rCnt == pCnt, "The helper is assigned to unexpected container!\n" );
680 #endif
682 if ( pCnt && pCnt->HasEmbeddedObject( aName ) )
684 uno::Reference < container::XChild > xChild( xOLERef.GetObject(), uno::UNO_QUERY );
685 if ( xChild.is() )
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& )
707 if ( xOLERef.is() )
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
710 xOLERef.Clear();
714 void SwOLEObj::SetNode( SwOLENode* pNode )
716 pOLENd = pNode;
717 if ( !aName.Len() )
719 SwDoc* pDoc = pNode->GetDoc();
721 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
722 SfxObjectShell* p = pDoc->GetPersist();
723 if( !p )
725 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
726 // diesem Dokument?
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" );
740 if ( xChild.is() )
741 xChild->setParent( 0 );
743 else
744 xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aObjName );
746 ( (SwOLENode*)pOLENd )->CheckFileLink_Impl(); // for this notification nonconst access is required
748 aName = aObjName;
752 sal_Bool SwOLEObj::IsOleRef() const
754 return xOLERef.is();
757 const uno::Reference < embed::XEmbeddedObject > SwOLEObj::GetOleRef()
759 if( !xOLERef.is() )
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" );
767 if ( !xObj.is() )
769 //Das Teil konnte nicht geladen werden (wahrsch. Kaputt).
770 Rectangle aArea;
771 SwFrm *pFrm = pOLENd->getLayoutFrm(0);
772 if ( pFrm )
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 );
780 else
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 );
787 // else
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
801 if( !pOLELRU_Cache )
802 pOLELRU_Cache = new SwOLELRUCache;
803 pOLELRU_Cache->InsertObj( *this );
806 return xOLERef.GetObject();
809 svt::EmbeddedObjectRef& SwOLEObj::GetObject()
811 GetOleRef();
812 return xOLERef;
815 sal_Bool SwOLEObj::UnloadObject()
817 sal_Bool bRet = sal_True;
818 if ( pOLENd )
820 const SwDoc* pDoc = pOLENd->GetDoc();
821 bRet = UnloadObject( xOLERef.GetObject(), pDoc, xOLERef.GetViewAspect() );
824 return bRet;
827 sal_Bool SwOLEObj::UnloadObject( uno::Reference< embed::XEmbeddedObject > xObj, const SwDoc* pDoc, sal_Int64 nAspect )
829 if ( !pDoc )
830 return sal_False;
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();
842 if( p )
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 );
852 if ( xPers.is() )
853 xPers->storeOwn();
854 else {
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& )
864 bRet = sal_False;
867 else
868 bRet = sal_False;
872 return bRet;
875 String SwOLEObj::GetDescription()
877 String aResult;
878 uno::Reference< embed::XEmbeddedObject > xEmbObj = GetOleRef();
879 if ( xEmbObj.is() )
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);
886 else
887 aResult = SW_RESSTR(STR_OLE);
890 return aResult;
894 SwOLELRUCache::SwOLELRUCache()
895 : utl::ConfigItem(OUString("Office.Common/Cache"))
896 , m_nLRU_InitSize( 20 )
898 EnableNotification( GetPropertyNames() );
899 Load();
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"));
907 return aNames;
910 void SwOLELRUCache::Notify( const uno::Sequence< rtl::OUString>& )
912 Load();
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() )
927 sal_Int32 nVal = 0;
928 *pValues >>= nVal;
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() )
942 nCount--;
943 if ( !nPos )
944 break;
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() )
976 nCount--;
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: */