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