/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



#include "precompiled_svtools.hxx"

#include "svtools/toolpanel/paneltabbar.hxx"
#include "svtools/toolpanel/toolpaneldeck.hxx"
#include "svtools/svtdata.hxx"
#include "svtools/svtools.hrc"

#include "tabitemdescriptor.hxx"
#include "paneltabbarpeer.hxx"
#include "tabbargeometry.hxx"

#include <vcl/button.hxx>
#include <vcl/help.hxx>
#include <vcl/virdev.hxx>
#include <tools/diagnose_ex.h>

#include <boost/optional.hpp>
#include <vector>

// space around an item
#define ITEM_OUTER_SPACE        2 * 3
// spacing before and after an item's text
#define ITEM_TEXT_FLOW_SPACE    5
// space between item icon and icon text
#define ITEM_ICON_TEXT_DISTANCE 4

//........................................................................
namespace svt
{
//........................................................................

    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::awt::XWindowPeer;

    typedef sal_uInt16  ItemFlags;

    #define ITEM_STATE_NORMAL   0x00
    #define ITEM_STATE_ACTIVE   0x01
    #define ITEM_STATE_HOVERED  0x02
    #define ITEM_STATE_FOCUSED  0x04
    #define ITEM_POSITION_FIRST 0x08
    #define ITEM_POSITION_LAST  0x10

	//==================================================================================================================
	//= helper
	//==================================================================================================================
    namespace
    {
        ControlState lcl_ItemToControlState( const ItemFlags i_nItemFlags )
        {
            ControlState nState = CTRL_STATE_ENABLED;
            if ( i_nItemFlags & ITEM_STATE_FOCUSED )    nState |= CTRL_STATE_FOCUSED | CTRL_STATE_PRESSED;
            if ( i_nItemFlags & ITEM_STATE_HOVERED )    nState |= CTRL_STATE_ROLLOVER;
            if ( i_nItemFlags & ITEM_STATE_ACTIVE )     nState |= CTRL_STATE_SELECTED;
            return nState;
        }
    }

	//==================================================================================================================
	//= ITabBarRenderer
	//==================================================================================================================
    class SAL_NO_VTABLE ITabBarRenderer
    {
    public:
        /** fills the background of our target device
        */
        virtual void        renderBackground() const = 0;
        virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const = 0;
        virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const = 0;
        virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const = 0;

        // TODO: postRenderItem takes the "real" window, i.e. effectively the tab bar. This is because
        // DrawSelectionBackground needs to be applied after everything else is painted, and is available at the Window
        // class, but not at the OutputDevice. This makes the API somewhat weird, as we're now mixing operations on the
        // target device, done in a normalized geometry, with operations on the window, done in a transformed geometry.
        // So, we should get rid of postRenderItem completely.
    };
    typedef ::boost::shared_ptr< ITabBarRenderer >  PTabBarRenderer;

	//==================================================================================================================
	//= VCLItemRenderer - declaration
	//==================================================================================================================
    class VCLItemRenderer : public ITabBarRenderer
    {
    public:
        VCLItemRenderer( OutputDevice& i_rTargetDevice )
            :m_rTargetDevice( i_rTargetDevice )
        {
        }

        // ITabBarRenderer
        virtual void        renderBackground() const;
        virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const;
        virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const;
        virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const;

    protected:
        OutputDevice&   getTargetDevice() const { return m_rTargetDevice; }

    private:
        OutputDevice&   m_rTargetDevice;
    };

	//==================================================================================================================
	//= VCLItemRenderer - implementation
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    void VCLItemRenderer::renderBackground() const
    {
        getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
    }

	//------------------------------------------------------------------------------------------------------------------
    Rectangle VCLItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
    {
        (void)i_nItemFlags;
        // no decorations at all
        return i_rContentArea;
    }

	//------------------------------------------------------------------------------------------------------------------
    void VCLItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
    {
        (void)i_rContentRect;
        (void)i_nItemFlags;
    }

	//------------------------------------------------------------------------------------------------------------------
    void VCLItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
    {
        const bool bActive = ( ( i_nItemFlags & ITEM_STATE_ACTIVE ) != 0 );
        const bool bHovered = ( ( i_nItemFlags & ITEM_STATE_HOVERED ) != 0 );
        const bool bFocused = ( ( i_nItemFlags & ITEM_STATE_FOCUSED ) != 0 );
        if ( bActive || bHovered || bFocused )
        {
            Rectangle aSelectionRect( i_rItemRect );
            aSelectionRect.Left() += ITEM_OUTER_SPACE / 2;
            aSelectionRect.Top() += ITEM_OUTER_SPACE / 2;
            aSelectionRect.Right() -= ITEM_OUTER_SPACE / 2;
            aSelectionRect.Bottom() -= ITEM_OUTER_SPACE / 2;
            i_rActualWindow.DrawSelectionBackground(
                aSelectionRect,
                ( bHovered || bFocused ) ? ( bActive ? 1 : 2 ) : 0 /* hilight */,
                bActive /* check */,
                sal_True /* border */,
                sal_False /* ext border only */,
                0 /* corner radius */,
                NULL,
                NULL
            );
        }
    }

	//==================================================================================================================
	//= NWFToolboxItemRenderer - declaration
	//==================================================================================================================
    class NWFToolboxItemRenderer : public ITabBarRenderer
    {
    public:
        NWFToolboxItemRenderer( OutputDevice& i_rTargetDevice )
            :m_rTargetDevice( i_rTargetDevice )
        {
        }

        // ITabBarRenderer
        virtual void        renderBackground() const;
        virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const;
        virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const;
        virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const;

    protected:
        OutputDevice&   getTargetDevice() const { return m_rTargetDevice; }

