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 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sdext.hxx"
30 
31 #include "PresenterViewFactory.hxx"
32 #include "PresenterPaneContainer.hxx"
33 #include "PresenterHelper.hxx"
34 #include "PresenterHelpView.hxx"
35 #include "PresenterNotesView.hxx"
36 #include "PresenterSlideShowView.hxx"
37 #include "PresenterSlidePreview.hxx"
38 #include "PresenterSlideSorter.hxx"
39 #include "PresenterToolBar.hxx"
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/drawing/framework/ResourceId.hpp>
42 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
43 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
44 #include <com/sun/star/drawing/XDrawPages.hpp>
45 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
46 #include <com/sun/star/drawing/XSlideSorterBase.hpp>
47 #include <com/sun/star/presentation/XSlideShow.hpp>
48 #include <com/sun/star/presentation/XSlideShowView.hpp>
49 #include <cppuhelper/compbase1.hxx>
50 #include <boost/bind.hpp>
51 
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::drawing::framework;
55 using ::rtl::OUString;
56 
57 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
58 
59 namespace sdext { namespace presenter {
60 
61 const ::rtl::OUString PresenterViewFactory::msCurrentSlidePreviewViewURL(
62     A2S("private:resource/view/Presenter/CurrentSlidePreview"));
63 const ::rtl::OUString PresenterViewFactory::msNextSlidePreviewViewURL(
64     A2S("private:resource/view/Presenter/NextSlidePreview"));
65 const ::rtl::OUString PresenterViewFactory::msNotesViewURL(
66     A2S("private:resource/view/Presenter/Notes"));
67 const ::rtl::OUString PresenterViewFactory::msToolBarViewURL(
68     A2S("private:resource/view/Presenter/ToolBar"));
69 const ::rtl::OUString PresenterViewFactory::msSlideSorterURL(
70     A2S("private:resource/view/Presenter/SlideSorter"));
71 const ::rtl::OUString PresenterViewFactory::msHelpViewURL(
72     A2S("private:resource/view/Presenter/Help"));
73 
74 
75 
76 //===== SimpleView ============================================================
77 
78 namespace {
79 
80 typedef ::cppu::WeakComponentImplHelper1 <XView> SimpleViewInterfaceBase;
81 
82 class SimpleView
83     : private ::cppu::BaseMutex,
84       public SimpleViewInterfaceBase
85 {
86 public:
87     SimpleView (const Reference<XResourceId>& rxViewId)
88         : SimpleViewInterfaceBase(m_aMutex),mxResourceId(rxViewId) {};
89     virtual ~SimpleView (void) {};
90 
91     // XView
92 
93     virtual Reference<XResourceId> SAL_CALL getResourceId (void) throw (RuntimeException)
94     { return mxResourceId; };
95 
96 private:
97     Reference<XResourceId> mxResourceId;
98 };
99 
100 
101 
102 /** By default the PresenterSlidePreview shows the preview of the current
103     slide.  This adapter class makes it display the preview of the next
104     slide.
105 */
106 class NextSlidePreview : public PresenterSlidePreview
107 {
108 public:
109     NextSlidePreview (
110         const css::uno::Reference<css::uno::XComponentContext>& rxContext,
111         const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId,
112         const css::uno::Reference<css::drawing::framework::XPane>& rxAnchorPane,
113         const ::rtl::Reference<PresenterController>& rpPresenterController)
114         : PresenterSlidePreview(rxContext, rxViewId, rxAnchorPane, rpPresenterController)
115     {
116     }
117     virtual ~NextSlidePreview (void) {}
118     virtual void SAL_CALL setCurrentPage (
119         const css::uno::Reference<css::drawing::XDrawPage>& rxSlide)
120         throw (css::uno::RuntimeException)
121     {
122         Reference<presentation::XSlideShowController> xSlideShowController (
123             mpPresenterController->GetSlideShowController());
124         Reference<drawing::XDrawPage> xSlide;
125         if (xSlideShowController.is())
126         {
127             const sal_Int32 nCount (xSlideShowController->getSlideCount());
128             sal_Int32 nNextSlideIndex (-1);
129             if (xSlideShowController->getCurrentSlide() == rxSlide)
130             {
131                 nNextSlideIndex = xSlideShowController->getNextSlideIndex();
132             }
133             else
134             {
135                 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
136                 {
137                     if (rxSlide == Reference<drawing::XDrawPage>(
138                         xSlideShowController->getSlideByIndex(nIndex), UNO_QUERY))
139                     {
140                         nNextSlideIndex = nIndex + 1;
141                     }
142                 }
143             }
144             if (nNextSlideIndex >= 0)
145             {
146                 if (nNextSlideIndex < nCount)
147                 {
148                     xSlide = Reference<drawing::XDrawPage>(
149                         xSlideShowController->getSlideByIndex(nNextSlideIndex),
150                          UNO_QUERY);
151                 }
152             }
153         }
154         PresenterSlidePreview::setCurrentPage(xSlide);
155     }
156 };
157 
158 } // end of anonymous namespace
159 
160 
161 
162 
163 //===== PresenterViewFactory ==============================================
164 
165 PresenterViewFactory::PresenterViewFactory (
166     const Reference<uno::XComponentContext>& rxContext,
167     const Reference<frame::XController>& rxController,
168     const ::rtl::Reference<PresenterController>& rpPresenterController)
169     : PresenterViewFactoryInterfaceBase(m_aMutex),
170       mxComponentContext(rxContext),
171       mxConfigurationController(),
172       mxControllerWeak(rxController),
173       mpPresenterController(rpPresenterController),
174       mpResourceCache()
175 {
176 }
177 
178 
179 
180 
181 Reference<drawing::framework::XResourceFactory> PresenterViewFactory::Create (
182     const Reference<uno::XComponentContext>& rxContext,
183     const Reference<frame::XController>& rxController,
184     const ::rtl::Reference<PresenterController>& rpPresenterController)
185 {
186     rtl::Reference<PresenterViewFactory> pFactory (
187         new PresenterViewFactory(rxContext,rxController,rpPresenterController));
188     pFactory->Register(rxController);
189     return Reference<drawing::framework::XResourceFactory>(
190         static_cast<XWeak*>(pFactory.get()), UNO_QUERY);
191 }
192 
193 
194 
195 
196 void PresenterViewFactory::Register (const Reference<frame::XController>& rxController)
197 {
198     try
199     {
200         // Get the configuration controller.
201         Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
202         mxConfigurationController = xCM->getConfigurationController();
203         if ( ! mxConfigurationController.is())
204         {
205             throw RuntimeException();
206         }
207         else
208         {
209             mxConfigurationController->addResourceFactory(msCurrentSlidePreviewViewURL, this);
210             mxConfigurationController->addResourceFactory(msNextSlidePreviewViewURL, this);
211             mxConfigurationController->addResourceFactory(msNotesViewURL, this);
212             mxConfigurationController->addResourceFactory(msToolBarViewURL, this);
213             mxConfigurationController->addResourceFactory(msSlideSorterURL, this);
214             mxConfigurationController->addResourceFactory(msHelpViewURL, this);
215         }
216     }
217     catch (RuntimeException&)
218     {
219         OSL_ASSERT(false);
220         if (mxConfigurationController.is())
221             mxConfigurationController->removeResourceFactoryForReference(this);
222         mxConfigurationController = NULL;
223 
224         throw;
225     }
226 }
227 
228 
229 
230 
231 PresenterViewFactory::~PresenterViewFactory (void)
232 {
233 }
234 
235 
236 
237 
238 void SAL_CALL PresenterViewFactory::disposing (void)
239     throw (RuntimeException)
240 {
241     if (mxConfigurationController.is())
242         mxConfigurationController->removeResourceFactoryForReference(this);
243     mxConfigurationController = NULL;
244 
245     if (mpResourceCache.get() != NULL)
246     {
247         // Dispose all views in the cache.
248         ResourceContainer::const_iterator iView (mpResourceCache->begin());
249         ResourceContainer::const_iterator iEnd (mpResourceCache->end());
250         for ( ; iView!=iEnd; ++iView)
251         {
252             try
253             {
254                 Reference<lang::XComponent> xComponent (iView->second.first, UNO_QUERY);
255                 if (xComponent.is())
256                     xComponent->dispose();
257             }
258             catch (lang::DisposedException&)
259             {
260             }
261         }
262         mpResourceCache.reset();
263     }
264 }
265 
266 
267 
268 
269 //----- XViewFactory ----------------------------------------------------------
270 
271 Reference<XResource> SAL_CALL PresenterViewFactory::createResource (
272     const Reference<XResourceId>& rxViewId)
273     throw (RuntimeException)
274 {
275     ThrowIfDisposed();
276 
277     Reference<XResource> xView;
278 
279     if (rxViewId.is())
280     {
281         Reference<XPane> xAnchorPane (
282             mxConfigurationController->getResource(rxViewId->getAnchor()),
283             UNO_QUERY_THROW);
284         xView = GetViewFromCache(rxViewId, xAnchorPane);
285         if (xView == NULL)
286             xView = CreateView(rxViewId, xAnchorPane);
287 
288         // Activate the view.
289         PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
290             mpPresenterController->GetPaneContainer()->FindPaneId(rxViewId->getAnchor()));
291         if (pDescriptor.get() != NULL)
292             pDescriptor->SetActivationState(true);
293     }
294 
295     return xView;
296 }
297 
298 
299 
300 
301 void SAL_CALL PresenterViewFactory::releaseResource (const Reference<XResource>& rxView)
302     throw (RuntimeException)
303 {
304     ThrowIfDisposed();
305 
306     if ( ! rxView.is())
307         return;
308 
309     // Deactivate the view.
310     PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
311         mpPresenterController->GetPaneContainer()->FindPaneId(
312             rxView->getResourceId()->getAnchor()));
313     if (pDescriptor.get() != NULL)
314         pDescriptor->SetActivationState(false);
315 
316     // Dispose only views that we can not put into the cache.
317     CachablePresenterView* pView = dynamic_cast<CachablePresenterView*>(rxView.get());
318     if (pView == NULL || mpResourceCache.get()==NULL)
319     {
320         try
321         {
322             if (pView != NULL)
323                 pView->ReleaseView();
324             Reference<lang::XComponent> xComponent (rxView, UNO_QUERY);
325             if (xComponent.is())
326                 xComponent->dispose();
327         }
328         catch (lang::DisposedException&)
329         {
330             // Do not let disposed exceptions get out.  It might be interpreted
331             // as coming from the factory, which would then be removed from the
332             // drawing framework.
333         }
334     }
335     else
336     {
337         // Put cachable views in the cache.
338         Reference<XResourceId> xViewId (rxView->getResourceId());
339         if (xViewId.is())
340         {
341             Reference<XPane> xAnchorPane (
342                 mxConfigurationController->getResource(xViewId->getAnchor()),
343                 UNO_QUERY_THROW);
344             (*mpResourceCache)[xViewId->getResourceURL()]
345                 = ViewResourceDescriptor(Reference<XView>(rxView, UNO_QUERY), xAnchorPane);
346             pView->DeactivatePresenterView();
347         }
348     }
349 }
350 
351 
352 
353 
354 //-----------------------------------------------------------------------------
355 
356 Reference<XResource> PresenterViewFactory::GetViewFromCache(
357     const Reference<XResourceId>& rxViewId,
358     const Reference<XPane>& rxAnchorPane) const
359 {
360     if (mpResourceCache.get() == NULL)
361         return NULL;
362 
363     try
364     {
365         const OUString sResourceURL (rxViewId->getResourceURL());
366 
367         // Can we use a view from the cache?
368         ResourceContainer::const_iterator iView (mpResourceCache->find(sResourceURL));
369         if (iView != mpResourceCache->end())
370         {
371             // The view is in the container but it can only be used if
372             // the anchor pane is the same now as it was at creation of
373             // the view.
374             if (iView->second.second == rxAnchorPane)
375             {
376                 CachablePresenterView* pView
377                     = dynamic_cast<CachablePresenterView*>(iView->second.first.get());
378                 if (pView != NULL)
379                     pView->ActivatePresenterView();
380                 return Reference<XResource>(iView->second.first, UNO_QUERY);
381             }
382 
383             // Right view, wrong pane.  Create a new view.
384         }
385     }
386     catch (RuntimeException&)
387     {
388     }
389     return NULL;
390 }
391 
392 
393 
394 
395 Reference<XResource> PresenterViewFactory::CreateView(
396     const Reference<XResourceId>& rxViewId,
397     const Reference<XPane>& rxAnchorPane)
398 {
399     Reference<XView> xView;
400 
401     try
402     {
403         const OUString sResourceURL (rxViewId->getResourceURL());
404 
405         if (sResourceURL.equals(msCurrentSlidePreviewViewURL))
406         {
407             xView = CreateSlideShowView(rxViewId);
408         }
409         else if (sResourceURL.equals(msNotesViewURL))
410         {
411             xView = CreateNotesView(rxViewId, rxAnchorPane);
412         }
413         else if (sResourceURL.equals(msNextSlidePreviewViewURL))
414         {
415             xView = CreateSlidePreviewView(rxViewId, rxAnchorPane);
416         }
417         else if (sResourceURL.equals(msToolBarViewURL))
418         {
419             xView = CreateToolBarView(rxViewId);
420         }
421         else if (sResourceURL.equals(msSlideSorterURL))
422         {
423             xView = CreateSlideSorterView(rxViewId);
424         }
425         else if (sResourceURL.equals(msHelpViewURL))
426         {
427             xView = CreateHelpView(rxViewId);
428         }
429 
430         // Activate it.
431         CachablePresenterView* pView = dynamic_cast<CachablePresenterView*>(xView.get());
432         if (pView != NULL)
433             pView->ActivatePresenterView();
434     }
435     catch (RuntimeException&)
436     {
437         xView = NULL;
438     }
439 
440     return Reference<XResource>(xView, UNO_QUERY);
441 }
442 
443 
444 
445 
446 Reference<XView> PresenterViewFactory::CreateSlideShowView(
447     const Reference<XResourceId>& rxViewId) const
448 {
449     Reference<XView> xView;
450 
451     if ( ! mxConfigurationController.is())
452         return xView;
453     if ( ! mxComponentContext.is())
454         return xView;
455 
456     try
457     {
458         rtl::Reference<PresenterSlideShowView> pShowView (
459             new PresenterSlideShowView(
460                 mxComponentContext,
461                 rxViewId,
462                 Reference<frame::XController>(mxControllerWeak),
463                 mpPresenterController));
464         pShowView->LateInit();
465         xView = Reference<XView>(pShowView.get());
466     }
467     catch (RuntimeException&)
468     {
469         xView = NULL;
470     }
471 
472     return xView;
473 }
474 
475 
476 
477 
478 Reference<XView> PresenterViewFactory::CreateSlidePreviewView(
479     const Reference<XResourceId>& rxViewId,
480     const Reference<XPane>& rxAnchorPane) const
481 {
482     Reference<XView> xView;
483 
484     if ( ! mxConfigurationController.is())
485         return xView;
486     if ( ! mxComponentContext.is())
487         return xView;
488 
489     try
490     {
491         xView = Reference<XView>(
492             static_cast<XWeak*>(new NextSlidePreview(
493                 mxComponentContext,
494                 rxViewId,
495                 rxAnchorPane,
496                 mpPresenterController)),
497             UNO_QUERY_THROW);
498     }
499     catch (RuntimeException&)
500     {
501         xView = NULL;
502     }
503 
504     return xView;
505 }
506 
507 
508 
509 
510 Reference<XView> PresenterViewFactory::CreateToolBarView(
511     const Reference<XResourceId>& rxViewId) const
512 {
513     return new PresenterToolBarView(
514         mxComponentContext,
515         rxViewId,
516         Reference<frame::XController>(mxControllerWeak),
517         mpPresenterController);
518 }
519 
520 
521 
522 
523 Reference<XView> PresenterViewFactory::CreateNotesView(
524     const Reference<XResourceId>& rxViewId,
525     const Reference<XPane>& rxAnchorPane) const
526 {
527     (void)rxAnchorPane;
528     Reference<XView> xView;
529 
530     if ( ! mxConfigurationController.is())
531         return xView;
532     if ( ! mxComponentContext.is())
533         return xView;
534 
535     try
536     {
537         xView = Reference<XView>(static_cast<XWeak*>(
538             new PresenterNotesView(
539                 mxComponentContext,
540                 rxViewId,
541                 Reference<frame::XController>(mxControllerWeak),
542                 mpPresenterController)),
543             UNO_QUERY_THROW);
544     }
545     catch (RuntimeException&)
546     {
547         xView = NULL;
548     }
549 
550     return xView;
551 }
552 
553 
554 
555 
556 Reference<XView> PresenterViewFactory::CreateSlideSorterView(
557     const Reference<XResourceId>& rxViewId) const
558 {
559     Reference<XView> xView;
560 
561     if ( ! mxConfigurationController.is())
562         return xView;
563     if ( ! mxComponentContext.is())
564         return xView;
565 
566     try
567     {
568         rtl::Reference<PresenterSlideSorter> pView (
569             new PresenterSlideSorter(
570                 mxComponentContext,
571                 rxViewId,
572                 Reference<frame::XController>(mxControllerWeak),
573                 mpPresenterController));
574         PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
575             mpPresenterController->GetPaneContainer()->FindPaneId(rxViewId->getAnchor()));
576         if (pDescriptor.get() != NULL)
577             pDescriptor->maActivator = ::boost::bind(
578                 &PresenterSlideSorter::SetActiveState, pView.get(), _1);
579         xView = pView.get();
580     }
581     catch (RuntimeException&)
582     {
583         xView = NULL;
584     }
585 
586     return xView;
587 }
588 
589 
590 
591 
592 Reference<XView> PresenterViewFactory::CreateHelpView(
593     const Reference<XResourceId>& rxViewId) const
594 {
595     return Reference<XView>(new PresenterHelpView(
596         mxComponentContext,
597         rxViewId,
598         Reference<frame::XController>(mxControllerWeak),
599         mpPresenterController));
600 }
601 
602 
603 
604 
605 
606 void PresenterViewFactory::ThrowIfDisposed (void) const
607     throw (::com::sun::star::lang::DisposedException)
608 {
609 	if (rBHelper.bDisposed || rBHelper.bInDispose)
610 	{
611         throw lang::DisposedException (
612             OUString(RTL_CONSTASCII_USTRINGPARAM(
613                 "PresenterViewFactory object has already been disposed")),
614             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
615     }
616 }
617 
618 
619 
620 
621 //===== CachablePresenterView =================================================
622 
623 CachablePresenterView::CachablePresenterView (void)
624     : mbIsPresenterViewActive(true)
625 {
626 }
627 
628 
629 
630 
631 void CachablePresenterView::ActivatePresenterView (void)
632 {
633     mbIsPresenterViewActive = true;
634 }
635 
636 
637 
638 
639 void CachablePresenterView::DeactivatePresenterView (void)
640 {
641     mbIsPresenterViewActive = false;
642 }
643 
644 
645 
646 
647 void CachablePresenterView::ReleaseView (void)
648 {
649 }
650 
651 
652 
653 } }
654