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

#undef ENABLE_PANE_RESIZING
//#define ENABLE_PANE_RESIZING

#include "PresenterWindowManager.hxx"
#include "PresenterAnimation.hxx"
#include "PresenterAnimator.hxx"
#include "PresenterController.hxx"
#include "PresenterGeometryHelper.hxx"
#include "PresenterHelper.hxx"
#include "PresenterPaintManager.hxx"
#include "PresenterPaneBase.hxx"
#include "PresenterPaneBorderManager.hxx"
#include "PresenterPaneBorderPainter.hxx"
#include "PresenterPaneContainer.hxx"
#include "PresenterPaneFactory.hxx"
#include "PresenterSprite.hxx"
#include "PresenterToolBar.hxx"
#include "PresenterViewFactory.hxx"
#include "PresenterTheme.hxx"
#include <com/sun/star/awt/InvalidateStyle.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/SystemPointer.hpp>
#include <com/sun/star/awt/XDevice.hpp>
#include <com/sun/star/awt/XWindow2.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/awt/WindowAttribute.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/FillRule.hpp>
#include <com/sun/star/rendering/PathCapType.hpp>
#include <com/sun/star/rendering/PathJoinType.hpp>
#include <com/sun/star/rendering/Texture.hpp>
#include <com/sun/star/rendering/TexturingMode.hpp>
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <math.h>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;

#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))

namespace sdext { namespace presenter {

namespace {

    typedef ::cppu::WeakComponentImplHelper1<
        css::drawing::framework::XConfigurationChangeListener
        > ModeChangeAnimationStarterInterfaceBase;

    class ModeChangeAnimationStarter
        : protected ::cppu::BaseMutex,
          public ModeChangeAnimationStarterInterfaceBase
    {
    public:
        ModeChangeAnimationStarter (
            const Reference<drawing::framework::XConfigurationController>& rxConfigurationController,
            const Reference<awt::XWindow>& rxWindow,
            const Reference<rendering::XSpriteCanvas>& rxCanvas,
            const ::boost::shared_ptr<PresenterAnimator>& rpAnimator);
        virtual ~ModeChangeAnimationStarter (void);
        virtual void SAL_CALL disposing (void);
        
        // XConfigurationChangeListener
        
        virtual void SAL_CALL notifyConfigurationChange (
            const com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent)
            throw (com::sun::star::uno::RuntimeException);


        // XEventListener

        virtual void SAL_CALL disposing (
            const com::sun::star::lang::EventObject& rEvent)
            throw (com::sun::star::uno::RuntimeException);

    private:
        Reference<drawing::framework::XConfigurationController> mxConfigurationController;
        ::boost::shared_ptr<PresenterAnimator> mpAnimator;
        ::boost::shared_ptr<PresenterSprite> mpSprite;
        Reference<rendering::XSpriteCanvas> mxCanvas;
    };

}




//===== PresenterWindowManager ================================================

PresenterWindowManager::PresenterWindowManager (
    const Reference<XComponentContext>& rxContext,
    const ::rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
    const ::rtl::Reference<PresenterController>& rpPresenterController)
    : PresenterWindowManagerInterfaceBase(m_aMutex),
      mxComponentContext(rxContext),
      mpPresenterController(rpPresenterController),
      mxParentWindow(),
      mxParentCanvas(),
      mxPaneBorderManager(),
      mpPaneBorderPainter(),
      mpPaneContainer(rpPaneContainer),
      mbIsLayoutPending(true),
      mbIsLayouting(false),
      mpTheme(),
      mpBackgroundBitmap(),
      mxScaledBackgroundBitmap(),
      maPaneBackgroundColor(),
      mxClipPolygon(),
      meLayoutMode(LM_Generic),
      mbIsSlideSorterActive(false),
      mbIsHelpViewActive(false),
      maLayoutListeners(),
      mbIsMouseClickPending(false)
{
    UpdateWindowList();
}




PresenterWindowManager::~PresenterWindowManager (void)
{
}




void SAL_CALL PresenterWindowManager::disposing (void)
{
    NotifyDisposing();

    SetParentPane(NULL);

    Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY);
    if (xComponent.is())
        xComponent->dispose();
    mxPaneBorderManager = NULL;

    PresenterPaneContainer::PaneList::const_iterator iPane;
    PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
    for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        if ((*iPane)->mxBorderWindow.is())
        {
            (*iPane)->mxBorderWindow->removeWindowListener(this);
            (*iPane)->mxBorderWindow->removeFocusListener(this);
#ifndef ENABLE_PANE_RESIZING
            (*iPane)->mxBorderWindow->removeMouseListener(this);
#endif
        }
    }
}




void PresenterWindowManager::SetParentPane (
    const Reference<drawing::framework::XPane>& rxPane)
{
    if (mxParentWindow.is())
    {
        mxParentWindow->removeWindowListener(this);
        mxParentWindow->removePaintListener(this);
        mxParentWindow->removeMouseListener(this);
        mxParentWindow->removeFocusListener(this);
    }
    mxParentWindow = NULL;
    mxParentCanvas = NULL;
    
    if (rxPane.is())
    {
        mxParentWindow = rxPane->getWindow();
        mxParentCanvas = rxPane->getCanvas();
    }
    else
    {
        mxParentWindow = NULL;
    }

    if (mxParentWindow.is())
    {
        mxParentWindow->addWindowListener(this);
        mxParentWindow->addPaintListener(this);
        mxParentWindow->addMouseListener(this);
        mxParentWindow->addFocusListener(this);

        // We paint our own background, make that of the parent window transparent.
        Reference<awt::XWindowPeer> xPeer (mxParentWindow, UNO_QUERY);
        if (xPeer.is())
            xPeer->setBackground(util::Color(0xff000000));
    }
} 




