/**************************************************************
 *
 * 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 "PresenterPaneAnimator.hxx"

#include "PresenterAnimation.hxx"
#include "PresenterAnimator.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterController.hxx"
#include "PresenterGeometryHelper.hxx"
#include "PresenterPaintManager.hxx"
#include "PresenterPaneContainer.hxx"
#include "PresenterPaneFactory.hxx"
#include "PresenterSprite.hxx"
#include "PresenterSpritePane.hxx"
#include "PresenterWindowManager.hxx"

#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <boost/enable_shared_from_this.hpp>

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

namespace sdext { namespace presenter {

namespace {

    class PaneGroup;

    class PresenterPaneAnimatorBase
        : public ::boost::enable_shared_from_this<PresenterPaneAnimatorBase>,
          public PresenterPaneAnimator
    {
    public:
        PresenterPaneAnimatorBase (
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
            const ::rtl::Reference<PresenterController>& rpPresenterController,
            const bool bAnimate,
            const EndActions& rShowEndActions,
            const EndActions& rEndEndActions);
        virtual ~PresenterPaneAnimatorBase (void);

        typedef ::std::vector< ::boost::function<void()> > EndOperators;

        void ActivatePanes (void);
        void ActivatePane (
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId);
        void RestoreFrozenWindows (void);
        void FreezePanes (const Reference<rendering::XSpriteCanvas>& rxCanvas);

    protected:
        ::rtl::Reference<PresenterController> mpPresenterController;
        ::rtl::Reference<PresenterPaneContainer> mpPaneContainer;
        ::rtl::Reference<PresenterWindowManager> mpWindowManager;
        ::std::vector< ::boost::shared_ptr<PaneGroup> > maPaneGroups;
        css::uno::Reference<css::drawing::framework::XResourceId> mxCenterPaneId;
        bool mbDoAnimation;
        EndActions maShowEndActions;
        EndActions maHideEndActions;

        void DeactivatePanes (void);
        void ResizePane (
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
            const geometry::RealRectangle2D& rBox);
        void DeactivatePane (
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId);
    };


    class UnfoldInCenterAnimator : public PresenterPaneAnimatorBase
    {
    public:
        UnfoldInCenterAnimator (
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
            const ::rtl::Reference<PresenterController>& rpPresenterController,
            const bool bAnimate,
            const EndActions& rShowEndActions,
            const EndActions& rEndEndActions);

        virtual ~UnfoldInCenterAnimator (void);

        virtual void ShowPane (void);

        virtual void HidePane (void);

    private:
        geometry::RealRectangle2D maCenterPaneBox;

        void SetupPaneGroups (void);
        geometry::RealRectangle2D MovePanesAway (
            const css::geometry::RealRectangle2D& rFreeCenterArea);
    };


    class MoveInFromBottomAnimator : public PresenterPaneAnimatorBase
    {
    public:
        MoveInFromBottomAnimator(
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
            const ::rtl::Reference<PresenterController>& rpPresenterController,
            const bool bAnimate,
            const EndActions& rShowEndActions,
            const EndActions& rEndEndActions);
        virtual ~MoveInFromBottomAnimator (void);

        virtual void ShowPane (void);
        virtual void HidePane (void);

    private:
        ::boost::shared_ptr<PresenterSprite> maNewPaneSprite;
        geometry::RealRectangle2D maCenterPaneBox;

        void CreateShowAnimation (
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
            const EndOperators& rpEndOperators,
            const css::uno::Reference<css::rendering::XSpriteCanvas>& rxSpriteCanvas,
            const bool bAnimate,
            const css::geometry::RealPoint2D& rStartLocation,
            const css::geometry::RealPoint2D& rEndLocation);
    };


    class TransparentOverlayAnimator : public PresenterPaneAnimatorBase
    {
    public:
        TransparentOverlayAnimator(
            const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
            const ::rtl::Reference<PresenterController>& rpPresenterController,
            const bool bAnimate,
            const EndActions& rShowEndActions,
            const EndActions& rEndEndActions);
        virtual ~TransparentOverlayAnimator (void);

        virtual void ShowPane (void);
        virtual void HidePane (void);

    private:
        PresenterSprite maBackgroundSprite;
        void CreateBackgroundSprite (void);
    };


    class PaneDescriptor
    {
    public:
        PresenterPaneContainer::SharedPaneDescriptor mpPaneDescriptor;

        PaneDescriptor (const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor);
        void Restore (void) const;
    private:
        double mnLeft;
        double mnTop;
        double mnRight;
        double mnBottom;
    };

    class MultiAnimation : public PresenterAnimation
    {
    public:
        typedef ::boost::function<void(double)> Animation;
        MultiAnimation (const sal_uInt32 nDuration);
        void AddAnimation (const Animation& rAnimation);
        virtual void Run (const double nProgress, const sal_uInt64 nCurrentTime);
    private:
        vector<Animation> maAnimations;
    };


    class PaneGroup
    {
    public:
        PaneGroup (void);
        ~PaneGroup (void);
        void AddPane (const PresenterPaneContainer::SharedPaneDescriptor& rpPane);
        void CreateSubstitution (const Reference<rendering::XSpriteCanvas>& rxCanvas);
        void ThawPanes (void);
        void Restore (void);
        ::boost::shared_ptr<PresenterSprite> GetSubstitution (void);
        css::geometry::RealRectangle2D GetOriginalBoundingBox (void) const;
        css::geometry::RealRectangle2D GetCurrentBoundingBox (void) const;
        void MovePanes (
            const double nXOffset,
            const double nYOffset,
            const ::rtl::Reference<PresenterWindowManager>& rpWindowManager);
        void ActivatePanes (void);
        void DeactivatePanes (void);
        void HidePanes (void);
        void ShowPanes (void);

    private:
        vector<PaneDescriptor> maPanes;
        awt::Rectangle maOriginalBoundingBox;
        css::geometry::RealRectangle2D maCurrentBoundingBox;
        ::boost::shared_ptr<PresenterSprite> mpSubstitution;

    };
    typedef ::boost::shared_ptr<PaneGroup> SharedPaneGroup;

    void InterpolatePosition (
        const ::boost::function<void(geometry::RealPoint2D)>& rSetter,
        double nP,
        const geometry::RealPoint2D rInitialBox,
        const geometry::RealPoint2D rFinalBox);

    template<typename T>
    void InterpolateValue (
        const ::boost::function<void(T)>& rSetter,
        double nP,
        const T aInitialValue,
        const T aFinalValue);

    void SpriteTransform(
        const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
        const Reference<XResourceId>& rxPaneId,
        const Reference<awt::XWindow>& rxSpriteOwnerWindow,
        const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager,
        const bool bAppear,
        const double nX,
        const double nInitialTop,
        const double nFinalTop,
        const double nP);

    void SpritePaneMove (
        const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
        const Reference<XResourceId>& rxPaneId,
        const geometry::RealPoint2D& rLocation);

    geometry::RealPoint2D GetLocation (const geometry::RealRectangle2D& rBox);
    geometry::RealSize2D GetSize (const geometry::RealRectangle2D& rBox);


} // end of anonymous namespace




//=============================================================================


::boost::shared_ptr<PresenterPaneAnimator> CreateUnfoldInCenterAnimator (
    const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
    const ::rtl::Reference<PresenterController>& rpPresenterController,
    const bool bAnimate,
    const EndActions& rShowEndActions,
    const EndActions& rEndEndActions)
{
    return ::boost::shared_ptr<PresenterPaneAnimator>(
        new UnfoldInCenterAnimator(rxPaneId, rpPresenterController, bAnimate,
            rShowEndActions, rEndEndActions));
}




::boost::shared_ptr<PresenterPaneAnimator> CreateMoveInFromBottomAnimator (
        const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
        const ::rtl::Reference<PresenterController>& rpPresenterController,
        const bool bAnimate,
        const EndActions& rShowEndActions,
        const EndActions& rEndEndActions)
{
    return ::boost::shared_ptr<PresenterPaneAnimator>(
        new MoveInFromBottomAnimator(rxPaneId, rpPresenterController, bAnimate,
            rShowEndActions, rEndEndActions));
}




::boost::shared_ptr<PresenterPaneAnimator> CreateTransparentOverlay (
        const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
        const ::rtl::Reference<PresenterController>& rpPresenterController,
        const bool bAnimate,
        const EndActions& rShowEndActions,
        const EndActions& rEndEndActions)
{
    return ::boost::shared_ptr<PresenterPaneAnimator>(
        new TransparentOverlayAnimator(rxPaneId, rpPresenterController, bAnimate,
            rShowEndActions, rEndEndActions));
}




//===== PresenterPaneAnimator =================================================

namespace {

PresenterPaneAnimatorBase::PresenterPaneAnimatorBase (
    const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
    const ::rtl::Reference<PresenterController>& rpPresenterController,
    const bool bAnimate,
    const EndActions& rShowEndActions,
    const EndActions& rHideEndActions)
    : mpPresenterController(rpPresenterController),
      mpPaneContainer(rpPresenterController->GetPaneContainer()),
      mpWindowManager(rpPresenterController->GetWindowManager()),
      maPaneGroups(),
      mxCenterPaneId(rxPaneId),
      mbDoAnimation(bAnimate),
      maShowEndActions(rShowEndActions),
      maHideEndActions(rHideEndActions)
{
}




PresenterPaneAnimatorBase::~PresenterPaneAnimatorBase (void)
{
}




void PresenterPaneAnimatorBase::FreezePanes (const Reference<rendering::XSpriteCanvas>& rxCanvas)
{
    ::std::vector<SharedPaneGroup>::const_iterator iGroup;
    for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup)
    {
        (*iGroup)->CreateSubstitution(rxCanvas);
        (*iGroup)->GetSubstitution()->MoveTo(GetLocation((*iGroup)->GetOriginalBoundingBox()));
    }
}




void PresenterPaneAnimatorBase::ActivatePanes (void)
{
    ActivatePane(mxCenterPaneId);

    ::std::vector<SharedPaneGroup>::const_iterator iGroup;
    for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup)
    {
        (*iGroup)->ShowPanes();
        (*iGroup)->ActivatePanes();
        (*iGroup)->GetSubstitution()->Hide();
    }

    mpWindowManager->Update();
}




void PresenterPaneAnimatorBase::DeactivatePanes (void)
{
    ::std::vector<SharedPaneGroup>::const_iterator iGroup;
    for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup)
    {
        (*iGroup)->GetSubstitution()->Show();
        (*iGroup)->DeactivatePanes();
        (*iGroup)->HidePanes();
    }

    mpWindowManager->Update();
}




void PresenterPaneAnimatorBase::ResizePane (
    const Reference<drawing::framework::XResourceId>& rxPaneId,
    const geometry::RealRectangle2D& rBox)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL)
    {
        mpWindowManager->SetPanePosSizeAbsolute (
            rxPaneId->getResourceURL(),
            rBox.X1,
            rBox.Y1,
            rBox.X2-rBox.X1,
            rBox.Y2-rBox.Y1);
        mpWindowManager->Layout();
        if ( ! pDescriptor->maSpriteProvider.empty())
        {
            pDescriptor->maSpriteProvider()->Resize(GetSize(rBox));
        }
    }
}




void PresenterPaneAnimatorBase::RestoreFrozenWindows (void)
{
    ::std::vector<SharedPaneGroup>::const_iterator iGroup;
    for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup)
    {
        (*iGroup)->Restore();
        (*iGroup)->ShowPanes();
        (*iGroup)->ActivatePanes();
        (*iGroup)->GetSubstitution()->Hide();
    }
    maPaneGroups.clear();

    ActivatePane(mxCenterPaneId);

    mpWindowManager->Update();
}




void PresenterPaneAnimatorBase::ActivatePane (
    const Reference<drawing::framework::XResourceId>& rxPaneId)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL)
        pDescriptor->SetActivationState(true);
}




void PresenterPaneAnimatorBase::DeactivatePane (
    const Reference<drawing::framework::XResourceId>& rxPaneId)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL)
        pDescriptor->SetActivationState(false);
}




//===== UnfoldInCenterAnimator ================================================

UnfoldInCenterAnimator::UnfoldInCenterAnimator (
    const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
    const ::rtl::Reference<PresenterController>& rpPresenterController,
    const bool bAnimate,
    const EndActions& rShowEndActions,
    const EndActions& rEndEndActions)
    : PresenterPaneAnimatorBase(rxPaneId, rpPresenterController, bAnimate,
        rShowEndActions, rEndEndActions)
{
}




UnfoldInCenterAnimator::~UnfoldInCenterAnimator (void)
{
}




void UnfoldInCenterAnimator::ShowPane (void)
{
    OSL_ASSERT(mpWindowManager.get()!=NULL);

    Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY);
    if ( ! xParentWindow.is())
        return;

    Reference<rendering::XSpriteCanvas> xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY);
    if ( ! xCanvas.is())
        return;

    Reference<rendering::XBitmap> xParentBitmap (xCanvas, UNO_QUERY);
    if ( ! xParentBitmap.is())
        return;

    Reference<rendering::XGraphicDevice> xDevice(xCanvas->getDevice());
    if ( ! xDevice.is())
        return;

    awt::Rectangle aWindowBox (xParentWindow->getPosSize());

    // Create two pane groups that will be moved together.  One contains the
    // notes view, the other group contains all other panes.
    SetupPaneGroups();

    // Setup the places where the two pane groups are moved to.
    maCenterPaneBox
        = MovePanesAway(geometry::RealRectangle2D(0,200,aWindowBox.Width, aWindowBox.Height-200));

    // Setup the final size of the new pane so that it fits into the space
    // between the two pane groups.
    ResizePane(mxCenterPaneId, maCenterPaneBox);

    // Avoid that the center pane updates its previews while being animated.
    DeactivatePane(mxCenterPaneId);

    // Replace the pane groups with sprites that look like the panes but can
    // be moved around much faster.
    FreezePanes(xCanvas);

    // The vertical center of the new pane.
    const double nY0 ((maPaneGroups[0]->GetOriginalBoundingBox().Y2
            + maPaneGroups[1]->GetOriginalBoundingBox().Y1) / 2);

    // Make sure that the new pane is painted once before the animation starts.
    SpriteTransform(
        mpPaneContainer,
        mxCenterPaneId,
        xParentWindow,
        mpPresenterController->GetPaintManager(),
        true,
        maCenterPaneBox.X1,
        nY0,
        maCenterPaneBox.Y1,
        0);
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(mxCenterPaneId));
    if (pDescriptor.get() != NULL)
    {
        mpPresenterController->GetPaintManager()->Invalidate(
            pDescriptor->mxBorderWindow,
            true);
    }

    // Animate the upper and lower window bitmaps.
    ::boost::shared_ptr<MultiAnimation> pMultiAnimation (
        new MultiAnimation(mbDoAnimation ? 500 : 0));

    // Animate the pane group sprites to be moved up or down.
    vector<SharedPaneGroup>::const_iterator iGroup;
    for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup)
    {
        pMultiAnimation->AddAnimation(
            ::boost::bind(
                InterpolatePosition,
                ::boost::protect(::boost::bind(
                    &PresenterSprite::MoveTo, (*iGroup)->GetSubstitution(), _1)),
                _1,
                GetLocation((*iGroup)->GetOriginalBoundingBox()),
                GetLocation((*iGroup)->GetCurrentBoundingBox())));
    }

    // Animate the new center pane to expand.
    pMultiAnimation->AddAnimation(
        ::boost::bind(
            SpriteTransform,
            mpPaneContainer,
            mxCenterPaneId,
            xParentWindow,
            mpPresenterController->GetPaintManager(),
            true,
            maCenterPaneBox.X1,
            nY0,
            maCenterPaneBox.Y1,
            _1));

    // Call updateScreen after each animation step.
    if (xCanvas.is())
        pMultiAnimation->AddAnimation(
            ::boost::bind(&rendering::XSpriteCanvas::updateScreen, xCanvas, sal_False));

    // Activate the panes when the animation is over.
    pMultiAnimation->AddEndCallback(
        ::boost::bind(&PresenterPaneAnimatorBase::ActivatePanes, shared_from_this()));
    EndActions::const_iterator iAction;
    for (iAction=maShowEndActions.begin(); iAction!=maShowEndActions.end(); ++iAction)
        pMultiAnimation->AddEndCallback(*iAction);

    // Start the animation.
    ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator());
    OSL_ASSERT(pAnimator.get()!=NULL);
    pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation));

    mpWindowManager->Update();
}




void UnfoldInCenterAnimator::HidePane (void)
{
    OSL_ASSERT(mpWindowManager.get()!=NULL);

    Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY);
    if ( ! xParentWindow.is())
        return;

    DeactivatePanes();
    DeactivatePane(mxCenterPaneId);

    ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator());
    const awt::Rectangle aWindowBox (xParentWindow->getPosSize());
    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);

    // Animate the upper and lower window bitmaps.
    Reference<rendering::XSpriteCanvas> xSpriteCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY);
    ::boost::shared_ptr<MultiAnimation> pMultiAnimation (new MultiAnimation(mbDoAnimation ? 500 : 1));

    vector<SharedPaneGroup>::const_iterator iGroup;
    for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup)
    {
        pMultiAnimation->AddAnimation(
            ::boost::bind(
                InterpolatePosition,
                ::boost::protect(::boost::bind(
                    &PresenterSprite::MoveTo, (*iGroup)->GetSubstitution(), _1)),
                _1,
                GetLocation((*iGroup)->GetCurrentBoundingBox()),
                GetLocation((*iGroup)->GetOriginalBoundingBox())));
    }

    // Animate the new center pane to collapse.
    const double nY0 ((maPaneGroups[0]->GetOriginalBoundingBox().Y2
            + maPaneGroups[1]->GetOriginalBoundingBox().Y1) / 2);
    pMultiAnimation->AddAnimation(
        ::boost::bind(
            SpriteTransform,
            mpPaneContainer,
            mxCenterPaneId,
            xParentWindow,
            mpPresenterController->GetPaintManager(),
            false,
            maCenterPaneBox.X1,
            nY0,
            maCenterPaneBox.Y1,
            _1));

    if (mbDoAnimation)
    {
        pMultiAnimation->AddAnimation(
            ::boost::bind(&rendering::XSpriteCanvas::updateScreen, xSpriteCanvas, sal_False));
    }
    pMultiAnimation->AddEndCallback(
        ::boost::bind(&PresenterPaneAnimatorBase::RestoreFrozenWindows, shared_from_this()));
    EndActions::const_iterator iAction;
    for (iAction=maHideEndActions.begin(); iAction!=maHideEndActions.end(); ++iAction)
        pMultiAnimation->AddEndCallback(*iAction);

    pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation));
}




void UnfoldInCenterAnimator::SetupPaneGroups (void)
{
    maPaneGroups.clear();

    // Setup the upper pane group.
    SharedPaneGroup pUpperPanes (new PaneGroup());
    pUpperPanes->AddPane(mpPaneContainer->FindPaneURL(
        PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
    pUpperPanes->AddPane(mpPaneContainer->FindPaneURL(
        PresenterPaneFactory::msNextSlidePreviewPaneURL));
    pUpperPanes->AddPane(mpPaneContainer->FindPaneURL(
        PresenterPaneFactory::msToolBarPaneURL));
    pUpperPanes->AddPane(mpPaneContainer->FindPaneURL(
        PresenterPaneFactory::msHelpPaneURL));
    maPaneGroups.push_back(pUpperPanes);

    // Setup the lower pane group.
    SharedPaneGroup pLowerPanes (new PaneGroup());
    pLowerPanes->AddPane(mpPaneContainer->FindPaneURL(
        PresenterPaneFactory::msNotesPaneURL));
    maPaneGroups.push_back(pLowerPanes);
}




geometry::RealRectangle2D UnfoldInCenterAnimator::MovePanesAway (
    const geometry::RealRectangle2D& rFreeCenterArea)
{
    SharedPaneGroup aUpperPanes = maPaneGroups[0];
    SharedPaneGroup aLowerPanes = maPaneGroups[1];

    // Move upper pane group out of the way.
    const double nTop (rFreeCenterArea.Y1);
    const double nUpperVerticalOffset (nTop - aUpperPanes->GetOriginalBoundingBox().Y2);
    aUpperPanes->MovePanes(0, nUpperVerticalOffset, mpWindowManager);

    // Move lower pane group out of the way.
    const double nBottom (rFreeCenterArea.Y2);
    const double nLowerVerticalOffset (nBottom - aLowerPanes->GetOriginalBoundingBox().Y1);
    aLowerPanes->MovePanes(0, nLowerVerticalOffset, mpWindowManager);

    return geometry::RealRectangle2D(
        ::std::min(
            aUpperPanes->GetOriginalBoundingBox().X1,
            aLowerPanes->GetOriginalBoundingBox().X1),
        nTop+20,
        ::std::max(
            aUpperPanes->GetOriginalBoundingBox().X2,
            aLowerPanes->GetOriginalBoundingBox().X2),
        nBottom-20);
}




//===== MoveInFromBottomAnimator ==============================================

MoveInFromBottomAnimator::MoveInFromBottomAnimator (
    const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
    const ::rtl::Reference<PresenterController>& rpPresenterController,
    const bool bAnimate,
    const EndActions& rShowEndActions,
    const EndActions& rEndEndActions)
    : PresenterPaneAnimatorBase(rxPaneId, rpPresenterController, bAnimate,
        rShowEndActions, rEndEndActions),
      maNewPaneSprite()
{
}




MoveInFromBottomAnimator::~MoveInFromBottomAnimator (void)
{
}




void MoveInFromBottomAnimator::ShowPane (void)
{
    OSL_ASSERT(mpWindowManager.get()!=NULL);

    Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY);
    if ( ! xParentWindow.is())
        return;

    Reference<rendering::XSpriteCanvas> xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY);
    if ( ! xCanvas.is())
        return;

    Reference<rendering::XBitmap> xParentBitmap (xCanvas, UNO_QUERY);
    if ( ! xParentBitmap.is())
        return;

    Reference<rendering::XGraphicDevice> xDevice(xCanvas->getDevice());
    if ( ! xDevice.is())
        return;

    awt::Rectangle aWindowBox (xParentWindow->getPosSize());

    // Create a pane group that just contains the notes view.
    SharedPaneGroup pLowerPanes (new PaneGroup());
    pLowerPanes->AddPane(mpPaneContainer->FindPaneURL(
        PresenterPaneFactory::msNotesPaneURL));
    maPaneGroups.push_back(pLowerPanes);

    // Deactivate the panes that will take place in the animation.
    pLowerPanes->DeactivatePanes();
    DeactivatePane(mxCenterPaneId);

    // Set the size of the new pane.
    maCenterPaneBox = pLowerPanes->GetOriginalBoundingBox();
    ResizePane(mxCenterPaneId, maCenterPaneBox);

    geometry::RealPoint2D aStartLocation (maCenterPaneBox.X1, aWindowBox.Height);
    geometry::RealPoint2D aEndLocation (maCenterPaneBox.X1, maCenterPaneBox.Y1);

    // Get the sprite of the new pane, make it visible and move it to the
    // start location.
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(mxCenterPaneId));
    if (pDescriptor.get() != NULL)
    {
        if (pDescriptor->mxBorderWindow.is())
            pDescriptor->mxBorderWindow->setVisible(sal_True);

        maNewPaneSprite = pDescriptor->maSpriteProvider();
        if (maNewPaneSprite.get() != NULL)
        {
            maNewPaneSprite->MoveTo(aStartLocation);
            maNewPaneSprite->Show();
        }
        xCanvas->updateScreen(sal_False);
    }

    CreateShowAnimation(
        mxCenterPaneId,
        maShowEndActions,
        xCanvas,
        mbDoAnimation,
        aStartLocation,
        aEndLocation);

    mpWindowManager->Update();
}




void MoveInFromBottomAnimator::HidePane (void)
{
    OSL_ASSERT(mpWindowManager.get()!=NULL);

    Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY);
    if ( ! xParentWindow.is())
        return;

    Reference<rendering::XSpriteCanvas> xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY);
    if ( ! xCanvas.is())
        return;

    DeactivatePanes();
    DeactivatePane(mxCenterPaneId);

    SharedPaneGroup aPanes (maPaneGroups[0]);

    aPanes->ShowPanes();

    ::boost::shared_ptr<MultiAnimation> pMultiAnimation (
        new MultiAnimation(mbDoAnimation ? 500 : 0));
    awt::Rectangle aWindowBox (xParentWindow->getPosSize());

    // Animate the new center pane to collapse.
    pMultiAnimation->AddAnimation(
        ::boost::bind(
            InterpolatePosition,
            ::boost::protect(::boost::bind(&SpritePaneMove, mpPaneContainer, mxCenterPaneId, _1)),
            _1,
            geometry::RealPoint2D(maCenterPaneBox.X1, maCenterPaneBox.Y1),
            geometry::RealPoint2D(maCenterPaneBox.X1, aWindowBox.Height)));

    if (mbDoAnimation)
    {
        pMultiAnimation->AddAnimation(
            ::boost::bind(&rendering::XSpriteCanvas::updateScreen, xCanvas, sal_False));
    }
    pMultiAnimation->AddEndCallback(
        ::boost::bind(&PresenterPaneAnimatorBase::RestoreFrozenWindows, shared_from_this()));
    EndActions::const_iterator iAction;
    for (iAction=maHideEndActions.begin(); iAction!=maHideEndActions.end(); ++iAction)
        pMultiAnimation->AddEndCallback(*iAction);

    ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator());
    pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation));
}




void MoveInFromBottomAnimator::CreateShowAnimation (
    const Reference<drawing::framework::XResourceId>& rxPaneId,
    const EndOperators& rEndOperators,
    const Reference<rendering::XSpriteCanvas>& rxSpriteCanvas,
    const bool bAnimate,
    const geometry::RealPoint2D& rStartLocation,
    const geometry::RealPoint2D& rEndLocation)
{
    // Animate the upper and lower window bitmaps.
    ::boost::shared_ptr<MultiAnimation> pMultiAnimation (new MultiAnimation(bAnimate ? 500 : 0));

    // Animate new pane to move in from the bottom.
    pMultiAnimation->AddAnimation(
        ::boost::bind(
            InterpolatePosition,
            ::boost::protect(::boost::bind(&SpritePaneMove, mpPaneContainer, rxPaneId, _1)),
            _1,
            rStartLocation,
            rEndLocation));

    // Call updateScreen after each animation step.
    if (rxSpriteCanvas.is())
        pMultiAnimation->AddAnimation(
            ::boost::bind(&rendering::XSpriteCanvas::updateScreen, rxSpriteCanvas, sal_False));

    // Activate the panes when the animation is over.
    pMultiAnimation->AddEndCallback(
        ::boost::bind(&PaneGroup::HidePanes, maPaneGroups[0]));
    pMultiAnimation->AddEndCallback(
        ::boost::bind(&PresenterPaneAnimatorBase::ActivatePane, shared_from_this(), mxCenterPaneId));
    EndActions::const_iterator iAction;
    for (iAction=rEndOperators.begin(); iAction!=rEndOperators.end(); ++iAction)
        pMultiAnimation->AddEndCallback(*iAction);

    // Start the animation.
    ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator());
    OSL_ASSERT(pAnimator.get()!=NULL);
    pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation));
}





//===== TransparentOverlayAnimator ============================================

TransparentOverlayAnimator::TransparentOverlayAnimator (
    const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
    const ::rtl::Reference<PresenterController>& rpPresenterController,
    const bool bAnimate,
    const EndActions& rShowEndActions,
    const EndActions& rEndEndActions)
    : PresenterPaneAnimatorBase(
        rxPaneId,
        rpPresenterController,
        bAnimate,
        rShowEndActions,
        rEndEndActions),
      maBackgroundSprite()
{
}




TransparentOverlayAnimator::~TransparentOverlayAnimator (void)
{
}




void TransparentOverlayAnimator::ShowPane (void)
{
    EndActions::const_iterator iAction;
    for (iAction=maShowEndActions.begin(); iAction!=maShowEndActions.end(); ++iAction)
        (*iAction)();

    CreateBackgroundSprite();

    Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY);
    if (xParentWindow.is())
    {
        const awt::Rectangle aWindowBox (xParentWindow->getPosSize());
        SharedPaneGroup pAllPanes (new PaneGroup());
        pAllPanes->AddPane(mpPaneContainer->FindPaneURL(
            PresenterPaneFactory::msCurrentSlidePreviewPaneURL));
        pAllPanes->AddPane(mpPaneContainer->FindPaneURL(
            PresenterPaneFactory::msNextSlidePreviewPaneURL));
        pAllPanes->AddPane(mpPaneContainer->FindPaneURL(
            PresenterPaneFactory::msToolBarPaneURL));
        pAllPanes->AddPane(mpPaneContainer->FindPaneURL(
            PresenterPaneFactory::msHelpPaneURL));
        pAllPanes->AddPane(mpPaneContainer->FindPaneURL(
            PresenterPaneFactory::msNotesPaneURL));
        maPaneGroups.push_back(pAllPanes);
        pAllPanes->DeactivatePanes();
        mpWindowManager->Update();
    }

    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        mpPaneContainer->FindPaneId(mxCenterPaneId));
    if (pDescriptor.get() != NULL)
    {
        PresenterSpritePane* pPane = dynamic_cast<PresenterSpritePane*>(
            pDescriptor->mxPane.get());
        if (pPane != NULL)
            pPane->ShowTransparentBorder();

        pDescriptor->SetActivationState(true);
        if (pDescriptor->mxBorderWindow.is())
            pDescriptor->mxBorderWindow->setVisible(sal_True);
    }
}




void TransparentOverlayAnimator::HidePane (void)
{
    maPaneGroups[0]->ActivatePanes();
    EndActions::const_iterator iAction;
    for (iAction=maHideEndActions.begin(); iAction!=maHideEndActions.end(); ++iAction)
        (*iAction)();
    mpWindowManager->Update();
}




void TransparentOverlayAnimator::CreateBackgroundSprite (void)
{
    Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY);
    Reference<rendering::XSpriteCanvas> xParentCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY);
    if (xParentWindow.is() && xParentCanvas.is())
    {
        const awt::Rectangle aWindowBox (xParentWindow->getPosSize());
        maBackgroundSprite.SetFactory(xParentCanvas);
        maBackgroundSprite.Resize(
            geometry::RealSize2D(aWindowBox.Width, aWindowBox.Height));
        maBackgroundSprite.MoveTo(
            geometry::RealPoint2D(aWindowBox.X, aWindowBox.Y));
        maBackgroundSprite.SetAlpha(0.5);
        maBackgroundSprite.Show();

        Reference<rendering::XCanvas> xCanvas (maBackgroundSprite.GetCanvas());

        if (xCanvas.is())
        {
            rendering::ViewState aViewState(
                geometry::AffineMatrix2D(1,0,0, 0,1,0),
                NULL);

            rendering::RenderState aRenderState(
                geometry::AffineMatrix2D(1,0,0, 0,1,0),
                NULL,
                Sequence<double>(4),
                rendering::CompositeOperation::SOURCE);
            PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x80808080));

            Reference<rendering::XPolyPolygon2D> xPolygon (
                PresenterGeometryHelper::CreatePolygon(aWindowBox, xCanvas->getDevice()));
            if (xPolygon.is())
                xCanvas->fillPolyPolygon(
                    xPolygon,
                    aViewState,
                    aRenderState);
        }
    }
}




//===== PaneGroup =============================================================

PaneGroup::PaneGroup (void)
    : maPanes(),
      maOriginalBoundingBox(),
      maCurrentBoundingBox(),
      mpSubstitution(new PresenterSprite())
{
}




PaneGroup::~PaneGroup (void)
{
    mpSubstitution.reset();
}




void PaneGroup::AddPane (const PresenterPaneContainer::SharedPaneDescriptor& rpPane)
{
    OSL_ASSERT(rpPane.get() != NULL);

    if (rpPane->mxBorderWindow.is())
    {
        PaneDescriptor aDescriptor (rpPane);
        maPanes.push_back(aDescriptor);
        maOriginalBoundingBox = PresenterGeometryHelper::Union(
            maOriginalBoundingBox,
            rpPane->mxBorderWindow->getPosSize());
    }
}




void PaneGroup::CreateSubstitution (const Reference<rendering::XSpriteCanvas>& rxCanvas)
{
    // Get the bitmap of the background.
    Reference<rendering::XBitmap> xBackgroundBitmap (rxCanvas, UNO_QUERY);
    if ( ! xBackgroundBitmap.is())
        return;

    // Create the sprite.
    mpSubstitution->SetFactory(rxCanvas);
    mpSubstitution->Resize(
        geometry::RealSize2D(maOriginalBoundingBox.Width, maOriginalBoundingBox.Height));

    // 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,-maOriginalBoundingBox.X, 0,1,-maOriginalBoundingBox.Y),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);

    Reference<rendering::XCanvas> xSpriteCanvas (mpSubstitution->GetCanvas());
    if (xSpriteCanvas.is())
        xSpriteCanvas->drawBitmap(xBackgroundBitmap, aViewState, aRenderState);
}




void PaneGroup::Restore (void)
{
    vector<PaneDescriptor>::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane)
    {
        iPane->Restore();
    }
}




::boost::shared_ptr<PresenterSprite> PaneGroup::GetSubstitution (void)
{
    return mpSubstitution;
}




geometry::RealRectangle2D PaneGroup::GetOriginalBoundingBox (void) const
{
    return geometry::RealRectangle2D(
        maOriginalBoundingBox.X,
        maOriginalBoundingBox.Y,
        maOriginalBoundingBox.X + maOriginalBoundingBox.Width,
        maOriginalBoundingBox.Y + maOriginalBoundingBox.Height);
}




geometry::RealRectangle2D PaneGroup::GetCurrentBoundingBox (void) const
{
    return maCurrentBoundingBox;
}




void PaneGroup::MovePanes (
    const double nXOffset,
    const double nYOffset,
    const ::rtl::Reference<PresenterWindowManager>& rpWindowManager
    )
{
    awt::Rectangle aBBox;
    vector<PaneDescriptor>::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane)
    {
        awt::Rectangle aBox (iPane->mpPaneDescriptor->mxBorderWindow->getPosSize());
        aBox.X += sal_Int32(nXOffset);
        aBox.Y += sal_Int32(nYOffset);
        rpWindowManager->SetPanePosSizeAbsolute(
            iPane->mpPaneDescriptor->mxPaneId->getResourceURL(),
            aBox.X,
            aBox.Y,
            aBox.Width,
            aBox.Height);
        aBBox = PresenterGeometryHelper::Union(aBBox, aBox);
    }
    maCurrentBoundingBox = geometry::RealRectangle2D(
        aBBox.X, aBBox.Y, aBBox.X+aBBox.Width, aBBox.Y+aBBox.Height);
}




void PaneGroup::ActivatePanes (void)
{
    vector<PaneDescriptor>::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane)
    {
        iPane->mpPaneDescriptor->SetActivationState(true);
    }
}




void PaneGroup::DeactivatePanes (void)
{
    vector<PaneDescriptor>::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane)
    {
        iPane->mpPaneDescriptor->SetActivationState(false);
    }
}




void PaneGroup::ShowPanes (void)
{
    vector<PaneDescriptor>::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane)
    {
        iPane->mpPaneDescriptor->mxBorderWindow->setVisible(sal_True);
        iPane->mpPaneDescriptor->mxContentWindow->setVisible(sal_True);
    }
}




void PaneGroup::HidePanes (void)
{
    vector<PaneDescriptor>::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane)
    {
        iPane->mpPaneDescriptor->mxBorderWindow->setVisible(sal_False);
        iPane->mpPaneDescriptor->mxContentWindow->setVisible(sal_False);
    }
}




//===== PaneDescriptor ========================================================

PaneDescriptor::PaneDescriptor (const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor)
    : mpPaneDescriptor(rpDescriptor),
      mnLeft(rpDescriptor->mnLeft),
      mnTop(rpDescriptor->mnTop),
      mnRight(rpDescriptor->mnRight),
      mnBottom(rpDescriptor->mnBottom)
{
}




void PaneDescriptor::Restore (void) const
{
    mpPaneDescriptor->mnLeft = mnLeft;
    mpPaneDescriptor->mnTop = mnTop;
    mpPaneDescriptor->mnRight = mnRight;
    mpPaneDescriptor->mnBottom = mnBottom;
}




//===== MultiAnimation ========================================================

MultiAnimation::MultiAnimation (const sal_uInt32 nDuration)
    : PresenterAnimation(0, nDuration, 1000/50),
      maAnimations()
{
}




void MultiAnimation::AddAnimation (const Animation& rAnimation)
{
    maAnimations.push_back(rAnimation);
}




void MultiAnimation::Run (const double nProgress, const sal_uInt64 nCurrentTime)
{
    (void)nCurrentTime;
    vector<Animation>::const_iterator iAnimation (maAnimations.begin());
    vector<Animation>::const_iterator iEnd (maAnimations.end());
    for ( ; iAnimation!=iEnd; ++iAnimation)
        (*iAnimation)(nProgress);
}




//===== functors ==============================================================

void InterpolatePosition (
    const ::boost::function<void(geometry::RealPoint2D)>& rSetter,
    double nP,
    const geometry::RealPoint2D rInitialBox,
    const geometry::RealPoint2D rFinalBox)
{
    const double nQ (1 - nP);

    OSL_TRACE("InterpolatePosition %f\n", nP);
    rSetter(
        geometry::RealPoint2D(
            nQ * rInitialBox.X + nP * rFinalBox.X,
            nQ * rInitialBox.Y + nP * rFinalBox.Y));
}




template<typename T>
    void InterpolateValue (
        const ::boost::function<void(T)>& rSetter,
        double nP,
        const T aInitialValue,
        const T aFinalValue)
{
    const double nQ (1 - nP);

    rSetter(T(nQ * aInitialValue + nP * aFinalValue));
}




void SpriteTransform(
    const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
    const Reference<XResourceId>& rxPaneId,
    const Reference<awt::XWindow>& rxSpriteOwnerWindow,
    const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager,
    const bool bAppear,
    const double nX,
    const double nInitialTop,
    const double nFinalTop,
    const double nP)
{
    OSL_ASSERT(rpPaintManager.get()!=NULL);

    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        rpPaneContainer->FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL
        && ! pDescriptor->maSpriteProvider.empty()
        && pDescriptor->mxBorderWindow.is())
    {
        ::boost::shared_ptr<PresenterSprite> pSprite (pDescriptor->maSpriteProvider());
        if (pSprite.get())
        {
            // There seems to be a problem with sprites not correctly
            // invalidating the background when being transformed.  As a
            // workaround invalidate the background in the bounding box of
            // the sprite before the transformation.
            rpPaintManager->Invalidate(
                rxSpriteOwnerWindow,
                awt::Rectangle(
                    sal::static_int_cast<sal_Int32>(pSprite->GetLocation().X),
                    sal::static_int_cast<sal_Int32>(pSprite->GetLocation().Y),
                    sal::static_int_cast<sal_Int32>(pSprite->GetSize().Width),
                    sal::static_int_cast<sal_Int32>(pSprite->GetSize().Height)));

            const double nYScale (bAppear ? nP : 1-nP);
            pSprite->Transform(geometry::AffineMatrix2D(
                1, 0, 0,
                0, nYScale, 0));
            pSprite->MoveTo(
                geometry::RealPoint2D(nX, nYScale*nFinalTop + (1-nYScale)*nInitialTop));
            pSprite->Show();

            pDescriptor->mxBorderWindow->setVisible(sal_True);
        }
    }
}




void SpritePaneMove (
    const rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
    const Reference<XResourceId>& rxPaneId,
    const geometry::RealPoint2D& rLocation)
{
    PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
        rpPaneContainer->FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL
        && ! pDescriptor->maSpriteProvider.empty()
        && pDescriptor->mxBorderWindow.is())
    {
        ::boost::shared_ptr<PresenterSprite> pSprite (pDescriptor->maSpriteProvider());
        if (pSprite.get() != NULL)
        {
            pDescriptor->mxBorderWindow->setVisible(sal_True);
            pSprite->MoveTo(rLocation);
        }
    }
}




geometry::RealPoint2D GetLocation (const geometry::RealRectangle2D& rBox)
{
    return geometry::RealPoint2D(rBox.X1, rBox.Y1);
}




geometry::RealSize2D GetSize (const geometry::RealRectangle2D& rBox)
{
    return geometry::RealSize2D(rBox.X2-rBox.X1, rBox.Y2-rBox.Y1);
}

} // end of anonymous namespace




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