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