// ===========================================================================
//	CSplitView.cp                                  2004.12.28  Tomoki Sekiyama
// ===========================================================================

#ifdef PowerPlant_PCH
	#include PowerPlant_PCH
#endif

#include "CSplitView.h"
#include <LStream.h>

PP_Begin_Namespace_PowerPlant

const int BAR_WIDTH = 6;
const int MarkerLen = 3;
const int MarkerPitch = 1;
const RGBColor Color_SplitBarFill  = { 0xf400, 0xf400, 0xf400 };
const RGBColor Color_SplitBarLine1 = { 0xcccc, 0xcccc, 0xcccc };
const RGBColor Color_SplitBarLine2 = { 0x9999, 0x9999, 0x9999 };
const RGBColor Color_SplitBarMark  = { 0x6666, 0x6666, 0x6666 };

// ---------------------------------------------------------------------------
//	¥ CSplitView							Default Constructor		  [public]
// ---------------------------------------------------------------------------

CSplitView::CSplitView()
{
	mVertical = false;
	mChild[0] = mChild[1] = 0;
	mChildHidden[0] = mChildHidden[1] = false;
	Shrink1onResize_Callback = DefaultShrink1onResize;
}


// ---------------------------------------------------------------------------
//	¥ CSplitView							Stream Constructor		  [public]
// ---------------------------------------------------------------------------

CSplitView::CSplitView(
	LStream*	inStream)

	: LView(inStream)
{
	mVertical = false;
	mChild[0] = mChild[1] = 0;	
	mChildHidden[0] = mChildHidden[1] = false;
	Shrink1onResize_Callback = DefaultShrink1onResize;
}


// ---------------------------------------------------------------------------
//	¥ CSplitView							Parameterized Constructor [public]
// ---------------------------------------------------------------------------

CSplitView::CSplitView(
	const SPaneInfo&	inPaneInfo,
	const SViewInfo&	inViewInfo,
	bool				inVertical)

	: LView(inPaneInfo, inViewInfo),
	  mVertical(inVertical)
{
	mChild[0] = mChild[1] = 0;
	mChildHidden[0] = mChildHidden[1] = false;
	Shrink1onResize_Callback = DefaultShrink1onResize;
}


// ---------------------------------------------------------------------------
//	¥ ~CSplitView							Destructor				  [public]
// ---------------------------------------------------------------------------

CSplitView::~CSplitView()
{
}


// ---------------------------------------------------------------------------
//	¥ FinishCreateSelf											   [protected]
// ---------------------------------------------------------------------------

void
CSplitView::FinishCreateSelf()
{
	mMin = 0;
	mMax = 0xffff;
	SetPosition(32, true);
}


// ---------------------------------------------------------------------------
//	¥ ResizeFrameBy												   [protected]
// ---------------------------------------------------------------------------

void
CSplitView::ResizeFrameBy(
	SInt16		inWidthDelta,
	SInt16		inHeightDelta,
	Boolean		inRefresh)
{
	int rr = mVertical ? mFrameSize.width : mFrameSize.height;
	rr -= BAR_WIDTH;

	LView::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh);

	if ( mShrinkable[1] ) {
		if ( mPosition == rr )
			SetPosition(mPosition + (mVertical ? inWidthDelta : inHeightDelta), true);
		else {
			rr = (mVertical ? mFrameSize.width : mFrameSize.height);
			rr -= BAR_WIDTH;
			if ( mPosition >= rr ) {
				if ( Shrink1onResize_Callback )
					Shrink1onResize_Callback(this, mPosition, rr);
			}
			else
				SetPosition(mPosition, true);
		}
	}
	else {
		SetPosition(mPosition, true);
	}
}


// ---------------------------------------------------------------------------
//	¥ DefaultShrink1onResize									   [protected]
// ---------------------------------------------------------------------------

void
CSplitView::DefaultShrink1onResize(
	CSplitView*	target,
	UInt16		pos,
	UInt16		rr)
{
	target->SetPosition(rr-1, true); // avoid shrink on making this view smaller
}


// ---------------------------------------------------------------------------
// ¥ Click															  [public]
// ---------------------------------------------------------------------------

void
CSplitView::Click(
	SMouseDownEvent	&inMouseDown)
{
	LPane	*clickedPane = FindSubPaneHitBy(inMouseDown.wherePort.h,
											inMouseDown.wherePort.v);
	if ( clickedPane ) {
		clickedPane->Click(inMouseDown);
		return;
	}

	Rect r;
	CalcSplitBarFrame(r);
	LocalToPortPoint(topLeft(r));
	LocalToPortPoint(botRight(r));
	
	if ( inMouseDown.wherePort.h >= r.left  &&
		 inMouseDown.wherePort.h <  r.right &&
		 inMouseDown.wherePort.v >= r.top   &&
		 inMouseDown.wherePort.v <  r.bottom ) {

		Pattern pat;
		FocusDraw();
		RGBForeColor(&Color_Black);
		PenPat(UQDGlobals::GetGrayPat(&pat));
		PenMode(srcXor);
		PenSize(BAR_WIDTH/2,BAR_WIDTH/2);

		Point point = inMouseDown.wherePort;
		PortToLocalPoint(point);
		int pos = (mVertical ? point.h : point.v)-BAR_WIDTH/2;
		if ( pos < 0 )
			pos = 0;
		SetPosition(pos, false);

		MouseTrackingResult result;
		do {
			CalcSplitBarFrame(r);
			FrameRect(&r);

			UMouseTracking::TrackMouseDown(
				GetMacPort(), point, result);

			FrameRect(&r);
			pos = (mVertical ? point.h : point.v)-BAR_WIDTH/2;
			if ( pos < 0 )
				pos = 0;
			SetPosition(pos, false);
		} while ( result != kMouseTrackingMouseReleased );

		SetPosition(mPosition, true);
	}
}