    private:
        OutputDevice&   m_rTargetDevice;
    };

	//==================================================================================================================
	//= NWFToolboxItemRenderer - implementation
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    void NWFToolboxItemRenderer::renderBackground() const
    {
        getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) );
    }

	//------------------------------------------------------------------------------------------------------------------
    Rectangle NWFToolboxItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
    {
        // don't ask GetNativeControlRegion, this will not deliver proper results in all cases.
        // Instead, simply assume that both the content and the bounding region are the same.
//        const ControlState nState( lcl_ItemToControlState( i_nItemFlags );
//        const ImplControlValue aControlValue;
//        bool bNativeOK = m_rTargetWindow.GetNativeControlRegion(
//            CTRL_TOOLBAR, PART_BUTTON,
//            i_rContentArea, nState,
//            aControlValue, ::rtl::OUString(),
//            aBoundingRegion, aContentRegion
//        );
        (void)i_nItemFlags;
        return Rectangle(
            Point( i_rContentArea.Left() - 1, i_rContentArea.Top() - 1 ),
            Size( i_rContentArea.GetWidth() + 2, i_rContentArea.GetHeight() + 2 )
        );
    }

	//------------------------------------------------------------------------------------------------------------------
    void NWFToolboxItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
    {
        const ControlState nState = lcl_ItemToControlState( i_nItemFlags );

        ImplControlValue aControlValue;
        aControlValue.setTristateVal( ( i_nItemFlags & ITEM_STATE_ACTIVE ) ? BUTTONVALUE_ON : BUTTONVALUE_OFF );

        bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, i_rContentRect, nState, aControlValue, rtl::OUString() );
        (void)bNativeOK;
        OSL_ENSURE( bNativeOK, "NWFToolboxItemRenderer::preRenderItem: inconsistent NWF implementation!" );
            // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
    }

	//------------------------------------------------------------------------------------------------------------------
    void NWFToolboxItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
    {
        (void)i_rActualWindow;
        (void)i_rItemRect;
        (void)i_nItemFlags;
    }

	//==================================================================================================================
	//= NWFTabItemRenderer - declaration
	//==================================================================================================================
    class NWFTabItemRenderer : public ITabBarRenderer
    {
    public:
        NWFTabItemRenderer( OutputDevice& i_rTargetDevice )
            :m_rTargetDevice( i_rTargetDevice )
        {
        }

        // ITabBarRenderer
        virtual void        renderBackground() const;
        virtual Rectangle   calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const;
        virtual void        preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const;
        virtual void        postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const;

    protected:
        OutputDevice&   getTargetDevice() const { return m_rTargetDevice; }

    private:
        OutputDevice&   m_rTargetDevice;
    };

	//==================================================================================================================
	//= NWFTabItemRenderer - implementation
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    void NWFTabItemRenderer::renderBackground() const
    {
        Rectangle aBackground( Point(), getTargetDevice().GetOutputSizePixel() );
        getTargetDevice().DrawRect( aBackground );

        aBackground.Top() = aBackground.Bottom();
        getTargetDevice().DrawNativeControl( CTRL_TAB_PANE, PART_ENTIRE_CONTROL, aBackground,
            CTRL_STATE_ENABLED, ImplControlValue(), ::rtl::OUString() );
    }

	//------------------------------------------------------------------------------------------------------------------
    Rectangle NWFTabItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const
    {
        const ControlState nState( lcl_ItemToControlState( i_nItemFlags ) );

        TabitemValue tiValue;

        Rectangle aBoundingRegion, aContentRegion;
        bool bNativeOK = getTargetDevice().GetNativeControlRegion(
            CTRL_TAB_ITEM, PART_ENTIRE_CONTROL,
            i_rContentArea, nState,
            tiValue, ::rtl::OUString(),
            aBoundingRegion, aContentRegion
        );
        (void)bNativeOK;
        OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::calculateDecorations: GetNativeControlRegion not implemented for CTRL_TAB_ITEM?!" );

        return aBoundingRegion;
    }

	//------------------------------------------------------------------------------------------------------------------
    void NWFTabItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const
    {
        const ControlState nState = lcl_ItemToControlState( i_nItemFlags );

        TabitemValue tiValue;
        if ( i_nItemFlags & ITEM_POSITION_FIRST )
            tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP;
        if ( i_nItemFlags & ITEM_POSITION_LAST )
            tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP;


        bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, i_rContentRect, nState, tiValue, rtl::OUString() );
        (void)bNativeOK;
        OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::preRenderItem: inconsistent NWF implementation!" );
            // IsNativeControlSupported returned true, previously, otherwise we would not be here ...
    }

	//------------------------------------------------------------------------------------------------------------------
    void NWFTabItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const
    {
        (void)i_rActualWindow;
        (void)i_rItemRect;
        (void)i_nItemFlags;
    }

    //==================================================================================================================
	//= PanelTabBar_Impl
	//==================================================================================================================
    class PanelTabBar_Impl : public IToolPanelDeckListener
    {
    public:
        PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent );

        ~PanelTabBar_Impl()
        {
            m_rPanelDeck.RemoveListener( *this );
        }

        // IToolPanelDeckListener
        virtual void PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition )
        {
            (void)i_pPanel;
            (void)i_nPosition;
            m_bItemsDirty = true;
            m_rTabBar.Invalidate();

            Relayout();
        }

        virtual void PanelRemoved( const size_t i_nPosition )
        {
            m_bItemsDirty = true;
            m_rTabBar.Invalidate();

            if ( i_nPosition < m_nScrollPosition )
                --m_nScrollPosition;

            Relayout();
        }

        virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive );
        virtual void LayouterChanged( const PDeckLayouter& i_rNewLayouter );
        virtual void Dying();

        void    UpdateScrollButtons()
        {
            m_aScrollBack.Enable( m_nScrollPosition > 0 );
            m_aScrollForward.Enable( m_nScrollPosition < m_aItems.size() - 1 );
        }

        void                        Relayout();
        void                        EnsureItemsCache();
        ::boost::optional< size_t > FindItemForPoint( const Point& i_rPoint ) const;
        void                        DrawItem( const size_t i_nItemIndex, const Rectangle& i_rBoundaries ) const;
        void                        InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags = 0 ) const;
        void                        CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const;
        Rectangle                   GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const;
        Rectangle                   GetItemScreenRect( const size_t i_nItemPos ) const;

        void                        FocusItem( const ::boost::optional< size_t >& i_rItemPos );

        inline bool                 IsVertical() const
        {
            return  (   ( m_eTabAlignment == TABS_LEFT )
                    ||  ( m_eTabAlignment == TABS_RIGHT )
                    );
        }

    protected:
        DECL_LINK( OnScroll, const PushButton* );

        void        impl_calcItemRects();
        Size        impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const;
        void        impl_renderItemContent( const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent ) const;
        ItemFlags   impl_getItemFlags( const size_t i_nItemIndex ) const;

    public:
        PanelTabBar&                m_rTabBar;
        TabBarGeometry              m_aGeometry;
        NormalizedArea              m_aNormalizer;
        TabAlignment                m_eTabAlignment;
        IToolPanelDeck&             m_rPanelDeck;

        VirtualDevice               m_aRenderDevice;
        PTabBarRenderer             m_pRenderer;

        ::boost::optional< size_t > m_aHoveredItem;
        ::boost::optional< size_t > m_aFocusedItem;
        bool                        m_bMouseButtonDown;

        ItemDescriptors             m_aItems;
        bool                        m_bItemsDirty;

        PushButton                  m_aScrollBack;
        PushButton                  m_aScrollForward;

        size_t                      m_nScrollPosition;
    };

    //==================================================================================================================
	//= helper
	//==================================================================================================================
    namespace
    {
	    //--------------------------------------------------------------------------------------------------------------
    #if OSL_DEBUG_LEVEL > 0
        static void lcl_checkConsistency( const PanelTabBar_Impl& i_rImpl )
        {
            if ( !i_rImpl.m_bItemsDirty )
            {
                if ( i_rImpl.m_rPanelDeck.GetPanelCount() != i_rImpl.m_aItems.size() )
                {
                    OSL_ENSURE( false, "lcl_checkConsistency: inconsistent array sizes!" );
                    return;
                }
                for ( size_t i = 0; i < i_rImpl.m_rPanelDeck.GetPanelCount(); ++i )
                {
                    if ( i_rImpl.m_rPanelDeck.GetPanel( i ).get() != i_rImpl.m_aItems[i].pPanel.get() )
                    {
                        OSL_ENSURE( false, "lcl_checkConsistency: array elements are inconsistent!" );
                        return;
                    }
                }
            }
        }

        #define DBG_CHECK( data ) \
            lcl_checkConsistency( data );
    #else
        #define DBG_CHECK( data ) \
            (void)data;
    #endif

        //--------------------------------------------------------------------------------------------------------------
        class ClipItemRegion
        {
        public:
            ClipItemRegion( const PanelTabBar_Impl& i_rImpl )
                :m_rDevice( i_rImpl.m_rTabBar )
            {
                m_rDevice.Push( PUSH_CLIPREGION );
                m_rDevice.SetClipRegion( i_rImpl.m_aNormalizer.getTransformed( i_rImpl.m_aGeometry.getItemsRect(), i_rImpl.m_eTabAlignment ) );
            }

            ~ClipItemRegion()
            {
                m_rDevice.Pop();
            }

        private:
            OutputDevice&   m_rDevice;
        };
    }

	//==================================================================================================================
	//= PanelTabBar_Impl - implementation
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    PanelTabBar_Impl::PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent )
        :m_rTabBar( i_rTabBar )
        ,m_aGeometry( i_eItemContent )
        ,m_aNormalizer()
        ,m_eTabAlignment( i_eAlignment )
        ,m_rPanelDeck( i_rPanelDeck )
        ,m_aRenderDevice( i_rTabBar )
        ,m_pRenderer()
        ,m_aHoveredItem()
        ,m_aFocusedItem()
        ,m_bMouseButtonDown( false )
        ,m_aItems()
        ,m_bItemsDirty( true )
        ,m_aScrollBack( &i_rTabBar, WB_BEVELBUTTON )
        ,m_aScrollForward( &i_rTabBar, WB_BEVELBUTTON )
        ,m_nScrollPosition( 0 )
    {
#ifdef WNT
        if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL ) )
            // this mode requires the NWF framework to be able to render those items onto a virtual
            // device. For some frameworks (some GTK themes, in particular), this is known to fail.
            // So, be on the safe side for the moment.
            m_pRenderer.reset( new NWFTabItemRenderer( m_aRenderDevice ) );
        else
#endif
        if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
            m_pRenderer.reset( new NWFToolboxItemRenderer( m_aRenderDevice ) );
        else
            m_pRenderer.reset( new VCLItemRenderer( m_aRenderDevice ) );

        m_aRenderDevice.SetLineColor();

        m_rPanelDeck.AddListener( *this );

        m_aScrollBack.SetSymbol( IsVertical() ? SYMBOL_ARROW_UP : SYMBOL_ARROW_LEFT );
        m_aScrollBack.Show();
        m_aScrollBack.SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) );
        m_aScrollBack.SetAccessibleDescription( String( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_FWD ) ) );
        m_aScrollBack.SetAccessibleName( m_aScrollBack.GetAccessibleDescription() );

        m_aScrollForward.SetSymbol( IsVertical() ? SYMBOL_ARROW_DOWN : SYMBOL_ARROW_RIGHT );
        m_aScrollForward.Show();
        m_aScrollForward.SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) );
        m_aScrollForward.SetAccessibleDescription( String( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_BACK ) ) );
        m_aScrollForward.SetAccessibleName( m_aScrollForward.GetAccessibleDescription() );
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::impl_calcItemRects()
    {
        m_aItems.resize(0);

        Point aCompletePos( m_aGeometry.getFirstItemPosition() );
        Point aIconOnlyPos( aCompletePos );
        Point aTextOnlyPos( aCompletePos );

        for (   size_t i = 0;
                i < m_rPanelDeck.GetPanelCount();
                ++i
            )
        {
            PToolPanel pPanel( m_rPanelDeck.GetPanel( i ) );

            ItemDescriptor aItem;
            aItem.pPanel = pPanel;

            Rectangle aContentArea;

            const Size aCompleteSize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_AND_TEXT ) );
            const Size aIconOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_ONLY ) );
            const Size aTextOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_TEXT_ONLY ) );

            // TODO: have one method calculating all sizes?

            // remember the three areas
            aItem.aCompleteArea = Rectangle( aCompletePos, aCompleteSize );
            aItem.aIconOnlyArea = Rectangle( aIconOnlyPos, aIconOnlySize );
            aItem.aTextOnlyArea = Rectangle( aTextOnlyPos, aTextOnlySize );

            m_aItems.push_back( aItem );

            aCompletePos = aItem.aCompleteArea.TopRight();
            aIconOnlyPos = aItem.aIconOnlyArea.TopRight();
            aTextOnlyPos = aItem.aTextOnlyArea.TopRight();
        }

        m_bItemsDirty = false;
    }

    //------------------------------------------------------------------------------------------------------------------
    Size PanelTabBar_Impl::impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const
    {
        // calculate the size needed for the content
        OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_calculateItemContentSize: illegal TabItemContent value!" );

        const Image aImage( i_pPanel->GetImage() );
        const bool bUseImage = !!aImage && ( i_eItemContent != TABITEM_TEXT_ONLY );

        const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() );
        const bool bUseText = ( sItemText.getLength() != 0 ) && ( i_eItemContent != TABITEM_IMAGE_ONLY );

        Size aItemContentSize;
        if ( bUseImage )
        {
            aItemContentSize = aImage.GetSizePixel();
        }

        if ( bUseText )
        {
            if ( bUseImage )
                aItemContentSize.Width() += ITEM_ICON_TEXT_DISTANCE;

            // add space for text
            const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() );
            aItemContentSize.Width() += aTextSize.Width();
            aItemContentSize.Height() = ::std::max( aItemContentSize.Height(), aTextSize.Height() );

            aItemContentSize.Width() += 2 * ITEM_TEXT_FLOW_SPACE;
        }

        if ( !bUseImage && !bUseText )
        {
            // have a minimal size - this is pure heuristics, but if it doesn't suit your needs, then give your panels
            // a name and or image! :)
            aItemContentSize = Size( 16, 16 );
        }

        aItemContentSize.Width() += 2 * ITEM_OUTER_SPACE;
        aItemContentSize.Height() += 2 * ITEM_OUTER_SPACE;

        return aItemContentSize;
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::impl_renderItemContent( const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent ) const
    {
        OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_renderItemContent: illegal TabItemContent value!" );

        Rectangle aRenderArea( i_rContentArea );
        if ( IsVertical() )
        {
            aRenderArea.Top() += ITEM_OUTER_SPACE;
        }
        else
        {
            aRenderArea.Left() += ITEM_OUTER_SPACE;
        }

        // draw the image
        const Image aItemImage( i_pPanel->GetImage() );
        const Size aImageSize( aItemImage.GetSizePixel() );
        const bool bUseImage = !!aItemImage && ( i_eItemContent != TABITEM_TEXT_ONLY );

        if ( bUseImage )
        {
            Point aImagePos;
            if ( IsVertical() )
            {
                aImagePos.X() = aRenderArea.Left() + ( aRenderArea.GetWidth() - aImageSize.Width() ) / 2;
                aImagePos.Y() = aRenderArea.Top();
            }
            else
            {
                aImagePos.X() = aRenderArea.Left();
                aImagePos.Y() = aRenderArea.Top() + ( aRenderArea.GetHeight() - aImageSize.Height() ) / 2;
            }
            m_rTabBar.DrawImage( aImagePos, aItemImage );
        }

        const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() );
        const bool bUseText = ( sItemText.getLength() != 0 ) && ( i_eItemContent != TABITEM_IMAGE_ONLY );

        if ( bUseText )
        {
            if ( IsVertical() )
            {
                if ( bUseImage )
                    aRenderArea.Top() += aImageSize.Height() + ITEM_ICON_TEXT_DISTANCE;
                aRenderArea.Top() += ITEM_TEXT_FLOW_SPACE;
            }
            else
            {
                if ( bUseImage )
                    aRenderArea.Left() += aImageSize.Width() + ITEM_ICON_TEXT_DISTANCE;
                aRenderArea.Left() += ITEM_TEXT_FLOW_SPACE;
            }

            // draw the text
            const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() );
            Point aTextPos( aRenderArea.TopLeft() );
            if ( IsVertical() )
            {
                m_rTabBar.Push( PUSH_FONT );

                Font aFont( m_rTabBar.GetFont() );
                aFont.SetOrientation( 2700 );
                aFont.SetVertical( sal_True );
                m_rTabBar.SetFont( aFont );

                aTextPos.X() += aTextSize.Height();
                aTextPos.X() += ( aRenderArea.GetWidth() - aTextSize.Height() ) / 2;
            }
            else
            {
                aTextPos.Y() += ( aRenderArea.GetHeight() - aTextSize.Height() ) / 2;
            }

            m_rTabBar.DrawText( aTextPos, sItemText );

            if ( IsVertical() )
            {
                m_rTabBar.Pop();
            }
        }
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const
    {
        BitmapEx aBitmap( m_aRenderDevice.GetBitmapEx(
            i_rLogicalRect.TopLeft(),
            Size(
                i_rLogicalRect.GetSize().Width(),
                i_rLogicalRect.GetSize().Height()
            )
        ) );
        if ( IsVertical() )
        {
            aBitmap.Rotate( 2700, COL_BLACK );
            if ( m_eTabAlignment == TABS_LEFT )
                aBitmap.Mirror( BMP_MIRROR_HORZ );
        }
        else if ( m_eTabAlignment == TABS_BOTTOM )
        {
            aBitmap.Mirror( BMP_MIRROR_VERT );
        }

        const Rectangle aActualRect( m_aNormalizer.getTransformed( i_rLogicalRect, m_eTabAlignment ) );
        m_rTabBar.DrawBitmapEx( aActualRect.TopLeft(), aBitmap );
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags ) const
    {
        const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] );
        const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) | i_nAdditionalItemFlags );

        const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
        const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) );

        const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment );
        m_rTabBar.Invalidate( aActualBounds );
    }

    //------------------------------------------------------------------------------------------------------------------
    ItemFlags PanelTabBar_Impl::impl_getItemFlags( const size_t i_nItemIndex ) const
    {
        ItemFlags nItemFlags( ITEM_STATE_NORMAL );
        if ( m_aHoveredItem == i_nItemIndex )
        {
            nItemFlags |= ITEM_STATE_HOVERED;
            if ( m_bMouseButtonDown )
                nItemFlags |= ITEM_STATE_ACTIVE;
        }

        if ( m_rPanelDeck.GetActivePanel() == i_nItemIndex )
            nItemFlags |= ITEM_STATE_ACTIVE;

        if ( m_aFocusedItem == i_nItemIndex )
            nItemFlags |= ITEM_STATE_FOCUSED;

        if ( 0 == i_nItemIndex )
            nItemFlags |= ITEM_POSITION_FIRST;

        if ( m_rPanelDeck.GetPanelCount() - 1 == i_nItemIndex )
            nItemFlags |= ITEM_POSITION_LAST;

        return nItemFlags;
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::DrawItem( const size_t i_nItemIndex, const Rectangle& i_rBoundaries ) const
    {
        const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] );
        const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) );

        // the normalized bounding and content rect
        const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
        const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) );

        // check whether the item actually overlaps with the painting area
        if ( !i_rBoundaries.IsEmpty() )
        {
            const Rectangle aItemRect( GetActualLogicalItemRect( rItem.GetCurrentRect() ) );
            if ( !aItemRect.IsOver( i_rBoundaries ) )
                return;
        }

        m_rTabBar.SetUpdateMode( sal_False );

        // the aligned bounding and content rect
        const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment );
        const Rectangle aActualContent = m_aNormalizer.getTransformed( aNormalizedContent, m_eTabAlignment );

        // render item "background" layer
        m_pRenderer->preRenderItem( aNormalizedContent, nItemFlags );

        // copy from the virtual device to ourself
        CopyFromRenderDevice( aNormalizedBounds );

        // render the actual item content
        impl_renderItemContent( rItem.pPanel, aActualContent, rItem.eContent );

        // render item "foreground" layer
        m_pRenderer->postRenderItem( m_rTabBar, aActualBounds, nItemFlags );

        m_rTabBar.SetUpdateMode( sal_True );
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::EnsureItemsCache()
    {
        if ( m_bItemsDirty == false )
        {
            DBG_CHECK( *this );
            return;
        }
        impl_calcItemRects();
        OSL_POSTCOND( m_bItemsDirty == false, "PanelTabBar_Impl::EnsureItemsCache: cache still dirty!" );
        DBG_CHECK( *this );
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::Relayout()
    {
        EnsureItemsCache();

        const Size aOutputSize( m_rTabBar.GetOutputSizePixel() );
        m_aNormalizer = NormalizedArea( Rectangle( Point(), aOutputSize ), IsVertical() );
        const Size aLogicalOutputSize( m_aNormalizer.getReferenceSize() );

        // forward actual output size to our render device
        m_aRenderDevice.SetOutputSizePixel( aLogicalOutputSize );

        // re-calculate the size of the scroll buttons and of the items
        m_aGeometry.relayout( aLogicalOutputSize, m_aItems );

        if ( m_aGeometry.getButtonBackRect().IsEmpty() )
        {
            m_aScrollBack.Hide();
        }
        else
        {
            const Rectangle aButtonBack( m_aNormalizer.getTransformed( m_aGeometry.getButtonBackRect(), m_eTabAlignment ) );
            m_aScrollBack.SetPosSizePixel( aButtonBack.TopLeft(), aButtonBack.GetSize() );
            m_aScrollBack.Show();
        }

        if ( m_aGeometry.getButtonForwardRect().IsEmpty() )
        {
            m_aScrollForward.Hide();
        }
        else
        {
            const Rectangle aButtonForward( m_aNormalizer.getTransformed( m_aGeometry.getButtonForwardRect(), m_eTabAlignment ) );
            m_aScrollForward.SetPosSizePixel( aButtonForward.TopLeft(), aButtonForward.GetSize() );
            m_aScrollForward.Show();
        }

        UpdateScrollButtons();
    }

    //------------------------------------------------------------------------------------------------------------------
    ::boost::optional< size_t > PanelTabBar_Impl::FindItemForPoint( const Point& i_rPoint ) const
    {
        Point aPoint( IsVertical() ? i_rPoint.Y() : i_rPoint.X(), IsVertical() ? i_rPoint.X() : i_rPoint.Y() );

        if ( !m_aGeometry.getItemsRect().IsInside( aPoint ) )
            return ::boost::optional< size_t >();

        size_t i=0;
        for (   ItemDescriptors::const_iterator item = m_aItems.begin();
                item != m_aItems.end();
                ++item, ++i
            )
        {
            Rectangle aItemRect( GetActualLogicalItemRect( item->GetCurrentRect() ) );
            if ( aItemRect.IsInside( aPoint ) )
            {
                return ::boost::optional< size_t >( i );
            }
        }
        return ::boost::optional< size_t >();
    }

    //------------------------------------------------------------------------------------------------------------------
    Rectangle PanelTabBar_Impl::GetItemScreenRect( const size_t i_nItemPos ) const
    {
        ENSURE_OR_RETURN( i_nItemPos < m_aItems.size(), "PanelTabBar_Impl::GetItemScreenRect: invalid item pos!", Rectangle() );
        const ItemDescriptor& rItem( m_aItems[ i_nItemPos ] );
        const Rectangle aItemRect( m_aNormalizer.getTransformed(
            GetActualLogicalItemRect( rItem.GetCurrentRect() ),
            m_eTabAlignment ) );

		const Rectangle aTabBarRect( m_rTabBar.GetWindowExtentsRelative( NULL ) );
        return Rectangle(
            Point( aTabBarRect.Left() + aItemRect.Left(), aTabBarRect.Top() + aItemRect.Top() ),
            aItemRect.GetSize()
        );
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::FocusItem( const ::boost::optional< size_t >& i_rItemPos )
    {
        // reset old focus item
        if ( !!m_aFocusedItem )
            InvalidateItem( *m_aFocusedItem );
        m_aFocusedItem.reset();

        // mark the active icon as focused
        if ( !!i_rItemPos )
        {
            m_aFocusedItem = i_rItemPos;
            InvalidateItem( *m_aFocusedItem );
        }
    }

    //------------------------------------------------------------------------------------------------------------------
    IMPL_LINK( PanelTabBar_Impl, OnScroll, const PushButton*, i_pButton )
    {
        if ( i_pButton == &m_aScrollBack )
        {
            OSL_ENSURE( m_nScrollPosition > 0, "PanelTabBar_Impl::OnScroll: inconsistency!" );
            --m_nScrollPosition;
            m_rTabBar.Invalidate();
        }
        else if ( i_pButton == &m_aScrollForward )
        {
            OSL_ENSURE( m_nScrollPosition < m_aItems.size() - 1, "PanelTabBar_Impl::OnScroll: inconsistency!" );
            ++m_nScrollPosition;
            m_rTabBar.Invalidate();
        }

        UpdateScrollButtons();

        return 0L;
    }

    //------------------------------------------------------------------------------------------------------------------
    Rectangle PanelTabBar_Impl::GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const
    {
        // care for the offset imposed by our geometry, i.e. whether or not we have scroll buttons
        Rectangle aItemRect( i_rLogicalItemRect );
        aItemRect.Move( m_aGeometry.getItemsRect().Left() - m_aGeometry.getButtonBackRect().Left(), 0 );

        // care for the current scroll position
        OSL_ENSURE( m_nScrollPosition < m_aItems.size(), "GetActualLogicalItemRect: invalid scroll position!" );
        if ( ( m_nScrollPosition > 0 ) && ( m_nScrollPosition < m_aItems.size() ) )
        {
            long nOffsetX = m_aItems[ m_nScrollPosition ].GetCurrentRect().Left() - m_aItems[ 0 ].GetCurrentRect().Left();
            long nOffsetY = m_aItems[ m_nScrollPosition ].GetCurrentRect().Top() - m_aItems[ 0 ].GetCurrentRect().Top();
            aItemRect.Move( -nOffsetX, -nOffsetY );
        }

        return aItemRect;
    }

	//==================================================================================================================
	//= PanelTabBar_Impl
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
    {
        EnsureItemsCache();

        if ( !!i_rOldActive )
            InvalidateItem( *i_rOldActive, ITEM_STATE_ACTIVE );
        if ( !!i_rNewActive )
            InvalidateItem( *i_rNewActive );
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::LayouterChanged( const PDeckLayouter& i_rNewLayouter )
    {
        // not interested in
        (void)i_rNewLayouter;
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar_Impl::Dying()
    {
        // not interested in - the notifier is a member of this instance here, so we're dying ourself at the moment
    }

	//==================================================================================================================
	//= PanelTabBar
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    PanelTabBar::PanelTabBar( Window& i_rParentWindow, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent )
        :Control( &i_rParentWindow, 0 )
        ,m_pImpl( new PanelTabBar_Impl( *this, i_rPanelDeck, i_eAlignment, i_eItemContent ) )
    {
        DBG_CHECK( *m_pImpl );
    }

	//------------------------------------------------------------------------------------------------------------------
    PanelTabBar::~PanelTabBar()
    {
    }

	//------------------------------------------------------------------------------------------------------------------
    TabItemContent PanelTabBar::GetTabItemContent() const
    {
        return m_pImpl->m_aGeometry.getItemContent();
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::SetTabItemContent( const TabItemContent& i_eItemContent )
    {
        m_pImpl->m_aGeometry.setItemContent( i_eItemContent );
        m_pImpl->Relayout();
        Invalidate();
    }

	//------------------------------------------------------------------------------------------------------------------
    IToolPanelDeck& PanelTabBar::GetPanelDeck() const
    {
        DBG_CHECK( *m_pImpl );
        return m_pImpl->m_rPanelDeck;
    }

	//------------------------------------------------------------------------------------------------------------------
    Size PanelTabBar::GetOptimalSize( WindowSizeType i_eType ) const
    {
        m_pImpl->EnsureItemsCache();
        Size aOptimalSize( m_pImpl->m_aGeometry.getOptimalSize( m_pImpl->m_aItems, i_eType == WINDOWSIZE_MINIMUM ) );
        if ( m_pImpl->IsVertical() )
            ::std::swap( aOptimalSize.Width(), aOptimalSize.Height() );
        return aOptimalSize;
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::Resize()
    {
        Control::Resize();
        m_pImpl->Relayout();
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::Paint( const Rectangle& i_rRect )
    {
        m_pImpl->EnsureItemsCache();

        // background
        const Rectangle aNormalizedPaintArea( m_pImpl->m_aNormalizer.getNormalized( i_rRect, m_pImpl->m_eTabAlignment ) );
        m_pImpl->m_aRenderDevice.Push( PUSH_CLIPREGION );
        m_pImpl->m_aRenderDevice.SetClipRegion( aNormalizedPaintArea );
        m_pImpl->m_pRenderer->renderBackground();
        m_pImpl->m_aRenderDevice.Pop();
        m_pImpl->CopyFromRenderDevice( aNormalizedPaintArea );

        // ensure the items really paint into their own playground only
        ClipItemRegion aClipItems( *m_pImpl );

        const Rectangle aLogicalPaintRect( m_pImpl->m_aNormalizer.getNormalized( i_rRect, m_pImpl->m_eTabAlignment ) );

        const ::boost::optional< size_t > aActivePanel( m_pImpl->m_rPanelDeck.GetActivePanel() );
        const ::boost::optional< size_t > aHoveredPanel( m_pImpl->m_aHoveredItem );

        // items:
        // 1. paint all non-active, non-hovered items
        size_t i=0;
        for (   ItemDescriptors::const_iterator item = m_pImpl->m_aItems.begin();
                item != m_pImpl->m_aItems.end();
                ++item, ++i
            )
        {
            if ( i == aActivePanel )
                continue;

            if ( aHoveredPanel == i )
                continue;

            m_pImpl->DrawItem( i, aLogicalPaintRect );
        }

        // 2. paint the item which is hovered, /without/ the mouse button pressed down
        if ( !!aHoveredPanel && !m_pImpl->m_bMouseButtonDown )
            m_pImpl->DrawItem( *aHoveredPanel, aLogicalPaintRect );

        // 3. paint the active item
        if ( !!aActivePanel )
            m_pImpl->DrawItem( *aActivePanel, aLogicalPaintRect );

        // 4. paint the item which is hovered, /with/ the mouse button pressed down
        if ( !!aHoveredPanel && m_pImpl->m_bMouseButtonDown )
            m_pImpl->DrawItem( *aHoveredPanel, aLogicalPaintRect );
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::MouseMove( const MouseEvent& i_rMouseEvent )
    {
        m_pImpl->EnsureItemsCache();

        ::boost::optional< size_t > aOldItem( m_pImpl->m_aHoveredItem );
        ::boost::optional< size_t > aNewItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );

        if  ( i_rMouseEvent.IsLeaveWindow() )
            aNewItem.reset();

        if ( aOldItem != aNewItem )
        {
            if ( !!aOldItem )
                m_pImpl->InvalidateItem( *aOldItem );

            m_pImpl->m_aHoveredItem = aNewItem;

            if ( !!aNewItem )
                m_pImpl->InvalidateItem( *aNewItem );
        }
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::MouseButtonDown( const MouseEvent& i_rMouseEvent )
    {
        Control::MouseButtonDown( i_rMouseEvent );

        if ( !i_rMouseEvent.IsLeft() )
            return;

        m_pImpl->EnsureItemsCache();

        ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
        if ( !aHitItem )
            return;

        CaptureMouse();
        m_pImpl->m_bMouseButtonDown = true;

        m_pImpl->InvalidateItem( *aHitItem );
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::MouseButtonUp( const MouseEvent& i_rMouseEvent )
    {
        Control::MouseButtonUp( i_rMouseEvent );

        if ( m_pImpl->m_bMouseButtonDown )
        {
            ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) );
            if ( !!aHitItem )
            {
                // re-draw that item now that we're not in mouse-down mode anymore
                m_pImpl->InvalidateItem( *aHitItem );
                // activate the respective panel
                m_pImpl->m_rPanelDeck.ActivatePanel( *aHitItem );
            }

            OSL_ENSURE( IsMouseCaptured(), "PanelTabBar::MouseButtonUp: inconsistency!" );
            if ( IsMouseCaptured() )
                ReleaseMouse();
            m_pImpl->m_bMouseButtonDown = false;
        }
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::RequestHelp( const HelpEvent& i_rHelpEvent )
    {
        m_pImpl->EnsureItemsCache();

        ::boost::optional< size_t > aHelpItem( m_pImpl->FindItemForPoint( ScreenToOutputPixel( i_rHelpEvent.GetMousePosPixel() ) ) );
        if ( !aHelpItem )
            return;

        const ItemDescriptor& rItem( m_pImpl->m_aItems[ *aHelpItem ] );
        if ( rItem.eContent != TABITEM_IMAGE_ONLY )
            // if the text is displayed for the item, we do not need to show it as tooltip
            return;

        const ::rtl::OUString sItemText( rItem.pPanel->GetDisplayName() );
		if ( i_rHelpEvent.GetMode() == HELPMODE_BALLOON )
			Help::ShowBalloon( this, OutputToScreenPixel( rItem.GetCurrentRect().Center() ), rItem.GetCurrentRect(), sItemText );
		else
			Help::ShowQuickHelp( this, rItem.GetCurrentRect(), sItemText );
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::GetFocus()
    {
        Control::GetFocus();
        if ( !m_pImpl->m_aFocusedItem )
            m_pImpl->FocusItem( m_pImpl->m_rPanelDeck.GetActivePanel() );
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::LoseFocus()
    {
        Control::LoseFocus();

        if ( !!m_pImpl->m_aFocusedItem )
        {
            m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
        }

        m_pImpl->m_aFocusedItem.reset();
    }

	//------------------------------------------------------------------------------------------------------------------
    class KeyInputHandler
    {
    public:
        KeyInputHandler( Control& i_rControl, const KeyEvent& i_rKeyEvent )
            :m_rControl( i_rControl )
            ,m_rKeyEvent( i_rKeyEvent )
            ,m_bHandled( false )
        {
        }

        ~KeyInputHandler()
        {
            if ( !m_bHandled )
                m_rControl.Control::KeyInput( m_rKeyEvent );
        }

        void   setHandled()
        {
            m_bHandled = true;
        }

    private:
        Control&        m_rControl;
        const KeyEvent& m_rKeyEvent;
        bool            m_bHandled;
    };

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::KeyInput( const KeyEvent& i_rKeyEvent )
    {
        KeyInputHandler aKeyInputHandler( *this, i_rKeyEvent );

        const KeyCode& rKeyCode( i_rKeyEvent.GetKeyCode() );
        if ( rKeyCode.GetModifier() != 0 )
            // only interested in mere key presses
            return;

        // if there are less than 2 panels, we cannot travel them ...
        const size_t nPanelCount( m_pImpl->m_rPanelDeck.GetPanelCount() );
        if ( nPanelCount < 2 )
            return;

        OSL_PRECOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::KeyInput: we should have a focused item here!" );
            // if we get KeyInput events, we should have the focus. In this case, m_aFocusedItem should not be empty,
            // except if there are no panels, but then we bail out of this method here earlier ...

        bool bFocusNext = false;
        bool bFocusPrev = false;

        switch ( rKeyCode.GetCode() )
        {
        case KEY_UP:    bFocusPrev = true; break;
        case KEY_DOWN:  bFocusNext = true; break;
        case KEY_LEFT:
            if ( IsRTLEnabled() )
                bFocusNext = true;
            else
                bFocusPrev = true;
            break;
        case KEY_RIGHT:
            if ( IsRTLEnabled() )
                bFocusPrev = true;
            else
                bFocusNext = true;
            break;
        case KEY_RETURN:
            m_pImpl->m_rPanelDeck.ActivatePanel( *m_pImpl->m_aFocusedItem );
            break;
        }

        if ( !bFocusNext && !bFocusPrev )
            return;

        m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
        if ( bFocusNext )
        {
            m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + 1 ) % nPanelCount );
        }
        else
        {
            m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + nPanelCount - 1 ) % nPanelCount );
        }
        m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );

        // don't delegate to base class
        aKeyInputHandler.setHandled();
    }

	//------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::DataChanged( const DataChangedEvent& i_rDataChanedEvent )
    {
        Control::DataChanged( i_rDataChanedEvent );

        if  (   ( i_rDataChanedEvent.GetType() == DATACHANGED_SETTINGS )
            &&  ( ( i_rDataChanedEvent.GetFlags() & SETTINGS_STYLE ) != 0 )
            )
        {
            Invalidate();
        }
    }

    //------------------------------------------------------------------------------------------------------------------
    bool PanelTabBar::IsVertical() const
    {
        return m_pImpl->IsVertical();
    }

    //------------------------------------------------------------------------------------------------------------------
    PushButton& PanelTabBar::GetScrollButton( const bool i_bForward )
    {
        return i_bForward ? m_pImpl->m_aScrollForward : m_pImpl->m_aScrollBack;
    }

    //------------------------------------------------------------------------------------------------------------------
    ::boost::optional< size_t > PanelTabBar::GetFocusedPanelItem() const
    {
        return m_pImpl->m_aFocusedItem;
    }

    //------------------------------------------------------------------------------------------------------------------
    void PanelTabBar::FocusPanelItem( const size_t i_nItemPos )
    {
        ENSURE_OR_RETURN_VOID( i_nItemPos < m_pImpl->m_rPanelDeck.GetPanelCount(), "PanelTabBar::FocusPanelItem: illegal item pos!" );

        if ( !HasChildPathFocus() )
            GrabFocus();

        m_pImpl->FocusItem( i_nItemPos );
        OSL_POSTCOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::FocusPanelItem: have the focus, but no focused item?" );
        if ( !!m_pImpl->m_aFocusedItem )
            m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem );
        m_pImpl->m_aFocusedItem.reset( i_nItemPos );
    }

    //------------------------------------------------------------------------------------------------------------------
    Rectangle PanelTabBar::GetItemScreenRect( const size_t i_nItemPos ) const
    {
        return m_pImpl->GetItemScreenRect( i_nItemPos );
    }

    //------------------------------------------------------------------------------------------------------------------
    Reference< XWindowPeer > PanelTabBar::GetComponentInterface( sal_Bool i_bCreate )
    {
        Reference< XWindowPeer > xWindowPeer( Control::GetComponentInterface( sal_False ) );
        if ( !xWindowPeer.is() && i_bCreate )
        {
            xWindowPeer.set( new PanelTabBarPeer( *this ) );
            SetComponentInterface( xWindowPeer );
        }
        return xWindowPeer;
    }

//........................................................................
} // namespace svt
//........................................................................
