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 Timeout();
43 SvLinkSourceTimer( SvLinkSource
* pOwn
);
46 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource
* pOwn
)
51 void SvLinkSourceTimer::Timeout()
53 // Secure against beeing 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( sal_True
)
83 SvLinkSource_Entry_Impl( SvBaseLink
* pLink
)
84 : xSink( pLink
), nAdviseModes( 0 ), bIsDataSink( sal_False
)
87 ~SvLinkSource_Entry_Impl();
90 SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
94 class SvLinkSource_Array_Impl
: public std::vector
<SvLinkSource_Entry_Impl
*>
97 void DeleteAndDestroy(SvLinkSource_Entry_Impl
* p
)
99 iterator it
= std::find(begin(), end(), p
);
107 ~SvLinkSource_Array_Impl()
109 for(const_iterator it
= begin(); it
!= end(); ++it
)
114 class SvLinkSource_EntryIter_Impl
116 SvLinkSource_Array_Impl aArr
;
117 const SvLinkSource_Array_Impl
& rOrigArr
;
120 SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl
& rArr
);
121 ~SvLinkSource_EntryIter_Impl();
122 SvLinkSource_Entry_Impl
* Curr()
123 { return nPos
< aArr
.size() ? aArr
[ nPos
] : 0; }
124 SvLinkSource_Entry_Impl
* Next();
125 sal_Bool
IsValidCurrValue( SvLinkSource_Entry_Impl
* pEntry
);
128 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
129 const SvLinkSource_Array_Impl
& rArr
)
130 : aArr( rArr
), rOrigArr( rArr
), nPos( 0 )
133 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
138 sal_Bool
SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl
* pEntry
)
140 return ( nPos
< aArr
.size() && aArr
[nPos
] == pEntry
141 && std::find( rOrigArr
.begin(), rOrigArr
.end(), pEntry
) != rOrigArr
.end() );
144 SvLinkSource_Entry_Impl
* SvLinkSource_EntryIter_Impl::Next()
146 SvLinkSource_Entry_Impl
* pRet
= 0;
147 if( nPos
+ 1 < (sal_uInt16
)aArr
.size() )
150 if( rOrigArr
.size() == aArr
.size() &&
151 rOrigArr
[ nPos
] == aArr
[ nPos
] )
155 // then we must search the current (or the next) in the orig
158 if( std::find(rOrigArr
.begin(), rOrigArr
.end(), pRet
) != rOrigArr
.end() )
162 } while( nPos
< aArr
.size() );
164 if( nPos
>= aArr
.size() )
171 struct SvLinkSource_Impl
173 SvLinkSource_Array_Impl aArr
;
174 OUString aDataMimeType
;
175 SvLinkSourceTimer
* pTimer
;
176 sal_uIntPtr nTimeout
;
177 css::uno::Reference
<css::io::XInputStream
>
178 m_xInputStreamToLoadFrom
;
179 sal_Bool m_bIsReadOnly
;
181 SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {}
182 ~SvLinkSource_Impl();
187 SvLinkSource_Impl::~SvLinkSource_Impl()
192 SvLinkSource::SvLinkSource()
193 : pImpl( new SvLinkSource_Impl
)
197 SvLinkSource::~SvLinkSource()
203 SvLinkSource::StreamToLoadFrom
SvLinkSource::getStreamToLoadFrom()
205 return StreamToLoadFrom(
206 pImpl
->m_xInputStreamToLoadFrom
,
207 pImpl
->m_bIsReadOnly
);
210 void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference
<com::sun::star::io::XInputStream
>& xInputStream
,sal_Bool bIsReadOnly
)
212 pImpl
->m_xInputStreamToLoadFrom
= xInputStream
;
213 pImpl
->m_bIsReadOnly
= bIsReadOnly
;
217 void SvLinkSource::clearStreamToLoadFrom()
219 pImpl
->m_xInputStreamToLoadFrom
.clear();
222 void SvLinkSource::Closed()
224 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
225 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
226 if( !p
->bIsDataSink
)
230 sal_uIntPtr
SvLinkSource::GetUpdateTimeout() const
232 return pImpl
->nTimeout
;
235 void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout
)
237 pImpl
->nTimeout
= nTimeout
;
239 pImpl
->pTimer
->SetTimeout( nTimeout
);
242 void SvLinkSource::SendDataChanged()
244 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
245 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
249 OUString
sDataMimeType( pImpl
->aDataMimeType
);
250 if( sDataMimeType
.isEmpty() )
251 sDataMimeType
= p
->aDataMimeType
;
254 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
255 GetData( aVal
, sDataMimeType
, sal_True
) )
257 p
->xSink
->DataChanged( sDataMimeType
, aVal
);
259 if ( !aIter
.IsValidCurrValue( p
) )
262 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
264 pImpl
->aArr
.DeleteAndDestroy( p
);
272 delete pImpl
->pTimer
;
273 pImpl
->pTimer
= NULL
;
275 pImpl
->aDataMimeType
= "";
278 void SvLinkSource::NotifyDataChanged()
280 if( pImpl
->nTimeout
)
281 StartTimer( &pImpl
->pTimer
, this, pImpl
->nTimeout
); // New timeout
284 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
285 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
289 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
290 GetData( aVal
, p
->aDataMimeType
, sal_True
) )
292 p
->xSink
->DataChanged( p
->aDataMimeType
, aVal
);
294 if ( !aIter
.IsValidCurrValue( p
) )
297 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
299 pImpl
->aArr
.DeleteAndDestroy( p
);
306 delete pImpl
->pTimer
;
307 pImpl
->pTimer
= NULL
;
312 // notify the sink, the mime type is not
313 // a selection criterion
314 void SvLinkSource::DataChanged( const OUString
& rMimeType
,
315 const ::com::sun::star::uno::Any
& rVal
)
317 if( pImpl
->nTimeout
&& !rVal
.hasValue() )
318 { // only when no data was included
319 // fire all data to the sink, independent of the requested format
320 pImpl
->aDataMimeType
= rMimeType
;
321 StartTimer( &pImpl
->pTimer
, this, pImpl
->nTimeout
); // New timeout
325 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
326 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
330 p
->xSink
->DataChanged( rMimeType
, rVal
);
332 if ( !aIter
.IsValidCurrValue( p
) )
335 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
337 pImpl
->aArr
.DeleteAndDestroy( p
);
344 delete pImpl
->pTimer
;
345 pImpl
->pTimer
= NULL
;
351 // only one link is correct
352 void SvLinkSource::AddDataAdvise( SvBaseLink
* pLink
, const OUString
& rMimeType
,
353 sal_uInt16 nAdviseModes
)
355 SvLinkSource_Entry_Impl
* pNew
= new SvLinkSource_Entry_Impl(
356 pLink
, rMimeType
, nAdviseModes
);
357 pImpl
->aArr
.push_back( pNew
);
360 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink
* pLink
)
362 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
363 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
364 if( p
->bIsDataSink
&& &p
->xSink
== pLink
)
366 pImpl
->aArr
.DeleteAndDestroy( p
);
370 // only one link is correct
371 void SvLinkSource::AddConnectAdvise( SvBaseLink
* pLink
)
373 SvLinkSource_Entry_Impl
* pNew
= new SvLinkSource_Entry_Impl( pLink
);
374 pImpl
->aArr
.push_back( pNew
);
377 void SvLinkSource::RemoveConnectAdvise( SvBaseLink
* pLink
)
379 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
380 for( SvLinkSource_Entry_Impl
* p
= aIter
.Curr(); p
; p
= aIter
.Next() )
381 if( !p
->bIsDataSink
&& &p
->xSink
== pLink
)
383 pImpl
->aArr
.DeleteAndDestroy( p
);
387 sal_Bool
SvLinkSource::HasDataLinks( const SvBaseLink
* pLink
) const
389 sal_Bool bRet
= sal_False
;
390 const SvLinkSource_Entry_Impl
* p
;
391 for( sal_uInt16 n
= 0, nEnd
= pImpl
->aArr
.size(); n
< nEnd
; ++n
)
392 if( ( p
= pImpl
->aArr
[ n
] )->bIsDataSink
&&
393 ( !pLink
|| &p
->xSink
== pLink
) )
401 // sal_True => waitinmg for data
402 sal_Bool
SvLinkSource::IsPending() const
407 // sal_True => data complete loaded
408 sal_Bool
SvLinkSource::IsDataComplete() const
413 sal_Bool
SvLinkSource::Connect( SvBaseLink
* )
418 sal_Bool
SvLinkSource::GetData( ::com::sun::star::uno::Any
&, const OUString
&, sal_Bool
)
423 void SvLinkSource::Edit( Window
*, SvBaseLink
*, const Link
& )
429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */