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