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