// ChildFrm.cpp : implementation of the CChildFrame class
//

#include "stdafx.h"
#include "ChildFrm.h"


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

/////////////////////////////////////////////////////////////////////////////
// CChildFrame

IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
	//{{AFX_MSG_MAP(CChildFrame)
	ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOM, OnUpdateViewZoom)
	ON_COMMAND(ID_VIEW_ZOOM, OnViewZoom)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MOVE, OnUpdateViewMove)
	ON_COMMAND(ID_VIEW_MOVE, OnViewMove)
	ON_COMMAND(ID_VIEW_SELECT, OnViewSelect)
	ON_UPDATE_COMMAND_UI(ID_VIEW_SELECT, OnUpdateViewSelect)
	ON_COMMAND(ID_ENABLE_BUG, OnEnableBug)
	ON_UPDATE_COMMAND_UI(ID_ENABLE_BUG, OnUpdateEnableBug)
	//}}AFX_MSG_MAP
	
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChildFrame construction/destruction

CChildFrame::CChildFrame()
{
	// TODO: add member initialization code here
	screenBitmap = new CBitmap;
	bitmapSize.cx = 0;
	bitmapSize.cy = 0;


	comboView = NULL;
	timeView = NULL;
	nameView = NULL;
	valueView = NULL;
	logicView = NULL;



	CRect zero(0,0,0,0);
	timeSize = zero;
	nameSize = zero;
	valueSize = zero;
	logicSize = zero;

	traceListArray = NULL;
	traceCount = 0;

	borderSize = BORDER_SIZE;
	boxMinimum = BOX_MINIMUM;

	currentMode = SelectMode;
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

CChildFrame::~CChildFrame()
{
	delete screenBitmap;

	if (traceListArray != NULL)
	{
		TraceLine *delete_me;
		for (int i = 0; i < traceCount; ++i)
		{
			delete_me = (TraceLine*)traceListArray->GetAt(i);
			delete(delete_me);	
		}
		delete traceListArray;
	}

}

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

//	afxDump << "CChildFrame::PreCreateWindow" << endl;

	
	
	// Use the document to set time and make the traces active...


	return CMDIChildWnd::PreCreateWindow(cs);

}

void CChildFrame::SaveSize(void) 
{
	
		timeView->GetClientRect(timeSize);
		nameView->GetClientRect(nameSize);
		valueView->GetClientRect(valueSize);
		logicView->GetClientRect(logicSize);
		
		nameSize += CSize(0, timeSize.Height());
		timeSize += CSize(valueSize.Width() + nameSize.Width(), 0);
		valueSize += CSize(nameSize.Width(), timeSize.Height());
		logicSize += CSize(valueSize.Width() + nameSize.Width(), timeSize.Height());
	
	
}


/////////////////////////////////////////////////////////////////////////////
// CChildFrame diagnostics

#ifdef _DEBUG
void CChildFrame::AssertValid() const
{
	CMDIChildWnd::AssertValid();
}