void PresenterWindowManager::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme)
{
    mpTheme = rpTheme;

    // Get background bitmap or background color from the theme.
    
    if (mpTheme.get() != NULL)
    {
        mpBackgroundBitmap = mpTheme->GetBitmap(OUString(), A2S("Background"));
    }
}




void PresenterWindowManager::NotifyPaneCreation (
    const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor)
{
    if (rpDescriptor.get()==NULL)
    {
        OSL_ASSERT(rpDescriptor.get()!=NULL);
        return;
    }
    if ( ! rpDescriptor->mxContentWindow.is())
    {
        OSL_ASSERT(rpDescriptor->mxContentWindow.is());
        return;
    }

    mbIsLayoutPending = true;

    Reference<awt::XWindow> xBorderWindow (rpDescriptor->mxBorderWindow);
    OSL_ASSERT(xBorderWindow.is());
    if (xBorderWindow.is() && ! rpDescriptor->mbIsSprite)
    {
        Invalidate();
        
        xBorderWindow->addWindowListener(this);
        xBorderWindow->addFocusListener(this);
#ifndef ENABLE_PANE_RESIZING
        xBorderWindow->addMouseListener(this);
#endif
    }

    UpdateWindowList();
    Layout();
}




void PresenterWindowManager::NotifyViewCreation (const Reference<XView>& rxView)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(rxView->getResourceId()->getAnchor()));
    OSL_ASSERT(pDescriptor.get() != NULL);
    if (pDescriptor.get() != NULL)
    {
        Layout();
        
        mpPresenterController->GetPaintManager()->Invalidate(
            pDescriptor->mxContentWindow,
            (sal_Int16)(awt::InvalidateStyle::TRANSPARENT
            | awt::InvalidateStyle::CHILDREN));
    }
}




void PresenterWindowManager::SetPanePosSizeRelative (
    const Reference<XResourceId>& rxPaneId,
    const double nRelativeX,
    const double nRelativeY,
    const double nRelativeWidth,
    const double nRelativeHeight)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL)
    {
        pDescriptor->mnLeft = nRelativeX;
        pDescriptor->mnTop = nRelativeY;
        pDescriptor->mnRight = nRelativeX + nRelativeWidth;
        pDescriptor->mnBottom = nRelativeY + nRelativeHeight;

        mpPaneContainer->ToTop(pDescriptor);
    }
}




void PresenterWindowManager::SetPanePosSizeAbsolute (
    const OUString& rsPaneURL,
    const double nX,
    const double nY,
    const double nWidth,
    const double nHeight)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneURL(rsPaneURL));
    if (pDescriptor.get() != NULL)
    {
        awt::Rectangle aParentBox = mxParentWindow->getPosSize();
        if (aParentBox.Width > 0 && aParentBox.Height > 0)
        {
            pDescriptor->mnLeft = nX / aParentBox.Width;
            pDescriptor->mnTop = nY / aParentBox.Height;
            pDescriptor->mnRight = (nX + nWidth) / aParentBox.Width;
            pDescriptor->mnBottom = (nY + nHeight) / aParentBox.Height;
        }
        if (pDescriptor->mxBorderWindow.is())
            pDescriptor->mxBorderWindow->setPosSize(
                ::sal::static_int_cast<sal_Int32>(nX),
                ::sal::static_int_cast<sal_Int32>(nY),
                ::sal::static_int_cast<sal_Int32>(nWidth),
                ::sal::static_int_cast<sal_Int32>(nHeight),
                awt::PosSize::POSSIZE);
    }
}




void PresenterWindowManager::SetPaneBorderPainter (
    const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter)
{
    mpPaneBorderPainter = rPainter;
}




//----- XWindowListener -------------------------------------------------------
    
void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent)
    throw (RuntimeException)
{
    ThrowIfDisposed();
    if (rEvent.Source == mxParentWindow)
    {
        Layout();
    }
    else
    {
        Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
        if (xWindow.is())
        {
            UpdateWindowSize(xWindow);

            // Make sure the background of a transparent window is painted.
            mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
        }
    }
}




void SAL_CALL PresenterWindowManager::windowMoved (const awt::WindowEvent& rEvent)
    throw (RuntimeException)
{
    ThrowIfDisposed();
    if (rEvent.Source != mxParentWindow)
    {
        Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
        UpdateWindowSize(xWindow);

        // Make sure the background of a transparent window is painted.
        mpPresenterController->GetPaintManager()->Invalidate(xWindow);
    }
}




void SAL_CALL PresenterWindowManager::windowShown (const lang::EventObject& rEvent)
    throw (RuntimeException)
{
    (void)rEvent;
}




void SAL_CALL PresenterWindowManager::windowHidden (const lang::EventObject& rEvent)
    throw (RuntimeException)
{
    (void)rEvent;
}




//----- XPaintListener --------------------------------------------------------
    
void SAL_CALL PresenterWindowManager::windowPaint (const awt::PaintEvent& rEvent)
    throw (RuntimeException)
{
    ThrowIfDisposed();

    if ( ! mxParentWindow.is())
        return;
    if ( ! mxParentCanvas.is())
        return;

    if (mpTheme.get()!=NULL)
    {
        try
        {
            if (mbIsLayoutPending)
                Layout();
            PaintBackground(rEvent.UpdateRect);
            if ( ! PaintChildren(rEvent))
            {
                Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxParentCanvas, UNO_QUERY);
                //                if (xSpriteCanvas.is())
                //                    xSpriteCanvas->updateScreen(sal_False);
            }
        }
        catch (RuntimeException&)
        {
            OSL_ASSERT(sal_False);
        }
    }
}




