/**************************************************************
 * 
 * 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 "PresenterSlideSorter.hxx"
#include "PresenterButton.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterGeometryHelper.hxx"
#include "PresenterHelper.hxx"
#include "PresenterPaintManager.hxx"
#include "PresenterPaneBase.hxx"
#include "PresenterScrollBar.hxx"
#include "PresenterUIPainter.hxx"
#include "PresenterWindowManager.hxx"
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/drawing/XSlideSorterBase.hpp>
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
#include <com/sun/star/util/Color.hpp>
#include <algorithm>
#include <math.h>
#include <boost/bind.hpp>

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 {
    const static sal_Int32 gnVerticalGap (10);
    const static sal_Int32 gnVerticalBorder (10);
    const static sal_Int32 gnHorizontalGap (10);
    const static sal_Int32 gnHorizontalBorder (10);

    const static double gnMinimalPreviewWidth (200);
    const static double gnPreferredPreviewWidth (300);
    const static double gnMaximalPreviewWidth (400);
    const static sal_Int32 gnPreferredColumnCount (6);
    const static double gnMinimalHorizontalPreviewGap(15);
    const static double gnPreferredHorizontalPreviewGap(25);
    const static double gnMaximalHorizontalPreviewGap(50);
    const static double gnMinimalVerticalPreviewGap(15);
    const static double gnPreferredVerticalPreviewGap(25);
    const static double gnMaximalVerticalPreviewGap(50);

    const static sal_Int32 gnHorizontalLabelBorder (3);
    const static sal_Int32 gnHorizontalLabelPadding (5);

    const static sal_Int32 gnVerticalButtonPadding (gnVerticalGap);
}

namespace sdext { namespace presenter {

namespace {
    sal_Int32 round (const double nValue) { return sal::static_int_cast<sal_Int32>(0.5 + nValue); }
    sal_Int32 floor (const double nValue) { return sal::static_int_cast<sal_Int32>(nValue); }
}



//===== PresenterSlideSorter::Layout ==========================================

class PresenterSlideSorter::Layout
{
public:
    enum Orientation { Horizontal, Vertical };
    Layout (
        const Orientation eOrientation,
        const ::rtl::Reference<PresenterScrollBar>& rpHorizontalScrollBar,
        const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar);

    void Update (const geometry::RealRectangle2D& rBoundingBox, const double nSlideAspectRatio);
    void SetupVisibleArea (void);
    void UpdateScrollBars (void);
    bool IsScrollBarNeeded (const sal_Int32 nSlideCount);
    geometry::RealPoint2D GetLocalPosition (const geometry::RealPoint2D& rWindowPoint) const;
    geometry::RealPoint2D GetWindowPosition(const geometry::RealPoint2D& rLocalPoint) const;
    sal_Int32 GetColumn (const geometry::RealPoint2D& rLocalPoint,
        const bool bReturnInvalidValue = false) const;
    sal_Int32 GetRow (const geometry::RealPoint2D& rLocalPoint,
        const bool bReturnInvalidValue = false) const;
    sal_Int32 GetSlideIndexForPosition (const css::geometry::RealPoint2D& rPoint) const;
    css::geometry::RealPoint2D GetPoint (
        const sal_Int32 nSlideIndex,
        const sal_Int32 nRelativeHorizontalPosition,
        const sal_Int32 nRelativeVerticalPosition) const;
    css::awt::Rectangle GetBoundingBox (const sal_Int32 nSlideIndex) const;
    void ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction);
    sal_Int32 GetFirstVisibleSlideIndex (void) const;
    sal_Int32 GetLastVisibleSlideIndex (void) const;
    bool SetHorizontalOffset (const double nOffset);
    bool SetVerticalOffset (const double nOffset);
    Orientation GetOrientation (void) const;

    css::geometry::RealRectangle2D maBoundingBox;
    css::geometry::IntegerSize2D maPreviewSize;
    sal_Int32 mnHorizontalOffset;
    sal_Int32 mnVerticalOffset;
    sal_Int32 mnHorizontalGap;
    sal_Int32 mnVerticalGap;
    sal_Int32 mnHorizontalBorder;
    sal_Int32 mnVerticalBorder;
    sal_Int32 mnRowCount;
    sal_Int32 mnColumnCount;
    sal_Int32 mnSlideCount;
    sal_Int32 mnSlideIndexAtMouse;
    sal_Int32 mnFirstVisibleColumn;
    sal_Int32 mnLastVisibleColumn;
    sal_Int32 mnFirstVisibleRow;
    sal_Int32 mnLastVisibleRow;
    
private:
    Orientation meOrientation;
    ::rtl::Reference<PresenterScrollBar> mpHorizontalScrollBar;
    ::rtl::Reference<PresenterScrollBar> mpVerticalScrollBar;

    sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const;
    sal_Int32 GetRow (const sal_Int32 nSlideIndex) const;
    sal_Int32 GetColumn (const sal_Int32 nSlideIndex) const;
};




//==== PresenterSlideSorter::MouseOverManager =================================

class PresenterSlideSorter::MouseOverManager
    : ::boost::noncopyable
{
public:
    MouseOverManager (
        const Reference<container::XIndexAccess>& rxSlides,
        const ::boost::shared_ptr<PresenterTheme>& rpTheme,
        const Reference<awt::XWindow>& rxInvalidateTarget,
        const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager);
    ~MouseOverManager (void);

    void Paint (
        const sal_Int32 nSlideIndex,
        const Reference<rendering::XCanvas>& rxCanvas,
        const Reference<rendering::XPolyPolygon2D>& rxClip);

    void SetSlide (
        const sal_Int32 nSlideIndex,
        const awt::Rectangle& rBox);

private:
    Reference<rendering::XCanvas> mxCanvas;
    const Reference<container::XIndexAccess> mxSlides;
    SharedBitmapDescriptor mpLeftLabelBitmap;
    SharedBitmapDescriptor mpCenterLabelBitmap;
    SharedBitmapDescriptor mpRightLabelBitmap;
    PresenterTheme::SharedFontDescriptor mpFont;
    sal_Int32 mnSlideIndex;
    awt::Rectangle maSlideBoundingBox;
    OUString msText;
    Reference<rendering::XBitmap> mxBitmap;
    Reference<awt::XWindow> mxInvalidateTarget;
    ::boost::shared_ptr<PresenterPaintManager> mpPaintManager;

    void SetCanvas (
        const Reference<rendering::XCanvas>& rxCanvas);
    /** Create a bitmap that shows the given text and is not wider than the
        given maximal width.
    */
    Reference<rendering::XBitmap> CreateBitmap (
        const OUString& rsText,
        const sal_Int32 nMaximalWidth) const;
    void Invalidate (void);
    geometry::IntegerSize2D CalculateLabelSize (
        const OUString& rsText) const;
    OUString GetFittingText (const OUString& rsText, const double nMaximalWidth) const;
    void PaintButtonBackground (
        const Reference<rendering::XBitmapCanvas>& rxCanvas,
        const geometry::IntegerSize2D& rSize) const;
};




//==== PresenterSlideSorter::CurrentSlideFrameRenderer ========================

class PresenterSlideSorter::CurrentSlideFrameRenderer
{
public:
    CurrentSlideFrameRenderer (
        const css::uno::Reference<css::uno::XComponentContext>& rxContext,
        const css::uno::Reference<css::rendering::XCanvas>& rxCanvas);
    ~CurrentSlideFrameRenderer (void);

    void PaintCurrentSlideFrame (
        const awt::Rectangle& rSlideBoundingBox,
        const Reference<rendering::XCanvas>& rxCanvas,
        const geometry::RealRectangle2D& rClipBox);

    /** Enlarge the given rectangle to include the current slide indicator.
    */
    awt::Rectangle GetBoundingBox (
        const awt::Rectangle& rSlideBoundingBox);

private:
    SharedBitmapDescriptor mpTopLeft;
    SharedBitmapDescriptor mpTop;
    SharedBitmapDescriptor mpTopRight;
    SharedBitmapDescriptor mpLeft;
    SharedBitmapDescriptor mpRight;
    SharedBitmapDescriptor mpBottomLeft;
    SharedBitmapDescriptor mpBottom;
    SharedBitmapDescriptor mpBottomRight;
    sal_Int32 mnTopFrameSize;
    sal_Int32 mnLeftFrameSize;
    sal_Int32 mnRightFrameSize;
    sal_Int32 mnBottomFrameSize;

    void PaintBitmapOnce(
        const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
        const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
        const Reference<rendering::XPolyPolygon2D>& rxClip,
        const double nX,
        const double nY);
    void PaintBitmapTiled(
        const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
        const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
        const geometry::RealRectangle2D& rClipBox,
        const double nX,
        const double nY,
        const double nWidth,
        const double nHeight);
};