void CChildFrame::Dump(CDumpContext& dc) const
{
	CMDIChildWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChildFrame message handlers

BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
	// TODO: Add your specialized code here and/or call the base class
	
//	afxDump << "CChildFrame::OnCreateClient" << endl;

	if (!m_wndSplitter.CreateStatic(this, 2, 2))
	{
		TRACE0("Failed to CreateStaticSplitter\n");
		return FALSE;
	}

	// add the first splitter pane - the default view in column 0
	if (!m_wndSplitter.CreateView(0, 0,
		RUNTIME_CLASS(CComboView), CSize(200, 50), pContext))
	{
		TRACE0("Failed to create first pane\n");
		return FALSE;
	}

	comboView = (CComboView*)m_wndSplitter.GetPane(0,0);

	if (!m_wndSplitter.CreateView(0, 1,
		RUNTIME_CLASS(CTimeView), CSize(600, 50), pContext))
	{
		TRACE0("Failed to create first pane\n");
		return FALSE;
	}

	timeView = (CTimeView*)m_wndSplitter.GetPane(0,1);


	if (!m_wndSplitter.CreateView(1, 1,
		RUNTIME_CLASS(CLogicView), CSize(600, 100), pContext))
	{
		TRACE0("Failed to create first pane\n");
		return FALSE;
	}

	logicView = (CLogicView*)m_wndSplitter.GetPane(1,1);

	// add the second splitter pane - which is a nested splitter with 2 rows
	if (!m_wndSplitter2.CreateStatic(
		&m_wndSplitter,     // our parent window is the first splitter
		1, 2,               // the new splitter is 2 rows, 1 column
		WS_CHILD | WS_VISIBLE | WS_BORDER,  // style, WS_BORDER is needed
		m_wndSplitter.IdFromRowCol(1, 0)
			// new splitter is in the first row, 2nd column of first splitter
	   ))
	{
		TRACE0("Failed to create nested splitter\n");
		return FALSE;
	}

	// now create the two views inside the nested splitter
	int cyText = max(lpcs->cy - 70, 20);    // height of text pane

	if (!m_wndSplitter2.CreateView(0, 0,
		RUNTIME_CLASS(CNameView), CSize(100, 100), pContext))
	{
		TRACE0("Failed to create second pane\n");
		return FALSE;
	}

	nameView = (CNameView*)m_wndSplitter2.GetPane(0,0);


	if (!m_wndSplitter2.CreateView(0, 1,
		RUNTIME_CLASS(CValueView), CSize(40, 100), pContext))
	{
		TRACE0("Failed to create third pane\n");
		return FALSE;
	}

	valueView = (CValueView*)m_wndSplitter2.GetPane(0,1);

	nameView->myParent = this;
	timeView->myParent = this;
	valueView->myParent = this;
	comboView->myParent = this;
	logicView->myParent = this;


	// Make a bitmap for the application to use.
	bitmapSize.cx = MAX_WIDTH;
	bitmapSize.cy = MAX_HEIGHT;
		
	//screenBitmap->CreateBitmap(bitmapSize.cx, bitmapSize.cy, 1, 8, NULL);
	CDC *dc  = logicView->GetDC();
	screenBitmap->CreateCompatibleBitmap(dc, bitmapSize.cx, bitmapSize.cy);

	SaveSize();
	Draw();

	// Clear the bitmap

	CRect bitmap_size;
	bitmap_size.left = 0;
	bitmap_size.top = 0;
	bitmap_size.right = MAX_WIDTH;
	bitmap_size.bottom = MAX_HEIGHT;

	MY_RGB color;
	color.red = 255;
	color.blue = 255;
	color.green = 255;

	DrawCRect(bitmap_size, color);

	document = (CLabRatDoc*)pContext->m_pCurrentDoc;

	return TRUE;
}


void
	CChildFrame::OnInitialUpdate(void)	
{
	
	//  This function is called in :
	//  void CComboView::OnInitialUpdate() 
	// CMDIChildWnd has no InitialUpdate. 
if(document->traceCount==0) 
 document->OnOpenDocument( document->GetPathName());

	viewedTime.startTime = document->firstTrace;
	viewedTime.endTime = document->lastTrace;
	Time span = document->lastTrace - document->firstTrace;

	FrameTimeSpan(span, timeSize.Width());
	
	traceListArray = new CObArray;
	traceCount = document->traceCount;
	traceListArray->SetSize(traceCount);

	TraceLine* trace_line;

	for (int i = 0; i < traceCount; ++i)
	{
		
		CObarrayHolder *data_holder = (CObarrayHolder*)document->dataArray->GetAt(i);

		trace_line = TraceStorage::CreateTraceLine(data_holder->traceType);

		trace_line->dataHolder = data_holder;
		trace_line->traceNumber = i;
		trace_line->traceName = trace_line->dataHolder->name;
		trace_line->document = document;
		trace_line->myParent = this;
		trace_line->SetMinMax();
		traceListArray->SetAt(i, trace_line);
		
	}
}



/////////////////////////////////////////////////////////////////////////////
// Time Routines


