/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sdext.hxx"

#include "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 <cppuhelper/compbase2.hxx>
#include <com/sun/star/awt/FontDescriptor.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/deployment/XPackageInformationProvider.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#include <com/sun/star/drawing/framework/XPane.hpp>
#include <com/sun/star/geometry/AffineMatrix2D.hpp>
#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/RenderState.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <com/sun/star/rendering/ViewState.hpp>
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/util/Color.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <rtl/ustrbuf.hxx>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <map>

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<rendering::XCanvas>& rxCanvas,
            const rendering::ViewState& rViewState,
            const awt::Rectangle& rBoundingBox,
            const awt::Point& rOffset);

        geometry::RealRectangle2D GetBoundingBox (
            const Reference<rendering::XCanvas>& 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<beans::XPropertySet>& rxProperties,
            const ::rtl::OUString& rsModeName,
            ::boost::shared_ptr<ElementMode>& rpDefaultMode,
            ::sdext::presenter::PresenterToolBar::Context& rContext);
    };
    typedef ::boost::shared_ptr<ElementMode> SharedElementMode;

}  // end of anonymous namespace


class PresenterToolBar::Context
    : private ::boost::noncopyable
{
public:
    Reference<drawing::XPresenterHelper> mxPresenterHelper;
    css::uno::Reference<css::rendering::XCanvas> 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<PresenterToolBar>& 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<rendering::XCanvas>& rxCanvas,
            const rendering::ViewState& rViewState) = 0;
        awt::Size GetBoundingSize (
            const Reference<rendering::XCanvas>& 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<PresenterToolBar> 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<rendering::XCanvas>& rxCanvas) = 0;

        bool IsEnabled (void) const;
        void SetEnabledState (const bool bIsEnabled);

    private:
        bool mbIsEnabled;
    };

} // end of anonymous namespace


class PresenterToolBar::ElementContainerPart
    : public ::std::vector<rtl::Reference<Element> >
{
};




//===== Button ================================================================

namespace {

    class Button : public Element
    {
    public:
        static ::rtl::Reference<Element> Create (
            const ::rtl::Reference<PresenterToolBar>& rpToolBar);

        virtual ~Button (void);
        virtual void SAL_CALL disposing (void);

        virtual void Paint (
            const Reference<rendering::XCanvas>& 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<rendering::XCanvas>& rxCanvas);
    
    private:
        bool mbIsListenerRegistered;

        Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
        void Initialize (void);
        void PaintIcon (
            const Reference<rendering::XCanvas>& rxCanvas,
            const sal_Int32 nTextHeight,
            const rendering::ViewState& rViewState);
        PresenterBitmapDescriptor::Mode GetMode (void) const;
    };




//===== Label =================================================================

    class Label : public Element
    {
    public:
        Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
        
        void SetText (const OUString& rsText);
        virtual void Paint (
            const Reference<rendering::XCanvas>& rxCanvas,
            const rendering::ViewState& rViewState);
        virtual bool SetState (const bool bIsOver, const bool bIsPressed);

    protected:
        virtual awt::Size CreateBoundingSize (
            const Reference<rendering::XCanvas>& rxCanvas);
    };


// Some specialized controls.


    class ProgressLabel : public Label
    {
    public:
        ProgressLabel (const ::rtl::Reference<PresenterToolBar>& 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<PresenterToolBar>& rpToolBar);
        using Element::disposing;
        virtual void SAL_CALL disposing (void);
    private:
        class Listener : public PresenterClockTimer::Listener
        {
        public:
            Listener (const ::rtl::Reference<TimeLabel>& rxLabel)
                : mxLabel(rxLabel) {}
            virtual ~Listener (void) {}
            virtual void TimeHasChanged (const oslDateTime& rCurrentTime)
            { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); }
        private:
            ::rtl::Reference<TimeLabel> mxLabel;
        };
        ::boost::shared_ptr<PresenterClockTimer::Listener> mpListener;
    };

    class CurrentTimeLabel : public TimeLabel
    {
    public:
        static ::rtl::Reference<Element> Create (
            const ::rtl::Reference<PresenterToolBar>& rpToolBar);
        virtual void SetModes (
            const SharedElementMode& rpNormalMode,
            const SharedElementMode& rpMouseOverMode,
            const SharedElementMode& rpSelectedMode,
            const SharedElementMode& rpDisabledMode);
    private:
        TimeFormatter maTimeFormatter;
        CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
        virtual ~CurrentTimeLabel (void);
        virtual void TimeHasChanged (const oslDateTime& rCurrentTime);
    };

    class PresentationTimeLabel : public TimeLabel
    {
    public:
        static ::rtl::Reference<Element> Create (
            const ::rtl::Reference<PresenterToolBar>& 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<PresenterToolBar>& rpToolBar);
        virtual ~PresentationTimeLabel (void);
        virtual void TimeHasChanged (const oslDateTime& rCurrentTime);
    };

    class VerticalSeparator : public Element
    {
    public:
        explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
        virtual void Paint (
            const Reference<rendering::XCanvas>& rxCanvas,
            const rendering::ViewState& rViewState);
        virtual bool IsFilling (void) const;

    protected:
        virtual awt::Size CreateBoundingSize (
            const Reference<rendering::XCanvas>& rxCanvas);
    };

    class HorizontalSeparator : public Element
    {
    public:
        explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
        virtual void Paint (
            const Reference<rendering::XCanvas>& rxCanvas,
            const rendering::ViewState& rViewState);
        virtual bool IsFilling (void) const;

    protected:
        virtual awt::Size CreateBoundingSize (
            const Reference<rendering::XCanvas>& rxCanvas);
    };
} // end of anonymous namespace



//===== PresenterToolBar ======================================================