//===== PresenterSlideSorter ==================================================

PresenterSlideSorter::PresenterSlideSorter (
    const Reference<uno::XComponentContext>& rxContext,
    const Reference<XResourceId>& rxViewId,
    const Reference<frame::XController>& rxController,
    const ::rtl::Reference<PresenterController>& rpPresenterController)
    : PresenterSlideSorterInterfaceBase(m_aMutex),
      mxComponentContext(rxContext),
      mxViewId(rxViewId),
      mxPane(),
      mxCanvas(),
      mxWindow(),
      mpPresenterController(rpPresenterController),
      mxSlideShowController(mpPresenterController->GetSlideShowController()),
      mxPreviewCache(),
      mbIsPaintPending(true),
      mbIsLayoutPending(true),
      mpLayout(),
      mpHorizontalScrollBar(),
      mpVerticalScrollBar(),
      mpCloseButton(),
      mpMouseOverManager(),
      mnSlideIndexMousePressed(-1),
      mnCurrentSlideIndex(-1),
      mnSeparatorY(0),
      maSeparatorColor(0x00ffffff),
      maCloseButtonCenter(),
      maCurrentSlideFrameBoundingBox(),
      mpCurrentSlideFrameRenderer(),
      mxPreviewFrame()
{
    if ( ! rxContext.is()
        || ! rxViewId.is()
        || ! rxController.is()
        || rpPresenterController.get()==NULL)
    {
        throw lang::IllegalArgumentException();
    }

    if ( ! mxSlideShowController.is())
        throw RuntimeException();

    try
    {
        // Get pane and window.
        Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
        Reference<XConfigurationController> xCC (
            xCM->getConfigurationController(), UNO_QUERY_THROW);
        Reference<lang::XMultiComponentFactory> xFactory (
            mxComponentContext->getServiceManager(), UNO_QUERY_THROW);

        mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
        mxWindow = mxPane->getWindow();

        // Add window listener.
        mxWindow->addWindowListener(this);
        mxWindow->addPaintListener(this);
        mxWindow->addMouseListener(this);
        mxWindow->addMouseMotionListener(this);
        mxWindow->setVisible(sal_True);

        // Remember the current slide.
        mnCurrentSlideIndex = mxSlideShowController->getCurrentSlideIndex();

        // Set the orientation.
        const bool bIsVertical (true);
        
        // Create the scroll bar.
        if (bIsVertical)
            mpVerticalScrollBar = ::rtl::Reference<PresenterScrollBar>(
                new PresenterVerticalScrollBar(
                    rxContext,
                    mxWindow,
                    mpPresenterController->GetPaintManager(),
                    ::boost::bind(&PresenterSlideSorter::SetVerticalOffset,this,_1)));
        else
            mpHorizontalScrollBar = ::rtl::Reference<PresenterScrollBar>(
                new PresenterHorizontalScrollBar(
                    rxContext,
                    mxWindow,
                    mpPresenterController->GetPaintManager(),
                    ::boost::bind(&PresenterSlideSorter::SetHorizontalOffset,this,_1)));
        mpCloseButton = PresenterButton::Create(
            rxContext,
            mpPresenterController,
            mpPresenterController->GetTheme(),
            mxWindow,
            mxCanvas,
            A2S("SlideSorterCloser"));

        if (mpPresenterController->GetTheme().get() != NULL)
        {
            PresenterTheme::SharedFontDescriptor pFont (
                mpPresenterController->GetTheme()->GetFont(A2S("ButtonFont")));
            if (pFont.get() != NULL)
                maSeparatorColor = pFont->mnColor;
        }

        // Create the layout.
        mpLayout.reset(new Layout(
            Layout::Vertical,
            mpHorizontalScrollBar,
            mpVerticalScrollBar));
        
        // Create the preview cache.
        mxPreviewCache = Reference<drawing::XSlidePreviewCache>(
            xFactory->createInstanceWithContext(
                OUString::createFromAscii("com.sun.star.drawing.PresenterPreviewCache"),
                mxComponentContext),
            UNO_QUERY_THROW);
        Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY);
        mxPreviewCache->setDocumentSlides(xSlides, rxController->getModel());
        mxPreviewCache->addPreviewCreationNotifyListener(this);
        if (xSlides.is())
        {
            mpLayout->mnSlideCount = xSlides->getCount();
        }

        // Create the mouse over manager.
        mpMouseOverManager.reset(new MouseOverManager(
            Reference<container::XIndexAccess>(mxSlideShowController, UNO_QUERY),
            mpPresenterController->GetTheme(),
            mxWindow,
            mpPresenterController->GetPaintManager()));
        
        // Listen for changes of the current slide.
        Reference<beans::XPropertySet> xControllerProperties (rxController, UNO_QUERY_THROW);
        xControllerProperties->addPropertyChangeListener(
            OUString::createFromAscii("CurrentPage"),
            this);

        // Move the current slide in the center of the window.
        const awt::Rectangle aCurrentSlideBBox (mpLayout->GetBoundingBox(mnCurrentSlideIndex));
        const awt::Rectangle aWindowBox (mxWindow->getPosSize());
        SetHorizontalOffset(aCurrentSlideBBox.X - aWindowBox.Width/2.0);
    }
    catch (RuntimeException&)
    {
        disposing();
        throw;
    }
}




PresenterSlideSorter::~PresenterSlideSorter (void)
{
}




void SAL_CALL PresenterSlideSorter::disposing (void)
{
    mxComponentContext = NULL;
    mxViewId = NULL;
    mxPane = NULL;

    if (mpVerticalScrollBar.is())
    {
        Reference<lang::XComponent> xComponent (
            static_cast<XWeak*>(mpVerticalScrollBar.get()), UNO_QUERY);
        mpVerticalScrollBar = NULL;
        if (xComponent.is())
            xComponent->dispose();
    }
    if (mpHorizontalScrollBar.is())
    {
        Reference<lang::XComponent> xComponent (
            static_cast<XWeak*>(mpHorizontalScrollBar.get()), UNO_QUERY);
        mpHorizontalScrollBar = NULL;
        if (xComponent.is())
            xComponent->dispose();
    }
    if (mpCloseButton.is())
    {
        Reference<lang::XComponent> xComponent (
            static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
        mpCloseButton = NULL;
        if (xComponent.is())
            xComponent->dispose();
    }

    if (mxCanvas.is())
    {
        Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
        if (xComponent.is())
            xComponent->removeEventListener(static_cast<awt::XWindowListener*>(this));
        mxCanvas = NULL;
    }
    mpPresenterController = NULL;
    mxSlideShowController = NULL;
    mpLayout.reset();
    mpMouseOverManager.reset();

    if (mxPreviewCache.is())
    {
        mxPreviewCache->removePreviewCreationNotifyListener(this);
        
        Reference<XComponent> xComponent (mxPreviewCache, UNO_QUERY);
        mxPreviewCache = NULL;
        if (xComponent.is())
            xComponent->dispose();
    }

    if (mxWindow.is())
    {
        mxWindow->removeWindowListener(this);
        mxWindow->removePaintListener(this);
        mxWindow->removeMouseListener(this);
        mxWindow->removeMouseMotionListener(this);
    }
}




void PresenterSlideSorter::SetActiveState (const bool bIsActive)
{
    (void)bIsActive;
}




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

void SAL_CALL PresenterSlideSorter::disposing (const lang::EventObject& rEventObject)
    throw (RuntimeException)
{
    if (rEventObject.Source == mxWindow)
    {
        mxWindow = NULL;
        dispose();
    }
    else if (rEventObject.Source == mxPreviewCache)
    {
        mxPreviewCache = NULL;
        dispose();
    }
    else if (rEventObject.Source == mxCanvas)
    {
        mxCanvas = NULL;
        if (mpHorizontalScrollBar.is())
            mpHorizontalScrollBar->SetCanvas(NULL);
        mbIsLayoutPending = true;
        mbIsPaintPending = true;

        mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
    }
}




//----- XWindowListener -------------------------------------------------------
    
void SAL_CALL PresenterSlideSorter::windowResized (const awt::WindowEvent& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
    mbIsLayoutPending = true;
    mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
}




void SAL_CALL PresenterSlideSorter::windowMoved (const awt::WindowEvent& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
}




void SAL_CALL PresenterSlideSorter::windowShown (const lang::EventObject& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
    mbIsLayoutPending = true;
    mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
}




void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
}




//----- XPaintListener --------------------------------------------------------

void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent)
    throw (RuntimeException)
{
    (void)rEvent;

    // Deactivated views must not be painted.
    if ( ! mbIsPresenterViewActive)
        return;

    Paint(rEvent.UpdateRect);

    Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
    if (xSpriteCanvas.is())
        xSpriteCanvas->updateScreen(sal_False);
}




//----- XMouseListener --------------------------------------------------------

void SAL_CALL PresenterSlideSorter::mousePressed (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y);
    mnSlideIndexMousePressed = mpLayout->GetSlideIndexForPosition(aPosition);
}




void SAL_CALL PresenterSlideSorter::mouseReleased (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y);
    const sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));

    if (nSlideIndex == mnSlideIndexMousePressed && mnSlideIndexMousePressed >= 0)
    {
        switch (rEvent.ClickCount)
        {
            case 1:
            default:
                GotoSlide(nSlideIndex);
                break;

            case 2:
                OSL_ASSERT(mpPresenterController.get()!=NULL);
                OSL_ASSERT(mpPresenterController->GetWindowManager().get()!=NULL);
                mpPresenterController->GetWindowManager()->SetSlideSorterState(false);
                GotoSlide(nSlideIndex);
                break;
        }
    }
}




void SAL_CALL PresenterSlideSorter::mouseEntered (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
}




void SAL_CALL PresenterSlideSorter::mouseExited (const css::awt::MouseEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
    mnSlideIndexMousePressed = -1;
    if (mpMouseOverManager.get() != NULL)
        mpMouseOverManager->SetSlide(mnSlideIndexMousePressed, awt::Rectangle(0,0,0,0));
}




//----- XMouseMotionListener --------------------------------------------------
    
void SAL_CALL PresenterSlideSorter::mouseMoved (const css::awt::MouseEvent& rEvent)
    throw (css::uno::RuntimeException)
{
    if (mpMouseOverManager.get() != NULL)
    {
        const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y);
        sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition));

        if (nSlideIndex < 0)
            mnSlideIndexMousePressed = -1;

        if (nSlideIndex < 0)
        {
            mpMouseOverManager->SetSlide(nSlideIndex, awt::Rectangle(0,0,0,0));
        }
        else
        {
            mpMouseOverManager->SetSlide(
                nSlideIndex,
                mpLayout->GetBoundingBox(nSlideIndex));
        }
    }
}




void SAL_CALL PresenterSlideSorter::mouseDragged (const css::awt::MouseEvent& rEvent)
    throw (css::uno::RuntimeException)
{
    (void)rEvent;
}




//----- XResourceId -----------------------------------------------------------

Reference<XResourceId> SAL_CALL PresenterSlideSorter::getResourceId (void)
    throw (RuntimeException)
{
    ThrowIfDisposed();
    return mxViewId;
}




sal_Bool SAL_CALL PresenterSlideSorter::isAnchorOnly (void)
    throw (RuntimeException)
{
    return false;
}




//----- XPropertyChangeListener -----------------------------------------------

void SAL_CALL PresenterSlideSorter::propertyChange (
    const css::beans::PropertyChangeEvent& rEvent)
    throw(css::uno::RuntimeException)
{
    (void)rEvent;
}




//----- XSlidePreviewCacheListener --------------------------------------------
    
void SAL_CALL PresenterSlideSorter::notifyPreviewCreation (
    sal_Int32 nSlideIndex)
    throw(css::uno::RuntimeException)
{
    OSL_ASSERT(mpLayout.get()!=NULL);
    
    awt::Rectangle aBBox (mpLayout->GetBoundingBox(nSlideIndex));
    mpPresenterController->GetPaintManager()->Invalidate(mxWindow, aBBox, true);
}




//----- XDrawView -------------------------------------------------------------

void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
    throw (RuntimeException)
{
    (void)rxSlide;
    
    ThrowIfDisposed();
    ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());

    if (mxSlideShowController.is())
    {
        const sal_Int32 nNewCurrentSlideIndex (mxSlideShowController->getCurrentSlideIndex());
        if (nNewCurrentSlideIndex != mnCurrentSlideIndex)
        {
            mnCurrentSlideIndex = nNewCurrentSlideIndex;

            // Request a repaint of the previous current slide to hide its
            // current slide indicator.
            mpPresenterController->GetPaintManager()->Invalidate(
                mxWindow,
                maCurrentSlideFrameBoundingBox);

            // Request a repaint of the new current slide to show its
            // current slide indicator.
            maCurrentSlideFrameBoundingBox = mpCurrentSlideFrameRenderer->GetBoundingBox(
                mpLayout->GetBoundingBox(mnCurrentSlideIndex));
            mpPresenterController->GetPaintManager()->Invalidate(
                mxWindow,
                maCurrentSlideFrameBoundingBox);
        }
    }
}




Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage (void)
    throw (RuntimeException)
{
    ThrowIfDisposed();
    return NULL;
}




//-----------------------------------------------------------------------------

void PresenterSlideSorter::UpdateLayout (void)
{
    if ( ! mxWindow.is())
        return;

    mbIsLayoutPending = false;
    mbIsPaintPending = true;

    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    awt::Rectangle aCenterBox (aWindowBox);
    sal_Int32 nLeftBorderWidth (aWindowBox.X);

    // Get border width.
    PresenterPaneContainer::SharedPaneDescriptor pPane (
        mpPresenterController->GetPaneContainer()->FindViewURL(
            mxViewId->getResourceURL()));
    do
    {
        if (pPane.get() == NULL)
            break;
        if ( ! pPane->mxPane.is())
            break;

        Reference<drawing::framework::XPaneBorderPainter> xBorderPainter (
            pPane->mxPane->GetPaneBorderPainter());
        if ( ! xBorderPainter.is())
            break;
        aCenterBox = xBorderPainter->addBorder (
            mxViewId->getAnchor()->getResourceURL(),
            awt::Rectangle(0, 0, aWindowBox.Width, aWindowBox.Height),
            drawing::framework::BorderType_INNER_BORDER);
    }
    while(false);

    // Place vertical separator.
    mnSeparatorY = aWindowBox.Height - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;

    PlaceCloseButton(pPane, aWindowBox, nLeftBorderWidth);

    geometry::RealRectangle2D aUpperBox(
        gnHorizontalBorder,
        gnVerticalBorder,
        aWindowBox.Width - 2*gnHorizontalBorder,
        mnSeparatorY - gnVerticalGap);

    // Determine whether the scroll bar has to be displayed.
    aUpperBox = PlaceScrollBars(aUpperBox);

    mpLayout->Update(aUpperBox, GetSlideAspectRatio());
    mpLayout->SetupVisibleArea();
    mpLayout->UpdateScrollBars();

    // Tell the preview cache about some of the values.
    mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize);
    mxPreviewCache->setVisibleRange(
        mpLayout->GetFirstVisibleSlideIndex(),
        mpLayout->GetLastVisibleSlideIndex());

    // Clear the frame polygon so that it is re-created on the next paint.
    mxPreviewFrame = NULL;
}




geometry::RealRectangle2D PresenterSlideSorter::PlaceScrollBars (
    const geometry::RealRectangle2D& rUpperBox)
{
    mpLayout->Update(rUpperBox, GetSlideAspectRatio());
    bool bIsScrollBarNeeded (false);
    Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY_THROW);
    if (xSlides.is())
        bIsScrollBarNeeded = mpLayout->IsScrollBarNeeded(xSlides->getCount());
    
    if (mpLayout->GetOrientation() == Layout::Vertical)
    {
        if (mpVerticalScrollBar.get() != NULL)
        {
            if (bIsScrollBarNeeded)
            {
                // Place vertical scroll bar at right border.
                mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D(
                    rUpperBox.X2 - mpVerticalScrollBar->GetSize(),
                    rUpperBox.Y1,
                    rUpperBox.X2,
                    rUpperBox.Y2));
                mpVerticalScrollBar->SetVisible(true);

                // Reduce area covered by the scroll bar from the available
                // space.
                return geometry::RealRectangle2D(
                    rUpperBox.X1,
                    rUpperBox.Y1,
                    rUpperBox.X2 - mpVerticalScrollBar->GetSize() - gnHorizontalGap,
                    rUpperBox.Y2);
            }
            else
                mpVerticalScrollBar->SetVisible(false);
        }
    }
    else
    {
        if (mpHorizontalScrollBar.get() != NULL)
        {
            if (bIsScrollBarNeeded)
            {
                // Place horixontal scroll bar at the bottom.
                mpHorizontalScrollBar->SetPosSize(geometry::RealRectangle2D(
                    rUpperBox.X1,
                    rUpperBox.Y2 - mpHorizontalScrollBar->GetSize(),
                    rUpperBox.X2,
                    rUpperBox.Y2));
                mpHorizontalScrollBar->SetVisible(true);
                
                // Reduce area covered by the scroll bar from the available
                // space.
                return geometry::RealRectangle2D(
                    rUpperBox.X1,
                    rUpperBox.Y1,
                    rUpperBox.X2,
                    rUpperBox.Y2 - mpHorizontalScrollBar->GetSize() - gnVerticalGap);
            }
            else
            mpHorizontalScrollBar->SetVisible(false);
        }
    }

    return rUpperBox;
}