void
	CChildFrame::FrameTimeSpan(
			Time time_span, 
			int screen_size	
		)
{

	Time temp_time_to_pixel = screen_size / time_span;

	Time time_to_pixel = -1.0f;

	Scalar divisions_on_screen = screen_size / (Scalar)PIXELS_PER_DIVISION; 
	

   Time closest_time_to_pixel = ((PIXELS_PER_DIVISION)/(SCALES[0] * SCALE_STEP[0]));
	closest_time_to_pixel -= temp_time_to_pixel;
	
	viewedTime.secondEnum = SCALES_COUNT-1;
	int stepEnum = SCALE_STEP_COUNT-1;

	
	for ( int i = 0; i < SCALES_COUNT; ++i )
	{
		for ( int j = 0; j < SCALE_STEP_COUNT; ++j)
		{
			Time check = (PIXELS_PER_DIVISION)/(Time)(SCALES[i] * (Time)SCALE_STEP[j]);
			
			check -= temp_time_to_pixel;

			if (Abs(check) < Abs(closest_time_to_pixel))
			{
				closest_time_to_pixel = check;
				viewedTime.secondEnum = i;
				stepEnum = j;
			}
		}
	}	

	//TRACE("secondEnum %d, stepEnum %d\n", secondEnum, stepEnum);

	time_to_pixel = (Time)(PIXELS_PER_DIVISION)/(Time)(SCALES[viewedTime.secondEnum] 
		* (Time)SCALE_STEP[stepEnum]);
	
	viewedTime.step = SCALE_STEP[stepEnum];

	SetComboBox(stepEnum, viewedTime.secondEnum);
	
	viewedTime.timeToPixel = time_to_pixel;
	viewedTime.pixelToTime = 1.0f / viewedTime.timeToPixel;

}


void 
	CChildFrame::SetTime()
{
	viewedTime.timeToPixel = (Time)(PIXELS_PER_DIVISION)/(Time)(SCALES[viewedTime.secondEnum] * (Time)viewedTime.step);
	viewedTime.pixelToTime = 1.0f / viewedTime.timeToPixel;


	
	viewedTime.endTime = 
		viewedTime.startTime + (viewedTime.pixelToTime * timeSize.Width());
	Max_Clamp(viewedTime.endTime, document->lastTrace);

}

void 
	CChildFrame::SetComboBox(int step_enum, int second_enum)
{

	CComboBox* pList = (CComboBox*)comboView->GetDlgItem(IDC_NUMBER_COMBO);
	pList->SetCurSel(step_enum);

	pList = (CComboBox*)comboView->GetDlgItem(IDC_SECOND_COMBO);
	pList->SetCurSel(second_enum);
}

/////////////////////////////////////////////////////////////////////////////
// Drawing Routines


