1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: linksrc.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include <sfx2/linksrc.hxx>
35 #include <sfx2/lnkbase.hxx>
36 //#include <sot/exchange.hxx>
37 #include <com/sun/star/uno/Any.hxx>
38 #include <com/sun/star/uno/Sequence.hxx>
40 #include <tools/debug.hxx>
41 #include <vcl/timer.hxx>
42 #include <svtools/svarray.hxx>
45 using namespace ::com::sun::star::uno
;
50 TYPEINIT0( SvLinkSource
)
52 /************** class SvLinkSourceTimer *********************************/
53 class SvLinkSourceTimer
: public Timer
55 SvLinkSource
* pOwner
;
56 virtual void Timeout();
58 SvLinkSourceTimer( SvLinkSource
* pOwn
);
61 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource
* pOwn
)
66 void SvLinkSourceTimer::Timeout()
68 // sicher gegen zerstoeren im Handler
69 SvLinkSourceRef
aAdv( pOwner
);
70 pOwner
->SendDataChanged();
73 static void StartTimer( SvLinkSourceTimer
** ppTimer
, SvLinkSource
* pOwner
,
78 *ppTimer
= new SvLinkSourceTimer( pOwner
);
79 (*ppTimer
)->SetTimeout( nTimeout
);
85 struct SvLinkSource_Entry_Impl
92 SvLinkSource_Entry_Impl( SvBaseLink
* pLink
, const String
& rMimeType
,
94 : xSink( pLink
), aDataMimeType( rMimeType
),
95 nAdviseModes( nAdvMode
), bIsDataSink( TRUE
)
98 SvLinkSource_Entry_Impl( SvBaseLink
* pLink
)
99 : xSink( pLink
), nAdviseModes( 0 ), bIsDataSink( FALSE
)
102 ~SvLinkSource_Entry_Impl();
105 SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
109 typedef SvLinkSource_Entry_Impl
* SvLinkSource_Entry_ImplPtr
;
110 SV_DECL_PTRARR_DEL( SvLinkSource_Array_Impl
, SvLinkSource_Entry_ImplPtr
, 4, 4 )
111 SV_IMPL_PTRARR( SvLinkSource_Array_Impl
, SvLinkSource_Entry_ImplPtr
);
113 class SvLinkSource_EntryIter_Impl
115 SvLinkSource_Array_Impl aArr
;
116 const SvLinkSource_Array_Impl
& rOrigArr
;
119 SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl
& rArr
);
120 ~SvLinkSource_EntryIter_Impl();
121 SvLinkSource_Entry_Impl
* Curr()
122 { return nPos
< aArr
.Count() ? aArr
[ nPos
] : 0; }
123 SvLinkSource_Entry_Impl
* Next();
124 sal_Bool
IsValidCurrValue( SvLinkSource_Entry_Impl
* pEntry
);
127 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
128 const SvLinkSource_Array_Impl
& rArr
)
129 : rOrigArr( rArr
), nPos( 0 )
131 aArr
.Insert( &rArr
, 0 );
133 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
135 aArr
.Remove( 0, aArr
.Count() );
138 sal_Bool
SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl
* pEntry
)
140 return ( nPos
< aArr
.Count() && aArr
[nPos
] == pEntry
&& USHRT_MAX
!= rOrigArr
.GetPos( pEntry
) );
143 SvLinkSource_Entry_Impl
* SvLinkSource_EntryIter_Impl::Next()
145 SvLinkSource_Entry_ImplPtr pRet
= 0;
146 if( nPos
+ 1 < aArr
.Count() )
149 if( rOrigArr
.Count() == aArr
.Count() &&
150 rOrigArr
[ nPos
] == aArr
[ nPos
] )
154 // then we must search the current (or the next) in the orig
157 if( USHRT_MAX
!= rOrigArr
.GetPos( pRet
))
161 } while( nPos
< aArr
.Count() );
163 if( nPos
>= aArr
.Count() )
170 struct SvLinkSource_Impl
172 SvLinkSource_Array_Impl aArr
;
173 String aDataMimeType
;
174 SvLinkSourceTimer
* pTimer
;
176 com::sun::star::uno::Reference
<com::sun::star::io::XInputStream
>
177 m_xInputStreamToLoadFrom
;
178 sal_Bool m_bIsReadOnly
;
180 SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {}
181 ~SvLinkSource_Impl();
186 SvLinkSource_Impl::~SvLinkSource_Impl()
191 SvLinkSource::SvLinkSource()
192 : pImpl( new SvLinkSource_Impl
)
196 SvLinkSource::~SvLinkSource()
202 SvLinkSource::StreamToLoadFrom
SvLinkSource::getStreamToLoadFrom()
204 return StreamToLoadFrom(
205 pImpl
->m_xInputStreamToLoadFrom
,
206 pImpl
->m_bIsReadOnly
);
209 void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference
<com::sun::star::io::XInputStream
>& xInputStream
,sal_Bool bIsReadOnly
)
211 pImpl
->m_xInputStreamToLoadFrom
= xInputStream
;
212 pImpl
->m_bIsReadOnly
= bIsReadOnly
;
215 // --> OD 2008-06-18 #i88291#
216 void SvLinkSource::clearStreamToLoadFrom()
218 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 ULONG
SvLinkSource::GetUpdateTimeout() const
232 return pImpl
->nTimeout
;
235 void SvLinkSource::SetUpdateTimeout( ULONG 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_ImplPtr p
= aIter
.Curr(); p
; p
= aIter
.Next() )
249 String
sDataMimeType( pImpl
->aDataMimeType
);
250 if( !sDataMimeType
.Len() )
251 sDataMimeType
= p
->aDataMimeType
;
254 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
255 GetData( aVal
, sDataMimeType
, TRUE
) )
257 p
->xSink
->DataChanged( sDataMimeType
, aVal
);
259 if ( !aIter
.IsValidCurrValue( p
) )
262 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
264 USHORT nFndPos
= pImpl
->aArr
.GetPos( p
);
265 if( USHRT_MAX
!= nFndPos
)
266 pImpl
->aArr
.DeleteAndDestroy( nFndPos
);
274 delete pImpl
->pTimer
;
275 pImpl
->pTimer
= NULL
;
277 pImpl
->aDataMimeType
.Erase();
280 void SvLinkSource::NotifyDataChanged()
282 if( pImpl
->nTimeout
)
283 StartTimer( &pImpl
->pTimer
, this, pImpl
->nTimeout
); // Timeout neu
286 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
287 for( SvLinkSource_Entry_ImplPtr p
= aIter
.Curr(); p
; p
= aIter
.Next() )
291 if( ( p
->nAdviseModes
& ADVISEMODE_NODATA
) ||
292 GetData( aVal
, p
->aDataMimeType
, TRUE
) )
294 p
->xSink
->DataChanged( p
->aDataMimeType
, aVal
);
296 if ( !aIter
.IsValidCurrValue( p
) )
299 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
301 USHORT nFndPos
= pImpl
->aArr
.GetPos( p
);
302 if( USHRT_MAX
!= nFndPos
)
303 pImpl
->aArr
.DeleteAndDestroy( nFndPos
);
310 delete pImpl
->pTimer
;
311 pImpl
->pTimer
= NULL
;
316 // notify the sink, the mime type is not
317 // a selection criterion
318 void SvLinkSource::DataChanged( const String
& rMimeType
,
319 const ::com::sun::star::uno::Any
& rVal
)
321 if( pImpl
->nTimeout
&& !rVal
.hasValue() )
322 { // nur wenn keine Daten mitgegeben wurden
323 // fire all data to the sink, independent of the requested format
324 pImpl
->aDataMimeType
= rMimeType
;
325 StartTimer( &pImpl
->pTimer
, this, pImpl
->nTimeout
); // Timeout neu
329 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
330 for( SvLinkSource_Entry_ImplPtr p
= aIter
.Curr(); p
; p
= aIter
.Next() )
334 p
->xSink
->DataChanged( rMimeType
, rVal
);
336 if ( !aIter
.IsValidCurrValue( p
) )
339 if( p
->nAdviseModes
& ADVISEMODE_ONLYONCE
)
341 USHORT nFndPos
= pImpl
->aArr
.GetPos( p
);
342 if( USHRT_MAX
!= nFndPos
)
343 pImpl
->aArr
.DeleteAndDestroy( nFndPos
);
350 delete pImpl
->pTimer
;
351 pImpl
->pTimer
= NULL
;
357 // only one link is correct
358 void SvLinkSource::AddDataAdvise( SvBaseLink
* pLink
, const String
& rMimeType
,
359 USHORT nAdviseModes
)
361 SvLinkSource_Entry_ImplPtr pNew
= new SvLinkSource_Entry_Impl(
362 pLink
, rMimeType
, nAdviseModes
);
363 pImpl
->aArr
.Insert( pNew
, pImpl
->aArr
.Count() );
366 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink
* pLink
)
368 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
369 for( SvLinkSource_Entry_ImplPtr p
= aIter
.Curr(); p
; p
= aIter
.Next() )
370 if( p
->bIsDataSink
&& &p
->xSink
== pLink
)
372 USHORT nFndPos
= pImpl
->aArr
.GetPos( p
);
373 if( USHRT_MAX
!= nFndPos
)
374 pImpl
->aArr
.DeleteAndDestroy( nFndPos
);
378 // only one link is correct
379 void SvLinkSource::AddConnectAdvise( SvBaseLink
* pLink
)
381 SvLinkSource_Entry_ImplPtr pNew
= new SvLinkSource_Entry_Impl( pLink
);
382 pImpl
->aArr
.Insert( pNew
, pImpl
->aArr
.Count() );
385 void SvLinkSource::RemoveConnectAdvise( SvBaseLink
* pLink
)
387 SvLinkSource_EntryIter_Impl
aIter( pImpl
->aArr
);
388 for( SvLinkSource_Entry_ImplPtr p
= aIter
.Curr(); p
; p
= aIter
.Next() )
389 if( !p
->bIsDataSink
&& &p
->xSink
== pLink
)
391 USHORT nFndPos
= pImpl
->aArr
.GetPos( p
);
392 if( USHRT_MAX
!= nFndPos
)
393 pImpl
->aArr
.DeleteAndDestroy( nFndPos
);
397 BOOL
SvLinkSource::HasDataLinks( const SvBaseLink
* pLink
) const
400 const SvLinkSource_Entry_Impl
* p
;
401 for( USHORT n
= 0, nEnd
= pImpl
->aArr
.Count(); n
< nEnd
; ++n
)
402 if( ( p
= pImpl
->aArr
[ n
] )->bIsDataSink
&&
403 ( !pLink
|| &p
->xSink
== pLink
) )
411 // TRUE => waitinmg for data
412 BOOL
SvLinkSource::IsPending() const
417 // TRUE => data complete loaded
418 BOOL
SvLinkSource::IsDataComplete() const
423 BOOL
SvLinkSource::Connect( SvBaseLink
* )
428 BOOL
SvLinkSource::GetData( ::com::sun::star::uno::Any
&, const String
&, BOOL
)
433 void SvLinkSource::Edit( Window
*, SvBaseLink
*, const Link
& )