void PresenterSlideSorter::PlaceCloseButton (
    const PresenterPaneContainer::SharedPaneDescriptor& rpPane,
    const awt::Rectangle& rCenterBox,
    const sal_Int32 nLeftBorderWidth)
{
    // Place button.  When the callout is near the center then the button is
    // centered over the callout.  Otherwise it is centered with respect to
    // the whole window.
    sal_Int32 nCloseButtonCenter (rCenterBox.Width/2);
    if (rpPane.get() != NULL && rpPane->mxPane.is())
    {
        const sal_Int32 nCalloutCenter (rpPane->mxPane->GetCalloutAnchor().X - nLeftBorderWidth);
        const sal_Int32 nDistanceFromWindowCenter (abs(nCalloutCenter - rCenterBox.Width/2));
        const sal_Int32 nButtonWidth (mpCloseButton->GetSize().Width);
        const static sal_Int32 nMaxDistanceForCalloutCentering (nButtonWidth * 2);
        if (nDistanceFromWindowCenter < nMaxDistanceForCalloutCentering)
        {
            if (nCalloutCenter < nButtonWidth/2)
                nCloseButtonCenter = nButtonWidth/2;
            else if (nCalloutCenter > rCenterBox.Width-nButtonWidth/2)
                nCloseButtonCenter = rCenterBox.Width-nButtonWidth/2;
            else
                nCloseButtonCenter = nCalloutCenter;
        }
    }
    mpCloseButton->SetCenter(geometry::RealPoint2D(
        nCloseButtonCenter,
        rCenterBox.Height - mpCloseButton->GetSize().Height/ 2));
}




void PresenterSlideSorter::ClearBackground (
    const Reference<rendering::XCanvas>& rxCanvas,
    const awt::Rectangle& rUpdateBox)
{
    OSL_ASSERT(rxCanvas.is());

    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    mpPresenterController->GetCanvasHelper()->Paint(
        mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
        rxCanvas,
        rUpdateBox,
        awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
        awt::Rectangle());
}




double PresenterSlideSorter::GetSlideAspectRatio (void) const
{
    double nSlideAspectRatio (28.0/21.0);
    
    try
    {
        Reference<container::XIndexAccess> xSlides(mxSlideShowController, UNO_QUERY_THROW);
        if (mxSlideShowController.is() && xSlides->getCount()>0)
        {
            Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
            sal_Int32 nWidth (28000);
            sal_Int32 nHeight (21000);
            if ((xProperties->getPropertyValue(OUString::createFromAscii("Width")) >>= nWidth)
                && (xProperties->getPropertyValue(OUString::createFromAscii("Height")) >>= nHeight)
                && nHeight > 0)
            {
                nSlideAspectRatio = double(nWidth) / double(nHeight);
            }
        }
    }
    catch (RuntimeException&)
    {
        OSL_ASSERT(false);
    }

    return nSlideAspectRatio;
}




Reference<rendering::XBitmap> PresenterSlideSorter::GetPreview (const sal_Int32 nSlideIndex)
{
    if (nSlideIndex < 0 || nSlideIndex>=mpLayout->mnSlideCount)
        return NULL;
    else if (mxPane.is())
        return mxPreviewCache->getSlidePreview(nSlideIndex, mxPane->getCanvas());
    else
        return NULL;
}




void PresenterSlideSorter::PaintPreview (
    const Reference<rendering::XCanvas>& rxCanvas,
    const css::awt::Rectangle& rUpdateBox,
    const sal_Int32 nSlideIndex)
{
    OSL_ASSERT(rxCanvas.is());

    geometry::IntegerSize2D aSize (mpLayout->maPreviewSize);

    if (PresenterGeometryHelper::AreRectanglesDisjoint(
        rUpdateBox,
        mpLayout->GetBoundingBox(nSlideIndex)))
    {
        return;
    }

    Reference<rendering::XBitmap> xPreview (GetPreview(nSlideIndex));

    const geometry::RealPoint2D aTopLeft (
        mpLayout->GetWindowPosition(
            mpLayout->GetPoint(nSlideIndex, -1, -1)));

    // Create clip rectangle as intersection of the current update area and
    // the bounding box of all previews.
    geometry::RealRectangle2D aBoundingBox (mpLayout->maBoundingBox);
    aBoundingBox.Y2 += 1;
    const geometry::RealRectangle2D aClipBox (
        PresenterGeometryHelper::Intersection(
            PresenterGeometryHelper::ConvertRectangle(rUpdateBox),
            aBoundingBox));
    Reference<rendering::XPolyPolygon2D> xClip (
        PresenterGeometryHelper::CreatePolygon(aClipBox, rxCanvas->getDevice()));

    const rendering::ViewState aViewState (geometry::AffineMatrix2D(1,0,0, 0,1,0), xClip);


    rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(
            1, 0, aTopLeft.X,
            0, 1, aTopLeft.Y),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);


    // Emphasize the current slide.
    if (nSlideIndex == mnCurrentSlideIndex)
    {
        if (mpCurrentSlideFrameRenderer.get() != NULL)
        {
            const awt::Rectangle aSlideBoundingBox(
                sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.X),
                sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.Y),
                aSize.Width,
                aSize.Height);
            maCurrentSlideFrameBoundingBox
                = mpCurrentSlideFrameRenderer->GetBoundingBox(aSlideBoundingBox);
            mpCurrentSlideFrameRenderer->PaintCurrentSlideFrame (
                aSlideBoundingBox,
                mxCanvas,
                aClipBox);
        }
    }

    // Paint the preview.
    if (xPreview.is())
    {
        aSize = xPreview->getSize();
        if (aSize.Width > 0 && aSize.Height > 0)
        {
            rxCanvas->drawBitmap(xPreview, aViewState, aRenderState);
        }
    }

    // Create a polygon that is used to paint a frame around previews.  Its
    // coordinates are chosen in the local coordinate system of a preview.
    if ( ! mxPreviewFrame.is())
        mxPreviewFrame = PresenterGeometryHelper::CreatePolygon(
            awt::Rectangle(-1, -1, aSize.Width+2, aSize.Height+2),
            rxCanvas->getDevice());

    // Paint a border around the preview.
    if (mxPreviewFrame.is())
    {
        const geometry::RealRectangle2D aBox (0, 0, aSize.Width, aSize.Height);
        const util::Color aFrameColor (0x00000000);
        PresenterCanvasHelper::SetDeviceColor(aRenderState, aFrameColor);
        rxCanvas->drawPolyPolygon(mxPreviewFrame, aViewState, aRenderState);
    }

    // Paint mouse over effect.
    mpMouseOverManager->Paint(nSlideIndex, mxCanvas, xClip);
}




void PresenterSlideSorter::Paint (const awt::Rectangle& rUpdateBox)
{
    const bool bCanvasChanged ( ! mxCanvas.is());
    if ( ! ProvideCanvas())
        return;

    if (mpLayout->mnRowCount<=0 || mpLayout->mnColumnCount<=0)
    {
        OSL_ASSERT(mpLayout->mnRowCount>0 || mpLayout->mnColumnCount>0);
        return;
    }

    mbIsPaintPending = false;

    ClearBackground(mxCanvas, rUpdateBox);

    // Give the canvas to the controls.
    if (bCanvasChanged)
    {
        if (mpHorizontalScrollBar.is())
            mpHorizontalScrollBar->SetCanvas(mxCanvas);
        if (mpVerticalScrollBar.is())
            mpVerticalScrollBar->SetCanvas(mxCanvas);
        if (mpCloseButton.is())
            mpCloseButton->SetCanvas(mxCanvas, mxWindow);
    }

    // Now that the controls have a canvas we can do the layouting.
    if (mbIsLayoutPending)
        UpdateLayout();

    // Paint the horizontal separator.
    rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0),
            NULL, Sequence<double>(4), rendering::CompositeOperation::SOURCE);
    PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor);
    mxCanvas->drawLine(
        geometry::RealPoint2D(0, mnSeparatorY),
        geometry::RealPoint2D(mxWindow->getPosSize().Width, mnSeparatorY),
        rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
        aRenderState);
        
    // Paint the slides.
    if ( ! PresenterGeometryHelper::AreRectanglesDisjoint(
        rUpdateBox,
        PresenterGeometryHelper::ConvertRectangle(mpLayout->maBoundingBox)))
    {
        mpLayout->ForAllVisibleSlides(
            ::boost::bind(&PresenterSlideSorter::PaintPreview, this, mxCanvas, rUpdateBox, _1));
    }

    Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
    if (xSpriteCanvas.is())
        xSpriteCanvas->updateScreen(sal_False);
}




