// LiveNodeView.h
// e.moon 6may99
//
// HISTORY
//   e.moon		11aug99		beginning NodeManager integration
//   e.moon		6may99		begun

#ifndef __LIVENODEVIEW_H__
#define __LIVENODEVIEW_H__

#include <vector>
#include <stdexcept>

//#include <MediaDefs.h>
//#include <MediaNode.h>

#include <View.h>
#include <Font.h>
#include <String.h>
#include <PopUpMenu.h>
#include <Messenger.h>

#include "MouseTrackingHelpers.h"

#include "WireVertex.h"

#include "cortex_defs.h"
__BEGIN_CORTEX_NAMESPACE

class TipManager;
class MediaRoutingView;

class NodeRef;

class LiveNodeView :
	public		MouseTrackingSourceView {
	typedef		MouseTrackingSourceView _inherited;

public:													// The NodeManager entry for this node
	NodeRef* const								ref;

public:					// ctor/dtor/accessors
	virtual ~LiveNodeView();
	
	// throws a runtime_error if it can't acquire the media_node
	// (or if it runs into an error enumerating inputs/outputs)
	LiveNodeView(
		MediaRoutingView*						routingView,
		NodeRef*										_ref);

// 11aug99: these functions are subsumed by NodeRef
//	const media_node& node() const { return m_node; }
//	const live_node_info& nodeInfo() const { return m_nodeInfo; }
	
	const vector<media_input>& freeInputs() const { return m_freeInputs; }
	const vector<media_input>& connectedInputs() const { return m_connectedInputs; }
	const vector<media_output>& freeOutputs() const { return m_freeOutputs; }
	const vector<media_output>& connectedOutputs() const { return m_connectedOutputs; }
	
public:					// hooks
	// extend to add items to the pop-up menu
	virtual void populateMenu();

	// draw the cell onto the given view
	virtual void drawCell(
		BView*											v,
		BRect												updateRect,
		bool												bDrawBackground=true);

public:					// routing-grid operations

	// fetches the bounding rectangle of the indicated connection's
	// icon; returns B_OK on success, or B_BAD_INDEX if the connection
	// doesn't exist
	virtual status_t getJackFrame(
		WireVertex::x_offset_t			jackType,
		uint16											index,
		BRect&											oFrame);

	// change font
	void setFont(
		const BFont&								font);
	
	// notify view that input/output connections may have changed
	// +++++ 11aug99: this notification should come from the NodeRef, via
	//                M_INPUTS_CHANGED & M_OUTPUTS_CHANGED

	void updateInputs();
	void updateOutputs();
	
	// [e.moon 29sep99]
	// notify view that the displayed name may have been changed
	// (nodes can't be renamed, but the cell may display the name of
	//  a file being played, for example.)
	void updateName();
	
	// cell selection
	bool isSelected() const { return m_bSelected; }
	void select() {
		if(m_bSelected)
			return;
		m_bSelected = true;
		Invalidate();
	}
	void deselect() {
		if(!m_bSelected)
			return;
		m_bSelected = false;
		Invalidate();
	}
	
	// required-size calculation
	// - figure the number of grid rows needed to display the cell
	//   frame & all connection points
	// - the value returned must be odd (the cell can't butt against a grid row)
	virtual uint32 gridRowsNeeded() const;

	// return WireVertex if the given point lies over a
	// viable connection jack.
	bool matchJackVertex(
		BPoint 											point,
		WireVertex&									outVertex);

	// get type of current drag operation
	enum drag_op_t {
		// no drag operation
		DRAG_NONE,
		// cell relocation
		DRAG_CELL,
		// wire connection
		DRAG_WIRE
	};
	drag_op_t dragOp() const { return m_dragOp; }
	
	// note: the nodeColumn & nodeRow members will always be 0,
	//       since the cell doesn't know its location
	WireVertex dragVertex() const { return m_dragVertex; }
	
	// returns media_input corresponding to the given vertex, or
	// bool if none exists
	bool findMediaInput(
		const WireVertex&						vertex,
		media_input&								outInput,
		bool&												isConnected);

	// returns media_output corresponding to the given vertex, or
	// bool if none exists
	bool findMediaOutput(
		const WireVertex&						vertex,
		media_output&								outOutput,
		bool&												isConnected);

public:					// BView impl.
	virtual void AttachedToWindow();
	virtual void DetachedFromWindow();
	
	// draw the cell
	virtual void Draw(
		BRect												updateRect);
	
	// handle mouse events
	virtual void MouseDown(
		BPoint											point);
	virtual void MouseMoved(
		BPoint											point,
		uint32											transit,
		const BMessage*							msg);
	virtual void MouseUp(
		BPoint											point);

	// +++++ is this a proper use of GetPreferredSize()? it'll never
	//       get called otherwise, but ick.
	//
	// when connection info for the node changes, the routing
	// grid will first ask the node to scan its inputs and/or
	// outputs, then call GetPreferredSize() to determine whether
	// the node will be taking up more (or fewer) grid slots.
	// width is ignored; it's okay to return 0.

	virtual void GetPreferredSize(
		float*											poWidth,
		float*											poHeight);
		
public:						// BHandler impl
	virtual void MessageReceived(
		BMessage*										msg);
	
protected:				// internal operations

	// populate the input & output sets
	void _scanInputs();
	void _scanOutputs();
	
	// handle a double-click appropriately
	virtual void _handleDoubleClick();

protected:				// node state data

	// the routing view
	MediaRoutingView*				m_routingView;

//  managed by NodeRef
//
//	// the node & extended info
//	media_node					m_node;
//	live_node_info			m_nodeInfo;
//	

	// input/output lists
	vector<media_input>		m_freeInputs;
	vector<media_input>		m_connectedInputs;
	vector<media_output>	m_freeOutputs;
	vector<media_output>	m_connectedOutputs;
	
	// the node's control panel +++++ not implemented
	BMessenger							m_controlPanel;

private:									// selection state
	bool										m_bSelected;

private:									// drag state
	drag_op_t								m_dragOp;
	WireVertex							m_dragVertex;
	
protected:								// context (node-command) menu
	BPopUpMenu*							m_pMenu;

protected:								// presentation methods
	// figure colors
	virtual void _prepareColors();
	
	// fetch node name (shortening as necessary to fit)
	void _prepareName();

	// figure bounds of the actual cell view (leaving room
	// for connection icons on either side)
	BRect _cellBounds(
		const BRect&								b) const;
	
	// figure jack positioning info
	void _getJackPositions(
		BRect&											outLeftTopJack,
		BRect&											outRightTopJack,
		BPoint&											outJackOffset);
	
	// add pop-up tips for all the input/output jacks
	void _updateTips(
		TipManager*									tipManager);

protected:				// presentation stuff

	// the node name, shortened to fit the cell bounds
	BString				m_displayName;

	// background (parent view) color
	rgb_color			m_backColor;
	
	// view (object background) color
	rgb_color			m_cellColor;
	// "  "  lightened
	rgb_color			m_cellColorL1, m_cellColorL2;
	// "  "  darkened
	rgb_color			m_cellColorD1, m_cellColorD2;
	
	// text & general scribbling color
	rgb_color			m_textColor;

	// base font
	BFont					m_font;
	font_height		m_fh;
	
	// jack colors
	rgb_color			m_freeJackColor;
	
	// tip rectangle for name (only used if the node name doesn't
	// fit in the cell view)
	BRect					m_nameTipRect;
	
	// last click time (for double-click support)
	bigtime_t			m_lastClickTime;
	
protected:				// constants
// moved to LayoutDefs 21may99
//	static const float		s_jackWidth = 8;
//	static const float		s_jackHeight = 8;
//	
//	static const float		s_jackPadX = 2;
//	static const float		s_jackPadY = 2;
//	
//	static const BPoint		s_jackTipOffset;
};

__END_CORTEX_NAMESPACE
#endif /* __LIVENODEVIEW_H__ */
