// NameView.cpp : implementation file
//

#include "stdafx.h"
#include "NameView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CNameView

IMPLEMENT_DYNCREATE(CNameView, CView)

CNameView::CNameView()
{
	displayMemory = new CDC;
	windowActive = False;

	ctrlPressed = False;
	shiftPressed = False;
	mouseMoveMode = NotActive;

	firstSelect = 0;
	insertAt = -1;

	sizeCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENS);
	arrowCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
	
}

CNameView::~CNameView()
{
	delete displayMemory;
}


BEGIN_MESSAGE_MAP(CNameView, CView)
	//{{AFX_MSG_MAP(CNameView)
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_SETCURSOR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNameView drawing

void CNameView::OnDraw(CDC* pDC)
{
	CRect client_rect;
	GetClientRect(client_rect);
	CBitmap *old_bitmap;
	old_bitmap = displayMemory->SelectObject(myParent->screenBitmap);

	
	pDC->BitBlt(0,0,client_rect.right,client_rect.bottom, displayMemory, 
		myParent->nameSize.left, myParent->nameSize.top, SRCCOPY);

	displayMemory->SelectObject(old_bitmap);
}

/////////////////////////////////////////////////////////////////////////////
// CNameView diagnostics

#ifdef _DEBUG
void CNameView::AssertValid() const
{
	CView::AssertValid();
}

void CNameView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CNameView message handlers

void CNameView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	windowActive = True;

	CClientDC client_dc(this);

	if(displayMemory->GetSafeHdc() == NULL)
	{
		displayMemory->CreateCompatibleDC(&client_dc);
	}




	myParent->SaveSize();
	myParent->Draw(this);
}

/////////////////////////////////////////////////////////////////////////////


void CNameView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here

	if (windowActive)
	{
		myParent->SaveSize();
		myParent->Draw(this);
	}

}

/////////////////////////////////////////////////////////////////////////////

void CNameView::Render(CRect placement)
{
	MY_RGB color;
	color.red = 255;
	color.blue = 255;
	color.green = 255;
	myParent->DrawCRect( placement,color);


	int place_to_draw = myParent->borderSize + myParent->nameSize.top;


	//Get starting trace as defined by the vert scroll bar in Logic View
	int start = myParent->logicView->GetScrollPos(SB_VERT);

	for (int i = start; i < myParent->traceCount; ++i)
	{
		//TRACE("%d\n", place_to_draw);

		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		trace_line->DrawName(place_to_draw);
		
		place_to_draw += trace_line->CalculateSize();
		place_to_draw += myParent->borderSize;
	}
}

/////////////////////////////////////////////////////////////////////////////


void CNameView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	
	CView::OnLButtonDown(nFlags, point);
	

	if (shiftPressed && ctrlPressed)
	{
		// invalid in this case
	}
	else if (shiftPressed)
	{
		// range select
		Logical resize;
		int selection = FindSelection(point, resize);

		if (selection != -1)
		{
			RangeSelect(selection);
			myParent->Draw(this);
			//myParent->Draw(myParent->logicView);
		}
	}
	else if (ctrlPressed)
	{	
		// multi select
		Logical resize;
		int selection = FindSelection(point, resize);

		if (selection != -1)
		{
			MultiSelect(selection);
			myParent->Draw(this);
			//myParent->Draw(myParent->logicView);
		}
	}
	else
	{
		// either select or move or resize;

		Logical resize;
		int selection = FindSelection(point, resize);

		if (selection != -1)
		{

			//SetCapture();

			if (resize)
			{
				myParent->Draw(this);
				myParent->Draw(myParent->logicView);
				SetCursor(sizeCursor);
				mouseMoveMode = ResizeTrace;
				resizeSelect = selection;

			}
			else
			{
				SingleSelect(selection);
				myParent->Draw(this);
				myParent->Draw(myParent->valueView);
				//myParent->Draw(myParent->logicView);
				
				mouseMoveMode = MoveTrace;
				insertAt = -1;
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////


void CNameView::SingleSelect(int selection)
{
	for (int i = 0; i < myParent->traceCount; ++i)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		if (i == selection)
		{
			if (trace_line->selected == True)
			{
				trace_line->selected = False;
			}
			else
			{
					trace_line->selected = True;
					firstSelect = i;
			}
		}
		else
		{
			trace_line->selected = False;
		}
	}
}

/////////////////////////////////////////////////////////////////////////////


void CNameView::MultiSelect(int selection)
{
	for (int i = 0; i < myParent->traceCount; ++i)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		if (i == selection)
		{
			if (trace_line->selected == True)
			{
				trace_line->selected = False;
			}
			else
			{
				
					trace_line->selected = True;
				
			}
			break;
		}
	}
}

/////////////////////////////////////////////////////////////////////////////


void CNameView::RangeSelect(int selection)
{
	int min, max;


	for (int i = 0; i < myParent->traceCount; ++i)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		
		trace_line->selected = False;

	}


	if (selection < firstSelect)
	{
		min = selection;
		max = firstSelect;
	}
	else
	{
		max = selection;
		min = firstSelect;
	}

	for (; min <= max; ++min)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(min);
		
		
			trace_line->selected = True;
		
	}
}