void PresenterSlideSorter::SetHorizontalOffset (const double nXOffset)
{
    if (mpLayout->SetHorizontalOffset(nXOffset))
    {
        mxPreviewCache->setVisibleRange(
            mpLayout->GetFirstVisibleSlideIndex(),
            mpLayout->GetLastVisibleSlideIndex());

        mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
    }
}




void PresenterSlideSorter::SetVerticalOffset (const double nYOffset)
{
    if (mpLayout->SetVerticalOffset(nYOffset))
    {
        mxPreviewCache->setVisibleRange(
            mpLayout->GetFirstVisibleSlideIndex(),
            mpLayout->GetLastVisibleSlideIndex());

        mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
    }
}




void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex)
{
    mxSlideShowController->gotoSlideIndex(nSlideIndex);
    mpPresenterController->HideSlideSorter();
}




bool PresenterSlideSorter::ProvideCanvas (void)
{
    if ( ! mxCanvas.is())
    {
        if (mxPane.is())
            mxCanvas = mxPane->getCanvas();

        // Register as event listener so that we are informed when the
        // canvas is disposed (and we have to fetch another one).
        Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
        if (xComponent.is())
            xComponent->addEventListener(static_cast<awt::XWindowListener*>(this));

        // Tell the scrollbar about the canvas.
        if (mpHorizontalScrollBar.is())
            mpHorizontalScrollBar->SetCanvas(mxCanvas);

        mpCurrentSlideFrameRenderer.reset(
            new CurrentSlideFrameRenderer(mxComponentContext, mxCanvas));
    }
    return mxCanvas.is();
}




void PresenterSlideSorter::ThrowIfDisposed (void)
    throw (lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        throw lang::DisposedException (
            OUString(RTL_CONSTASCII_USTRINGPARAM(
                "PresenterSlideSorter has been already disposed")),
            const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}




//===== PresenterSlideSorter::Layout ==========================================

PresenterSlideSorter::Layout::Layout (
    const Orientation eOrientation,
    const ::rtl::Reference<PresenterScrollBar>& rpHorizontalScrollBar,
    const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar)
    : maBoundingBox(),
      maPreviewSize(),
      mnHorizontalOffset(0),
      mnVerticalOffset(0),
      mnHorizontalGap(0),
      mnVerticalGap(0),
      mnHorizontalBorder(0),
      mnVerticalBorder(0),
      mnRowCount(1),
      mnColumnCount(1),
      mnSlideCount(0),
      mnSlideIndexAtMouse(-1),
      mnFirstVisibleColumn(-1),
      mnLastVisibleColumn(-1),
      mnFirstVisibleRow(-1),
      mnLastVisibleRow(-1),
      meOrientation(eOrientation),
      mpHorizontalScrollBar(rpHorizontalScrollBar),
      mpVerticalScrollBar(rpVerticalScrollBar)
{
}




void PresenterSlideSorter::Layout::Update (
    const geometry::RealRectangle2D& rBoundingBox,
    const double nSlideAspectRatio)
{
    maBoundingBox = rBoundingBox;
    
    mnHorizontalBorder = gnHorizontalBorder;
    mnVerticalBorder = gnVerticalBorder;

    const double nWidth (rBoundingBox.X2 - rBoundingBox.X1 - 2*mnHorizontalBorder);
    const double nHeight (rBoundingBox.Y2 - rBoundingBox.Y1 - 2*mnVerticalBorder);
    if (nWidth<=0 || nHeight<=0)
        return;

    double nPreviewWidth;
    
    // Determine column count, preview width, and horizontal gap (borders
    // are half the gap).  Try to use the preferred values.  Try more to
    // stay in the valid intervalls.  This last constraint may be not
    // fullfilled in some cases.
    const double nElementWidth = nWidth / gnPreferredColumnCount;
    if (nElementWidth < gnMinimalPreviewWidth + gnMinimalHorizontalPreviewGap)
    {
        // The preferred column count is too large.
        // Can we use the preferred preview width?
        if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
        {
            // Yes.
            nPreviewWidth = gnPreferredPreviewWidth;
            mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
                / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
            mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
        }
        else
        {
            // No.  Set the column count to 1 and adapt preview width and
            // gap.
            mnColumnCount = 1;
            mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
            if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth)
                nPreviewWidth = nWidth - gnMinimalHorizontalPreviewGap;
            else
                nPreviewWidth = ::std::max(gnMinimalPreviewWidth, nWidth-mnHorizontalGap);
        }
    }
    else if (nElementWidth > gnMaximalPreviewWidth + gnMaximalHorizontalPreviewGap)
    {
        // The preferred column count is too small.
        nPreviewWidth = gnPreferredPreviewWidth;
        mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap)
            / (nPreviewWidth+gnPreferredHorizontalPreviewGap));
        mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
    }
    else
    {
        // The preferred column count is possible.  Determine gap and
        // preview width.
        mnColumnCount = gnPreferredColumnCount;
        if (nElementWidth - gnPreferredPreviewWidth < gnMinimalHorizontalPreviewGap)
        {
            // Use the minimal gap and adapt the preview width.
            mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap);
            nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
        }
        else if (nElementWidth - gnPreferredPreviewWidth <= gnMaximalHorizontalPreviewGap)
        {
            // Use the maximal gap and adapt the preview width.
            mnHorizontalGap = round(gnMaximalHorizontalPreviewGap);
            nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount;
        }
        else
        {
            // Use the preferred preview width and adapt the gap.
            nPreviewWidth = gnPreferredPreviewWidth;
            mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount);
        }
    }

    // Now determine the row count, preview height, and vertical gap.
    const double nPreviewHeight = nPreviewWidth / nSlideAspectRatio;
    mnRowCount = ::std::max(
        sal_Int32(1),
        sal_Int32(ceil((nHeight+gnPreferredVerticalPreviewGap)
                / (nPreviewHeight + gnPreferredVerticalPreviewGap))));
    mnVerticalGap = round(gnPreferredVerticalPreviewGap);

    maPreviewSize = geometry::IntegerSize2D(floor(nPreviewWidth), floor(nPreviewHeight));

    // Reset the offset.
    if (meOrientation == Horizontal)
    {
        mnVerticalOffset = round(-(nHeight
            - mnRowCount*maPreviewSize.Height - (mnRowCount-1)*mnVerticalGap)
            / 2);
        mnHorizontalOffset = 0;
    }
    else
    {
        mnVerticalOffset = 0;
        mnHorizontalOffset = round(-(nWidth
            - mnColumnCount*maPreviewSize.Width
            - (mnColumnCount-1)*mnHorizontalGap)
            / 2);
    }
}




void PresenterSlideSorter::Layout::SetupVisibleArea (void)
{
    geometry::RealPoint2D aPoint (GetLocalPosition(
        geometry::RealPoint2D(maBoundingBox.X1, maBoundingBox.Y1)));
    if (meOrientation == Horizontal)
    {
        mnFirstVisibleColumn = ::std::max(sal_Int32(0), GetColumn(aPoint));
        mnFirstVisibleRow = 0;
    }
    else
    {
        mnFirstVisibleColumn = 0;
        mnFirstVisibleRow = ::std::max(sal_Int32(0), GetRow(aPoint));
    }
    
    aPoint = GetLocalPosition(geometry::RealPoint2D( maBoundingBox.X2, maBoundingBox.Y2));
    if (meOrientation == Horizontal)
    {
        mnLastVisibleColumn = GetColumn(aPoint, true);
        mnLastVisibleRow = mnRowCount - 1;
    }
    else
    {
        mnLastVisibleColumn = mnColumnCount - 1;
        mnLastVisibleRow = GetRow(aPoint, true);
    }
}




bool PresenterSlideSorter::Layout::IsScrollBarNeeded (const sal_Int32 nSlideCount)
{
    geometry::RealPoint2D aBottomRight;
    if (GetOrientation() == Layout::Vertical)
        aBottomRight = GetPoint(
            mnColumnCount * (GetRow(nSlideCount)+1) - 1, +1, +1);
    else
        aBottomRight = GetPoint(
            mnRowCount * (GetColumn(nSlideCount)+1) - 1, +1, +1);
    return aBottomRight.X > maBoundingBox.X2-maBoundingBox.X1
        || aBottomRight.Y > maBoundingBox.Y2-maBoundingBox.Y1;
}




geometry::RealPoint2D PresenterSlideSorter::Layout::GetLocalPosition(
    const geometry::RealPoint2D& rWindowPoint) const
{
    return css::geometry::RealPoint2D(
        rWindowPoint.X - maBoundingBox.X1 + mnHorizontalOffset,
        rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset);
}




geometry::RealPoint2D PresenterSlideSorter::Layout::GetWindowPosition(
    const geometry::RealPoint2D& rLocalPoint) const
{
    return css::geometry::RealPoint2D(
        rLocalPoint.X - mnHorizontalOffset + maBoundingBox.X1,
        rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1);
}




sal_Int32 PresenterSlideSorter::Layout::GetColumn (
    const css::geometry::RealPoint2D& rLocalPoint,
    const bool bReturnInvalidValue) const
{
    const sal_Int32 nColumn(floor(
        (rLocalPoint.X + mnHorizontalGap/2.0) / (maPreviewSize.Width+mnHorizontalGap)));
    if (bReturnInvalidValue
        || (nColumn>=mnFirstVisibleColumn && nColumn<=mnLastVisibleColumn))
    {
        return nColumn;
    }
    else
        return -1;
}




sal_Int32 PresenterSlideSorter::Layout::GetRow (
    const css::geometry::RealPoint2D& rLocalPoint,
    const bool bReturnInvalidValue) const
{
    const sal_Int32 nRow (floor(
        (rLocalPoint.Y + mnVerticalGap/2.0) / (maPreviewSize.Height+mnVerticalGap)));
    if (bReturnInvalidValue
        || (nRow>=mnFirstVisibleRow && nRow<=mnLastVisibleRow))
    {
        return nRow;
    }
    else
        return -1;
}




sal_Int32 PresenterSlideSorter::Layout::GetSlideIndexForPosition (
    const css::geometry::RealPoint2D& rWindowPoint) const
{
    if ( ! PresenterGeometryHelper::IsInside(maBoundingBox, rWindowPoint))
        return -1;

    const css::geometry::RealPoint2D aLocalPosition (GetLocalPosition(rWindowPoint));
    const sal_Int32 nColumn (GetColumn(aLocalPosition));
    const sal_Int32 nRow (GetRow(aLocalPosition));

    if (nColumn < 0 || nRow < 0)
        return -1;
    else
    {
        sal_Int32 nIndex (GetIndex(nRow, nColumn));
        if (nIndex >= mnSlideCount)
            return -1;
        else
            return nIndex;
    }
}




geometry::RealPoint2D PresenterSlideSorter::Layout::GetPoint (
    const sal_Int32 nSlideIndex,
    const sal_Int32 nRelativeHorizontalPosition,
    const sal_Int32 nRelativeVerticalPosition) const
{
    sal_Int32 nColumn (GetColumn(nSlideIndex));
    sal_Int32 nRow (GetRow(nSlideIndex));
        
    geometry::RealPoint2D aPosition (
        mnHorizontalBorder + nColumn*(maPreviewSize.Width+mnHorizontalGap),
        mnVerticalBorder + nRow*(maPreviewSize.Height+mnVerticalGap));

    if (nRelativeHorizontalPosition >= 0)
    {
        if (nRelativeHorizontalPosition > 0)
            aPosition.X += maPreviewSize.Width;
        else
            aPosition.X += maPreviewSize.Width / 2.0;
    }
    if (nRelativeVerticalPosition >= 0)
    {
        if (nRelativeVerticalPosition > 0)
            aPosition.Y += maPreviewSize.Height;
        else
            aPosition.Y += maPreviewSize.Height / 2.0;
    }

    return aPosition;
}




awt::Rectangle PresenterSlideSorter::Layout::GetBoundingBox (const sal_Int32 nSlideIndex) const
{
    const geometry::RealPoint2D aWindowPosition(GetWindowPosition(GetPoint(nSlideIndex, -1, -1)));
    return PresenterGeometryHelper::ConvertRectangle(
        geometry::RealRectangle2D(
            aWindowPosition.X,
            aWindowPosition.Y,
            aWindowPosition.X + maPreviewSize.Width,
            aWindowPosition.Y + maPreviewSize.Height));
}




void PresenterSlideSorter::Layout::ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction)
{
    for (sal_Int32 nRow=mnFirstVisibleRow; nRow<=mnLastVisibleRow; ++nRow)
    {
        for (sal_Int32 nColumn=mnFirstVisibleColumn; nColumn<=mnLastVisibleColumn; ++nColumn)
        {
            const sal_Int32 nSlideIndex (GetIndex(nRow, nColumn));
            if (nSlideIndex >= mnSlideCount)
                return;
            rAction(nSlideIndex);
        }
    }
}




sal_Int32 PresenterSlideSorter::Layout::GetFirstVisibleSlideIndex (void) const
{
    return GetIndex(mnFirstVisibleRow, mnFirstVisibleColumn);
}




sal_Int32 PresenterSlideSorter::Layout::GetLastVisibleSlideIndex (void) const
{
    return ::std::min(
        GetIndex(mnLastVisibleRow, mnLastVisibleColumn),
        mnSlideCount);
}




bool PresenterSlideSorter::Layout::SetHorizontalOffset (const double nOffset)
{
    if (mnHorizontalOffset != nOffset)
    {
        mnHorizontalOffset = round(nOffset);
        SetupVisibleArea();
        UpdateScrollBars();
        return true;
    }
    else
        return false;
}




bool PresenterSlideSorter::Layout::SetVerticalOffset (const double nOffset)
{
    if (mnVerticalOffset != nOffset)
    {
        mnVerticalOffset = round(nOffset);
        SetupVisibleArea();
        UpdateScrollBars();
        return true;
    }
    else
        return false;
}




PresenterSlideSorter::Layout::Orientation
    PresenterSlideSorter::Layout::GetOrientation (void) const
{
    return meOrientation;
}




void PresenterSlideSorter::Layout::UpdateScrollBars (void)
{
    sal_Int32 nTotalColumnCount (0);
    sal_Int32 nTotalRowCount (0);
    if (meOrientation == Horizontal)
    {
        nTotalColumnCount = sal_Int32(ceil(double(mnSlideCount) / double(mnRowCount)));
        nTotalRowCount = mnRowCount;
    }
    else
    {
        nTotalColumnCount = mnColumnCount;
        nTotalRowCount = sal_Int32(ceil(double(mnSlideCount) / double(mnColumnCount)));
    }
    
    if (mpHorizontalScrollBar.get() != NULL)
    {
        mpHorizontalScrollBar->SetTotalSize(
            nTotalColumnCount * maPreviewSize.Width
            + (nTotalColumnCount-1) * mnHorizontalGap
            + 2*mnHorizontalBorder);
        mpHorizontalScrollBar->SetThumbPosition(mnHorizontalOffset, false);
        mpHorizontalScrollBar->SetThumbSize(maBoundingBox.X2 - maBoundingBox.X1 + 1);
        mpHorizontalScrollBar->SetLineHeight(maPreviewSize.Width);
    }
    if (mpVerticalScrollBar.get() != NULL)
    {
        mpVerticalScrollBar->SetTotalSize(
            nTotalRowCount * maPreviewSize.Height
                + (nTotalRowCount-1) * mnVerticalGap
            + 2*mnVerticalGap);
        mpVerticalScrollBar->SetThumbPosition(mnVerticalOffset, false);
        mpVerticalScrollBar->SetThumbSize(maBoundingBox.Y2 - maBoundingBox.Y1 + 1);
        mpVerticalScrollBar->SetLineHeight(maPreviewSize.Height);
    }

    

    // No place yet for the vertical scroll bar.
}




sal_Int32 PresenterSlideSorter::Layout::GetIndex (
    const sal_Int32 nRow,
    const sal_Int32 nColumn) const
{
    if (meOrientation == Horizontal)
        return nColumn * mnRowCount + nRow;
    else
        return nRow * mnColumnCount + nColumn;
}




sal_Int32 PresenterSlideSorter::Layout::GetRow (const sal_Int32 nSlideIndex) const
{
    if (meOrientation == Horizontal)
        return nSlideIndex % mnRowCount;
    else
        return nSlideIndex / mnColumnCount;
}




sal_Int32 PresenterSlideSorter::Layout::GetColumn (const sal_Int32 nSlideIndex) const
{
    if (meOrientation == Horizontal)
        return nSlideIndex / mnRowCount;
    else
        return nSlideIndex % mnColumnCount;
}




//===== PresenterSlideSorter::MouseOverManager ================================

PresenterSlideSorter::MouseOverManager::MouseOverManager (
    const Reference<container::XIndexAccess>& rxSlides,
    const ::boost::shared_ptr<PresenterTheme>& rpTheme,
    const Reference<awt::XWindow>& rxInvalidateTarget,
    const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager)
    : mxCanvas(),
      mxSlides(rxSlides),
      mpLeftLabelBitmap(),
      mpCenterLabelBitmap(),
      mpRightLabelBitmap(),
      mpFont(),
      mnSlideIndex(-1),
      maSlideBoundingBox(),
      mxInvalidateTarget(rxInvalidateTarget),
      mpPaintManager(rpPaintManager)
{
    if (rpTheme.get()!=NULL)
    {
        ::boost::shared_ptr<PresenterBitmapContainer> pBitmaps (rpTheme->GetBitmapContainer());
        if (pBitmaps.get() != NULL)
        {
            mpLeftLabelBitmap = pBitmaps->GetBitmap(A2S("LabelLeft"));
            mpCenterLabelBitmap = pBitmaps->GetBitmap(A2S("LabelCenter"));
            mpRightLabelBitmap = pBitmaps->GetBitmap(A2S("LabelRight"));
        }

        mpFont = rpTheme->GetFont(A2S("SlideSorterLabelFont"));
    }
}




