/**************************************************************
 *
 * 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