//----- XMouseListener --------------------------------------------------------

void SAL_CALL PresenterWindowManager::mousePressed (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
    mbIsMouseClickPending = true;
}




void SAL_CALL PresenterWindowManager::mouseReleased (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
#ifndef ENABLE_PANE_RESIZING
    if (mbIsMouseClickPending)
    {
        mbIsMouseClickPending = false;
        mpPresenterController->HandleMouseClick(rEvent);
    }
#else
    (void)rEvent;
#endif
}




void SAL_CALL PresenterWindowManager::mouseEntered (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
    mbIsMouseClickPending = false;
}




void SAL_CALL PresenterWindowManager::mouseExited (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
    mbIsMouseClickPending = false;
}




//----- XFocusListener --------------------------------------------------------

void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& rEvent)
    throw (css::uno::RuntimeException)
{
    ThrowIfDisposed();
    (void)rEvent;
    OSL_TRACE("PresenterWindowManager::focusGained window %x\n",
        rEvent.Source.get());
}




void SAL_CALL PresenterWindowManager::focusLost (const css::awt::FocusEvent& rEvent)
    throw (css::uno::RuntimeException)
{
    ThrowIfDisposed();
    (void)rEvent;
}




//----- XEventListener --------------------------------------------------------

void SAL_CALL PresenterWindowManager::disposing (const lang::EventObject& rEvent)
    throw (RuntimeException)
{
    if (rEvent.Source == mxParentWindow)
        mxParentWindow = NULL;
    else
    {
        Reference<awt::XWindow> xWindow (rEvent.Source, UNO_QUERY);
    }
}




//-----------------------------------------------------------------------------

bool PresenterWindowManager::PaintChildren (const awt::PaintEvent& rEvent) const
{
    bool bChildInvalidated (false);
    
    // Call windowPaint on all children that lie in or touch the
    // update rectangle.
    PresenterPaneContainer::PaneList::const_iterator iPane;
    PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
    for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        try
        {
            // Make sure that the pane shall and can be painted.
            if ( ! (*iPane)->mbIsActive)
                continue;
            if ((*iPane)->mbIsSprite)
                continue;
            if ( ! (*iPane)->mxPane.is())
                continue;
            if ( ! (*iPane)->mxBorderWindow.is())
                continue;
            Reference<awt::XWindow> xBorderWindow ((*iPane)->mxBorderWindow);
            if ( ! xBorderWindow.is())
                continue;

            // Get the area in which the border of the pane has to be painted.
            const awt::Rectangle aBorderBox (xBorderWindow->getPosSize());
            const awt::Rectangle aBorderUpdateBox(
                PresenterGeometryHelper::Intersection(
                    rEvent.UpdateRect,
                    aBorderBox));
            if (aBorderUpdateBox.Width<=0 || aBorderUpdateBox.Height<=0)
                continue;

            const awt::Rectangle aLocalBorderUpdateBox(
                PresenterGeometryHelper::TranslateRectangle(
                    aBorderUpdateBox,
                    -aBorderBox.X,
                    -aBorderBox.Y));

            // Invalidate the area of the content window.
            mpPresenterController->GetPaintManager()->Invalidate(
                xBorderWindow,
                aLocalBorderUpdateBox,
                sal_Int16(awt::InvalidateStyle::CHILDREN
                    | awt::InvalidateStyle::NOTRANSPARENT));
        }
        catch (RuntimeException&)
        {
            OSL_ASSERT(sal_False);
        }
    }

    return bChildInvalidated;
}




void PresenterWindowManager::SetLayoutMode (const LayoutMode eMode)
{
    OSL_ASSERT(mpPresenterController.get() != NULL);
    
    if (meLayoutMode != eMode
        || mbIsSlideSorterActive
        || mbIsHelpViewActive)
    {
        meLayoutMode = eMode;
        mbIsSlideSorterActive = false;
        mbIsHelpViewActive = false;

        mpPresenterController->RequestViews(
            mbIsSlideSorterActive,
            meLayoutMode==LM_Notes,
            mbIsHelpViewActive);
        Layout();
        NotifyLayoutModeChange();
    }
}




PresenterWindowManager::LayoutMode PresenterWindowManager::GetLayoutMode (void) const
{
    return meLayoutMode;
}




void PresenterWindowManager::SetSlideSorterState (bool bIsActive)
{
    if (mbIsSlideSorterActive != bIsActive)
    {
        mbIsSlideSorterActive = bIsActive;
        if (mbIsSlideSorterActive)
            mbIsHelpViewActive = false;
        StoreViewMode(GetViewMode());

        mpPresenterController->RequestViews(
            mbIsSlideSorterActive,
            meLayoutMode==LM_Notes,
            mbIsHelpViewActive);
        Layout();
        NotifyLayoutModeChange();
    }
}




bool PresenterWindowManager::IsSlideSorterActive (void) const
{
    return mbIsSlideSorterActive;
}




void PresenterWindowManager::SetHelpViewState (bool bIsActive)
{
    if (mbIsHelpViewActive != bIsActive)
    {
        mbIsHelpViewActive = bIsActive;
        if (mbIsHelpViewActive)
            mbIsSlideSorterActive = false;
        StoreViewMode(GetViewMode());

        mpPresenterController->RequestViews(
            mbIsSlideSorterActive,
            meLayoutMode==LM_Notes,
            mbIsHelpViewActive);
        Layout();
        NotifyLayoutModeChange();
    }
}




