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 .
21 #include <sfx2/linksrc.hxx>
22 #include <sfx2/lnkbase.hxx>
23 #include <com/sun/star/uno/Any.hxx>
24 #include <com/sun/star/uno/Sequence.hxx>
26 #include <vcl/timer.hxx>
31 using namespace ::com::sun::star::uno
;
36 TYPEINIT0( SvLinkSource
)
38 class SvLinkSourceTimer
: public Timer
40 SvLinkSource
* pOwner
;
41 virtual void Invoke() SAL_OVERRIDE
;
43 SvLinkSourceTimer( SvLinkSource
* pOwn
);
46 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource
* pOwn
)
51 void SvLinkSourceTimer::Invoke()
53 // Secure against being destroyed in Handler
54 SvLinkSourceRef
aAdv( pOwner
);
55 pOwner
->SendDataChanged();
58 static void StartTimer( SvLinkSourceTimer
** ppTimer
, SvLinkSource
* pOwner
,
59 sal_uIntPtr nTimeout
)
63 *ppTimer
= new SvLinkSourceTimer( pOwner
);
64 (*ppTimer
)->SetTimeout( nTimeout
);
70 struct SvLinkSource_Entry_Impl
73 OUString aDataMimeType
;
74 sal_uInt16 nAdviseModes
;
77 SvLinkSource_Entry_Impl( SvBaseLink
* pLink
, const OUString
& rMimeType
,
79 : xSink( pLink
), aDataMimeType( rMimeType
),
80 nAdviseModes( nAdvMode
), bIsDataSink( true )
83 SvLinkSource_Entry_Impl( SvBaseLink
* pLink
)
84 : xSink( pLink
), nAdviseModes( 0 ), bIsDataSink( false )
87 ~SvLinkSource_Entry_Impl();
90 SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
94 class SvLinkSource_Array_Impl
97 std::vector
<SvLinkSource_Entry_Impl
*> mvData
;
100 SvLinkSource_Array_Impl() : mvData() {}
102 size_t size() const { return mvData
.size(); }
103 SvLinkSource_Entry_Impl
*operator[](size_t idx
) const { return mvData
[idx
]; }
104 std::vector
<SvLinkSource_Entry_Impl
*>::const_iterator
cbegin() const { return mvData
.cbegin(); }
105 std::vector
<SvLinkSource_Entry_Impl
*>::const_iterator
cend() const { return mvData
.cend(); }
106 void clear() { mvData
.clear(); }
107 void push_back(SvLinkSource_Entry_Impl
* rData
) { mvData
.push_back(rData
); }
109 void DeleteAndDestroy(SvLinkSource_Entry_Impl
* p
)
111 std::vector
<SvLinkSource_Entry_Impl
*>::iterator it
= std::find(mvData
.begin(), mvData
.end(), p
);
112 if (it
!= mvData
.end())
119 ~SvLinkSource_Array_Impl()
121 for(std::vector
<SvLinkSource_Entry_Impl
*>::const_iterator it
= mvData
.begin(); it
!= mvData
.end(); ++it
)
126 class SvLinkSource_EntryIter_Impl
128 SvLinkSource_Array_Impl aArr
;
129 const SvLinkSource_Array_Impl
& rOrigArr
;
132 SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl
& rArr
);
133 ~SvLinkSource_EntryIter_Impl();
134 SvLinkSource_Entry_Impl
* Curr()
135 { return nPos
< aArr
.size() ? aArr
[ nPos
] : 0; }
136 SvLinkSource_Entry_Impl
* Next();
137 bool IsValidCurrValue( SvLinkSource_Entry_Impl
* pEntry
);
140 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
141 const SvLinkSource_Array_Impl
& rArr
)
142 : aArr( rArr
), rOrigArr( rArr
), nPos( 0 )
145 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
150 bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl
* pEntry
)
152 return ( nPos
< aArr
.size() && aArr
[nPos
] == pEntry
153 && std::find( rOrigArr
.cbegin(), rOrigArr
.cend(), pEntry
) != rOrigArr
.cend() );
156 SvLinkSource_Entry_Impl
* SvLinkSource_EntryIter_Impl::Next()
158 SvLinkSource_Entry_Impl
* pRet
= 0;
159 if( nPos
+ 1 < (sal_uInt16
)aArr
.size() )
162 if( rOrigArr
.size() == aArr
.size() &&
163 rOrigArr
[ nPos
] == aArr
[ nPos
] )
167 // then we must search the current (or the next) in the orig
170 if( std::find(rOrigArr
.cbegin(), rOrigArr
.cend(), pRet
) != rOrigArr
.cend() )
174 } while( nPos
< aArr
.size() );
176 if( nPos
>= aArr
.size() )
183 struct SvLinkSource_Impl
185 SvLinkSource_Array_Impl aArr
;
186 OUString aDataMimeType
;
187 SvLinkSourceTimer
* pTimer
;
188 sal_uIntPtr nTimeout
;
189 css::uno::Reference
<css::io::XInputStream
>
190 m_xInputStreamToLoadFrom
;
196 , m_bIsReadOnly(false)
199 ~SvLinkSource_Impl();
202 SvLinkSource_Impl::~SvLinkSource_Impl()
207 SvLinkSource::SvLinkSource()
208 : pImpl( new SvLinkSource_Impl
)
212 SvLinkSource::~SvLinkSource()
218 SvLinkSource::StreamToLoadFrom
SvLinkSource::getStreamToLoadFrom()
220 return StreamToLoadFrom(
221 pImpl
->m_xInputStreamToLoadFrom
,
222 pImpl
->m_bIsReadOnly
);
225 void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference
<com::sun::star::io::XInputStream
>& xInputStream
, bool bIsReadOnly
)
227 pImpl
->m_xInputStreamToLoadFrom
= xInputStream
;
228 pImpl
->m_bIsReadOnly
= bIsReadOnly
;
232 void SvLinkSource::clearStreamToLoadFrom()
234 pImpl
->m_xInputStreamToLoadFrom
.clear();
237 void SvLinkSource::Closed()
239 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
240 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
241 if( !p
->bIsDataSink
)
245 sal_uIntPtr
SvLinkSource::GetUpdateTimeout() const
247 return pImpl
->nTimeout
;
250 void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout
)
252 pImpl
->nTimeout
= nTimeout
;
254 pImpl
->pTimer
->SetTimeout( nTimeout
);
257 void SvLinkSource::SendDataChanged()
259 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
260 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
264 OUString
sDataMimeType( pImpl
->aDataMimeType
);
265 if( sDataMimeType
.isEmpty() )
266 sDataMimeType
= p
->aDataMimeType
;
269 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
270 GetData( aVal
, sDataMimeType
, true ) )
272 p
->xSink
->DataChanged( sDataMimeType
, aVal
);
274 if ( !aIter
.IsValidCurrValue( p
) )
277 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
279 pImpl
->aArr
.DeleteAndDestroy( p
);
287 delete pImpl
->pTimer
;
288 pImpl
->pTimer
= NULL
;
290 pImpl
->aDataMimeType
.clear();
293 void SvLinkSource::NotifyDataChanged()
295 if( pImpl
->nTimeout
)
296 StartTimer( &pImpl
->pTimer
, this, pImpl
->nTimeout
); // New timeout
299 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
300 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
304 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
305 GetData( aVal
, p
->aDataMimeType
, true ) )
307 p
->xSink
->DataChanged( p
->aDataMimeType
, aVal
);
309 if ( !aIter
.IsValidCurrValue( p
) )
312 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
314 pImpl
->aArr
.DeleteAndDestroy( p
);
321 delete pImpl
->pTimer
;
322 pImpl
->pTimer
= NULL
;
327 // notify the sink, the mime type is not
328 // a selection criterion
329 void SvLinkSource::DataChanged( const OUString
& rMimeType
,
330 const ::com::sun::star::uno::Any
& rVal
)
332 if( pImpl
->nTimeout
&& !rVal
.hasValue() )
333 { // only when no data was included
334 // fire all data to the sink, independent of the requested format
335 pImpl
->aDataMimeType
= rMimeType
;
336 StartTimer( &pImpl
->pTimer
, this, pImpl
->nTimeout
); // New timeout
340 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
341 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
345 p
->xSink
->DataChanged( rMimeType
, rVal
);
347 if ( !aIter
.IsValidCurrValue( p
) )
350 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
352 pImpl
->aArr
.DeleteAndDestroy( p
);
359 delete pImpl
->pTimer
;
360 pImpl
->pTimer
= NULL
;
366 // only one link is correct
367 void SvLinkSource::AddDataAdvise( SvBaseLink
* pLink
, const OUString
& rMimeType
,
368 sal_uInt16 nAdviseModes
)
370 SvLinkSource_Entry_Impl
* pNew
= new SvLinkSource_Entry_Impl(
371 pLink
, rMimeType
, nAdviseModes
);
372 pImpl
->aArr
.push_back( pNew
);
375 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink
* pLink
)
377 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
378 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
379 if( p
->bIsDataSink
&& &p
->xSink
== pLink
)
381 pImpl
->aArr
.DeleteAndDestroy( p
);
385 // only one link is correct
386 void SvLinkSource::AddConnectAdvise( SvBaseLink
* pLink
)
388 SvLinkSource_Entry_Impl
* pNew
= new SvLinkSource_Entry_Impl( pLink
);
389 pImpl
->aArr
.push_back( pNew
);
392 void SvLinkSource::RemoveConnectAdvise( SvBaseLink
* pLink
)
394 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
395 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
396 if( !p
->bIsDataSink
&& &p
->xSink
== pLink
)
398 pImpl
->aArr
.DeleteAndDestroy( p
);
402 bool SvLinkSource::HasDataLinks( const SvBaseLink
* pLink
) const
405 const SvLinkSource_Entry_Impl
* p
;
406 for( sal_uInt16 n
= 0, nEnd
= pImpl
->aArr
.size(); n
< nEnd
; ++n
)
407 if( ( p
= pImpl
->aArr
[ n
] )->bIsDataSink
&&
408 ( !pLink
|| &p
->xSink
== pLink
) )
416 // sal_True => waitinmg for data
417 bool SvLinkSource::IsPending() const
422 // sal_True => data complete loaded
423 bool SvLinkSource::IsDataComplete() const
428 bool SvLinkSource::Connect( SvBaseLink
* )
433 bool SvLinkSource::GetData( ::com::sun::star::uno::Any
&, const OUString
&, bool )
438 void SvLinkSource::Edit( vcl::Window
*, SvBaseLink
*, const Link
<>& )
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */