/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * 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 "PresenterToolBar.hxx" #include "PresenterBitmapContainer.hxx" #include "PresenterCanvasHelper.hxx" #include "PresenterComponent.hxx" #include "PresenterGeometryHelper.hxx" #include "PresenterPaintManager.hxx" #include "PresenterPaneBase.hxx" #include "PresenterPaneFactory.hxx" #include "PresenterTimer.hxx" #include "PresenterWindowManager.hxx" #include #include #include #include #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; #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) namespace sdext { namespace presenter { static const sal_Int32 gnGapSize (20); static const sal_Int32 gnMinimalSeparatorSize (20); static const sal_Int32 gnSeparatorInset (0); namespace { class Text { public: Text (void); Text (const Text& rText); Text ( const OUString& rsText, const PresenterTheme::SharedFontDescriptor& rpFont); void SetText (const OUString& rsText); OUString GetText (void) const; PresenterTheme::SharedFontDescriptor GetFont (void) const; void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState, const awt::Rectangle& rBoundingBox, const awt::Point& rOffset); geometry::RealRectangle2D GetBoundingBox ( const Reference& rxCanvas); private: OUString msText; PresenterTheme::SharedFontDescriptor mpFont; }; class ElementMode : private ::boost::noncopyable { public: ElementMode (void); SharedBitmapDescriptor mpIcon; OUString msAction; Text maText; void ReadElementMode ( const Reference& rxProperties, const ::rtl::OUString& rsModeName, ::boost::shared_ptr& rpDefaultMode, ::sdext::presenter::PresenterToolBar::Context& rContext); }; typedef ::boost::shared_ptr SharedElementMode; } // end of anonymous namespace class PresenterToolBar::Context : private ::boost::noncopyable { public: ::rtl::OUString msBasePath; Reference mxPresenterHelper; css::uno::Reference mxCanvas; }; //===== PresenterToolBar::Element ============================================= namespace { typedef cppu::WeakComponentImplHelper2< css::document::XEventListener, css::frame::XStatusListener > ElementInterfaceBase; class Element : private ::cppu::BaseMutex, private ::boost::noncopyable, public ElementInterfaceBase { public: Element (const ::rtl::Reference& rpToolBar); virtual ~Element (void); virtual void SAL_CALL disposing (void); virtual void SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode); virtual void CurrentSlideHasChanged (void); virtual void SetLocation (const awt::Point& rLocation); virtual void SetSize (const geometry::RealSize2D& rSize); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState) = 0; awt::Size GetBoundingSize ( const Reference& rxCanvas); awt::Rectangle GetBoundingBox (void) const; virtual bool SetState (const bool bIsOver, const bool bIsPressed); virtual void Invalidate (const bool bSynchronous = true); virtual bool IsOutside (const awt::Rectangle& rBox); virtual bool IsFilling (void) const; void UpdateState (void); OUString GetAction (void) const; // lang::XEventListener virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) throw(css::uno::RuntimeException); // document::XEventListener virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) throw(css::uno::RuntimeException); // frame::XStatusListener virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent) throw(css::uno::RuntimeException); protected: ::rtl::Reference mpToolBar; awt::Point maLocation; awt::Size maSize; SharedElementMode mpNormal; SharedElementMode mpMouseOver; SharedElementMode mpSelected; SharedElementMode mpDisabled; SharedElementMode mpMode; bool mbIsOver; bool mbIsPressed; bool mbIsSelected; virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas) = 0; bool IsEnabled (void) const; void SetEnabledState (const bool bIsEnabled); private: bool mbIsEnabled; }; } // end of anonymous namespace class PresenterToolBar::ElementContainerPart : public ::std::vector > { }; //===== Button ================================================================ namespace { class Button : public Element { public: static ::rtl::Reference Create ( const ::rtl::Reference& rpToolBar); virtual ~Button (void); virtual void SAL_CALL disposing (void); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState); // lang::XEventListener virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) throw(css::uno::RuntimeException); protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas); private: bool mbIsListenerRegistered; Button (const ::rtl::Reference& rpToolBar); void Initialize (void); void PaintIcon ( const Reference& rxCanvas, const sal_Int32 nTextHeight, const rendering::ViewState& rViewState); PresenterBitmapDescriptor::Mode GetMode (void) const; }; //===== Label ================================================================= class Label : public Element { public: Label (const ::rtl::Reference& rpToolBar); void SetText (const OUString& rsText); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState); virtual bool SetState (const bool bIsOver, const bool bIsPressed); protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas); }; // Some specialized controls. class ProgressLabel : public Label { public: ProgressLabel (const ::rtl::Reference& rpToolBar); virtual void CurrentSlideHasChanged (void); }; class TimeFormatter { public: TimeFormatter (void); OUString FormatTime (const oslDateTime& rTime); private: bool mbIs24HourFormat; bool mbIsAmPmFormat; bool mbIsShowSeconds; }; class TimeLabel : public Label { public: void ConnectToTimer (void); virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0; protected: TimeLabel(const ::rtl::Reference& rpToolBar); using Element::disposing; virtual void SAL_CALL disposing (void); private: class Listener : public PresenterClockTimer::Listener { public: Listener (const ::rtl::Reference& rxLabel) : mxLabel(rxLabel) {} virtual ~Listener (void) {} virtual void TimeHasChanged (const oslDateTime& rCurrentTime) { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); } private: ::rtl::Reference mxLabel; }; ::boost::shared_ptr mpListener; }; class CurrentTimeLabel : public TimeLabel { public: static ::rtl::Reference Create ( const ::rtl::Reference& rpToolBar); virtual void SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode); private: TimeFormatter maTimeFormatter; CurrentTimeLabel (const ::rtl::Reference& rpToolBar); virtual ~CurrentTimeLabel (void); virtual void TimeHasChanged (const oslDateTime& rCurrentTime); }; class PresentationTimeLabel : public TimeLabel { public: static ::rtl::Reference Create ( const ::rtl::Reference& rpToolBar); virtual void SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode); private: TimeFormatter maTimeFormatter; TimeValue maStartTimeValue; PresentationTimeLabel (const ::rtl::Reference& rpToolBar); virtual ~PresentationTimeLabel (void); virtual void TimeHasChanged (const oslDateTime& rCurrentTime); }; class VerticalSeparator : public Element { public: explicit VerticalSeparator (const ::rtl::Reference& rpToolBar); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState); virtual bool IsFilling (void) const; protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas); }; class HorizontalSeparator : public Element { public: explicit HorizontalSeparator (const ::rtl::Reference& rpToolBar); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState); virtual bool IsFilling (void) const; protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas); }; } // end of anonymous namespace //===== PresenterToolBar ====================================================== PresenterToolBar::PresenterToolBar ( const Reference& rxContext, const css::uno::Reference& rxWindow, const css::uno::Reference& rxCanvas, const ::rtl::Reference& rpPresenterController, const Anchor eAnchor) : PresenterToolBarInterfaceBase(m_aMutex), mxComponentContext(rxContext), maElementContainer(), mpCurrentContainerPart(), mxWindow(rxWindow), mxCanvas(rxCanvas), mxSlideShowController(), mxCurrentSlide(), mpPresenterController(rpPresenterController), mbIsLayoutPending(false), meAnchor(eAnchor), maBoundingBox(), maMinimalSize() { } void PresenterToolBar::Initialize ( const ::rtl::OUString& rsConfigurationPath) { try { CreateControls(rsConfigurationPath); if (mxWindow.is()) { mxWindow->addWindowListener(this); mxWindow->addPaintListener(this); mxWindow->addMouseListener(this); mxWindow->addMouseMotionListener(this); Reference xPeer (mxWindow, UNO_QUERY); if (xPeer.is()) xPeer->setBackground(util::Color(0xff000000)); mxWindow->setVisible(sal_True); } mxSlideShowController = mpPresenterController->GetSlideShowController(); UpdateSlideNumber(); mbIsLayoutPending = true; } catch (RuntimeException&) { mpCurrentContainerPart.reset(); maElementContainer.clear(); throw; } } PresenterToolBar::~PresenterToolBar (void) { } void SAL_CALL PresenterToolBar::disposing (void) { if (mxWindow.is()) { mxWindow->removeWindowListener(this); mxWindow->removePaintListener(this); mxWindow->removeMouseListener(this); mxWindow->removeMouseMotionListener(this); mxWindow = NULL; } // Dispose tool bar elements. ElementContainer::iterator iPart (maElementContainer.begin()); ElementContainer::const_iterator iEnd (maElementContainer.end()); for ( ; iPart!=iEnd; ++iPart) { OSL_ASSERT(iPart->get()!=NULL); ElementContainerPart::iterator iElement ((*iPart)->begin()); ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); for ( ; iElement!=iPartEnd; ++iElement) { if (iElement->get() != NULL) { ::rtl::Reference pElement (*iElement); Reference xComponent ( static_cast(pElement.get()), UNO_QUERY); if (xComponent.is()) xComponent->dispose(); } } } mpCurrentContainerPart.reset(); maElementContainer.clear(); } void PresenterToolBar::InvalidateArea ( const awt::Rectangle& rRepaintBox, const bool bSynchronous) { mpPresenterController->GetPaintManager()->Invalidate( mxWindow, rRepaintBox, bSynchronous); } sal_Int32 PresenterToolBar::GetCurrentSlideIndex (void) { if (mxSlideShowController.is()) return mxSlideShowController->getCurrentSlideIndex(); else return -1; } sal_Int32 PresenterToolBar::GetSlideCount (void) { if (mxSlideShowController.is()) return mxSlideShowController->getSlideCount(); else return 0; } void PresenterToolBar::RequestLayout (void) { mbIsLayoutPending = true; mpPresenterController->GetPaintManager()->Invalidate(mxWindow); } geometry::RealSize2D PresenterToolBar::GetSize (void) { if (mbIsLayoutPending) Layout(mxCanvas); return geometry::RealSize2D( maBoundingBox.X2 - maBoundingBox.X1, maBoundingBox.Y2 - maBoundingBox.Y1); } geometry::RealSize2D PresenterToolBar::GetMinimalSize (void) { if (mbIsLayoutPending) Layout(mxCanvas); return maMinimalSize; } ::rtl::Reference PresenterToolBar::GetPresenterController (void) const { return mpPresenterController; } Reference PresenterToolBar::GetWindow (void) const { return mxWindow; } Reference PresenterToolBar::GetComponentContext (void) const { return mxComponentContext; } //----- lang::XEventListener ------------------------------------------------- void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject) throw (RuntimeException) { if (rEventObject.Source == mxWindow) mxWindow = NULL; } //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent& rEvent) throw (RuntimeException) { (void)rEvent; mbIsLayoutPending = true; } void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent& rEvent) throw (RuntimeException) { (void)rEvent; } void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject& rEvent) throw (RuntimeException) { (void)rEvent; mbIsLayoutPending = true; } void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject& rEvent) throw (RuntimeException) { (void)rEvent; } //----- XPaintListener -------------------------------------------------------- void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent) throw (RuntimeException) { if ( ! mxCanvas.is()) return; if ( ! mbIsPresenterViewActive) return; const rendering::ViewState aViewState ( geometry::AffineMatrix2D(1,0,0, 0,1,0), PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice())); if (mbIsLayoutPending) Layout(mxCanvas); Paint(rEvent.UpdateRect, aViewState); // Make the back buffer visible. Reference xSpriteCanvas (mxCanvas, UNO_QUERY); if (xSpriteCanvas.is()) xSpriteCanvas->updateScreen(sal_False); } //----- XMouseListener -------------------------------------------------------- void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { CheckMouseOver(rEvent, true, true); } void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { CheckMouseOver(rEvent, true); } void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { CheckMouseOver(rEvent, true); } void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { CheckMouseOver(rEvent, false); } //----- XMouseMotionListener -------------------------------------------------- void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent) throw (css::uno::RuntimeException) { ThrowIfDisposed(); CheckMouseOver(rEvent, true); } void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent& rEvent) throw (css::uno::RuntimeException) { ThrowIfDisposed(); (void)rEvent; } //----- XDrawView ------------------------------------------------------------- void SAL_CALL PresenterToolBar::setCurrentPage (const Reference& rxSlide) throw (RuntimeException) { if (rxSlide != mxCurrentSlide) { mxCurrentSlide = rxSlide; UpdateSlideNumber(); } } Reference SAL_CALL PresenterToolBar::getCurrentPage (void) throw (RuntimeException) { return mxCurrentSlide; } //----------------------------------------------------------------------------- void PresenterToolBar::CreateControls ( const ::rtl::OUString& rsConfigurationPath) { if ( ! mxWindow.is()) return; // Expand the macro in the bitmap file names. PresenterConfigurationAccess aConfiguration ( mxComponentContext, OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"), PresenterConfigurationAccess::READ_ONLY); const OUString sBasePath (PresenterComponent::GetBasePath(mxComponentContext)); mpCurrentContainerPart.reset(new ElementContainerPart()); maElementContainer.clear(); maElementContainer.push_back(mpCurrentContainerPart); Reference xToolBarNode ( aConfiguration.GetConfigurationNode(rsConfigurationPath), UNO_QUERY); if (xToolBarNode.is()) { Reference xEntries ( PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, A2S("Entries")), UNO_QUERY); Context aContext; aContext.msBasePath = sBasePath; aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper(); aContext.mxCanvas = mxCanvas; if (xEntries.is() && aContext.mxPresenterHelper.is() && aContext.mxCanvas.is()) { PresenterConfigurationAccess::ForAll( xEntries, ::boost::bind(&PresenterToolBar::ProcessEntry, this, _2, ::boost::ref(aContext))); } } } void PresenterToolBar::ProcessEntry ( const Reference& rxProperties, Context& rContext) { if ( ! rxProperties.is()) return; // Type has to be present. OUString sType; if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Type")) >>= sType)) return; OUString sName; PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Name")) >>= sName; // Read mode specific values. SharedElementMode pNormalMode (new ElementMode()); SharedElementMode pMouseOverMode (new ElementMode()); SharedElementMode pSelectedMode (new ElementMode()); SharedElementMode pDisabledMode (new ElementMode()); pNormalMode->ReadElementMode(rxProperties, A2S("Normal"), pNormalMode, rContext); pMouseOverMode->ReadElementMode(rxProperties, A2S("MouseOver"), pNormalMode, rContext); pSelectedMode->ReadElementMode(rxProperties, A2S("Selected"), pNormalMode, rContext); pDisabledMode->ReadElementMode(rxProperties, A2S("Disabled"), pNormalMode, rContext); // Create new element. ::rtl::Reference pElement; if (sType.equalsAscii("Button")) pElement = Button::Create(this); else if (sType.equalsAscii("CurrentTimeLabel")) pElement = CurrentTimeLabel::Create(this); else if (sType.equalsAscii("PresentationTimeLabel")) pElement = PresentationTimeLabel::Create(this); else if (sType.equalsAscii("VerticalSeparator")) pElement = ::rtl::Reference(new VerticalSeparator(this)); else if (sType.equalsAscii("HorizontalSeparator")) pElement = ::rtl::Reference(new HorizontalSeparator(this)); else if (sType.equalsAscii("Label")) pElement = ::rtl::Reference(new Label(this)); else if (sType.equalsAscii("ChangeOrientation")) { mpCurrentContainerPart.reset(new ElementContainerPart()); maElementContainer.push_back(mpCurrentContainerPart); return; } if (pElement.is()) { pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode); pElement->UpdateState(); if (mpCurrentContainerPart.get() != NULL) mpCurrentContainerPart->push_back(pElement); } } void PresenterToolBar::Layout ( const Reference& rxCanvas) { if (maElementContainer.size() == 0) return; mbIsLayoutPending = false; const awt::Rectangle aWindowBox (mxWindow->getPosSize()); ElementContainer::iterator iPart; ElementContainer::iterator iEnd (maElementContainer.end()); ::std::vector aPartSizes (maElementContainer.size()); geometry::RealSize2D aTotalSize (0,0); bool bIsHorizontal (true); sal_Int32 nIndex; double nTotalHorizontalGap (0); sal_Int32 nGapCount (0); for (iPart=maElementContainer.begin(),nIndex=0; iPart!=iEnd; ++iPart,++nIndex) { geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, *iPart, bIsHorizontal)); // Remember the size of each part for later. aPartSizes[nIndex] = aSize; // Add gaps between elements. if ((*iPart)->size()>1 && bIsHorizontal) { nTotalHorizontalGap += ((*iPart)->size() - 1) * gnGapSize; nGapCount += (*iPart)->size()-1; } // Orientation changes for each part. bIsHorizontal = !bIsHorizontal; // Width is accumulated. aTotalSize.Width += aSize.Width; // Height is the maximum height of all parts. aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height); } // Add gaps between parts. if (maElementContainer.size() > 1) { nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize; nGapCount += maElementContainer.size()-1; } // Calculate the minimal size so that the window size of the tool bar // can be adapted accordingly. maMinimalSize = aTotalSize; maMinimalSize.Width += nTotalHorizontalGap; // Calculate the gaps between elements. double nGapWidth (0); if (nGapCount > 0) { if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width) nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width; nGapWidth = nTotalHorizontalGap / nGapCount; } // Determine the location of the left edge. double nX (0); switch (meAnchor) { case Left : nX = 0; break; case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break; case Right: nX = aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap; break; } // Place the parts. double nY ((aWindowBox.Height - aTotalSize.Height) / 2); bIsHorizontal = true; maBoundingBox.X1 = nX; maBoundingBox.Y1 = nY; maBoundingBox.X2 = nX + aTotalSize.Width + nTotalHorizontalGap; maBoundingBox.Y2 = nY + aTotalSize.Height; for (iPart=maElementContainer.begin(), nIndex=0; iPart!=iEnd; ++iPart,++nIndex) { geometry::RealRectangle2D aBoundingBox( nX, nY, nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height); // Add space for gaps between elements. if ((*iPart)->size() > 1) if (bIsHorizontal) aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth; LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal); bIsHorizontal = !bIsHorizontal; nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth; } // The whole window has to be repainted. mpPresenterController->GetPaintManager()->Invalidate(mxWindow); } geometry::RealSize2D PresenterToolBar::CalculatePartSize ( const Reference& rxCanvas, const SharedElementContainerPart& rpPart, const bool bIsHorizontal) { geometry::RealSize2D aTotalSize (0,0); if (mxWindow.is()) { const awt::Rectangle aWindowBox (mxWindow->getPosSize()); // Calculate the summed width of all elements. ElementContainerPart::const_iterator iElement; for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement) { if (iElement->get() == NULL) continue; const awt::Size aBSize ((*iElement)->GetBoundingSize(rxCanvas)); if (bIsHorizontal) { aTotalSize.Width += aBSize.Width; if (aBSize.Height > aTotalSize.Height) aTotalSize.Height = aBSize.Height; } else { aTotalSize.Height += aBSize.Height; if (aBSize.Width > aTotalSize.Width) aTotalSize.Width = aBSize.Width; } } } return aTotalSize; } void PresenterToolBar::LayoutPart ( const Reference& rxCanvas, const SharedElementContainerPart& rpPart, const geometry::RealRectangle2D& rBoundingBox, const geometry::RealSize2D& rPartSize, const bool bIsHorizontal) { double nGap (0); if (rpPart->size() > 1) { if (bIsHorizontal) nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1); else nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1); } // Place the elements. double nX (rBoundingBox.X1); double nY (rBoundingBox.Y1); ElementContainerPart::const_iterator iElement; ElementContainerPart::const_iterator iEnd (rpPart->end()); for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement) { if (iElement->get() == NULL) continue; const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas)); if (bIsHorizontal) { if ((*iElement)->IsFilling()) { nY = rBoundingBox.Y1; (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1)); } else nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2; (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY))); nX += aElementSize.Width + nGap; } else { if ((*iElement)->IsFilling()) { nX = rBoundingBox.X1; (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height)); } else nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2; (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY))); nY += aElementSize.Height + nGap; } } } void PresenterToolBar::Paint ( const awt::Rectangle& rUpdateBox, const rendering::ViewState& rViewState) { OSL_ASSERT(mxCanvas.is()); ElementContainer::iterator iPart; ElementContainer::const_iterator iEnd (maElementContainer.end()); for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart) { ElementContainerPart::iterator iElement; ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement) { if (iElement->get() != NULL) { if ( ! (*iElement)->IsOutside(rUpdateBox)) (*iElement)->Paint(mxCanvas, rViewState); } } } } void PresenterToolBar::UpdateSlideNumber (void) { if( mxSlideShowController.is() ) { ElementContainer::iterator iPart; ElementContainer::const_iterator iEnd (maElementContainer.end()); for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart) { ElementContainerPart::iterator iElement; ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement) { if (iElement->get() != NULL) (*iElement)->CurrentSlideHasChanged(); } } } } void PresenterToolBar::CheckMouseOver ( const css::awt::MouseEvent& rEvent, const bool bOverWindow, const bool bMouseDown) { ElementContainer::iterator iPart; ElementContainer::const_iterator iEnd (maElementContainer.end()); for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart) { ElementContainerPart::iterator iElement; ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement) { if (iElement->get() == NULL) continue; awt::Rectangle aBox ((*iElement)->GetBoundingBox()); const bool bIsOver = bOverWindow && aBox.X <= rEvent.X && aBox.Width+aBox.X-1 >= rEvent.X && aBox.Y <= rEvent.Y && aBox.Height+aBox.Y-1 >= rEvent.Y; (*iElement)->SetState( bIsOver, bIsOver && rEvent.Buttons!=0 && bMouseDown && rEvent.ClickCount>0); } } } void PresenterToolBar::ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose) { throw lang::DisposedException ( OUString(RTL_CONSTASCII_USTRINGPARAM( "PresenterToolBar has already been disposed")), const_cast(static_cast(this))); } } //===== PresenterToolBarView ================================================== PresenterToolBarView::PresenterToolBarView ( const Reference& rxContext, const Reference& rxViewId, const Reference& rxController, const ::rtl::Reference& rpPresenterController) : PresenterToolBarViewInterfaceBase(m_aMutex), mxPane(), mxViewId(rxViewId), mxWindow(), mxCanvas(), mpPresenterController(rpPresenterController), mxSlideShowController(rpPresenterController->GetSlideShowController()), mpToolBar() { try { Reference xCM (rxController, UNO_QUERY_THROW); Reference xCC(xCM->getConfigurationController(),UNO_QUERY_THROW); mxPane = Reference(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); mxWindow = mxPane->getWindow(); mxCanvas = mxPane->getCanvas(); mpToolBar = new PresenterToolBar( rxContext, mxWindow, mxCanvas, rpPresenterController, PresenterToolBar::Center); mpToolBar->Initialize(A2S("PresenterScreenSettings/ToolBars/ToolBar")); if (mxWindow.is()) { mxWindow->addPaintListener(this); Reference xPeer (mxWindow, UNO_QUERY); if (xPeer.is()) xPeer->setBackground(util::Color(0xff000000)); mxWindow->setVisible(sal_True); } } catch (RuntimeException&) { mxViewId = NULL; throw; } } PresenterToolBarView::~PresenterToolBarView (void) { } void SAL_CALL PresenterToolBarView::disposing (void) { Reference xComponent (static_cast(mpToolBar.get()), UNO_QUERY); mpToolBar = NULL; if (xComponent.is()) xComponent->dispose(); if (mxWindow.is()) { mxWindow->removePaintListener(this); mxWindow = NULL; } mxCanvas = NULL; mxViewId = NULL; mxPane = NULL; mpPresenterController = NULL; mxSlideShowController = NULL; } ::rtl::Reference PresenterToolBarView::GetPresenterToolBar (void) const { return mpToolBar; } //----- XPaintListener -------------------------------------------------------- void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent) throw (RuntimeException) { awt::Rectangle aWindowBox (mxWindow->getPosSize()); mpPresenterController->GetCanvasHelper()->Paint( mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), mxCanvas, rEvent.UpdateRect, awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height), awt::Rectangle()); } //----- lang::XEventListener ------------------------------------------------- void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject) throw (RuntimeException) { if (rEventObject.Source == mxWindow) mxWindow = NULL; } //----- XResourceId ----------------------------------------------------------- Reference SAL_CALL PresenterToolBarView::getResourceId (void) throw (RuntimeException) { return mxViewId; } sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly (void) throw (RuntimeException) { return false; } //----- XDrawView ------------------------------------------------------------- void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference& rxSlide) throw (RuntimeException) { Reference xToolBar (static_cast(mpToolBar.get()), UNO_QUERY); if (xToolBar.is()) xToolBar->setCurrentPage(rxSlide); } Reference SAL_CALL PresenterToolBarView::getCurrentPage (void) throw (RuntimeException) { return NULL; } //----------------------------------------------------------------------------- void PresenterToolBarView::ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose) { throw lang::DisposedException ( OUString(RTL_CONSTASCII_USTRINGPARAM( "PresenterToolBarView has already been disposed")), const_cast(static_cast(this))); } } //===== PresenterToolBar::Element ============================================= namespace { Element::Element ( const ::rtl::Reference& rpToolBar) : ElementInterfaceBase(m_aMutex), mpToolBar(rpToolBar), maLocation(), maSize(), mpNormal(), mpMouseOver(), mpSelected(), mpDisabled(), mpMode(), mbIsOver(false), mbIsPressed(false), mbIsSelected(false), mbIsEnabled(true) { if (mpToolBar.get() != NULL) { OSL_ASSERT(mpToolBar->GetPresenterController().is()); OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is()); } } Element::~Element (void) { } void Element::SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode) { mpNormal = rpNormalMode; mpMouseOver = rpMouseOverMode; mpSelected = rpSelectedMode; mpDisabled = rpDisabledMode; mpMode = rpNormalMode; } void Element::disposing (void) { } awt::Size Element::GetBoundingSize ( const Reference& rxCanvas) { maSize = CreateBoundingSize(rxCanvas); return maSize; } awt::Rectangle Element::GetBoundingBox (void) const { return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height); } void Element::CurrentSlideHasChanged (void) { UpdateState(); } void Element::SetLocation (const awt::Point& rLocation) { maLocation = rLocation; } void Element::SetSize (const geometry::RealSize2D& rSize) { maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height)); } bool Element::SetState ( const bool bIsOver, const bool bIsPressed) { bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed); bool bClicked (mbIsPressed && bIsOver && ! bIsPressed); mbIsOver = bIsOver; mbIsPressed = bIsPressed; // When the element is disabled then ignore mouse over or selection. // When the element is selected then ignore mouse over. if ( ! mbIsEnabled) mpMode = mpDisabled; else if (mbIsSelected) mpMode = mpSelected; else if (mbIsOver) mpMode = mpMouseOver; else mpMode = mpNormal; if (bClicked && mbIsEnabled) { if (mpMode.get() != NULL) { do { if (mpMode->msAction.getLength() <= 0) break; if (mpToolBar.get() == NULL) break; if (mpToolBar->GetPresenterController().get() == NULL) break; mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction); mpToolBar->RequestLayout(); } while (false); } } else if (bModified) { Invalidate(); } return bModified; } void Element::Invalidate (const bool bSynchronous) { OSL_ASSERT(mpToolBar.is()); mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous); } bool Element::IsOutside (const awt::Rectangle& rBox) { if (rBox.X >= maLocation.X+maSize.Width) return true; else if (rBox.Y >= maLocation.Y+maSize.Height) return true; else if (maLocation.X >= rBox.X+rBox.Width) return true; else if (maLocation.Y >= rBox.Y+rBox.Height) return true; else return false; } bool Element::IsEnabled (void) const { return mbIsEnabled; } void Element::SetEnabledState (const bool bIsEnabled) { mbIsEnabled = bIsEnabled; } bool Element::IsFilling (void) const { return false; } void Element::UpdateState (void) { OSL_ASSERT(mpToolBar.get() != NULL); OSL_ASSERT(mpToolBar->GetPresenterController().get() != NULL); if (mpMode.get() == NULL) return; util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction)); Reference xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL)); if (xDispatch.is()) { xDispatch->addStatusListener(this, aURL); xDispatch->removeStatusListener(this, aURL); } } //----- lang::XEventListener -------------------------------------------------- void SAL_CALL Element::disposing (const css::lang::EventObject& rEvent) throw(css::uno::RuntimeException) { (void)rEvent; } //----- document::XEventListener ---------------------------------------------- void SAL_CALL Element::notifyEvent (const css::document::EventObject& rEvent) throw(css::uno::RuntimeException) { (void)rEvent; UpdateState(); } //----- frame::XStatusListener ------------------------------------------------ void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent) throw(css::uno::RuntimeException) { bool bIsSelected (mbIsSelected); bool bIsEnabled (rEvent.IsEnabled); rEvent.State >>= bIsSelected; if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled) { mbIsEnabled = bIsEnabled; mbIsSelected = bIsSelected; SetState(mbIsOver, mbIsPressed); mpToolBar->RequestLayout(); } } } // end of anonymous namespace //===== ElementMode =========================================================== namespace { ElementMode::ElementMode (void) : mpIcon(), msAction(), maText() { } void ElementMode::ReadElementMode ( const Reference& rxElementProperties, const OUString& rsModeName, ::boost::shared_ptr& rpDefaultMode, ::sdext::presenter::PresenterToolBar::Context& rContext) { try { Reference xNode ( PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName), UNO_QUERY); Reference xProperties ( PresenterConfigurationAccess::GetNodeProperties(xNode, OUString())); if ( ! xProperties.is() && rpDefaultMode.get()!=NULL) { // The mode is not specified. Use the given, possibly empty, // default mode instead. mpIcon = rpDefaultMode->mpIcon; msAction = rpDefaultMode->msAction; maText = rpDefaultMode->maText; } // Read action. if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, A2S("Action")) >>= msAction)) if (rpDefaultMode.get()!=NULL) msAction = rpDefaultMode->msAction; // Read text and font OUString sText (rpDefaultMode.get()!=NULL ? rpDefaultMode->maText.GetText() : OUString()); PresenterConfigurationAccess::GetProperty(xProperties, A2S("Text")) >>= sText; Reference xFontNode ( PresenterConfigurationAccess::GetProperty(xProperties, A2S("Font")), UNO_QUERY); PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont( xFontNode, A2S(""), rpDefaultMode.get()!=NULL ? rpDefaultMode->maText.GetFont() : PresenterTheme::SharedFontDescriptor())); maText = Text(sText,pFont); // Read bitmaps to display as icons. Reference xIconNode ( PresenterConfigurationAccess::GetProperty(xProperties, A2S("Icon")), UNO_QUERY); mpIcon = PresenterBitmapContainer::LoadBitmap( xIconNode, A2S(""), rContext.mxPresenterHelper, rContext.msBasePath, rContext.mxCanvas, rpDefaultMode.get()!=NULL ? rpDefaultMode->mpIcon : SharedBitmapDescriptor()); } catch(Exception&) { OSL_ASSERT(false); } } } // end of anonymous namespace //===== Button ================================================================ namespace { ::rtl::Reference Button::Create ( const ::rtl::Reference& rpToolBar) { ::rtl::Reference