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

#define _TASKBAR_CXX

#include <tools/list.hxx>
#include <tools/debug.hxx>
#include <vcl/floatwin.hxx>

#include <svtools/taskbar.hxx>

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

class ImplTaskBarFloat : public FloatingWindow
{
public:
	TaskBar*			mpTaskBar;

public:
						ImplTaskBarFloat( TaskBar* pTaskBar );
};

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

ImplTaskBarFloat::ImplTaskBarFloat( TaskBar* pTaskBar ) :
	FloatingWindow( pTaskBar, 0 )
{
	mpTaskBar	= pTaskBar;
}

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

#define TASKBAR_BORDER				2
#define TASKBAR_OFFSIZE 			3
#define TASKBAR_OFFX				2
#define TASKBAR_OFFY				1
#define TASKBAR_BUTTONOFF			5
#define TASKBAR_AUTOHIDE_HEIGHT 	2

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

TaskBar::TaskBar( Window* pParent, WinBits nWinStyle ) :
	Window( pParent, WB_3DLOOK )
{
	mpButtonBar 		= NULL;
	mpTaskToolBox		= NULL;
	mpStatusBar 		= NULL;
	mnStatusWidth		= 0;
	mnOldStatusWidth	= 0;
	mnLines 			= 1;
	mnWinBits			= nWinStyle;
	mbStatusText		= sal_False;
	mbShowItems 		= sal_False;
	mbAutoHide			= sal_False;

	ImplInitSettings();
}

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

TaskBar::~TaskBar()
{
	if ( mpButtonBar )
		delete mpButtonBar;
	if ( mpTaskToolBox )
		delete mpTaskToolBox;
	if ( mpStatusBar )
		delete mpStatusBar;
}

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

void TaskBar::ImplInitSettings()
{
	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();

	Color aColor;
	if ( IsControlBackground() )
		aColor = GetControlBackground();
	else if ( Window::GetStyle() & WB_3DLOOK )
		aColor = rStyleSettings.GetFaceColor();
	else
		aColor = rStyleSettings.GetWindowColor();
	SetBackground( aColor );
}

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

void TaskBar::ImplNewHeight( long nNewHeight )
{
	long nOldHeight = GetSizePixel().Height();
	if ( nNewHeight != nOldHeight )
	{
		long nY = GetPosPixel().Y()-(nNewHeight-nOldHeight);
		SetPosSizePixel( 0, nY, 0, nNewHeight,
						 WINDOW_POSSIZE_Y | WINDOW_POSSIZE_HEIGHT );
		TaskResize();
	}
}

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

void TaskBar::TaskResize()
{
	maTaskResizeHdl.Call( this );
}

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

TaskButtonBar* TaskBar::CreateButtonBar()
{
	return new TaskButtonBar( this );
}

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

TaskToolBox* TaskBar::CreateTaskToolBox()
{
	return new TaskToolBox( this );
}

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

TaskStatusBar* TaskBar::CreateTaskStatusBar()
{
	return new TaskStatusBar( this );
}

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

void TaskBar::MouseMove( const MouseEvent& rMEvt )
{
	if ( mnWinBits & WB_SIZEABLE )
	{
		TaskToolBox*	pTempTaskToolBox = GetTaskToolBox();
		TaskStatusBar*	pTempStatusBar = GetStatusBar();

		if ( pTempTaskToolBox && pTempStatusBar )
		{
			long			nStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
			long			nMouseX = rMEvt.GetPosPixel().X();
			PointerStyle	ePtrStyle;
			if ( (nMouseX >= nStatusX-1) && (nMouseX <= nStatusX+3) )
				ePtrStyle = POINTER_HSIZEBAR;
			else
				ePtrStyle = POINTER_ARROW;
			Pointer aPtr( ePtrStyle );
			SetPointer( aPtr );
		}
	}
}

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

void TaskBar::MouseButtonDown( const MouseEvent& rMEvt )
{
	if ( rMEvt.IsLeft() && (mnWinBits & WB_SIZEABLE) )
	{
		TaskToolBox*	pTempTaskToolBox = GetTaskToolBox();
		TaskStatusBar*	pTempStatusBar = GetStatusBar();

		if ( pTempTaskToolBox && pTempStatusBar )
		{
			long	nStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
			long	nMouseX = rMEvt.GetPosPixel().X();
			if ( (nMouseX >= nStatusX-1) && (nMouseX <= nStatusX+3) )
			{
				if ( rMEvt.GetClicks() == 2 )
				{
					if ( mnStatusWidth )
					{
						mnStatusWidth = 0;
						Resize();
					}
				}
				else
				{
					StartTracking();
					mnOldStatusWidth = mnStatusWidth;
					mnMouseOff = nMouseX-nStatusX;
				}
			}
		}
	}
}

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

void TaskBar::Tracking( const TrackingEvent& rTEvt )
{
	if ( rTEvt.IsTrackingEnded() )
	{
		if ( rTEvt.IsTrackingCanceled() )
		{
			mnStatusWidth = mnOldStatusWidth;
			Resize();
			Update();
		}
	}
	else
	{
		Size aSize = GetOutputSizePixel();

		long nMouseX = rTEvt.GetMouseEvent().GetPosPixel().X()-mnMouseOff;
		if ( nMouseX < 0 )
			nMouseX = 0;
		long nMaxX = aSize.Width()-TASKBAR_OFFX-TASKBAR_OFFSIZE-1;
		if ( nMouseX > nMaxX )
			nMouseX = nMaxX;
		mnStatusWidth = aSize.Width()-nMouseX-TASKBAR_OFFX-TASKBAR_OFFSIZE;
		Resize();
		Update();
	}
}

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

void TaskBar::Paint( const Rectangle& rRect )
{
	if ( mnWinBits & (WB_BORDER | WB_SIZEABLE) )
	{
		const StyleSettings&	rStyleSettings = GetSettings().GetStyleSettings();
		Size					aSize = GetOutputSizePixel();
		long	nY = 0;

		if ( mnWinBits & WB_BORDER )
		{
			SetLineColor( rStyleSettings.GetShadowColor() );
			DrawLine( Point( 0, 0 ), Point( aSize.Width()-1, 0 ) );
			SetLineColor( rStyleSettings.GetLightColor() );
			DrawLine( Point( 0, 1 ), Point( aSize.Width()-1, 1 ) );
			nY += 2;
		}

		if ( (mnWinBits & WB_SIZEABLE) )
		{
			//TaskButtonBar*	pTempButtonBar = GetButtonBar();
			TaskToolBox*	pTempTaskToolBox = GetTaskToolBox();
			TaskStatusBar*	pTempStatusBar = GetStatusBar();

			if ( pTempTaskToolBox && pTempStatusBar )
			{
				long nStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
				if ( nStatusX > 0 )
				{
					SetLineColor( rStyleSettings.GetShadowColor() );
					DrawLine( Point( nStatusX, nY ), Point( nStatusX, aSize.Height()-1 ) );
					nStatusX++;
					SetLineColor( rStyleSettings.GetLightColor() );
					DrawLine( Point( nStatusX, nY ), Point( nStatusX, aSize.Height()-1 ) );
				}
			}
		}
	}

	Window::Paint( rRect );
}

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

void TaskBar::Resize()
{
	if ( !IsReallyShown() )
		return;

	TaskButtonBar*	pTempButtonBar = GetButtonBar();
	TaskToolBox*	pTempTaskToolBox = GetTaskToolBox();
	TaskStatusBar*	pTempStatusBar = GetStatusBar();
	Point			aToolPos( TASKBAR_OFFX, 0 );
	Size			aSize = GetOutputSizePixel();
	Size			aStatusSize;
	Size			aToolSize( aSize.Width()-(TASKBAR_OFFX*2), 0 );
	long			nOldStatusX = -1;
	long			nNewStatusX = -1;
	long			nTaskHeight = aSize.Height() - (TASKBAR_OFFY*2);

	if ( mnWinBits & WB_BORDER )
	{
		nTaskHeight -= TASKBAR_BORDER;
		aToolPos.Y() += TASKBAR_BORDER;
	}

	if ( pTempButtonBar )
	{
		sal_uInt16	i = 0;
		sal_Bool	bVisibleItems = sal_False;
		while ( i < pTempButtonBar->GetItemCount() )
		{
			if ( pTempButtonBar->IsItemVisible( pTempButtonBar->GetItemId( i ) ) )
			{
				bVisibleItems = sal_True;
				break;
			}
			i++;
		}
		if ( mbStatusText || !bVisibleItems )
			pTempButtonBar->Hide();
		else
		{
			Size aButtonBarSize = pTempButtonBar->CalcWindowSizePixel();
			if ( pTempButtonBar->GetItemCount() )
				nTaskHeight = aButtonBarSize.Height();
			else
				aButtonBarSize.Height() = nTaskHeight;
			Point aTempPos = aToolPos;
			aTempPos.Y() += (aSize.Height()-aButtonBarSize.Height()-aTempPos.Y())/2;
			pTempButtonBar->SetPosSizePixel( aTempPos, aButtonBarSize );
			pTempButtonBar->Show();
			aToolPos.X() += aButtonBarSize.Width()+TASKBAR_BUTTONOFF;
		}
	}

	if ( pTempStatusBar )
	{
		aStatusSize = pTempStatusBar->CalcWindowSizePixel();
		if ( mnStatusWidth )
			aStatusSize.Width() = mnStatusWidth;
		if ( !pTempTaskToolBox || mbStatusText )
			aStatusSize.Width() = aSize.Width();
		long nMaxHeight = aSize.Height()-(TASKBAR_OFFY*2);
		if ( mnWinBits & WB_BORDER )
			nMaxHeight -= TASKBAR_BORDER;
		if ( nMaxHeight+2 > aStatusSize.Height() )
			aStatusSize.Height() = nMaxHeight;
		Point aPos( aSize.Width()-aStatusSize.Width(), 0 );
		if ( pTempTaskToolBox && (mnWinBits & WB_SIZEABLE) && !mbStatusText )
		{
			long nMinToolWidth = aToolPos.X()+50;
			if ( aPos.X() < nMinToolWidth )
			{
				aStatusSize.Width() -= nMinToolWidth-aPos.X();
				aPos.X() = nMinToolWidth;
			}
		}
		if ( aPos.X() < 0 )
		{
			aStatusSize.Width() = aSize.Width();
			aPos.X() = 0;
		}
		if ( mnWinBits & WB_BORDER )
			aPos.Y() += TASKBAR_BORDER;
		aPos.Y() += (aSize.Height()-aStatusSize.Height()-aPos.Y())/2;
		if ( mnWinBits & WB_SIZEABLE )
		{
			if ( pTempTaskToolBox )
			{
				nOldStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
				nNewStatusX = aPos.X()-TASKBAR_OFFSIZE-2;
			}
		}
		pTempStatusBar->SetPosSizePixel( aPos, aStatusSize );
		pTempStatusBar->Show();
		aToolSize.Width() = aPos.X()-aToolPos.X()-TASKBAR_OFFX;
		if ( mnWinBits & WB_SIZEABLE )
			aToolSize.Width() -= (TASKBAR_OFFSIZE*2)-2;
	}

	if ( pTempTaskToolBox )
	{
		if ( aToolSize.Width() <= 24 )
			pTempTaskToolBox->Hide();
		else
		{
			aToolSize.Height() = pTempTaskToolBox->CalcWindowSizePixel().Height();
			if ( pTempTaskToolBox->GetItemCount() )
				nTaskHeight = aToolSize.Height();
			else
				aToolSize.Height() = nTaskHeight;
			aToolPos.Y() += (aSize.Height()-aToolSize.Height()-aToolPos.Y())/2;
			pTempTaskToolBox->SetPosSizePixel( aToolPos, aToolSize );
			pTempTaskToolBox->Show();
		}
	}

	if ( nOldStatusX != nNewStatusX )
	{
		if ( nOldStatusX > 0 )
		{
			Rectangle aRect( nOldStatusX, 0, nOldStatusX+2, aSize.Height()-1 );
			Invalidate( aRect );
		}
		if ( nNewStatusX > 0 )
		{
			Rectangle aRect( nNewStatusX, 0, nNewStatusX+2, aSize.Height()-1 );
			Invalidate( aRect );
		}
	}
}

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

void TaskBar::StateChanged( StateChangedType nType )
{
	Window::StateChanged( nType );

	if ( nType == STATE_CHANGE_INITSHOW )
		Format();
	else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
	{
		ImplInitSettings();
		Invalidate();
	}
	else if ( nType == STATE_CHANGE_FORMAT )
	{
		ImplInitSettings();
		ImplNewHeight( CalcWindowSizePixel().Height() );
		Format();
		Invalidate();
	}
}

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

void TaskBar::DataChanged( const DataChangedEvent& rDCEvt )
{
	Window::DataChanged( rDCEvt );

	if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
		 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
		 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
		  (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
	{
		// Asyncronen StateChanged ausloesen, damit sich die
		// TaskBar an die neuen Groessen der Child-Fenster
		// orientieren kann
		PostStateChanged( STATE_CHANGE_FORMAT );
	}
}

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

void TaskBar::Format()
{
	ImplNewHeight( CalcWindowSizePixel().Height() );
	Resize();
}

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

void TaskBar::SetLines( sal_uInt16 nLines )
{
	mnLines = nLines;
}

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

void TaskBar::EnableAutoHide( sal_Bool bAutoHide )
{
	mbAutoHide = bAutoHide;

	if ( mbAutoHide )
	{
		ImplNewHeight( TASKBAR_AUTOHIDE_HEIGHT );
	}
	else
	{
		ImplNewHeight( CalcWindowSizePixel().Height() );
	}
}

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

void TaskBar::ShowStatusText( const String& rText )
{
	if ( mpStatusBar )
	{
		if ( !mbStatusText )
		{
			mbStatusText = sal_True;
			if ( mpStatusBar->AreItemsVisible() )
			{
				mbShowItems = sal_True;
				mpStatusBar->HideItems();
			}
			else
				mbShowItems = sal_True;
			maOldText = mpStatusBar->GetText();
			Resize();
			mpStatusBar->SetText( rText );
			Update();
			mpStatusBar->Update();
		}
		else
			mpStatusBar->SetText( rText );
	}
}

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

void TaskBar::HideStatusText()
{
	if ( mbStatusText && mpStatusBar )
	{
		mbStatusText = sal_False;
		mpStatusBar->SetText( maOldText );
		Resize();
		if ( mbShowItems )
			mpStatusBar->ShowItems();
	}
}

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

Size TaskBar::CalcWindowSizePixel() const
{
	TaskButtonBar*	pTempButtonBar = GetButtonBar();
	TaskToolBox*	pTempTaskToolBox = GetTaskToolBox();
	TaskStatusBar*	pTempStatusBar = GetStatusBar();
	Size			aSize;
	long			nTempHeight;

	if ( pTempButtonBar && pTempButtonBar->GetItemCount() )
		aSize.Height() = pTempButtonBar->CalcWindowSizePixel().Height()+(TASKBAR_OFFY*2);
	if ( pTempTaskToolBox && pTempTaskToolBox->GetItemCount() )
	{
		nTempHeight = pTempTaskToolBox->CalcWindowSizePixel().Height()+(TASKBAR_OFFY*2);
		if ( nTempHeight > aSize.Height() )
			 aSize.Height() = nTempHeight;
	}
	if ( pTempStatusBar )
	{
		nTempHeight = pTempStatusBar->GetSizePixel().Height();
		if ( nTempHeight > aSize.Height() )
			 aSize.Height() = nTempHeight;
	}

	if ( mnWinBits & WB_BORDER )
		aSize.Height() += TASKBAR_BORDER;

	return aSize;
}

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

TaskButtonBar* TaskBar::GetButtonBar() const
{
	if ( !mpButtonBar )
		((TaskBar*)this)->mpButtonBar = ((TaskBar*)this)->CreateButtonBar();
	return mpButtonBar;
}

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

TaskToolBox* TaskBar::GetTaskToolBox() const
{
	if ( !mpTaskToolBox )
		((TaskBar*)this)->mpTaskToolBox = ((TaskBar*)this)->CreateTaskToolBox();
	return mpTaskToolBox;
}

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

TaskStatusBar* TaskBar::GetStatusBar() const
{
	if ( !mpStatusBar )
	{
		((TaskBar*)this)->mpStatusBar = ((TaskBar*)this)->CreateTaskStatusBar();
		if ( mpStatusBar )
			mpStatusBar->mpNotifyTaskBar = (TaskBar*)this;
	}
	return mpStatusBar;
}
