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