PresenterSlideSorter::MouseOverManager::~MouseOverManager (void)
{
}




void PresenterSlideSorter::MouseOverManager::Paint (
    const sal_Int32 nSlideIndex,
    const Reference<rendering::XCanvas>& rxCanvas,
    const Reference<rendering::XPolyPolygon2D>& rxClip)
{
    if (nSlideIndex != mnSlideIndex)
        return;
    
    if (mxCanvas != rxCanvas)
        SetCanvas(rxCanvas);
    if (rxCanvas != NULL)
    {
        if ( ! mxBitmap.is())
            mxBitmap = CreateBitmap(msText, maSlideBoundingBox.Width);
        if (mxBitmap.is())
        {
            geometry::IntegerSize2D aSize (mxBitmap->getSize());
            const double nXOffset (maSlideBoundingBox.X
                + (maSlideBoundingBox.Width - aSize.Width) / 2.0);
            const double nYOffset (maSlideBoundingBox.Y
                + (maSlideBoundingBox.Height - aSize.Height) / 2.0);
            rxCanvas->drawBitmap(
                mxBitmap,
                rendering::ViewState(
                    geometry::AffineMatrix2D(1,0,0, 0,1,0),
                    rxClip),
                rendering::RenderState(
                    geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
                    NULL,
                    Sequence<double>(4),
                    rendering::CompositeOperation::SOURCE));
        }
    }
}




void PresenterSlideSorter::MouseOverManager::SetCanvas (
    const Reference<rendering::XCanvas>& rxCanvas)
{
    mxCanvas = rxCanvas;
    if (mpFont.get() != NULL)
        mpFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
}




void PresenterSlideSorter::MouseOverManager::SetSlide (
    const sal_Int32 nSlideIndex,
    const awt::Rectangle& rBox)
{
    if (mnSlideIndex == nSlideIndex)
        return;

    mnSlideIndex = -1;
    Invalidate();

    maSlideBoundingBox = rBox;
    mnSlideIndex = nSlideIndex;
    
    if (nSlideIndex >= 0)
    {
        if (mxSlides.get() != NULL)
        {
            msText = OUString();

            Reference<beans::XPropertySet> xSlideProperties(mxSlides->getByIndex(nSlideIndex), UNO_QUERY);
            if (xSlideProperties.is())
                xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= msText;

            if (msText.getLength() == 0)
                msText = A2S("Slide ") + OUString::valueOf(nSlideIndex + 1);
        }
    }
    else
    {
        msText = OUString();
    }
    mxBitmap = NULL;

    Invalidate();
}




Reference<rendering::XBitmap> PresenterSlideSorter::MouseOverManager::CreateBitmap (
    const OUString& rsText,
    const sal_Int32 nMaximalWidth) const
{
    if ( ! mxCanvas.is())
        return NULL;

    if (mpFont.get()==NULL || !mpFont->mxFont.is())
        return NULL;

    // Long text has to be shortened.
    const OUString sText (GetFittingText(rsText, nMaximalWidth
            - 2*gnHorizontalLabelBorder
            - 2*gnHorizontalLabelPadding));

    // Determine the size of the label.  Its height is defined by the
    // bitmaps that are used to paints its background.  The width is defined
    // by the text.
    geometry::IntegerSize2D aLabelSize (CalculateLabelSize(sText));
    
    // Create a new bitmap that will contain the complete label.
    Reference<rendering::XBitmap> xBitmap (
        mxCanvas->getDevice()->createCompatibleAlphaBitmap(aLabelSize));

    if ( ! xBitmap.is())
        return NULL;
    
    Reference<rendering::XBitmapCanvas> xBitmapCanvas (xBitmap, UNO_QUERY);
    if ( ! xBitmapCanvas.is())
        return NULL;
    
    // Paint the background.
    PaintButtonBackground(xBitmapCanvas, aLabelSize);

    // Paint the text.
    if (sText.getLength() > 0)
    {

        const rendering::StringContext aContext (sText, 0, sText.getLength());
        const Reference<rendering::XTextLayout> xLayout (mpFont->mxFont->createTextLayout(
            aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
        const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());

        const double nXOffset = (aLabelSize.Width - aTextBBox.X2 + aTextBBox.X1) / 2;
        const double nYOffset = aLabelSize.Height
            - (aLabelSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y2;

        const rendering::ViewState aViewState(
            geometry::AffineMatrix2D(1,0,0, 0,1,0),
            NULL);
                
        rendering::RenderState aRenderState (
            geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset),
            NULL,
            Sequence<double>(4),
            rendering::CompositeOperation::SOURCE);
        PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);

        xBitmapCanvas->drawText(
            aContext,
            mpFont->mxFont,
            aViewState,
            aRenderState,
            rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
    }

    return xBitmap;
}




OUString PresenterSlideSorter::MouseOverManager::GetFittingText (
    const OUString& rsText,
    const double nMaximalWidth) const
{
    const double nTextWidth (
        PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText).Width);
    if (nTextWidth > nMaximalWidth)
    {
        // Text is too wide.  Shorten it by removing characters from the end
        // and replacing them by ellipses.

        // Guess a start value of the final string length.
        double nBestWidth (0);
        OUString sBestCandidate;
        sal_Int32 nLength (round(rsText.getLength() * nMaximalWidth / nTextWidth));
        const OUString sEllipses (A2S("..."));
        while (true)
        {
            const OUString sCandidate (rsText.copy(0,nLength) + sEllipses);
            const double nWidth (
                PresenterCanvasHelper::GetTextSize(mpFont->mxFont, sCandidate).Width);
            if (nWidth > nMaximalWidth)
            {
                // Candidate still too wide, shorten it.
                nLength -= 1;
                if (nLength <= 0)
                    break;
            }
            else if (nWidth < nMaximalWidth)
            {
                // Candidate short enough.
                if (nWidth > nBestWidth)
                {
                    // Best length so far.
                    sBestCandidate = sCandidate;
                    nBestWidth = nWidth;
                    nLength += 1;
                    if (nLength >= rsText.getLength())
                        break;
                }
                else
                    break;
            }
            else
            {
                // Candidate is exactly as long as it may be.  Use it
                // without looking any further.
                sBestCandidate = sCandidate;
                break;
            }
        }
        return sBestCandidate;
    }
    else
        return rsText;
}




geometry::IntegerSize2D PresenterSlideSorter::MouseOverManager::CalculateLabelSize (
    const OUString& rsText) const
{
    // Height is specified by the label bitmaps.
    sal_Int32 nHeight (32);
    if (mpCenterLabelBitmap.get() != NULL)
    {
        Reference<rendering::XBitmap> xBitmap (mpCenterLabelBitmap->GetNormalBitmap());
        if (xBitmap.is())
            nHeight = xBitmap->getSize().Height;
    }

    // Width is specified by text width and maximal width.
    const geometry::RealSize2D aTextSize (
        PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText));
    
    const sal_Int32 nWidth (round(aTextSize.Width + 2*gnHorizontalLabelPadding));

    return geometry::IntegerSize2D(nWidth, nHeight);
}




void PresenterSlideSorter::MouseOverManager::PaintButtonBackground (
    const Reference<rendering::XBitmapCanvas>& rxCanvas,
    const geometry::IntegerSize2D& rSize) const
{
    // Get the bitmaps for painting the label background.
    Reference<rendering::XBitmap> xLeftLabelBitmap;
    if (mpLeftLabelBitmap.get() != NULL)
        xLeftLabelBitmap = mpLeftLabelBitmap->GetNormalBitmap();
            
    Reference<rendering::XBitmap> xCenterLabelBitmap;
    if (mpCenterLabelBitmap.get() != NULL)
        xCenterLabelBitmap = mpCenterLabelBitmap->GetNormalBitmap();
            
    Reference<rendering::XBitmap> xRightLabelBitmap;
    if (mpRightLabelBitmap.get() != NULL)
        xRightLabelBitmap = mpRightLabelBitmap->GetNormalBitmap();

    PresenterUIPainter::PaintHorizontalBitmapComposite (
        Reference<rendering::XCanvas>(rxCanvas, UNO_QUERY),
        awt::Rectangle(0,0, rSize.Width,rSize.Height),
        awt::Rectangle(0,0, rSize.Width,rSize.Height),
        xLeftLabelBitmap,
        xCenterLabelBitmap,
        xRightLabelBitmap);
}




