xref: /trunk/main/sfx2/source/appl/linksrc.cxx (revision d119d52d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 
27 #include <sfx2/linksrc.hxx>
28 #include <sfx2/lnkbase.hxx>
29 //#include <sot/exchange.hxx>
30 #include <com/sun/star/uno/Any.hxx>
31 #include <com/sun/star/uno/Sequence.hxx>
32 
33 #include <tools/debug.hxx>
34 #include <vcl/timer.hxx>
35 #include <svl/svarray.hxx>
36 
37 
38 using namespace ::com::sun::star::uno;
39 
40 namespace sfx2
41 {
42 
43 TYPEINIT0( SvLinkSource )
44 
45 /************** class SvLinkSourceTimer *********************************/
46 class SvLinkSourceTimer : public Timer
47 {
48 	SvLinkSource *  pOwner;
49 	virtual void    Timeout();
50 public:
51 			SvLinkSourceTimer( SvLinkSource * pOwn );
52 };
53 
SvLinkSourceTimer(SvLinkSource * pOwn)54 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn )
55 	: pOwner( pOwn )
56 {
57 }
58 
Timeout()59 void SvLinkSourceTimer::Timeout()
60 {
61 	// sicher gegen zerstoeren im Handler
62 	SvLinkSourceRef aAdv( pOwner );
63 	pOwner->SendDataChanged();
64 }
65 
StartTimer(SvLinkSourceTimer ** ppTimer,SvLinkSource * pOwner,sal_uIntPtr nTimeout)66 static void StartTimer( SvLinkSourceTimer ** ppTimer, SvLinkSource * pOwner,
67 						sal_uIntPtr nTimeout )
68 {
69 	if( !*ppTimer )
70 	{
71 		*ppTimer = new SvLinkSourceTimer( pOwner );
72 		(*ppTimer)->SetTimeout( nTimeout );
73 		(*ppTimer)->Start();
74 	}
75 }
76 
77 
78 struct SvLinkSource_Entry_Impl
79 {
80 	SvBaseLinkRef		xSink;
81 	String				aDataMimeType;
82 	sal_uInt16				nAdviseModes;
83 	sal_Bool 				bIsDataSink;
84 
SvLinkSource_Entry_Implsfx2::SvLinkSource_Entry_Impl85 	SvLinkSource_Entry_Impl( SvBaseLink* pLink, const String& rMimeType,
86 								sal_uInt16 nAdvMode )
87 		: xSink( pLink ), aDataMimeType( rMimeType ),
88 			nAdviseModes( nAdvMode ), bIsDataSink( sal_True )
89 	{}
90 
SvLinkSource_Entry_Implsfx2::SvLinkSource_Entry_Impl91 	SvLinkSource_Entry_Impl( SvBaseLink* pLink )
92 		: xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( sal_False )
93 	{}
94 
95 	~SvLinkSource_Entry_Impl();
96 };
97 
~SvLinkSource_Entry_Impl()98 SvLinkSource_Entry_Impl::~SvLinkSource_Entry_Impl()
99 {
100 }
101 
102 typedef SvLinkSource_Entry_Impl* SvLinkSource_Entry_ImplPtr;
103 SV_DECL_PTRARR_DEL( SvLinkSource_Array_Impl, SvLinkSource_Entry_ImplPtr, 4, 4 )
104 SV_IMPL_PTRARR( SvLinkSource_Array_Impl, SvLinkSource_Entry_ImplPtr );
105 
106 class SvLinkSource_EntryIter_Impl
107 {
108 	SvLinkSource_Array_Impl aArr;
109 	const SvLinkSource_Array_Impl& rOrigArr;
110 	sal_uInt16 nPos;
111 public:
112 	SvLinkSource_EntryIter_Impl( const SvLinkSource_Array_Impl& rArr );
113 	~SvLinkSource_EntryIter_Impl();
Curr()114 	SvLinkSource_Entry_Impl* Curr()
115 							{ return nPos < aArr.Count() ? aArr[ nPos ] : 0; }
116 	SvLinkSource_Entry_Impl* Next();
117 	sal_Bool IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry );
118 };
119 
SvLinkSource_EntryIter_Impl(const SvLinkSource_Array_Impl & rArr)120 SvLinkSource_EntryIter_Impl::SvLinkSource_EntryIter_Impl(
121 		const SvLinkSource_Array_Impl& rArr )
122 	: rOrigArr( rArr ), nPos( 0 )
123 {
124 	aArr.Insert( &rArr, 0 );
125 }
~SvLinkSource_EntryIter_Impl()126 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl()
127 {
128 	aArr.Remove( 0, aArr.Count() );
129 }
130 
IsValidCurrValue(SvLinkSource_Entry_Impl * pEntry)131 sal_Bool SvLinkSource_EntryIter_Impl::IsValidCurrValue( SvLinkSource_Entry_Impl* pEntry )
132 {
133 	return ( nPos < aArr.Count() && aArr[nPos] == pEntry && USHRT_MAX != rOrigArr.GetPos( pEntry ) );
134 }
135 
Next()136 SvLinkSource_Entry_Impl* SvLinkSource_EntryIter_Impl::Next()
137 {
138 	SvLinkSource_Entry_ImplPtr pRet = 0;
139 	if( nPos + 1 < aArr.Count() )
140 	{
141 		++nPos;
142 		if( rOrigArr.Count() == aArr.Count() &&
143 			rOrigArr[ nPos ] == aArr[ nPos ] )
144 			pRet = aArr[ nPos ];
145 		else
146 		{
147 			// then we must search the current (or the next) in the orig
148 			do {
149 				pRet = aArr[ nPos ];
150 				if( USHRT_MAX != rOrigArr.GetPos( pRet ))
151 					break;
152 				pRet = 0;
153 				++nPos;
154 			} while( nPos < aArr.Count() );
155 
156 			if( nPos >= aArr.Count() )
157 				pRet = 0;
158 		}
159 	}
160 	return pRet;
161 }
162 
163 struct SvLinkSource_Impl
164 {
165 	SvLinkSource_Array_Impl aArr;
166 	String				aDataMimeType;
167 	SvLinkSourceTimer *	pTimer;
168 	sal_uIntPtr				nTimeout;
169     com::sun::star::uno::Reference<com::sun::star::io::XInputStream>
170     m_xInputStreamToLoadFrom;
171     sal_Bool m_bIsReadOnly;
172 
SvLinkSource_Implsfx2::SvLinkSource_Impl173 	SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {}
174 	~SvLinkSource_Impl();
175 
176 	void Closed();
177 };
178 
~SvLinkSource_Impl()179 SvLinkSource_Impl::~SvLinkSource_Impl()
180 {
181 	delete pTimer;
182 }
183 
SvLinkSource()184 SvLinkSource::SvLinkSource()
185  	: pImpl( new SvLinkSource_Impl )
186 {
187 }
188 
~SvLinkSource()189 SvLinkSource::~SvLinkSource()
190 {
191 	delete pImpl;
192 }
193 
194 
getStreamToLoadFrom()195 SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom()
196 {
197     return StreamToLoadFrom(
198         pImpl->m_xInputStreamToLoadFrom,
199         pImpl->m_bIsReadOnly);
200 }
201 
setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream> & xInputStream,sal_Bool bIsReadOnly)202 void SvLinkSource::setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xInputStream,sal_Bool bIsReadOnly )
203 {
204     pImpl->m_xInputStreamToLoadFrom = xInputStream;
205     pImpl->m_bIsReadOnly = bIsReadOnly;
206 }
207 
208 // --> OD 2008-06-18 #i88291#
clearStreamToLoadFrom()209 void SvLinkSource::clearStreamToLoadFrom()
210 {
211     pImpl->m_xInputStreamToLoadFrom.clear();
212 }
213 // <--
214 
Closed()215 void  SvLinkSource::Closed()
216 {
217 	SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
218 	for( SvLinkSource_Entry_Impl* p = aIter.Curr(); p; p = aIter.Next() )
219 		if( !p->bIsDataSink )
220 			p->xSink->Closed();
221 }
222 
GetUpdateTimeout() const223 sal_uIntPtr SvLinkSource::GetUpdateTimeout() const
224 {
225 	return pImpl->nTimeout;
226 }
227 
SetUpdateTimeout(sal_uIntPtr nTimeout)228 void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout )
229 {
230 	pImpl->nTimeout = nTimeout;
231 	if( pImpl->pTimer )
232 		pImpl->pTimer->SetTimeout( nTimeout );
233 }
234 
SendDataChanged()235 void SvLinkSource::SendDataChanged()
236 {
237 	SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
238 	for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
239 	{
240 		if( p->bIsDataSink )
241 		{
242 			String sDataMimeType( pImpl->aDataMimeType );
243 			if( !sDataMimeType.Len() )
244 				sDataMimeType = p->aDataMimeType;
245 
246 			Any aVal;
247 			if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
248 				GetData( aVal, sDataMimeType, sal_True ) )
249 			{
250 				p->xSink->DataChanged( sDataMimeType, aVal );
251 
252 				if ( !aIter.IsValidCurrValue( p ) )
253 					continue;
254 
255 				if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
256 				{
257 					sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
258 					if( USHRT_MAX != nFndPos )
259 						pImpl->aArr.DeleteAndDestroy( nFndPos );
260 				}
261 
262 			}
263 		}
264 	}
265 	if( pImpl->pTimer )
266 	{
267 		delete pImpl->pTimer;
268 		pImpl->pTimer = NULL;
269 	}
270 	pImpl->aDataMimeType.Erase();
271 }
272 
NotifyDataChanged()273 void SvLinkSource::NotifyDataChanged()
274 {
275 	if( pImpl->nTimeout )
276 		StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // Timeout neu
277 	else
278 	{
279 		SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
280 		for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
281 			if( p->bIsDataSink )
282 			{
283 				Any aVal;
284 				if( ( p->nAdviseModes & ADVISEMODE_NODATA ) ||
285 					GetData( aVal, p->aDataMimeType, sal_True ) )
286 				{
287 					p->xSink->DataChanged( p->aDataMimeType, aVal );
288 
289 					if ( !aIter.IsValidCurrValue( p ) )
290 						continue;
291 
292 					if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
293 					{
294 						sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
295 						if( USHRT_MAX != nFndPos )
296 							pImpl->aArr.DeleteAndDestroy( nFndPos );
297 					}
298 				}
299 			}
300 
301 			if( pImpl->pTimer )
302 			{
303 				delete pImpl->pTimer;
304 				pImpl->pTimer = NULL;
305 			}
306 	}
307 }
308 
309 // notify the sink, the mime type is not
310 // a selection criterion
DataChanged(const String & rMimeType,const::com::sun::star::uno::Any & rVal)311 void SvLinkSource::DataChanged( const String & rMimeType,
312 								const ::com::sun::star::uno::Any & rVal )
313 {
314 	if( pImpl->nTimeout && !rVal.hasValue() )
315 	{   // nur wenn keine Daten mitgegeben wurden
316 		// fire all data to the sink, independent of the requested format
317 		pImpl->aDataMimeType = rMimeType;
318 		StartTimer( &pImpl->pTimer, this, pImpl->nTimeout ); // Timeout neu
319 	}
320 	else
321 	{
322 		SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
323 		for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
324 		{
325 			if( p->bIsDataSink )
326 			{
327 				p->xSink->DataChanged( rMimeType, rVal );
328 
329 				if ( !aIter.IsValidCurrValue( p ) )
330 					continue;
331 
332 				if( p->nAdviseModes & ADVISEMODE_ONLYONCE )
333 				{
334 					sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
335 					if( USHRT_MAX != nFndPos )
336 						pImpl->aArr.DeleteAndDestroy( nFndPos );
337 				}
338 			}
339 		}
340 
341 		if( pImpl->pTimer )
342 		{
343 			delete pImpl->pTimer;
344 			pImpl->pTimer = NULL;
345 		}
346 	}
347 }
348 
349 
350 // only one link is correct
AddDataAdvise(SvBaseLink * pLink,const String & rMimeType,sal_uInt16 nAdviseModes)351 void SvLinkSource::AddDataAdvise( SvBaseLink * pLink, const String& rMimeType,
352 									sal_uInt16 nAdviseModes )
353 {
354 	SvLinkSource_Entry_ImplPtr pNew = new SvLinkSource_Entry_Impl(
355 					pLink, rMimeType, nAdviseModes );
356 	pImpl->aArr.Insert( pNew, pImpl->aArr.Count() );
357 }
358 
RemoveAllDataAdvise(SvBaseLink * pLink)359 void SvLinkSource::RemoveAllDataAdvise( SvBaseLink * pLink )
360 {
361 	SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
362 	for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
363 		if( p->bIsDataSink && &p->xSink == pLink )
364 		{
365 			sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
366 			if( USHRT_MAX != nFndPos )
367 				pImpl->aArr.DeleteAndDestroy( nFndPos );
368 		}
369 }
370 
371 // only one link is correct
AddConnectAdvise(SvBaseLink * pLink)372 void SvLinkSource::AddConnectAdvise( SvBaseLink * pLink )
373 {
374 	SvLinkSource_Entry_ImplPtr pNew = new SvLinkSource_Entry_Impl( pLink );
375 	pImpl->aArr.Insert( pNew, pImpl->aArr.Count() );
376 }
377 
RemoveConnectAdvise(SvBaseLink * pLink)378 void SvLinkSource::RemoveConnectAdvise( SvBaseLink * pLink )
379 {
380 	SvLinkSource_EntryIter_Impl aIter( pImpl->aArr );
381 	for( SvLinkSource_Entry_ImplPtr p = aIter.Curr(); p; p = aIter.Next() )
382 		if( !p->bIsDataSink && &p->xSink == pLink )
383 		{
384 			sal_uInt16 nFndPos = pImpl->aArr.GetPos( p );
385 			if( USHRT_MAX != nFndPos )
386 				pImpl->aArr.DeleteAndDestroy( nFndPos );
387 		}
388 }
389 
HasDataLinks(const SvBaseLink * pLink) const390 sal_Bool SvLinkSource::HasDataLinks( const SvBaseLink* pLink ) const
391 {
392 	sal_Bool bRet = sal_False;
393 	const SvLinkSource_Entry_Impl* p;
394 	for( sal_uInt16 n = 0, nEnd = pImpl->aArr.Count(); n < nEnd; ++n )
395 		if( ( p = pImpl->aArr[ n ] )->bIsDataSink &&
396 			( !pLink || &p->xSink == pLink ) )
397 		{
398 			bRet = sal_True;
399 			break;
400 		}
401 	return bRet;
402 }
403 
404 // sal_True => waitinmg for data
IsPending() const405 sal_Bool SvLinkSource::IsPending() const
406 {
407 	return sal_False;
408 }
409 
410 // sal_True => data complete loaded
IsDataComplete() const411 sal_Bool SvLinkSource::IsDataComplete() const
412 {
413 	return sal_True;
414 }
415 
Connect(SvBaseLink *)416 sal_Bool SvLinkSource::Connect( SvBaseLink* )
417 {
418 	return sal_True;
419 }
420 
GetData(::com::sun::star::uno::Any &,const String &,sal_Bool)421 sal_Bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const String &, sal_Bool )
422 {
423 	return sal_False;
424 }
425 
Edit(Window *,SvBaseLink *,const Link &)426 void SvLinkSource::Edit( Window *, SvBaseLink *, const Link& )
427 {
428 }
429 
430 }
431 
432