/************************************************************************* * * 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: PresenterWindowManager.cxx,v $ * * $Revision: 1.7 $ * * 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 "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 #include #include #include #include #include #include #include #include #include #include #include #include #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; #undef ENABLE_PANE_RESIZING #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& rxConfigurationController, const Reference& rxWindow, const Reference& rxCanvas, const ::boost::shared_ptr& 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 mxConfigurationController; ::boost::shared_ptr mpAnimator; ::boost::shared_ptr mpSprite; Reference mxCanvas; }; } //===== PresenterWindowManager ================================================ PresenterWindowManager::PresenterWindowManager ( const Reference& rxContext, const ::rtl::Reference& rpPaneContainer, const ::rtl::Reference& rpPresenterController) : PresenterWindowManagerInterfaceBase(m_aMutex), mxComponentContext(rxContext), mpPresenterController(rpPresenterController), mxParentWindow(), mxParentCanvas(), mxPaneBorderManager(), mpPaneBorderPainter(), mpPaneContainer(rpPaneContainer), mbIsLayoutPending(true), mbIsLayouting(false), mpTheme(), mpBackgroundBitmap(), mxScaledBackgroundBitmap(), maPaneBackgroundColor(), mxClipPolygon(), meLayoutMode(Generic), mbIsSlideSorterActive(false), mbIsHelpViewActive(false), maLayoutListeners(), mbIsMouseClickPending(false) { UpdateWindowList(); } PresenterWindowManager::~PresenterWindowManager (void) { } void SAL_CALL PresenterWindowManager::disposing (void) { NotifyDisposing(); SetParentPane(NULL); Reference 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& 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 xPeer (mxParentWindow, UNO_QUERY); if (xPeer.is()) xPeer->setBackground(util::Color(0xff000000)); } } Reference PresenterWindowManager::GetParentWidnow (void) const { return mxParentWindow; } void PresenterWindowManager::SetTheme (const ::boost::shared_ptr& 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 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& 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& 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(nX), ::sal::static_int_cast(nY), ::sal::static_int_cast(nWidth), ::sal::static_int_cast(nHeight), awt::PosSize::POSSIZE); } } void PresenterWindowManager::SetPaneBorderPainter ( const ::rtl::Reference& rPainter) { mpPaneBorderPainter = rPainter; } //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent) throw (RuntimeException) { ThrowIfDisposed(); if (rEvent.Source == mxParentWindow) { Layout(); } else { Reference 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 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 xSpriteCanvas (mxParentCanvas, UNO_QUERY); // if (xSpriteCanvas.is()) // xSpriteCanvas->updateScreen(sal_False); } } catch (RuntimeException&) { OSL_ASSERT(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; } 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 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 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(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==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; mpPresenterController->RequestViews( mbIsSlideSorterActive, meLayoutMode==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; mpPresenterController->RequestViews( mbIsSlideSorterActive, meLayoutMode==Notes, mbIsHelpViewActive); Layout(); NotifyLayoutModeChange(); } } bool PresenterWindowManager::IsHelpViewActive (void) const { return mbIsHelpViewActive; } void PresenterWindowManager::AddLayoutListener ( const Reference& rxListener) { maLayoutListeners.push_back(rxListener); } void PresenterWindowManager::RemoveLayoutListener ( const Reference& 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 Standard: default: LayoutStandardMode(); break; case Notes: LayoutNotesMode(); break; case Generic: LayoutUnknownMode(); 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(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(static_cast(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(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& 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 xDevice (mxParentCanvas->getDevice()); if ( ! xDevice.is()) return; // Create a polygon for the background and for clipping. Reference 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(4), rendering::CompositeOperation::SOURCE); // Paint the background. if (mpBackgroundBitmap.get() != NULL) { ProvideBackgroundBitmap(); if (mxScaledBackgroundBitmap.is()) { Sequence 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 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(xBitmap, UNO_QUERY); } } } } Reference 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 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 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 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 xComponent (mxPaneBorderManager, UNO_QUERY); if (xComponent.is()) xComponent->dispose(); Reference xFactory (mxComponentContext->getServiceManager()); if (xFactory.is()) { Sequence aArguments (1 + mpPaneContainer->maPanes.size()*2); sal_Int32 nIndex (0); aArguments[nIndex++] = Any(mxParentWindow); for (sal_uInt32 nPaneIndex=0; nPaneIndexmaPanes.size(); ++nPaneIndex) { if ( ! mpPaneContainer->maPanes[nPaneIndex]->mbIsActive) continue; const Reference xBorderWindow ( mpPaneContainer->maPanes[nPaneIndex]->mxBorderWindow); const Reference xContentWindow ( mpPaneContainer->maPanes[nPaneIndex]->mxContentWindow); const Reference 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 pManager ( new PresenterPaneBorderManager ( mxComponentContext, mpPresenterController)); pManager->initialize(aArguments); mxPaneBorderManager = Reference(static_cast(pManager.get())); } } catch (RuntimeException&) { } #endif } void PresenterWindowManager::Invalidate (void) { mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow); } Reference PresenterWindowManager::GetParentWindow (void) const { return mxParentWindow; } Reference 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(static_cast(this))); } } namespace { //===== ModeChangeAnimation =================================================== class ModeChangeAnimation : public PresenterAnimation { public: ModeChangeAnimation ( const ::boost::shared_ptr& rpSprite, const Reference& 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 mpSprite; Reference mxCanvas; }; ModeChangeAnimationStarter::ModeChangeAnimationStarter ( const Reference& rxConfigurationController, const Reference& rxWindow, const Reference& rxCanvas, const ::boost::shared_ptr& 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 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(4), rendering::CompositeOperation::SOURCE); Reference 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