// MediaRoutingContainerView.cpp
// e.moon 7may99

#include "MediaRoutingContainerView.h"

#include "MediaRoutingView.h"
#include "GutterColumn.h"
#include "GutterRow.h"
#include "NodeColumn.h"
#include "NodeRow.h"

#include "debug_tools.h"

__USE_CORTEX_NAMESPACE

// -------------------------------------------------------- //
// ctor/dtor/accessors
// -------------------------------------------------------- //

MediaRoutingContainerView::~MediaRoutingContainerView() {}
MediaRoutingContainerView::MediaRoutingContainerView(
	MediaRoutingView* routingView) :
	BView(BRect(0,0,0,0), "mediaRoutingContainer",
		B_FOLLOW_LEFT|B_FOLLOW_TOP,
		B_WILL_DRAW|B_FRAME_EVENTS),
	m_routingView(routingView)/*,
	m_tipManager(0)*/ {

	// lazy and nasty-looking! +++++
	cacheColors();
	SetViewColor(m_nodeSlotColor);		
}

//TipManager* MediaRoutingContainerView::tipManager() const {
//	return const_cast<TipManager*>(m_tipManager);
//}

// -------------------------------------------------------- //
// BView impl.
// -------------------------------------------------------- //

void MediaRoutingContainerView::AttachedToWindow() {
//	m_tipManager = new TipManager(this, 250000);
}

void MediaRoutingContainerView::DetachedFromWindow() {

//	// stop the TipManager thread before the window goes away
//	delete m_tipManager;
//	m_tipManager = 0;
	
	_inherited::DetachedFromWindow();
}

void MediaRoutingContainerView::Draw(BRect updateRect) {
/*
	ASSERT(m_routingView);
	
	// draw backdrop:
	SetHighColor(s_gutterColor);

	// gutter rows
	GutterRow* pGutterRow = m_routingView->gutterRow(
		0, MediaRoutingView::TOP_GUTTER);
	if(!pGutterRow) {
		PRINT((
			"MediaRoutingContainerView::Draw(): couldn't find first gutter row.\n"));
		return;
	}	
	NodeRow* pNodeRow = m_routingView->nodeRow(0);
	if(!pNodeRow) {
		PRINT((
			"MediaRoutingContainerView::Draw(): couldn't find first node row.\n"));
		return;
	}

	BRect gutterRect = Bounds();
	gutterRect.top = pGutterRow->yOffset();
	gutterRect.bottom = gutterRect.top + pGutterRow->height() - 1;	
	float rowHeight = pNodeRow->height() + pGutterRow->height();
	
	FillRect(gutterRect);
	for(uint32 row = 0; row < m_routingView->nodeRows(); row++) {
		gutterRect.OffsetBy(0.0, rowHeight);
		FillRect(gutterRect);
	}

	// gutter columns
	GutterColumn* pGutterColumn = m_routingView->gutterColumn(
		0, MediaRoutingView::LEFT_GUTTER);
	if(!pGutterColumn) {
		PRINT((
			"MediaRoutingContainerView::Draw(): couldn't find first gutter column.\n"));
		return;
	}	
	NodeColumn* pNodeColumn = m_routingView->nodeColumn(0);
	if(!pNodeColumn) {
		PRINT((
			"MediaRoutingContainerView::Draw(): couldn't find first node column.\n"));
		return;
	}

	gutterRect = Bounds();
	gutterRect.left = pGutterColumn->xOffset();
	gutterRect.right = gutterRect.left + pGutterColumn->width() - 1;
	float columnWidth = pNodeColumn->width() + pGutterColumn->width();
	
	FillRect(gutterRect);
	for(uint32 column = 0; column < m_routingView->nodeColumns(); column++) {
		gutterRect.OffsetBy(columnWidth, 0.0);
		FillRect(gutterRect);
	}
*/
}

void MediaRoutingContainerView::FrameResized(float width, float height) {
	_inherited::FrameResized(width, height);
//	PRINT((
//		"* MediaRoutingContainerView::FrameResized(%.1f, %.1f)\n", width, height));
}

// MouseDown helper: simple linear search through the given segment
// list for a segment under the given point

Wire* MediaRoutingContainerView::hitTestSegments(
	const list<WireSegment>& segments,
	BPoint where) {

	for(list<WireSegment>::const_iterator it = segments.begin();
		it != segments.end(); ++it) {
		BRect r = m_routingView->segmentToRect(*it);
		// grow the rectangle a little to make selection easier
		r.InsetBy(-2.0, -2.0);
		
		if(r.Contains(where))
			return (*it).pWire;
	}
	return 0;
}

Wire* MediaRoutingContainerView::findWireAt(BPoint where) {
	// +++++ should react predictably given overlapping segments!

	// hit-test wire segments
	// a) fetch row and column; bail unless both are valid
	int32 gridColumn = m_routingView->columnIndexFor(where.x);
	if(gridColumn >= m_routingView->columns())
		return 0;
	int32 gridRow = m_routingView->rowIndexFor(where.y);
	if(gridRow >= m_routingView->rows())
		return 0;
		
	// hit-test segments in row/column
	RoutingColumn* pColumn = dynamic_cast<RoutingColumn*>(
		m_routingView->columnAt(gridColumn));
	if(!pColumn)
		return 0;
	Wire* pFound = hitTestSegments(pColumn->segments(), where);
	if(pFound) 
		return pFound;

	RoutingRow* pRow = dynamic_cast<RoutingRow*>(
		m_routingView->rowAt(gridRow));
	if(!pRow)
		return 0;
	return hitTestSegments(pRow->segments(), where);
}

void MediaRoutingContainerView::MouseDown(BPoint where) {
	ASSERT(where.x >= 0.0);
	ASSERT(where.y >= 0.0);

	// clear routing view's selection
	m_routingView->deselectAll();

	Wire* pFound = findWireAt(where);
	if(pFound)
		m_routingView->selectWire(pFound);	
}

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

void MediaRoutingContainerView::cacheColors() {
	m_nodeSlotColor = tint_color(
		ui_color(B_PANEL_BACKGROUND_COLOR),
		B_DARKEN_1_TINT);
	m_nodeSlotColor.red = (uint8)(m_nodeSlotColor.red * 0.97);
	
	m_gutterColor = m_nodeSlotColor;
}

// END -- MediaRoutingContainerView.cpp --