void CChildFrame::Draw(CWnd *window_pointer)
{

	CRect size;
	
		
	if (window_pointer == nameView)
	{
			nameView->Render(nameSize);
			nameView->GetClientRect(size);
			nameView->InvalidateRect(size);
	}
	else if (window_pointer == timeView)
	{
			timeView->Render(timeSize);
			timeView->GetClientRect(size);
			timeView->InvalidateRect(size);
	}
	else if (window_pointer == valueView)
	{
			valueView->Render(valueSize);
			valueView->GetClientRect(size);
			valueView->InvalidateRect(size);
	}
	else if (window_pointer == logicView)
	{
			logicView->Render(logicSize);
		
	}
	else
	{
		nameView->Render(nameSize);
		timeView->Render(timeSize);
		valueView->Render(valueSize);
		logicView->Render(logicSize);
		

		nameView->GetClientRect(size);
		nameView->InvalidateRect(size);

		timeView->GetClientRect(size);
		timeView->InvalidateRect(size);
		
		valueView->GetClientRect(size);
		valueView->InvalidateRect(size);

	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawCRect(CRect rectangle, MY_RGB color)
{

	CBrush brush;  
	CPen pen;
	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);
		
	if( brush.CreateSolidBrush(RGB(color.red,color.green,color.blue) ) )
	{
		if( pen.CreatePen( PS_SOLID, 1, RGB(color.red,color.green,color.blue) ) )
		{
		
			CPen* pOldPen = display_memory.SelectObject( &pen );
			CBrush* pOldBrush = display_memory.SelectObject( &brush );
		
			display_memory.Rectangle(rectangle);
			
			display_memory.SelectObject( pOldBrush );
			display_memory.SelectObject( pOldPen );
		}
	}

	display_memory.SelectObject(old_bitmap);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawLine(
		CPoint from_point,
		CPoint to_point,
		MY_RGB  color,
		int  thickness
	)
{


	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);

	CPen pen;  // Construct it, then initialize
	if( pen.CreatePen( PS_SOLID, thickness, RGB(color.red,color.green,color.blue) ) )
	{
		
		CPen* pOldPen = display_memory.SelectObject( &pen );
	
		
		display_memory.MoveTo(from_point);
		display_memory.LineTo(to_point);

		display_memory.SelectObject( pOldPen );
	}

	display_memory.SelectObject(old_bitmap);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawLine(
		Time from_time,
		Time to_time,
		int  from_value,
		int  to_value,
		int  offset,
		MY_RGB  color,
		int  thickness
	)
{
	//afxDump << "CLabRatTimeView::DrawLine" << endl;


	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);

	CPen pen;  // Construct it, then initialize
	if( pen.CreatePen( PS_SOLID, thickness, RGB(color.red,color.green,color.blue) ) )
	{
		
		CPen* pOldPen = display_memory.SelectObject( &pen );
	
		int 
			from_time_pixel,
			to_time_pixel;

		Time zero_from_time = (from_time - viewedTime.startTime);
		Time zero_to_time = (to_time - viewedTime.startTime);

		from_time_pixel = (int)((zero_from_time * viewedTime.timeToPixel));
		to_time_pixel   = (int)((zero_to_time * viewedTime.timeToPixel));


		from_value += offset;
		to_value += offset;

		
			
		display_memory.MoveTo(from_time_pixel, from_value);
		display_memory.LineTo(to_time_pixel, to_value);

		
		display_memory.SelectObject( pOldPen );
	}

	display_memory.SelectObject(old_bitmap);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawBox(
		Time from_time,
		Time to_time,
		int  to_value,
		int  from_value,
		int  offset,
		MY_RGB  color
	)
{


	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);

	CBrush brush;  // Construct it, then initialize
	//if( brush.CreateHatchBrush( HS_DIAGCROSS, RGB(color.red,color.green,color.blue) ) )
	CPen pen;

	if( brush.CreateSolidBrush(RGB(color.red,color.green,color.blue) ) )
	{
		if( pen.CreatePen( PS_SOLID, 1, RGB(color.red,color.green,color.blue) ) )
		{
		
			CPen* pOldPen = display_memory.SelectObject( &pen );
			CBrush* pOldBrush = display_memory.SelectObject( &brush );
		
			int 
				from_time_pixel,
				to_time_pixel;

			Time zero_from_time = (from_time - viewedTime.startTime);
			Time zero_to_time = (to_time - viewedTime.startTime);

			from_time_pixel = (int)((zero_from_time * viewedTime.timeToPixel));
			to_time_pixel   = (int)((zero_to_time * viewedTime.timeToPixel));

			from_value += offset;
			to_value += offset;

			CRect rectangle;
			
			rectangle.top = from_value;
			rectangle.bottom = to_value;
			rectangle.left = from_time_pixel;
			rectangle.right = to_time_pixel;

			rectangle.NormalizeRect();

			display_memory.Rectangle(rectangle);
			
			display_memory.SelectObject( pOldBrush );
			display_memory.SelectObject( pOldPen );
		}
	}
	display_memory.SelectObject(old_bitmap);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawText(
		CString text,
		Time time,
		int  height,
		MY_RGB  color
	)
{
	//afxDump << "CLabRatTimeView::DrawLine" << endl;


	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);
	display_memory.SetBkMode(TRANSPARENT);
	
	int 
		time_pixel;
		

	Time zero_time = (time - viewedTime.startTime);
	time_pixel = (int)((zero_time * viewedTime.timeToPixel));
	
	COLORREF old_color = display_memory.GetTextColor();
	UINT old_text_set = display_memory.SetTextAlign(TA_BOTTOM|TA_CENTER);
	
	display_memory.SetTextColor(RGB(color.red, color.blue, color.green));
	display_memory.TextOut(time_pixel, height, text);
	
	display_memory.SetTextColor(old_color);
	display_memory.SetTextAlign(old_text_set);

	display_memory.SelectObject(old_bitmap);
		
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawTextLeft(
		CString text,
		Time time,
		int  height,
		MY_RGB  color
	)
{
	//afxDump << "CLabRatTimeView::DrawLine" << endl;


	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);
	display_memory.SetBkMode(TRANSPARENT);
	int 
		time_pixel;
		

	Time zero_time = (time - viewedTime.startTime);
	time_pixel = (int)((zero_time * viewedTime.timeToPixel));
	
	COLORREF old_color = display_memory.GetTextColor();
	UINT old_text_set = display_memory.SetTextAlign(TA_BOTTOM|TA_LEFT);
	
	display_memory.SetTextColor(RGB(color.red, color.blue, color.green));
	display_memory.TextOut(time_pixel, height, text);
	
	display_memory.SetTextColor(old_color);
	display_memory.SetTextAlign(old_text_set);

	display_memory.SelectObject(old_bitmap);
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void CChildFrame::DrawText(
		CString text,
		int  x,
		int  height,
		MY_RGB  color
	)
{
	//afxDump << "CLabRatTimeView::DrawLine" << endl;
	CClientDC client_dc(this);
	CDC display_memory;

	display_memory.CreateCompatibleDC(&client_dc);
	CBitmap *old_bitmap = display_memory.SelectObject(screenBitmap);		

	display_memory.SetBkMode(TRANSPARENT);

	COLORREF old_color = display_memory.GetTextColor();
	UINT old_text_set = display_memory.SetTextAlign(TA_BOTTOM|TA_LEFT);
	
	display_memory.SetTextColor(RGB(color.red, color.blue, color.green));
	display_memory.TextOut(x, height, text);
	
	display_memory.SetTextColor(old_color);
	display_memory.SetTextAlign(old_text_set);

	display_memory.SelectObject(old_bitmap);
	
}


void CChildFrame::OnViewZoom() 
{
	currentMode = ZoomMode;	
	logicView->subMode = CLogicView::ZoomIn;
}
void CChildFrame::OnViewMove() 
{
	currentMode = MoveMode;	
	logicView->subMode = CLogicView::Move;
}
void CChildFrame::OnViewSelect() 
{
	currentMode = SelectMode;	
	logicView->subMode = CLogicView::Select;
}

void CChildFrame::OnUpdateViewZoom(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(TRUE);
	if (currentMode == ZoomMode)
	{
		pCmdUI->SetCheck(True);	
	}
	else
	{
		pCmdUI->SetCheck(False);	
	}
	
}
void CChildFrame::OnUpdateViewMove(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(TRUE);
	if (currentMode == MoveMode)
	{
		pCmdUI->SetCheck(True);	
	}
	else
	{
		pCmdUI->SetCheck(False);	
	}
}
void CChildFrame::OnUpdateViewSelect(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(TRUE);
	if (currentMode == SelectMode)
	{
		pCmdUI->SetCheck(True);	
	}
	else
	{
		pCmdUI->SetCheck(False);	
	}
}

void CChildFrame::OnEnableBug() 
{
	if (logicView->bugEnabled)
	{
		logicView->bugEnabled = False;
		logicView->ShowScrollBar(SB_BOTH, True);
	}
	else
	{
		logicView->bugEnabled = True;
		logicView->ShowScrollBar(SB_BOTH, False);
	}
	
}

void CChildFrame::OnUpdateEnableBug(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(logicView->bugEnabled);	
}



