using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Data;
using Microsoft.VisualBasic;
using System.Diagnostics;


namespace Specefications
{
	/// <summary>
	/// Summary description for CheckBoxStyle.
	/// </summary>
	// Derive class from DataGridTextBoxColumn
	public class DataGridCheckBoxColumn : DataGridTextBoxColumn
	{
		// Hosted CheckBox control
		private CheckBox checkBox;
		private CurrencyManager cm;
		private int iCurrentRow;
		
		// Constructor - create checkBox, register selection change event handler,
		// register lose focus event handler
		public DataGridCheckBoxColumn()
		{
			this.cm = null;

			// Create CheckBox and force DropDownList style
			this.checkBox = new CheckBox();
			this.checkBox.DropDownStyle = CheckBoxStyle.DropDownList;
			
			// Add event handler for notification of when CheckBox loses focus
			this.checkBox.Leave += new EventHandler(checkBox_Leave);
		}
		
		// Property to provide access to CheckBox
		public CheckBox CheckBox
		{
			get { return checkBox; }
		}																				 
																									
		// On edit, add scroll event handler, and display combo box
		protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
		{
			
			Debug.WriteLine(String.Format("Edit {0}", rowNum));
			base.Edit(source, rowNum, bounds, readOnly, instantText, cellIsVisible);

			if (!readOnly && cellIsVisible)
			{
				// Save current row in the datagrid and currency manager associated with
				// the data source for the datagrid
				this.iCurrentRow = rowNum;
				this.cm = source;
		
				// Add event handler for datagrid scroll notification
				this.DataGridTableStyle.DataGrid.Scroll += new EventHandler(DataGrid_Scroll);

				// Site the combo box control within the bounds of the current cell
				this.checkBox.Parent = this.TextBox.Parent;
				Rectangle rect = this.DataGridTableStyle.DataGrid.GetCurrentCellBounds();
				this.checkBox.Location = rect.Location;
				this.checkBox.Size = new Size(this.TextBox.Size.Width, this.checkBox.Size.Height);

				// Set combo box selection to given text
				this.checkBox.SelectedIndex = this.checkBox.FindStringExact(this.TextBox.Text);

				// Make the CheckBox visible and place on top text box control
				this.checkBox.Show();
				this.checkBox.BringToFront();
				this.checkBox.Focus();
			}
		}

		// Given a row, get the value member associated with a row.  Use the value
		// member to find the associated display member by iterating over bound datasource
		protected override object GetColumnValueAtRow(System.Windows.Forms.CurrencyManager source, int rowNum)
		{
			Debug.WriteLine(String.Format("GetColumnValueAtRow {0}", rowNum));
			// Given a row number in the datagrid, get the display member
			object obj =  base.GetColumnValueAtRow(source, rowNum);
			
			// Iterate through the datasource bound to the ColumnCheckBox
			// Don't confuse this datasource with the datasource of the associated datagrid
			CurrencyManager cm = (CurrencyManager) 
				(this.DataGridTableStyle.DataGrid.BindingContext[this.checkBox.DataSource]);
			// Assumes the associated DataGrid is bound to a DataView, or DataTable that
			// implements a default DataView
			DataView dataview = ((DataView)cm.List);
								
			int i;

			for (i = 0; i < dataview.Count; i++)
			{
				if (obj.Equals(dataview[i][this.checkBox.ValueMember]))
					break;
			}
			
			if (i < dataview.Count)
				return dataview[i][this.checkBox.DisplayMember];
			else
				return dataview[0][this.checkBox.DisplayMember];
			
			return DBNull.Value;
		}

		// Given a row and a display member, iterating over bound datasource to find
		// the associated value member.  Set this value member.
		protected override void SetColumnValueAtRow(System.Windows.Forms.CurrencyManager source, int rowNum, object value)
		{
			Debug.WriteLine(String.Format("SetColumnValueAtRow {0} {1}", rowNum, value));
			object s = value;

			// Iterate through the datasource bound to the ColumnCheckBox
			// Don't confuse this datasource with the datasource of the associated datagrid
			CurrencyManager cm = (CurrencyManager) 
				(this.DataGridTableStyle.DataGrid.BindingContext[this.checkBox.DataSource]);
			// Assumes the associated DataGrid is bound to a DataView, or DataTable that
			// implements a default DataView
			DataView dataview = ((DataView)cm.List);
			int i;

			for (i = 0; i < dataview.Count; i++)
			{
				if (s.Equals(dataview[i][this.checkBox.DisplayMember]))
					break;
			}

			// If set item was found return corresponding value, otherwise return DbNull.Value
			if(i < dataview.Count)
				s =  dataview[i][this.checkBox.ValueMember];
			else
				s = DBNull.Value;
		
			base.SetColumnValueAtRow(source, rowNum, s);
		}

		// On datagrid scroll, hide the checkBox
		private void DataGrid_Scroll(object sender, EventArgs e)
		{
			Debug.WriteLine("Scroll");
			this.checkBox.Hide();
		}

		// On combo box losing focus, set the column value, hide the combo box,
		// and unregister scroll event handler
		private void checkBox_Leave(object sender, EventArgs e)
		{
			DataRowView rowView = (DataRowView) this.checkBox.SelectedItem;
			string s = (string) rowView.Row[this.checkBox.DisplayMember];
			Debug.WriteLine(String.Format("Leave: {0} {1}", this.checkBox.Text, s));

			SetColumnValueAtRow(this.cm, this.iCurrentRow, s);
			Invalidate();

			this.checkBox.Hide();
			this.DataGridTableStyle.DataGrid.Scroll -= new EventHandler(DataGrid_Scroll);			
		}
	}
}
