// DiagramEngView.cpp : implementation of the CDiagramEngView class
//

#include "stdafx.h"
#include "DiagramEng.h"
#include "DiagramEngDoc.h"
#include "DiagramEngView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CDiagramEngView

//IMPLEMENT_DYNCREATE(CDiagramEngView, CView)
IMPLEMENT_DYNCREATE(CDiagramEngView, CScrollView)		// DiagramEng: CView changed to CScrollView

//BEGIN_MESSAGE_MAP(CDiagramEngView, CView)
BEGIN_MESSAGE_MAP(CDiagramEngView, CScrollView)			// DiagramEng: CView changed to CScrollView
	//{{AFX_MSG_MAP(CDiagramEngView)
	ON_COMMAND(ID_VIEW_ZOOM_IN, OnViewZoomIn)
	ON_COMMAND(ID_VIEW_ZOOM_OUT, OnViewZoomOut)
	ON_COMMAND(ID_VIEW_AUTO_FIT_DIAGRAM, OnViewAutoFitDiagram)
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_CONTEXTMENU()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_KEYDOWN()
	ON_UPDATE_COMMAND_UI(ID_VIEW_AUTO_FIT_DIAGRAM, OnUpdateViewAutoFitDiagram)
	ON_COMMAND(ID_VIEW_RESET_DIAGRAM, OnViewResetDiagram)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
	ON_UPDATE_COMMAND_UI(ID_FORMAT_SHOW_ANNOTATIONS, OnUpdateFormatShowAnnotations)
	//}}AFX_MSG_MAP
	// Standard printing commands
	//ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)					// DiagramEng: CView changed to CScrollView
	//ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)			// DiagramEng: CView changed to CScrollView
	//ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)	// DiagramEng: CView changed to CScrollView
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDiagramEngView construction/destruction

CDiagramEngView::CDiagramEngView()
{
	// TODO: add construction code here

	// DiagramEng (start)
	m_iAutoFitFlag = 0;
	// DiagramEng (end)
}

CDiagramEngView::~CDiagramEngView()
{
}

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

	//return CView::PreCreateWindow(cs);
	return CScrollView::PreCreateWindow(cs);	// DiagramEng: CView changed to CScrollView
}

/////////////////////////////////////////////////////////////////////////////
// CDiagramEngView drawing

void CDiagramEngView::OnDraw(CDC* pDC)
{
	CDiagramEngDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	// DiagramEng (start)

	// IF PRINTING THEN SCALE THE DIAGRAM
	if(pDC->IsPrinting())
	{
		int iLogPixelsXPrinter;		// number of dots per logical inch of the printer device
		int iLogPixelsXScreen;		// number of pixels per logical inch of the screen device
		int iWndRect_x1 = 0;		// x1 coord of window rectangle
		int iWndRect_y1 = 0;		// y1 coord of window rectangle
		int iWndRect_x2 = 1000;		// x2 coord of window rectangle
		int iWndRect_y2 = 1000;		// y2 coord of window rectangle
		int iVptRectExt_x;			// x extent of viewport
		int iVptRectExt_y;			// y extent of viewport
		double scale = 1.0;			// scale of the transformation bw. the screen and printer (default: 1.0)

		// Set mapping mode (set in OnPrepareDC())
		//pDC->SetMapMode(MM_ISOTROPIC);

		// Scale
		iLogPixelsXPrinter = pDC->GetDeviceCaps(LOGPIXELSX);				// no. of dots per logical inch of printer device
		iLogPixelsXScreen = 96;												// default no. of pixels per logical inch of the screen device
		scale = double(iLogPixelsXPrinter)/double(iLogPixelsXScreen);		// scale ratio

		// Window Rectangle
		CRect WndRect(iWndRect_x1, iWndRect_y1, iWndRect_x2, iWndRect_y2);	// (x1, y1, x2, y2)
		pDC->SetWindowExt(WndRect.Size());									// set extent of Window rect
		pDC->SetWindowOrg(WndRect.TopLeft());								// set origin of Window rect

		// Viewport Rectangle
		CRect client;														// client rect
		GetClientRect(&client);												// get client rect
		iVptRectExt_x = int(scale*(iWndRect_x2 - iWndRect_x1));				// x extent of viewport
		iVptRectExt_y = int(scale*(iWndRect_y2 - iWndRect_y1));				// y extent of viewport
		pDC->SetViewportExt(iVptRectExt_x, iVptRectExt_y);					// set extent of viewport
		//pDC->SetViewportOrg(client.TopLeft());							// viewport origin set in OnPrepareDC()
	}

	// DRAW SYSTEM MODEL
	pDoc->GetSystemModel().DrawSystemModel(pDC);

	// DiagramEng (end)
}

/////////////////////////////////////////////////////////////////////////////
// CDiagramEngView printing

BOOL CDiagramEngView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CDiagramEngView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
	// TODO: add extra initialization before printing

	// DiagramEng (start)
	int numPages;		// no. of pages
	int pageHeight;		// page height of printer device (mm)
	int pageWidth;		// page width of printer device (mm)
	double max_x;		// extreme x posn (mm)
	double max_y;		// extreme y posn (mm)
	CPoint ptMax;		// pseudo extreme point on diagram (extreme coords may be from diff. elements)
	CDiagramEngDoc *pDoc = GetDocument();
	
	// Get page width and height
	pageHeight = pDC->GetDeviceCaps(VERTSIZE);	// height of page in mm
	pageWidth =  pDC->GetDeviceCaps(HORZSIZE);	// width of page in mm

	// Get extreme coords from digram entities and convert to mm. (96 pixels = 1 inch = 25.4 mm)
	ptMax = pDoc->GetSystemModel().DetermineDiagramCoordinateExtrema();
	max_x = 25.4*double(ptMax.x)/96.0;			
	max_y = 25.4*double(ptMax.y)/96.0;			
	
	// Calculate no. of pages
	m_iNpagesWide = int(max_x/pageWidth) + 1;
	m_iNpagesHigh = int(max_y/pageHeight) + 1;
	numPages = m_iNpagesWide*m_iNpagesHigh;

	//CString str;
	//str.Format("\n OnBeginPrinting(), pageWidth = %d, pageHeight = %d, m_iNpagesWide = %d, m_iNpagesHigh = %d, numPages = %d\n", pageWidth, pageHeight, m_iNpagesWide, m_iNpagesHigh, numPages);
	//AfxMessageBox(str, MB_OK, 0);

	// Set max page
	pInfo->SetMaxPage(numPages);
	// DiagramEng (end)
}

void CDiagramEngView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CDiagramEngView diagnostics

#ifdef _DEBUG
void CDiagramEngView::AssertValid() const
{
	//CView::AssertValid();
	CScrollView::AssertValid();		// DiagramEng: CView changed to CScrollView
}

void CDiagramEngView::Dump(CDumpContext& dc) const
{
	//CView::Dump(dc);
	CScrollView::Dump(dc);			// DiagramEng: CView changed to CScrollView
}

CDiagramEngDoc* CDiagramEngView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDiagramEngDoc)));
	return (CDiagramEngDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDiagramEngView message handlers

void CDiagramEngView::OnViewZoomIn() 
{
	// TODO: Add your command handler code here
	
	// DiagramEng (start)
	double length;				// used to scale m_dDeltaLength
	double scale_factor = 1.1;	// scale factor: inverse of that used in OnViewZoomOut()

	//AfxMessageBox("\n CDiagramEngView::OnViewZoomIn()\n", MB_OK, 0);

	// Scale m_dDeltaLength of CDiagramEngDoc
	length = GetDocument()->GetDeltaLength();
	length = length*scale_factor;
	GetDocument()->SetDeltaLength(length);

	// Scale the current diagram
	GetDocument()->GetSystemModel().ScaleSystemModel(scale_factor);
	
	// Invalidate the client area to force a redraw on the next WM_PAINT message.
	GetDocument()->UpdateAllViews(NULL);		// indicate that sys. should redraw.
	GetDocument()->SetModifiedFlag(TRUE);		// mark the document as having been modified 

	// DiagramEng (end)
}

void CDiagramEngView::OnViewZoomOut() 
{
	// TODO: Add your command handler code here
	
	// DiagramEng (start)
	double length;					// used to scale m_dDeltaLength
	double scale_factor = 1/1.1;	// scale factor: inverse of that used in OnViewZoomIn()

	//AfxMessageBox("\n CDiagramEngView::OnViewZoomOut()\n", MB_OK, 0);

	// Scale m_dDeltaLength of CDiagramEngDoc
	length = GetDocument()->GetDeltaLength();
	length = length*scale_factor;
	GetDocument()->SetDeltaLength(length);

	// Scale the current diagram
	GetDocument()->GetSystemModel().ScaleSystemModel(scale_factor);

	// Invalidate the client area to force a redraw on the next WM_PAINT message.
	GetDocument()->UpdateAllViews(NULL);		// indicate that sys. should redraw.
	GetDocument()->SetModifiedFlag(TRUE);		// mark the document as having been modified

	// DiagramEng (end)
}

void CDiagramEngView::OnViewAutoFitDiagram() 
{
	// TODO: Add your command handler code here
	
	// DiagramEng (start)
	//AfxMessageBox("\n CDiagramEngView::OnViewAutoFitDiagram()\n", MB_OK, 0);

	// CScrollView-related change
	int buffer = 20;							// 20 pixel point fixed buffer size
	CPoint ptExtreme = GetDocument()->GetSystemModel().DetermineDiagramCoordinateExtrema();	// get extreme coords
	SIZE szExtreme;								// extreme size

	// Assign scale size using extreme point
	szExtreme.cx = ptExtreme.x + buffer;		// extreme horizontal size
	szExtreme.cy = ptExtreme.y + buffer;		// extreme vertical size

	// If the integer flag, to enable/disable setting of viewport scale to fit view window, modulus two, is zero, then scale to fit
	if(m_iAutoFitFlag%2 == 0)					// FIT VIEWPORT SCALE TO WND
	{
			SetScaleToFitSize(szExtreme);		// set the viewport scale to fit the physical view window
	}
	else										// UNFIT VIEWPORT BY SETTING SCROLL SIZES
	{
			CSize sizeTotal;					// total size of scroll view: cx and cy are horiz and vert extents (logical units)
			sizeTotal.cx = 5000;				// horizontal extent of the scroll view
			sizeTotal.cy = 5000;				// vertical extent of the scroll view
			SetScrollSizes(MM_TEXT, sizeTotal);	// call to adjust scrolling characteristics, for initial document display or size changes
	}
	m_iAutoFitFlag++;							// increment flag such that subsequent call results in correct operation

	// DiagramEng (end)
}

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

	// DiagramEng (start)
	int tracker_flag;		// 0 => no tracker and hence a connector, 1 => tracker and hence no connector	
	
	//AfxMessageBox("\n CDiagramEngView::OnLButtondown()\n", MB_OK, 0);

	// Assume an item is being tracked: if so tracker_flag = 1, if not: tracker_flag = 0.
	tracker_flag = GetDocument()->TrackItem(point, this);	// this is a ptr-to-CWnd, i.e. CWnd *pWnd.

	// Reset Select-All Action
	if(GetDocument()->GetSelectAllFlag() == 1)
	{
		GetDocument()->ResetSelectAll();
	}

	// If nothing was tracked, i.e. tracker_flag = 0, then record points to draw and construct a connector.
	if(tracker_flag == 0)
	{
		// CScrollView-related change
		CClientDC dc(this);								// create a device context using the pointer-to-CWnd "this"
		OnPrepareDC(&dc);								// prepare the device context
		dc.DPtoLP(&point);								// use the dc to convert the point from device to logical units

		// Capture the mouse so no other apps. can get it.
		SetCapture();

		// Save the pt that the cursor is at, upon left-btn-down, i.e. init member var with incoming CPoint var.
		m_ptPrevPos = point;	// Init the prev. pt, to be used in OnMouseMove(), to the current point
		m_ptOrigin = point;		// Init the origin of the ensuing line, to be drawn in OnMouseMove(), to be the starting pt.
	}

	// DiagramEng (end)

	//CView::OnLButtonDown(nFlags, point);
	CScrollView::OnLButtonDown(nFlags, point);	// DiagramEng: CView changed to CScrollView
}

void CDiagramEngView::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	// DiagramEng (start)

	// Check to see if the left mouse btn. is down
	if((nFlags & MK_LBUTTON) == MK_LBUTTON)
	{
		// Check to see if mouse is captured
		if(GetCapture() == this)	// If what has been captured is the obj. upon which the present fn is called.
		{
			// CScrollView-related change
			CClientDC dc(this);					// create a device context using the pointer-to-CWnd "this"
			CPoint ptLogical = point;			// ptLogical records the point in logical units
			OnPrepareDC(&dc);					// prepare the device context
			dc.DPtoLP(&ptLogical);				// use the dc to convert ptLogical from device to logical units

			// Get the device context
			//CClientDC dc(this);

			// Reverse the pixel color from the original pt to the prev pt.
			// SetROP2() sets the current foreground mix mode.
			dc.SetROP2(R2_NOT);		// R2_NOT => pixel is the inverse of the screen color

			// Declare a CConnection obj in order to call DrawConnection()
			CConnection con_obj1(m_ptOrigin, m_ptPrevPos);
			con_obj1.DrawConnection(&dc);	

			// Declare a CConnection obj in order to call DrawConnection()
			// Draw the current stretch of line (but don't save it until OnLButtonUp().
			//CConnection con_obj2(m_ptOrigin, point);
			CConnection con_obj2(m_ptOrigin, ptLogical);	// CScrollView-related change: point changed to ptLogical
			con_obj2.DrawConnection(&dc);

			// Save the current pt (point) as the prev. pt (m_ptPrevPos) of the CView class.
			//m_ptPrevPos = point;
			m_ptPrevPos = ptLogical;	// CScrollView-related change: point changed to ptLogical
		}
	}

	// DiagramEng (end)

	//CView::OnMouseMove(nFlags, point);
	CScrollView::OnMouseMove(nFlags, point);	// DiagramEng: CView changed to CScrollView
}

void CDiagramEngView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	// DiagramEng (start)
	int valid = 0;		// validity of connection object (length)

	// CScrollView-related change
	CClientDC dc(this);								// create a device context using the pointer-to-CWnd "this"
	OnPrepareDC(&dc);								// prepare the device context
	dc.DPtoLP(&point);								// use the dc to convert the point from device to logical units

	// Check to see if mouse has been captured
	if(GetCapture() == this) // if what has been captured is the obj. that the "this" ptr. is pointing to.
	{
		// Add the connection to the connection list
		valid = GetDocument()->GetSystemModel().AddConnection(m_ptOrigin, point);

		if(valid)
		{
			// Attempt snapping of connection end points to ports or bend points
			GetDocument()->SnapConnectionEndPointsAfterInitialConstruction();
		}

		// Make the document redraw itself using either Invalidate(TRUE) or UpdateAllViews(NULL)
		//Invalidate(TRUE);
		GetDocument()->UpdateAllViews(NULL);

		// Release the capture so other apps. can have access to the mouse.
		ReleaseCapture();
	}

	// DiagramEng (end)

	//CView::OnLButtonUp(nFlags, point);
	CScrollView::OnLButtonUp(nFlags, point);	// DiagramEng: CView changed to CScrollView
}