/////////////////////////////////////////////////////////////////////////////


int CNameView::FindSelection(CPoint point, Logical &resize)
{


	resize = False;

	int trace_hit = -1;

	int top = myParent->borderSize;
	int start = myParent->logicView->GetScrollPos(SB_VERT);

	for (int i = start; i < myParent->traceCount; ++i)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		int bottom = top + trace_line->CalculateSize();
		
		if (point.y < bottom && point.y > top)
		{
			trace_hit = i;
		}
		
		if ((point.y < bottom + 2) && (point.y > bottom - 2))
		{
			trace_hit = i;
			resize = True;
		}


		top = bottom;
		top += myParent->borderSize;
	}

	//afxDump << trace_hit << endl;
	return trace_hit;

}

/////////////////////////////////////////////////////////////////////////////


void CNameView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	
	CView::OnLButtonUp(nFlags, point);
	mouseMoveMode = NotActive;

	//ReleaseCapture();


}

/////////////////////////////////////////////////////////////////////////////

void CNameView::OnMouseMove(UINT nFlags, CPoint point) 
{
	
	CView::OnMouseMove(nFlags, point);


	SetFocus();

	if (mouseMoveMode == ResizeTrace)
	{
		Resize(point);	
		myParent->Draw(this);
		myParent->Draw(myParent->logicView);
		SetCursor(sizeCursor);
	}
	else if (mouseMoveMode == MoveTrace)
	{
		Move(point);
		myParent->Draw(this);
		myParent->Draw(myParent->logicView);
	}
	else
	{

		Logical resize = False;
		FindSelection(point, resize);
		if (resize)
		{
			SetCursor(sizeCursor);
		}
		else
		{
			SetCursor(arrowCursor);
		}
	}

}

/////////////////////////////////////////////////////////////////////////////

void CNameView::Resize(CPoint point) 
{
		
	int top = myParent->borderSize;
	int start = myParent->logicView->GetScrollPos(SB_VERT);

	for (int i = start; i < myParent->traceCount; ++i)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		int bottom = top + trace_line->CalculateSize();
			
		if (i == resizeSelect)
		{
			if (point.y > top + MIN_TRACE_SIZE)
			{
				trace_line->traceHeight = point.y - top;
				trace_line->AdjustHeight();
			}
			else
			{
				trace_line->traceHeight = MIN_TRACE_SIZE;
				trace_line->AdjustHeight();
			}
			break;
		}

		top = bottom;
		top += myParent->borderSize;
	}
}

/////////////////////////////////////////////////////////////////////////////


void CNameView::Move(CPoint point) 
{
		

	int top = myParent->borderSize;
	int start = myParent->logicView->GetScrollPos(SB_VERT);

	for (int i = start; i < myParent->traceCount; ++i)
	{
		
		TraceLine *trace_line;
		trace_line = (TraceLine *)myParent->traceListArray->GetAt(i);
		
		int bottom = top + trace_line->CalculateSize();
		
		if (point.y < bottom && point.y > top)
		{
			if (i != firstSelect)
			{
				// i is where it should go, first select is where it's at.
				
				TraceLine *insert_me;
				insert_me = (TraceLine *)myParent->traceListArray->GetAt(firstSelect);
			
				myParent->traceListArray->RemoveAt(firstSelect);
				myParent->traceListArray->InsertAt(i, insert_me);
				firstSelect = i;
				break;
			}
		}

		top = bottom;
		top += myParent->borderSize;
	}

}

/////////////////////////////////////////////////////////////////////////////


void CNameView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{

	CView::OnKeyDown(nChar, nRepCnt, nFlags);

	switch(nChar)
	{
	case VK_SHIFT:	
		shiftPressed = True;
		break;
	case VK_CONTROL :
		ctrlPressed = True;
		break;
	}

}

/////////////////////////////////////////////////////////////////////////////

void CNameView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{	
	CView::OnKeyUp(nChar, nRepCnt, nFlags);
	switch(nChar)
	{
	case VK_SHIFT:	
		shiftPressed = False;
		break;
	case VK_CONTROL :	
		ctrlPressed = False;
		break;
	}
}

void CNameView::OnLButtonDblClk(UINT /*nFlags*/, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	

	Logical resize;

	int selection = FindSelection(point, resize);

	if (selection != -1)
	{
		TraceLine *trace;
		trace = (TraceLine *)myParent->traceListArray->GetAt(selection);
			
		if (trace->on)
		{
			trace->on = False;
		}
		else
		{
			trace->on = True;
		}

		myParent->Draw(this);
		myParent->Draw(myParent->logicView);
	}
}

BOOL CNameView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}

	

BOOL CNameView::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
{
	// TODO: Add your message handler code here and/or call default
	
	//return CView::OnSetCursor(pWnd, nHitTest, message);
	return True;
}