bool PresenterWindowManager::IsHelpViewActive (void) const
{
    return mbIsHelpViewActive;
}




void PresenterWindowManager::SetViewMode (const ViewMode eMode)
{
    switch (eMode)
    {
        case VM_Standard:
            SetSlideSorterState(false);
            SetHelpViewState(false);
            SetLayoutMode(LM_Standard);
            break;

        case VM_Notes:
            SetSlideSorterState(false);
            SetHelpViewState(false);
            SetLayoutMode(LM_Notes);
            break;

        case VM_SlideOverview:
            SetHelpViewState(false);
            SetSlideSorterState(true);
            break;

        case VM_Help:
            SetHelpViewState(true);
            SetSlideSorterState(false);
            break;
    }

    StoreViewMode(eMode);
}




PresenterWindowManager::ViewMode PresenterWindowManager::GetViewMode (void) const
{
    if (mbIsHelpViewActive)
        return VM_Help;
    else if (mbIsSlideSorterActive)
        return VM_SlideOverview;
    else if (meLayoutMode == LM_Notes)
        return VM_Notes;
    else
        return VM_Standard;
}




void PresenterWindowManager::RestoreViewMode (void)
{
    sal_Int32 nMode (0);
    PresenterConfigurationAccess aConfiguration (
        mxComponentContext,
        OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
        PresenterConfigurationAccess::READ_ONLY);
    aConfiguration.GetConfigurationNode(A2S("Presenter/InitialViewMode")) >>= nMode;
    switch (nMode)
    {
        default:
        case 0:
            SetViewMode(VM_Standard);
            break;
            
        case 1:
            SetViewMode(VM_Notes);
            break;
            
        case 2:
            SetViewMode(VM_SlideOverview);
            break;
    }                               
}




void PresenterWindowManager::StoreViewMode (const ViewMode eViewMode)
{
    try
    {
        PresenterConfigurationAccess aConfiguration (
            mxComponentContext,
            OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
            PresenterConfigurationAccess::READ_WRITE);
        aConfiguration.GoToChild(A2S("Presenter"));
        Any aValue;
        switch (eViewMode)
        {
            default:
            case VM_Standard:
                aValue = Any(sal_Int32(0));
                break;

            case VM_Notes:
                aValue = Any(sal_Int32(1));
                break;

            case VM_SlideOverview:
                aValue = Any(sal_Int32(2));
                break;
        }

        aConfiguration.SetProperty (A2S("InitialViewMode"), aValue);
        aConfiguration.CommitChanges();
    }
    catch (Exception&)
    {
    }
}




void PresenterWindowManager::AddLayoutListener (
    const Reference<document::XEventListener>& rxListener)
{
    maLayoutListeners.push_back(rxListener);
}




void PresenterWindowManager::RemoveLayoutListener (
    const Reference<document::XEventListener>& rxListener)
{
    LayoutListenerContainer::iterator iListener (maLayoutListeners.begin());
    LayoutListenerContainer::iterator iEnd (maLayoutListeners.end());
    for ( ; iListener!=iEnd; ++iListener)
    {
        if (*iListener == rxListener)
        {
            maLayoutListeners.erase(iListener);
            // Assume that there are no multiple entries.
            break;
        }
    }
}




void PresenterWindowManager::Layout (void)
{
    if (mxParentWindow.is() && ! mbIsLayouting)
    {
        mbIsLayoutPending = false;
        mbIsLayouting = true;
        mxScaledBackgroundBitmap = NULL;
        mxClipPolygon = NULL;

        try
        {
            if (mbIsSlideSorterActive)
                LayoutSlideSorterMode();
            else if (mbIsHelpViewActive)
                LayoutHelpMode();
            else
                switch (meLayoutMode)
                {
                    case LM_Standard:
                    default:
                        LayoutStandardMode();
                        break;
                    
                    case LM_Notes:
                        LayoutNotesMode();
                        break;
                }
        }
        catch (Exception&)
        {
            OSL_ASSERT(false);
            throw;
        }

        mbIsLayouting = false;
    }
}




void PresenterWindowManager::LayoutStandardMode (void)
{
    awt::Rectangle aBox = mxParentWindow->getPosSize();

    const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
    const double nGap (20);
    const double nHorizontalSlideDivide (aBox.Width / nGoldenRatio);
    double nSlidePreviewTop (0);

    // For the current slide view calculate the outer height from the outer
    // width.  This takes into acount the slide aspect ratio and thus has to
    // go over the inner pane size.
    PresenterPaneContainer::SharedPaneDescriptor pPane (
        mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
    if (pPane.get() != NULL)
    {
        const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
            nHorizontalSlideDivide - 1.5*nGap,
            PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
        nSlidePreviewTop = (aBox.Height - aCurrentSlideOuterBox.Height) / 2;
        SetPanePosSizeAbsolute (
            PresenterPaneFactory::msCurrentSlidePreviewPaneURL,
            nGap,
            nSlidePreviewTop,
            aCurrentSlideOuterBox.Width,
            aCurrentSlideOuterBox.Height);
    }
    

    // For the next slide view calculate the outer height from the outer
    // width.  This takes into acount the slide aspect ratio and thus has to
    // go over the inner pane size.
    pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL);
    if (pPane.get() != NULL)
    {
        const awt::Size aNextSlideOuterBox (CalculatePaneSize(
            aBox.Width - nHorizontalSlideDivide - 1.5*nGap,
            PresenterPaneFactory::msNextSlidePreviewPaneURL));
        SetPanePosSizeAbsolute (
            PresenterPaneFactory::msNextSlidePreviewPaneURL,
            aBox.Width - aNextSlideOuterBox.Width - nGap,
            nSlidePreviewTop,
            aNextSlideOuterBox.Width,
            aNextSlideOuterBox.Height);
    }

    LayoutToolBar();
}




