/// <summary>
/// DataGridComboBoxColumn - Displays a combo box.
/// </summary>
public class DataGridComboBoxColumn : DataGridColumnStyle
{
private ComboBox combo = new ComboBox();
private bool editing = false;
private string originalText;

public DataGridComboBoxColumn(DataTable dt, int displayMember, int
valueMember)
    : this(dt, dt.Columns[displayMember].ToString(),
dt.Columns[valueMember].ToString())
{
}

public DataGridComboBoxColumn(DataTable dt, string displayMember,
string valueMember)
    : this()
{
    combo.DataSource = dt;
    combo.DisplayMember = displayMember;
    combo.ValueMember = valueMember;
}

public DataGridComboBoxColumn(ArrayList al, string displayMember,
string valueMember)
    : this()
{
    combo.DataSource = al;
    combo.DisplayMember = displayMember;
    combo.ValueMember = valueMember;
}

public DataGridComboBoxColumn()
{
    combo.Visible = false;
    combo.DropDownStyle = ComboBoxStyle.DropDownList;
}

protected override void Abort(int row)
{
    RollBack();
    HideComboBox();
    EndEdit();
}

protected override bool Commit(CurrencyManager cm, int row)
{
    HideComboBox();

    if (!editing)
    {
        return true;
    }

    try
    {
        object o = combo.SelectedValue;
        if (NullText.Equals(o))
        {
            o = System.Convert.DBNull;
        }
        
        SetColumnValueAtRow(cm, row, o);
    }
    catch
    {
        return false;
    }
    
    EndEdit();

    return true;
}

protected override void ConcedeFocus()
{
    editing = false;

    HideComboBox();
}

protected override void Edit(CurrencyManager cm, int row, Rectangle
rect, bool readOnly, string text, bool visible)
{
    originalText = combo.Text;
    
    combo.Text = string.Empty;
    combo.Bounds = rect;
    combo.RightToLeft = DataGridTableStyle.DataGrid.RightToLeft;
    combo.Visible = visible ? true : false;
    
    string temp = GetText(GetColumnValueAtRow(cm, row));
    combo.SelectedValue = temp;

    if (text != null)
    {
        combo.SelectedValue = text;
    }

    combo.Select(combo.Text.Length, 0);

    if (combo.Visible)
    {
        DataGridTableStyle.DataGrid.Invalidate(combo.Bounds);
    }

    if (ReadOnly)
    {
        combo.Enabled = false;
    }

    editing = true;
}

protected override int GetMinimumHeight()
{
    return combo.PreferredHeight;
}

protected override int GetPreferredHeight(Graphics g, object o)
{
    return 0;
}

protected override Size GetPreferredSize(Graphics g, object o)
{
    return new Size(0, 0);
}

protected override void Paint(Graphics g, Rectangle rect,
CurrencyManager cm, int row)
{
    Paint(g, rect, cm, row, false);
}

protected override void Paint(Graphics g, Rectangle rect,
CurrencyManager cm, int row, bool alignToRight)
{
    string text = GetText(GetColumnValueAtRow(cm, row));
    PaintText(g, rect, text, alignToRight);
}

protected override void Paint(Graphics g, Rectangle rect,
CurrencyManager cm, int row, Brush backBrush, Brush foreBrush, bool
alignToRight)
{
    string text = GetText(GetColumnValueAtRow(cm, row));
    PaintText(g, rect, text, backBrush, foreBrush, alignToRight);
}

protected override void SetDataGridInColumn(DataGrid dg)
{
    base.SetDataGridInColumn(dg);

    if (combo.Parent != dg)
    {
        if (combo.Parent != null)
        {
            combo.Parent.Controls.Remove(combo);
        }
    }
    
    if (dg != null)
    {
        dg.Controls.Add(combo);
    }
}

protected override void UpdateUI(CurrencyManager cm, int row, string
text)
{
    combo.Text = GetText(GetColumnValueAtRow(cm, row));
    
    if (text != null)
    {
        combo.Text = text;
    }
}                                                            

private int DataGridTableGridLineWidth
{
    get
    {
        return (DataGridTableStyle.GridLineStyle == DataGridLineStyle.Solid)
? 1 : 0;
    }
}

public void EndEdit()
{
    editing = false;

    Invalidate();
}

private string GetText(object o)
{
    if (o == System.DBNull.Value)
    {
        return NullText;
    }

    if (o != null)
    {
        return o.ToString();
    }
    else
    {
        return string.Empty;
    }
}

private void HideComboBox()
{
    if (combo.Focused)
    {
        DataGridTableStyle.DataGrid.Focus();
    }

    combo.Visible = false;
}

private void RollBack()
{
    combo.Text = originalText;
}

protected virtual void PaintText(Graphics g, Rectangle rect, string
text, bool alignToRight)
{
    Brush backBrush = new SolidBrush(DataGridTableStyle.BackColor);
    Brush foreBrush = new SolidBrush(DataGridTableStyle.ForeColor);

    PaintText(g, rect, text, backBrush, foreBrush, alignToRight);
}

protected virtual void PaintText(Graphics g, Rectangle rect, string
text, Brush backBrush, Brush foreBrush, bool alignToRight)
{    
    StringFormat format = new StringFormat();
    if (alignToRight)
    {
        format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
    }

    switch (Alignment)
    {
        case HorizontalAlignment.Left:
            format.Alignment = StringAlignment.Near;
            break;
        case HorizontalAlignment.Right:
            format.Alignment = StringAlignment.Far;
            break;
        case HorizontalAlignment.Center:
            format.Alignment = StringAlignment.Center;
            break;
    }

    format.FormatFlags = StringFormatFlags.NoWrap;

    g.FillRectangle(backBrush, rect);
    g.DrawString(text, DataGridTableStyle.DataGrid.Font, foreBrush, rect,
format);

    format.Dispose();
}
}