void CDiagramEngView::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	// TODO: Add your message handler code here
	
	// DiagramEng (start)
	CPoint ptClient;	// used to store the converted screen pt coords to the client coord sys.
	CString sMsg;		// main msg string
	UINT nType = MB_OK;	// style of msg. box
	UINT nIDhelp = 0;	// help context ID for the msg.

	// Print msg.
	//sMsg.Format("\n CDiagramEngView::OnContextMenu(), point (x,y) = (%d,%d)\n", point.x, point.y);
	//AfxMessageBox(sMsg, nType, nIDhelp);

	// Declare a local menu obj.
	CMenu menu;

	// Load the context menu
	menu.LoadMenu(IDR_CONTEXTMENU);

	// Get the first sub-menu (the actual context menu has a 'space' to diff. it from std. menus).
	CMenu *pContextMenu = menu.GetSubMenu(0);

	// Display the context menu for the user
	pContextMenu->TrackPopupMenu(TPM_LEFTALIGN + TPM_RIGHTBUTTON + TPM_TOPALIGN, point.x, point.y, this, NULL);

	// Set the m_ptContextMenu var in the doc class first converting the Screen coord to the Client coord
	ptClient = point;								// make a copy of the screen coord
	ScreenToClient(&ptClient);						// overwrite the screen coord with the client coord

	// CScrollView-related change
	CClientDC dc(this);								// create a device context using the pointer-to-CWnd "this"
	OnPrepareDC(&dc);								// prepare the device context
	dc.DPtoLP(&ptClient);							// use the dc to convert the ptClient from device to logical units

	GetDocument()->SetContextMenuPoint(ptClient);	// set the client coord in the CDiagramEngDoc class.

	// DiagramEng (end)
}

void CDiagramEngView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	// DiagramEng (start)
	int dbl_click_flag = 0;

	// CScrollView-related change
	CClientDC dc(this);								// create a device context using the pointer-to-CWnd "this"
	OnPrepareDC(&dc);								// prepare the device context
	dc.DPtoLP(&point);								// use the dc to convert the point from device to logical units

	// Assume that a block is being double-clicked: if so dbl_click_flag = 1, if not, dlb_click_flag = 0.
	dbl_click_flag = GetDocument()->DoubleLeftClickBlock(point); 

	// DiagramEng (end)

	//CView::OnLButtonDblClk(nFlags, point);
	CScrollView::OnLButtonDblClk(nFlags, point);	// DiagramEng: CView changed to CScrollView
}

void CDiagramEngView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	
	// DiagramEng (start)
	int key_flag = 0;		// local key flag
	char lchar;				// local character
	lchar = char(nChar);	// typecast the nChar

	// Get a ptr to the doc
	CDiagramEngDoc *pDoc = GetDocument(); 

	// -- CHECK THAT THE "T" CHARACTER HAS BEEN PRESSED
	if(lchar == 'T') 
	{
		key_flag = 1;
		pDoc->SetKeyFlagTrack(key_flag);		// set the m_iKeyFlagTrack in the CDiagramEngDoc class
	}

	// -- CHECK THAT THE FINE MOVE FLAG HAS BEEN SET INDICATING FINE MOVEMENT OF AN ITEM
	if(pDoc->GetFineMoveFlag() > 0)
	{
		// -- CHECK KEY PRESSED
		if(lchar == 37)							// LEFT ARROW					
		{
			key_flag = 37;
			pDoc->FineMoveItem(key_flag);		// move item left
		}
		else if(lchar == 38)					// UP ARROW
		{
			key_flag = 38;
			pDoc->FineMoveItem(key_flag);		// move item up
		}
		else if(lchar == 39)					// RIGHT ARROW
		{
			key_flag = 39;
			pDoc->FineMoveItem(key_flag);		// move item right
		}
		else if(lchar == 40)					// DOWN ARROW
		{
			key_flag = 40;
			pDoc->FineMoveItem(key_flag);		// move item down
		}
		else									// NOT AN ARROW KEY 
		{
			key_flag = 0;
			pDoc->SetFineMoveFlag(key_flag);	// set move flag to zero to indicate no longer performing fine movement
		}
	}

	// DiagramEng (end)

	//CView::OnKeyDown(nChar, nRepCnt, nFlags);
	CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);	// DiagramEng: CView changed to CScrollView
}

void CDiagramEngView::OnInitialUpdate() 
{
	//CView::OnInitialUpdate();
	CScrollView::OnInitialUpdate();		// DiagramEng: CView changed to CScrollView
	
	// TODO: Add your specialized code here and/or call the base class
	
	// DiagramEng (start)
	// CScrollView specific setup
	CSize sizeTotal;					// total size of scroll view: cx and cy are horiz and vert extents, sizes are in logical units
	sizeTotal.cx = 5000;				// horizontal extent of the scroll view
	sizeTotal.cy = 5000;				// vertical extent of the scroll view
	
	SetScrollSizes(MM_TEXT, sizeTotal);	// set scrolling characteristics, for initial document display or size changes

	InvalidateRect(NULL);				// Invalidates the client area, i.e. forces a redraw on the next WM_PAINT message.
	// DiagramEng (end)
}

void CDiagramEngView::OnUpdate(CScrollView* pSender, LPARAM lHint, CObject* pHint) // DiagramEng: CView changed to CScrollView
{
	// TODO: Add your specialized code here and/or call the base class
	
	// DiagramEng (start)
	InvalidateRect(NULL);	// Invalidates the client area, i.e. forces a redraw on the next WM_PAINT message.
	// DiagramEng (end)
}

void CDiagramEngView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	// DiagramEng (start)
	//CView::OnPrepareDC(pDC, pInfo);		// call base class version first
	CScrollView::OnPrepareDC(pDC, pInfo);	// CView changed to CScrollView: call base class version first
	
	if(pDC->IsPrinting())
	{
		int i;				// row index
		int j;				// col index
		int originX;		// x-coord of viewport origin
		int originY;		// y-coord of viewport origin
		int page_no;		// page number calculated
		int pageHeight;		// page height in dots
		int pageWidth;		// page width in dots
		int val = 0;		// loop-breaking value

		// SET MAPPING MODE
		pDC->SetMapMode(MM_ISOTROPIC);

		// PAGE DIMS IN DOTS
		pageHeight = pDC->GetDeviceCaps(VERTRES);
		pageWidth = pDC->GetDeviceCaps(HORZRES);

		// LOOP THROUGH ROWS AND COLS OF PAGES AND DETERMINE ORIGIN COORDS
		for(j=0; j<m_iNpagesWide; j++)
		{
			for(i=0; i<m_iNpagesHigh; i++)
			{
				page_no = j*m_iNpagesHigh + i + 1;	// add 1, since m_nCurPage is an element of [1,n] (starts from 1).

				// Compare current and calculated pages
				if(pInfo->m_nCurPage == page_no)
				{
					originX = pageWidth*j;			// column multiples of pageWidth
					originY = pageHeight*i;			// row multiples of pageHeight
					val = -1;
					break;							// break from i loop
				}
			}

			if(val == -1)
			{
				break;								// break from j loop
			}
		}

		//CString str;
		//str.Format("\n OnPrepareDC(), m_nCurPage = %d, m_iNpagesWide = %d, m_iNpagesHigh = %d,\n pageWidth = %d, pageHeight = %d, originX = %d, originY = %d\n", pInfo->m_nCurPage, m_iNpagesWide, m_iNpagesHigh, pageWidth, pageHeight, originX, originY);
		//AfxMessageBox(str, MB_OK, 0);
	
		// SET VIEWPORT ORIGIN
		// Think: "Pull origin left and up by originX and originY, respectively, 
		// leaving the appropriate portion of the document on the current printing page".
		pDC->SetViewportOrg(-originX,-originY);
	}

	// DiagramEng (end)
}

void CDiagramEngView::OnUpdateViewAutoFitDiagram(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	
	// DiagramEng (start)
	UINT nID = ID_VIEW_AUTO_FIT_DIAGRAM;					// menu entry ID

	// Get the correct menu item
	CMenu *pMenu = AfxGetApp()->GetMainWnd()->GetMenu();	// get the main wnd menu
	//CMenu *pSubMenu = pMenu->GetSubMenu(2);				// get submenu: (0) File, (1) Edit, (2) View. Actually unnec.	

	// If the integer flag, to enable/disable setting of viewport scale to fit view window, modulus two, is zero, then uncheck menu item
	if(m_iAutoFitFlag%2 == 0)		
	{
		//pSubMenu->CheckMenuItem(nID, MF_UNCHECKED | MF_BYCOMMAND);	// inconsistent behaviour when using the maximize button
		pMenu->CheckMenuItem(nID, MF_UNCHECKED | MF_BYCOMMAND);
	}
	else							
	{
		//pSubMenu->CheckMenuItem(nID, MF_CHECKED | MF_BYCOMMAND);		// inconsistent behaviour when using the maximize button
		pMenu->CheckMenuItem(nID, MF_CHECKED | MF_BYCOMMAND);
	}

	// DiagramEng (end)
}

