/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: PresenterPaneAnimator.cxx,v $ * * $Revision: 1.6 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 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 #include #include #include #include #include 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, public PresenterPaneAnimator { public: PresenterPaneAnimatorBase ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& rpPresenterController, const bool bAnimate, const EndActions& rShowEndActions, const EndActions& rEndEndActions); virtual ~PresenterPaneAnimatorBase (void); typedef ::std::vector< ::boost::function > EndOperators; void ActivatePanes (void); void ActivatePane ( const css::uno::Reference& rxPaneId); void RestoreFrozenWindows (void); void FreezePanes (const Reference& rxCanvas); protected: ::rtl::Reference mpPresenterController; ::rtl::Reference mpPaneContainer; ::rtl::Reference mpWindowManager; ::std::vector< ::boost::shared_ptr > maPaneGroups; css::uno::Reference mxCenterPaneId; bool mbDoAnimation; EndActions maShowEndActions; EndActions maHideEndActions; void DeactivatePanes (void); void ResizePane ( const css::uno::Reference& rxPaneId, const geometry::RealRectangle2D& rBox); void DeactivatePane ( const css::uno::Reference& rxPaneId); }; class UnfoldInCenterAnimator : public PresenterPaneAnimatorBase { public: UnfoldInCenterAnimator ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& 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& rxPaneId, const ::rtl::Reference& 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 maNewPaneSprite; geometry::RealRectangle2D maCenterPaneBox; void CreateShowAnimation ( const css::uno::Reference& rxPaneId, const EndOperators& rpEndOperators, const css::uno::Reference& rxSpriteCanvas, const bool bAnimate, const css::geometry::RealPoint2D& rStartLocation, const css::geometry::RealPoint2D& rEndLocation); }; class TransparentOverlayAnimator : public PresenterPaneAnimatorBase { public: TransparentOverlayAnimator( const css::uno::Reference& rxPaneId, const ::rtl::Reference& 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 Animation; MultiAnimation (const sal_uInt32 nDuration); void AddAnimation (const Animation& rAnimation); virtual void Run (const double nProgress, const sal_uInt64 nCurrentTime); private: vector maAnimations; }; class PaneGroup { public: PaneGroup (void); ~PaneGroup (void); void AddPane (const PresenterPaneContainer::SharedPaneDescriptor& rpPane); void CreateSubstitution (const Reference& rxCanvas); void ThawPanes (void); void Restore (void); ::boost::shared_ptr 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& rpWindowManager); void ActivatePanes (void); void DeactivatePanes (void); void HidePanes (void); void ShowPanes (void); private: vector maPanes; awt::Rectangle maOriginalBoundingBox; css::geometry::RealRectangle2D maCurrentBoundingBox; ::boost::shared_ptr mpSubstitution; }; typedef ::boost::shared_ptr SharedPaneGroup; void InterpolatePosition ( const ::boost::function& rSetter, double nP, const geometry::RealPoint2D rInitialBox, const geometry::RealPoint2D rFinalBox); template void InterpolateValue ( const ::boost::function& rSetter, double nP, const T aInitialValue, const T aFinalValue); void SpriteTransform( const rtl::Reference& rpPaneContainer, const Reference& rxPaneId, const Reference& rxSpriteOwnerWindow, const ::boost::shared_ptr& rpPaintManager, const bool bAppear, const double nX, const double nInitialTop, const double nFinalTop, const double nP); void SpritePaneMove ( const rtl::Reference& rpPaneContainer, const Reference& 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 CreateUnfoldInCenterAnimator ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& rpPresenterController, const bool bAnimate, const EndActions& rShowEndActions, const EndActions& rEndEndActions) { return ::boost::shared_ptr( new UnfoldInCenterAnimator(rxPaneId, rpPresenterController, bAnimate, rShowEndActions, rEndEndActions)); } ::boost::shared_ptr CreateMoveInFromBottomAnimator ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& rpPresenterController, const bool bAnimate, const EndActions& rShowEndActions, const EndActions& rEndEndActions) { return ::boost::shared_ptr( new MoveInFromBottomAnimator(rxPaneId, rpPresenterController, bAnimate, rShowEndActions, rEndEndActions)); } ::boost::shared_ptr CreateTransparentOverlay ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& rpPresenterController, const bool bAnimate, const EndActions& rShowEndActions, const EndActions& rEndEndActions) { return ::boost::shared_ptr( new TransparentOverlayAnimator(rxPaneId, rpPresenterController, bAnimate, rShowEndActions, rEndEndActions)); } //===== PresenterPaneAnimator ================================================= namespace { PresenterPaneAnimatorBase::PresenterPaneAnimatorBase ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& 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& rxCanvas) { ::std::vector::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::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::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& 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::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& rxPaneId) { PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( mpPaneContainer->FindPaneId(rxPaneId)); if (pDescriptor.get() != NULL) pDescriptor->SetActivationState(true); } void PresenterPaneAnimatorBase::DeactivatePane ( const Reference& rxPaneId) { PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( mpPaneContainer->FindPaneId(rxPaneId)); if (pDescriptor.get() != NULL) pDescriptor->SetActivationState(false); } //===== UnfoldInCenterAnimator ================================================ UnfoldInCenterAnimator::UnfoldInCenterAnimator ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& 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 xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); if ( ! xParentWindow.is()) return; Reference xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); if ( ! xCanvas.is()) return; Reference xParentBitmap (xCanvas, UNO_QUERY); if ( ! xParentBitmap.is()) return; Reference 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 pMultiAnimation ( new MultiAnimation(mbDoAnimation ? 500 : 0)); // Animate the pane group sprites to be moved up or down. vector::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 pAnimator (mpPresenterController->GetAnimator()); OSL_ASSERT(pAnimator.get()!=NULL); pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); mpWindowManager->Update(); } void UnfoldInCenterAnimator::HidePane (void) { OSL_ASSERT(mpWindowManager.get()!=NULL); Reference xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); if ( ! xParentWindow.is()) return; DeactivatePanes(); DeactivatePane(mxCenterPaneId); ::boost::shared_ptr 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(4), rendering::CompositeOperation::SOURCE); // Animate the uppder and lower window bitmaps. Reference xSpriteCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); ::boost::shared_ptr pMultiAnimation (new MultiAnimation(mbDoAnimation ? 500 : 1)); vector::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& rxPaneId, const ::rtl::Reference& 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 xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); if ( ! xParentWindow.is()) return; Reference xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); if ( ! xCanvas.is()) return; Reference xParentBitmap (xCanvas, UNO_QUERY); if ( ! xParentBitmap.is()) return; Reference 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 xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); if ( ! xParentWindow.is()) return; Reference xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); if ( ! xCanvas.is()) return; DeactivatePanes(); DeactivatePane(mxCenterPaneId); SharedPaneGroup aPanes (maPaneGroups[0]); aPanes->ShowPanes(); ::boost::shared_ptr 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 pAnimator (mpPresenterController->GetAnimator()); pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); } void MoveInFromBottomAnimator::CreateShowAnimation ( const Reference& rxPaneId, const EndOperators& rEndOperators, const Reference& rxSpriteCanvas, const bool bAnimate, const geometry::RealPoint2D& rStartLocation, const geometry::RealPoint2D& rEndLocation) { // Animate the uppder and lower window bitmaps. ::boost::shared_ptr pMultiAnimation (new MultiAnimation(bAnimate ? 500 : 0)); // Animate new pane to move in from the buttom. 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 pAnimator (mpPresenterController->GetAnimator()); OSL_ASSERT(pAnimator.get()!=NULL); pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); } //===== TransparentOverlayAnimator ============================================ TransparentOverlayAnimator::TransparentOverlayAnimator ( const css::uno::Reference& rxPaneId, const ::rtl::Reference& 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 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( 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 xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); Reference 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 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(4), rendering::CompositeOperation::SOURCE); PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x80808080)); Reference 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& rxCanvas) { // Get the bitmap of the background. Reference 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(4), rendering::CompositeOperation::SOURCE); Reference xSpriteCanvas (mpSubstitution->GetCanvas()); if (xSpriteCanvas.is()) xSpriteCanvas->drawBitmap(xBackgroundBitmap, aViewState, aRenderState); } void PaneGroup::Restore (void) { vector::iterator iPane; for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) { iPane->Restore(); } } ::boost::shared_ptr 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& rpWindowManager ) { awt::Rectangle aBBox; vector::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::iterator iPane; for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) { iPane->mpPaneDescriptor->SetActivationState(true); } } void PaneGroup::DeactivatePanes (void) { vector::iterator iPane; for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) { iPane->mpPaneDescriptor->SetActivationState(false); } } void PaneGroup::ShowPanes (void) { vector::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::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::const_iterator iAnimation (maAnimations.begin()); vector::const_iterator iEnd (maAnimations.end()); for ( ; iAnimation!=iEnd; ++iAnimation) (*iAnimation)(nProgress); } //===== functors ============================================================== void InterpolatePosition ( const ::boost::function& 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 void InterpolateValue ( const ::boost::function& 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& rpPaneContainer, const Reference& rxPaneId, const Reference& rxSpriteOwnerWindow, const ::boost::shared_ptr& 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 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(pSprite->GetLocation().X), sal::static_int_cast(pSprite->GetLocation().Y), sal::static_int_cast(pSprite->GetSize().Width), sal::static_int_cast(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& rpPaneContainer, const Reference& rxPaneId, const geometry::RealPoint2D& rLocation) { PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( rpPaneContainer->FindPaneId(rxPaneId)); if (pDescriptor.get() != NULL && ! pDescriptor->maSpriteProvider.empty() && pDescriptor->mxBorderWindow.is()) { ::boost::shared_ptr 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