/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include //#include #include #include #include #include #include using namespace ::com::sun::star::uno; namespace sfx2 { TYPEINIT0( SvLinkSource ) /************** class SvLinkSourceTimer *********************************/ class SvLinkSourceTimer : public Timer { SvLinkSource * pOwner; virtual void Timeout(); public: SvLinkSourceTimer( SvLinkSource * pOwn ); }; SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn ) : pOwner( pOwn ) { } void SvLinkSourceTimer::Timeout() { // sicher gegen zerstoeren im Handler SvLinkSourceRef aAdv( pOwner ); pOwner->SendDataChanged(); } static void StartTimer( SvLinkSourceTimer ** ppTimer, SvLinkSource * pOwner, sal_uIntPtr nTimeout ) { if( !*ppTimer ) { *ppTimer = new SvLinkSourceTimer( pOwner ); (*ppTimer)->SetTimeout( nTimeout ); (*ppTimer)->Start(); } } struct SvLinkSource_Entry_Impl { SvBaseLinkRef xSink; String aDataMimeType; sal_uInt16 nAdviseModes; sal_Bool bIsDataSink; SvLinkSource_Entry_Impl( SvBaseLink* pLink, const String& rMimeType, sal_uInt16 nAdvMode ) : xSink( pLink ), aDataMimeType( rMimeType ), nAdviseModes( nAdvMode ), bIsDataSink( sal_True ) {} SvLinkSource_Entry_Impl( SvBaseLink* pLink ) : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( sal_False ) {} ~SvLinkSource_Entry_Impl(); }; SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl() { } typedef SvLinkSource_Entry_Impl* SvLinkSource_Entry_ImplPtr; SV_DECL_PTRARR_DEL( SvLinkSource_Array_Impl, SvLinkSource_Entry_ImplPtr, 4, 4 ) SV_IMPL_PTRARR( SvLinkSource_Array_Impl, SvLinkSource_Entry_ImplPtr ); class SvLinkSource_EntryIter_Impl { SvLinkSource_Array_Impl aArr; const SvLinkSource_Array_Impl& rOrigArr; sal_uInt16 nPos; public: SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr ); ~SvLinkSource_EntryIter_Impl(); SvLinkSource_Entry_Impl* Curr() { return nPos < aArr.Count() ? aArr[ nPos ] : 0; } SvLinkSource_Entry_Impl* Next(); sal_Bool IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry ); }; SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr ) : rOrigArr( rArr ), nPos( 0 ) { aArr.Insert( &rArr, 0 ); } SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl() { aArr.Remove( 0, aArr.Count() ); } sal_Bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry ) { return ( nPos < aArr.Count() && aArr[nPos] == pEntry && USHRT_MAX != rOrigArr.GetPos( pEntry ) ); } SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next() { SvLinkSource_Entry_ImplPtr pRet = 0; if( nPos + 1 < aArr.Count() ) { ++nPos; if( rOrigArr.Count() == aArr.Count() && rOrigArr[ nPos ] == aArr[ nPos ] ) pRet = aArr[ nPos ]; else { // then we must search the current (or the next) in the orig do { pRet = aArr[ nPos ]; if( USHRT_MAX != rOrigArr.GetPos( pRet )) break; pRet = 0; ++nPos; } while( nPos < aArr.Count() ); if( nPos >= aArr.Count() ) pRet = 0; } } return pRet; } struct SvLinkSource_Impl { SvLinkSource_Array_Impl aArr; String aDataMimeType; SvLinkSourceTimer * pTimer; sal_uIntPtr nTimeout; com::sun::star::uno::Reference m_xInputStreamToLoadFrom; sal_Bool m_bIsReadOnly; SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {} ~SvLinkSource_Impl(); void Closed(); }; SvLinkSource_Impl::~SvLinkSource_Impl() { delete pTimer; } SvLinkSource::SvLinkSource() : pImpl( new SvLinkSource_Impl ) { } SvLinkSource::~SvLinkSource() { delete pImpl; } SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom() { return StreamToLoadFrom( pImpl->m_xInputStreamToLoadFrom, pImpl->m_bIsReadOnly); } void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference& xInputStream,sal_Bool bIsReadOnly ) { pImpl->m_xInputStreamToLoadFrom = xInputStream; pImpl->m_bIsReadOnly = bIsReadOnly; } // --> OD 2008-06-18 #i88291# void SvLinkSource::clearStreamToLoadFrom() { pImpl->m_xInputStreamToLoadFrom.clear(); } // <-- void SvLinkSource::Closed() { SvLinkSource_EntryIter_Impl aIter( pImpl->aArr ); for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() ) if( !p->bIsDataSink ) p->xSink->Closed(); } sal_uIntPtr SvLinkSource::GetUpdateTimeout() const { return pImpl->nTimeout; } void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout ) { pImpl->nTimeout = nTimeout; if( pImpl->pTimer ) pImpl->pTimer->SetTimeout( nTimeout ); } void SvLinkSource::SendDataChanged() { SvLinkSource_EntryIter_Impl aIter( pImpl->aArr ); for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() ) { if( p->bIsDataSink ) { String sDataMimeType( pImpl->aDataMimeType ); if( !sDataMimeType.Len() ) sDataMimeType = p->aDataMimeType; Any aVal; if( ( p->nAdviseModes & ADVISEMODE_NODATA ) || GetData( aVal, sDataMimeType, sal_True ) ) { p->xSink->DataChanged( sDataMimeType, aVal ); if ( !aIter.IsValidCurrValue( p ) ) continue; if( p->nAdviseModes & ADVISEMODE_ONLYONCE ) { sal_uInt16 nFndPos = pImpl->aArr.GetPos( p ); if( USHRT_MAX != nFndPos ) pImpl->aArr.DeleteAndDestroy( nFndPos ); } } } } if( pImpl->pTimer ) { delete pImpl->pTimer; pImpl->pTimer = NULL; } pImpl->aDataMimeType.Erase(); } void SvLinkSource::NotifyDataChanged() { if( pImpl->nTimeout ) StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // Timeout neu else { SvLinkSource_EntryIter_Impl aIter( pImpl->aArr ); for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() ) if( p->bIsDataSink ) { Any aVal; if( ( p->nAdviseModes & ADVISEMODE_NODATA ) || GetData( aVal, p->aDataMimeType, sal_True ) ) { p->xSink->DataChanged( p->aDataMimeType, aVal ); if ( !aIter.IsValidCurrValue( p ) ) continue; if( p->nAdviseModes & ADVISEMODE_ONLYONCE ) { sal_uInt16 nFndPos = pImpl->aArr.GetPos( p ); if( USHRT_MAX != nFndPos ) pImpl->aArr.DeleteAndDestroy( nFndPos ); } } } if( pImpl->pTimer ) { delete pImpl->pTimer; pImpl->pTimer = NULL; } } } // notify the sink, the mime type is not // a selection criterion void SvLinkSource::DataChanged( const String & rMimeType, const ::com::sun::star::uno::Any & rVal ) { if( pImpl->nTimeout && !rVal.hasValue() ) { // nur wenn keine Daten mitgegeben wurden // fire all data to the sink, independent of the requested format pImpl->aDataMimeType = rMimeType; StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // Timeout neu } else { SvLinkSource_EntryIter_Impl aIter( pImpl->aArr ); for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() ) { if( p->bIsDataSink ) { p->xSink->DataChanged( rMimeType, rVal ); if ( !aIter.IsValidCurrValue( p ) ) continue; if( p->nAdviseModes & ADVISEMODE_ONLYONCE ) { sal_uInt16 nFndPos = pImpl->aArr.GetPos( p ); if( USHRT_MAX != nFndPos ) pImpl->aArr.DeleteAndDestroy( nFndPos ); } } } if( pImpl->pTimer ) { delete pImpl->pTimer; pImpl->pTimer = NULL; } } } // only one link is correct void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const String& rMimeType, sal_uInt16 nAdviseModes ) { SvLinkSource_Entry_ImplPtr pNew = new SvLinkSource_Entry_Impl( pLink, rMimeType, nAdviseModes ); pImpl->aArr.Insert( pNew, pImpl->aArr.Count() ); } void SvLinkSource::RemoveAllDataAdvise( SvBaseLink * pLink ) { SvLinkSource_EntryIter_Impl aIter( pImpl->aArr ); for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() ) if( p->bIsDataSink && &p->xSink == pLink ) { sal_uInt16 nFndPos = pImpl->aArr.GetPos( p ); if( USHRT_MAX != nFndPos ) pImpl->aArr.DeleteAndDestroy( nFndPos ); } } // only one link is correct void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink ) { SvLinkSource_Entry_ImplPtr pNew = new SvLinkSource_Entry_Impl( pLink ); pImpl->aArr.Insert( pNew, pImpl->aArr.Count() ); } void SvLinkSource::RemoveConnectAdvise( SvBaseLink * pLink ) { SvLinkSource_EntryIter_Impl aIter( pImpl->aArr ); for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() ) if( !p->bIsDataSink && &p->xSink == pLink ) { sal_uInt16 nFndPos = pImpl->aArr.GetPos( p ); if( USHRT_MAX != nFndPos ) pImpl->aArr.DeleteAndDestroy( nFndPos ); } } sal_Bool SvLinkSource::HasDataLinks( const SvBaseLink* pLink ) const { sal_Bool bRet = sal_False; const SvLinkSource_Entry_Impl* p; for( sal_uInt16 n = 0, nEnd = pImpl->aArr.Count(); n < nEnd; ++n ) if( ( p = pImpl->aArr[ n ] )->bIsDataSink && ( !pLink || &p->xSink == pLink ) ) { bRet = sal_True; break; } return bRet; } // sal_True => waitinmg for data sal_Bool SvLinkSource::IsPending() const { return sal_False; } // sal_True => data complete loaded sal_Bool SvLinkSource::IsDataComplete() const { return sal_True; } sal_Bool SvLinkSource::Connect( SvBaseLink* ) { return sal_True; } sal_Bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const String &, sal_Bool ) { return sal_False; } void SvLinkSource::Edit( Window *, SvBaseLink *, const Link& ) { } }