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 "PresenterController.hxx"
28 
29 #include "PresenterAccessibility.hxx"
30 #include "PresenterAnimator.hxx"
31 #include "PresenterCanvasHelper.hxx"
32 #include "PresenterCurrentSlideObserver.hxx"
33 #include "PresenterFrameworkObserver.hxx"
34 #include "PresenterHelper.hxx"
35 #include "PresenterNotesView.hxx"
36 #include "PresenterPaintManager.hxx"
37 #include "PresenterPaneAnimator.hxx"
38 #include "PresenterPaneBase.hxx"
39 #include "PresenterPaneContainer.hxx"
40 #include "PresenterPaneBorderPainter.hxx"
41 #include "PresenterTheme.hxx"
42 #include "PresenterViewFactory.hxx"
43 #include "PresenterWindowManager.hxx"
44 
45 #include <com/sun/star/accessibility/AccessibleRole.hpp>
46 #include <com/sun/star/accessibility/XAccessible.hpp>
47 #include <com/sun/star/awt/Key.hpp>
48 #include <com/sun/star/awt/KeyModifier.hpp>
49 #include <com/sun/star/awt/MouseButton.hpp>
50 #include <com/sun/star/awt/XWindowPeer.hpp>
51 #include <com/sun/star/container/XNamed.hpp>
52 #include <com/sun/star/drawing/XDrawView.hpp>
53 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
54 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
55 #include <com/sun/star/drawing/framework/ResourceId.hpp>
56 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
57 #include <com/sun/star/frame/FrameSearchFlag.hpp>
58 #include <com/sun/star/frame/XDispatchProvider.hpp>
59 #include <com/sun/star/presentation/XPresentation.hpp>
60 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
61 #include <com/sun/star/rendering/CompositeOperation.hpp>
62 #include <com/sun/star/rendering/TextDirection.hpp>
63 
64 #include <rtl/ustrbuf.hxx>
65 #include <boost/bind.hpp>
66 
67 using namespace ::com::sun::star;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::presentation;
70 using namespace ::com::sun::star::drawing::framework;
71 using ::rtl::OUString;
72 using ::rtl::OUStringBuffer;
73 
74 namespace {
75     const sal_Int32 ResourceActivationEventType = 0;
76     const sal_Int32 ResourceDeactivationEventType = 1;
77     const sal_Int32 ConfigurationUpdateEndEventType = 2;
78 }
79 
80 
81 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
82 
83 
84 namespace sdext { namespace presenter {
85 
86 PresenterController::InstanceContainer PresenterController::maInstances;
87 
Instance(const css::uno::Reference<css::frame::XFrame> & rxFrame)88 ::rtl::Reference<PresenterController> PresenterController::Instance (
89     const css::uno::Reference<css::frame::XFrame>& rxFrame)
90 {
91     InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame));
92     if (iInstance != maInstances.end())
93         return iInstance->second;
94     else
95         return ::rtl::Reference<PresenterController>();
96 }
97 
98 
99 
100 
PresenterController(const Reference<XComponentContext> & rxContext,const Reference<frame::XController> & rxController,const Reference<presentation::XSlideShowController> & rxSlideShowController,const rtl::Reference<PresenterPaneContainer> & rpPaneContainer,const Reference<XResourceId> & rxMainPaneId)101 PresenterController::PresenterController (
102     const Reference<XComponentContext>& rxContext,
103     const Reference<frame::XController>& rxController,
104     const Reference<presentation::XSlideShowController>& rxSlideShowController,
105     const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
106     const Reference<XResourceId>& rxMainPaneId)
107     : PresenterControllerInterfaceBase(m_aMutex),
108       mxComponentContext(rxContext),
109       mxController(rxController),
110       mxConfigurationController(),
111       mxSlideShowController(rxSlideShowController),
112       mxMainPaneId(rxMainPaneId),
113       mpPaneContainer(rpPaneContainer),
114       mnCurrentSlideIndex(-1),
115       mxCurrentSlide(),
116       mxNextSlide(),
117       mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)),
118       mpCurrentPaneAnimation(),
119       mnWindowBackgroundColor(0x00ffffff),
120       mpTheme(),
121       mxMainWindow(),
122       mpPaneBorderPainter(),
123       mpAnimator(new PresenterAnimator()),
124       mpCanvasHelper(new PresenterCanvasHelper()),
125       mxPresenterHelper(),
126       mpPaintManager(),
127       mnPendingSlideNumber(-1),
128       mxUrlTransformer(),
129       mpAccessibleObject(),
130       mbIsAccessibilityActive(false)
131 {
132     OSL_ASSERT(mxController.is());
133 
134     if ( ! mxSlideShowController.is())
135         throw new lang::IllegalArgumentException(
136             A2S("missing slide show controller"),
137             static_cast<XWeak*>(this),
138             2);
139 
140     new PresenterCurrentSlideObserver(this,rxSlideShowController);
141 
142     // Listen for configuration changes.
143     Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW);
144     mxConfigurationController = xCM->getConfigurationController();
145     if (mxConfigurationController.is())
146     {
147         mxConfigurationController->addConfigurationChangeListener(
148             this,
149             A2S("ResourceActivation"),
150             Any(ResourceActivationEventType));
151         mxConfigurationController->addConfigurationChangeListener(
152             this,
153             A2S("ResourceDeactivation"),
154             Any(ResourceDeactivationEventType));
155         mxConfigurationController->addConfigurationChangeListener(
156             this,
157             A2S("ConfigurationUpdateEnd"),
158             Any(ConfigurationUpdateEndEventType));
159     }
160 
161     // Listen for the frame being activated.
162     Reference<frame::XFrame> xFrame (mxController->getFrame());
163     if (xFrame.is())
164         xFrame->addFrameActionListener(this);
165 
166     // Create the border painter.
167     mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext);
168     mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter);
169 
170     // Create an object that is able to load the bitmaps in a format that is
171     // supported by the canvas.
172     Reference<lang::XMultiComponentFactory> xFactory (
173         rxContext->getServiceManager(), UNO_QUERY);
174     if ( ! xFactory.is())
175         return;
176     mxPresenterHelper = Reference<drawing::XPresenterHelper>(
177         xFactory->createInstanceWithContext(
178             A2S("com.sun.star.drawing.PresenterHelper"),
179             rxContext),
180         UNO_QUERY_THROW);
181 
182     if (mxSlideShowController.is())
183     {
184         mxSlideShowController->activate();
185         Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY);
186         if (xProperties.is())
187         {
188             Reference<awt::XWindow> xWindow (
189                 xProperties->getPropertyValue(A2S("ParentWindow")), UNO_QUERY);
190             if (xWindow.is())
191                 xWindow->addKeyListener(this);
192         }
193     }
194 
195     UpdateCurrentSlide(0);
196 
197     maInstances[mxController->getFrame()] = this;
198 
199     // Create a URLTransformer.
200     if (xFactory.is())
201     {
202         mxUrlTransformer = Reference<util::XURLTransformer>(
203             xFactory->createInstanceWithContext(
204                 A2S("com.sun.star.util.URLTransformer"),
205                 mxComponentContext),
206             UNO_QUERY);
207     }
208 }
209 
210 
211 
212 
~PresenterController(void)213 PresenterController::~PresenterController (void)
214 {
215 }
216 
217 
218 
219 
disposing(void)220 void PresenterController::disposing (void)
221 {
222     maInstances.erase(mxController->getFrame());
223 
224     if (mxMainWindow.is())
225     {
226         mxMainWindow->removeKeyListener(this);
227         mxMainWindow->removeFocusListener(this);
228         mxMainWindow->removeMouseListener(this);
229         mxMainWindow->removeMouseMotionListener(this);
230         mxMainWindow = NULL;
231     }
232     if (mxConfigurationController.is())
233         mxConfigurationController->removeConfigurationChangeListener(this);
234 
235     Reference<XComponent> xWindowManagerComponent (
236         static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY);
237     mpWindowManager = NULL;
238     if (xWindowManagerComponent.is())
239         xWindowManagerComponent->dispose();
240 
241     if (mxController.is())
242     {
243         Reference<frame::XFrame> xFrame (mxController->getFrame());
244         if (xFrame.is())
245             xFrame->removeFrameActionListener(this);
246         mxController = NULL;
247     }
248 
249     mxComponentContext = NULL;
250     mxConfigurationController = NULL;
251     mxSlideShowController = NULL;
252     mxMainPaneId = NULL;
253     mpPaneContainer = NULL;
254     mnCurrentSlideIndex = -1;
255     mxCurrentSlide = NULL;
256     mxNextSlide = NULL;
257     mpCurrentPaneAnimation.reset();
258     mpTheme.reset();
259     {
260         Reference<lang::XComponent> xComponent (
261             static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY);
262         mpPaneBorderPainter = NULL;
263         if (xComponent.is())
264             xComponent->dispose();
265     }
266     mpAnimator.reset();
267     mpCanvasHelper.reset();
268     {
269         Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY);
270         mxPresenterHelper = NULL;
271         if (xComponent.is())
272             xComponent->dispose();
273     }
274     mpPaintManager.reset();
275     mnPendingSlideNumber = -1;
276     {
277         Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY);
278         mxUrlTransformer = NULL;
279         if (xComponent.is())
280             xComponent->dispose();
281     }
282 }
283 
284 
285 
286 
UpdateCurrentSlide(const sal_Int32 nOffset)287 void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset)
288 {
289     GetSlides(nOffset);
290     UpdatePaneTitles();
291     UpdateViews();
292 
293     // Update the accessibility object.
294     if (IsAccessibilityActive())
295     {
296         sal_Int32 nSlideCount (0);
297         Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
298         if (xIndexAccess.is())
299             nSlideCount = xIndexAccess->getCount();
300         mpAccessibleObject->NotifyCurrentSlideChange(mnCurrentSlideIndex, nSlideCount);
301     }
302 }
303 
304 
305 
306 
GetSlides(const sal_Int32 nOffset)307 void PresenterController::GetSlides (const sal_Int32 nOffset)
308 {
309     if ( ! mxSlideShowController.is())
310         return;
311 
312     // Get the current slide from the slide show controller.
313     mxCurrentSlide = NULL;
314     Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
315     sal_Int32 nSlideIndex = -1;
316     try
317     {
318         nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset;
319         if (mxSlideShowController->isPaused())
320             nSlideIndex = -1;
321 
322         if (xIndexAccess.is() && nSlideIndex>=0)
323         {
324             if (nSlideIndex < xIndexAccess->getCount())
325             {
326                 mnCurrentSlideIndex = nSlideIndex;
327                 mxCurrentSlide = Reference<drawing::XDrawPage>(
328                     xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
329             }
330         }
331     }
332     catch (RuntimeException&)
333     {
334     }
335 
336     // Get the next slide.
337     mxNextSlide = NULL;
338     try
339     {
340         const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset);
341         if (nNextSlideIndex >= 0)
342         {
343             if (xIndexAccess.is())
344             {
345                 if (nNextSlideIndex < xIndexAccess->getCount())
346                     mxNextSlide = Reference<drawing::XDrawPage>(
347                         xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY);
348             }
349         }
350     }
351     catch (RuntimeException&)
352     {
353     }
354 }
355 
356 
357 
358 
UpdatePaneTitles(void)359 void PresenterController::UpdatePaneTitles (void)
360 {
361     if ( ! mxSlideShowController.is())
362         return;
363 
364     // Get placeholders and their values.
365     const OUString sCurrentSlideNumberPlaceholder (A2S("CURRENT_SLIDE_NUMBER"));
366     const OUString sCurrentSlideNamePlaceholder (A2S("CURRENT_SLIDE_NAME"));
367     const OUString sSlideCountPlaceholder (A2S("SLIDE_COUNT"));
368 
369     // Get string for slide count.
370     OUString sSlideCount (A2S("---"));
371     Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
372     if (xIndexAccess.is())
373         sSlideCount = OUString::valueOf(xIndexAccess->getCount());
374 
375     // Get string for current slide index.
376     OUString sCurrentSlideNumber (OUString::valueOf(mnCurrentSlideIndex + 1));
377 
378     // Get name of the current slide.
379     OUString sCurrentSlideName;
380     Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY);
381     if (xNamedSlide.is())
382         sCurrentSlideName = xNamedSlide->getName();
383     Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY);
384     if (xSlideProperties.is())
385     {
386         try
387         {
388             OUString sName;
389             if (xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= sName)
390             {
391                 // Find out whether the name of the current slide has been
392                 // automatically created or has been set by the user.
393                 if (sName != sCurrentSlideName)
394                     sCurrentSlideName = sName;
395             }
396         }
397         catch (beans::UnknownPropertyException&)
398         {
399         }
400     }
401 
402     // Replace the placeholders with their current values.
403     PresenterPaneContainer::PaneList::const_iterator iPane;
404     for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
405     {
406         OSL_ASSERT((*iPane).get() != NULL);
407 
408         OUString sTemplate (IsAccessibilityActive()
409             ? (*iPane)->msAccessibleTitleTemplate
410             : (*iPane)->msTitleTemplate);
411         if (sTemplate.getLength() <= 0)
412             continue;
413 
414         OUStringBuffer sResult;
415         sResult.ensureCapacity(sTemplate.getLength());
416 
417         sal_Int32 nIndex (0);
418         while (true)
419         {
420             sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex);
421             if (nStartIndex < 0)
422             {
423                 // Add the remaining part of the string.
424                 sResult.append(sTemplate.copy(nIndex, sTemplate.getLength()-nIndex));
425                 break;
426             }
427             else
428             {
429                 // Add the part preceding the next %.
430                 sResult.append(sTemplate.copy(nIndex, nStartIndex-nIndex));
431 
432                 // Get the placeholder
433                 ++nIndex;
434                 ++nStartIndex;
435                 const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1));
436                 const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex));
437                 nIndex = nEndIndex+1;
438 
439                 // Replace the placeholder with its current value.
440                 if (sPlaceholder == sCurrentSlideNumberPlaceholder)
441                     sResult.append(sCurrentSlideNumber);
442                 else if (sPlaceholder == sCurrentSlideNamePlaceholder)
443                     sResult.append(sCurrentSlideName);
444                 else if (sPlaceholder == sSlideCountPlaceholder)
445                     sResult.append(sSlideCount);
446             }
447         }
448 
449         (*iPane)->msTitle = sResult.makeStringAndClear();
450         if ((*iPane)->mxPane.is())
451             (*iPane)->mxPane->SetTitle((*iPane)->msTitle);
452     }
453 }
454 
455 
456 
457 
UpdateViews(void)458 void PresenterController::UpdateViews (void)
459 {
460     // Tell all views about the slides they should display.
461     PresenterPaneContainer::PaneList::const_iterator iPane;
462     for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
463     {
464         Reference<drawing::XDrawView> xDrawView ((*iPane)->mxView, UNO_QUERY);
465         if (xDrawView.is())
466             xDrawView->setCurrentPage(mxCurrentSlide);
467     }
468 }
469 
470 
471 
472 
473 SharedBitmapDescriptor
GetViewBackground(const::rtl::OUString & rsViewURL) const474     PresenterController::GetViewBackground (const ::rtl::OUString& rsViewURL) const
475 {
476     if (mpTheme.get() != NULL)
477     {
478         const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
479         return mpTheme->GetBitmap(sStyleName, A2S("Background"));
480     }
481     return SharedBitmapDescriptor();
482 }
483 
484 
485 
486 
487 PresenterTheme::SharedFontDescriptor
GetViewFont(const::rtl::OUString & rsViewURL) const488     PresenterController::GetViewFont (const ::rtl::OUString& rsViewURL) const
489 {
490     if (mpTheme.get() != NULL)
491     {
492         const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
493         return mpTheme->GetFont(sStyleName);
494     }
495     return PresenterTheme::SharedFontDescriptor();
496 }
497 
498 
499 
500 
GetTheme(void) const501 ::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme (void) const
502 {
503     return mpTheme;
504 }
505 
506 
507 
508 
GetWindowManager(void) const509 ::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const
510 {
511     return mpWindowManager;
512 }
513 
514 
515 
516 
517 Reference<presentation::XSlideShowController>
GetSlideShowController(void) const518     PresenterController::GetSlideShowController(void) const
519 {
520     return mxSlideShowController;
521 }
522 
523 
524 
525 
GetPaneContainer(void) const526 rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const
527 {
528     return mpPaneContainer;
529 }
530 
531 
532 
533 
GetPaneBorderPainter(void) const534 ::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const
535 {
536     return mpPaneBorderPainter;
537 }
538 
539 
540 
541 
GetAnimator(void) const542 ::boost::shared_ptr<PresenterAnimator> PresenterController::GetAnimator (void) const
543 {
544     return mpAnimator;
545 }
546 
547 
548 
549 
GetCanvasHelper(void) const550 ::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const
551 {
552     return mpCanvasHelper;
553 }
554 
555 
556 
557 
GetPresenterHelper(void) const558 Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const
559 {
560     return mxPresenterHelper;
561 }
562 
563 
564 
565 
GetPaintManager(void) const566 ::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) const
567 {
568     return mpPaintManager;
569 }
570 
571 
572 
573 
HideSlideSorter(void)574 void PresenterController::HideSlideSorter (void)
575 {
576     if (mpCurrentPaneAnimation.get() != NULL)
577     {
578         mpCurrentPaneAnimation->HidePane();
579         mpCurrentPaneAnimation.reset();
580     }
581 }
582 
583 
584 
585 
ShowView(const OUString & rsViewURL)586 void PresenterController::ShowView (const OUString& rsViewURL)
587 {
588     PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
589         mpPaneContainer->FindViewURL(rsViewURL));
590     if (pDescriptor.get() != NULL)
591     {
592         pDescriptor->mbIsActive = true;
593         mxConfigurationController->requestResourceActivation(
594             pDescriptor->mxPaneId,
595             ResourceActivationMode_ADD);
596         mxConfigurationController->requestResourceActivation(
597             ResourceId::createWithAnchor(
598                 mxComponentContext,
599                 rsViewURL,
600                 pDescriptor->mxPaneId),
601             ResourceActivationMode_REPLACE);
602     }
603 }
604 
605 
606 
607 
HideView(const OUString & rsViewURL)608 void PresenterController::HideView (const OUString& rsViewURL)
609 {
610     PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
611         mpPaneContainer->FindViewURL(rsViewURL));
612     if (pDescriptor.get() != NULL)
613     {
614         mxConfigurationController->requestResourceDeactivation(
615             ResourceId::createWithAnchor(
616                 mxComponentContext,
617                 rsViewURL,
618                 pDescriptor->mxPaneId));
619     }
620 }
621 
622 
623 
624 
IsViewVisible(const OUString & rsViewURL) const625 bool PresenterController::IsViewVisible (const OUString& rsViewURL) const
626 {
627    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
628         mpPaneContainer->FindViewURL(rsViewURL));
629     if (pDescriptor.get() != NULL)
630     {
631         return mxConfigurationController->getResource(
632             ResourceId::createWithAnchor(
633                 mxComponentContext,
634                 rsViewURL,
635                 pDescriptor->mxPaneId)).is();
636     }
637     return false;
638 }
639 
640 
641 
642 
DispatchUnoCommand(const OUString & rsCommand) const643 void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const
644 {
645     if ( ! mxUrlTransformer.is())
646         return;
647 
648     util::URL aURL;
649     aURL.Complete = rsCommand;
650     mxUrlTransformer->parseStrict(aURL);
651 
652     Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
653     if ( ! xDispatch.is())
654         return;
655 
656     xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
657 }
658 
659 
660 
661 
GetDispatch(const util::URL & rURL) const662 Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const
663 {
664     if ( ! mxController.is())
665         return NULL;
666 
667     Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY);
668     if ( ! xDispatchProvider.is())
669         return NULL;
670 
671     return xDispatchProvider->queryDispatch(
672         rURL,
673         OUString(),
674         frame::FrameSearchFlag::SELF);
675 }
676 
677 
678 
679 
CreateURLFromString(const::rtl::OUString & rsURL) const680 util::URL PresenterController::CreateURLFromString (const ::rtl::OUString& rsURL) const
681 {
682     util::URL aURL;
683 
684     if (mxUrlTransformer.is())
685     {
686         aURL.Complete = rsURL;
687         mxUrlTransformer->parseStrict(aURL);
688     }
689 
690     return aURL;
691 }
692 
693 
694 
695 
696 Reference<drawing::framework::XConfigurationController>
GetConfigurationController(void) const697     PresenterController::GetConfigurationController (void) const
698 {
699     return mxConfigurationController;
700 }
701 
702 
703 
704 
GetCurrentSlide(void) const705 Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const
706 {
707     return mxCurrentSlide;
708 }
709 
710 
711 
712 
GetAccessible(void) const713 ::rtl::Reference<PresenterAccessible> PresenterController::GetAccessible (void) const
714 {
715     return mpAccessibleObject;
716 }
717 
718 
719 
720 
SetAccessibilityActiveState(const bool bIsActive)721 void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
722 {
723     if ( mbIsAccessibilityActive != bIsActive)
724     {
725         mbIsAccessibilityActive = bIsActive;
726         UpdatePaneTitles();
727     }
728 }
729 
730 
731 
732 
IsAccessibilityActive(void) const733 bool PresenterController::IsAccessibilityActive (void) const
734 {
735     return mbIsAccessibilityActive;
736 }
737 
738 
739 
740 
HandleMouseClick(const awt::MouseEvent & rEvent)741 void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
742 {
743     if (mxSlideShowController.is())
744     {
745         switch (rEvent.Buttons)
746         {
747             case awt::MouseButton::LEFT:
748                 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
749                     mxSlideShowController->gotoNextSlide();
750                 else
751                     mxSlideShowController->gotoNextEffect();
752                 break;
753 
754             case awt::MouseButton::RIGHT:
755                 mxSlideShowController->gotoPreviousSlide();
756                 break;
757 
758             default:
759                 // Other or multiple buttons.
760                 break;
761         }
762     }
763 }
764 
765 
766 
767 
RequestViews(const bool bIsSlideSorterActive,const bool bIsNotesViewActive,const bool bIsHelpViewActive)768 void PresenterController::RequestViews (
769     const bool bIsSlideSorterActive,
770     const bool bIsNotesViewActive,
771     const bool bIsHelpViewActive)
772 {
773     PresenterPaneContainer::PaneList::const_iterator iPane;
774     PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
775     for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
776     {
777         bool bActivate (true);
778         const OUString sViewURL ((*iPane)->msViewURL);
779         if (sViewURL == PresenterViewFactory::msNotesViewURL)
780         {
781             bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
782         }
783         else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
784         {
785             bActivate = bIsSlideSorterActive;
786         }
787         else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
788             || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
789         {
790             bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
791         }
792         else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
793         {
794             bActivate = true;
795         }
796         else if (sViewURL == PresenterViewFactory::msHelpViewURL)
797         {
798             bActivate = bIsHelpViewActive;
799         }
800 
801         if (bActivate)
802             ShowView(sViewURL);
803         else
804             HideView(sViewURL);
805     }
806 }
807 
808 
809 
810 
811 //----- XConfigurationChangeListener ------------------------------------------
812 
notifyConfigurationChange(const ConfigurationChangeEvent & rEvent)813 void SAL_CALL PresenterController::notifyConfigurationChange (
814     const ConfigurationChangeEvent& rEvent)
815     throw (RuntimeException)
816 {
817     ThrowIfDisposed();
818 
819     sal_Int32 nType (0);
820     if ( ! (rEvent.UserData >>= nType))
821         return;
822 
823     switch (nType)
824     {
825         case ResourceActivationEventType:
826             if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
827             {
828                 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
829             }
830             else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
831             {
832                 // A pane bound to the main pane has been created and is
833                 // stored in the pane container.
834                 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
835                 if (xPane.is())
836                 {
837                     PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
838                         mpPaneContainer->FindPaneId(xPane->getResourceId()));
839 
840                     // When there is a call out anchor location set then tell the
841                     // window about it.
842                     if (pDescriptor->mbHasCalloutAnchor)
843                         pDescriptor->mxPane->SetCalloutAnchor(
844                             pDescriptor->maCalloutAnchorLocation);
845                 }
846             }
847             else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
848             {
849                 // A view bound to one of the panes has been created and is
850                 // stored in the pane container along with its pane.
851                 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
852                 if (xView.is())
853                 {
854                     SharedBitmapDescriptor pViewBackground(
855                         GetViewBackground(xView->getResourceId()->getResourceURL()));
856                     mpPaneContainer->StoreView(xView, pViewBackground);
857                     UpdateViews();
858                     mpWindowManager->NotifyViewCreation(xView);
859                 }
860             }
861             break;
862 
863         case ResourceDeactivationEventType:
864             if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
865             {
866                 // If this is a view then remove it from the pane container.
867                 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
868                 if (xView.is())
869                 {
870                     PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
871                         mpPaneContainer->RemoveView(xView));
872 
873                     // A possibly opaque view has been removed.  Update()
874                     // updates the clip polygon.
875                     mpWindowManager->Update();
876                     // Request the repainting of the area previously
877                     // occupied by the view.
878                     if (pDescriptor.get() != NULL)
879                         GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
880                 }
881             }
882             break;
883 
884         case ConfigurationUpdateEndEventType:
885             if (IsAccessibilityActive())
886             {
887                 mpAccessibleObject->UpdateAccessibilityHierarchy();
888                 UpdateCurrentSlide(0);
889             }
890             break;
891     }
892 }
893 
894 
895 
896 
897 //----- XEventListener --------------------------------------------------------
898 
disposing(const lang::EventObject & rEvent)899 void SAL_CALL PresenterController::disposing (
900     const lang::EventObject& rEvent)
901     throw (RuntimeException)
902 {
903     if (rEvent.Source == mxController)
904         mxController = NULL;
905     else if (rEvent.Source == mxConfigurationController)
906         mxConfigurationController = NULL;
907     else if (rEvent.Source == mxSlideShowController)
908         mxSlideShowController = NULL;
909     else if (rEvent.Source == mxMainWindow)
910         mxMainWindow = NULL;
911 }
912 
913 
914 
915 
916 //----- XFrameActionListener --------------------------------------------------
917 
frameAction(const frame::FrameActionEvent & rEvent)918 void SAL_CALL PresenterController::frameAction (
919     const frame::FrameActionEvent& rEvent)
920     throw (RuntimeException)
921 {
922     if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
923     {
924         if (mxSlideShowController.is())
925             mxSlideShowController->activate();
926     }
927 }
928 
929 
930 
931 
932 //----- XKeyListener ----------------------------------------------------------
933 
keyPressed(const awt::KeyEvent & rEvent)934 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
935     throw (RuntimeException)
936 {
937     // Tell all views about the unhandled key event.
938     PresenterPaneContainer::PaneList::const_iterator iPane;
939     for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
940     {
941         if ( ! (*iPane)->mbIsActive)
942             continue;
943 
944         Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
945         if (xKeyListener.is())
946             xKeyListener->keyPressed(rEvent);
947     }
948 }
949 
950 
951 
952 
keyReleased(const awt::KeyEvent & rEvent)953 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
954     throw (RuntimeException)
955 {
956     if (rEvent.Source != mxMainWindow)
957         return;
958 
959     switch (rEvent.KeyCode)
960     {
961         case awt::Key::ESCAPE:
962         case awt::Key::SUBTRACT:
963         {
964 			if( mxController.is() )
965 			{
966 				Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
967 				if( xPS.is() )
968 				{
969 					Reference< XPresentation > xP( xPS->getPresentation() );
970 					if( xP.is() )
971 						xP->end();
972 				}
973 			}
974         }
975         break;
976 
977         case awt::Key::PAGEDOWN:
978             if (mxSlideShowController.is())
979             {
980                 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
981                     mxSlideShowController->gotoNextSlide();
982                 else
983                     mxSlideShowController->gotoNextEffect();
984             }
985             break;
986 
987         case awt::Key::RIGHT:
988         case awt::Key::SPACE:
989         case awt::Key::DOWN:
990         case awt::Key::N:
991             if (mxSlideShowController.is())
992             {
993                 mxSlideShowController->gotoNextEffect();
994             }
995             break;
996 
997         case awt::Key::LEFT:
998         case awt::Key::PAGEUP:
999             if (mxSlideShowController.is())
1000             {
1001                 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
1002                     mxSlideShowController->gotoPreviousSlide();
1003                 else
1004                     mxSlideShowController->gotoPreviousEffect();
1005             }
1006             break;
1007 
1008         case awt::Key::UP:
1009         case awt::Key::P:
1010         case awt::Key::BACKSPACE:
1011             if (mxSlideShowController.is())
1012             {
1013                 mxSlideShowController->gotoPreviousEffect();
1014             }
1015             break;
1016 
1017         case awt::Key::HOME:
1018             if (mxSlideShowController.is())
1019             {
1020                 mxSlideShowController->gotoFirstSlide();
1021             }
1022             break;
1023 
1024         case awt::Key::END:
1025             if (mxSlideShowController.is())
1026             {
1027                 mxSlideShowController->gotoLastSlide();
1028             }
1029             break;
1030 
1031         case awt::Key::W:
1032         case awt::Key::COMMA:
1033             if (mxSlideShowController.is())
1034             {
1035                 if (mxSlideShowController->isPaused())
1036                     mxSlideShowController->resume();
1037                 else
1038                     mxSlideShowController->blankScreen(0x00ffffff);
1039             }
1040             break;
1041 
1042         case awt::Key::B:
1043         case awt::Key::POINT:
1044             if (mxSlideShowController.is())
1045             {
1046                 if (mxSlideShowController->isPaused())
1047                     mxSlideShowController->resume();
1048                 else
1049                     mxSlideShowController->blankScreen(0x00000000);
1050             }
1051             break;
1052 
1053         case awt::Key::NUM0:
1054         case awt::Key::NUM1:
1055         case awt::Key::NUM2:
1056         case awt::Key::NUM3:
1057         case awt::Key::NUM4:
1058         case awt::Key::NUM5:
1059         case awt::Key::NUM6:
1060         case awt::Key::NUM7:
1061         case awt::Key::NUM8:
1062         case awt::Key::NUM9:
1063             HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
1064             break;
1065 
1066         case awt::Key::RETURN:
1067             if (mnPendingSlideNumber > 0)
1068             {
1069                 if (mxSlideShowController.is())
1070                     mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
1071                 mnPendingSlideNumber = -1;
1072             }
1073             else
1074             {
1075                 if (mxSlideShowController.is())
1076                     mxSlideShowController->gotoNextEffect();
1077             }
1078 
1079             break;
1080 
1081         case awt::Key::F1:
1082             // Toggle the help view.
1083             if (mpWindowManager.get() != NULL)
1084             {
1085                 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
1086                     mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
1087                 else
1088                     mpWindowManager->SetHelpViewState(false);
1089             }
1090 
1091             break;
1092 
1093         default:
1094             // Tell all views about the unhandled key event.
1095             PresenterPaneContainer::PaneList::const_iterator iPane;
1096             for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
1097             {
1098                 if ( ! (*iPane)->mbIsActive)
1099                     continue;
1100 
1101                 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
1102                 if (xKeyListener.is())
1103                     xKeyListener->keyReleased(rEvent);
1104             }
1105             break;
1106     }
1107 }
1108 
1109 
1110 
1111 
HandleNumericKeyPress(const sal_Int32 nKey,const sal_Int32 nModifiers)1112 void PresenterController::HandleNumericKeyPress (
1113     const sal_Int32 nKey,
1114     const sal_Int32 nModifiers)
1115 {
1116     switch (nModifiers)
1117     {
1118         case 0:
1119             if (mnPendingSlideNumber == -1)
1120                 mnPendingSlideNumber = 0;
1121             UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
1122             break;
1123 
1124         case awt::KeyModifier::MOD1:
1125             // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
1126             // (slide view, notes view, normal)
1127             mnPendingSlideNumber = -1;
1128             if (mpWindowManager.get() == NULL)
1129                 return;
1130             switch(nKey)
1131             {
1132                 case 1:
1133                     mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
1134                     break;
1135                 case 2:
1136                     mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
1137                     break;
1138                 case 3:
1139                     mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
1140                     break;
1141                 default:
1142                     // Ignore unsupported key.
1143                     break;
1144             }
1145 
1146         default:
1147             // Ignore unsupported modifiers.
1148             break;
1149     }
1150 }
1151 
1152 
1153 
1154 
1155 //----- XFocusListener --------------------------------------------------------
1156 
focusGained(const css::awt::FocusEvent & rEvent)1157 void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent)
1158     throw (css::uno::RuntimeException)
1159 {
1160     (void)rEvent;
1161 }
1162 
1163 
1164 
1165 
focusLost(const css::awt::FocusEvent & rEvent)1166 void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent)
1167     throw (css::uno::RuntimeException)
1168 {
1169     (void)rEvent;
1170 }
1171 
1172 
1173 
1174 
1175 //----- XMouseListener --------------------------------------------------------
1176 
mousePressed(const css::awt::MouseEvent & rEvent)1177 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent)
1178     throw (css::uno::RuntimeException)
1179 {
1180     (void)rEvent;
1181     if (mxMainWindow.is())
1182         mxMainWindow->setFocus();
1183 }
1184 
1185 
1186 
1187 
mouseReleased(const css::awt::MouseEvent & rEvent)1188 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent)
1189     throw (css::uno::RuntimeException)
1190 {
1191     (void)rEvent;
1192 }
1193 
1194 
1195 
1196 
mouseEntered(const css::awt::MouseEvent & rEvent)1197 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent)
1198     throw (css::uno::RuntimeException)
1199 {
1200     (void)rEvent;
1201 }
1202 
1203 
1204 
1205 
mouseExited(const css::awt::MouseEvent & rEvent)1206 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent)
1207     throw (css::uno::RuntimeException)
1208 {
1209     (void)rEvent;
1210 }
1211 
1212 
1213 
1214 
1215 //----- XMouseMotionListener --------------------------------------------------
1216 
mouseMoved(const css::awt::MouseEvent & rEvent)1217 void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent)
1218     throw (css::uno::RuntimeException)
1219 {
1220     (void)rEvent;
1221 }
1222 
1223 
1224 
1225 
mouseDragged(const css::awt::MouseEvent & rEvent)1226 void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent)
1227     throw (css::uno::RuntimeException)
1228 {
1229     (void)rEvent;
1230 }
1231 
1232 
1233 
1234 
1235 //-----------------------------------------------------------------------------
1236 
InitializeMainPane(const Reference<XPane> & rxPane)1237 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
1238 {
1239     if ( ! rxPane.is())
1240         return;
1241 
1242     mpAccessibleObject = new PresenterAccessible(
1243         mxComponentContext,
1244         this,
1245         rxPane);
1246 
1247     LoadTheme(rxPane);
1248 
1249     // Main pane has been created and is now observed by the window
1250     // manager.
1251     mpWindowManager->SetParentPane(rxPane);
1252     mpWindowManager->SetTheme(mpTheme);
1253 
1254     if (mpPaneBorderPainter.get() != NULL)
1255         mpPaneBorderPainter->SetTheme(mpTheme);
1256 
1257     // Add key listener
1258     mxMainWindow = rxPane->getWindow();
1259     if (mxMainWindow.is())
1260     {
1261         mxMainWindow->addKeyListener(this);
1262         mxMainWindow->addFocusListener(this);
1263         mxMainWindow->addMouseListener(this);
1264         mxMainWindow->addMouseMotionListener(this);
1265     }
1266     Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
1267     if (xPane2.is())
1268         xPane2->setVisible(sal_True);
1269 
1270     mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer));
1271 
1272     mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY);
1273 
1274     if (mxSlideShowController.is())
1275         mxSlideShowController->activate();
1276 
1277     UpdateCurrentSlide(0);
1278 }
1279 
1280 
1281 
1282 
LoadTheme(const Reference<XPane> & rxPane)1283 void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
1284 {
1285     // Create (load) the current theme.
1286     if (rxPane.is())
1287         mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas()));
1288 }
1289 
1290 
1291 
1292 
GetSlideAspectRatio(void) const1293 double PresenterController::GetSlideAspectRatio (void) const
1294 {
1295     double nSlideAspectRatio (28.0/21.0);
1296 
1297     try
1298     {
1299         if (mxController.is())
1300         {
1301             Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
1302                 mxController->getModel(), UNO_QUERY_THROW);
1303             Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
1304             if (xSlides.is() && xSlides->getCount()>0)
1305             {
1306                 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
1307                 sal_Int32 nWidth (28000);
1308                 sal_Int32 nHeight (21000);
1309                 if ((xProperties->getPropertyValue(OUString::createFromAscii("Width")) >>= nWidth)
1310                     && (xProperties->getPropertyValue(OUString::createFromAscii("Height")) >>= nHeight)
1311                     && nHeight > 0)
1312                 {
1313                     nSlideAspectRatio = double(nWidth) / double(nHeight);
1314                 }
1315             }
1316         }
1317     }
1318     catch (RuntimeException&)
1319     {
1320         OSL_ASSERT(false);
1321     }
1322 
1323     return nSlideAspectRatio;
1324 }
1325 
1326 
1327 
1328 
UpdatePendingSlideNumber(const sal_Int32 nPendingSlideNumber)1329 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
1330 {
1331     mnPendingSlideNumber = nPendingSlideNumber;
1332 
1333     if (mpTheme.get() == NULL)
1334         return;
1335 
1336     if ( ! mxMainWindow.is())
1337         return;
1338 
1339     PresenterTheme::SharedFontDescriptor pFont (
1340         mpTheme->GetFont(A2S("PendingSlideNumberFont")));
1341     if (pFont.get() == NULL)
1342         return;
1343 
1344     pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1345     if ( ! pFont->mxFont.is())
1346         return;
1347 
1348     const OUString sText (OUString::valueOf(mnPendingSlideNumber));
1349     rendering::StringContext aContext (sText, 0, sText.getLength());
1350     Reference<rendering::XTextLayout> xLayout (
1351         pFont->mxFont->createTextLayout(
1352             aContext,
1353             rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1354             0));
1355 }
1356 
1357 
1358 
1359 
ThrowIfDisposed(void) const1360 void PresenterController::ThrowIfDisposed (void) const
1361     throw (::com::sun::star::lang::DisposedException)
1362 {
1363 	if (rBHelper.bDisposed || rBHelper.bInDispose)
1364 	{
1365         throw lang::DisposedException (
1366             OUString(RTL_CONSTASCII_USTRINGPARAM(
1367                 "PresenterController object has already been disposed")),
1368             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1369     }
1370 }
1371 
1372 
1373 } } // end of namespace ::sdext::presenter
1374 
1375