#pragma mark -

// ---------------------------------------------------------------------------
//	¥ SetChild														  [public]
// ---------------------------------------------------------------------------

void
CSplitView::SetChild(
	UInt8	n,
	LPane	*pane)
{
	if ( pane && ! mSubPanes.ContainsItem(pane) )
		return;
	if ( n < 2 )
	mChild[n] = pane;
}


// ---------------------------------------------------------------------------
//	¥ SetMinMax														  [public]
// ---------------------------------------------------------------------------

void
CSplitView::SetMinMax(
	UInt16 min,
	UInt16 max)
{
	if ( min > max )
		mMin = mMax = min;
	else {
		mMin = min;
		mMax = max;
	}

	if ( mPosition < min || mPosition > max )
		SetPosition(mPosition, true);
}


// ---------------------------------------------------------------------------
//	¥ SetPosition													  [public]
// ---------------------------------------------------------------------------

void
CSplitView::SetPosition(
	UInt16  pos,
	Boolean redraw)
{
	UInt16 oldPos = mPosition;

	Rect r;
	CalcLocalFrameRect(r);
	int rr = mVertical ? r.right : r.bottom;
	rr -= BAR_WIDTH;

	if ( mShrinkable[0] && pos <= 0 )
		mPosition = 0;
	else if ( mShrinkable[1] && pos >= rr )
		mPosition = rr;
	else if ( pos < mMin )
		mPosition = mMin;
	else if ( pos > mMax )
		mPosition = mMax;
	else
		mPosition = pos;
	
	if ( rr <= 0 )
		mPosition = 0;
	else if ( mPosition > rr )
		mPosition = rr;
	
	if ( mChild[0] )
		mChild[0]->ResizeFrameBy(
				mVertical?mPosition-oldPos:0,
				mVertical?0:mPosition-oldPos,
				redraw);
	if ( mChild[1] ) {
		mChild[1]->ResizeFrameBy(
				mVertical?oldPos-mPosition:0,
				mVertical?0:oldPos-mPosition,
				false);
		mChild[1]->MoveBy(
				mVertical?mPosition-oldPos:0,
				mVertical?0:mPosition-oldPos,
				redraw);
	}

	if ( redraw ) {
		FocusDraw();
		Refresh();
		BroadcastMessage(msg_SplitBarMoved, (void*)mPosition);
	}
}


// ---------------------------------------------------------------------------
//	¥ ShowChild														  [public]
// ---------------------------------------------------------------------------

void
CSplitView::ShowChild(
	UInt8  n)
{
	n = n?1:0;
	mChildHidden[n] = false;
	if ( mChild[n] )
		mChild[n]->Show();
	Refresh();
}


// ---------------------------------------------------------------------------
//	¥ HideChild														  [public]
// ---------------------------------------------------------------------------

void
CSplitView::HideChild(
	UInt8  n)
{
	n = n?1:0;
	mChildHidden[n] = true;
	if ( mChild[n] )
		mChild[n]->Hide();
	Refresh();
}

#pragma mark -

// ---------------------------------------------------------------------------
//	¥ DrawSelf													   [protected]
// ---------------------------------------------------------------------------

void
CSplitView::DrawSelf()
{
	if ( mChildHidden[0] || mChildHidden[1] )
		return;
	
	Rect		frame;
	CalcSplitBarFrame(frame);

	Pattern		pat;
	RGBForeColor(&Color_SplitBarFill);
	::MacFillRect(&frame, UQDGlobals::GetBlackPat(&pat));
	
	RGBForeColor(&Color_SplitBarLine1);
	::MoveTo(frame.left, frame.top);
	if ( mVertical )
		::LineTo(frame.left, frame.bottom);
	else		
		::LineTo(frame.right, frame.top);

	RGBForeColor(&Color_SplitBarLine2);
	::MoveTo(frame.right, frame.bottom);
	if ( mVertical )
		::LineTo(frame.right, frame.top);
	else		
		::LineTo(frame.left, frame.bottom);
	
	UInt16 cx = (frame.left + frame.right )/2;
	UInt16 cy = (frame.top  + frame.bottom)/2;
	RGBForeColor(&Color_SplitBarMark);
	if ( mVertical ) {
		::MoveTo(cx-MarkerPitch, cy-MarkerLen);
		::LineTo(cx-MarkerPitch, cy+MarkerLen);
		::MoveTo(cx+MarkerPitch, cy-MarkerLen);
		::LineTo(cx+MarkerPitch, cy+MarkerLen);
	}
	else {
		::MoveTo(cx-MarkerLen, cy-MarkerPitch);
		::LineTo(cx+MarkerLen, cy-MarkerPitch);
		::MoveTo(cx-MarkerLen, cy+MarkerPitch);
		::LineTo(cx+MarkerLen, cy+MarkerPitch);
	}
}


// ---------------------------------------------------------------------------
//	¥ CalcSplitBarFrame											   [protected]
// ---------------------------------------------------------------------------

void
CSplitView::CalcSplitBarFrame(Rect &frame)
{
	CalcLocalFrameRect(frame);
	if ( mVertical ) {
		frame.left += mPosition;
		frame.right = frame.left + BAR_WIDTH;
	}
	else {
		frame.top += mPosition;
		frame.bottom = frame.top + BAR_WIDTH;
	}
}

PP_End_Namespace_PowerPlant