void CDiagramEngView::OnViewResetDiagram() 
{
	// TODO: Add your command handler code here
	
	// DiagramEng (start)

	// Reset the default model diagram geometry
	GetDocument()->ResetDefaultGeometry();

	// DiagramEng (end)
}

void CDiagramEngView::OnUpdateEditUndo(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	// DiagramEng (start)
	UINT nID = ID_EDIT_UNDO;					// menu entry ID

	// Get the correct menu item
	//CMenu *pMenu = AfxGetApp()->GetMainWnd()->GetMenu();	// get the main wnd menu
	
	// If integer flag indicating whether undo is possible is: (0) disable menu entry, (1) enable menu entry
	if(GetDocument()->GetEditUndoFlag() == 0)
	{
		//pMenu->CheckMenuItem(nID, MF_UNCHECKED | MF_BYCOMMAND);
		//pMenu->EnableMenuItem(nID, MF_GRAYED | MF_BYCOMMAND);
		pCmdUI->Enable(FALSE);
	}
	else
	{
		//pMenu->CheckMenuItem(nID, MF_CHECKED | MF_BYCOMMAND);
		//pMenu->EnableMenuItem(nID, MF_ENABLED | MF_BYCOMMAND);
		pCmdUI->Enable(TRUE);
	}

	// DiagramEng (end)
}

void CDiagramEngView::OnUpdateEditRedo(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	// DiagramEng (start)
	UINT nID = ID_EDIT_REDO;					// menu entry ID

	// Get the correct menu item
	//CMenu *pMenu = AfxGetApp()->GetMainWnd()->GetMenu();	// get the main wnd menu
	
	// If integer flag indicating whether redo is possible is: (0) disable menu entry, (1) enable menu entry
	if(GetDocument()->GetEditRedoFlag() == 0)
	{
		//pMenu->CheckMenuItem(nID, MF_UNCHECKED | MF_BYCOMMAND);
		//pMenu->EnableMenuItem(nID, MF_GRAYED | MF_BYCOMMAND);
		pCmdUI->Enable(FALSE);
	}
	else
	{
		//pMenu->CheckMenuItem(nID, MF_CHECKED | MF_BYCOMMAND);
		//pMenu->EnableMenuItem(nID, MF_ENABLED | MF_BYCOMMAND);
		pCmdUI->Enable(TRUE);
	}

	// DiagramEng (end)
}

void CDiagramEngView::OnUpdateFormatShowAnnotations(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here

	// DiagramEng (start)
	int draw_an = GetDocument()->GetSystemModel().GetDrawAnnotationFlag();		// show annotation state	
	int list_size = GetDocument()->GetSystemModel().GetAnnotationList().size();	// annotation list size
	UINT nID = ID_FORMAT_SHOW_ANNOTATIONS;										// menu entry ID

	// Get the correct menu item
	CMenu *pMenu = AfxGetApp()->GetMainWnd()->GetMenu();						// get the main wnd menu

	// Check Annotation List Size
	if(list_size == 0)
	{
		pCmdUI->Enable(FALSE);
		pMenu->CheckMenuItem(nID, MF_UNCHECKED | MF_BYCOMMAND);
		return;
	}
	else if(list_size > 0)
	{
		pCmdUI->Enable(TRUE);
	}

	// Check Display State
	if(draw_an == 1)
	{
		pMenu->CheckMenuItem(nID, MF_CHECKED | MF_BYCOMMAND);
	}
	else if(draw_an == 0)
	{
		pMenu->CheckMenuItem(nID, MF_UNCHECKED | MF_BYCOMMAND);	
	}

	// DiagramEng (end)
}