void PresenterSlideSorter::MouseOverManager::Invalidate (void)
{
    if (mpPaintManager.get() != NULL)
        mpPaintManager->Invalidate(mxInvalidateTarget, maSlideBoundingBox, true);
}




//===== PresenterSlideSorter::CurrentSlideFrameRenderer =======================

PresenterSlideSorter::CurrentSlideFrameRenderer::CurrentSlideFrameRenderer (
    const css::uno::Reference<css::uno::XComponentContext>& rxContext,
    const css::uno::Reference<css::rendering::XCanvas>& rxCanvas)
    : mpTopLeft(),
      mpTop(),
      mpTopRight(),
      mpLeft(),
      mpRight(),
      mpBottomLeft(),
      mpBottom(),
      mpBottomRight(),
      mnTopFrameSize(0),
      mnLeftFrameSize(0),
      mnRightFrameSize(0),
      mnBottomFrameSize(0)
{
    PresenterConfigurationAccess aConfiguration (
        rxContext,
        OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
        PresenterConfigurationAccess::READ_ONLY);
    Reference<container::XHierarchicalNameAccess> xBitmaps (
        aConfiguration.GetConfigurationNode(
            A2S("PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps")),
        UNO_QUERY);
    if ( ! xBitmaps.is())
        return;

    PresenterBitmapContainer aContainer (
        A2S("PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps"),
        ::boost::shared_ptr<PresenterBitmapContainer>(),
        rxContext,
        rxCanvas);

    mpTopLeft = aContainer.GetBitmap(A2S("TopLeft"));
    mpTop = aContainer.GetBitmap(A2S("Top"));
    mpTopRight = aContainer.GetBitmap(A2S("TopRight"));
    mpLeft = aContainer.GetBitmap(A2S("Left"));
    mpRight = aContainer.GetBitmap(A2S("Right"));
    mpBottomLeft = aContainer.GetBitmap(A2S("BottomLeft"));
    mpBottom = aContainer.GetBitmap(A2S("Bottom"));
    mpBottomRight = aContainer.GetBitmap(A2S("BottomRight"));

    // Determine size of frame.
    if (mpTop.get() != NULL)
        mnTopFrameSize = mpTop->mnHeight;
    if (mpLeft.get() != NULL)
        mnLeftFrameSize = mpLeft->mnWidth;
    if (mpRight.get() != NULL)
        mnRightFrameSize = mpRight->mnWidth;
    if (mpBottom.get() != NULL)
        mnBottomFrameSize = mpBottom->mnHeight;

    if (mpTopLeft.get() != NULL)
    {
        mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopLeft->mnHeight);
        mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpTopLeft->mnWidth);
    }
    if (mpTopRight.get() != NULL)
    {
        mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopRight->mnHeight);
        mnRightFrameSize = ::std::max(mnRightFrameSize, mpTopRight->mnWidth);
    }
    if (mpBottomLeft.get() != NULL)
    {
        mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpBottomLeft->mnWidth);
        mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomLeft->mnHeight);
    }
    if (mpBottomRight.get() != NULL)
    {
        mnRightFrameSize = ::std::max(mnRightFrameSize, mpBottomRight->mnWidth);
        mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomRight->mnHeight);
    }
}




PresenterSlideSorter::CurrentSlideFrameRenderer::~CurrentSlideFrameRenderer (void)
{
}




void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintCurrentSlideFrame (
    const awt::Rectangle& rSlideBoundingBox,
    const Reference<rendering::XCanvas>& rxCanvas,
    const geometry::RealRectangle2D& rClipBox)
{
    if ( ! rxCanvas.is())
        return;

    const Reference<rendering::XPolyPolygon2D> xClip (
        PresenterGeometryHelper::CreatePolygon(rClipBox, rxCanvas->getDevice()));

    if (mpTop.get() != NULL)
    {
        PaintBitmapTiled(
            mpTop->GetNormalBitmap(),
            rxCanvas,
            rClipBox,
            rSlideBoundingBox.X,
            rSlideBoundingBox.Y - mpTop->mnHeight,
            rSlideBoundingBox.Width,
            mpTop->mnHeight);
    }
    if (mpLeft.get() != NULL)
    {
        PaintBitmapTiled(
            mpLeft->GetNormalBitmap(),
            rxCanvas,
            rClipBox,
            rSlideBoundingBox.X - mpLeft->mnWidth,
            rSlideBoundingBox.Y,
            mpLeft->mnWidth,
            rSlideBoundingBox.Height);
    }
    if (mpRight.get() != NULL)
    {
        PaintBitmapTiled(
            mpRight->GetNormalBitmap(),
            rxCanvas,
            rClipBox,
            rSlideBoundingBox.X + rSlideBoundingBox.Width,
            rSlideBoundingBox.Y,
            mpRight->mnWidth,
            rSlideBoundingBox.Height);
    }
    if (mpBottom.get() != NULL)
    {
        PaintBitmapTiled(
            mpBottom->GetNormalBitmap(),
            rxCanvas,
            rClipBox,
            rSlideBoundingBox.X,
            rSlideBoundingBox.Y + rSlideBoundingBox.Height,
            rSlideBoundingBox.Width,
            mpBottom->mnHeight);
    }
    if (mpTopLeft.get() != NULL)
    {
        PaintBitmapOnce(
            mpTopLeft->GetNormalBitmap(),
            rxCanvas,
            xClip,
            rSlideBoundingBox.X - mpTopLeft->mnWidth,
            rSlideBoundingBox.Y - mpTopLeft->mnHeight);
    }
    if (mpTopRight.get() != NULL)
    {
        PaintBitmapOnce(
            mpTopRight->GetNormalBitmap(),
            rxCanvas,
            xClip,
            rSlideBoundingBox.X + rSlideBoundingBox.Width,
            rSlideBoundingBox.Y - mpTopLeft->mnHeight);
    }
    if (mpBottomLeft.get() != NULL)
    {
        PaintBitmapOnce(
            mpBottomLeft->GetNormalBitmap(),
            rxCanvas,
            xClip,
            rSlideBoundingBox.X - mpBottomLeft->mnWidth,
            rSlideBoundingBox.Y + rSlideBoundingBox.Height);
    }
    if (mpBottomRight.get() != NULL)
    {
        PaintBitmapOnce(
            mpBottomRight->GetNormalBitmap(),
            rxCanvas,
            xClip,
            rSlideBoundingBox.X + rSlideBoundingBox.Width,
            rSlideBoundingBox.Y + rSlideBoundingBox.Height);
    }
}




awt::Rectangle PresenterSlideSorter::CurrentSlideFrameRenderer::GetBoundingBox (
    const awt::Rectangle& rSlideBoundingBox)
{
    return awt::Rectangle(
        rSlideBoundingBox.X - mnLeftFrameSize,
        rSlideBoundingBox.Y - mnTopFrameSize,
        rSlideBoundingBox.Width + mnLeftFrameSize + mnRightFrameSize,
        rSlideBoundingBox.Height + mnTopFrameSize + mnBottomFrameSize);
}




void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapOnce(
    const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
    const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
    const Reference<rendering::XPolyPolygon2D>& rxClip,
    const double nX,
    const double nY)
{
    OSL_ASSERT(rxCanvas.is());
    if ( ! rxBitmap.is())
        return;

    const rendering::ViewState aViewState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        rxClip);

    const rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(
            1, 0, nX,
            0, 1, nY),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);

    rxCanvas->drawBitmap(
        rxBitmap,
        aViewState,
        aRenderState);
}




void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapTiled(
    const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
    const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
    const geometry::RealRectangle2D& rClipBox,
    const double nX0,
    const double nY0,
    const double nWidth,
    const double nHeight)
{
    OSL_ASSERT(rxCanvas.is());
    if ( ! rxBitmap.is())
        return;

    geometry::IntegerSize2D aSize (rxBitmap->getSize());

    const rendering::ViewState aViewState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        PresenterGeometryHelper::CreatePolygon(
            PresenterGeometryHelper::Intersection(
                rClipBox,
                geometry::RealRectangle2D(nX0,nY0,nX0+nWidth,nY0+nHeight)),
            rxCanvas->getDevice()));

    rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(
            1, 0, nX0,
            0, 1, nY0),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);

    const double nX1 = nX0 + nWidth;
    const double nY1 = nY0 + nHeight;
    for (double nY=nY0; nY<nY1; nY+=aSize.Height)
        for (double nX=nX0; nX<nX1; nX+=aSize.Width)
        {
            aRenderState.AffineTransform.m02 = nX;
            aRenderState.AffineTransform.m12 = nY;
            rxCanvas->drawBitmap(
                rxBitmap,
                aViewState,
                aRenderState);
        }
}

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