PresenterToolBar::PresenterToolBar (
    const Reference<XComponentContext>& rxContext,
    const css::uno::Reference<css::awt::XWindow>& rxWindow,
    const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
    const ::rtl::Reference<PresenterController>& 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<awt::XWindowPeer> 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<Element> pElement (*iElement);
                Reference<lang::XComponent> xComponent (
                    static_cast<XWeak*>(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<PresenterController> PresenterToolBar::GetPresenterController (void) const
{
    return mpPresenterController;
}




Reference<awt::XWindow> PresenterToolBar::GetWindow (void) const
{
    return mxWindow;
}




Reference<XComponentContext> 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<rendering::XSpriteCanvas> 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<drawing::XDrawPage>& rxSlide)
    throw (RuntimeException)
{
    if (rxSlide != mxCurrentSlide)
    {
        mxCurrentSlide = rxSlide;
        UpdateSlideNumber();
    }
}




Reference<drawing::XDrawPage> 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.PresenterScreen/"),
        PresenterConfigurationAccess::READ_ONLY);

    mpCurrentContainerPart.reset(new ElementContainerPart());
    maElementContainer.clear();
    maElementContainer.push_back(mpCurrentContainerPart);

    Reference<container::XHierarchicalNameAccess> xToolBarNode (
        aConfiguration.GetConfigurationNode(rsConfigurationPath),
        UNO_QUERY);
    if (xToolBarNode.is())
    {
        Reference<container::XNameAccess> xEntries (
            PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, A2S("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<beans::XPropertySet>& 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<Element> 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<Element>(new VerticalSeparator(this));
    else if (sType.equalsAscii("HorizontalSeparator"))
        pElement = ::rtl::Reference<Element>(new HorizontalSeparator(this));
    else if (sType.equalsAscii("Label"))
        pElement = ::rtl::Reference<Element>(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<rendering::XCanvas>& rxCanvas)
{
    if (maElementContainer.size() == 0)
        return;

    mbIsLayoutPending = false;

    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    ElementContainer::iterator iPart;
    ElementContainer::iterator iEnd (maElementContainer.end());
    ::std::vector<geometry::RealSize2D> 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<rendering::XCanvas>& 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<rendering::XCanvas>& 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<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}




//===== PresenterToolBarView ==================================================

PresenterToolBarView::PresenterToolBarView (
    const Reference<XComponentContext>& rxContext,
    const Reference<XResourceId>& rxViewId,
    const Reference<frame::XController>& rxController,
    const ::rtl::Reference<PresenterController>& rpPresenterController)
    : PresenterToolBarViewInterfaceBase(m_aMutex),
      mxPane(),
      mxViewId(rxViewId),
      mxWindow(),
      mxCanvas(),
      mpPresenterController(rpPresenterController),
      mxSlideShowController(rpPresenterController->GetSlideShowController()),
      mpToolBar()
{
    try
    {
        Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
        Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_QUERY_THROW);
        mxPane = Reference<XPane>(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<awt::XWindowPeer> 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<lang::XComponent> xComponent (static_cast<XWeak*>(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<PresenterToolBar> 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<XResourceId> 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<drawing::XDrawPage>& rxSlide)
    throw (RuntimeException)
{
    Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
    if (xToolBar.is())
        xToolBar->setCurrentPage(rxSlide);
}




Reference<drawing::XDrawPage> 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<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}




//===== PresenterToolBar::Element =============================================

namespace {

Element::Element (
    const ::rtl::Reference<PresenterToolBar>& 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<rendering::XCanvas>& 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<frame::XDispatch> 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<beans::XPropertySet>& rxElementProperties,
    const OUString& rsModeName,
    ::boost::shared_ptr<ElementMode>& rpDefaultMode,
    ::sdext::presenter::PresenterToolBar::Context& rContext)
{
    try
    {
    Reference<container::XHierarchicalNameAccess> xNode (
        PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName),
        UNO_QUERY);
    Reference<beans::XPropertySet> 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<container::XHierarchicalNameAccess> 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<container::XHierarchicalNameAccess> xIconNode (
        PresenterConfigurationAccess::GetProperty(xProperties, A2S("Icon")), UNO_QUERY);
    mpIcon = PresenterBitmapContainer::LoadBitmap(
        xIconNode,
        A2S(""),
        rContext.mxPresenterHelper,
        rContext.mxCanvas,
        rpDefaultMode.get()!=NULL ? rpDefaultMode->mpIcon : SharedBitmapDescriptor());
    }
    catch(Exception&)
    {
        OSL_ASSERT(false);
    }
}

} // end of anonymous namespace




//===== Button ================================================================

namespace {

::rtl::Reference<Element> Button::Create (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
{
    ::rtl::Reference<Button> pElement (new Button(rpToolBar));
    pElement->Initialize();
    return ::rtl::Reference<Element>(pElement.get());
}




Button::Button (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : Element(rpToolBar),
      mbIsListenerRegistered(false)
{
    OSL_ASSERT(mpToolBar.get() != NULL);
    OSL_ASSERT(mpToolBar->GetPresenterController().is());
    OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
}




Button::~Button (void)
{
}




void Button::Initialize (void)
{
    mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this);
    mbIsListenerRegistered = true;
}




void Button::disposing (void)
{
    OSL_ASSERT(mpToolBar.get() != NULL);
    if (mpToolBar.get() != NULL
        && mbIsListenerRegistered)
    {
        OSL_ASSERT(mpToolBar->GetPresenterController().is());
        OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());

        mbIsListenerRegistered = false;
        mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this);
    }
    Element::disposing();
}




void Button::Paint (
    const Reference<rendering::XCanvas>& rxCanvas,
    const rendering::ViewState& rViewState)
{
    OSL_ASSERT(rxCanvas.is());

    if (mpMode.get() == NULL)
        return;
    
    if (mpMode->mpIcon.get() == NULL)
        return;

    geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
    sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
    
    PaintIcon(rxCanvas, nTextHeight, rViewState);
    awt::Point aOffset(0,0);
    if ( ! IsEnabled())
        if (mpMode->mpIcon.get() != NULL)
        {
            Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetNormalBitmap());
            if (xBitmap.is())
                aOffset.Y = xBitmap->getSize().Height;
        }
    mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), aOffset);
}




awt::Size Button::CreateBoundingSize (
    const Reference<rendering::XCanvas>& rxCanvas)
{
    if (mpMode.get() == NULL)
        return awt::Size();

    geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
    const sal_Int32 nGap (5);
    sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
    sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1));
    Reference<rendering::XBitmap> xBitmap;
    if (mpMode->mpIcon.get() != NULL)
        xBitmap = mpMode->mpIcon->GetNormalBitmap();
    if (xBitmap.is())
    {
        geometry::IntegerSize2D aSize (xBitmap->getSize());
        return awt::Size(
            ::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)),
            aSize.Height+ nGap + nTextHeight);
    }
    else
        return awt::Size(nTextWidth,nTextHeight);
}




