nss: upgrade to release 3.73
[LibreOffice.git] / sdext / source / presenter / PresenterController.cxx
blob6d414d5f66ca2d47b20fd39a57ceabf49d942bce
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include "PresenterController.hxx"
26 #include "PresenterAccessibility.hxx"
27 #include "PresenterCanvasHelper.hxx"
28 #include "PresenterCurrentSlideObserver.hxx"
29 #include "PresenterScreen.hxx"
30 #include "PresenterPaintManager.hxx"
31 #include "PresenterPaneBase.hxx"
32 #include "PresenterPaneContainer.hxx"
33 #include "PresenterPaneBorderPainter.hxx"
34 #include "PresenterTheme.hxx"
35 #include "PresenterViewFactory.hxx"
36 #include "PresenterWindowManager.hxx"
38 #include <com/sun/star/awt/Key.hpp>
39 #include <com/sun/star/awt/KeyModifier.hpp>
40 #include <com/sun/star/awt/MouseButton.hpp>
41 #include <com/sun/star/container/XNamed.hpp>
42 #include <com/sun/star/drawing/XDrawView.hpp>
43 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
44 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
45 #include <com/sun/star/drawing/framework/ResourceId.hpp>
46 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
47 #include <com/sun/star/frame/FrameSearchFlag.hpp>
48 #include <com/sun/star/frame/XDispatchProvider.hpp>
49 #include <com/sun/star/presentation/AnimationEffect.hpp>
50 #include <com/sun/star/presentation/XPresentation.hpp>
51 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
52 #include <com/sun/star/rendering/TextDirection.hpp>
53 #include <com/sun/star/util/URLTransformer.hpp>
55 #include <rtl/ustrbuf.hxx>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::presentation;
60 using namespace ::com::sun::star::drawing::framework;
62 namespace {
63 const sal_Int32 ResourceActivationEventType = 0;
64 const sal_Int32 ResourceDeactivationEventType = 1;
65 const sal_Int32 ConfigurationUpdateEndEventType = 2;
68 namespace sdext::presenter {
70 IPresentationTime::~IPresentationTime()
74 PresenterController::InstanceContainer PresenterController::maInstances;
76 ::rtl::Reference<PresenterController> PresenterController::Instance (
77 const css::uno::Reference<css::frame::XFrame>& rxFrame)
79 InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame));
80 if (iInstance != maInstances.end())
81 return iInstance->second;
82 else
83 return ::rtl::Reference<PresenterController>();
86 PresenterController::PresenterController (
87 const css::uno::WeakReference<css::lang::XEventListener> &rxScreen,
88 const Reference<XComponentContext>& rxContext,
89 const Reference<frame::XController>& rxController,
90 const Reference<presentation::XSlideShowController>& rxSlideShowController,
91 const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
92 const Reference<XResourceId>& rxMainPaneId)
93 : PresenterControllerInterfaceBase(m_aMutex),
94 mxScreen(rxScreen),
95 mxComponentContext(rxContext),
96 mxController(rxController),
97 mxConfigurationController(),
98 mxSlideShowController(rxSlideShowController),
99 mxMainPaneId(rxMainPaneId),
100 mpPaneContainer(rpPaneContainer),
101 mnCurrentSlideIndex(-1),
102 mxCurrentSlide(),
103 mxNextSlide(),
104 mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)),
105 mpTheme(),
106 mxMainWindow(),
107 mpPaneBorderPainter(),
108 mpCanvasHelper(std::make_shared<PresenterCanvasHelper>()),
109 mxPresenterHelper(),
110 mpPaintManager(),
111 mnPendingSlideNumber(-1),
112 mxUrlTransformer(),
113 mpAccessibleObject(),
114 mbIsAccessibilityActive(false)
116 OSL_ASSERT(mxController.is());
118 if ( ! mxSlideShowController.is())
119 throw lang::IllegalArgumentException(
120 "missing slide show controller",
121 static_cast<XWeak*>(this),
124 new PresenterCurrentSlideObserver(this,rxSlideShowController);
126 // Listen for configuration changes.
127 Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW);
128 mxConfigurationController = xCM->getConfigurationController();
129 if (mxConfigurationController.is())
131 mxConfigurationController->addConfigurationChangeListener(
132 this,
133 "ResourceActivation",
134 Any(ResourceActivationEventType));
135 mxConfigurationController->addConfigurationChangeListener(
136 this,
137 "ResourceDeactivation",
138 Any(ResourceDeactivationEventType));
139 mxConfigurationController->addConfigurationChangeListener(
140 this,
141 "ConfigurationUpdateEnd",
142 Any(ConfigurationUpdateEndEventType));
145 // Listen for the frame being activated.
146 Reference<frame::XFrame> xFrame (mxController->getFrame());
147 if (xFrame.is())
148 xFrame->addFrameActionListener(this);
150 // Create the border painter.
151 mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext);
152 mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter);
154 // Create an object that is able to load the bitmaps in a format that is
155 // supported by the canvas.
156 Reference<lang::XMultiComponentFactory> xFactory =
157 rxContext->getServiceManager();
158 if ( ! xFactory.is())
159 return;
160 mxPresenterHelper.set(
161 xFactory->createInstanceWithContext(
162 "com.sun.star.drawing.PresenterHelper",
163 rxContext),
164 UNO_QUERY_THROW);
166 if (mxSlideShowController.is())
168 mxSlideShowController->activate();
169 Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY);
170 if (xProperties.is())
172 Reference<awt::XWindow> xWindow (
173 xProperties->getPropertyValue("ParentWindow"), UNO_QUERY);
174 if (xWindow.is())
175 xWindow->addKeyListener(this);
179 UpdateCurrentSlide(0);
181 maInstances[mxController->getFrame()] = this;
183 // Create a URLTransformer.
184 if (xFactory.is())
186 mxUrlTransformer.set(util::URLTransformer::create(mxComponentContext));
190 PresenterController::~PresenterController()
194 void PresenterController::disposing()
196 maInstances.erase(mxController->getFrame());
198 if (mxMainWindow.is())
200 mxMainWindow->removeKeyListener(this);
201 mxMainWindow->removeMouseListener(this);
202 mxMainWindow = nullptr;
204 if (mxConfigurationController.is())
205 mxConfigurationController->removeConfigurationChangeListener(this);
207 Reference<XComponent> xWindowManagerComponent (
208 static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY);
209 mpWindowManager = nullptr;
210 if (xWindowManagerComponent.is())
211 xWindowManagerComponent->dispose();
213 if (mxController.is())
215 Reference<frame::XFrame> xFrame (mxController->getFrame());
216 if (xFrame.is())
217 xFrame->removeFrameActionListener(this);
218 mxController = nullptr;
221 mxComponentContext = nullptr;
222 mxConfigurationController = nullptr;
223 mxSlideShowController = nullptr;
224 mxMainPaneId = nullptr;
225 mpPaneContainer = nullptr;
226 mnCurrentSlideIndex = -1;
227 mxCurrentSlide = nullptr;
228 mxNextSlide = nullptr;
229 mpTheme.reset();
231 Reference<lang::XComponent> xComponent (
232 static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY);
233 mpPaneBorderPainter = nullptr;
234 if (xComponent.is())
235 xComponent->dispose();
237 mpCanvasHelper.reset();
239 Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY);
240 mxPresenterHelper = nullptr;
241 if (xComponent.is())
242 xComponent->dispose();
244 mpPaintManager.reset();
245 mnPendingSlideNumber = -1;
247 Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY);
248 mxUrlTransformer = nullptr;
249 if (xComponent.is())
250 xComponent->dispose();
254 void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset)
256 // std::cerr << "Updating current Slide to " << nOffset << std::endl;
257 GetSlides(nOffset);
258 UpdatePaneTitles();
259 UpdateViews();
261 // Update the accessibility object.
262 if (IsAccessibilityActive())
264 mpAccessibleObject->NotifyCurrentSlideChange();
268 void PresenterController::GetSlides (const sal_Int32 nOffset)
270 if ( ! mxSlideShowController.is())
271 return;
273 // Get the current slide from the slide show controller.
274 mxCurrentSlide = nullptr;
275 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
278 sal_Int32 nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset;
279 if (mxSlideShowController->isPaused())
280 nSlideIndex = -1;
282 if (xIndexAccess.is() && nSlideIndex>=0)
284 if (nSlideIndex < xIndexAccess->getCount())
286 mnCurrentSlideIndex = nSlideIndex;
287 mxCurrentSlide.set( xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
291 catch (RuntimeException&)
295 // Get the next slide.
296 mxNextSlide = nullptr;
299 const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset);
300 if (nNextSlideIndex >= 0)
302 if (xIndexAccess.is())
304 if (nNextSlideIndex < xIndexAccess->getCount())
305 mxNextSlide.set( xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY);
309 catch (RuntimeException&)
314 void PresenterController::UpdatePaneTitles()
316 if ( ! mxSlideShowController.is())
317 return;
319 // Get placeholders and their values.
320 const OUString sCurrentSlideNumberPlaceholder ("CURRENT_SLIDE_NUMBER");
321 const OUString sCurrentSlideNamePlaceholder ("CURRENT_SLIDE_NAME");
322 const OUString sSlideCountPlaceholder ("SLIDE_COUNT");
324 // Get string for slide count.
325 OUString sSlideCount ("---");
326 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
327 if (xIndexAccess.is())
328 sSlideCount = OUString::number(xIndexAccess->getCount());
330 // Get string for current slide index.
331 OUString sCurrentSlideNumber (OUString::number(mnCurrentSlideIndex + 1));
333 // Get name of the current slide.
334 OUString sCurrentSlideName;
335 Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY);
336 if (xNamedSlide.is())
337 sCurrentSlideName = xNamedSlide->getName();
338 Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY);
339 if (xSlideProperties.is())
343 OUString sName;
344 if (xSlideProperties->getPropertyValue("LinkDisplayName") >>= sName)
346 // Find out whether the name of the current slide has been
347 // automatically created or has been set by the user.
348 if (sName != sCurrentSlideName)
349 sCurrentSlideName = sName;
352 catch (const beans::UnknownPropertyException&)
357 // Replace the placeholders with their current values.
358 for (auto& rxPane : mpPaneContainer->maPanes)
360 OSL_ASSERT(rxPane != nullptr);
362 OUString sTemplate (IsAccessibilityActive()
363 ? rxPane->msAccessibleTitleTemplate
364 : rxPane->msTitleTemplate);
365 if (sTemplate.isEmpty())
366 continue;
368 OUStringBuffer sResult;
369 sResult.ensureCapacity(sTemplate.getLength());
371 sal_Int32 nIndex (0);
372 while (true)
374 sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex);
375 if (nStartIndex < 0)
377 // Add the remaining part of the string.
378 sResult.append(std::u16string_view(sTemplate).substr(nIndex));
379 break;
381 else
383 // Add the part preceding the next %.
384 sResult.append(std::u16string_view(sTemplate).substr(nIndex, nStartIndex-nIndex));
386 // Get the placeholder
387 ++nStartIndex;
388 const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1));
389 const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex));
390 nIndex = nEndIndex+1;
392 // Replace the placeholder with its current value.
393 if (sPlaceholder == sCurrentSlideNumberPlaceholder)
394 sResult.append(sCurrentSlideNumber);
395 else if (sPlaceholder == sCurrentSlideNamePlaceholder)
396 sResult.append(sCurrentSlideName);
397 else if (sPlaceholder == sSlideCountPlaceholder)
398 sResult.append(sSlideCount);
402 rxPane->msTitle = sResult.makeStringAndClear();
403 if (rxPane->mxPane.is())
404 rxPane->mxPane->SetTitle(rxPane->msTitle);
408 void PresenterController::UpdateViews()
410 // Tell all views about the slides they should display.
411 for (const auto& rxPane : mpPaneContainer->maPanes)
413 Reference<drawing::XDrawView> xDrawView (rxPane->mxView, UNO_QUERY);
414 if (xDrawView.is())
415 xDrawView->setCurrentPage(mxCurrentSlide);
419 SharedBitmapDescriptor
420 PresenterController::GetViewBackground (const OUString& rsViewURL) const
422 if (mpTheme != nullptr)
424 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
425 return mpTheme->GetBitmap(sStyleName, "Background");
427 return SharedBitmapDescriptor();
430 PresenterTheme::SharedFontDescriptor
431 PresenterController::GetViewFont (const OUString& rsViewURL) const
433 if (mpTheme != nullptr)
435 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
436 return mpTheme->GetFont(sStyleName);
438 return PresenterTheme::SharedFontDescriptor();
441 const std::shared_ptr<PresenterTheme>& PresenterController::GetTheme() const
443 return mpTheme;
446 const ::rtl::Reference<PresenterWindowManager>& PresenterController::GetWindowManager() const
448 return mpWindowManager;
451 const Reference<presentation::XSlideShowController>&
452 PresenterController::GetSlideShowController() const
454 return mxSlideShowController;
457 const rtl::Reference<PresenterPaneContainer>& PresenterController::GetPaneContainer() const
459 return mpPaneContainer;
462 const ::rtl::Reference<PresenterPaneBorderPainter>& PresenterController::GetPaneBorderPainter() const
464 return mpPaneBorderPainter;
467 const std::shared_ptr<PresenterCanvasHelper>& PresenterController::GetCanvasHelper() const
469 return mpCanvasHelper;
472 const Reference<drawing::XPresenterHelper>& PresenterController::GetPresenterHelper() const
474 return mxPresenterHelper;
477 const std::shared_ptr<PresenterPaintManager>& PresenterController::GetPaintManager() const
479 return mpPaintManager;
482 void PresenterController::ShowView (const OUString& rsViewURL)
484 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
485 mpPaneContainer->FindViewURL(rsViewURL));
486 if (!pDescriptor)
487 return;
489 pDescriptor->mbIsActive = true;
490 mxConfigurationController->requestResourceActivation(
491 pDescriptor->mxPaneId,
492 ResourceActivationMode_ADD);
493 mxConfigurationController->requestResourceActivation(
494 ResourceId::createWithAnchor(
495 mxComponentContext,
496 rsViewURL,
497 pDescriptor->mxPaneId),
498 ResourceActivationMode_REPLACE);
501 void PresenterController::HideView (const OUString& rsViewURL)
503 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
504 mpPaneContainer->FindViewURL(rsViewURL));
505 if (pDescriptor)
507 mxConfigurationController->requestResourceDeactivation(
508 ResourceId::createWithAnchor(
509 mxComponentContext,
510 rsViewURL,
511 pDescriptor->mxPaneId));
515 void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const
517 if ( ! mxUrlTransformer.is())
518 return;
520 util::URL aURL;
521 aURL.Complete = rsCommand;
522 mxUrlTransformer->parseStrict(aURL);
524 Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
525 if ( ! xDispatch.is())
526 return;
528 xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
531 Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const
533 if ( ! mxController.is())
534 return nullptr;
536 Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY);
537 if ( ! xDispatchProvider.is())
538 return nullptr;
540 return xDispatchProvider->queryDispatch(
541 rURL,
542 OUString(),
543 frame::FrameSearchFlag::SELF);
546 util::URL PresenterController::CreateURLFromString (const OUString& rsURL) const
548 util::URL aURL;
550 if (mxUrlTransformer.is())
552 aURL.Complete = rsURL;
553 mxUrlTransformer->parseStrict(aURL);
556 return aURL;
559 const Reference<drawing::framework::XConfigurationController>&
560 PresenterController::GetConfigurationController() const
562 return mxConfigurationController;
565 const Reference<drawing::XDrawPage>& PresenterController::GetCurrentSlide() const
567 return mxCurrentSlide;
570 bool PresenterController::HasTransition (Reference<drawing::XDrawPage> const & rxPage)
572 bool bTransition = false;
573 if( rxPage.is() )
575 Reference<beans::XPropertySet> xSlidePropertySet (rxPage, UNO_QUERY);
578 sal_uInt16 aTransitionType = 0;
579 xSlidePropertySet->getPropertyValue("TransitionType") >>= aTransitionType;
580 if (aTransitionType > 0)
582 bTransition = true;
585 catch (const beans::UnknownPropertyException&)
589 return bTransition;
592 bool PresenterController::HasCustomAnimation (Reference<drawing::XDrawPage> const & rxPage)
594 bool bCustomAnimation = false;
595 if( rxPage.is() )
597 sal_uInt32 i, nCount = rxPage->getCount();
598 for ( i = 0; i < nCount; i++ )
600 Reference<drawing::XShape> xShape(rxPage->getByIndex(i), UNO_QUERY);
601 Reference<beans::XPropertySet> xShapePropertySet(xShape, UNO_QUERY);
602 presentation::AnimationEffect aEffect = presentation::AnimationEffect_NONE;
603 presentation::AnimationEffect aTextEffect = presentation::AnimationEffect_NONE;
606 xShapePropertySet->getPropertyValue("Effect") >>= aEffect;
607 xShapePropertySet->getPropertyValue("TextEffect") >>= aTextEffect;
609 catch (const beans::UnknownPropertyException&)
612 if( aEffect != presentation::AnimationEffect_NONE ||
613 aTextEffect != presentation::AnimationEffect_NONE )
615 bCustomAnimation = true;
616 break;
620 return bCustomAnimation;
623 void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
625 if ( mbIsAccessibilityActive != bIsActive)
627 mbIsAccessibilityActive = bIsActive;
628 UpdatePaneTitles();
633 void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
635 if (!mxSlideShowController.is())
636 return;
638 switch (rEvent.Buttons)
640 case awt::MouseButton::LEFT:
641 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
642 mxSlideShowController->gotoNextSlide();
643 else
644 mxSlideShowController->gotoNextEffect();
645 break;
647 case awt::MouseButton::RIGHT:
648 mxSlideShowController->gotoPreviousSlide();
649 break;
651 default:
652 // Other or multiple buttons.
653 break;
657 void PresenterController::RequestViews (
658 const bool bIsSlideSorterActive,
659 const bool bIsNotesViewActive,
660 const bool bIsHelpViewActive)
662 for (const auto& rxPane : mpPaneContainer->maPanes)
664 bool bActivate (true);
665 const OUString sViewURL (rxPane->msViewURL);
666 if (sViewURL == PresenterViewFactory::msNotesViewURL)
668 bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
670 else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
672 bActivate = bIsSlideSorterActive;
674 else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
675 || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
677 bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
679 else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
681 bActivate = true;
683 else if (sViewURL == PresenterViewFactory::msHelpViewURL)
685 bActivate = bIsHelpViewActive;
688 if (bActivate)
689 ShowView(sViewURL);
690 else
691 HideView(sViewURL);
695 void PresenterController::SetPresentationTime(IPresentationTime* pPresentationTime)
697 mpPresentationTime = pPresentationTime;
700 IPresentationTime* PresenterController::GetPresentationTime()
702 return mpPresentationTime;
705 //----- XConfigurationChangeListener ------------------------------------------
707 void SAL_CALL PresenterController::notifyConfigurationChange (
708 const ConfigurationChangeEvent& rEvent)
710 if (rBHelper.bDisposed || rBHelper.bInDispose)
712 throw lang::DisposedException (
713 "PresenterController object has already been disposed",
714 static_cast<uno::XWeak*>(this));
717 sal_Int32 nType (0);
718 if ( ! (rEvent.UserData >>= nType))
719 return;
721 switch (nType)
723 case ResourceActivationEventType:
724 if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
726 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
728 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
730 // A pane bound to the main pane has been created and is
731 // stored in the pane container.
732 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
733 if (xPane.is())
735 mpPaneContainer->FindPaneId(xPane->getResourceId());
738 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
740 // A view bound to one of the panes has been created and is
741 // stored in the pane container along with its pane.
742 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
743 if (xView.is())
745 mpPaneContainer->StoreView(xView);
746 UpdateViews();
747 mpWindowManager->NotifyViewCreation(xView);
750 break;
752 case ResourceDeactivationEventType:
753 if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
755 // If this is a view then remove it from the pane container.
756 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
757 if (xView.is())
759 PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
760 mpPaneContainer->RemoveView(xView));
762 // A possibly opaque view has been removed. Update()
763 // updates the clip polygon.
764 mpWindowManager->Update();
765 // Request the repainting of the area previously
766 // occupied by the view.
767 if (pDescriptor)
768 GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
771 break;
773 case ConfigurationUpdateEndEventType:
774 if (IsAccessibilityActive())
776 mpAccessibleObject->UpdateAccessibilityHierarchy();
777 UpdateCurrentSlide(0);
779 break;
783 //----- XEventListener --------------------------------------------------------
785 void SAL_CALL PresenterController::disposing (
786 const lang::EventObject& rEvent)
788 if (rEvent.Source == mxController)
789 mxController = nullptr;
790 else if (rEvent.Source == mxConfigurationController)
791 mxConfigurationController = nullptr;
792 else if (rEvent.Source == mxSlideShowController)
793 mxSlideShowController = nullptr;
794 else if (rEvent.Source == mxMainWindow)
795 mxMainWindow = nullptr;
798 //----- XFrameActionListener --------------------------------------------------
800 void SAL_CALL PresenterController::frameAction (
801 const frame::FrameActionEvent& rEvent)
803 if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
805 if (mxSlideShowController.is())
806 mxSlideShowController->activate();
810 //----- XKeyListener ----------------------------------------------------------
812 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
814 // Tell all views about the unhandled key event.
815 for (const auto& rxPane : mpPaneContainer->maPanes)
817 if ( ! rxPane->mbIsActive)
818 continue;
820 Reference<awt::XKeyListener> xKeyListener (rxPane->mxView, UNO_QUERY);
821 if (xKeyListener.is())
822 xKeyListener->keyPressed(rEvent);
826 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
828 if (rEvent.Source != mxMainWindow)
829 return;
831 switch (rEvent.KeyCode)
833 case awt::Key::ESCAPE:
834 case awt::Key::SUBTRACT:
836 if( mxController.is() )
838 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
839 if( xPS.is() )
841 Reference< XPresentation > xP( xPS->getPresentation() );
842 if( xP.is() )
843 xP->end();
847 break;
849 case awt::Key::PAGEDOWN:
850 if (mxSlideShowController.is())
852 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
853 mxSlideShowController->gotoNextSlide();
854 else
855 mxSlideShowController->gotoNextEffect();
857 break;
859 case awt::Key::RIGHT:
860 case awt::Key::SPACE:
861 case awt::Key::DOWN:
862 case awt::Key::N:
863 if (mxSlideShowController.is())
865 mxSlideShowController->gotoNextEffect();
867 break;
869 case awt::Key::PAGEUP:
870 if (mxSlideShowController.is())
872 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
873 mxSlideShowController->gotoPreviousSlide();
874 else
875 mxSlideShowController->gotoPreviousEffect();
877 break;
879 case awt::Key::LEFT:
880 case awt::Key::UP:
881 case awt::Key::P:
882 case awt::Key::BACKSPACE:
883 if (mxSlideShowController.is())
885 mxSlideShowController->gotoPreviousEffect();
887 break;
889 case awt::Key::HOME:
890 if (mxSlideShowController.is())
892 mxSlideShowController->gotoFirstSlide();
894 break;
896 case awt::Key::END:
897 if (mxSlideShowController.is())
899 mxSlideShowController->gotoLastSlide();
901 break;
903 case awt::Key::W:
904 case awt::Key::COMMA:
905 if (mxSlideShowController.is())
907 if (mxSlideShowController->isPaused())
908 mxSlideShowController->resume();
909 else
910 mxSlideShowController->blankScreen(0x00ffffff);
912 break;
914 case awt::Key::B:
915 case awt::Key::POINT:
916 if (mxSlideShowController.is())
918 if (mxSlideShowController->isPaused())
919 mxSlideShowController->resume();
920 else
921 mxSlideShowController->blankScreen(0x00000000);
923 break;
925 case awt::Key::NUM0:
926 case awt::Key::NUM1:
927 case awt::Key::NUM2:
928 case awt::Key::NUM3:
929 case awt::Key::NUM4:
930 case awt::Key::NUM5:
931 case awt::Key::NUM6:
932 case awt::Key::NUM7:
933 case awt::Key::NUM8:
934 case awt::Key::NUM9:
935 HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
936 break;
938 case awt::Key::RETURN:
939 if (mnPendingSlideNumber > 0)
941 if (mxSlideShowController.is())
942 mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
943 mnPendingSlideNumber = -1;
945 else
947 if (mxSlideShowController.is())
948 mxSlideShowController->gotoNextEffect();
951 break;
953 case awt::Key::F1:
954 // Toggle the help view.
955 if (mpWindowManager)
957 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
958 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
959 else
960 mpWindowManager->SetHelpViewState(false);
963 break;
965 default:
966 // Tell all views about the unhandled key event.
967 for (const auto& rxPane : mpPaneContainer->maPanes)
969 if ( ! rxPane->mbIsActive)
970 continue;
972 Reference<awt::XKeyListener> xKeyListener (rxPane->mxView, UNO_QUERY);
973 if (xKeyListener.is())
974 xKeyListener->keyReleased(rEvent);
976 break;
980 void PresenterController::HandleNumericKeyPress (
981 const sal_Int32 nKey,
982 const sal_Int32 nModifiers)
984 switch (nModifiers)
986 case 0:
987 if (mnPendingSlideNumber == -1)
988 mnPendingSlideNumber = 0;
989 UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
990 break;
992 case awt::KeyModifier::MOD1:
993 // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
994 // (slide view, notes view, normal). Ctrl-4 switches monitors
995 mnPendingSlideNumber = -1;
996 if (!mpWindowManager)
997 return;
998 switch(nKey)
1000 case 1:
1001 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
1002 break;
1003 case 2:
1004 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
1005 break;
1006 case 3:
1007 mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
1008 break;
1009 case 4:
1010 SwitchMonitors();
1011 break;
1012 default:
1013 // Ignore unsupported key.
1014 break;
1016 break;
1018 default:
1019 // Ignore unsupported modifiers.
1020 break;
1024 //----- XMouseListener --------------------------------------------------------
1026 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent&)
1028 if (mxMainWindow.is())
1029 mxMainWindow->setFocus();
1032 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent&) {}
1034 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent&) {}
1036 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent&) {}
1038 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
1040 if ( ! rxPane.is())
1041 return;
1043 mpAccessibleObject = new PresenterAccessible(
1044 mxComponentContext,
1045 this,
1046 rxPane);
1048 LoadTheme(rxPane);
1050 // Main pane has been created and is now observed by the window
1051 // manager.
1052 mpWindowManager->SetParentPane(rxPane);
1053 mpWindowManager->SetTheme(mpTheme);
1055 if (mpPaneBorderPainter)
1056 mpPaneBorderPainter->SetTheme(mpTheme);
1058 // Add key listener
1059 mxMainWindow = rxPane->getWindow();
1060 if (mxMainWindow.is())
1062 mxMainWindow->addKeyListener(this);
1063 mxMainWindow->addMouseListener(this);
1065 Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
1066 if (xPane2.is())
1067 xPane2->setVisible(true);
1069 mpPaintManager = std::make_shared<PresenterPaintManager>(mxMainWindow, mxPresenterHelper, mpPaneContainer);
1071 mxCanvas.set(rxPane->getCanvas(), UNO_QUERY);
1073 if (mxSlideShowController.is())
1074 mxSlideShowController->activate();
1076 UpdateCurrentSlide(0);
1079 void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
1081 // Create (load) the current theme.
1082 if (rxPane.is())
1083 mpTheme = std::make_shared<PresenterTheme>(mxComponentContext, rxPane->getCanvas());
1086 double PresenterController::GetSlideAspectRatio() const
1088 double nSlideAspectRatio (28.0/21.0);
1092 if (mxController.is())
1094 Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
1095 mxController->getModel(), UNO_QUERY_THROW);
1096 Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
1097 if (xSlides.is() && xSlides->getCount()>0)
1099 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
1100 sal_Int32 nWidth (28000);
1101 sal_Int32 nHeight (21000);
1102 if ((xProperties->getPropertyValue("Width") >>= nWidth)
1103 && (xProperties->getPropertyValue("Height") >>= nHeight)
1104 && nHeight > 0)
1106 nSlideAspectRatio = double(nWidth) / double(nHeight);
1111 catch (RuntimeException&)
1113 OSL_ASSERT(false);
1116 return nSlideAspectRatio;
1119 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
1121 mnPendingSlideNumber = nPendingSlideNumber;
1123 if (mpTheme == nullptr)
1124 return;
1126 if ( ! mxMainWindow.is())
1127 return;
1129 PresenterTheme::SharedFontDescriptor pFont (
1130 mpTheme->GetFont("PendingSlideNumberFont"));
1131 if (!pFont)
1132 return;
1134 pFont->PrepareFont(mxCanvas);
1135 if ( ! pFont->mxFont.is())
1136 return;
1138 const OUString sText (OUString::number(mnPendingSlideNumber));
1139 rendering::StringContext aContext (sText, 0, sText.getLength());
1140 pFont->mxFont->createTextLayout(
1141 aContext,
1142 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1146 void PresenterController::SwitchMonitors()
1148 Reference<lang::XEventListener> xScreen( mxScreen );
1149 if (!xScreen.is())
1150 return;
1152 PresenterScreen *pScreen = dynamic_cast<PresenterScreen *>(xScreen.get());
1153 if (!pScreen)
1154 return;
1156 pScreen->SwitchMonitors();
1159 void PresenterController::ExitPresenter()
1161 if( mxController.is() )
1163 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
1164 if( xPS.is() )
1166 Reference< XPresentation > xP( xPS->getPresentation() );
1167 if( xP.is() )
1168 xP->end();
1173 } // end of namespace ::sdext::presenter
1175 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */