//
//  control_panel.h - control panel header file
//
//  $Id: control_panel.h 37 2014-02-06 17:38:11Z brian $ 
//
//  Copyright (c) 1999-2014 by Precision Micro Control Corp. All rights reserved.
//
#ifndef CONTROL_PANEL_H
#define CONTROL_PANEL_H

//
// ControlPanel form view
//
#ifndef __AFXEXT_H__
#include <afxext.h>
#endif

#define ZERO_BUTTON_CNT	4
#define POS_DISPLAY_CNT	4
#define JOG_BUTTON_CNT	6

// Button states
#define ALL_BUTTONS		0xFFFF
#define JOG_XPLUS_DOWN	0x1
#define JOG_XMINUS_DOWN	0x2
#define JOG_YPLUS_DOWN	0x4
#define JOG_YMINUS_DOWN	0x8
#define JOG_ZPLUS_DOWN	0x10
#define JOG_ZMINUS_DOWN	0x20
#define START_DOWN		0x100
#define BLOCK_DOWN		0x200
#define FHOLD_DOWN		0x400

/// <summary>
/// ControlPanel - app UI control panel class
/// </summary>
class ControlPanel : public CDialogBar
{ 
	DECLARE_DYNCREATE(ControlPanel)
public:
	/// <summary>Constructor.</summary>
	ControlPanel();
	/// <summary>Destructor.</summary>
	virtual ~ControlPanel();

	// Implementation

	/// <summary>Dialog data exchange.</summary>
	/// <param name="pDX">Dialog data.</param>
	virtual void				DoDataExchange(CDataExchange* pDX);
	/// <summary>Initialize.</summary>
	/// <remarks>
	/// <para>This function will make changes to the control panel, both in the mechanics
	/// of how it works, and its' visual appearance. In order to provide special
	/// handling of messages for controls on the panel, derived controls are
	/// "subclassed" for the controls that were placed on the dialog bar.</para>
	/// </remarks>
	void						InitialUpdate(void);
	/// <summary>Process timer messages.</summary>
	virtual void				OnTimer(void);
	/// <summary>Set button state.</summary>
	/// <param name="state">State.</param>
	void						SetExternalButtonState(int channel_num, int state);
	/// <summary>Set indicator state.</summary>
	/// <param name="state">True to enable, false to disable.</param>
	void						EnableExternalIndicator(int channel_num, bool state);

	/// <summary>Set X Zero control enable/disable state.</summary>
	/// <param name="pCmdUI">X Zero control.</param>
	void						OnUpdateXZero(CCmdUI* pCmdUI) { pCmdUI->Enable(ZeroEnabled() && theApp.GetMachine()->XAxis.GetAxis()); }
	/// <summary>Set Y Zero control enable/disable state.</summary>
	/// <param name="pCmdUI">Y Zero control.</param>
	void						OnUpdateYZero(CCmdUI* pCmdUI) { pCmdUI->Enable(ZeroEnabled() && theApp.GetMachine()->YAxis.GetAxis()); }
	/// <summary>Set Z Zero control enable/disable state.</summary>
	/// <param name="pCmdUI">X Zero control.</param>
	void						OnUpdateZZero(CCmdUI* pCmdUI) { pCmdUI->Enable(ZeroEnabled() && theApp.GetMachine()->ZAxis.GetAxis()); }
	/// <summary>Get state of Zero mode.</summary>
	/// <returns>True if enabled, false if not.</returns>
	bool						ZeroEnabled(void);

	/// <summary>Set X Plus control enable/disable state.</summary>
	/// <param name="pCmdUI">X Plus control.</param>
	void						OnUpdateXPlus(CCmdUI* pCmdUI) { pCmdUI->Enable(JogEnabled() && theApp.GetMachine()->XAxis.GetAxis()); }
	/// <summary>Set X Minus control enable/disable state.</summary>
	/// <param name="pCmdUI">X Minus control.</param>
	void						OnUpdateXMinus(CCmdUI* pCmdUI) { pCmdUI->Enable(JogEnabled() && theApp.GetMachine()->XAxis.GetAxis()); }
	/// <summary>Set Y Plus control enable/disable state.</summary>
	/// <param name="pCmdUI">Y Plus control.</param>
	void						OnUpdateYPlus(CCmdUI* pCmdUI) { pCmdUI->Enable(JogEnabled() && theApp.GetMachine()->YAxis.GetAxis()); }
	/// <summary>Set Y Minus control enable/disable state.</summary>
	/// <param name="pCmdUI">Y Minus control.</param>
	void						OnUpdateYMinus(CCmdUI* pCmdUI) { pCmdUI->Enable(JogEnabled() && theApp.GetMachine()->YAxis.GetAxis()); }
	/// <summary>Set Z Plus control enable/disable state.</summary>
	/// <param name="pCmdUI">X Plus control.</param>
	void						OnUpdateZPlus(CCmdUI* pCmdUI) { pCmdUI->Enable(JogEnabled() && (theApp.GetMachine()->ZAxis.GetAxis() || ((int)theApp.GetMachine()->m_cutter.GetAxis() && (int)theApp.GetMachine()->m_cutter.RaiseMacro))); }
	/// <summary>Set Z Minus control enable/disable state.</summary>
	/// <param name="pCmdUI">X Minus control.</param>
	void						OnUpdateZMinus(CCmdUI* pCmdUI) { pCmdUI->Enable(JogEnabled() && (theApp.GetMachine()->ZAxis.GetAxis() || ((int)theApp.GetMachine()->m_cutter.GetAxis() && (int)theApp.GetMachine()->m_cutter.LowerMacro))); }
	/// <summary>Get state of Jog mode.</summary>
	/// <returns>True if enabled, false if not.</returns>
	bool						JogEnabled(void);
	
	/// <summary>Set state of Start mode.</summary>
	/// <param name="pCmdUI">Start control.</param>
	void						OnUpdateStart(CCmdUI* pCmdUI) { pCmdUI->Enable(StartEnabled()); }
	/// <summary>Set state of Block mode.</summary>
	/// <param name="pCmdUI">Block control.</param>
	void						OnUpdateBlock(CCmdUI* pCmdUI) { pCmdUI->Enable(BlockEnabled()); }
	/// <summary>Set state of Feedhold mode.</summary>
	/// <param name="pCmdUI">Feedhold control.</param>
	void						OnUpdateFhold(CCmdUI* pCmdUI) { pCmdUI->Enable(FholdEnabled()); }

	/// <summary>Kill feed override focus.</summary>
	void						OnKillfocusFeedOverride(void);
	/// <summary>Kill rapid override focus.</summary>
	void						OnKillfocusRapidOverride(void);
	/// <summary>Kill spindle override focus.</summary>
	void						OnKillfocusSpindleOverride(void);

	/// <summary>Check mouse left button down state and set control.</summary>
	/// <param name="id">Desired control ID.</param>
	void						LeftButtonDown(int id);
	/// <summary>Check mouse left button up state and set control.</summary>
	/// <param name="id">Desired control ID.</param>
	void						LeftButtonUp(int id);
	/// <summary>Get button state.</summary>
	/// <returns>State.</returns>
	int							GetButtonState() { return m_button_state; }

private:
	/// <summary>Get state of Start mode.</summary>
	/// <returns>True if enabled, false if not.</returns>
	bool						StartEnabled(void);
	/// <summary>Get state of Block mode.</summary>
	/// <returns>True if enabled, false if not.</returns>
	bool						BlockEnabled(void);
	/// <summary>Get state of Feedhold.</summary>
	/// <returns>True if enabled, false if not.</returns>
	bool						FholdEnabled(void);
	
	/// <summary>Set button state flag.</summary>
	/// <param name="state">Flag.</param>
	void						SetButtonState(int state) { m_button_state |= state; }
	/// <summary>Clear button state flag.</summary>
	/// <param name="state">Flag.</param>
	void						ClearButtonState(int state) { m_button_state &= ~state; }
	
	// Generated message map functions
	//{ { AFX_MSG(ControlPanel)
	afx_msg void				OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

private:
	enum { 
		IDD = IDD_RUN_PANEL 
	};

	ControlButton				m_block_button;					///< block button
	int							m_button_state;					///< current button state
	int							m_button_state_old;				///< previous button state
	ControlButton				m_cut_enable_button;			///< cut enable button
	unsigned int				m_dio_channels;					///< digital I/O channels state
	ControlButton				m_feed_hold_button;				///< feed hold button
	CString						m_feed_override;				///< feed rate override string
	CScrollBar					m_feed_scroll;					///< feed rate override scrollbar
	ControlButton				m_jog_button[JOG_BUTTON_CNT];	///< jog buttons
	CFont*						m_pos_disp_font;				///< display font
	CString						m_pos_display1;					///< position display 1 string
	CString						m_pos_display2;					///< position display 2 string
	CString						m_pos_display3;					///< position display 3 string
	CString						m_pos_display4;					///< position display 4 string
	CString						m_rapid_override;				///< rapid override string
	CScrollBar					m_rapid_scroll;					///< rapid override scrollbar
	int							m_run_status;					///< run status from motion controller (read in timer service)
	CString						m_spindle_override;				///< spindle override string
	CScrollBar					m_spindle_scroll;				///< spindle override scrollbar
	ControlButton				m_start_button;					///< start button
	CButton						m_status_ready;					///< ready status indicator
	CButton						m_status_running;				///< running status indicator
	CButton						m_status_paused;				///< paused status indicator
	CButton						m_status_feedhold;				///< free hold status indicator
	CButton						m_status_finished;				///< finished status indicator
	CButton						m_status_error;					///< error status indicator
	bool						m_timer_update;					///< flag to limit DoDataExchange during timer updates
	ControlButton				m_zero_button[ZERO_BUTTON_CNT];	///< sero buttons
 };

#endif			// CONTROL_PANEL_H