void PresenterWindowManager::LayoutNotesMode (void)
{
    awt::Rectangle aBox = mxParentWindow->getPosSize();

    const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
    
    const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
    const double nGap (20);
    const double nPrimaryWidth (aBox.Width / nGoldenRatio);
    const double nSecondaryWidth (aBox.Width - nPrimaryWidth);
    const double nTertiaryWidth (nSecondaryWidth / nGoldenRatio);
    double nSlidePreviewTop (0);
    double nNotesViewBottom (aToolBarBox.Y1 - nGap);
    
    // The notes view has no fixed aspect ratio.
    PresenterPaneContainer::SharedPaneDescriptor pPane (
        mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
    if (pPane.get() != NULL)
    {
        const geometry::RealSize2D aNotesViewOuterSize(
            nPrimaryWidth - 1.5*nGap + 0.5,
            nNotesViewBottom);
        nSlidePreviewTop = (aBox.Height
            - aToolBarBox.Y2 + aToolBarBox.Y1 - aNotesViewOuterSize.Height) / 2;
        SetPanePosSizeAbsolute (
            PresenterPaneFactory::msNotesPaneURL,
            aBox.Width - aNotesViewOuterSize.Width - nGap,
            nSlidePreviewTop,
            aNotesViewOuterSize.Width,
            aNotesViewOuterSize.Height);
        nNotesViewBottom = nSlidePreviewTop + aNotesViewOuterSize.Height;
    }
    
    // For the current slide view calculate the outer height from the outer
    // width.  This takes into acount the slide aspect ratio and thus has to
    // go over the inner pane size.
    pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
    if (pPane.get() != NULL)
    {
        const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
            nSecondaryWidth - 1.5*nGap,
            PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
        SetPanePosSizeAbsolute (
            PresenterPaneFactory::msCurrentSlidePreviewPaneURL,
            nGap,
            nSlidePreviewTop,
            aCurrentSlideOuterBox.Width,
            aCurrentSlideOuterBox.Height);
    }
    

    // For the next slide view calculate the outer height from the outer
    // width.  This takes into acount the slide aspect ratio and thus has to
    // go over the inner pane size.
    pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL);
    if (pPane.get() != NULL)
    {
        const awt::Size aNextSlideOuterBox (CalculatePaneSize(
            nTertiaryWidth,
            PresenterPaneFactory::msNextSlidePreviewPaneURL));
        SetPanePosSizeAbsolute (
            PresenterPaneFactory::msNextSlidePreviewPaneURL,
            nGap,
            nNotesViewBottom - aNextSlideOuterBox.Height,
            aNextSlideOuterBox.Width,
            aNextSlideOuterBox.Height);
    }
}




void PresenterWindowManager::LayoutSlideSorterMode (void)
{
    const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());

    awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
    const double nGap (20);
    SetPanePosSizeAbsolute(
        mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msSlideSorterURL),
        nGap,
        nGap,
        aWindowBox.Width - 2*nGap,
        aToolBarBox.Y1 - 2*nGap);
}




void PresenterWindowManager::LayoutHelpMode (void)
{
    const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());

    awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
    const double nGap (20);
    const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
    const double nWidth = ::std::min(aWindowBox.Width - 2*nGap, aWindowBox.Width/nGoldenRatio);
    SetPanePosSizeAbsolute(
        mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msHelpViewURL),
        (aWindowBox.Width - nWidth)/2,
        nGap,
        nWidth,
        aToolBarBox.Y1 - 2*nGap);
}




geometry::RealRectangle2D PresenterWindowManager::LayoutToolBar (void)
{
    double nToolBarWidth (400);
    double nToolBarHeight (80);

    // Get access to the tool bar.
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
        mpPaneContainer->FindPaneURL(PresenterPaneFactory::msToolBarPaneURL));
    if (pDescriptor.get() != NULL)
    {
        PresenterToolBarView* pToolBarView
            = dynamic_cast<PresenterToolBarView*>(pDescriptor->mxView.get());
        if (pToolBarView != NULL && pToolBarView->GetPresenterToolBar().is())
        {
            geometry::RealSize2D aSize (pToolBarView->GetPresenterToolBar()->GetMinimalSize());

            if (mpPaneBorderPainter.is())
            {
                const awt::Rectangle aBox (mpPaneBorderPainter->addBorder (
                    PresenterPaneFactory::msToolBarPaneURL,
                    awt::Rectangle(
                        0,
                        0,
                        PresenterGeometryHelper::Round(aSize.Width),
                        PresenterGeometryHelper::Round(aSize.Height)),
                    css::drawing::framework::BorderType_TOTAL_BORDER));

                nToolBarWidth = aBox.Width;
                nToolBarHeight = aBox.Height;
            }
            else
            {
                nToolBarWidth = aSize.Width + 20;
                nToolBarHeight = aSize.Height + 10;
            }
        }
    }

    const awt::Rectangle aBox = mxParentWindow->getPosSize();
    const double nToolBarX ((aBox.Width - nToolBarWidth) / 2);
    const double nToolBarY (aBox.Height - nToolBarHeight);
    SetPanePosSizeAbsolute(
        PresenterPaneFactory::msToolBarPaneURL,
        nToolBarX,
        nToolBarY,
        nToolBarWidth,
        nToolBarHeight);

    return geometry::RealRectangle2D(
        nToolBarX,
        nToolBarY,
        nToolBarX + nToolBarWidth - 1,
        nToolBarY + nToolBarHeight - 1);
}




