Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / console / PresenterController.cxx
blob39ed5506960d4080ec188704b3ad2c2c5f94270e
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 "PresenterController.hxx"
24 #include "PresenterAccessibility.hxx"
25 #include "PresenterCanvasHelper.hxx"
26 #include "PresenterCurrentSlideObserver.hxx"
27 #include "PresenterScreen.hxx"
28 #include "PresenterPaintManager.hxx"
29 #include "PresenterPaneBase.hxx"
30 #include "PresenterPaneContainer.hxx"
31 #include "PresenterPaneBorderPainter.hxx"
32 #include "PresenterTheme.hxx"
33 #include "PresenterViewFactory.hxx"
34 #include "PresenterWindowManager.hxx"
35 #include <DrawController.hxx>
37 #include <com/sun/star/awt/Key.hpp>
38 #include <com/sun/star/awt/KeyModifier.hpp>
39 #include <com/sun/star/awt/MouseButton.hpp>
40 #include <com/sun/star/container/XNamed.hpp>
41 #include <com/sun/star/drawing/XDrawView.hpp>
42 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
43 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
44 #include <com/sun/star/drawing/framework/ResourceId.hpp>
45 #include <com/sun/star/frame/FrameSearchFlag.hpp>
46 #include <com/sun/star/frame/XDispatchProvider.hpp>
47 #include <com/sun/star/presentation/AnimationEffect.hpp>
48 #include <com/sun/star/presentation/XPresentation.hpp>
49 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
50 #include <com/sun/star/rendering/TextDirection.hpp>
51 #include <com/sun/star/util/URLTransformer.hpp>
53 #include <rtl/ustrbuf.hxx>
54 #include <utility>
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::presentation;
59 using namespace ::com::sun::star::drawing::framework;
61 namespace {
62 const sal_Int32 ResourceActivationEventType = 0;
63 const sal_Int32 ResourceDeactivationEventType = 1;
64 const sal_Int32 ConfigurationUpdateEndEventType = 2;
67 namespace sdext::presenter {
69 IPresentationTime::~IPresentationTime()
73 PresenterController::InstanceContainer PresenterController::maInstances;
75 ::rtl::Reference<PresenterController> PresenterController::Instance (
76 const css::uno::Reference<css::frame::XFrame>& rxFrame)
78 InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame));
79 if (iInstance != maInstances.end())
80 return iInstance->second;
81 else
82 return ::rtl::Reference<PresenterController>();
85 PresenterController::PresenterController (
86 unotools::WeakReference<PresenterScreen> xScreen,
87 const Reference<XComponentContext>& rxContext,
88 const rtl::Reference<::sd::DrawController>& rxController,
89 const Reference<presentation::XSlideShowController>& rxSlideShowController,
90 rtl::Reference<PresenterPaneContainer> xPaneContainer,
91 const Reference<XResourceId>& rxMainPaneId)
92 : PresenterControllerInterfaceBase(m_aMutex),
93 mxScreen(std::move(xScreen)),
94 mxComponentContext(rxContext),
95 mxController(rxController),
96 mxSlideShowController(rxSlideShowController),
97 mxMainPaneId(rxMainPaneId),
98 mpPaneContainer(std::move(xPaneContainer)),
99 mnCurrentSlideIndex(-1),
100 mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)),
101 mpCanvasHelper(std::make_shared<PresenterCanvasHelper>()),
102 mnPendingSlideNumber(-1),
103 mbIsAccessibilityActive(false)
105 OSL_ASSERT(mxController.is());
107 if ( ! mxSlideShowController.is())
108 throw lang::IllegalArgumentException(
109 "missing slide show controller",
110 static_cast<XWeak*>(this),
113 new PresenterCurrentSlideObserver(this,rxSlideShowController);
115 // Listen for configuration changes.
116 mxConfigurationController = mxController->getConfigurationController();
117 if (mxConfigurationController.is())
119 mxConfigurationController->addConfigurationChangeListener(
120 this,
121 "ResourceActivation",
122 Any(ResourceActivationEventType));
123 mxConfigurationController->addConfigurationChangeListener(
124 this,
125 "ResourceDeactivation",
126 Any(ResourceDeactivationEventType));
127 mxConfigurationController->addConfigurationChangeListener(
128 this,
129 "ConfigurationUpdateEnd",
130 Any(ConfigurationUpdateEndEventType));
133 // Listen for the frame being activated.
134 Reference<frame::XFrame> xFrame (mxController->getFrame());
135 if (xFrame.is())
136 xFrame->addFrameActionListener(this);
138 // Create the border painter.
139 mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext);
140 mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter);
142 // Create an object that is able to load the bitmaps in a format that is
143 // supported by the canvas.
144 Reference<lang::XMultiComponentFactory> xFactory =
145 rxContext->getServiceManager();
146 if ( ! xFactory.is())
147 return;
148 mxPresenterHelper.set(
149 xFactory->createInstanceWithContext(
150 "com.sun.star.drawing.PresenterHelper",
151 rxContext),
152 UNO_QUERY_THROW);
154 if (mxSlideShowController.is())
156 mxSlideShowController->activate();
157 Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY);
158 if (xProperties.is())
160 Reference<awt::XWindow> xWindow (
161 xProperties->getPropertyValue("ParentWindow"), UNO_QUERY);
162 if (xWindow.is())
163 xWindow->addKeyListener(this);
167 UpdateCurrentSlide(0);
169 maInstances[mxController->getFrame()] = this;
171 // Create a URLTransformer.
172 if (xFactory.is())
174 mxUrlTransformer.set(util::URLTransformer::create(mxComponentContext));
178 PresenterController::~PresenterController()
182 void PresenterController::disposing()
184 maInstances.erase(mxController->getFrame());
186 if (mxMainWindow.is())
188 mxMainWindow->removeKeyListener(this);
189 mxMainWindow->removeMouseListener(this);
190 mxMainWindow = nullptr;
192 if (mxConfigurationController.is())
193 mxConfigurationController->removeConfigurationChangeListener(this);
195 if (mxController.is())
197 Reference<frame::XFrame> xFrame (mxController->getFrame());
198 if (xFrame.is())
199 xFrame->removeFrameActionListener(this);
200 mxController = nullptr;
203 Reference<XComponent> xWindowManagerComponent = mpWindowManager;
204 mpWindowManager = nullptr;
205 if (xWindowManagerComponent.is())
206 xWindowManagerComponent->dispose();
208 mxComponentContext = nullptr;
209 mxConfigurationController = nullptr;
210 mxSlideShowController = nullptr;
211 mxMainPaneId = nullptr;
212 mpPaneContainer = nullptr;
213 mnCurrentSlideIndex = -1;
214 mxCurrentSlide = nullptr;
215 mxNextSlide = nullptr;
216 mpTheme.reset();
218 Reference<lang::XComponent> xComponent = mpPaneBorderPainter;
219 mpPaneBorderPainter = nullptr;
220 if (xComponent.is())
221 xComponent->dispose();
223 mpCanvasHelper.reset();
225 Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY);
226 mxPresenterHelper = nullptr;
227 if (xComponent.is())
228 xComponent->dispose();
230 mpPaintManager.reset();
231 mnPendingSlideNumber = -1;
233 Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY);
234 mxUrlTransformer = nullptr;
235 if (xComponent.is())
236 xComponent->dispose();
240 void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset)
242 // std::cerr << "Updating current Slide to " << nOffset << std::endl;
243 GetSlides(nOffset);
244 UpdatePaneTitles();
245 UpdateViews();
247 // Update the accessibility object.
248 if (IsAccessibilityActive())
250 mpAccessibleObject->NotifyCurrentSlideChange();
254 void PresenterController::GetSlides (const sal_Int32 nOffset)
256 if ( ! mxSlideShowController.is())
257 return;
259 // Get the current slide from the slide show controller.
260 mxCurrentSlide = nullptr;
261 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
264 sal_Int32 nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset;
265 if (mxSlideShowController->isPaused())
266 nSlideIndex = -1;
268 if (xIndexAccess.is() && nSlideIndex>=0)
270 if (nSlideIndex < xIndexAccess->getCount())
272 mnCurrentSlideIndex = nSlideIndex;
273 mxCurrentSlide.set( xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
277 catch (RuntimeException&)
281 // Get the next slide.
282 mxNextSlide = nullptr;
285 const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset);
286 if (nNextSlideIndex >= 0)
288 if (xIndexAccess.is())
290 if (nNextSlideIndex < xIndexAccess->getCount())
291 mxNextSlide.set( xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY);
295 catch (RuntimeException&)
300 void PresenterController::UpdatePaneTitles()
302 if ( ! mxSlideShowController.is())
303 return;
305 // Get placeholders and their values.
306 static const OUStringLiteral sCurrentSlideNumberPlaceholder (u"CURRENT_SLIDE_NUMBER");
307 static const OUStringLiteral sCurrentSlideNamePlaceholder (u"CURRENT_SLIDE_NAME");
308 static const OUStringLiteral sSlideCountPlaceholder (u"SLIDE_COUNT");
310 // Get string for slide count.
311 OUString sSlideCount ("---");
312 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
313 if (xIndexAccess.is())
314 sSlideCount = OUString::number(xIndexAccess->getCount());
316 // Get string for current slide index.
317 OUString sCurrentSlideNumber (OUString::number(mnCurrentSlideIndex + 1));
319 // Get name of the current slide.
320 OUString sCurrentSlideName;
321 Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY);
322 if (xNamedSlide.is())
323 sCurrentSlideName = xNamedSlide->getName();
324 Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY);
325 if (xSlideProperties.is())
329 OUString sName;
330 if (xSlideProperties->getPropertyValue("LinkDisplayName") >>= sName)
332 // Find out whether the name of the current slide has been
333 // automatically created or has been set by the user.
334 if (sName != sCurrentSlideName)
335 sCurrentSlideName = sName;
338 catch (const beans::UnknownPropertyException&)
343 // Replace the placeholders with their current values.
344 for (auto& rxPane : mpPaneContainer->maPanes)
346 OSL_ASSERT(rxPane != nullptr);
348 OUString sTemplate (IsAccessibilityActive()
349 ? rxPane->msAccessibleTitleTemplate
350 : rxPane->msTitleTemplate);
351 if (sTemplate.isEmpty())
352 continue;
354 OUStringBuffer sResult;
355 sResult.ensureCapacity(sTemplate.getLength());
357 sal_Int32 nIndex (0);
358 while (true)
360 sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex);
361 if (nStartIndex < 0)
363 // Add the remaining part of the string.
364 sResult.append(sTemplate.subView(nIndex));
365 break;
367 else
369 // Add the part preceding the next %.
370 sResult.append(sTemplate.subView(nIndex, nStartIndex-nIndex));
372 // Get the placeholder
373 ++nStartIndex;
374 const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1));
375 const std::u16string_view sPlaceholder (sTemplate.subView(nStartIndex, nEndIndex-nStartIndex));
376 nIndex = nEndIndex+1;
378 // Replace the placeholder with its current value.
379 if (sPlaceholder == sCurrentSlideNumberPlaceholder)
380 sResult.append(sCurrentSlideNumber);
381 else if (sPlaceholder == sCurrentSlideNamePlaceholder)
382 sResult.append(sCurrentSlideName);
383 else if (sPlaceholder == sSlideCountPlaceholder)
384 sResult.append(sSlideCount);
388 rxPane->msTitle = sResult.makeStringAndClear();
389 if (rxPane->mxPane.is())
390 rxPane->mxPane->SetTitle(rxPane->msTitle);
394 void PresenterController::UpdateViews()
396 // Tell all views about the slides they should display.
397 for (const auto& rxPane : mpPaneContainer->maPanes)
399 Reference<drawing::XDrawView> xDrawView (rxPane->mxView, UNO_QUERY);
400 if (xDrawView.is())
401 xDrawView->setCurrentPage(mxCurrentSlide);
405 SharedBitmapDescriptor
406 PresenterController::GetViewBackground (const OUString& rsViewURL) const
408 if (mpTheme != nullptr)
410 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
411 return mpTheme->GetBitmap(sStyleName, "Background");
413 return SharedBitmapDescriptor();
416 PresenterTheme::SharedFontDescriptor
417 PresenterController::GetViewFont (const OUString& rsViewURL) const
419 if (mpTheme != nullptr)
421 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
422 return mpTheme->GetFont(sStyleName);
424 return PresenterTheme::SharedFontDescriptor();
427 const std::shared_ptr<PresenterTheme>& PresenterController::GetTheme() const
429 return mpTheme;
432 const ::rtl::Reference<PresenterWindowManager>& PresenterController::GetWindowManager() const
434 return mpWindowManager;
437 const Reference<presentation::XSlideShowController>&
438 PresenterController::GetSlideShowController() const
440 return mxSlideShowController;
443 const rtl::Reference<PresenterPaneContainer>& PresenterController::GetPaneContainer() const
445 return mpPaneContainer;
448 const ::rtl::Reference<PresenterPaneBorderPainter>& PresenterController::GetPaneBorderPainter() const
450 return mpPaneBorderPainter;
453 const std::shared_ptr<PresenterCanvasHelper>& PresenterController::GetCanvasHelper() const
455 return mpCanvasHelper;
458 const Reference<drawing::XPresenterHelper>& PresenterController::GetPresenterHelper() const
460 return mxPresenterHelper;
463 const std::shared_ptr<PresenterPaintManager>& PresenterController::GetPaintManager() const
465 return mpPaintManager;
468 void PresenterController::ShowView (const OUString& rsViewURL)
470 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
471 mpPaneContainer->FindViewURL(rsViewURL));
472 if (!pDescriptor)
473 return;
475 pDescriptor->mbIsActive = true;
476 mxConfigurationController->requestResourceActivation(
477 pDescriptor->mxPaneId,
478 ResourceActivationMode_ADD);
479 mxConfigurationController->requestResourceActivation(
480 ResourceId::createWithAnchor(
481 mxComponentContext,
482 rsViewURL,
483 pDescriptor->mxPaneId),
484 ResourceActivationMode_REPLACE);
487 void PresenterController::HideView (const OUString& rsViewURL)
489 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
490 mpPaneContainer->FindViewURL(rsViewURL));
491 if (pDescriptor)
493 mxConfigurationController->requestResourceDeactivation(
494 ResourceId::createWithAnchor(
495 mxComponentContext,
496 rsViewURL,
497 pDescriptor->mxPaneId));
501 void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const
503 if ( ! mxUrlTransformer.is())
504 return;
506 util::URL aURL;
507 aURL.Complete = rsCommand;
508 mxUrlTransformer->parseStrict(aURL);
510 Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
511 if ( ! xDispatch.is())
512 return;
514 xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
517 Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const
519 if ( ! mxController.is())
520 return nullptr;
522 Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY);
523 if ( ! xDispatchProvider.is())
524 return nullptr;
526 return xDispatchProvider->queryDispatch(
527 rURL,
528 OUString(),
529 frame::FrameSearchFlag::SELF);
532 util::URL PresenterController::CreateURLFromString (const OUString& rsURL) const
534 util::URL aURL;
536 if (mxUrlTransformer.is())
538 aURL.Complete = rsURL;
539 mxUrlTransformer->parseStrict(aURL);
542 return aURL;
545 const Reference<drawing::framework::XConfigurationController>&
546 PresenterController::GetConfigurationController() const
548 return mxConfigurationController;
551 const Reference<drawing::XDrawPage>& PresenterController::GetCurrentSlide() const
553 return mxCurrentSlide;
556 bool PresenterController::HasTransition (Reference<drawing::XDrawPage> const & rxPage)
558 bool bTransition = false;
559 if( rxPage.is() )
561 Reference<beans::XPropertySet> xSlidePropertySet (rxPage, UNO_QUERY);
564 sal_uInt16 aTransitionType = 0;
565 xSlidePropertySet->getPropertyValue("TransitionType") >>= aTransitionType;
566 if (aTransitionType > 0)
568 bTransition = true;
571 catch (const beans::UnknownPropertyException&)
575 return bTransition;
578 bool PresenterController::HasCustomAnimation (Reference<drawing::XDrawPage> const & rxPage)
580 bool bCustomAnimation = false;
581 if( rxPage.is() )
583 sal_uInt32 i, nCount = rxPage->getCount();
584 for ( i = 0; i < nCount; i++ )
586 Reference<drawing::XShape> xShape(rxPage->getByIndex(i), UNO_QUERY);
587 Reference<beans::XPropertySet> xShapePropertySet(xShape, UNO_QUERY);
588 presentation::AnimationEffect aEffect = presentation::AnimationEffect_NONE;
589 presentation::AnimationEffect aTextEffect = presentation::AnimationEffect_NONE;
592 xShapePropertySet->getPropertyValue("Effect") >>= aEffect;
593 xShapePropertySet->getPropertyValue("TextEffect") >>= aTextEffect;
595 catch (const beans::UnknownPropertyException&)
598 if( aEffect != presentation::AnimationEffect_NONE ||
599 aTextEffect != presentation::AnimationEffect_NONE )
601 bCustomAnimation = true;
602 break;
606 return bCustomAnimation;
609 void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
611 if ( mbIsAccessibilityActive != bIsActive)
613 mbIsAccessibilityActive = bIsActive;
614 UpdatePaneTitles();
619 void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
621 if (!mxSlideShowController.is())
622 return;
624 switch (rEvent.Buttons)
626 case awt::MouseButton::LEFT:
627 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
628 mxSlideShowController->gotoNextSlide();
629 else
630 mxSlideShowController->gotoNextEffect();
631 break;
633 case awt::MouseButton::RIGHT:
634 mxSlideShowController->gotoPreviousSlide();
635 break;
637 default:
638 // Other or multiple buttons.
639 break;
643 void PresenterController::RequestViews (
644 const bool bIsSlideSorterActive,
645 const bool bIsNotesViewActive,
646 const bool bIsHelpViewActive)
648 for (const auto& rxPane : mpPaneContainer->maPanes)
650 bool bActivate (true);
651 const OUString sViewURL (rxPane->msViewURL);
652 if (sViewURL == PresenterViewFactory::msNotesViewURL)
654 bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
656 else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
658 bActivate = bIsSlideSorterActive;
660 else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
661 || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
663 bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
665 else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
667 bActivate = true;
669 else if (sViewURL == PresenterViewFactory::msHelpViewURL)
671 bActivate = bIsHelpViewActive;
674 if (bActivate)
675 ShowView(sViewURL);
676 else
677 HideView(sViewURL);
681 void PresenterController::SetPresentationTime(IPresentationTime* pPresentationTime)
683 mpPresentationTime = pPresentationTime;
686 IPresentationTime* PresenterController::GetPresentationTime()
688 return mpPresentationTime;
691 //----- XConfigurationChangeListener ------------------------------------------
693 void SAL_CALL PresenterController::notifyConfigurationChange (
694 const ConfigurationChangeEvent& rEvent)
696 if (rBHelper.bDisposed || rBHelper.bInDispose)
698 throw lang::DisposedException (
699 "PresenterController object has already been disposed",
700 static_cast<uno::XWeak*>(this));
703 sal_Int32 nType (0);
704 if ( ! (rEvent.UserData >>= nType))
705 return;
707 switch (nType)
709 case ResourceActivationEventType:
710 if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
712 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
714 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
716 // A pane bound to the main pane has been created and is
717 // stored in the pane container.
718 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
719 if (xPane.is())
721 mpPaneContainer->FindPaneId(xPane->getResourceId());
724 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
726 // A view bound to one of the panes has been created and is
727 // stored in the pane container along with its pane.
728 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
729 if (xView.is())
731 mpPaneContainer->StoreView(xView);
732 UpdateViews();
733 mpWindowManager->NotifyViewCreation(xView);
736 break;
738 case ResourceDeactivationEventType:
739 if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
741 // If this is a view then remove it from the pane container.
742 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
743 if (xView.is())
745 PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
746 mpPaneContainer->RemoveView(xView));
748 // A possibly opaque view has been removed. Update()
749 // updates the clip polygon.
750 mpWindowManager->Update();
751 // Request the repainting of the area previously
752 // occupied by the view.
753 if (pDescriptor)
754 GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
757 break;
759 case ConfigurationUpdateEndEventType:
760 if (IsAccessibilityActive())
762 mpAccessibleObject->UpdateAccessibilityHierarchy();
763 UpdateCurrentSlide(0);
765 break;
769 //----- XEventListener --------------------------------------------------------
771 void SAL_CALL PresenterController::disposing (
772 const lang::EventObject& rEvent)
774 if (rEvent.Source.get() == static_cast<cppu::OWeakObject*>(mxController.get()))
775 mxController = nullptr;
776 else if (rEvent.Source == mxConfigurationController)
777 mxConfigurationController = nullptr;
778 else if (rEvent.Source == mxSlideShowController)
779 mxSlideShowController = nullptr;
780 else if (rEvent.Source == mxMainWindow)
781 mxMainWindow = nullptr;
784 //----- XFrameActionListener --------------------------------------------------
786 void SAL_CALL PresenterController::frameAction (
787 const frame::FrameActionEvent& rEvent)
789 if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
791 if (mxSlideShowController.is())
792 mxSlideShowController->activate();
796 //----- XKeyListener ----------------------------------------------------------
798 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
800 // Tell all views about the unhandled key event.
801 for (const auto& rxPane : mpPaneContainer->maPanes)
803 if ( ! rxPane->mbIsActive)
804 continue;
806 Reference<awt::XKeyListener> xKeyListener (rxPane->mxView, UNO_QUERY);
807 if (xKeyListener.is())
808 xKeyListener->keyPressed(rEvent);
812 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
814 if (rEvent.Source != mxMainWindow)
815 return;
817 switch (rEvent.KeyCode)
819 case awt::Key::ESCAPE:
820 case awt::Key::SUBTRACT:
822 if( mxController.is() )
824 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
825 if( xPS.is() )
827 Reference< XPresentation > xP( xPS->getPresentation() );
828 if( xP.is() )
829 xP->end();
833 break;
835 case awt::Key::PAGEDOWN:
836 if (mxSlideShowController.is())
838 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
839 mxSlideShowController->gotoNextSlide();
840 else
841 mxSlideShowController->gotoNextEffect();
843 break;
845 case awt::Key::RIGHT:
846 case awt::Key::SPACE:
847 case awt::Key::DOWN:
848 if (mxSlideShowController.is())
850 mxSlideShowController->gotoNextEffect();
852 break;
854 case awt::Key::PAGEUP:
855 if (mxSlideShowController.is())
857 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
858 mxSlideShowController->gotoPreviousSlide();
859 else
860 mxSlideShowController->gotoPreviousEffect();
862 break;
864 case awt::Key::LEFT:
865 case awt::Key::UP:
866 case awt::Key::BACKSPACE:
867 if (mxSlideShowController.is())
869 mxSlideShowController->gotoPreviousEffect();
871 break;
873 case awt::Key::P:
874 if (mxSlideShowController.is())
876 bool bPenEnabled = mxSlideShowController->getUsePen();
877 mxSlideShowController->setUsePen( !bPenEnabled );
879 break;
881 // tdf#149351 Ctrl+A disables pointer as pen mode
882 case awt::Key::A:
883 if (mxSlideShowController.is())
885 if (rEvent.Modifiers == awt::KeyModifier::MOD1)
887 mxSlideShowController->setUsePen( false );
890 break;
892 case awt::Key::E:
893 if (mxSlideShowController.is())
895 mxSlideShowController->setEraseAllInk( true );
897 break;
899 case awt::Key::HOME:
900 if (mxSlideShowController.is())
902 mxSlideShowController->gotoFirstSlide();
904 break;
906 case awt::Key::END:
907 if (mxSlideShowController.is())
909 mxSlideShowController->gotoLastSlide();
911 break;
913 case awt::Key::W:
914 case awt::Key::COMMA:
915 if (mxSlideShowController.is())
917 if (mxSlideShowController->isPaused())
918 mxSlideShowController->resume();
919 else
920 mxSlideShowController->blankScreen(0x00ffffff);
922 break;
924 case awt::Key::B:
925 case awt::Key::POINT:
926 if (mxSlideShowController.is())
928 if (mxSlideShowController->isPaused())
929 mxSlideShowController->resume();
930 else
931 mxSlideShowController->blankScreen(0x00000000);
933 break;
935 case awt::Key::NUM0:
936 case awt::Key::NUM1:
937 case awt::Key::NUM2:
938 case awt::Key::NUM3:
939 case awt::Key::NUM4:
940 case awt::Key::NUM5:
941 case awt::Key::NUM6:
942 case awt::Key::NUM7:
943 case awt::Key::NUM8:
944 case awt::Key::NUM9:
945 HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
946 break;
948 case awt::Key::RETURN:
949 if (mnPendingSlideNumber > 0)
951 if (mxSlideShowController.is())
952 mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
953 mnPendingSlideNumber = -1;
955 else
957 if (mxSlideShowController.is())
958 mxSlideShowController->gotoNextEffect();
961 break;
963 case awt::Key::F1:
964 // Toggle the help view.
965 if (mpWindowManager)
967 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
968 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
969 else
970 mpWindowManager->SetHelpViewState(false);
973 break;
975 default:
976 // Tell all views about the unhandled key event.
977 for (const auto& rxPane : mpPaneContainer->maPanes)
979 if ( ! rxPane->mbIsActive)
980 continue;
982 Reference<awt::XKeyListener> xKeyListener (rxPane->mxView, UNO_QUERY);
983 if (xKeyListener.is())
984 xKeyListener->keyReleased(rEvent);
986 break;
990 void PresenterController::HandleNumericKeyPress (
991 const sal_Int32 nKey,
992 const sal_Int32 nModifiers)
994 switch (nModifiers)
996 case 0:
997 if (mnPendingSlideNumber == -1)
998 mnPendingSlideNumber = 0;
999 UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
1000 break;
1002 case awt::KeyModifier::MOD1:
1003 // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
1004 // (slide view, notes view, normal). Ctrl-4 switches monitors
1005 mnPendingSlideNumber = -1;
1006 if (!mpWindowManager)
1007 return;
1008 switch(nKey)
1010 case 1:
1011 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
1012 break;
1013 case 2:
1014 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
1015 break;
1016 case 3:
1017 mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
1018 break;
1019 case 4:
1020 SwitchMonitors();
1021 break;
1022 default:
1023 // Ignore unsupported key.
1024 break;
1026 break;
1028 default:
1029 // Ignore unsupported modifiers.
1030 break;
1034 //----- XMouseListener --------------------------------------------------------
1036 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent&)
1038 if (mxMainWindow.is())
1039 mxMainWindow->setFocus();
1042 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent&) {}
1044 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent&) {}
1046 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent&) {}
1048 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
1050 if ( ! rxPane.is())
1051 return;
1053 mpAccessibleObject = new PresenterAccessible(
1054 mxComponentContext,
1055 this,
1056 rxPane);
1058 LoadTheme(rxPane);
1060 // Main pane has been created and is now observed by the window
1061 // manager.
1062 mpWindowManager->SetParentPane(rxPane);
1063 mpWindowManager->SetTheme(mpTheme);
1065 if (mpPaneBorderPainter)
1066 mpPaneBorderPainter->SetTheme(mpTheme);
1068 // Add key listener
1069 mxMainWindow = rxPane->getWindow();
1070 if (mxMainWindow.is())
1072 mxMainWindow->addKeyListener(this);
1073 mxMainWindow->addMouseListener(this);
1075 Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
1076 if (xPane2.is())
1077 xPane2->setVisible(true);
1079 mpPaintManager = std::make_shared<PresenterPaintManager>(mxMainWindow, mxPresenterHelper, mpPaneContainer);
1081 mxCanvas.set(rxPane->getCanvas(), UNO_QUERY);
1083 if (mxSlideShowController.is())
1084 mxSlideShowController->activate();
1086 UpdateCurrentSlide(0);
1089 void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
1091 // Create (load) the current theme.
1092 if (rxPane.is())
1093 mpTheme = std::make_shared<PresenterTheme>(mxComponentContext, rxPane->getCanvas());
1096 double PresenterController::GetSlideAspectRatio() const
1098 double nSlideAspectRatio (28.0/21.0);
1102 if (mxController.is())
1104 Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
1105 mxController->getModel(), UNO_QUERY_THROW);
1106 Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
1107 if (xSlides.is() && xSlides->getCount()>0)
1109 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
1110 sal_Int32 nWidth (28000);
1111 sal_Int32 nHeight (21000);
1112 if ((xProperties->getPropertyValue("Width") >>= nWidth)
1113 && (xProperties->getPropertyValue("Height") >>= nHeight)
1114 && nHeight > 0)
1116 nSlideAspectRatio = double(nWidth) / double(nHeight);
1121 catch (RuntimeException&)
1123 OSL_ASSERT(false);
1126 return nSlideAspectRatio;
1129 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
1131 mnPendingSlideNumber = nPendingSlideNumber;
1133 if (mpTheme == nullptr)
1134 return;
1136 if ( ! mxMainWindow.is())
1137 return;
1139 PresenterTheme::SharedFontDescriptor pFont (
1140 mpTheme->GetFont("PendingSlideNumberFont"));
1141 if (!pFont)
1142 return;
1144 pFont->PrepareFont(mxCanvas);
1145 if ( ! pFont->mxFont.is())
1146 return;
1148 const OUString sText (OUString::number(mnPendingSlideNumber));
1149 rendering::StringContext aContext (sText, 0, sText.getLength());
1150 pFont->mxFont->createTextLayout(
1151 aContext,
1152 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1156 void PresenterController::SwitchMonitors()
1158 rtl::Reference<PresenterScreen> pScreen( mxScreen );
1159 if (!pScreen)
1160 return;
1162 pScreen->SwitchMonitors();
1165 void PresenterController::ExitPresenter()
1167 if( mxController.is() )
1169 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
1170 if( xPS.is() )
1172 Reference< XPresentation > xP( xPS->getPresentation() );
1173 if( xP.is() )
1174 xP->end();
1179 } // end of namespace ::sdext::presenter
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */