Updated core
[LibreOffice.git] / sdext / source / presenter / PresenterController.cxx
blobceceadd2a21369cdfc2463da570c8144581da6bc
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/XPresentation.hpp>
52 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
53 #include <com/sun/star/rendering/CompositeOperation.hpp>
54 #include <com/sun/star/rendering/TextDirection.hpp>
55 #include <com/sun/star/util/URLTransformer.hpp>
57 #include <rtl/ustrbuf.hxx>
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::presentation;
62 using namespace ::com::sun::star::drawing::framework;
64 namespace {
65 const sal_Int32 ResourceActivationEventType = 0;
66 const sal_Int32 ResourceDeactivationEventType = 1;
67 const sal_Int32 ConfigurationUpdateEndEventType = 2;
70 namespace sdext { namespace presenter {
72 PresenterController::InstanceContainer PresenterController::maInstances;
74 ::rtl::Reference<PresenterController> PresenterController::Instance (
75 const css::uno::Reference<css::frame::XFrame>& rxFrame)
77 InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame));
78 if (iInstance != maInstances.end())
79 return iInstance->second;
80 else
81 return ::rtl::Reference<PresenterController>();
84 PresenterController::PresenterController (
85 const css::uno::WeakReference<css::lang::XEventListener> &rxScreen,
86 const Reference<XComponentContext>& rxContext,
87 const Reference<frame::XController>& rxController,
88 const Reference<presentation::XSlideShowController>& rxSlideShowController,
89 const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
90 const Reference<XResourceId>& rxMainPaneId)
91 : PresenterControllerInterfaceBase(m_aMutex),
92 mxScreen(rxScreen),
93 mxComponentContext(rxContext),
94 mxController(rxController),
95 mxConfigurationController(),
96 mxSlideShowController(rxSlideShowController),
97 mxMainPaneId(rxMainPaneId),
98 mpPaneContainer(rpPaneContainer),
99 mnCurrentSlideIndex(-1),
100 mxCurrentSlide(),
101 mxNextSlide(),
102 mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)),
103 mnWindowBackgroundColor(0x00ffffff),
104 mpTheme(),
105 mxMainWindow(),
106 mpPaneBorderPainter(),
107 mpCanvasHelper(new PresenterCanvasHelper()),
108 mxPresenterHelper(),
109 mpPaintManager(),
110 mnPendingSlideNumber(-1),
111 mxUrlTransformer(),
112 mpAccessibleObject(),
113 mbIsAccessibilityActive(false)
115 OSL_ASSERT(mxController.is());
117 if ( ! mxSlideShowController.is())
118 throw lang::IllegalArgumentException(
119 "missing slide show controller",
120 static_cast<XWeak*>(this),
123 new PresenterCurrentSlideObserver(this,rxSlideShowController);
125 // Listen for configuration changes.
126 Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW);
127 mxConfigurationController = xCM->getConfigurationController();
128 if (mxConfigurationController.is())
130 mxConfigurationController->addConfigurationChangeListener(
131 this,
132 "ResourceActivation",
133 Any(ResourceActivationEventType));
134 mxConfigurationController->addConfigurationChangeListener(
135 this,
136 "ResourceDeactivation",
137 Any(ResourceDeactivationEventType));
138 mxConfigurationController->addConfigurationChangeListener(
139 this,
140 "ConfigurationUpdateEnd",
141 Any(ConfigurationUpdateEndEventType));
144 // Listen for the frame being activated.
145 Reference<frame::XFrame> xFrame (mxController->getFrame());
146 if (xFrame.is())
147 xFrame->addFrameActionListener(this);
149 // Create the border painter.
150 mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext);
151 mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter);
153 // Create an object that is able to load the bitmaps in a format that is
154 // supported by the canvas.
155 Reference<lang::XMultiComponentFactory> xFactory (
156 rxContext->getServiceManager(), UNO_QUERY);
157 if ( ! xFactory.is())
158 return;
159 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
160 xFactory->createInstanceWithContext(
161 "com.sun.star.drawing.PresenterHelper",
162 rxContext),
163 UNO_QUERY_THROW);
165 if (mxSlideShowController.is())
167 mxSlideShowController->activate();
168 Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY);
169 if (xProperties.is())
171 Reference<awt::XWindow> xWindow (
172 xProperties->getPropertyValue("ParentWindow"), UNO_QUERY);
173 if (xWindow.is())
174 xWindow->addKeyListener(this);
178 UpdateCurrentSlide(0);
180 maInstances[mxController->getFrame()] = this;
182 // Create a URLTransformer.
183 if (xFactory.is())
185 mxUrlTransformer = Reference<util::XURLTransformer>(util::URLTransformer::create(mxComponentContext));
189 PresenterController::~PresenterController (void)
193 void PresenterController::disposing (void)
195 maInstances.erase(mxController->getFrame());
197 if (mxMainWindow.is())
199 mxMainWindow->removeKeyListener(this);
200 mxMainWindow->removeFocusListener(this);
201 mxMainWindow->removeMouseListener(this);
202 mxMainWindow->removeMouseMotionListener(this);
203 mxMainWindow = NULL;
205 if (mxConfigurationController.is())
206 mxConfigurationController->removeConfigurationChangeListener(this);
208 Reference<XComponent> xWindowManagerComponent (
209 static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY);
210 mpWindowManager = NULL;
211 if (xWindowManagerComponent.is())
212 xWindowManagerComponent->dispose();
214 if (mxController.is())
216 Reference<frame::XFrame> xFrame (mxController->getFrame());
217 if (xFrame.is())
218 xFrame->removeFrameActionListener(this);
219 mxController = NULL;
222 mxComponentContext = NULL;
223 mxConfigurationController = NULL;
224 mxSlideShowController = NULL;
225 mxMainPaneId = NULL;
226 mpPaneContainer = NULL;
227 mnCurrentSlideIndex = -1;
228 mxCurrentSlide = NULL;
229 mxNextSlide = NULL;
230 mpTheme.reset();
232 Reference<lang::XComponent> xComponent (
233 static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY);
234 mpPaneBorderPainter = NULL;
235 if (xComponent.is())
236 xComponent->dispose();
238 mpCanvasHelper.reset();
240 Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY);
241 mxPresenterHelper = NULL;
242 if (xComponent.is())
243 xComponent->dispose();
245 mpPaintManager.reset();
246 mnPendingSlideNumber = -1;
248 Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY);
249 mxUrlTransformer = NULL;
250 if (xComponent.is())
251 xComponent->dispose();
255 void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset)
257 GetSlides(nOffset);
258 UpdatePaneTitles();
259 UpdateViews();
261 // Update the accessibility object.
262 if (IsAccessibilityActive())
264 sal_Int32 nSlideCount (0);
265 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
266 if (xIndexAccess.is())
267 nSlideCount = xIndexAccess->getCount();
268 mpAccessibleObject->NotifyCurrentSlideChange(mnCurrentSlideIndex, nSlideCount);
272 void PresenterController::GetSlides (const sal_Int32 nOffset)
274 if ( ! mxSlideShowController.is())
275 return;
277 // Get the current slide from the slide show controller.
278 mxCurrentSlide = NULL;
279 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
280 sal_Int32 nSlideIndex = -1;
283 nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset;
284 if (mxSlideShowController->isPaused())
285 nSlideIndex = -1;
287 if (xIndexAccess.is() && nSlideIndex>=0)
289 if (nSlideIndex < xIndexAccess->getCount())
291 mnCurrentSlideIndex = nSlideIndex;
292 mxCurrentSlide = Reference<drawing::XDrawPage>(
293 xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
297 catch (RuntimeException&)
301 // Get the next slide.
302 mxNextSlide = NULL;
305 const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset);
306 if (nNextSlideIndex >= 0)
308 if (xIndexAccess.is())
310 if (nNextSlideIndex < xIndexAccess->getCount())
311 mxNextSlide = Reference<drawing::XDrawPage>(
312 xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY);
316 catch (RuntimeException&)
321 void PresenterController::UpdatePaneTitles (void)
323 if ( ! mxSlideShowController.is())
324 return;
326 // Get placeholders and their values.
327 const OUString sCurrentSlideNumberPlaceholder ("CURRENT_SLIDE_NUMBER");
328 const OUString sCurrentSlideNamePlaceholder ("CURRENT_SLIDE_NAME");
329 const OUString sSlideCountPlaceholder ("SLIDE_COUNT");
331 // Get string for slide count.
332 OUString sSlideCount ("---");
333 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
334 if (xIndexAccess.is())
335 sSlideCount = OUString::valueOf(xIndexAccess->getCount());
337 // Get string for current slide index.
338 OUString sCurrentSlideNumber (OUString::valueOf(mnCurrentSlideIndex + 1));
340 // Get name of the current slide.
341 OUString sCurrentSlideName;
342 Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY);
343 if (xNamedSlide.is())
344 sCurrentSlideName = xNamedSlide->getName();
345 Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY);
346 if (xSlideProperties.is())
350 OUString sName;
351 if (xSlideProperties->getPropertyValue("LinkDisplayName") >>= sName)
353 // Find out whether the name of the current slide has been
354 // automatically created or has been set by the user.
355 if (sName != sCurrentSlideName)
356 sCurrentSlideName = sName;
359 catch (beans::UnknownPropertyException&)
364 // Replace the placeholders with their current values.
365 PresenterPaneContainer::PaneList::const_iterator iPane;
366 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
368 OSL_ASSERT((*iPane).get() != NULL);
370 OUString sTemplate (IsAccessibilityActive()
371 ? (*iPane)->msAccessibleTitleTemplate
372 : (*iPane)->msTitleTemplate);
373 if (sTemplate.isEmpty())
374 continue;
376 OUStringBuffer sResult;
377 sResult.ensureCapacity(sTemplate.getLength());
379 sal_Int32 nIndex (0);
380 while (true)
382 sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex);
383 if (nStartIndex < 0)
385 // Add the remaining part of the string.
386 sResult.append(sTemplate.copy(nIndex, sTemplate.getLength()-nIndex));
387 break;
389 else
391 // Add the part preceding the next %.
392 sResult.append(sTemplate.copy(nIndex, nStartIndex-nIndex));
394 // Get the placeholder
395 ++nIndex;
396 ++nStartIndex;
397 const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1));
398 const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex));
399 nIndex = nEndIndex+1;
401 // Replace the placeholder with its current value.
402 if (sPlaceholder == sCurrentSlideNumberPlaceholder)
403 sResult.append(sCurrentSlideNumber);
404 else if (sPlaceholder == sCurrentSlideNamePlaceholder)
405 sResult.append(sCurrentSlideName);
406 else if (sPlaceholder == sSlideCountPlaceholder)
407 sResult.append(sSlideCount);
411 (*iPane)->msTitle = sResult.makeStringAndClear();
412 if ((*iPane)->mxPane.is())
413 (*iPane)->mxPane->SetTitle((*iPane)->msTitle);
417 void PresenterController::UpdateViews (void)
419 // Tell all views about the slides they should display.
420 PresenterPaneContainer::PaneList::const_iterator iPane;
421 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
423 Reference<drawing::XDrawView> xDrawView ((*iPane)->mxView, UNO_QUERY);
424 if (xDrawView.is())
425 xDrawView->setCurrentPage(mxCurrentSlide);
429 SharedBitmapDescriptor
430 PresenterController::GetViewBackground (const OUString& rsViewURL) const
432 if (mpTheme.get() != NULL)
434 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
435 return mpTheme->GetBitmap(sStyleName, "Background");
437 return SharedBitmapDescriptor();
440 PresenterTheme::SharedFontDescriptor
441 PresenterController::GetViewFont (const OUString& rsViewURL) const
443 if (mpTheme.get() != NULL)
445 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
446 return mpTheme->GetFont(sStyleName);
448 return PresenterTheme::SharedFontDescriptor();
451 ::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme (void) const
453 return mpTheme;
456 ::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const
458 return mpWindowManager;
461 Reference<presentation::XSlideShowController>
462 PresenterController::GetSlideShowController(void) const
464 return mxSlideShowController;
467 rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const
469 return mpPaneContainer;
472 ::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const
474 return mpPaneBorderPainter;
477 ::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const
479 return mpCanvasHelper;
482 Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const
484 return mxPresenterHelper;
487 ::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) const
489 return mpPaintManager;
492 void PresenterController::ShowView (const OUString& rsViewURL)
494 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
495 mpPaneContainer->FindViewURL(rsViewURL));
496 if (pDescriptor.get() != NULL)
498 pDescriptor->mbIsActive = true;
499 mxConfigurationController->requestResourceActivation(
500 pDescriptor->mxPaneId,
501 ResourceActivationMode_ADD);
502 mxConfigurationController->requestResourceActivation(
503 ResourceId::createWithAnchor(
504 mxComponentContext,
505 rsViewURL,
506 pDescriptor->mxPaneId),
507 ResourceActivationMode_REPLACE);
511 void PresenterController::HideView (const OUString& rsViewURL)
513 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
514 mpPaneContainer->FindViewURL(rsViewURL));
515 if (pDescriptor.get() != NULL)
517 mxConfigurationController->requestResourceDeactivation(
518 ResourceId::createWithAnchor(
519 mxComponentContext,
520 rsViewURL,
521 pDescriptor->mxPaneId));
525 void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const
527 if ( ! mxUrlTransformer.is())
528 return;
530 util::URL aURL;
531 aURL.Complete = rsCommand;
532 mxUrlTransformer->parseStrict(aURL);
534 Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
535 if ( ! xDispatch.is())
536 return;
538 xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
541 Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const
543 if ( ! mxController.is())
544 return NULL;
546 Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY);
547 if ( ! xDispatchProvider.is())
548 return NULL;
550 return xDispatchProvider->queryDispatch(
551 rURL,
552 OUString(),
553 frame::FrameSearchFlag::SELF);
556 util::URL PresenterController::CreateURLFromString (const OUString& rsURL) const
558 util::URL aURL;
560 if (mxUrlTransformer.is())
562 aURL.Complete = rsURL;
563 mxUrlTransformer->parseStrict(aURL);
566 return aURL;
569 Reference<drawing::framework::XConfigurationController>
570 PresenterController::GetConfigurationController (void) const
572 return mxConfigurationController;
575 Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const
577 return mxCurrentSlide;
580 void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
582 if ( mbIsAccessibilityActive != bIsActive)
584 mbIsAccessibilityActive = bIsActive;
585 UpdatePaneTitles();
589 bool PresenterController::IsAccessibilityActive (void) const
591 return mbIsAccessibilityActive;
594 void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
596 if (mxSlideShowController.is())
598 switch (rEvent.Buttons)
600 case awt::MouseButton::LEFT:
601 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
602 mxSlideShowController->gotoNextSlide();
603 else
604 mxSlideShowController->gotoNextEffect();
605 break;
607 case awt::MouseButton::RIGHT:
608 mxSlideShowController->gotoPreviousSlide();
609 break;
611 default:
612 // Other or multiple buttons.
613 break;
618 void PresenterController::RequestViews (
619 const bool bIsSlideSorterActive,
620 const bool bIsNotesViewActive,
621 const bool bIsHelpViewActive)
623 PresenterPaneContainer::PaneList::const_iterator iPane;
624 PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
625 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
627 bool bActivate (true);
628 const OUString sViewURL ((*iPane)->msViewURL);
629 if (sViewURL == PresenterViewFactory::msNotesViewURL)
631 bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
633 else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
635 bActivate = bIsSlideSorterActive;
637 else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
638 || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
640 bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
642 else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
644 bActivate = true;
646 else if (sViewURL == PresenterViewFactory::msHelpViewURL)
648 bActivate = bIsHelpViewActive;
651 if (bActivate)
652 ShowView(sViewURL);
653 else
654 HideView(sViewURL);
658 //----- XConfigurationChangeListener ------------------------------------------
660 void SAL_CALL PresenterController::notifyConfigurationChange (
661 const ConfigurationChangeEvent& rEvent)
662 throw (RuntimeException)
664 ThrowIfDisposed();
666 sal_Int32 nType (0);
667 if ( ! (rEvent.UserData >>= nType))
668 return;
670 switch (nType)
672 case ResourceActivationEventType:
673 if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
675 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
677 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
679 // A pane bound to the main pane has been created and is
680 // stored in the pane container.
681 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
682 if (xPane.is())
684 PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
685 mpPaneContainer->FindPaneId(xPane->getResourceId()));
687 // When there is a call out anchor location set then tell the
688 // window about it.
689 if (pDescriptor->mbHasCalloutAnchor)
690 pDescriptor->mxPane->SetCalloutAnchor(
691 pDescriptor->maCalloutAnchorLocation);
694 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
696 // A view bound to one of the panes has been created and is
697 // stored in the pane container along with its pane.
698 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
699 if (xView.is())
701 SharedBitmapDescriptor pViewBackground(
702 GetViewBackground(xView->getResourceId()->getResourceURL()));
703 mpPaneContainer->StoreView(xView, pViewBackground);
704 UpdateViews();
705 mpWindowManager->NotifyViewCreation(xView);
708 break;
710 case ResourceDeactivationEventType:
711 if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
713 // If this is a view then remove it from the pane container.
714 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
715 if (xView.is())
717 PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
718 mpPaneContainer->RemoveView(xView));
720 // A possibly opaque view has been removed. Update()
721 // updates the clip polygon.
722 mpWindowManager->Update();
723 // Request the repainting of the area previously
724 // occupied by the view.
725 if (pDescriptor.get() != NULL)
726 GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
729 break;
731 case ConfigurationUpdateEndEventType:
732 if (IsAccessibilityActive())
734 mpAccessibleObject->UpdateAccessibilityHierarchy();
735 UpdateCurrentSlide(0);
737 break;
741 //----- XEventListener --------------------------------------------------------
743 void SAL_CALL PresenterController::disposing (
744 const lang::EventObject& rEvent)
745 throw (RuntimeException)
747 if (rEvent.Source == mxController)
748 mxController = NULL;
749 else if (rEvent.Source == mxConfigurationController)
750 mxConfigurationController = NULL;
751 else if (rEvent.Source == mxSlideShowController)
752 mxSlideShowController = NULL;
753 else if (rEvent.Source == mxMainWindow)
754 mxMainWindow = NULL;
757 //----- XFrameActionListener --------------------------------------------------
759 void SAL_CALL PresenterController::frameAction (
760 const frame::FrameActionEvent& rEvent)
761 throw (RuntimeException)
763 if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
765 if (mxSlideShowController.is())
766 mxSlideShowController->activate();
770 //----- XKeyListener ----------------------------------------------------------
772 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
773 throw (RuntimeException)
775 // Tell all views about the unhandled key event.
776 PresenterPaneContainer::PaneList::const_iterator iPane;
777 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
779 if ( ! (*iPane)->mbIsActive)
780 continue;
782 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
783 if (xKeyListener.is())
784 xKeyListener->keyPressed(rEvent);
788 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
789 throw (RuntimeException)
791 if (rEvent.Source != mxMainWindow)
792 return;
794 switch (rEvent.KeyCode)
796 case awt::Key::ESCAPE:
797 case awt::Key::SUBTRACT:
799 if( mxController.is() )
801 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
802 if( xPS.is() )
804 Reference< XPresentation > xP( xPS->getPresentation() );
805 if( xP.is() )
806 xP->end();
810 break;
812 case awt::Key::PAGEDOWN:
813 if (mxSlideShowController.is())
815 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
816 mxSlideShowController->gotoNextSlide();
817 else
818 mxSlideShowController->gotoNextEffect();
820 break;
822 case awt::Key::RIGHT:
823 case awt::Key::SPACE:
824 case awt::Key::DOWN:
825 case awt::Key::N:
826 if (mxSlideShowController.is())
828 mxSlideShowController->gotoNextEffect();
830 break;
832 case awt::Key::PAGEUP:
833 if (mxSlideShowController.is())
835 if (rEvent.Modifiers == awt::KeyModifier::MOD2)
836 mxSlideShowController->gotoPreviousSlide();
837 else
838 mxSlideShowController->gotoPreviousEffect();
840 break;
842 case awt::Key::LEFT:
843 case awt::Key::UP:
844 case awt::Key::P:
845 case awt::Key::BACKSPACE:
846 if (mxSlideShowController.is())
848 mxSlideShowController->gotoPreviousEffect();
850 break;
852 case awt::Key::HOME:
853 if (mxSlideShowController.is())
855 mxSlideShowController->gotoFirstSlide();
857 break;
859 case awt::Key::END:
860 if (mxSlideShowController.is())
862 mxSlideShowController->gotoLastSlide();
864 break;
866 case awt::Key::W:
867 case awt::Key::COMMA:
868 if (mxSlideShowController.is())
870 if (mxSlideShowController->isPaused())
871 mxSlideShowController->resume();
872 else
873 mxSlideShowController->blankScreen(0x00ffffff);
875 break;
877 case awt::Key::B:
878 case awt::Key::POINT:
879 if (mxSlideShowController.is())
881 if (mxSlideShowController->isPaused())
882 mxSlideShowController->resume();
883 else
884 mxSlideShowController->blankScreen(0x00000000);
886 break;
888 case awt::Key::NUM0:
889 case awt::Key::NUM1:
890 case awt::Key::NUM2:
891 case awt::Key::NUM3:
892 case awt::Key::NUM4:
893 case awt::Key::NUM5:
894 case awt::Key::NUM6:
895 case awt::Key::NUM7:
896 case awt::Key::NUM8:
897 case awt::Key::NUM9:
898 HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
899 break;
901 case awt::Key::RETURN:
902 if (mnPendingSlideNumber > 0)
904 if (mxSlideShowController.is())
905 mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
906 mnPendingSlideNumber = -1;
908 else
910 if (mxSlideShowController.is())
911 mxSlideShowController->gotoNextEffect();
914 break;
916 case awt::Key::F1:
917 // Toggle the help view.
918 if (mpWindowManager.get() != NULL)
920 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
921 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
922 else
923 mpWindowManager->SetHelpViewState(false);
926 break;
928 default:
929 // Tell all views about the unhandled key event.
930 PresenterPaneContainer::PaneList::const_iterator iPane;
931 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
933 if ( ! (*iPane)->mbIsActive)
934 continue;
936 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
937 if (xKeyListener.is())
938 xKeyListener->keyReleased(rEvent);
940 break;
944 void PresenterController::HandleNumericKeyPress (
945 const sal_Int32 nKey,
946 const sal_Int32 nModifiers)
948 switch (nModifiers)
950 case 0:
951 if (mnPendingSlideNumber == -1)
952 mnPendingSlideNumber = 0;
953 UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
954 break;
956 case awt::KeyModifier::MOD1:
957 // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
958 // (slide view, notes view, normal)
959 mnPendingSlideNumber = -1;
960 if (mpWindowManager.get() == NULL)
961 return;
962 switch(nKey)
964 case 1:
965 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
966 break;
967 case 2:
968 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
969 break;
970 case 3:
971 mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
972 break;
973 default:
974 // Ignore unsupported key.
975 break;
978 default:
979 // Ignore unsupported modifiers.
980 break;
984 //----- XFocusListener --------------------------------------------------------
986 void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent)
987 throw (css::uno::RuntimeException)
989 (void)rEvent;
992 void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent)
993 throw (css::uno::RuntimeException)
995 (void)rEvent;
998 //----- XMouseListener --------------------------------------------------------
1000 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent)
1001 throw (css::uno::RuntimeException)
1003 (void)rEvent;
1004 if (mxMainWindow.is())
1005 mxMainWindow->setFocus();
1008 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent)
1009 throw (css::uno::RuntimeException)
1011 (void)rEvent;
1014 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent)
1015 throw (css::uno::RuntimeException)
1017 (void)rEvent;
1020 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent)
1021 throw (css::uno::RuntimeException)
1023 (void)rEvent;
1026 //----- XMouseMotionListener --------------------------------------------------
1028 void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent)
1029 throw (css::uno::RuntimeException)
1031 (void)rEvent;
1034 void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent)
1035 throw (css::uno::RuntimeException)
1037 (void)rEvent;
1040 //-----------------------------------------------------------------------------
1042 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
1044 if ( ! rxPane.is())
1045 return;
1047 mpAccessibleObject = new PresenterAccessible(
1048 mxComponentContext,
1049 this,
1050 rxPane);
1052 LoadTheme(rxPane);
1054 // Main pane has been created and is now observed by the window
1055 // manager.
1056 mpWindowManager->SetParentPane(rxPane);
1057 mpWindowManager->SetTheme(mpTheme);
1059 if (mpPaneBorderPainter.get() != NULL)
1060 mpPaneBorderPainter->SetTheme(mpTheme);
1062 // Add key listener
1063 mxMainWindow = rxPane->getWindow();
1064 if (mxMainWindow.is())
1066 mxMainWindow->addKeyListener(this);
1067 mxMainWindow->addFocusListener(this);
1068 mxMainWindow->addMouseListener(this);
1069 mxMainWindow->addMouseMotionListener(this);
1071 Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
1072 if (xPane2.is())
1073 xPane2->setVisible(sal_True);
1075 mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer));
1077 mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY);
1079 if (mxSlideShowController.is())
1080 mxSlideShowController->activate();
1082 UpdateCurrentSlide(0);
1085 void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
1087 // Create (load) the current theme.
1088 if (rxPane.is())
1089 mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas()));
1092 double PresenterController::GetSlideAspectRatio (void) const
1094 double nSlideAspectRatio (28.0/21.0);
1098 if (mxController.is())
1100 Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
1101 mxController->getModel(), UNO_QUERY_THROW);
1102 Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
1103 if (xSlides.is() && xSlides->getCount()>0)
1105 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
1106 sal_Int32 nWidth (28000);
1107 sal_Int32 nHeight (21000);
1108 if ((xProperties->getPropertyValue(OUString("Width")) >>= nWidth)
1109 && (xProperties->getPropertyValue(OUString("Height")) >>= nHeight)
1110 && nHeight > 0)
1112 nSlideAspectRatio = double(nWidth) / double(nHeight);
1117 catch (RuntimeException&)
1119 OSL_ASSERT(false);
1122 return nSlideAspectRatio;
1125 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
1127 mnPendingSlideNumber = nPendingSlideNumber;
1129 if (mpTheme.get() == NULL)
1130 return;
1132 if ( ! mxMainWindow.is())
1133 return;
1135 PresenterTheme::SharedFontDescriptor pFont (
1136 mpTheme->GetFont("PendingSlideNumberFont"));
1137 if (pFont.get() == NULL)
1138 return;
1140 pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1141 if ( ! pFont->mxFont.is())
1142 return;
1144 const OUString sText (OUString::valueOf(mnPendingSlideNumber));
1145 rendering::StringContext aContext (sText, 0, sText.getLength());
1146 Reference<rendering::XTextLayout> xLayout (
1147 pFont->mxFont->createTextLayout(
1148 aContext,
1149 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1150 0));
1153 void PresenterController::ThrowIfDisposed (void) const
1154 throw (::com::sun::star::lang::DisposedException)
1156 if (rBHelper.bDisposed || rBHelper.bInDispose)
1158 throw lang::DisposedException (
1159 OUString( "PresenterController object has already been disposed"),
1160 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1164 void PresenterController::SwitchMonitors (void)
1166 Reference<lang::XEventListener> xScreen( mxScreen );
1167 if (!xScreen.is())
1168 return;
1170 PresenterScreen *pScreen = dynamic_cast<PresenterScreen *>(xScreen.get());
1171 if (!pScreen)
1172 return;
1174 pScreen->SwitchMonitors();
1177 } } // end of namespace ::sdext::presenter
1179 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */