
#include <XConfig.h>

#ifndef PandaWave_XSLIDECONTROL
#include <XSlideControl.h>
#endif

#include <XDraw.h>
#include <XMessages.h>


/*$	XGSlideControl::XGSlideControl
 *
 *		Construct me
 */

XGSlideControl::XGSlideControl(XGView *parent, XGArgStream &s) : XGSlider(parent,s)
{
	fCurValue = s.ReadInteger();
	fMinValue = s.ReadInteger();
	fMaxValue = s.ReadInteger();
}

/*$	XGSlideControl::~XGSlideControl
 *
 *		Go the way of the dodo
 */

XGSlideControl::~XGSlideControl()
{
}




void XGSlideControl::DoDrawView( XRect )
{
	if (fMinValue >= fMaxValue) return;
	
	XRect content = GetContentRect();
	bool horiz = (content.right - content.left > content.bottom - content.top);
	
	XGDraw draw(this);
	draw.Draw3DRect( content, KXGEBackground );
	draw.SetForeColor( KXGColorBtnText );
	long range;
	if (horiz) {
		InsetRect( &content, 5, 0 );
		range = content.right - content.left;
	} else {
		InsetRect( &content, 0, 5 );
		range = content.bottom - content.top;
	}
	if (range < 0) return;
	long pos = (long)(((double)range) * (double)(fCurValue + 0.5 - fMinValue) / (double)(fMaxValue - fMinValue));
	XRect r = content;
	if (horiz) {
		r.bottom = r.top + 3;
	} else {
		r.right = r.left + 3;
	}
	draw.FrameRect( r );
	if (horiz) {
		draw.MoveTo( r.left + pos, r.bottom );
		draw.Line( -5, 5 );
		draw.Line( 10, 0 );
		draw.Line( -5, -5 );
	} else {
		draw.MoveTo( r.right, r.bottom - pos );
		draw.Line( 5, 5 );
		draw.Line( 0, -5 );
		draw.Line( -5, 5 );
	}
}


bool XGSlideControl::DoMouseDown( XPoint pt, short )
{
	XRect content = GetContentRect();
	bool horiz = (content.right - content.left > content.bottom - content.top);
	long range;
	if (horiz) {
		InsetRect( &content, 5, 0 );
		range = content.right - content.left;
	} else {
		InsetRect( &content, 0, 5 );
		range = content.bottom - content.top;
	}
	if (range < 0) return false;
	long pos = (long)(((double)range) * (double)(fCurValue + 0.5 - fMinValue) / (double)(fMaxValue - fMinValue));
	
	fDragAnchor = pt;
	if (horiz) {
		if (abs(pt.h - (content.left + pos)) > 5) {
			SetValue( fMinValue + 0.5 + (fMaxValue - fMinValue) * (double)(pt.h - content.left) / (double)(content.right - content.left) );
			UpdateView();
		}
	} else {
		if (abs(pt.v - (content.bottom - pos)) > 5) {
			SetValue( fMinValue + 0.5 + (fMaxValue - fMinValue) * (double)(content.bottom - pt.v) / (double)(content.bottom - content.top) );
			UpdateView();
		}
	}
	fDragValue = fCurValue;
	
	return true;
}


void XGSlideControl::DoMouseMove( XPoint pt, short a )
{
	if (!(a & KCapturedMouse)) return;
	
	XRect content = GetContentRect();
	bool horiz = (content.right - content.left > content.bottom - content.top);
	long range;
	if (horiz) {
		InsetRect( &content, 5, 0 );
		range = content.right - content.left;
	} else {
		InsetRect( &content, 0, 5 );
		range = content.bottom - content.top;
	}
	if (range < 0) return;
	long pos = (long)(((double)range) * (double)(fDragValue + 0.5 - fMinValue) / (double)(fMaxValue - fMinValue));
	if (horiz) {
		SetValue( fDragValue + (long)((double)(pt.h - fDragAnchor.h) * (double)(fMaxValue - fMinValue) / (double)range) );
	} else {
		SetValue( fDragValue + (long)((double)(fDragAnchor.v - pt.v) * (double)(fMaxValue - fMinValue) / (double)range) );
	}
	UpdateView();
}


/************************************************************************/
/*																		*/
/*	Value management													*/
/*																		*/
/************************************************************************/

/*$	XGSlideControl::GetMinValue
 *
 *		Get my minimum value
 */

long XGSlideControl::GetMinValue()
{
	return fMinValue;
}

/*$	XGSlideControl::GetMaxValue
 *
 *		Get my maximum value
 */

long XGSlideControl::GetMaxValue()
{
	return fMaxValue;
}

/*$	XGSlideControl::GetValue
 8
 *		Get my current value
 */

long XGSlideControl::GetValue()
{
	return fCurValue;
}

/*$	XGSlideControl::SetMinValue
 *
 *		Set my minimum value.
 */

void XGSlideControl::SetMinValue(long value)
{
	if (fMinValue == value) return;
	fMinValue = value;
	if (fCurValue < fMinValue) {
		SetValue(fMinValue);
	} else {
		InvalView();
	}
}

/*$	XGSlideControl::SetMaxValue
 *
 *		Set my maximum value
 */

void XGSlideControl::SetMaxValue(long value)
{
	if (fMaxValue == value) return;
	fMaxValue = value;
	if (fCurValue > fMaxValue) {
		SetValue(fMinValue);
	} else {
		InvalView();
	}
}

/*$	XGSlideControl::SetValue
 *
 *		Set my value. This draws the status bar immediately. The
 *	'fUpdate' flag is used to determine if I should update when the
 *	value is the same; that's set when the min or max values are changed.
 */

void XGSlideControl::SetValue(long value)
{
	if (fMinValue > value) value = fMinValue;
	if (fMaxValue < value) value = fMaxValue;
	if (fCurValue == value) return;
	XGSValue v;
	
	v.slider = this;
	v.oldVal = fCurValue;
	v.newVal = value;
	fCurValue = value;
	DoDispatch( KXGSliderValue, GetViewID(), (void *)&v );
	InvalView();
}