void Button::PaintIcon (
    const Reference<rendering::XCanvas>& rxCanvas,
    const sal_Int32 nTextHeight,
    const rendering::ViewState& rViewState)
{
    if (mpMode.get() == NULL)
        return;
    
    Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode()));
    if (xBitmap.is())
    {
        const sal_Int32 nX (maLocation.X
            + (maSize.Width-xBitmap->getSize().Width) / 2);
        const sal_Int32 nY (maLocation.Y
            + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
        const rendering::RenderState aRenderState(
            geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
            NULL,
            Sequence<double>(4),
            rendering::CompositeOperation::OVER);
        rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
    }
}




PresenterBitmapDescriptor::Mode Button::GetMode (void) const
{
    if ( ! IsEnabled())
        return PresenterBitmapDescriptor::Disabled;
    else if (mbIsPressed)
        return PresenterBitmapDescriptor::ButtonDown;
    else if (mbIsOver)
        return PresenterBitmapDescriptor::MouseOver;
    else
        return PresenterBitmapDescriptor::Normal;
}




//----- lang::XEventListener --------------------------------------------------

void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
    mbIsListenerRegistered = false;
    Element::disposing(rEvent);
}
    
} // end of anonymous namespace




//===== PresenterToolBar::Label ===============================================

namespace {

Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : Element(rpToolBar)
{
}




awt::Size Label::CreateBoundingSize (
    const Reference<rendering::XCanvas>& rxCanvas)
{
    if (mpMode.get() == NULL)
        return awt::Size(0,0);
    
    geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
    return awt::Size(
        sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1),
        sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
}
 




void Label::SetText (const OUString& rsText)
{
    OSL_ASSERT(mpToolBar.get() != NULL);
    if (mpMode.get() == NULL)
        return;

    const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength());

    mpMode->maText.SetText(rsText);
    // Just use the character count for determing whether a layout is
    // necessary.  This is an optimization to avoid layouts every time a new
    // time value is set on some labels.
    if (bRequestLayout)
        mpToolBar->RequestLayout();
    else
        Invalidate(false);
}




void Label::Paint (
    const Reference<rendering::XCanvas>& rxCanvas,
    const rendering::ViewState& rViewState)
{
    OSL_ASSERT(rxCanvas.is());
    if (mpMode.get() == NULL)
        return;
    
    mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), awt::Point(0,0));
}




bool Label::SetState (const bool bIsOver, const bool bIsPressed)
{
    // For labels there is no mouse over effect.
    (void)bIsOver;
    (void)bIsPressed;
    return Element::SetState(false, false);
}

} // end of anonymous namespace




//===== Text ==================================================================

namespace {

Text::Text (void)
    : msText(),
      mpFont()
{
}




Text::Text (const Text& rText)
    : msText(rText.msText),
      mpFont(rText.mpFont)
{
}




Text::Text (
    const OUString& rsText,
    const PresenterTheme::SharedFontDescriptor& rpFont)
    : msText(rsText),
      mpFont(rpFont)
{
}




void Text::SetText (const OUString& rsText)
{
    msText = rsText;
}




OUString Text::GetText (void) const
{
    return msText;
}




PresenterTheme::SharedFontDescriptor Text::GetFont (void) const
{
    return mpFont;
}




void Text::Paint (
    const Reference<rendering::XCanvas>& rxCanvas,
    const rendering::ViewState& rViewState,
    const awt::Rectangle& rBoundingBox,
    const awt::Point& rOffset)
{
    (void)rOffset;
    OSL_ASSERT(rxCanvas.is());

    if (msText.getLength() <= 0)
        return;
    if (mpFont.get() == NULL)
        return;

    if ( ! mpFont->mxFont.is())
        mpFont->PrepareFont(rxCanvas);
    if ( ! mpFont->mxFont.is())
        return;

    rendering::StringContext aContext (msText, 0, msText.getLength());

    Reference<rendering::XTextLayout> xLayout (
        mpFont->mxFont->createTextLayout(
            aContext,
            rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
            0));

    geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
    const double nTextWidth = aBox.X2 - aBox.X1;
    const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2;
    const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2;

    rendering::RenderState aRenderState(
        geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);
    PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
    
    rxCanvas->drawText(
        aContext,
        mpFont->mxFont,
        rViewState,
        aRenderState,
        rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
}




geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas)
{
    if (mpFont.get() != NULL && msText.getLength() > 0)
    {
        if ( ! mpFont->mxFont.is())
            mpFont->PrepareFont(rxCanvas);
        if (mpFont->mxFont.is())
        {
            rendering::StringContext aContext (msText, 0, msText.getLength());
            Reference<rendering::XTextLayout> xLayout (
                mpFont->mxFont->createTextLayout(
                    aContext,
                    rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
                    0));
            return xLayout->queryTextBounds();
        }
    }
    return geometry::RealRectangle2D(0,0,0,0);
}




//===== ProgressLabel =========================================================

ProgressLabel::ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : Label(rpToolBar)
{
    SetText(A2S("-/-"));
}




void ProgressLabel::CurrentSlideHasChanged (void)
{
    Label::CurrentSlideHasChanged();
    OSL_ASSERT(mpToolBar.is());
    try
    {
        const sal_Int32 nCurrentSlideIndex (mpToolBar->GetCurrentSlideIndex() + 1);
        const sal_Int32 nSlideCount (mpToolBar->GetSlideCount());
        if (nCurrentSlideIndex >= 0 && nSlideCount > 0)
            SetText(
                OUString::valueOf(nCurrentSlideIndex)
                    + OUString::createFromAscii(" / ")
                        + OUString::valueOf(nSlideCount));
        else
            SetText(A2S(""));
        Invalidate();
    }
    catch (RuntimeException&)
    {
    }
}




//===== TimeFormatter =========================================================

TimeFormatter::TimeFormatter (void)
    : mbIs24HourFormat(true),
      mbIsAmPmFormat(false),
      mbIsShowSeconds(true)
{
}




OUString TimeFormatter::FormatTime (const oslDateTime& rTime)
{
    ::rtl::OUStringBuffer sText;

    const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours));
    const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes));
    const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds));
    
    // Hours
    if (mbIs24HourFormat)
        sText.append(OUString::valueOf(nHours));
    else
        sText.append(OUString::valueOf(
            sal::static_int_cast<sal_Int32>(nHours>12 ? nHours-12 : nHours)));

    sText.append(A2S(":"));

    // Minutes
    const OUString sMinutes (OUString::valueOf(nMinutes));
    if (sMinutes.getLength() == 1)
        sText.append(A2S("0"));
    sText.append(sMinutes);

    // Seconds
    if (mbIsShowSeconds)
    {
        sText.append(A2S(":"));
        const OUString sSeconds (OUString::valueOf(nSeconds));
        if (sSeconds.getLength() == 1)
            sText.append(A2S("0"));
        sText.append(sSeconds);
    }

    if (mbIsAmPmFormat)
    {
        if (rTime.Hours < 12)
            sText.append(A2S("am"));
        else
            sText.append(A2S("pm"));
    }
    return sText.makeStringAndClear();
}




//===== TimeLabel =============================================================

TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : Label(rpToolBar),
      mpListener()
{
}




void SAL_CALL TimeLabel::disposing (void)
{
    PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener);
    mpListener.reset();
}




void TimeLabel::ConnectToTimer (void)
{
    mpListener.reset(new Listener(this));
    PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener);
}




//===== CurrentTimeLabel ======================================================

::rtl::Reference<Element> CurrentTimeLabel::Create (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
{
    ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar));
    pElement->ConnectToTimer();
    return ::rtl::Reference<Element>(pElement.get());
}




CurrentTimeLabel::~CurrentTimeLabel (void)
{
}




CurrentTimeLabel::CurrentTimeLabel (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : TimeLabel(rpToolBar),
      maTimeFormatter()
{
}




void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
{
    SetText(maTimeFormatter.FormatTime(rCurrentTime));
    Invalidate(false);
}




void CurrentTimeLabel::SetModes (
    const SharedElementMode& rpNormalMode,
    const SharedElementMode& rpMouseOverMode,
    const SharedElementMode& rpSelectedMode,
    const SharedElementMode& rpDisabledMode)
{
    TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
    SetText(maTimeFormatter.FormatTime(PresenterClockTimer::GetCurrentTime()));
}




//===== PresentationTimeLabel =================================================

::rtl::Reference<Element> PresentationTimeLabel::Create (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
{
    ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar));
    pElement->ConnectToTimer();
    return ::rtl::Reference<Element>(pElement.get());
}