awt::Size PresenterWindowManager::CalculatePaneSize (
    const double nOuterWidth,
    const OUString& rsPaneURL)
{
    // Calculate the inner width by removing the pane border.
    awt::Rectangle aInnerBox (mpPaneBorderPainter->RemoveBorder (
        rsPaneURL,
        awt::Rectangle(0,0,
            sal_Int32(nOuterWidth+0.5),sal_Int32(nOuterWidth)),
        drawing::framework::BorderType_TOTAL_BORDER));

    // Calculate the inner height with the help of the slide aspect ratio.
    const double nCurrentSlideInnerHeight (
        aInnerBox.Width / mpPresenterController->GetSlideAspectRatio());

    // Add the pane border to get the outer box.
    awt::Rectangle aOuterBox (mpPaneBorderPainter->AddBorder (
        rsPaneURL,
        awt::Rectangle(0,0,
            aInnerBox.Width,sal_Int32(nCurrentSlideInnerHeight+0.5)),
        drawing::framework::BorderType_TOTAL_BORDER));

    return awt::Size(aOuterBox.Width, aOuterBox.Height);
}




void PresenterWindowManager::NotifyLayoutModeChange (void)
{
    document::EventObject aEvent;
    aEvent.Source = Reference<XInterface>(static_cast<XWeak*>(this));

    LayoutListenerContainer aContainerCopy (maLayoutListeners);
    LayoutListenerContainer::iterator iListener (aContainerCopy.begin());
    LayoutListenerContainer::iterator iEnd (aContainerCopy.end());
    for ( ; iListener!=iEnd; ++iListener)
    {
        if (iListener->is())
        {
            try
            {
                (*iListener)->notifyEvent(aEvent);
            }
            catch (lang::DisposedException&)
            {
                RemoveLayoutListener(*iListener);
            }
            catch (RuntimeException&)
            {
            }
        }
    }    
}




void PresenterWindowManager::NotifyDisposing (void)
{
    lang::EventObject aEvent;
    aEvent.Source = static_cast<XWeak*>(this);

    LayoutListenerContainer aContainer;
    aContainer.swap(maLayoutListeners);
    LayoutListenerContainer::iterator iListener (aContainer.begin());
    LayoutListenerContainer::iterator iEnd (aContainer.end());
    for ( ; iListener!=iEnd; ++iListener)
    {
        if (iListener->is())
        {
            try
            {
                (*iListener)->disposing(aEvent);
            }
            catch (lang::DisposedException&)
            {
            }
            catch (RuntimeException&)
            {
            }
        }
    }    
}




void PresenterWindowManager::LayoutUnknownMode (void)
{
    awt::Rectangle aBox = mxParentWindow->getPosSize();
        
    PresenterPaneContainer::PaneList::const_iterator iPane;
    PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
    for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        const PresenterPaneContainer::SharedPaneDescriptor& pDescriptor (*iPane);
        if ( ! pDescriptor->mxBorderWindow.is())
            continue;

        // Layout the border window.
        const sal_Int32 nX = (sal_Int32)(pDescriptor->mnLeft * aBox.Width);
        const sal_Int32 nY = (sal_Int32)(pDescriptor->mnTop * aBox.Height);
        const sal_Int32 nWidth = (sal_Int32)(pDescriptor->mnRight * aBox.Width) - nX;
        const sal_Int32 nHeight = (sal_Int32)(pDescriptor->mnBottom * aBox.Height) - nY;

        pDescriptor->mxBorderWindow->setPosSize(
            nX,nY,nWidth,nHeight,
            awt::PosSize::POSSIZE);
    }
}




void PresenterWindowManager::UpdateWindowSize (const Reference<awt::XWindow>& rxBorderWindow)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindBorderWindow(rxBorderWindow));
    if (pDescriptor.get() != NULL)
    {
        mxClipPolygon = NULL;

        awt::Rectangle aParentBox = mxParentWindow->getPosSize();
        awt::Rectangle aBorderBox (pDescriptor->mxBorderWindow->getPosSize());

        if ( ! mbIsLayouting)
        {
            const double nWidth (aParentBox.Width);
            const double nHeight (aParentBox.Height);
            pDescriptor->mnLeft = double(aBorderBox.X) / nWidth;
            pDescriptor->mnTop = double(aBorderBox.Y) / nHeight;
            pDescriptor->mnRight = double(aBorderBox.X + aBorderBox.Width) / nWidth;
            pDescriptor->mnBottom = double(aBorderBox.Y + aBorderBox.Height) / nHeight;
        }
        else
        {
            // This update of the window size was initiated by
            // Layout(). Therefore the window size does not have to be
            // updated.
        }

        // ToTop is called last because it may invalidate the iterator.
        if ( ! mbIsLayouting)
            mpPaneContainer->ToTop(pDescriptor);
    }
}




void PresenterWindowManager::PaintBackground (const awt::Rectangle& rUpdateBox)
{
    (void)rUpdateBox;
    if ( ! mxParentWindow.is())
        return;

    Reference<rendering::XGraphicDevice> xDevice (mxParentCanvas->getDevice());
    if ( ! xDevice.is())
        return;
    
    // Create a polygon for the background and for clipping.
    Reference<rendering::XPolyPolygon2D> xBackgroundPolygon (
        PresenterGeometryHelper::CreatePolygon(mxParentWindow->getPosSize(), xDevice));
    if ( ! mxClipPolygon.is())
        mxClipPolygon = CreateClipPolyPolygon();

    // Create View- and RenderState structs.
    const rendering::ViewState aViewState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        PresenterGeometryHelper::CreatePolygon(rUpdateBox, xDevice));
    rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        mxClipPolygon,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);

    // Paint the background.
    if (mpBackgroundBitmap.get() != NULL)
    {
        ProvideBackgroundBitmap();
        
        if (mxScaledBackgroundBitmap.is())
        {
            Sequence<rendering::Texture> aTextures (1);
            const geometry::IntegerSize2D aBitmapSize(mxScaledBackgroundBitmap->getSize());
            aTextures[0] = rendering::Texture (
                geometry::AffineMatrix2D(
                    aBitmapSize.Width,0,0,
                    0,aBitmapSize.Height,0),
                1,
                0,
                mxScaledBackgroundBitmap,
                NULL,
                NULL,
                rendering::StrokeAttributes(),
                rendering::TexturingMode::REPEAT,
                rendering::TexturingMode::REPEAT);

            mxParentCanvas->fillTexturedPolyPolygon(
                xBackgroundPolygon,
                aViewState,
                aRenderState,
                aTextures);
        }
        else
        {
            const util::Color aBackgroundColor (mpBackgroundBitmap->maReplacementColor);
            aRenderState.DeviceColor[0] = ((aBackgroundColor >> 16) & 0x0ff) / 255.0;
            aRenderState.DeviceColor[1] = ((aBackgroundColor >> 8) & 0x0ff) / 255.0;
            aRenderState.DeviceColor[2] = ((aBackgroundColor >> 0) & 0x0ff) / 255.0;
            aRenderState.DeviceColor[3] = ((aBackgroundColor >> 24) & 0x0ff) / 255.0;
            mxParentCanvas->fillPolyPolygon(
                xBackgroundPolygon,
                aViewState,
                aRenderState);
        }
    }
}




void PresenterWindowManager::ProvideBackgroundBitmap (void)
{
    if ( ! mxScaledBackgroundBitmap.is())
    {
        Reference<rendering::XBitmap> xBitmap (mpBackgroundBitmap->GetNormalBitmap());
        if (xBitmap.is())
        {
            const bool bStretchVertical (mpBackgroundBitmap->meVerticalTexturingMode
                == PresenterBitmapDescriptor::Stretch);
            const bool bStretchHorizontal (mpBackgroundBitmap->meHorizontalTexturingMode
                == PresenterBitmapDescriptor::Stretch);
            if (bStretchHorizontal || bStretchVertical)
            {
                geometry::RealSize2D aSize;
                if (bStretchVertical)
                    aSize.Height = mxParentWindow->getPosSize().Height;
                else
                    aSize.Height = xBitmap->getSize().Height;
                if (bStretchHorizontal)
                    aSize.Width = mxParentWindow->getPosSize().Width;
                else
                    aSize.Width = xBitmap->getSize().Width;
                mxScaledBackgroundBitmap = xBitmap->getScaledBitmap(aSize, sal_False);
            }
            else
            {
                mxScaledBackgroundBitmap
                    = Reference<rendering::XBitmap>(xBitmap, UNO_QUERY);
            }
        }
    }
}




Reference<rendering::XPolyPolygon2D> PresenterWindowManager::CreateClipPolyPolygon (void) const
{
    // Create a clip polygon that includes the whole update area but has the
    // content windows as holes.
    const sal_Int32 nPaneCount (mpPaneContainer->maPanes.size());
    ::std::vector<awt::Rectangle> aRectangles;
    aRectangles.reserve(1+nPaneCount);
    aRectangles.push_back(mxParentWindow->getPosSize());
    PresenterPaneContainer::PaneList::const_iterator iPane;
    PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
    for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        PresenterPaneContainer::SharedPaneDescriptor pDescriptor (*iPane);
        if ( ! pDescriptor->mbIsActive)
            continue;
        if ( ! pDescriptor->mbIsOpaque)
            continue;
        if ( ! pDescriptor->mxBorderWindow.is() || ! pDescriptor->mxContentWindow.is())
            continue;
        Reference<awt::XWindow2> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY);
        if (xWindow.is() && ! xWindow->isVisible())
            continue;

        const awt::Rectangle aOuterBorderBox (pDescriptor->mxBorderWindow->getPosSize());
        awt::Rectangle aInnerBorderBox (pDescriptor->mxContentWindow->getPosSize());
        aInnerBorderBox.X += aOuterBorderBox.X;
        aInnerBorderBox.Y += aOuterBorderBox.Y;
        aRectangles.push_back(aInnerBorderBox);
    }
    Reference<rendering::XPolyPolygon2D> xPolyPolygon (
        PresenterGeometryHelper::CreatePolygon(
            aRectangles,
            mxParentCanvas->getDevice()));
    if (xPolyPolygon.is())
        xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD);
    return xPolyPolygon;
}




