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 54 SvLinkSourceTimer::SvLinkSourceTimer( SvLinkSource * pOwn ) 55 : pOwner( pOwn ) 56 { 57 } 58 59 void SvLinkSourceTimer::Timeout() 60 { 61 // sicher gegen zerstoeren im Handler 62 SvLinkSourceRef aAdv( pOwner ); 63 pOwner->SendDataChanged(); 64 } 65 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 85 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 91 SvLinkSource_Entry_Impl( SvBaseLink* pLink ) 92 : xSink( pLink ), nAdviseModes( 0 ), bIsDataSink( sal_False ) 93 {} 94 95 ~SvLinkSource_Entry_Impl(); 96 }; 97 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(); 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 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 } 126 SvLinkSource_EntryIter_Impl::~SvLinkSource_EntryIter_Impl() 127 { 128 aArr.Remove( 0, aArr.Count() ); 129 } 130 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 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 173 SvLinkSource_Impl() : pTimer( 0 ), nTimeout( 3000 ) {} 174 ~SvLinkSource_Impl(); 175 176 void Closed(); 177 }; 178 179 SvLinkSource_Impl::~SvLinkSource_Impl() 180 { 181 delete pTimer; 182 } 183 184 SvLinkSource::SvLinkSource() 185 : pImpl( new SvLinkSource_Impl ) 186 { 187 } 188 189 SvLinkSource::~SvLinkSource() 190 { 191 delete pImpl; 192 } 193 194 195 SvLinkSource::StreamToLoadFrom SvLinkSource::getStreamToLoadFrom() 196 { 197 return StreamToLoadFrom( 198 pImpl->m_xInputStreamToLoadFrom, 199 pImpl->m_bIsReadOnly); 200 } 201 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# 209 void SvLinkSource::clearStreamToLoadFrom() 210 { 211 pImpl->m_xInputStreamToLoadFrom.clear(); 212 } 213 // <-- 214 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 223 sal_uIntPtr SvLinkSource::GetUpdateTimeout() const 224 { 225 return pImpl->nTimeout; 226 } 227 228 void SvLinkSource::SetUpdateTimeout( sal_uIntPtr nTimeout ) 229 { 230 pImpl->nTimeout = nTimeout; 231 if( pImpl->pTimer ) 232 pImpl->pTimer->SetTimeout( nTimeout ); 233 } 234 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 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 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 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 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 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 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 390 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 405 sal_Bool SvLinkSource::IsPending() const 406 { 407 return sal_False; 408 } 409 410 // sal_True => data complete loaded 411 sal_Bool SvLinkSource::IsDataComplete() const 412 { 413 return sal_True; 414 } 415 416 sal_Bool SvLinkSource::Connect( SvBaseLink* ) 417 { 418 return sal_True; 419 } 420 421 sal_Bool SvLinkSource::GetData( ::com::sun::star::uno::Any &, const String &, sal_Bool ) 422 { 423 return sal_False; 424 } 425 426 void SvLinkSource::Edit( Window *, SvBaseLink *, const Link& ) 427 { 428 } 429 430 } 431 432