Bump version to 5.0-14
[LibreOffice.git] / sdext / source / presenter / PresenterController.cxx
blob180e2fdfc043f3f3c102c15d2842b0bee8e7e900
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 "PresenterController.hxx"
22 #include "PresenterAccessibility.hxx"
23 #include "PresenterCanvasHelper.hxx"
24 #include "PresenterCurrentSlideObserver.hxx"
25 #include "PresenterFrameworkObserver.hxx"
26 #include "PresenterHelper.hxx"
27 #include "PresenterScreen.hxx"
28 #include "PresenterNotesView.hxx"
29 #include "PresenterPaintManager.hxx"
30 #include "PresenterPaneBase.hxx"
31 #include "PresenterPaneContainer.hxx"
32 #include "PresenterPaneBorderPainter.hxx"
33 #include "PresenterTheme.hxx"
34 #include "PresenterViewFactory.hxx"
35 #include "PresenterWindowManager.hxx"
37 #include <com/sun/star/accessibility/AccessibleRole.hpp>
38 #include <com/sun/star/accessibility/XAccessible.hpp>
39 #include <com/sun/star/awt/Key.hpp>
40 #include <com/sun/star/awt/KeyModifier.hpp>
41 #include <com/sun/star/awt/MouseButton.hpp>
42 #include <com/sun/star/awt/XWindowPeer.hpp>
43 #include <com/sun/star/container/XNamed.hpp>
44 #include <com/sun/star/drawing/XDrawView.hpp>
45 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
46 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
47 #include <com/sun/star/drawing/framework/ResourceId.hpp>
48 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
49 #include <com/sun/star/frame/FrameSearchFlag.hpp>
50 #include <com/sun/star/frame/XDispatchProvider.hpp>
51 #include <com/sun/star/presentation/AnimationEffect.hpp>
52 #include <com/sun/star/presentation/XPresentation.hpp>
53 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
54 #include <com/sun/star/rendering/CompositeOperation.hpp>
55 #include <com/sun/star/rendering/TextDirection.hpp>
56 #include <com/sun/star/util/URLTransformer.hpp>
58 #include <rtl/ustrbuf.hxx>
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::uno;
62 using namespace ::com::sun::star::presentation;
63 using namespace ::com::sun::star::drawing::framework;
65 namespace {
66 const sal_Int32 ResourceActivationEventType = 0;
67 const sal_Int32 ResourceDeactivationEventType = 1;
68 const sal_Int32 ConfigurationUpdateEndEventType = 2;
71 namespace sdext { namespace presenter {
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 const css::uno::WeakReference<css::lang::XEventListener> &rxScreen,
87 const Reference<XComponentContext>& rxContext,
88 const Reference<frame::XController>& rxController,
89 const Reference<presentation::XSlideShowController>& rxSlideShowController,
90 const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
91 const Reference<XResourceId>& rxMainPaneId)
92 : PresenterControllerInterfaceBase(m_aMutex),
93 mxScreen(rxScreen),
94 mxComponentContext(rxContext),
95 mxController(rxController),
96 mxConfigurationController(),
97 mxSlideShowController(rxSlideShowController),
98 mxMainPaneId(rxMainPaneId),
99 mpPaneContainer(rpPaneContainer),
100 mnCurrentSlideIndex(-1),
101 mxCurrentSlide(),
102 mxNextSlide(),
103 mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)),
104 mnWindowBackgroundColor(0x00ffffff),
105 mpTheme(),
106 mxMainWindow(),
107 mpPaneBorderPainter(),
108 mpCanvasHelper(new 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(), UNO_QUERY);
158 if ( ! xFactory.is())
159 return;
160 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
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 = Reference<util::XURLTransformer>(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->removeFocusListener(this);
202 mxMainWindow->removeMouseListener(this);
203 mxMainWindow->removeMouseMotionListener(this);
204 mxMainWindow = NULL;
206 if (mxConfigurationController.is())
207 mxConfigurationController->removeConfigurationChangeListener(this);
209 Reference<XComponent> xWindowManagerComponent (
210 static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY);
211 mpWindowManager = NULL;
212 if (xWindowManagerComponent.is())
213 xWindowManagerComponent->dispose();
215 if (mxController.is())
217 Reference<frame::XFrame> xFrame (mxController->getFrame());
218 if (xFrame.is())
219 xFrame->removeFrameActionListener(this);
220 mxController = NULL;
223 mxComponentContext = NULL;
224 mxConfigurationController = NULL;
225 mxSlideShowController = NULL;
226 mxMainPaneId = NULL;
227 mpPaneContainer = NULL;
228 mnCurrentSlideIndex = -1;
229 mxCurrentSlide = NULL;
230 mxNextSlide = NULL;
231 mpTheme.reset();
233 Reference<lang::XComponent> xComponent (
234 static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY);
235 mpPaneBorderPainter = NULL;
236 if (xComponent.is())
237 xComponent->dispose();
239 mpCanvasHelper.reset();
241 Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY);
242 mxPresenterHelper = NULL;
243 if (xComponent.is())
244 xComponent->dispose();
246 mpPaintManager.reset();
247 mnPendingSlideNumber = -1;
249 Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY);
250 mxUrlTransformer = NULL;
251 if (xComponent.is())
252 xComponent->dispose();
256 void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset)
258 // std::cerr << "Updating current Slide to " << nOffset << std::endl;
259 GetSlides(nOffset);
260 UpdatePaneTitles();
261 UpdateViews();
263 // Update the accessibility object.
264 if (IsAccessibilityActive())
266 sal_Int32 nSlideCount (0);
267 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
268 if (xIndexAccess.is())
269 nSlideCount = xIndexAccess->getCount();
270 mpAccessibleObject->NotifyCurrentSlideChange(mnCurrentSlideIndex, nSlideCount);
274 void PresenterController::GetSlides (const sal_Int32 nOffset)
276 if ( ! mxSlideShowController.is())
277 return;
279 // Get the current slide from the slide show controller.
280 mxCurrentSlide = NULL;
281 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
282 sal_Int32 nSlideIndex = -1;
285 nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset;
286 if (mxSlideShowController->isPaused())
287 nSlideIndex = -1;
289 if (xIndexAccess.is() && nSlideIndex>=0)
291 if (nSlideIndex < xIndexAccess->getCount())
293 mnCurrentSlideIndex = nSlideIndex;
294 mxCurrentSlide = Reference<drawing::XDrawPage>(
295 xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
299 catch (RuntimeException&)
303 // Get the next slide.
304 mxNextSlide = NULL;
307 const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset);
308 if (nNextSlideIndex >= 0)
310 if (xIndexAccess.is())
312 if (nNextSlideIndex < xIndexAccess->getCount())
313 mxNextSlide = Reference<drawing::XDrawPage>(
314 xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY);
318 catch (RuntimeException&)
323 void PresenterController::UpdatePaneTitles()
325 if ( ! mxSlideShowController.is())
326 return;
328 // Get placeholders and their values.
329 const OUString sCurrentSlideNumberPlaceholder ("CURRENT_SLIDE_NUMBER");
330 const OUString sCurrentSlideNamePlaceholder ("CURRENT_SLIDE_NAME");
331 const OUString sSlideCountPlaceholder ("SLIDE_COUNT");
333 // Get string for slide count.
334 OUString sSlideCount ("---");
335 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
336 if (xIndexAccess.is())
337 sSlideCount = OUString::number(xIndexAccess->getCount());
339 // Get string for current slide index.
340 OUString sCurrentSlideNumber (OUString::number(mnCurrentSlideIndex + 1));
342 // Get name of the current slide.
343 OUString sCurrentSlideName;
344 Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY);
345 if (xNamedSlide.is())
346 sCurrentSlideName = xNamedSlide->getName();
347 Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY);
348 if (xSlideProperties.is())
352 OUString sName;
353 if (xSlideProperties->getPropertyValue("LinkDisplayName") >>= sName)
355 // Find out whether the name of the current slide has been
356 // automatically created or has been set by the user.
357 if (sName != sCurrentSlideName)
358 sCurrentSlideName = sName;
361 catch (const beans::UnknownPropertyException&)
366 // Replace the placeholders with their current values.
367 PresenterPaneContainer::PaneList::const_iterator iPane;
368 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
370 OSL_ASSERT((*iPane).get() != NULL);
372 OUString sTemplate (IsAccessibilityActive()
373 ? (*iPane)->msAccessibleTitleTemplate
374 : (*iPane)->msTitleTemplate);
375 if (sTemplate.isEmpty())
376 continue;
378 OUStringBuffer sResult;
379 sResult.ensureCapacity(sTemplate.getLength());
381 sal_Int32 nIndex (0);
382 while (true)
384 sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex);
385 if (nStartIndex < 0)
387 // Add the remaining part of the string.
388 sResult.append(sTemplate.copy(nIndex, sTemplate.getLength()-nIndex));
389 break;
391 else
393 // Add the part preceding the next %.
394 sResult.append(sTemplate.copy(nIndex, nStartIndex-nIndex));
396 // Get the placeholder
397 ++nStartIndex;
398 const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1));
399 const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex));
400 nIndex = nEndIndex+1;
402 // Replace the placeholder with its current value.
403 if (sPlaceholder == sCurrentSlideNumberPlaceholder)
404 sResult.append(sCurrentSlideNumber);
405 else if (sPlaceholder == sCurrentSlideNamePlaceholder)
406 sResult.append(sCurrentSlideName);
407 else if (sPlaceholder == sSlideCountPlaceholder)
408 sResult.append(sSlideCount);
412 (*iPane)->msTitle = sResult.makeStringAndClear();
413 if ((*iPane)->mxPane.is())
414 (*iPane)->mxPane->SetTitle((*iPane)->msTitle);
418 void PresenterController::UpdateViews()
420 // Tell all views about the slides they should display.
421 PresenterPaneContainer::PaneList::const_iterator iPane;
422 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
424 Reference<drawing::XDrawView> xDrawView ((*iPane)->mxView, UNO_QUERY);
425 if (xDrawView.is())
426 xDrawView->setCurrentPage(mxCurrentSlide);
430 SharedBitmapDescriptor
431 PresenterController::GetViewBackground (const OUString& rsViewURL) const
433 if (mpTheme.get() != NULL)
435 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
436 return mpTheme->GetBitmap(sStyleName, "Background");
438 return SharedBitmapDescriptor();
441 PresenterTheme::SharedFontDescriptor
442 PresenterController::GetViewFont (const OUString& rsViewURL) const
444 if (mpTheme.get() != NULL)
446 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
447 return mpTheme->GetFont(sStyleName);
449 return PresenterTheme::SharedFontDescriptor();
452 ::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme() const
454 return mpTheme;
457 ::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager() const
459 return mpWindowManager;
462 Reference<presentation::XSlideShowController>
463 PresenterController::GetSlideShowController() const
465 return mxSlideShowController;
468 rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer() const
470 return mpPaneContainer;
473 ::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter() const
475 return mpPaneBorderPainter;
478 ::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper() const
480 return mpCanvasHelper;
483 Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper() const
485 return mxPresenterHelper;
488 ::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager() const
490 return mpPaintManager;
493 void PresenterController::ShowView (const OUString& rsViewURL)
495 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
496 mpPaneContainer->FindViewURL(rsViewURL));
497 if (pDescriptor.get() != NULL)
499 pDescriptor->mbIsActive = true;
500 mxConfigurationController->requestResourceActivation(
501 pDescriptor->mxPaneId,
502 ResourceActivationMode_ADD);
503 mxConfigurationController->requestResourceActivation(
504 ResourceId::createWithAnchor(
505 mxComponentContext,
506 rsViewURL,
507 pDescriptor->mxPaneId),
508 ResourceActivationMode_REPLACE);
512 void PresenterController::HideView (const OUString& rsViewURL)
514 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
515 mpPaneContainer->FindViewURL(rsViewURL));
516 if (pDescriptor.get() != NULL)
518 mxConfigurationController->requestResourceDeactivation(
519 ResourceId::createWithAnchor(
520 mxComponentContext,
521 rsViewURL,
522 pDescriptor->mxPaneId));
526 void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const
528 if ( ! mxUrlTransformer.is())
529 return;
531 util::URL aURL;
532 aURL.Complete = rsCommand;
533 mxUrlTransformer->parseStrict(aURL);
535 Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
536 if ( ! xDispatch.is())
537 return;
539 xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
542 Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const
544 if ( ! mxController.is())
545 return NULL;
547 Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY);
548 if ( ! xDispatchProvider.is())
549 return NULL;
551 return xDispatchProvider->queryDispatch(
552 rURL,
553 OUString(),
554 frame::FrameSearchFlag::SELF);
557 util::URL PresenterController::CreateURLFromString (const OUString& rsURL) const
559 util::URL aURL;
561 if (mxUrlTransformer.is())
563 aURL.Complete = rsURL;
564 mxUrlTransformer->parseStrict(aURL);
567 return aURL;
570 Reference<drawing::framework::XConfigurationController>
571 PresenterController::GetConfigurationController() const
573 return mxConfigurationController;
576 Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide() const
578 return mxCurrentSlide;
581 bool PresenterController::HasTransition (Reference<drawing::XDrawPage>& rxPage)
583 bool bTransition = false;
584 sal_uInt16 aTransitionType = 0;
585 if( rxPage.is() )
587 Reference<beans::XPropertySet> xSlidePropertySet (rxPage, UNO_QUERY);
590 xSlidePropertySet->getPropertyValue("TransitionType") >>= aTransitionType;
591 if (aTransitionType > 0)
593 bTransition = true;
596 catch (const beans::UnknownPropertyException&)
600 return bTransition;
603 bool PresenterController::HasCustomAnimation (Reference<drawing::XDrawPage>& rxPage)
605 bool bCustomAnimation = false;
606 if( rxPage.is() )
608 sal_uInt32 i, nCount = rxPage->getCount();
609 for ( i = 0; i < nCount; i++ )
611 Reference<drawing::XShape> xShape(rxPage->getByIndex(i), UNO_QUERY);
612 Reference<beans::XPropertySet> xShapePropertySet(xShape, UNO_QUERY);
613 presentation::AnimationEffect aEffect = presentation::AnimationEffect_NONE;
614 presentation::AnimationEffect aTextEffect = presentation::AnimationEffect_NONE;
617 xShapePropertySet->getPropertyValue("Effect") >>= aEffect;
618 xShapePropertySet->getPropertyValue("TextEffect") >>= aTextEffect;
620 catch (const beans::UnknownPropertyException&)
623 if( aEffect != presentation::AnimationEffect_NONE ||
624 aTextEffect != presentation::AnimationEffect_NONE )
626 bCustomAnimation = true;
627 break;
631 return bCustomAnimation;
634 void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
636 if ( mbIsAccessibilityActive != bIsActive)
638 mbIsAccessibilityActive = bIsActive;
639 UpdatePaneTitles();
644 void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
646 if (mxSlideShowController.is())
648 switch (rEvent.Buttons)
650 case awt::MouseButton::LEFT:
651 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
652 mxSlideShowController->gotoNextSlide();
653 else
654 mxSlideShowController->gotoNextEffect();
655 break;
657 case awt::MouseButton::RIGHT:
658 mxSlideShowController->gotoPreviousSlide();
659 break;
661 default:
662 // Other or multiple buttons.
663 break;
668 void PresenterController::RequestViews (
669 const bool bIsSlideSorterActive,
670 const bool bIsNotesViewActive,
671 const bool bIsHelpViewActive)
673 PresenterPaneContainer::PaneList::const_iterator iPane;
674 PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
675 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
677 bool bActivate (true);
678 const OUString sViewURL ((*iPane)->msViewURL);
679 if (sViewURL == PresenterViewFactory::msNotesViewURL)
681 bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
683 else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
685 bActivate = bIsSlideSorterActive;
687 else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
688 || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
690 bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
692 else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
694 bActivate = true;
696 else if (sViewURL == PresenterViewFactory::msHelpViewURL)
698 bActivate = bIsHelpViewActive;
701 if (bActivate)
702 ShowView(sViewURL);
703 else
704 HideView(sViewURL);
708 //----- XConfigurationChangeListener ------------------------------------------
710 void SAL_CALL PresenterController::notifyConfigurationChange (
711 const ConfigurationChangeEvent& rEvent)
712 throw (RuntimeException, std::exception)
714 ThrowIfDisposed();
716 sal_Int32 nType (0);
717 if ( ! (rEvent.UserData >>= nType))
718 return;
720 switch (nType)
722 case ResourceActivationEventType:
723 if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
725 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
727 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
729 // A pane bound to the main pane has been created and is
730 // stored in the pane container.
731 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
732 if (xPane.is())
734 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
735 mpPaneContainer->FindPaneId(xPane->getResourceId()));
737 // When there is a call out anchor location set then tell the
738 // window about it.
739 if (pDescriptor->mbHasCalloutAnchor)
740 pDescriptor->mxPane->SetCalloutAnchor(
741 pDescriptor->maCalloutAnchorLocation);
744 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
746 // A view bound to one of the panes has been created and is
747 // stored in the pane container along with its pane.
748 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
749 if (xView.is())
751 SharedBitmapDescriptor pViewBackground(
752 GetViewBackground(xView->getResourceId()->getResourceURL()));
753 mpPaneContainer->StoreView(xView, pViewBackground);
754 UpdateViews();
755 mpWindowManager->NotifyViewCreation(xView);
758 break;
760 case ResourceDeactivationEventType:
761 if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
763 // If this is a view then remove it from the pane container.
764 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
765 if (xView.is())
767 PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
768 mpPaneContainer->RemoveView(xView));
770 // A possibly opaque view has been removed. Update()
771 // updates the clip polygon.
772 mpWindowManager->Update();
773 // Request the repainting of the area previously
774 // occupied by the view.
775 if (pDescriptor.get() != NULL)
776 GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
779 break;
781 case ConfigurationUpdateEndEventType:
782 if (IsAccessibilityActive())
784 mpAccessibleObject->UpdateAccessibilityHierarchy();
785 UpdateCurrentSlide(0);
787 break;
791 //----- XEventListener --------------------------------------------------------
793 void SAL_CALL PresenterController::disposing (
794 const lang::EventObject& rEvent)
795 throw (RuntimeException, std::exception)
797 if (rEvent.Source == mxController)
798 mxController = NULL;
799 else if (rEvent.Source == mxConfigurationController)
800 mxConfigurationController = NULL;
801 else if (rEvent.Source == mxSlideShowController)
802 mxSlideShowController = NULL;
803 else if (rEvent.Source == mxMainWindow)
804 mxMainWindow = NULL;
807 //----- XFrameActionListener --------------------------------------------------
809 void SAL_CALL PresenterController::frameAction (
810 const frame::FrameActionEvent& rEvent)
811 throw (RuntimeException, std::exception)
813 if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
815 if (mxSlideShowController.is())
816 mxSlideShowController->activate();
820 //----- XKeyListener ----------------------------------------------------------
822 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
823 throw (RuntimeException, std::exception)
825 // Tell all views about the unhandled key event.
826 PresenterPaneContainer::PaneList::const_iterator iPane;
827 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
829 if ( ! (*iPane)->mbIsActive)
830 continue;
832 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
833 if (xKeyListener.is())
834 xKeyListener->keyPressed(rEvent);
838 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
839 throw (RuntimeException, std::exception)
841 if (rEvent.Source != mxMainWindow)
842 return;
844 switch (rEvent.KeyCode)
846 case awt::Key::ESCAPE:
847 case awt::Key::SUBTRACT:
849 if( mxController.is() )
851 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
852 if( xPS.is() )
854 Reference< XPresentation > xP( xPS->getPresentation() );
855 if( xP.is() )
856 xP->end();
860 break;
862 case awt::Key::PAGEDOWN:
863 if (mxSlideShowController.is())
865 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
866 mxSlideShowController->gotoNextSlide();
867 else
868 mxSlideShowController->gotoNextEffect();
870 break;
872 case awt::Key::RIGHT:
873 case awt::Key::SPACE:
874 case awt::Key::DOWN:
875 case awt::Key::N:
876 if (mxSlideShowController.is())
878 mxSlideShowController->gotoNextEffect();
880 break;
882 case awt::Key::PAGEUP:
883 if (mxSlideShowController.is())
885 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
886 mxSlideShowController->gotoPreviousSlide();
887 else
888 mxSlideShowController->gotoPreviousEffect();
890 break;
892 case awt::Key::LEFT:
893 case awt::Key::UP:
894 case awt::Key::P:
895 case awt::Key::BACKSPACE:
896 if (mxSlideShowController.is())
898 mxSlideShowController->gotoPreviousEffect();
900 break;
902 case awt::Key::HOME:
903 if (mxSlideShowController.is())
905 mxSlideShowController->gotoFirstSlide();
907 break;
909 case awt::Key::END:
910 if (mxSlideShowController.is())
912 mxSlideShowController->gotoLastSlide();
914 break;
916 case awt::Key::W:
917 case awt::Key::COMMA:
918 if (mxSlideShowController.is())
920 if (mxSlideShowController->isPaused())
921 mxSlideShowController->resume();
922 else
923 mxSlideShowController->blankScreen(0x00ffffff);
925 break;
927 case awt::Key::B:
928 case awt::Key::POINT:
929 if (mxSlideShowController.is())
931 if (mxSlideShowController->isPaused())
932 mxSlideShowController->resume();
933 else
934 mxSlideShowController->blankScreen(0x00000000);
936 break;
938 case awt::Key::NUM0:
939 case awt::Key::NUM1:
940 case awt::Key::NUM2:
941 case awt::Key::NUM3:
942 case awt::Key::NUM4:
943 case awt::Key::NUM5:
944 case awt::Key::NUM6:
945 case awt::Key::NUM7:
946 case awt::Key::NUM8:
947 case awt::Key::NUM9:
948 HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
949 break;
951 case awt::Key::RETURN:
952 if (mnPendingSlideNumber > 0)
954 if (mxSlideShowController.is())
955 mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
956 mnPendingSlideNumber = -1;
958 else
960 if (mxSlideShowController.is())
961 mxSlideShowController->gotoNextEffect();
964 break;
966 case awt::Key::F1:
967 // Toggle the help view.
968 if (mpWindowManager.get() != NULL)
970 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
971 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
972 else
973 mpWindowManager->SetHelpViewState(false);
976 break;
978 default:
979 // Tell all views about the unhandled key event.
980 PresenterPaneContainer::PaneList::const_iterator iPane;
981 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
983 if ( ! (*iPane)->mbIsActive)
984 continue;
986 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
987 if (xKeyListener.is())
988 xKeyListener->keyReleased(rEvent);
990 break;
994 void PresenterController::HandleNumericKeyPress (
995 const sal_Int32 nKey,
996 const sal_Int32 nModifiers)
998 switch (nModifiers)
1000 case 0:
1001 if (mnPendingSlideNumber == -1)
1002 mnPendingSlideNumber = 0;
1003 UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
1004 break;
1006 case awt::KeyModifier::MOD1:
1007 // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
1008 // (slide view, notes view, normal). Ctrl-4 switches monitors
1009 mnPendingSlideNumber = -1;
1010 if (mpWindowManager.get() == NULL)
1011 return;
1012 switch(nKey)
1014 case 1:
1015 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
1016 break;
1017 case 2:
1018 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
1019 break;
1020 case 3:
1021 mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
1022 break;
1023 case 4:
1024 SwitchMonitors();
1025 break;
1026 default:
1027 // Ignore unsupported key.
1028 break;
1031 default:
1032 // Ignore unsupported modifiers.
1033 break;
1037 //----- XFocusListener --------------------------------------------------------
1039 void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent)
1040 throw (css::uno::RuntimeException, std::exception)
1042 (void)rEvent;
1045 void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent)
1046 throw (css::uno::RuntimeException, std::exception)
1048 (void)rEvent;
1051 //----- XMouseListener --------------------------------------------------------
1053 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent)
1054 throw (css::uno::RuntimeException, std::exception)
1056 (void)rEvent;
1057 if (mxMainWindow.is())
1058 mxMainWindow->setFocus();
1061 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent)
1062 throw (css::uno::RuntimeException, std::exception)
1064 (void)rEvent;
1067 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent)
1068 throw (css::uno::RuntimeException, std::exception)
1070 (void)rEvent;
1073 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent)
1074 throw (css::uno::RuntimeException, std::exception)
1076 (void)rEvent;
1079 //----- XMouseMotionListener --------------------------------------------------
1081 void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent)
1082 throw (css::uno::RuntimeException, std::exception)
1084 (void)rEvent;
1087 void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent)
1088 throw (css::uno::RuntimeException, std::exception)
1090 (void)rEvent;
1095 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
1097 if ( ! rxPane.is())
1098 return;
1100 mpAccessibleObject = new PresenterAccessible(
1101 mxComponentContext,
1102 this,
1103 rxPane);
1105 LoadTheme(rxPane);
1107 // Main pane has been created and is now observed by the window
1108 // manager.
1109 mpWindowManager->SetParentPane(rxPane);
1110 mpWindowManager->SetTheme(mpTheme);
1112 if (mpPaneBorderPainter.get() != NULL)
1113 mpPaneBorderPainter->SetTheme(mpTheme);
1115 // Add key listener
1116 mxMainWindow = rxPane->getWindow();
1117 if (mxMainWindow.is())
1119 mxMainWindow->addKeyListener(this);
1120 mxMainWindow->addFocusListener(this);
1121 mxMainWindow->addMouseListener(this);
1122 mxMainWindow->addMouseMotionListener(this);
1124 Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
1125 if (xPane2.is())
1126 xPane2->setVisible(sal_True);
1128 mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer));
1130 mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY);
1132 if (mxSlideShowController.is())
1133 mxSlideShowController->activate();
1135 UpdateCurrentSlide(0);
1138 void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
1140 // Create (load) the current theme.
1141 if (rxPane.is())
1142 mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas()));
1145 double PresenterController::GetSlideAspectRatio() const
1147 double nSlideAspectRatio (28.0/21.0);
1151 if (mxController.is())
1153 Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
1154 mxController->getModel(), UNO_QUERY_THROW);
1155 Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
1156 if (xSlides.is() && xSlides->getCount()>0)
1158 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
1159 sal_Int32 nWidth (28000);
1160 sal_Int32 nHeight (21000);
1161 if ((xProperties->getPropertyValue("Width") >>= nWidth)
1162 && (xProperties->getPropertyValue("Height") >>= nHeight)
1163 && nHeight > 0)
1165 nSlideAspectRatio = double(nWidth) / double(nHeight);
1170 catch (RuntimeException&)
1172 OSL_ASSERT(false);
1175 return nSlideAspectRatio;
1178 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
1180 mnPendingSlideNumber = nPendingSlideNumber;
1182 if (mpTheme.get() == NULL)
1183 return;
1185 if ( ! mxMainWindow.is())
1186 return;
1188 PresenterTheme::SharedFontDescriptor pFont (
1189 mpTheme->GetFont("PendingSlideNumberFont"));
1190 if (pFont.get() == NULL)
1191 return;
1193 pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1194 if ( ! pFont->mxFont.is())
1195 return;
1197 const OUString sText (OUString::number(mnPendingSlideNumber));
1198 rendering::StringContext aContext (sText, 0, sText.getLength());
1199 Reference<rendering::XTextLayout> xLayout (
1200 pFont->mxFont->createTextLayout(
1201 aContext,
1202 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1203 0));
1206 void PresenterController::ThrowIfDisposed() const
1207 throw (::com::sun::star::lang::DisposedException)
1209 if (rBHelper.bDisposed || rBHelper.bInDispose)
1211 throw lang::DisposedException (
1212 OUString( "PresenterController object has already been disposed"),
1213 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1217 void PresenterController::SwitchMonitors()
1219 Reference<lang::XEventListener> xScreen( mxScreen );
1220 if (!xScreen.is())
1221 return;
1223 PresenterScreen *pScreen = dynamic_cast<PresenterScreen *>(xScreen.get());
1224 if (!pScreen)
1225 return;
1227 pScreen->SwitchMonitors();
1230 } } // end of namespace ::sdext::presenter
1232 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */