//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================

#include "vgui_scrollbar2.h"
#include "vgui_slider2.h"
#include "vgui_loadtga.h"

#include <VGUI_IntChangeSignal.h>
#include <VGUI_Button.h>
#include <VGUI_ActionSignal.h>
#include <VGUI_LineBorder.h>

using namespace vgui;

namespace
{
class FooDefaultScrollBarIntChangeSignal : public IntChangeSignal
{
public:
	FooDefaultScrollBarIntChangeSignal( ScrollBar2 *scrollBar )
	{
		_scrollBar = scrollBar;
	}

	virtual void intChanged( int value, Panel *panel )
	{
		_scrollBar->fireIntChangeSignal();
	}
protected:
	ScrollBar2 *_scrollBar;
};

class FooDefaultButtonSignal : public ActionSignal
{
public:
	ScrollBar2	*_scrollBar;
	int		 _buttonIndex;

	FooDefaultButtonSignal( ScrollBar2 *scrollBar, int buttonIndex )
	{
		_scrollBar = scrollBar;
		_buttonIndex = buttonIndex;
	}

	virtual void actionPerformed( Panel *panel )
	{
		_scrollBar->doButtonPressed( _buttonIndex );
	}
};
}

//-----------------------------------------------------------------------------
// Purpose: Default scrollbar button
//			Draws in new scoreboard style
//-----------------------------------------------------------------------------
class ScrollBarButton : public Button
{
private:
	LineBorder m_Border;

public:
	ScrollBarButton( const char *filename, int x, int y, int wide, int tall ) : m_Border( Color( 60, 60, 60, 0 ) ), Button( "", x, y, wide, tall )
	{
		Image *image = vgui_LoadTGA( filename );
		if( image )
		{
			image->setColor( Color( 140, 140, 140, 0 ) );
			setImage( image );
		}

		setBorder( &m_Border );
	}

	virtual void paintBackground()
	{
		int wide, tall;
		getPaintSize( wide, tall );

		// fill the background
		drawSetColor( 0, 0, 0, 0 );
		drawFilledRect( 0, 0, wide, tall );
	}
};

//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input  : x - 
//			y - 
//			wide - 
//			tall - 
//			vertical - 
//-----------------------------------------------------------------------------
ScrollBar2::ScrollBar2( int x, int y, int wide, int tall, bool vertical ) : Panel( x, y, wide, tall )
{
	_slider = null;
	_button[0] = null;
	_button[1] = null;
	
	if( vertical )
	{
		setSlider( new Slider2( 0, wide - 1, wide, ( tall - ( wide * 2 ) ) + 2, true ) );
		setButton( new ScrollBarButton( "gfx/vgui/arrowup.tga", 0, 0, wide, wide ), 0 );
		setButton( new ScrollBarButton( "gfx/vgui/arrowdown.tga", 0, tall - wide, wide, wide ), 1 );
	}
	else
	{
		// untested code
		setSlider( new Slider2( tall, 0, wide - ( tall * 2 ), tall, false ) );
		setButton( new ScrollBarButton( "gfx/vgui/320_arrowlt.tga", 0, 0, tall + 1, tall + 1 ), 0 );
		setButton( new ScrollBarButton( "gfx/vgui/320_arrowrt.tga", wide - tall, 0, tall + 1, tall + 1 ) , 1 );
	}

	setPaintBorderEnabled( true );
	setPaintBackgroundEnabled( true );
	setPaintEnabled( true );
	setButtonPressedScrollValue( 15 );

	validate();
}

void ScrollBar2::setSize( int wide, int tall )
{
	Panel::setSize( wide, tall );

	if( _slider == null )
	{
		return;
	}

	if( _button[0] == null )
	{
		return;
	}

	if( _button[1] == null )
	{
		return;
	}

	getPaintSize( wide, tall );

	if( _slider->isVertical() )
	{
		_slider->setBounds( 0, wide, wide, tall - ( wide * 2 ) );
		// _slider->setBounds( 0, 0, wide, tall );
		_button[0]->setBounds( 0, 0, wide, wide );
		_button[1]->setBounds( 0, tall - wide, wide, wide );
	}
	else
	{
		_slider->setBounds( tall, 0, wide - ( tall * 2 ), tall );
		// _slider->setBounds( 0, 0, wide, tall );
		_button[0]->setBounds( 0, 0, tall, tall );
		_button[1]->setBounds( ( wide - tall ), 0, tall, tall);
	}
}

void ScrollBar2::performLayout()
{
}

void ScrollBar2::setValue( int value )
{
	_slider->setValue( value );
}

int ScrollBar2::getValue()
{
	return _slider->getValue();
}

void ScrollBar2::addIntChangeSignal( IntChangeSignal *s )
{
	_intChangeSignalDar.putElement( s );
	_slider->addIntChangeSignal( new FooDefaultScrollBarIntChangeSignal( this ) );
}

void ScrollBar2::setRange( int min, int max )
{
	_slider->setRange( min, max );
}

void ScrollBar2::fireIntChangeSignal()
{
	for( int i = 0; i < _intChangeSignalDar.getCount(); i++ )
	{
		_intChangeSignalDar[i]->intChanged( _slider->getValue(), this );
	}
}

bool ScrollBar2::isVertical()
{
	return _slider->isVertical();
}

bool ScrollBar2::hasFullRange()
{
	return _slider->hasFullRange();
}

// LEAK: new and old slider will leak
void ScrollBar2::setButton( Button *button, int index )
{
	if( _button[index] != null )
	{
		removeChild( _button[index] );
	}

	_button[index] = button;
	addChild( _button[index] );

	_button[index]->addActionSignal( new FooDefaultButtonSignal( this, index ) );

	validate();

	// _button[index]->setVisible( false );
}

Button *ScrollBar2::getButton( int index )
{
	return _button[index];
}

// LEAK: new and old slider will leak
void ScrollBar2::setSlider( Slider2 *slider )
{
	if( _slider != null )
	{
		removeChild( _slider );
	}

	_slider = slider;
	addChild( _slider );

	_slider->addIntChangeSignal( new FooDefaultScrollBarIntChangeSignal( this ) );

	validate();
}

Slider2 *ScrollBar2::getSlider()
{
	return _slider;
}

void ScrollBar2::doButtonPressed( int buttonIndex )
{
	if( buttonIndex == 0 )
	{
		_slider->setValue( _slider->getValue() - _buttonPressedScrollValue );
	}
	else
	{
		_slider->setValue( _slider->getValue() + _buttonPressedScrollValue );
	}
}

void ScrollBar2::setButtonPressedScrollValue( int value )
{
	_buttonPressedScrollValue = value;
}

void ScrollBar2::setRangeWindow( int rangeWindow )
{
	_slider->setRangeWindow( rangeWindow );
}

void ScrollBar2::setRangeWindowEnabled( bool state )
{
	_slider->setRangeWindowEnabled( state );
}

void ScrollBar2::validate()
{
	if( _slider != null )
	{
		int buttonOffset = 0;

		for( int i = 0; i < 2; i++ )
		{
			if( _button[i] != null )
			{
				if( _button[i]->isVisible() )
				{
					if( _slider->isVertical() )
					{				
						buttonOffset += _button[i]->getTall();
					}
					else
					{
						buttonOffset += _button[i]->getWide();
					}
				}
			}
		}

		_slider->setButtonOffset( buttonOffset );
	}

	int wide, tall;

	getSize( wide, tall );
	setSize( wide, tall );
}