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