/**************************************************************
 * 
 * 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_vcl.hxx"

#include <tools/rc.h>
#include <tools/poly.hxx>

#include <vcl/event.hxx>
#include <vcl/split.hxx>
#include <vcl/svapp.hxx>
#include <vcl/syswin.hxx>
#include <vcl/taskpanelist.hxx>
#include <vcl/gradient.hxx>
#include <vcl/lineinfo.hxx>

#include <rtl/instance.hxx>

#include <window.h>

namespace 
{ 
    struct ImplBlackWall
        : public rtl::StaticWithInit<Wallpaper, ImplBlackWall> {
        Wallpaper operator () () {
            return Wallpaper(COL_BLACK);
        }
    };
    struct ImplWhiteWall
        : public rtl::StaticWithInit<Wallpaper, ImplWhiteWall> {
        Wallpaper operator () () {
            return Wallpaper(COL_LIGHTGRAY);
        }
    }; 
}

// =======================================================================

void Splitter::ImplInitSplitterData()
{
    ImplGetWindowImpl()->mbSplitter        = sal_True;
	mpRefWin		  = NULL;
	mnSplitPos		  = 0;
	mnLastSplitPos	  = 0;
	mnStartSplitPos   = 0;
	mbDragFull		  = sal_False;
    mbKbdSplitting    = sal_False;
    mbInKeyEvent      = 0;
    mnKeyboardStepSize = SPLITTER_DEFAULTSTEPSIZE;
}

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

void Splitter::ImplInit( Window* pParent, WinBits nWinStyle )
{
	Window::ImplInit( pParent, nWinStyle, NULL );

	mpRefWin = pParent;

	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
	long nA = rSettings.GetScrollBarSize();
	long nB = rSettings.GetSplitSize();

	PointerStyle ePointerStyle;

	if ( nWinStyle & WB_HSCROLL )
	{
		ePointerStyle = POINTER_HSPLIT;
		mbHorzSplit = sal_True;
		SetSizePixel( Size( nB, nA ) );
	}
	else
	{
		ePointerStyle = POINTER_VSPLIT;
		mbHorzSplit = sal_False;
		SetSizePixel( Size( nA, nB ) );
	}

	SetPointer( Pointer( ePointerStyle ) );

    if( GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
	    SetBackground( ImplWhiteWall::get() );
    else 
	    SetBackground( ImplBlackWall::get() );

    TaskPaneList *pTList = GetSystemWindow()->GetTaskPaneList();
    pTList->AddWindow( this ); 
}

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

void Splitter::ImplSplitMousePos( Point& rPos )
{
	if ( mbHorzSplit )
	{
		if ( rPos.X() > maDragRect.Right()-1 )
			rPos.X() = maDragRect.Right()-1;
		if ( rPos.X() < maDragRect.Left()+1 )
			rPos.X() = maDragRect.Left()+1;
	}
	else
	{
		if ( rPos.Y() > maDragRect.Bottom()-1 )
			rPos.Y() = maDragRect.Bottom()-1;
		if ( rPos.Y() < maDragRect.Top()+1 )
			rPos.Y() = maDragRect.Top()+1;
	}
}

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

void Splitter::ImplDrawSplitter()
{
	Rectangle aInvRect( maDragRect );

	if ( mbHorzSplit )
	{
		aInvRect.Left() 	= maDragPos.X() - 1;
		aInvRect.Right()	= maDragPos.X() + 1;
	}
	else
	{
		aInvRect.Top()		= maDragPos.Y() - 1;
		aInvRect.Bottom()	= maDragPos.Y() + 1;
	}

	mpRefWin->InvertTracking( mpRefWin->PixelToLogic(aInvRect), SHOWTRACK_SPLIT );
}

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

Splitter::Splitter( Window* pParent, WinBits nStyle ) :
	Window( WINDOW_SPLITTER )
{
	ImplInitSplitterData();
	ImplInit( pParent, nStyle );
}

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

Splitter::Splitter( Window* pParent, const ResId& rResId ) :
	Window( WINDOW_SPLITTER )
{
	ImplInitSplitterData();
	rResId.SetRT( RSC_SPLITTER );
	WinBits nStyle = ImplInitRes( rResId );
	ImplInit( pParent, nStyle );
	ImplLoadRes( rResId );

	if ( !(nStyle & WB_HIDE) )
		Show();
}

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

Splitter::~Splitter()
{
    TaskPaneList *pTList = GetSystemWindow()->GetTaskPaneList();
    pTList->RemoveWindow( this ); 
}

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

void Splitter::SetKeyboardStepSize( long nStepSize )
{
    mnKeyboardStepSize = nStepSize;
}

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

long Splitter::GetKeyboardStepSize() const
{
    return mnKeyboardStepSize;
}
 
// -----------------------------------------------------------------------

Splitter* Splitter::ImplFindSibling()
{
    // look for another splitter with the same parent but different orientation
    Window *pWin = GetParent()->GetWindow( WINDOW_FIRSTCHILD );
    Splitter *pSplitter = NULL;
    while( pWin )
    {
        if( pWin->ImplIsSplitter() )
        {
            pSplitter = (Splitter*) pWin;
            if( pSplitter != this && IsHorizontal() != pSplitter->IsHorizontal() )
                return pSplitter;
        }
        pWin = pWin->GetWindow( WINDOW_NEXT );
    }
    return NULL;
}

// -----------------------------------------------------------------------
    
sal_Bool Splitter::ImplSplitterActive()
{
    // is splitter in document or at scrollbar handle ?

    sal_Bool bActive = sal_True;
	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
	long nA = rSettings.GetScrollBarSize();
	long nB = rSettings.GetSplitSize();

    Size aSize = GetOutputSize();
	if ( mbHorzSplit )
	{
        if( aSize.Width() == nB && aSize.Height() == nA )
            bActive = sal_False;
	}
	else
	{
        if( aSize.Width() == nA && aSize.Height() == nB )
            bActive = sal_False;
	}
    return bActive;
}

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

void Splitter::MouseButtonDown( const MouseEvent& rMEvt )
{
	if ( rMEvt.GetClicks() == 2 )
	{
		if ( mnLastSplitPos != mnSplitPos )
		{
			StartSplit();
			Point aPos = rMEvt.GetPosPixel();
			if ( mbHorzSplit )
				aPos.X() = mnLastSplitPos;
			else
				aPos.Y() = mnLastSplitPos;
			ImplSplitMousePos( aPos );
			Splitting( aPos );
			ImplSplitMousePos( aPos );
			long nTemp = mnSplitPos;
			if ( mbHorzSplit )
				SetSplitPosPixel( aPos.X() );
			else
				SetSplitPosPixel( aPos.Y() );
			mnLastSplitPos = nTemp;
			Split();
			EndSplit();
		}
	}
	else
		StartDrag();
}

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

void Splitter::Tracking( const TrackingEvent& rTEvt )
{
	if ( rTEvt.IsTrackingEnded() )
	{
		if ( !mbDragFull )
			ImplDrawSplitter();

		if ( !rTEvt.IsTrackingCanceled() )
		{
			long nNewPos;
			if ( mbHorzSplit )
				nNewPos = maDragPos.X();
			else
				nNewPos = maDragPos.Y();
			if ( nNewPos != mnStartSplitPos )
			{
				SetSplitPosPixel( nNewPos );
				mnLastSplitPos = 0;
				Split();
			}
			EndSplit();
		}
		else if ( mbDragFull )
		{
			SetSplitPosPixel( mnStartSplitPos );
			Split();
		}
		mnStartSplitPos = 0;
	}
	else
	{
		//Point aNewPos = mpRefWin->ScreenToOutputPixel( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
		Point aNewPos = mpRefWin->NormalizedScreenToOutputPixel( OutputToNormalizedScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
		ImplSplitMousePos( aNewPos );
		Splitting( aNewPos );
		ImplSplitMousePos( aNewPos );

		if ( mbHorzSplit )
		{
			if ( aNewPos.X() == maDragPos.X() )
				return;
		}
		else
		{
			if ( aNewPos.Y() == maDragPos.Y() )
				return;
		}

		if ( mbDragFull )
		{
			maDragPos = aNewPos;
			long nNewPos;
			if ( mbHorzSplit )
				nNewPos = maDragPos.X();
			else
				nNewPos = maDragPos.Y();
			if ( nNewPos != mnSplitPos )
			{
				SetSplitPosPixel( nNewPos );
				mnLastSplitPos = 0;
				Split();
			}

			GetParent()->Update();
		}
		else
		{
			ImplDrawSplitter();
			maDragPos = aNewPos;
			ImplDrawSplitter();
		}
	}
}

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

void Splitter::ImplKbdTracking( KeyCode aKeyCode )
{
    sal_uInt16 nCode = aKeyCode.GetCode();
	if ( nCode == KEY_ESCAPE || nCode == KEY_RETURN )
	{
        if( !mbKbdSplitting )
            return;
        else
            mbKbdSplitting = sal_False;

		if ( nCode != KEY_ESCAPE )
		{
			long nNewPos;
			if ( mbHorzSplit )
				nNewPos = maDragPos.X();
			else
				nNewPos = maDragPos.Y();
			if ( nNewPos != mnStartSplitPos )
			{
				SetSplitPosPixel( nNewPos );
				mnLastSplitPos = 0;
				Split();
			}
		}
		else
		{
			SetSplitPosPixel( mnStartSplitPos );
			Split();
			EndSplit();
		}
		mnStartSplitPos = 0;
	}
	else
	{
		Point aNewPos;
        Size aSize = mpRefWin->GetOutputSize();
        Point aPos = GetPosPixel();
        // depending on the position calc allows continous moves or snaps to row/columns
        // continous mode is active when position is at the origin or end of the splitter
        // otherwise snap mode is active
        // default here is snap, holding shift sets continous mode
        if( mbHorzSplit )
            aNewPos = Point( ImplSplitterActive() ? aPos.X() : mnSplitPos, aKeyCode.IsShift() ? 0 : aSize.Height()/2);
        else
            aNewPos = Point( aKeyCode.IsShift() ? 0 : aSize.Width()/2, ImplSplitterActive() ? aPos.Y() : mnSplitPos );

        Point aOldWindowPos = GetPosPixel();

        int maxiter = 500;  // avoid endless loop
        int delta=0;
        int delta_step = mbHorzSplit  ? aSize.Width()/10 : aSize.Height()/10;
        
        // use the specified step size if it was set
        if( mnKeyboardStepSize != SPLITTER_DEFAULTSTEPSIZE )
            delta_step = mnKeyboardStepSize;

        while( maxiter-- && aOldWindowPos == GetPosPixel() )
        {
            // inc/dec position until application performs changes
            // thus a single key press really moves the splitter
            if( aKeyCode.IsShift() )
                delta++;
            else
                delta += delta_step;

            switch( nCode )
            {
            case KEY_LEFT:  
                aNewPos.X()-=delta;
                break;
            case KEY_RIGHT:  
                aNewPos.X()+=delta;
                break;
            case KEY_UP:  
                aNewPos.Y()-=delta;
                break;
            case KEY_DOWN:  
                aNewPos.Y()+=delta;
                break;
            default:
                maxiter = 0;    // leave loop
                break;
            }
		    ImplSplitMousePos( aNewPos );
		    Splitting( aNewPos );
		    ImplSplitMousePos( aNewPos );

		    if ( mbHorzSplit )
		    {
			    if ( aNewPos.X() == maDragPos.X() )
				    continue;
		    }
		    else
		    {
			    if ( aNewPos.Y() == maDragPos.Y() )
				    continue;
		    }
        
			maDragPos = aNewPos;
			long nNewPos;
			if ( mbHorzSplit )
				nNewPos = maDragPos.X();
			else
				nNewPos = maDragPos.Y();
			if ( nNewPos != mnSplitPos )
			{
				SetSplitPosPixel( nNewPos );
				mnLastSplitPos = 0;
				Split();
			}
			GetParent()->Update();
        }
	}
}

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

void Splitter::StartSplit()
{
	maStartSplitHdl.Call( this );
}

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

void Splitter::Split()
{
	maSplitHdl.Call( this );
}

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

void Splitter::EndSplit()
{
	if ( maEndSplitHdl.IsSet() )
		maEndSplitHdl.Call( this );
}

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

void Splitter::Splitting( Point& /* rSplitPos */ )
{
}

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

void Splitter::SetDragRectPixel( const Rectangle& rDragRect, Window* _pRefWin )
{
	maDragRect = rDragRect;
	if ( !_pRefWin )
		mpRefWin = GetParent();
	else
		mpRefWin = _pRefWin;
}

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

void Splitter::SetSplitPosPixel( long nNewPos )
{
	mnSplitPos = nNewPos;
}

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

void Splitter::SetLastSplitPosPixel( long nNewPos )
{
	mnLastSplitPos = nNewPos;
}

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

void Splitter::StartDrag()
{
	if ( IsTracking() )
		return;

	StartSplit();

	// Tracking starten
	StartTracking();

	// Start-Positon ermitteln
	maDragPos = mpRefWin->GetPointerPosPixel();
	ImplSplitMousePos( maDragPos );
	Splitting( maDragPos );
	ImplSplitMousePos( maDragPos );
	if ( mbHorzSplit )
		mnStartSplitPos = maDragPos.X();
	else
		mnStartSplitPos = maDragPos.Y();

	mbDragFull = (Application::GetSettings().GetStyleSettings().GetDragFullOptions() & DRAGFULL_OPTION_SPLIT) != 0;
	if ( !mbDragFull )
		ImplDrawSplitter();
}


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

void Splitter::ImplStartKbdSplitting()
{
    if( mbKbdSplitting )
        return;

    mbKbdSplitting = sal_True;

	StartSplit();

	// determine start position 
    // because we have no mouse position we take either the position
    // of the splitter window or the last split position
    // the other coordinate is just the center of the reference window
    Size aSize = mpRefWin->GetOutputSize();
    Point aPos = GetPosPixel();
    if( mbHorzSplit )
        maDragPos = Point( ImplSplitterActive() ? aPos.X() : mnSplitPos, aSize.Height()/2 );
    else
        maDragPos = Point( aSize.Width()/2, ImplSplitterActive() ? aPos.Y() : mnSplitPos );
	ImplSplitMousePos( maDragPos );
	Splitting( maDragPos );
	ImplSplitMousePos( maDragPos );
	if ( mbHorzSplit )
		mnStartSplitPos = maDragPos.X();
	else
		mnStartSplitPos = maDragPos.Y();
}

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

void Splitter::ImplRestoreSplitter()
{
    // set splitter in the center of the ref window
    StartSplit();
    Size aSize = mpRefWin->GetOutputSize();
    Point aPos = Point( aSize.Width()/2 , aSize.Height()/2);
    if ( mnLastSplitPos != mnSplitPos && mnLastSplitPos > 5 )
    {
        // restore last pos if it was a useful position (>5)
	    if ( mbHorzSplit )
		    aPos.X() = mnLastSplitPos;
	    else
		    aPos.Y() = mnLastSplitPos;
    }

    ImplSplitMousePos( aPos );
    Splitting( aPos );
    ImplSplitMousePos( aPos );
    long nTemp = mnSplitPos;
    if ( mbHorzSplit )
	    SetSplitPosPixel( aPos.X() );
    else
	    SetSplitPosPixel( aPos.Y() );
    mnLastSplitPos = nTemp;
    Split();
	EndSplit();
}


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

void Splitter::GetFocus()
{
    if( !ImplSplitterActive() )
        ImplRestoreSplitter();

    Invalidate();
}

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

void Splitter::LoseFocus()
{
    if( mbKbdSplitting )
    {
        KeyCode aReturnKey( KEY_RETURN );
        ImplKbdTracking( aReturnKey );
        mbKbdSplitting = sal_False;
    }
    Invalidate();
}

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

void Splitter::KeyInput( const KeyEvent& rKEvt )
{
    if( mbInKeyEvent )
        return;

    mbInKeyEvent = 1;

    Splitter *pSibling = ImplFindSibling();
    KeyCode aKeyCode = rKEvt.GetKeyCode();
    sal_uInt16 nCode = aKeyCode.GetCode();
    switch ( nCode )
    {
        case KEY_UP:
        case KEY_DOWN:
            if( !mbHorzSplit )
            {
                ImplStartKbdSplitting();
                ImplKbdTracking( aKeyCode );
            }
            else
            {
                if( pSibling )
                {
                    pSibling->GrabFocus();
                    pSibling->KeyInput( rKEvt );
                }
            }
            break;
        case KEY_RIGHT:
        case KEY_LEFT:
            if( mbHorzSplit )
            {
                ImplStartKbdSplitting();
                ImplKbdTracking( aKeyCode );
            }
            else
            {
                if( pSibling )
                {
                    pSibling->GrabFocus();
                    pSibling->KeyInput( rKEvt );
                }
            }
            break;

        case KEY_DELETE:
            if( ImplSplitterActive() )
            {
                if( mbKbdSplitting )
                {
                    KeyCode aKey( KEY_ESCAPE );
                    ImplKbdTracking( aKey );
                }

			    StartSplit();
			    Point aPos;
			    if ( mbHorzSplit )
				    aPos.X() = 0;
			    else
				    aPos.Y() = 0;
			    ImplSplitMousePos( aPos );
			    Splitting( aPos );
			    ImplSplitMousePos( aPos );
			    long nTemp = mnSplitPos;
			    if ( mbHorzSplit )
				    SetSplitPosPixel( aPos.X() );
			    else
				    SetSplitPosPixel( aPos.Y() );
			    mnLastSplitPos = nTemp;
			    Split();
				EndSplit();

                // Shift-Del deletes both splitters
                if( aKeyCode.IsShift() && pSibling )
                    pSibling->KeyInput( rKEvt );

                GrabFocusToDocument();
            }
            break;

        case KEY_ESCAPE:
            if( mbKbdSplitting )
                ImplKbdTracking( aKeyCode );
            else
                GrabFocusToDocument();
            break;

        case KEY_RETURN:
            ImplKbdTracking( aKeyCode );
            GrabFocusToDocument();
            break;
        default:    // let any key input fix the splitter
            Window::KeyInput( rKEvt );
            GrabFocusToDocument();
            break;
    }
    mbInKeyEvent = 0;    
}

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

long Splitter::Notify( NotifyEvent& rNEvt )
{
    return Window::Notify( rNEvt );
}

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

void Splitter::DataChanged( const DataChangedEvent& rDCEvt )
{
    Window::DataChanged( rDCEvt );
    if( rDCEvt.GetType() == DATACHANGED_SETTINGS )
    {
        Color oldFaceColor = ((AllSettings *) rDCEvt.GetData())->GetStyleSettings().GetFaceColor();
        Color newFaceColor = Application::GetSettings().GetStyleSettings().GetFaceColor();
        if( oldFaceColor.IsDark() != newFaceColor.IsDark() )
        {
            if( newFaceColor.IsDark() )
	            SetBackground( ImplWhiteWall::get() );
            else 
	            SetBackground( ImplBlackWall::get() );
        }
    }
}

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

void Splitter::Paint( const Rectangle& rPaintRect )
{
    if( HasFocus() || mbKbdSplitting )
    {   
        Color oldFillCol = GetFillColor();
        Color oldLineCol = GetLineColor();

        SetLineColor();
        SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
        DrawRect( rPaintRect );

        Color aSelectionBorderCol( GetSettings().GetStyleSettings().GetActiveColor() );
        SetFillColor( aSelectionBorderCol );
        SetLineColor();

	    Polygon aPoly( rPaintRect );
		PolyPolygon aPolyPoly( aPoly );
		DrawTransparent( aPolyPoly, 85 );

        SetLineColor( aSelectionBorderCol );
        SetFillColor();

        if( mbKbdSplitting )
        {
            LineInfo aInfo( LINE_DASH );
            //aInfo.SetDashLen( 2 );
            //aInfo.SetDashCount( 1 );
            aInfo.SetDistance( 1 );
            aInfo.SetDotLen( 2 );
            aInfo.SetDotCount( 1 );

            DrawPolyLine( aPoly, aInfo );
        }
        else
            DrawRect( rPaintRect );

        SetFillColor( oldFillCol);
        SetLineColor( oldLineCol);
    }
    else
    {
        Window::Paint( rPaintRect );
    }
}