/// <summary>
/// DataGridDateTimePickerColumn - Displays a date picker, optionaly
displays date in red if in past, and
/// can display a check box to represent DBNull.
/// </summary>
public class DataGridDateTimePickerColumn : DataGridColumnStyle
{
private DateTimePicker picker;
private bool editing = false;
private string originalText;
private bool _redIfInPast;

public DataGridDateTimePickerColumn() :
    this(false, false)
{
}

public DataGridDateTimePickerColumn(bool checkBox) :
    this(checkBox, false)
{
}

public DataGridDateTimePickerColumn(bool checkBox, bool redIfInPast)
{
    picker = new DateTimePicker();

    picker.Visible = false;
    picker.ShowCheckBox = checkBox;
    picker.Format = DateTimePickerFormat.Short;
    
    RedIfInPast = redIfInPast;
}

public bool RedIfInPast
{
    get {return _redIfInPast;}
    set {_redIfInPast = value;}
}

public bool ShowCheckBox
{
    get {return picker.ShowCheckBox;}
    set {picker.ShowCheckBox = value;}
}

protected override void Abort(int row)
{
    RollBack();
    HideDatePicker();
    EndEdit();
}

protected override bool Commit(CurrencyManager cm, int row)
{
    HideDatePicker();

    if (!editing)
    {
        return true;
    }

    try
    {
        if (picker.Checked)
        {
            SetColumnValueAtRow(cm, row, picker.Value);                    
        }
        else
        {
            SetColumnValueAtRow(cm, row, System.DBNull.Value);
        }
    }
    catch
    {
        return false;
    }

    EndEdit();

    return true;
}

protected override void ConcedeFocus()
{
    editing = false;

    HideDatePicker();
}

protected override void Edit(CurrencyManager cm, int row, Rectangle
rect, bool readOnly, string text, bool visible)
{
    originalText = GetText(GetColumnValueAtRow(cm, row));
    Rectangle originalRect = rect;

    picker.Bounds = rect;
    picker.Visible = visible ? true : false;

    string temp = GetText(GetColumnValueAtRow(cm, row));
    if (temp.Length != 0)
    {
        if (temp == "(None)")
        {
            picker.Checked = false;
        }
        else
        {
            picker.Checked = true;
            picker.Value = DateTime.Parse(temp);
        }
    }

    if (picker.Visible)
    {
        DataGridTableStyle.DataGrid.Invalidate(originalRect);
    }

    if (ReadOnly)
    {
        picker.Enabled = false;
    }

    editing = true;
}

protected override int GetMinimumHeight()
{
    return 0;
}

protected override int GetPreferredHeight(Graphics g, object o)
{
    return 0;
}

protected override Size GetPreferredSize(Graphics g, object o)
{
    return new Size(0, 0);
}

protected override void Paint(Graphics g, Rectangle rect,
CurrencyManager cm, int row)
{
    Paint(g, rect, cm, row, false);
}

protected override void Paint(Graphics g, Rectangle rect,
CurrencyManager cm, int row, bool alignToRight)
{
    string text = GetText(GetColumnValueAtRow(cm, row));
    PaintText(g, rect, text, alignToRight);
}

protected override void Paint(Graphics g, Rectangle rect,
CurrencyManager cm, int row, Brush backBrush, Brush foreBrush, bool
alignToRight)
{
    string text = GetText(GetColumnValueAtRow(cm, row));
    PaintText(g, rect, text, backBrush, foreBrush, alignToRight);
}

protected override void SetDataGridInColumn(DataGrid dg)
{
    base.SetDataGridInColumn(dg);

    if (picker.Parent != dg)
    {
        if (picker.Parent != null)
        {
            picker.Parent.Controls.Remove(picker);
        }
    }

    if (dg != null)
    {
        dg.Controls.Add(picker);
    }
}

protected override void UpdateUI(CurrencyManager cm, int row, string
text)
{
    string temp = GetText(GetColumnValueAtRow(cm, row));

    if (text != null)
    {
        DateTime dateTime = DateTime.Parse(temp);
        picker.Value = dateTime;
    }
}

private void HideDatePicker()
{
    if (picker.Focused)
    {
        DataGridTableStyle.DataGrid.Focus();
    }

    picker.Visible = false;
}

public void EndEdit()
{
    editing = false;

    Invalidate();
}

private int DataGridTableGridLineWidth
{
    get
    {
        return (DataGridTableStyle.GridLineStyle == DataGridLineStyle.Solid)
? 1 : 0;
    }
}

private string GetText(object o)
{
    if (o == System.DBNull.Value)
    {
        return NullText;
    }

    if (o != null)
    {
        return o.ToString();
    }
    else
    {
        return string.Empty;
    }
}

protected virtual void PaintText(Graphics g, Rectangle rect, string
text, bool alignToRight)
{
    Brush backBrush = new SolidBrush(DataGridTableStyle.BackColor);
    Brush foreBrush = new SolidBrush(DataGridTableStyle.ForeColor);

    PaintText(g, rect, text, backBrush, foreBrush, alignToRight);
}

protected virtual void PaintText(Graphics g, Rectangle rect, string
text, Brush backBrush, Brush foreBrush, bool alignToRight)
{    
    StringFormat format = new StringFormat();
    if (alignToRight)
    {
        format.FormatFlags = StringFormatFlags.DirectionRightToLeft;
    }

    switch (Alignment)
    {
        case HorizontalAlignment.Left:
            format.Alignment = StringAlignment.Near;
            break;
        case HorizontalAlignment.Right:
            format.Alignment = StringAlignment.Far;
            break;
        case HorizontalAlignment.Center:
            format.Alignment = StringAlignment.Center;
            break;
    }

    format.FormatFlags = StringFormatFlags.NoWrap;

    if (RedIfInPast && text != NullText)
    {
        if (DateTime.Parse(text) < DateTime.Now)
        {
            foreBrush = new SolidBrush(Color.Red);
        }
    }

    g.FillRectangle(backBrush, rect);
    g.DrawString(text, DataGridTableStyle.DataGrid.Font, foreBrush, rect,
format);

    format.Dispose();
}

private void RollBack()
{
    if (originalText == "(None)")
    {
        picker.Value = DateTime.Parse("1/1/0001");
    }
    else
    {
        picker.Value = DateTime.Parse(originalText);
    }
}