PresentationTimeLabel::~PresentationTimeLabel (void)
{
}




PresentationTimeLabel::PresentationTimeLabel (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : TimeLabel(rpToolBar),
      maTimeFormatter(),
      maStartTimeValue()
{
    maStartTimeValue.Seconds = 0;
    maStartTimeValue.Nanosec = 0;
}




void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
{
    TimeValue aCurrentTimeValue;
    if (osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rCurrentTime), &aCurrentTimeValue))
    {
        if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0)
        {
            // This method is called for the first time.  Initialize the
            // start time.  The start time is rounded to nearest second to
            // keep the time updates synchronized with the current time label.
            maStartTimeValue = aCurrentTimeValue;
            if (maStartTimeValue.Nanosec >= 500000000)
                maStartTimeValue.Seconds += 1;
            maStartTimeValue.Nanosec = 0;
        }
        
        TimeValue aElapsedTimeValue;
        aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds;
        aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec;

        oslDateTime aElapsedDateTime;
        if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime))
        {
            SetText(maTimeFormatter.FormatTime(aElapsedDateTime));
            Invalidate(false);
        }
    }
}



void PresentationTimeLabel::SetModes (
    const SharedElementMode& rpNormalMode,
    const SharedElementMode& rpMouseOverMode,
    const SharedElementMode& rpSelectedMode,
    const SharedElementMode& rpDisabledMode)
{
    TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);

    oslDateTime aStartDateTime;
    if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime))
    {
        SetText(maTimeFormatter.FormatTime(aStartDateTime));
    }
}




//===== VerticalSeparator =====================================================

VerticalSeparator::VerticalSeparator (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : Element(rpToolBar)
{
}




void VerticalSeparator::Paint (
    const Reference<rendering::XCanvas>& rxCanvas,
    const rendering::ViewState& rViewState)
{
    OSL_ASSERT(rxCanvas.is());

    awt::Rectangle aBBox (GetBoundingBox());

    rendering::RenderState aRenderState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::OVER);
    if (mpMode.get() != NULL)
    {
        PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
        if (pFont.get() != NULL)
            PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
    }

    if (aBBox.Height >= gnMinimalSeparatorSize + 2*gnSeparatorInset)
    {
        aBBox.Height -= 2*gnSeparatorInset;
        aBBox.Y += gnSeparatorInset;
    }
    rxCanvas->fillPolyPolygon(
        PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
        rViewState,
        aRenderState);
}




awt::Size VerticalSeparator::CreateBoundingSize (
    const Reference<rendering::XCanvas>& rxCanvas)
{
    (void)rxCanvas;
    return awt::Size(1,20);
}




bool VerticalSeparator::IsFilling (void) const
{
    return true;
}




//===== HorizontalSeparator ===================================================

HorizontalSeparator::HorizontalSeparator (
    const ::rtl::Reference<PresenterToolBar>& rpToolBar)
    : Element(rpToolBar)
{
}




void HorizontalSeparator::Paint (
    const Reference<rendering::XCanvas>& rxCanvas,
    const rendering::ViewState& rViewState)
{
    OSL_ASSERT(rxCanvas.is());

    awt::Rectangle aBBox (GetBoundingBox());

    rendering::RenderState aRenderState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::OVER);
    if (mpMode.get() != NULL)
    {
        PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
        if (pFont.get() != NULL)
            PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
    }

    if (aBBox.Width >= gnMinimalSeparatorSize+2*gnSeparatorInset)
    {
        aBBox.Width -= 2*gnSeparatorInset;
        aBBox.X += gnSeparatorInset;
    }
    rxCanvas->fillPolyPolygon(
        PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
        rViewState,
        aRenderState);
}




awt::Size HorizontalSeparator::CreateBoundingSize (
    const Reference<rendering::XCanvas>& rxCanvas)
{
    (void)rxCanvas;
    return awt::Size(20,1);
}




bool HorizontalSeparator::IsFilling (void) const
{
    return true;
}




} // end of anonymous namespace


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