/**************************************************************
 * 
 * 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/drawerlayouter.hxx"
#include "toolpaneldrawer.hxx"

#include <com/sun/star/accessibility/XAccessible.hpp>

#include <comphelper/accimplaccess.hxx>
#include <tools/diagnose_ex.h>

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

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::accessibility::XAccessible;
    /** === end UNO using === **/

	//==================================================================================================================
	//= DrawerDeckLayouter
	//==================================================================================================================
	//------------------------------------------------------------------------------------------------------------------
    DrawerDeckLayouter::DrawerDeckLayouter( ::Window& i_rParentWindow, IToolPanelDeck& i_rPanels )
        :m_rParentWindow( i_rParentWindow )
        ,m_rPanelDeck( i_rPanels )
        ,m_aDrawers()
        ,m_aLastKnownActivePanel()
    {
        m_rPanelDeck.AddListener( *this );

        // simulate PanelInserted events for the panels which are already there
        for ( size_t i=0; i<m_rPanelDeck.GetPanelCount(); ++i )
            PanelInserted( m_rPanelDeck.GetPanel( i ), i );
    }

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

	//------------------------------------------------------------------------------------------------------------------
    IMPLEMENT_IREFERENCE( DrawerDeckLayouter )

	//------------------------------------------------------------------------------------------------------------------
    Rectangle DrawerDeckLayouter::Layout( const Rectangle& i_rDeckPlayground )
    {
        const size_t nPanelCount( m_rPanelDeck.GetPanelCount() );
        if ( nPanelCount == 0 )
            return i_rDeckPlayground;

        const int nWidth( i_rDeckPlayground.GetWidth() );
        ::boost::optional< size_t > aActivePanel( m_rPanelDeck.GetActivePanel() );
        if ( !aActivePanel )
            aActivePanel = m_aLastKnownActivePanel;

        // arrange the title bars which are *above* the active panel (or *all* if there is no active panel), plus
        // the title bar of the active panel itself
        Point aUpperDrawerPos( i_rDeckPlayground.TopLeft() );
        const size_t nUpperBound = !!aActivePanel ? *aActivePanel : nPanelCount - 1;
        for ( size_t i=0; i<=nUpperBound; ++i )
        {
            long const nDrawerHeight = m_aDrawers[i]->GetPreferredHeightPixel();
            m_aDrawers[i]->SetPosSizePixel(
                aUpperDrawerPos, Size( nWidth, nDrawerHeight ) );
            aUpperDrawerPos.Move( 0, nDrawerHeight );
        }

        // arrange title bars which are below the active panel (or *none* if there is no active panel)
        Point aLowerDrawerPos( i_rDeckPlayground.BottomLeft() );
        for ( size_t j = nPanelCount - 1; j > nUpperBound; --j )
        {
            long const nDrawerHeight = m_aDrawers[j]->GetPreferredHeightPixel();
            m_aDrawers[j]->SetPosSizePixel(
                Point( aLowerDrawerPos.X(), aLowerDrawerPos.Y() - nDrawerHeight + 1 ),
                Size( nWidth, nDrawerHeight )
            );
            aLowerDrawerPos.Move( 0, -nDrawerHeight );
        }

        // fincally calculate the rectangle for the active panel
        return Rectangle(
            aUpperDrawerPos,
            Size( nWidth, aLowerDrawerPos.Y() - aUpperDrawerPos.Y() + 1 )
        );
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::Destroy()
    {
        while ( !m_aDrawers.empty() )
            impl_removeDrawer( 0 );
        m_rPanelDeck.RemoveListener( *this );
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::SetFocusToPanelSelector()
    {
        const size_t nPanelCount( m_rPanelDeck.GetPanelCount() );
        if ( !nPanelCount )
            // nothing to focus
            return;
        ::boost::optional< size_t > aActivePanel( m_rPanelDeck.GetActivePanel() );
        if ( !aActivePanel )
            aActivePanel = 0;
        ENSURE_OR_RETURN_VOID( *aActivePanel < m_aDrawers.size(), "DrawerDeckLayouter::SetFocusToPanelSelector: invalid active panel, or inconsistent drawers!" );
        m_aDrawers[ *aActivePanel ]->GrabFocus();
    }

	//------------------------------------------------------------------------------------------------------------------
    size_t DrawerDeckLayouter::GetAccessibleChildCount() const
    {
        return m_aDrawers.size();
    }

	//------------------------------------------------------------------------------------------------------------------
    Reference< XAccessible > DrawerDeckLayouter::GetAccessibleChild( const size_t i_nChildIndex, const Reference< XAccessible >& i_rParentAccessible )
    {
        ENSURE_OR_RETURN( i_nChildIndex < m_aDrawers.size(), "illegal index", NULL );

        const PToolPanelDrawer pDrawer( m_aDrawers[ i_nChildIndex ] );

        Reference< XAccessible > xItemAccessible = pDrawer->GetAccessible( sal_False );
        if ( !xItemAccessible.is() )
        {
            xItemAccessible = pDrawer->GetAccessible( sal_True );
            ENSURE_OR_RETURN( xItemAccessible.is(), "illegal accessible provided by the drawer implementation!", NULL );
            OSL_VERIFY( ::comphelper::OAccessibleImplementationAccess::setAccessibleParent( xItemAccessible->getAccessibleContext(),
                i_rParentAccessible ) );
        }

        return xItemAccessible;
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition )
    {
        OSL_PRECOND( i_nPosition <= m_aDrawers.size(), "DrawerDeckLayouter::PanelInserted: inconsistency!" );

        PToolPanelDrawer pDrawer( new ToolPanelDrawer( m_rParentWindow, i_pPanel->GetDisplayName() ) );
        pDrawer->SetHelpId( i_pPanel->GetHelpID() );
        // proper Z-Order
        if ( i_nPosition == 0 )
        {
            pDrawer->SetZOrder( NULL, WINDOW_ZORDER_FIRST );
        }
        else
        {
            const PToolPanelDrawer pFirstDrawer( m_aDrawers[ i_nPosition - 1 ] );
            pDrawer->SetZOrder( pFirstDrawer.get(), WINDOW_ZORDER_BEHIND );
        }

        pDrawer->Show();
        pDrawer->AddEventListener( LINK( this, DrawerDeckLayouter, OnWindowEvent ) );
        m_aDrawers.insert( m_aDrawers.begin() + i_nPosition, pDrawer );
        impl_triggerRearrange();
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::PanelRemoved( const size_t i_nPosition )
    {
        impl_removeDrawer( i_nPosition );
        impl_triggerRearrange();
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::impl_triggerRearrange() const
    {
        // this is somewhat hacky, it assumes that the parent of our panels is a tool panel deck, which, in its
        // Resize implementation, rearrances all elements.
        m_rParentWindow.Resize();
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
    {
        if ( !!i_rOldActive )
        {
            OSL_ENSURE( *i_rOldActive < m_aDrawers.size(), "DrawerDeckLayouter::ActivePanelChanged: illegal old index!" );
            m_aDrawers[ *i_rOldActive ]->SetExpanded( false );
        }

        if ( !!i_rNewActive )
        {
            OSL_ENSURE( *i_rNewActive < m_aDrawers.size(), "DrawerDeckLayouter::ActivePanelChanged: illegal new index!" );
            m_aDrawers[ *i_rNewActive ]->SetExpanded( true );
        }

        impl_triggerRearrange();
    }

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

	//------------------------------------------------------------------------------------------------------------------
    size_t DrawerDeckLayouter::impl_getPanelPositionFromWindow( const Window* i_pDrawerWindow ) const
    {
        for (   ::std::vector< PToolPanelDrawer >::const_iterator drawerPos = m_aDrawers.begin();
                drawerPos != m_aDrawers.end();
                ++drawerPos
            )
        {
            if ( drawerPos->get() == i_pDrawerWindow )
                return drawerPos - m_aDrawers.begin();
        }
        return m_aDrawers.size();
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::impl_removeDrawer( const size_t i_nPosition )
    {
        OSL_PRECOND( i_nPosition < m_aDrawers.size(), "DrawerDeckLayouter::impl_removeDrawer: invalid panel position!" );
        m_aDrawers[ i_nPosition ]->RemoveEventListener( LINK( this, DrawerDeckLayouter, OnWindowEvent ) );
        OSL_ENSURE( m_aDrawers[ i_nPosition ].unique(), "DrawerDeckLayouter::impl_removeDrawer: somebody else is still holding a reference!" );
        m_aDrawers.erase( m_aDrawers.begin() + i_nPosition );
    }

	//------------------------------------------------------------------------------------------------------------------
    IMPL_LINK( DrawerDeckLayouter, OnWindowEvent, VclSimpleEvent*, i_pEvent )
    {
        const VclWindowEvent* pWindowEvent = PTR_CAST( VclWindowEvent, i_pEvent );
        ENSURE_OR_RETURN( pWindowEvent, "no WindowEvent", 0L );

        bool bActivatePanel = false;
        switch ( pWindowEvent->GetId() )
        {
            case VCLEVENT_WINDOW_MOUSEBUTTONUP:
            {
                const MouseEvent* pMouseEvent = static_cast< const MouseEvent* >( pWindowEvent->GetData() );
                ENSURE_OR_RETURN( pMouseEvent, "no mouse event with MouseButtonUp", 0L );
                if ( pMouseEvent->GetButtons() == MOUSE_LEFT )
                {
                    bActivatePanel = true;
                }
            }
            break;
            case VCLEVENT_WINDOW_KEYINPUT:
            {
                const KeyEvent* pKeyEvent = static_cast< const KeyEvent* >( pWindowEvent->GetData() );
                ENSURE_OR_RETURN( pKeyEvent, "no key event with KeyInput", 0L );
                const KeyCode& rKeyCode( pKeyEvent->GetKeyCode() );
                if ( ( rKeyCode.GetModifier() == 0 ) && ( rKeyCode.GetCode() == KEY_RETURN ) )
                {
                    bActivatePanel = true;
                }
            }
            break;
        }
        if ( bActivatePanel )
        {
            const size_t nPanelPos = impl_getPanelPositionFromWindow( pWindowEvent->GetWindow() );
            if ( nPanelPos != m_rPanelDeck.GetActivePanel() )
            {
                m_rPanelDeck.ActivatePanel( nPanelPos );
            }
            else
            {
                PToolPanel pPanel( m_rPanelDeck.GetPanel( nPanelPos ) );
                pPanel->GrabFocus();
            }
            return 1L;
        }
        return 0L;
    }

	//------------------------------------------------------------------------------------------------------------------
    void DrawerDeckLayouter::Dying()
    {
        Destroy();
    }

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