void PresenterWindowManager::UpdateWindowList (void)
{
#ifdef ENABLE_PANE_RESIZING
    try
    {
        OSL_ASSERT(mxComponentContext.is());

        Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY);
        if (xComponent.is())
            xComponent->dispose();
        
        Reference<lang::XMultiComponentFactory> xFactory (mxComponentContext->getServiceManager());
        if (xFactory.is())
        {
            Sequence<Any> aArguments (1 + mpPaneContainer->maPanes.size()*2);
            sal_Int32 nIndex (0);
            aArguments[nIndex++] = Any(mxParentWindow);
            for (sal_uInt32 nPaneIndex=0; nPaneIndex<mpPaneContainer->maPanes.size(); ++nPaneIndex)
            {
                if ( ! mpPaneContainer->maPanes[nPaneIndex]->mbIsActive)
                    continue;

                const Reference<awt::XWindow> xBorderWindow (
                    mpPaneContainer->maPanes[nPaneIndex]->mxBorderWindow);
                const Reference<awt::XWindow> xContentWindow (
                    mpPaneContainer->maPanes[nPaneIndex]->mxContentWindow);
                const Reference<awt::XWindow2> xBorderWindow2(xBorderWindow, UNO_QUERY);
                if (xBorderWindow.is()
                    && xContentWindow.is()
                    && ( ! xBorderWindow2.is() || xBorderWindow2->isVisible()))
                {
                    aArguments[nIndex++] = Any(xBorderWindow);
                    aArguments[nIndex++] = Any(xContentWindow);
                }
            }

            aArguments.realloc(nIndex);
            rtl::Reference<PresenterPaneBorderManager> pManager (
                new PresenterPaneBorderManager (
                    mxComponentContext,
                    mpPresenterController));
            pManager->initialize(aArguments);
            mxPaneBorderManager = Reference<XInterface>(static_cast<XWeak*>(pManager.get()));
        }
    }
    catch (RuntimeException&)
    {
    }
#endif
}




void PresenterWindowManager::Invalidate (void)
{
    mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
}




Reference<awt::XWindow> PresenterWindowManager::GetParentWindow (void) const
{
    return mxParentWindow;
}




Reference<rendering::XCanvas> PresenterWindowManager::GetParentCanvas (void) const
{
    return mxParentCanvas;
}




void PresenterWindowManager::Update (void)
{
    mxClipPolygon = NULL;
    mbIsLayoutPending = true;

    UpdateWindowList();
    Invalidate();
}




void PresenterWindowManager::ThrowIfDisposed (void) const
    throw (::com::sun::star::lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        throw lang::DisposedException (
            OUString(RTL_CONSTASCII_USTRINGPARAM(
                "PresenterWindowManager has already been disposed")),
            const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}



namespace {

//===== ModeChangeAnimation ===================================================

class ModeChangeAnimation : public PresenterAnimation
{
public:
    ModeChangeAnimation (
        const ::boost::shared_ptr<PresenterSprite>& rpSprite,
        const Reference<rendering::XSpriteCanvas>& rxCanvas)
        : PresenterAnimation (0, 1000, 20),
          mpSprite(rpSprite),
          mxCanvas(rxCanvas)
    {
    }

    virtual void Run (const double nProgress, const sal_uInt64 nCurrentTime)
    {
        (void)nCurrentTime;
        mpSprite->SetAlpha(1.0 - nProgress);
        mxCanvas->updateScreen(sal_False);
    }

private:
    ::boost::shared_ptr<PresenterSprite> mpSprite;
    Reference<rendering::XSpriteCanvas> mxCanvas;
};




ModeChangeAnimationStarter::ModeChangeAnimationStarter (
    const Reference<drawing::framework::XConfigurationController>& rxConfigurationController,
    const Reference<awt::XWindow>& rxWindow,
    const Reference<rendering::XSpriteCanvas>& rxCanvas,
    const ::boost::shared_ptr<PresenterAnimator>& rpAnimator)
    : ModeChangeAnimationStarterInterfaceBase(m_aMutex),
      mxConfigurationController(rxConfigurationController),
      mpAnimator(rpAnimator),
      mpSprite(new PresenterSprite()),
      mxCanvas(rxCanvas)
{
    OSL_ASSERT(rxWindow.is());
    OSL_ASSERT(rxCanvas.is());

    // Get the bitmap of the background.
    Reference<rendering::XBitmap> xBackgroundBitmap (rxCanvas, UNO_QUERY);
    if ( ! xBackgroundBitmap.is())
        return;

    // Create the sprite.
    const awt::Rectangle aWindowSize (rxWindow->getPosSize());
    mpSprite->SetFactory(rxCanvas);
    mpSprite->Resize(geometry::RealSize2D(aWindowSize.Width, aWindowSize.Height));
    mpSprite->SetPriority(10);
    
    // Fill it with the background inside the bounding box.
    const rendering::ViewState aViewState (
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        NULL);
    const rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);
    Reference<rendering::XCanvas> xSpriteCanvas (mpSprite->GetCanvas());
    if (xSpriteCanvas.is())
    {
        xSpriteCanvas->drawBitmap(xBackgroundBitmap, aViewState, aRenderState);
        mpSprite->Show();
    }

    // Register as listener to be notified when the new panes are visible
    // and the sprite can be faded out.
    mxConfigurationController->addConfigurationChangeListener(
            this,
            A2S("ConfigurationUpdateEnd"),
            Any());
}




ModeChangeAnimationStarter::~ModeChangeAnimationStarter (void)
{
}




void SAL_CALL ModeChangeAnimationStarter::disposing (void)
{
    mxConfigurationController = NULL;
    mpAnimator.reset();
    mpSprite.reset();
}




// XConfigurationChangeListener

void SAL_CALL ModeChangeAnimationStarter::notifyConfigurationChange (
    const com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent)
    throw (com::sun::star::uno::RuntimeException)
{
    (void)rEvent;
    
    // Start the actual animation.
    mpAnimator->AddAnimation(SharedPresenterAnimation(new ModeChangeAnimation(
        mpSprite,
        mxCanvas)));

    mxConfigurationController->removeConfigurationChangeListener(this);
}




// XEventListener

void SAL_CALL ModeChangeAnimationStarter::disposing (
    const com::sun::star::lang::EventObject& rEvent)
    throw (com::sun::star::uno::RuntimeException)
{
    if (rEvent.Source == mxConfigurationController)
        mxConfigurationController = NULL;
}



} // end of anonymous namespace


} } // end of namespace ::sdext::presenter
