blob: a7a54e312ea279caaf778610c835edaf86cceaa9 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sdext.hxx"
#include "PresenterController.hxx"
#include "PresenterAccessibility.hxx"
#include "PresenterAnimator.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterCurrentSlideObserver.hxx"
#include "PresenterFrameworkObserver.hxx"
#include "PresenterHelper.hxx"
#include "PresenterNotesView.hxx"
#include "PresenterPaintManager.hxx"
#include "PresenterPaneAnimator.hxx"
#include "PresenterPaneBase.hxx"
#include "PresenterPaneContainer.hxx"
#include "PresenterPaneBorderPainter.hxx"
#include "PresenterTheme.hxx"
#include "PresenterViewFactory.hxx"
#include "PresenterWindowManager.hxx"
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/XAccessible.hpp>
#include <com/sun/star/awt/Key.hpp>
#include <com/sun/star/awt/KeyModifier.hpp>
#include <com/sun/star/awt/MouseButton.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/drawing/XDrawView.hpp>
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/presentation/XPresentation.hpp>
#include <com/sun/star/presentation/XPresentationSupplier.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <rtl/ustrbuf.hxx>
#include <boost/bind.hpp>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::presentation;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
namespace {
const sal_Int32 ResourceActivationEventType = 0;
const sal_Int32 ResourceDeactivationEventType = 1;
const sal_Int32 ConfigurationUpdateEndEventType = 2;
}
#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
namespace sdext { namespace presenter {
PresenterController::InstanceContainer PresenterController::maInstances;
::rtl::Reference<PresenterController> PresenterController::Instance (
const css::uno::Reference<css::frame::XFrame>& rxFrame)
{
InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame));
if (iInstance != maInstances.end())
return iInstance->second;
else
return ::rtl::Reference<PresenterController>();
}
PresenterController::PresenterController (
const Reference<XComponentContext>& rxContext,
const Reference<frame::XController>& rxController,
const Reference<presentation::XSlideShowController>& rxSlideShowController,
const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
const Reference<XResourceId>& rxMainPaneId)
: PresenterControllerInterfaceBase(m_aMutex),
mxComponentContext(rxContext),
mxController(rxController),
mxConfigurationController(),
mxSlideShowController(rxSlideShowController),
mxMainPaneId(rxMainPaneId),
mpPaneContainer(rpPaneContainer),
mnCurrentSlideIndex(-1),
mxCurrentSlide(),
mxNextSlide(),
mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)),
mpCurrentPaneAnimation(),
mnWindowBackgroundColor(0x00ffffff),
mpTheme(),
mxMainWindow(),
mpPaneBorderPainter(),
mpAnimator(new PresenterAnimator()),
mpCanvasHelper(new PresenterCanvasHelper()),
mxPresenterHelper(),
mpPaintManager(),
mnPendingSlideNumber(-1),
mxUrlTransformer(),
mpAccessibleObject(),
mbIsAccessibilityActive(false)
{
OSL_ASSERT(mxController.is());
if ( ! mxSlideShowController.is())
throw new lang::IllegalArgumentException(
A2S("missing slide show controller"),
static_cast<XWeak*>(this),
2);
new PresenterCurrentSlideObserver(this,rxSlideShowController);
// Listen for configuration changes.
Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW);
mxConfigurationController = xCM->getConfigurationController();
if (mxConfigurationController.is())
{
mxConfigurationController->addConfigurationChangeListener(
this,
A2S("ResourceActivation"),
Any(ResourceActivationEventType));
mxConfigurationController->addConfigurationChangeListener(
this,
A2S("ResourceDeactivation"),
Any(ResourceDeactivationEventType));
mxConfigurationController->addConfigurationChangeListener(
this,
A2S("ConfigurationUpdateEnd"),
Any(ConfigurationUpdateEndEventType));
}
// Listen for the frame being activated.
Reference<frame::XFrame> xFrame (mxController->getFrame());
if (xFrame.is())
xFrame->addFrameActionListener(this);
// Create the border painter.
mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext);
mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter);
// Create an object that is able to load the bitmaps in a format that is
// supported by the canvas.
Reference<lang::XMultiComponentFactory> xFactory (
rxContext->getServiceManager(), UNO_QUERY);
if ( ! xFactory.is())
return;
mxPresenterHelper = Reference<drawing::XPresenterHelper>(
xFactory->createInstanceWithContext(
A2S("com.sun.star.drawing.PresenterHelper"),
rxContext),
UNO_QUERY_THROW);
if (mxSlideShowController.is())
{
mxSlideShowController->activate();
Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY);
if (xProperties.is())
{
Reference<awt::XWindow> xWindow (
xProperties->getPropertyValue(A2S("ParentWindow")), UNO_QUERY);
if (xWindow.is())
xWindow->addKeyListener(this);
}
}
UpdateCurrentSlide(0);
maInstances[mxController->getFrame()] = this;
// Create a URLTransformer.
if (xFactory.is())
{
mxUrlTransformer = Reference<util::XURLTransformer>(
xFactory->createInstanceWithContext(
A2S("com.sun.star.util.URLTransformer"),
mxComponentContext),
UNO_QUERY);
}
}
PresenterController::~PresenterController (void)
{
}
void PresenterController::disposing (void)
{
maInstances.erase(mxController->getFrame());
if (mxMainWindow.is())
{
mxMainWindow->removeKeyListener(this);
mxMainWindow->removeFocusListener(this);
mxMainWindow->removeMouseListener(this);
mxMainWindow->removeMouseMotionListener(this);
mxMainWindow = NULL;
}
if (mxConfigurationController.is())
mxConfigurationController->removeConfigurationChangeListener(this);
Reference<XComponent> xWindowManagerComponent (
static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY);
mpWindowManager = NULL;
if (xWindowManagerComponent.is())
xWindowManagerComponent->dispose();
if (mxController.is())
{
Reference<frame::XFrame> xFrame (mxController->getFrame());
if (xFrame.is())
xFrame->removeFrameActionListener(this);
mxController = NULL;
}
mxComponentContext = NULL;
mxConfigurationController = NULL;
mxSlideShowController = NULL;
mxMainPaneId = NULL;
mpPaneContainer = NULL;
mnCurrentSlideIndex = -1;
mxCurrentSlide = NULL;
mxNextSlide = NULL;
mpCurrentPaneAnimation.reset();
mpTheme.reset();
{
Reference<lang::XComponent> xComponent (
static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY);
mpPaneBorderPainter = NULL;
if (xComponent.is())
xComponent->dispose();
}
mpAnimator.reset();
mpCanvasHelper.reset();
{
Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY);
mxPresenterHelper = NULL;
if (xComponent.is())
xComponent->dispose();
}
mpPaintManager.reset();
mnPendingSlideNumber = -1;
{
Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY);
mxUrlTransformer = NULL;
if (xComponent.is())
xComponent->dispose();
}
}
void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset)
{
GetSlides(nOffset);
UpdatePaneTitles();
UpdateViews();
// Update the accessibility object.
if (IsAccessibilityActive())
{
sal_Int32 nSlideCount (0);
Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
if (xIndexAccess.is())
nSlideCount = xIndexAccess->getCount();
mpAccessibleObject->NotifyCurrentSlideChange(mnCurrentSlideIndex, nSlideCount);
}
}
void PresenterController::GetSlides (const sal_Int32 nOffset)
{
if ( ! mxSlideShowController.is())
return;
// Get the current slide from the slide show controller.
mxCurrentSlide = NULL;
Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
sal_Int32 nSlideIndex = -1;
try
{
nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset;
if (mxSlideShowController->isPaused())
nSlideIndex = -1;
if (xIndexAccess.is() && nSlideIndex>=0)
{
if (nSlideIndex < xIndexAccess->getCount())
{
mnCurrentSlideIndex = nSlideIndex;
mxCurrentSlide = Reference<drawing::XDrawPage>(
xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY);
}
}
}
catch (RuntimeException&)
{
}
// Get the next slide.
mxNextSlide = NULL;
try
{
const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset);
if (nNextSlideIndex >= 0)
{
if (xIndexAccess.is())
{
if (nNextSlideIndex < xIndexAccess->getCount())
mxNextSlide = Reference<drawing::XDrawPage>(
xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY);
}
}
}
catch (RuntimeException&)
{
}
}
void PresenterController::UpdatePaneTitles (void)
{
if ( ! mxSlideShowController.is())
return;
// Get placeholders and their values.
const OUString sCurrentSlideNumberPlaceholder (A2S("CURRENT_SLIDE_NUMBER"));
const OUString sCurrentSlideNamePlaceholder (A2S("CURRENT_SLIDE_NAME"));
const OUString sSlideCountPlaceholder (A2S("SLIDE_COUNT"));
// Get string for slide count.
OUString sSlideCount (A2S("---"));
Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY);
if (xIndexAccess.is())
sSlideCount = OUString::valueOf(xIndexAccess->getCount());
// Get string for current slide index.
OUString sCurrentSlideNumber (OUString::valueOf(mnCurrentSlideIndex + 1));
// Get name of the current slide.
OUString sCurrentSlideName;
Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY);
if (xNamedSlide.is())
sCurrentSlideName = xNamedSlide->getName();
Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY);
if (xSlideProperties.is())
{
try
{
OUString sName;
if (xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= sName)
{
// Find out whether the name of the current slide has been
// automatically created or has been set by the user.
if (sName != sCurrentSlideName)
sCurrentSlideName = sName;
}
}
catch (beans::UnknownPropertyException&)
{
}
}
// Replace the placeholders with their current values.
PresenterPaneContainer::PaneList::const_iterator iPane;
for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
{
OSL_ASSERT((*iPane).get() != NULL);
OUString sTemplate (IsAccessibilityActive()
? (*iPane)->msAccessibleTitleTemplate
: (*iPane)->msTitleTemplate);
if (sTemplate.getLength() <= 0)
continue;
OUStringBuffer sResult;
sResult.ensureCapacity(sTemplate.getLength());
sal_Int32 nIndex (0);
while (true)
{
sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex);
if (nStartIndex < 0)
{
// Add the remaining part of the string.
sResult.append(sTemplate.copy(nIndex, sTemplate.getLength()-nIndex));
break;
}
else
{
// Add the part preceding the next %.
sResult.append(sTemplate.copy(nIndex, nStartIndex-nIndex));
// Get the placeholder
++nIndex;
++nStartIndex;
const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1));
const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex));
nIndex = nEndIndex+1;
// Replace the placeholder with its current value.
if (sPlaceholder == sCurrentSlideNumberPlaceholder)
sResult.append(sCurrentSlideNumber);
else if (sPlaceholder == sCurrentSlideNamePlaceholder)
sResult.append(sCurrentSlideName);
else if (sPlaceholder == sSlideCountPlaceholder)
sResult.append(sSlideCount);
}
}
(*iPane)->msTitle = sResult.makeStringAndClear();
if ((*iPane)->mxPane.is())
(*iPane)->mxPane->SetTitle((*iPane)->msTitle);
}
}
void PresenterController::UpdateViews (void)
{
// Tell all views about the slides they should display.
PresenterPaneContainer::PaneList::const_iterator iPane;
for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
{
Reference<drawing::XDrawView> xDrawView ((*iPane)->mxView, UNO_QUERY);
if (xDrawView.is())
xDrawView->setCurrentPage(mxCurrentSlide);
}
}
SharedBitmapDescriptor
PresenterController::GetViewBackground (const ::rtl::OUString& rsViewURL) const
{
if (mpTheme.get() != NULL)
{
const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
return mpTheme->GetBitmap(sStyleName, A2S("Background"));
}
return SharedBitmapDescriptor();
}
PresenterTheme::SharedFontDescriptor
PresenterController::GetViewFont (const ::rtl::OUString& rsViewURL) const
{
if (mpTheme.get() != NULL)
{
const OUString sStyleName (mpTheme->GetStyleName(rsViewURL));
return mpTheme->GetFont(sStyleName);
}
return PresenterTheme::SharedFontDescriptor();
}
::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme (void) const
{
return mpTheme;
}
::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const
{
return mpWindowManager;
}
Reference<presentation::XSlideShowController>
PresenterController::GetSlideShowController(void) const
{
return mxSlideShowController;
}
rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const
{
return mpPaneContainer;
}
::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const
{
return mpPaneBorderPainter;
}
::boost::shared_ptr<PresenterAnimator> PresenterController::GetAnimator (void) const
{
return mpAnimator;
}
::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const
{
return mpCanvasHelper;
}
Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const
{
return mxPresenterHelper;
}
::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) const
{
return mpPaintManager;
}
void PresenterController::HideSlideSorter (void)
{
if (mpCurrentPaneAnimation.get() != NULL)
{
mpCurrentPaneAnimation->HidePane();
mpCurrentPaneAnimation.reset();
}
}
void PresenterController::ShowView (const OUString& rsViewURL)
{
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPaneContainer->FindViewURL(rsViewURL));
if (pDescriptor.get() != NULL)
{
pDescriptor->mbIsActive = true;
mxConfigurationController->requestResourceActivation(
pDescriptor->mxPaneId,
ResourceActivationMode_ADD);
mxConfigurationController->requestResourceActivation(
ResourceId::createWithAnchor(
mxComponentContext,
rsViewURL,
pDescriptor->mxPaneId),
ResourceActivationMode_REPLACE);
}
}
void PresenterController::HideView (const OUString& rsViewURL)
{
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPaneContainer->FindViewURL(rsViewURL));
if (pDescriptor.get() != NULL)
{
mxConfigurationController->requestResourceDeactivation(
ResourceId::createWithAnchor(
mxComponentContext,
rsViewURL,
pDescriptor->mxPaneId));
}
}
bool PresenterController::IsViewVisible (const OUString& rsViewURL) const
{
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPaneContainer->FindViewURL(rsViewURL));
if (pDescriptor.get() != NULL)
{
return mxConfigurationController->getResource(
ResourceId::createWithAnchor(
mxComponentContext,
rsViewURL,
pDescriptor->mxPaneId)).is();
}
return false;
}
void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const
{
if ( ! mxUrlTransformer.is())
return;
util::URL aURL;
aURL.Complete = rsCommand;
mxUrlTransformer->parseStrict(aURL);
Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
if ( ! xDispatch.is())
return;
xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
}
Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const
{
if ( ! mxController.is())
return NULL;
Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY);
if ( ! xDispatchProvider.is())
return NULL;
return xDispatchProvider->queryDispatch(
rURL,
OUString(),
frame::FrameSearchFlag::SELF);
}
util::URL PresenterController::CreateURLFromString (const ::rtl::OUString& rsURL) const
{
util::URL aURL;
if (mxUrlTransformer.is())
{
aURL.Complete = rsURL;
mxUrlTransformer->parseStrict(aURL);
}
return aURL;
}
Reference<drawing::framework::XConfigurationController>
PresenterController::GetConfigurationController (void) const
{
return mxConfigurationController;
}
Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const
{
return mxCurrentSlide;
}
::rtl::Reference<PresenterAccessible> PresenterController::GetAccessible (void) const
{
return mpAccessibleObject;
}
void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
{
if ( mbIsAccessibilityActive != bIsActive)
{
mbIsAccessibilityActive = bIsActive;
UpdatePaneTitles();
}
}
bool PresenterController::IsAccessibilityActive (void) const
{
return mbIsAccessibilityActive;
}
void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
{
if (mxSlideShowController.is())
{
switch (rEvent.Buttons)
{
case awt::MouseButton::LEFT:
if (rEvent.Modifiers == awt::KeyModifier::MOD2)
mxSlideShowController->gotoNextSlide();
else
mxSlideShowController->gotoNextEffect();
break;
case awt::MouseButton::RIGHT:
mxSlideShowController->gotoPreviousSlide();
break;
default:
// Other or multiple buttons.
break;
}
}
}
void PresenterController::RequestViews (
const bool bIsSlideSorterActive,
const bool bIsNotesViewActive,
const bool bIsHelpViewActive)
{
PresenterPaneContainer::PaneList::const_iterator iPane;
PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
{
bool bActivate (true);
const OUString sViewURL ((*iPane)->msViewURL);
if (sViewURL == PresenterViewFactory::msNotesViewURL)
{
bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
}
else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
{
bActivate = bIsSlideSorterActive;
}
else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
|| sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
{
bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
}
else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
{
bActivate = true;
}
else if (sViewURL == PresenterViewFactory::msHelpViewURL)
{
bActivate = bIsHelpViewActive;
}
if (bActivate)
ShowView(sViewURL);
else
HideView(sViewURL);
}
}
//----- XConfigurationChangeListener ------------------------------------------
void SAL_CALL PresenterController::notifyConfigurationChange (
const ConfigurationChangeEvent& rEvent)
throw (RuntimeException)
{
ThrowIfDisposed();
sal_Int32 nType (0);
if ( ! (rEvent.UserData >>= nType))
return;
switch (nType)
{
case ResourceActivationEventType:
if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
{
InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
}
else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
{
// A pane bound to the main pane has been created and is
// stored in the pane container.
Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
if (xPane.is())
{
PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
mpPaneContainer->FindPaneId(xPane->getResourceId()));
// When there is a call out anchor location set then tell the
// window about it.
if (pDescriptor->mbHasCalloutAnchor)
pDescriptor->mxPane->SetCalloutAnchor(
pDescriptor->maCalloutAnchorLocation);
}
}
else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
{
// A view bound to one of the panes has been created and is
// stored in the pane container along with its pane.
Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
if (xView.is())
{
SharedBitmapDescriptor pViewBackground(
GetViewBackground(xView->getResourceId()->getResourceURL()));
mpPaneContainer->StoreView(xView, pViewBackground);
UpdateViews();
mpWindowManager->NotifyViewCreation(xView);
}
}
break;
case ResourceDeactivationEventType:
if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
{
// If this is a view then remove it from the pane container.
Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
if (xView.is())
{
PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
mpPaneContainer->RemoveView(xView));
// A possibly opaque view has been removed. Update()
// updates the clip polygon.
mpWindowManager->Update();
// Request the repainting of the area previously
// occupied by the view.
if (pDescriptor.get() != NULL)
GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
}
}
break;
case ConfigurationUpdateEndEventType:
if (IsAccessibilityActive())
{
mpAccessibleObject->UpdateAccessibilityHierarchy();
UpdateCurrentSlide(0);
}
break;
}
}
//----- XEventListener --------------------------------------------------------
void SAL_CALL PresenterController::disposing (
const lang::EventObject& rEvent)
throw (RuntimeException)
{
if (rEvent.Source == mxController)
mxController = NULL;
else if (rEvent.Source == mxConfigurationController)
mxConfigurationController = NULL;
else if (rEvent.Source == mxSlideShowController)
mxSlideShowController = NULL;
else if (rEvent.Source == mxMainWindow)
mxMainWindow = NULL;
}
//----- XFrameActionListener --------------------------------------------------
void SAL_CALL PresenterController::frameAction (
const frame::FrameActionEvent& rEvent)
throw (RuntimeException)
{
if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
{
if (mxSlideShowController.is())
mxSlideShowController->activate();
}
}
//----- XKeyListener ----------------------------------------------------------
void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
throw (RuntimeException)
{
// Tell all views about the unhandled key event.
PresenterPaneContainer::PaneList::const_iterator iPane;
for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
{
if ( ! (*iPane)->mbIsActive)
continue;
Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
if (xKeyListener.is())
xKeyListener->keyPressed(rEvent);
}
}
void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
throw (RuntimeException)
{
if (rEvent.Source != mxMainWindow)
return;
switch (rEvent.KeyCode)
{
case awt::Key::ESCAPE:
case awt::Key::SUBTRACT:
{
if( mxController.is() )
{
Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
if( xPS.is() )
{
Reference< XPresentation > xP( xPS->getPresentation() );
if( xP.is() )
xP->end();
}
}
}
break;
case awt::Key::PAGEDOWN:
if (mxSlideShowController.is())
{
if (rEvent.Modifiers == awt::KeyModifier::MOD2)
mxSlideShowController->gotoNextSlide();
else
mxSlideShowController->gotoNextEffect();
}
break;
case awt::Key::RIGHT:
case awt::Key::SPACE:
case awt::Key::DOWN:
case awt::Key::N:
if (mxSlideShowController.is())
{
mxSlideShowController->gotoNextEffect();
}
break;
case awt::Key::LEFT:
case awt::Key::PAGEUP:
if (mxSlideShowController.is())
{
if (rEvent.Modifiers == awt::KeyModifier::MOD2)
mxSlideShowController->gotoPreviousSlide();
else
mxSlideShowController->gotoPreviousEffect();
}
break;
case awt::Key::UP:
case awt::Key::P:
case awt::Key::BACKSPACE:
if (mxSlideShowController.is())
{
mxSlideShowController->gotoPreviousEffect();
}
break;
case awt::Key::HOME:
if (mxSlideShowController.is())
{
mxSlideShowController->gotoFirstSlide();
}
break;
case awt::Key::END:
if (mxSlideShowController.is())
{
mxSlideShowController->gotoLastSlide();
}
break;
case awt::Key::W:
case awt::Key::COMMA:
if (mxSlideShowController.is())
{
if (mxSlideShowController->isPaused())
mxSlideShowController->resume();
else
mxSlideShowController->blankScreen(0x00ffffff);
}
break;
case awt::Key::B:
case awt::Key::POINT:
if (mxSlideShowController.is())
{
if (mxSlideShowController->isPaused())
mxSlideShowController->resume();
else
mxSlideShowController->blankScreen(0x00000000);
}
break;
case awt::Key::NUM0:
case awt::Key::NUM1:
case awt::Key::NUM2:
case awt::Key::NUM3:
case awt::Key::NUM4:
case awt::Key::NUM5:
case awt::Key::NUM6:
case awt::Key::NUM7:
case awt::Key::NUM8:
case awt::Key::NUM9:
HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
break;
case awt::Key::RETURN:
if (mnPendingSlideNumber > 0)
{
if (mxSlideShowController.is())
mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
mnPendingSlideNumber = -1;
}
else
{
if (mxSlideShowController.is())
mxSlideShowController->gotoNextEffect();
}
break;
case awt::Key::F1:
// Toggle the help view.
if (mpWindowManager.get() != NULL)
{
if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
else
mpWindowManager->SetHelpViewState(false);
}
break;
default:
// Tell all views about the unhandled key event.
PresenterPaneContainer::PaneList::const_iterator iPane;
for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
{
if ( ! (*iPane)->mbIsActive)
continue;
Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
if (xKeyListener.is())
xKeyListener->keyReleased(rEvent);
}
break;
}
}
void PresenterController::HandleNumericKeyPress (
const sal_Int32 nKey,
const sal_Int32 nModifiers)
{
switch (nModifiers)
{
case 0:
if (mnPendingSlideNumber == -1)
mnPendingSlideNumber = 0;
UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
break;
case awt::KeyModifier::MOD1:
// Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
// (slide view, notes view, normal)
mnPendingSlideNumber = -1;
if (mpWindowManager.get() == NULL)
return;
switch(nKey)
{
case 1:
mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
break;
case 2:
mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
break;
case 3:
mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
break;
default:
// Ignore unsupported key.
break;
}
default:
// Ignore unsupported modifiers.
break;
}
}
//----- XFocusListener --------------------------------------------------------
void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
//----- XMouseListener --------------------------------------------------------
void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
if (mxMainWindow.is())
mxMainWindow->setFocus();
}
void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
//----- XMouseMotionListener --------------------------------------------------
void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
(void)rEvent;
}
//-----------------------------------------------------------------------------
void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
{
if ( ! rxPane.is())
return;
mpAccessibleObject = new PresenterAccessible(
mxComponentContext,
this,
rxPane);
LoadTheme(rxPane);
// Main pane has been created and is now observed by the window
// manager.
mpWindowManager->SetParentPane(rxPane);
mpWindowManager->SetTheme(mpTheme);
if (mpPaneBorderPainter.get() != NULL)
mpPaneBorderPainter->SetTheme(mpTheme);
// Add key listener
mxMainWindow = rxPane->getWindow();
if (mxMainWindow.is())
{
mxMainWindow->addKeyListener(this);
mxMainWindow->addFocusListener(this);
mxMainWindow->addMouseListener(this);
mxMainWindow->addMouseMotionListener(this);
}
Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
if (xPane2.is())
xPane2->setVisible(sal_True);
mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer));
mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY);
if (mxSlideShowController.is())
mxSlideShowController->activate();
UpdateCurrentSlide(0);
}
void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
{
// Create (load) the current theme.
if (rxPane.is())
mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas()));
}
double PresenterController::GetSlideAspectRatio (void) const
{
double nSlideAspectRatio (28.0/21.0);
try
{
if (mxController.is())
{
Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
mxController->getModel(), UNO_QUERY_THROW);
Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
if (xSlides.is() && xSlides->getCount()>0)
{
Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
sal_Int32 nWidth (28000);
sal_Int32 nHeight (21000);
if ((xProperties->getPropertyValue(OUString::createFromAscii("Width")) >>= nWidth)
&& (xProperties->getPropertyValue(OUString::createFromAscii("Height")) >>= nHeight)
&& nHeight > 0)
{
nSlideAspectRatio = double(nWidth) / double(nHeight);
}
}
}
}
catch (RuntimeException&)
{
OSL_ASSERT(false);
}
return nSlideAspectRatio;
}
void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
{
mnPendingSlideNumber = nPendingSlideNumber;
if (mpTheme.get() == NULL)
return;
if ( ! mxMainWindow.is())
return;
PresenterTheme::SharedFontDescriptor pFont (
mpTheme->GetFont(A2S("PendingSlideNumberFont")));
if (pFont.get() == NULL)
return;
pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
if ( ! pFont->mxFont.is())
return;
const OUString sText (OUString::valueOf(mnPendingSlideNumber));
rendering::StringContext aContext (sText, 0, sText.getLength());
Reference<rendering::XTextLayout> xLayout (
pFont->mxFont->createTextLayout(
aContext,
rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
0));
}
void PresenterController::ThrowIfDisposed (void) const
throw (::com::sun::star::lang::DisposedException)
{
if (rBHelper.bDisposed || rBHelper.bInDispose)
{
throw lang::DisposedException (
OUString(RTL_CONSTASCII_USTRINGPARAM(
"PresenterController object has already been disposed")),
const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
}
}
} } // end of namespace ::sdext::presenter