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 // MARKER(update_precomp.py): autogen include statement, do not remove 28 #include "precompiled_sd.hxx" 29 30 #include "precompiled_sd.hxx" 31 32 #include "PresenterPreviewCache.hxx" 33 34 #include "cache/SlsCacheContext.hxx" 35 #include "tools/IdleDetection.hxx" 36 #include "sdpage.hxx" 37 #include <cppcanvas/vclfactory.hxx> 38 #include <com/sun/star/drawing/XDrawPage.hpp> 39 #include <com/sun/star/rendering/XBitmapCanvas.hpp> 40 41 using namespace ::com::sun::star; 42 using namespace ::com::sun::star::uno; 43 using namespace ::sd::slidesorter::cache; 44 using ::rtl::OUString; 45 46 namespace sd { namespace presenter { 47 48 49 class PresenterPreviewCache::PresenterCacheContext : public CacheContext 50 { 51 public: 52 PresenterCacheContext (void); 53 virtual ~PresenterCacheContext (void); 54 55 void SetDocumentSlides ( 56 const Reference<container::XIndexAccess>& rxSlides, 57 const Reference<XInterface>& rxDocument); 58 void SetVisibleSlideRange ( 59 const sal_Int32 nFirstVisibleSlideIndex, 60 const sal_Int32 nLastVisibleSlideIndex); 61 const SdrPage* GetPage (const sal_Int32 nSlideIndex) const; 62 void AddPreviewCreationNotifyListener (const Reference<drawing::XSlidePreviewCacheListener>& rxListener); 63 void RemovePreviewCreationNotifyListener (const Reference<drawing::XSlidePreviewCacheListener>& rxListener); 64 65 // CacheContext 66 virtual void NotifyPreviewCreation ( 67 CacheKey aKey, 68 const Bitmap& rPreview); 69 virtual bool IsIdle (void); 70 virtual bool IsVisible (CacheKey aKey); 71 virtual const SdrPage* GetPage (CacheKey aKey); 72 virtual ::boost::shared_ptr<std::vector<CacheKey> > GetEntryList (bool bVisible); 73 virtual sal_Int32 GetPriority (CacheKey aKey); 74 virtual ::com::sun::star::uno::Reference<com::sun::star::uno::XInterface> GetModel (void); 75 76 private: 77 Reference<container::XIndexAccess> mxSlides; 78 Reference<XInterface> mxDocument; 79 sal_Int32 mnFirstVisibleSlideIndex; 80 sal_Int32 mnLastVisibleSlideIndex; 81 typedef ::std::vector<css::uno::Reference<css::drawing::XSlidePreviewCacheListener> > ListenerContainer; 82 ListenerContainer maListeners; 83 84 void CallListeners (const sal_Int32 nSlideIndex); 85 }; 86 87 88 89 90 //===== Service =============================================================== 91 92 Reference<XInterface> SAL_CALL PresenterPreviewCache_createInstance ( 93 const Reference<XComponentContext>& rxContext) 94 { 95 return Reference<XInterface>(static_cast<XWeak*>(new PresenterPreviewCache(rxContext))); 96 } 97 98 99 100 101 ::rtl::OUString PresenterPreviewCache_getImplementationName (void) throw(RuntimeException) 102 { 103 return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterPreviewCache"); 104 } 105 106 107 108 109 Sequence<rtl::OUString> SAL_CALL PresenterPreviewCache_getSupportedServiceNames (void) 110 throw (RuntimeException) 111 { 112 static const ::rtl::OUString sServiceName( 113 ::rtl::OUString::createFromAscii("com.sun.star.drawing.PresenterPreviewCache")); 114 return Sequence<rtl::OUString>(&sServiceName, 1); 115 } 116 117 118 119 120 //===== PresenterPreviewCache ================================================= 121 122 PresenterPreviewCache::PresenterPreviewCache (const Reference<XComponentContext>& rxContext) 123 : PresenterPreviewCacheInterfaceBase(m_aMutex), 124 maPreviewSize(Size(200,200)), 125 mpCacheContext(new PresenterCacheContext()), 126 mpCache(new PageCache(maPreviewSize, false, mpCacheContext)) 127 { 128 (void)rxContext; 129 } 130 131 132 133 134 PresenterPreviewCache::~PresenterPreviewCache (void) 135 { 136 } 137 138 139 140 141 //----- XInitialize ----------------------------------------------------------- 142 143 void SAL_CALL PresenterPreviewCache::initialize (const Sequence<Any>& rArguments) 144 throw(Exception, RuntimeException) 145 { 146 if (rArguments.getLength() != 0) 147 throw RuntimeException(); 148 } 149 150 151 152 153 //----- XSlidePreviewCache ---------------------------------------------------- 154 155 void SAL_CALL PresenterPreviewCache::setDocumentSlides ( 156 const Reference<container::XIndexAccess>& rxSlides, 157 const Reference<XInterface>& rxDocument) 158 throw (RuntimeException) 159 { 160 ThrowIfDisposed(); 161 OSL_ASSERT(mpCacheContext.get()!=NULL); 162 163 mpCacheContext->SetDocumentSlides(rxSlides, rxDocument); 164 } 165 166 167 168 169 void SAL_CALL PresenterPreviewCache::setVisibleRange ( 170 sal_Int32 nFirstVisibleSlideIndex, 171 sal_Int32 nLastVisibleSlideIndex) 172 throw (css::uno::RuntimeException) 173 { 174 ThrowIfDisposed(); 175 OSL_ASSERT(mpCacheContext.get()!=NULL); 176 177 mpCacheContext->SetVisibleSlideRange (nFirstVisibleSlideIndex, nLastVisibleSlideIndex); 178 } 179 180 181 182 183 void SAL_CALL PresenterPreviewCache::setPreviewSize ( 184 const css::geometry::IntegerSize2D& rSize) 185 throw (css::uno::RuntimeException) 186 { 187 ThrowIfDisposed(); 188 OSL_ASSERT(mpCache.get()!=NULL); 189 190 maPreviewSize = Size(rSize.Width, rSize.Height); 191 mpCache->ChangeSize(maPreviewSize, false); 192 } 193 194 195 196 197 Reference<rendering::XBitmap> SAL_CALL PresenterPreviewCache::getSlidePreview ( 198 sal_Int32 nSlideIndex, 199 const Reference<rendering::XCanvas>& rxCanvas) 200 throw (css::uno::RuntimeException) 201 { 202 ThrowIfDisposed(); 203 OSL_ASSERT(mpCacheContext.get()!=NULL); 204 205 cppcanvas::BitmapCanvasSharedPtr pCanvas ( 206 cppcanvas::VCLFactory::getInstance().createCanvas( 207 Reference<rendering::XBitmapCanvas>(rxCanvas, UNO_QUERY))); 208 209 const SdrPage* pPage = mpCacheContext->GetPage(nSlideIndex); 210 if (pPage == NULL) 211 throw RuntimeException(); 212 213 const BitmapEx aPreview (mpCache->GetPreviewBitmap(pPage,true)); 214 if (aPreview.IsEmpty()) 215 return NULL; 216 else 217 return cppcanvas::VCLFactory::getInstance().createBitmap( 218 pCanvas, 219 aPreview)->getUNOBitmap(); 220 } 221 222 223 224 225 void SAL_CALL PresenterPreviewCache::addPreviewCreationNotifyListener ( 226 const Reference<drawing::XSlidePreviewCacheListener>& rxListener) 227 throw (css::uno::RuntimeException) 228 { 229 if (rBHelper.bDisposed || rBHelper.bInDispose) 230 return; 231 if (rxListener.is()) 232 mpCacheContext->AddPreviewCreationNotifyListener(rxListener); 233 } 234 235 236 237 238 void SAL_CALL PresenterPreviewCache::removePreviewCreationNotifyListener ( 239 const css::uno::Reference<css::drawing::XSlidePreviewCacheListener>& rxListener) 240 throw (css::uno::RuntimeException) 241 { 242 ThrowIfDisposed(); 243 mpCacheContext->RemovePreviewCreationNotifyListener(rxListener); 244 } 245 246 247 248 249 void SAL_CALL PresenterPreviewCache::pause (void) 250 throw (css::uno::RuntimeException) 251 { 252 ThrowIfDisposed(); 253 OSL_ASSERT(mpCache.get()!=NULL); 254 mpCache->Pause(); 255 } 256 257 258 259 260 void SAL_CALL PresenterPreviewCache::resume (void) 261 throw (css::uno::RuntimeException) 262 { 263 ThrowIfDisposed(); 264 OSL_ASSERT(mpCache.get()!=NULL); 265 mpCache->Resume(); 266 } 267 268 269 270 271 //----------------------------------------------------------------------------- 272 273 void PresenterPreviewCache::ThrowIfDisposed (void) 274 throw (::com::sun::star::lang::DisposedException) 275 { 276 if (rBHelper.bDisposed || rBHelper.bInDispose) 277 { 278 throw lang::DisposedException ( 279 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 280 "PresenterPreviewCache object has already been disposed")), 281 static_cast<uno::XWeak*>(this)); 282 } 283 } 284 285 286 287 288 //===== PresenterPreviewCache::PresenterCacheContext ========================== 289 290 291 PresenterPreviewCache::PresenterCacheContext::PresenterCacheContext (void) 292 : mxSlides(), 293 mxDocument(), 294 mnFirstVisibleSlideIndex(-1), 295 mnLastVisibleSlideIndex(-1), 296 maListeners() 297 { 298 } 299 300 301 302 303 PresenterPreviewCache::PresenterCacheContext::~PresenterCacheContext (void) 304 { 305 } 306 307 308 309 310 void PresenterPreviewCache::PresenterCacheContext::SetDocumentSlides ( 311 const Reference<container::XIndexAccess>& rxSlides, 312 const Reference<XInterface>& rxDocument) 313 { 314 mxSlides = rxSlides; 315 mxDocument = rxDocument; 316 mnFirstVisibleSlideIndex = -1; 317 mnLastVisibleSlideIndex = -1; 318 } 319 320 321 322 323 void PresenterPreviewCache::PresenterCacheContext::SetVisibleSlideRange ( 324 const sal_Int32 nFirstVisibleSlideIndex, 325 const sal_Int32 nLastVisibleSlideIndex) 326 { 327 if (nFirstVisibleSlideIndex > nLastVisibleSlideIndex || nFirstVisibleSlideIndex<0) 328 { 329 mnFirstVisibleSlideIndex = -1; 330 mnLastVisibleSlideIndex = -1; 331 } 332 else 333 { 334 mnFirstVisibleSlideIndex = nFirstVisibleSlideIndex; 335 mnLastVisibleSlideIndex = nLastVisibleSlideIndex; 336 } 337 if (mxSlides.is() && mnLastVisibleSlideIndex >= mxSlides->getCount()) 338 mnLastVisibleSlideIndex = mxSlides->getCount() - 1; 339 } 340 341 342 343 344 void PresenterPreviewCache::PresenterCacheContext::AddPreviewCreationNotifyListener ( 345 const Reference<drawing::XSlidePreviewCacheListener>& rxListener) 346 { 347 maListeners.push_back(rxListener); 348 } 349 350 351 352 353 void PresenterPreviewCache::PresenterCacheContext::RemovePreviewCreationNotifyListener ( 354 const Reference<drawing::XSlidePreviewCacheListener>& rxListener) 355 { 356 ListenerContainer::iterator iListener; 357 for (iListener=maListeners.begin(); iListener!=maListeners.end(); ++iListener) 358 if (*iListener == rxListener) 359 { 360 maListeners.erase(iListener); 361 return; 362 } 363 } 364 365 366 367 368 //----- CacheContext ---------------------------------------------------------- 369 370 void PresenterPreviewCache::PresenterCacheContext::NotifyPreviewCreation ( 371 CacheKey aKey, 372 const Bitmap& rPreview) 373 { 374 (void)rPreview; 375 376 if ( ! mxSlides.is()) 377 return; 378 const sal_Int32 nCount(mxSlides->getCount()); 379 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) 380 if (aKey == GetPage(nIndex)) 381 CallListeners(nIndex); 382 } 383 384 385 386 387 bool PresenterPreviewCache::PresenterCacheContext::IsIdle (void) 388 { 389 return true; 390 /* 391 sal_Int32 nIdleState (tools::IdleDetection::GetIdleState(NULL)); 392 if (nIdleState == tools::IdleDetection::IDET_IDLE) 393 return true; 394 else 395 return false; 396 */ 397 } 398 399 400 401 402 bool PresenterPreviewCache::PresenterCacheContext::IsVisible (CacheKey aKey) 403 { 404 if (mnFirstVisibleSlideIndex < 0) 405 return false; 406 for (sal_Int32 nIndex=mnFirstVisibleSlideIndex; nIndex<=mnLastVisibleSlideIndex; ++nIndex) 407 { 408 const SdrPage* pPage = GetPage(nIndex); 409 if (pPage == static_cast<const SdrPage*>(aKey)) 410 return true; 411 } 412 return false; 413 } 414 415 416 417 418 const SdrPage* PresenterPreviewCache::PresenterCacheContext::GetPage (CacheKey aKey) 419 { 420 return static_cast<const SdrPage*>(aKey); 421 } 422 423 424 425 426 ::boost::shared_ptr<std::vector<CacheKey> > 427 PresenterPreviewCache::PresenterCacheContext::GetEntryList (bool bVisible) 428 { 429 ::boost::shared_ptr<std::vector<CacheKey> > pKeys (new std::vector<CacheKey>()); 430 431 if ( ! mxSlides.is()) 432 return pKeys; 433 434 const sal_Int32 nFirstIndex (bVisible ? mnFirstVisibleSlideIndex : 0); 435 const sal_Int32 nLastIndex (bVisible ? mnLastVisibleSlideIndex : mxSlides->getCount()-1); 436 437 if (nFirstIndex < 0) 438 return pKeys; 439 440 for (sal_Int32 nIndex=nFirstIndex; nIndex<=nLastIndex; ++nIndex) 441 { 442 pKeys->push_back(GetPage(nIndex)); 443 } 444 445 return pKeys; 446 } 447 448 449 450 451 sal_Int32 PresenterPreviewCache::PresenterCacheContext::GetPriority (CacheKey aKey) 452 { 453 if ( ! mxSlides.is()) 454 return 0; 455 456 const sal_Int32 nCount (mxSlides->getCount()); 457 458 for (sal_Int32 nIndex=mnFirstVisibleSlideIndex; nIndex<=mnLastVisibleSlideIndex; ++nIndex) 459 if (aKey == GetPage(nIndex)) 460 return -nCount-1+nIndex; 461 462 for (sal_Int32 nIndex=0; nIndex<=nCount; ++nIndex) 463 if (aKey == GetPage(nIndex)) 464 return nIndex; 465 466 return 0; 467 } 468 469 470 471 472 Reference<XInterface> PresenterPreviewCache::PresenterCacheContext::GetModel (void) 473 { 474 return mxDocument; 475 } 476 477 478 479 480 //----------------------------------------------------------------------------- 481 482 const SdrPage* PresenterPreviewCache::PresenterCacheContext::GetPage ( 483 const sal_Int32 nSlideIndex) const 484 { 485 if ( ! mxSlides.is()) 486 return NULL; 487 if (nSlideIndex < 0 || nSlideIndex >= mxSlides->getCount()) 488 return NULL; 489 490 Reference<drawing::XDrawPage> xSlide (mxSlides->getByIndex(nSlideIndex), UNO_QUERY); 491 const SdPage* pPage = SdPage::getImplementation(xSlide); 492 return dynamic_cast<const SdrPage*>(pPage); 493 } 494 495 496 497 498 void PresenterPreviewCache::PresenterCacheContext::CallListeners ( 499 const sal_Int32 nIndex) 500 { 501 ListenerContainer aListeners (maListeners); 502 ListenerContainer::const_iterator iListener; 503 for (iListener=aListeners.begin(); iListener!=aListeners.end(); ++iListener) 504 { 505 try 506 { 507 (*iListener)->notifyPreviewCreation(nIndex); 508 } 509 catch (lang::DisposedException&) 510 { 511 RemovePreviewCreationNotifyListener(*iListener); 512 } 513 } 514 } 515 516 } } // end of namespace ::sd::presenter 517