/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include "PresenterToolBar.hxx" #include "PresenterBitmapContainer.hxx" #include "PresenterCanvasHelper.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 using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::drawing::framework; 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(); Text ( const OUString& rsText, const PresenterTheme::SharedFontDescriptor& rpFont); void SetText (const OUString& rsText); OUString GetText() const; PresenterTheme::SharedFontDescriptor GetFont() 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(); SharedBitmapDescriptor mpIcon; OUString msAction; Text maText; void ReadElementMode ( const Reference& rxProperties, const OUString& rsModeName, std::shared_ptr& rpDefaultMode, ::sdext::presenter::PresenterToolBar::Context& rContext); }; typedef std::shared_ptr SharedElementMode; } // end of anonymous namespace class PresenterToolBar::Context : private ::boost::noncopyable { public: Reference mxPresenterHelper; css::uno::Reference mxCanvas; }; //===== PresenterToolBar::Element ============================================= namespace { typedef cppu::WeakComponentImplHelper< css::document::XEventListener, css::frame::XStatusListener > ElementInterfaceBase; class Element : private ::cppu::BaseMutex, private ::boost::noncopyable, public ElementInterfaceBase { public: explicit Element (const ::rtl::Reference& rpToolBar); virtual ~Element(); virtual void SAL_CALL disposing() override; virtual void SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode); void CurrentSlideHasChanged(); void SetLocation (const awt::Point& rLocation); 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() const; virtual bool SetState (const bool bIsOver, const bool bIsPressed); void Invalidate (const bool bSynchronous = true); bool IsOutside (const awt::Rectangle& rBox); virtual bool IsFilling() const; void UpdateState(); // lang::XEventListener virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) throw(css::uno::RuntimeException, std::exception) override; // document::XEventListener virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) throw(css::uno::RuntimeException, std::exception) override; // frame::XStatusListener virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent) throw(css::uno::RuntimeException, std::exception) override; 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() const { return mbIsEnabled;} 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(); virtual void SAL_CALL disposing() override; virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState) override; // lang::XEventListener virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) throw(css::uno::RuntimeException, std::exception) override; protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas) override; private: bool mbIsListenerRegistered; Button (const ::rtl::Reference& rpToolBar); void Initialize(); void PaintIcon ( const Reference& rxCanvas, const sal_Int32 nTextHeight, const rendering::ViewState& rViewState); PresenterBitmapDescriptor::Mode GetMode() const; }; //===== Label ================================================================= class Label : public Element { public: explicit Label (const ::rtl::Reference& rpToolBar); void SetText (const OUString& rsText); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState) override; virtual bool SetState (const bool bIsOver, const bool bIsPressed) override; protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas) override; }; // Some specialized controls. class TimeFormatter { public: TimeFormatter(); OUString FormatTime (const oslDateTime& rTime); private: bool mbIs24HourFormat; bool mbIsAmPmFormat; bool mbIsShowSeconds; }; class TimeLabel : public Label { public: void ConnectToTimer(); virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0; protected: explicit TimeLabel(const ::rtl::Reference& rpToolBar); using Element::disposing; virtual void SAL_CALL disposing() override; private: class Listener : public PresenterClockTimer::Listener { public: explicit Listener (const ::rtl::Reference& rxLabel) : mxLabel(rxLabel) {} virtual ~Listener() {} virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); } private: ::rtl::Reference mxLabel; }; std::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) override; private: TimeFormatter maTimeFormatter; CurrentTimeLabel (const ::rtl::Reference& rpToolBar); virtual ~CurrentTimeLabel(); virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override; }; class PresentationTimeLabel : public TimeLabel, public IPresentationTime { public: static ::rtl::Reference Create ( const ::rtl::Reference& rpToolBar); virtual void SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, const SharedElementMode& rpDisabledMode) override; virtual void restart() override; private: TimeFormatter maTimeFormatter; TimeValue maStartTimeValue; PresentationTimeLabel (const ::rtl::Reference& rpToolBar); virtual ~PresentationTimeLabel(); virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override; }; class VerticalSeparator : public Element { public: explicit VerticalSeparator (const ::rtl::Reference& rpToolBar); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState) override; virtual bool IsFilling() const override; protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas) override; }; class HorizontalSeparator : public Element { public: explicit HorizontalSeparator (const ::rtl::Reference& rpToolBar); virtual void Paint ( const Reference& rxCanvas, const rendering::ViewState& rViewState) override; virtual bool IsFilling() const override; protected: virtual awt::Size CreateBoundingSize ( const Reference& rxCanvas) override; }; } // 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 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 SAL_CALL PresenterToolBar::disposing() { if (mxWindow.is()) { mxWindow->removeWindowListener(this); mxWindow->removePaintListener(this); mxWindow->removeMouseListener(this); mxWindow->removeMouseMotionListener(this); mxWindow = nullptr; } // Dispose tool bar elements. ElementContainer::iterator iPart (maElementContainer.begin()); ElementContainer::const_iterator iEnd (maElementContainer.end()); for ( ; iPart!=iEnd; ++iPart) { OSL_ASSERT(iPart->get()!=nullptr); ElementContainerPart::iterator iElement ((*iPart)->begin()); ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); for ( ; iElement!=iPartEnd; ++iElement) { if (iElement->get() != nullptr) { ::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) { std::shared_ptr xManager(mpPresenterController->GetPaintManager()); if (!xManager) return; xManager->Invalidate( mxWindow, rRepaintBox, bSynchronous); } void PresenterToolBar::RequestLayout() { mbIsLayoutPending = true; std::shared_ptr xManager(mpPresenterController->GetPaintManager()); if (!xManager) return; xManager->Invalidate(mxWindow); } geometry::RealSize2D PresenterToolBar::GetMinimalSize() { if (mbIsLayoutPending) Layout(mxCanvas); return maMinimalSize; } ::rtl::Reference PresenterToolBar::GetPresenterController() const { return mpPresenterController; } Reference PresenterToolBar::GetComponentContext() const { return mxComponentContext; } //----- lang::XEventListener ------------------------------------------------- void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject) throw (RuntimeException, std::exception) { if (rEventObject.Source == mxWindow) mxWindow = nullptr; } //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent& rEvent) throw (RuntimeException, std::exception) { (void)rEvent; mbIsLayoutPending = true; } void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent& rEvent) throw (RuntimeException, std::exception) { (void)rEvent; } void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject& rEvent) throw (RuntimeException, std::exception) { (void)rEvent; mbIsLayoutPending = true; } void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject& rEvent) throw (RuntimeException, std::exception) { (void)rEvent; } //----- XPaintListener -------------------------------------------------------- void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent) throw (RuntimeException, std::exception) { 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, std::exception) { ThrowIfDisposed(); CheckMouseOver(rEvent, true, true); } void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); CheckMouseOver(rEvent, true); } void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); CheckMouseOver(rEvent, true); } void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); CheckMouseOver(rEvent, false); } //----- XMouseMotionListener -------------------------------------------------- void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent) throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); CheckMouseOver(rEvent, true); } void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent& rEvent) throw (css::uno::RuntimeException, std::exception) { ThrowIfDisposed(); (void)rEvent; } //----- XDrawView ------------------------------------------------------------- void SAL_CALL PresenterToolBar::setCurrentPage (const Reference& rxSlide) throw (RuntimeException, std::exception) { if (rxSlide != mxCurrentSlide) { mxCurrentSlide = rxSlide; UpdateSlideNumber(); } } Reference SAL_CALL PresenterToolBar::getCurrentPage() throw (RuntimeException, std::exception) { return mxCurrentSlide; } void PresenterToolBar::CreateControls ( const OUString& rsConfigurationPath) { if ( ! mxWindow.is()) return; // Expand the macro in the bitmap file names. PresenterConfigurationAccess aConfiguration ( mxComponentContext, OUString("/org.openoffice.Office.PresenterScreen/"), PresenterConfigurationAccess::READ_ONLY); 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, "Entries"), UNO_QUERY); Context aContext; 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, "Type") >>= sType)) return; OUString sName; PresenterConfigurationAccess::GetProperty(rxProperties, "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, "Normal", pNormalMode, rContext); pMouseOverMode->ReadElementMode(rxProperties, "MouseOver", pNormalMode, rContext); pSelectedMode->ReadElementMode(rxProperties, "Selected", pNormalMode, rContext); pDisabledMode->ReadElementMode(rxProperties, "Disabled", pNormalMode, rContext); // Create new element. ::rtl::Reference pElement; if ( sType == "Button" ) pElement = Button::Create(this); else if ( sType == "CurrentTimeLabel" ) pElement = CurrentTimeLabel::Create(this); else if ( sType == "PresentationTimeLabel" ) pElement = PresentationTimeLabel::Create(this); else if ( sType == "VerticalSeparator" ) pElement.set(new VerticalSeparator(this)); else if ( sType == "HorizontalSeparator" ) pElement.set(new HorizontalSeparator(this)); else if ( sType == "Label" ) pElement.set(new Label(this)); else if ( sType == "ChangeOrientation" ) { mpCurrentContainerPart.reset(new ElementContainerPart()); maElementContainer.push_back(mpCurrentContainerPart); return; } if (pElement.is()) { pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode); pElement->UpdateState(); if (mpCurrentContainerPart.get() != nullptr) mpCurrentContainerPart->push_back(pElement); } } void PresenterToolBar::Layout ( const Reference& rxCanvas) { if (maElementContainer.empty()) return; mbIsLayoutPending = false; const awt::Rectangle aWindowBox (mxWindow->getPosSize()); ElementContainer::iterator iPart; ElementContainer::iterator iEnd (maElementContainer.end()); ElementContainer::iterator iBegin (maElementContainer.begin()); ::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; /* push front or back ? ... */ /// check whether RTL interface or not if(!AllSettings::GetLayoutRTL()){ 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; } } else { for (iPart=maElementContainer.end()-1, nIndex=2; iPart!=iBegin-1; --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. std::shared_ptr xManager(mpPresenterController->GetPaintManager()); if (!xManager) return; xManager->Invalidate(mxWindow); } geometry::RealSize2D PresenterToolBar::CalculatePartSize ( const Reference& rxCanvas, const SharedElementContainerPart& rpPart, const bool bIsHorizontal) { geometry::RealSize2D aTotalSize (0,0); if (mxWindow.is()) { // Calculate the summed width of all elements. ElementContainerPart::const_iterator iElement; for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement) { if (iElement->get() == nullptr) 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()); ElementContainerPart::const_iterator iBegin (rpPart->begin()); /// check whether RTL interface or not if(!AllSettings::GetLayoutRTL()){ for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement) { if (iElement->get() == nullptr) 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; } } } else { for (iElement=rpPart->end()-1; iElement!=iBegin-1; --iElement) { if (iElement->get() == nullptr) 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 { // reverse presentation time with current time if (iElement==iBegin){ iElement=iBegin+2; } else if (iElement==iBegin+2){ iElement=iBegin; } const awt::Size aNewElementSize ((*iElement)->GetBoundingSize(rxCanvas)); if ((*iElement)->IsFilling()) { nX = rBoundingBox.X1; (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aNewElementSize.Height)); } else nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aNewElementSize.Width) / 2; (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY))); nY += aNewElementSize.Height + nGap; // return the index as it was before the reversing if (iElement==iBegin) iElement=iBegin+2; else if (iElement==iBegin+2) iElement=iBegin; } } } } 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() != nullptr) { if ( ! (*iElement)->IsOutside(rUpdateBox)) (*iElement)->Paint(mxCanvas, rViewState); } } } } void PresenterToolBar::UpdateSlideNumber() { 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() != nullptr) (*iElement)->CurrentSlideHasChanged(); } } } } void PresenterToolBar::CheckMouseOver ( const css::awt::MouseEvent& rEvent, const bool bOverWindow, const bool bMouseDown) { css::awt::MouseEvent rTemp =rEvent; if(AllSettings::GetLayoutRTL()){ awt::Rectangle aWindowBox = mxWindow->getPosSize(); rTemp.X=aWindowBox.Width-rTemp.X; } 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() == nullptr) continue; awt::Rectangle aBox ((*iElement)->GetBoundingBox()); const bool bIsOver = bOverWindow && aBox.X <= rTemp.X && aBox.Width+aBox.X-1 >= rTemp.X && aBox.Y <= rTemp.Y && aBox.Height+aBox.Y-1 >= rTemp.Y; (*iElement)->SetState( bIsOver, bIsOver && rTemp.Buttons!=0 && bMouseDown && rTemp.ClickCount>0); } } } void PresenterToolBar::ThrowIfDisposed() const throw (css::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose) { throw lang::DisposedException ( OUString( "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.set(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); mxWindow = mxPane->getWindow(); mxCanvas = mxPane->getCanvas(); mpToolBar = new PresenterToolBar( rxContext, mxWindow, mxCanvas, rpPresenterController, PresenterToolBar::Center); mpToolBar->Initialize("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 = nullptr; throw; } } PresenterToolBarView::~PresenterToolBarView() { } void SAL_CALL PresenterToolBarView::disposing() { Reference xComponent (static_cast(mpToolBar.get()), UNO_QUERY); mpToolBar = nullptr; if (xComponent.is()) xComponent->dispose(); if (mxWindow.is()) { mxWindow->removePaintListener(this); mxWindow = nullptr; } mxCanvas = nullptr; mxViewId = nullptr; mxPane = nullptr; mpPresenterController = nullptr; mxSlideShowController = nullptr; } ::rtl::Reference PresenterToolBarView::GetPresenterToolBar() const { return mpToolBar; } //----- XPaintListener -------------------------------------------------------- void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent) throw (RuntimeException, std::exception) { 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, std::exception) { if (rEventObject.Source == mxWindow) mxWindow = nullptr; } //----- XResourceId ----------------------------------------------------------- Reference SAL_CALL PresenterToolBarView::getResourceId() throw (RuntimeException, std::exception) { return mxViewId; } sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly() throw (RuntimeException, std::exception) { return false; } //----- XDrawView ------------------------------------------------------------- void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference& rxSlide) throw (RuntimeException, std::exception) { Reference xToolBar (static_cast(mpToolBar.get()), UNO_QUERY); if (xToolBar.is()) xToolBar->setCurrentPage(rxSlide); } Reference SAL_CALL PresenterToolBarView::getCurrentPage() throw (RuntimeException, std::exception) { return nullptr; } //===== 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() != nullptr) { OSL_ASSERT(mpToolBar->GetPresenterController().is()); OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is()); } } Element::~Element() { } 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() { } awt::Size Element::GetBoundingSize ( const Reference& rxCanvas) { maSize = CreateBoundingSize(rxCanvas); return maSize; } awt::Rectangle Element::GetBoundingBox() const { return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height); } void Element::CurrentSlideHasChanged() { 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() != nullptr) { do { if (mpMode->msAction.isEmpty()) break; if (mpToolBar.get() == nullptr) break; if (mpToolBar->GetPresenterController().get() == nullptr) 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::IsFilling() const { return false; } void Element::UpdateState() { OSL_ASSERT(mpToolBar.get() != nullptr); OSL_ASSERT(mpToolBar->GetPresenterController().get() != nullptr); if (mpMode.get() == nullptr) 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, std::exception) { (void)rEvent; } //----- document::XEventListener ---------------------------------------------- void SAL_CALL Element::notifyEvent (const css::document::EventObject& rEvent) throw(css::uno::RuntimeException, std::exception) { (void)rEvent; UpdateState(); } //----- frame::XStatusListener ------------------------------------------------ void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent) throw(css::uno::RuntimeException, std::exception) { 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() : mpIcon(), msAction(), maText() { } void ElementMode::ReadElementMode ( const Reference& rxElementProperties, const OUString& rsModeName, std::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()!=nullptr) { // 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, "Action") >>= msAction)) if (rpDefaultMode.get()!=nullptr) msAction = rpDefaultMode->msAction; // Read text and font OUString sText (rpDefaultMode.get()!=nullptr ? rpDefaultMode->maText.GetText() : OUString()); PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText; Reference xFontNode ( PresenterConfigurationAccess::GetProperty(xProperties, "Font"), UNO_QUERY); PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont( xFontNode, "", rpDefaultMode.get()!=nullptr ? rpDefaultMode->maText.GetFont() : PresenterTheme::SharedFontDescriptor())); maText = Text(sText,pFont); // Read bitmaps to display as icons. Reference xIconNode ( PresenterConfigurationAccess::GetProperty(xProperties, "Icon"), UNO_QUERY); mpIcon = PresenterBitmapContainer::LoadBitmap( xIconNode, "", rContext.mxPresenterHelper, rContext.mxCanvas, rpDefaultMode.get()!=nullptr ? rpDefaultMode->mpIcon : SharedBitmapDescriptor()); } catch(Exception&) { OSL_ASSERT(false); } } } // end of anonymous namespace //===== Button ================================================================ namespace { ::rtl::Reference Button::Create ( const ::rtl::Reference& rpToolBar) { ::rtl::Reference