2007-08-28 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridBoolColumn.cs
index 6d1df4aafd979bea6e31b914be3c39b8bc20ee7d..74fc49f8f3a53530e9f3c40d5d9ea07f5cc25790 100644 (file)
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2005-2007 Novell, Inc. (http://www.novell.com)
 //
 // Author:
 //     Jordi Mas i Hernandez <jordi@ximian.com>
+//     Chris toshok <toshok@ximian.com>
 //
 //
 
-// NOT COMPLETE
-
 using System.ComponentModel;
 using System.Drawing;
 using System.Runtime.InteropServices;
 using System.Diagnostics;
+using System.Collections;
 
 namespace System.Windows.Forms
 {
        public class DataGridBoolColumn : DataGridColumnStyle
        {
+               [Flags]
+               private enum CheckState {
+                       Checked         = 0x00000001,
+                       UnChecked       = 0x00000002,
+                       Null            = 0x00000004,
+                       Selected        = 0x00000008
+               }
+
                #region Local Variables
-               private bool allownull;
-               private object falsevalue;
-               private object nullvalue;
-               private object truevalue;
+               private bool allow_null;
+               private object false_value;
+               private object null_value;
+               private object true_value;
+               int editing_row;
+               CheckState editing_state;
+               CheckState model_state;
+               Size checkbox_size;
+
                #endregion      // Local Variables
 
                #region Constructors
-               public DataGridBoolColumn () : base ()
+               public DataGridBoolColumn () : this (null, false)
                {
-                       CommonConstructor ();
                }
 
-               public DataGridBoolColumn (PropertyDescriptor prop) : base (prop)
+               public DataGridBoolColumn (PropertyDescriptor prop) : this (prop, false)
                {
-                       CommonConstructor ();
                }
 
                public DataGridBoolColumn (PropertyDescriptor prop, bool isDefault)  : base (prop)
                {
-                       CommonConstructor ();
+                       false_value = false;
+                       null_value = null;
+                       true_value = true;
+                       allow_null = true;
+                       is_default = isDefault;
+                       checkbox_size = new Size (ThemeEngine.Current.DataGridMinimumColumnCheckBoxWidth, ThemeEngine.Current.DataGridMinimumColumnCheckBoxHeight);
                }
-
-               private void CommonConstructor ()
-               {
-                       allownull = true;
-                       falsevalue = false;
-                       nullvalue = null;
-                       truevalue = true;
-               }
-
                #endregion
 
                #region Public Instance Properties
+               [DefaultValue(true)]
                public bool AllowNull {
                        get {
-                               return allownull;
+                               return allow_null;
                        }
                        set {
-                               if (value != allownull) {
-                                       allownull = value;
+                               if (value != allow_null) {
+                                       allow_null = value;
 
-                                       if (AllowNullChanged != null) {
-                                               AllowNullChanged (this, EventArgs.Empty);
-                                       }
+                                       EventHandler eh = (EventHandler)(Events [AllowNullChangedEvent]);
+                                       if (eh != null)
+                                               eh (this, EventArgs.Empty);
                                }
                        }
                }
 
+               [TypeConverter(typeof(System.ComponentModel.StringConverter))]
+#if NET_2_0
+               [DefaultValue (false)]
+#endif
                public object FalseValue {
                        get {
-                               return falsevalue;
+                               return false_value;
                        }
                        set {
-                               if (value != falsevalue) {
-                                       falsevalue = value;
+                               if (value != false_value) {
+                                       false_value = value;
 
-                                       if (FalseValueChanged != null) {
-                                               FalseValueChanged (this, EventArgs.Empty);
-                                       }
+                                       EventHandler eh = (EventHandler)(Events [FalseValueChangedEvent]);
+                                       if (eh != null)
+                                               eh (this, EventArgs.Empty);
                                }
                        }
                }
 
+               [TypeConverter(typeof(System.ComponentModel.StringConverter))]
                public object NullValue {
                        get {
-                               return nullvalue;
+                               return null_value;
                        }
                        set {
-                               if (value != nullvalue) {
-                                       nullvalue = value;
+                               if (value != null_value) {
+                                       null_value = value;
+
+                                       // XXX no NullValueChangedEvent?  lame.
                                }
                        }
                }
 
+               [TypeConverter(typeof(System.ComponentModel.StringConverter))]
+#if NET_2_0
+               [DefaultValue (true)]
+#endif
                public object TrueValue {
                        get {
-                               return truevalue;
+                               return true_value;
                        }
                        set {
-                               if (value != truevalue) {
-                                       truevalue = value;
+                               if (value != true_value) {
+                                       true_value = value;
 
-                                       if (TrueValueChanged != null) {
-                                               TrueValueChanged (this, EventArgs.Empty);
-                                       }
+                                       EventHandler eh = (EventHandler)(Events [TrueValueChangedEvent]);
+                                       if (eh != null)
+                                               eh (this, EventArgs.Empty);
                                }
                        }
                }
                #endregion      // Public Instance Properties
 
                #region Public Instance Methods
-               [MonoTODO]
                protected internal override void Abort (int rowNum)
                {
-
+                       if (rowNum == editing_row) {
+                               // XXX 
+                               // this needs to not use the current cell
+                               // bounds, but the bounds of the cell for this
+                               // column/rowNum.
+                               grid.Invalidate (grid.GetCurrentCellBounds ());
+                               editing_row = -1;
+                       }
                }
 
-               [MonoTODO]
-               protected internal override bool Commit (CurrencyManager dataSource, int rowNum)
+               protected internal override bool Commit (CurrencyManager source, int rowNum)
                {
-                       throw new NotImplementedException ();
+                       if (rowNum == editing_row) {
+                               SetColumnValueAtRow (source, rowNum, FromStateToValue (editing_state));
+                               // XXX 
+                               // this needs to not use the current cell
+                               // bounds, but the bounds of the cell for this
+                               // column/rowNum.
+                               grid.Invalidate (grid.GetCurrentCellBounds ());
+                               editing_row = -1;
+                       }
+                       return true;
                }
 
                [MonoTODO]
                protected internal override void ConcedeFocus ()
                {
-
                }
 
-               [MonoTODO]
                protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string instantText,  bool cellIsVisible)
                {
-
+                       editing_row = rowNum;
+                       model_state = FromValueToState (GetColumnValueAtRow (source, rowNum));
+                       editing_state = model_state | CheckState.Selected;
+                       // XXX 
+                       // this needs to not use the current cell
+                       // bounds, but the bounds of the cell for this
+                       // column/rowNum.
+                       grid.Invalidate (grid.GetCurrentCellBounds ());
                }
 
                [MonoTODO]
@@ -157,66 +195,197 @@ namespace System.Windows.Forms
 
                }
 
-               [MonoTODO]
+               private bool ValueEquals (object value, object obj)
+               {
+                       return value == null ? obj == null : value.Equals (obj);
+               }
+
                protected internal override object GetColumnValueAtRow (CurrencyManager lm, int row)
                {
-                       throw new NotImplementedException ();
+                       object obj = base.GetColumnValueAtRow (lm, row);
+
+                       if (ValueEquals (DBNull.Value, obj))
+                               return null_value;
+
+                       if (ValueEquals (true, obj))
+                               return true_value;
+
+                       return false_value;
                }
 
-               [MonoTODO]
                protected internal override int GetMinimumHeight ()
                {
-                       throw new NotImplementedException ();
+                       return checkbox_size.Height;
                }
 
-               [MonoTODO]
                protected internal override int GetPreferredHeight (Graphics g, object value)
                {
-                       throw new NotImplementedException ();
+                       return checkbox_size.Height;
                }
 
-               [MonoTODO]
                protected internal override Size GetPreferredSize (Graphics g, object value)
                {
-                       throw new NotImplementedException ();
+                       return checkbox_size;
                }
 
-               [MonoTODO]
                protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum)
                {
-
+                       Paint (g, bounds, source, rowNum, false);
                }
 
-               [MonoTODO]
-               protected internal override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, int rowNum,   bool alignToRight)
+               protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
                {
-
+                       Paint (g, bounds, source, rowNum, ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.BackColor),
+                               ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.ForeColor), alignToRight);
                }
 
-               [MonoTODO]
-               protected internal override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
+               protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
                {
+                       Rectangle rect = new Rectangle ();                      
+                       ButtonState state;
+                       CheckState check_state;
+
+                       if (rowNum == editing_row)
+                               check_state = editing_state;
+                       else
+                               check_state = FromValueToState (GetColumnValueAtRow (source, rowNum));
+
+                       rect.X = bounds.X + ((bounds.Width - checkbox_size.Width - 2) / 2);
+                       rect.Y = bounds.Y + ((bounds.Height - checkbox_size.Height - 2) / 2);
+                       rect.Width = checkbox_size.Width - 2;
+                       rect.Height = checkbox_size.Height - 2;
+                       
+                       // If the cell is selected
+                       if ((check_state & CheckState.Selected) == CheckState.Selected) { 
+                               backBrush = ThemeEngine.Current.ResPool.GetSolidBrush (grid.SelectionBackColor);
+                               check_state &= ~CheckState.Selected;
+                       }
+                                               
+                       g.FillRectangle (backBrush, bounds);                    
+                       
+                       switch (check_state) {
+                       case CheckState.Checked:
+                               state = ButtonState.Checked;
+                               break;
+                       case CheckState.Null:
+                               state = ButtonState.Checked | ButtonState.Inactive;
+                               break;
+                       case CheckState.UnChecked:
+                       default:
+                               state = ButtonState.Normal;
+                               break;
+                       }
 
+                       ThemeEngine.Current.CPDrawCheckBox (g, rect, state);
+                       PaintGridLine (g, bounds);
                }
 
-               [MonoTODO]
-               protected internal override void SetColumnValueAtRow (CurrencyManager lm, int row, object value)
+               protected internal override void SetColumnValueAtRow (CurrencyManager lm, int row, object obj)
                {
+                       object value = null;
 
+                       if (ValueEquals (null_value, obj))
+                               value = DBNull.Value;
+                       else if (ValueEquals (true_value, obj))
+                               value = true;
+                       else if (ValueEquals (false_value, obj))
+                               value = false;
+                       /* else error? */
+
+                       base.SetColumnValueAtRow (lm, row, value);
                }
                #endregion      // Public Instance Methods
-               
+
                #region Private Instance Methods
-               internal static bool CanRenderType (Type type)
-               {                       
-                       return (type == typeof (Boolean));
+               private object FromStateToValue (CheckState state)
+               {
+                       if ((state & CheckState.Checked) == CheckState.Checked)
+                               return true_value;
+                       else if ((state & CheckState.Null) == CheckState.Null)
+                               return null_value;
+                       else
+                               return false_value;
+               }
+
+               private CheckState FromValueToState (object obj)
+               {
+                       if (ValueEquals (true_value, obj))
+                               return CheckState.Checked;
+                       else if (ValueEquals (null_value, obj))
+                               return CheckState.Null;
+                       else
+                               return CheckState.UnChecked;
+               }
+
+               private CheckState GetNextState (CheckState state)
+               {
+                       CheckState new_state;
+
+                       switch (state & ~CheckState.Selected) {
+                       case CheckState.Checked:
+                               if (AllowNull)
+                                       new_state = CheckState.Null;
+                               else
+                                       new_state = CheckState.UnChecked;
+                               break;
+                       case CheckState.Null:
+                               new_state = CheckState.UnChecked;
+                               break;
+                       case CheckState.UnChecked:
+                       default:
+                               new_state = CheckState.Checked;
+                               break;
+                       }
+                       
+                       new_state |= (state & CheckState.Selected);
+
+                       return new_state;
+               }
+
+               internal override void OnKeyDown (KeyEventArgs ke, int row, int column)
+               {
+                       switch (ke.KeyCode) {
+                       case Keys.Space:
+                               NextState (row, column);
+                               break;
+                       }
+               }
+
+               internal override void OnMouseDown (MouseEventArgs e, int row, int column)
+               {
+                       NextState (row, column);
+               }
+
+               private void NextState (int row, int column)
+               {
+                       grid.ColumnStartedEditing (new Rectangle());
+
+                       editing_state = GetNextState (editing_state);
+
+                       grid.Invalidate (grid.GetCellBounds (row, column));
                }
-               #endregion Private Instance Methods     
+
+               #endregion Private Instance Methods
 
                #region Events
-               public event EventHandler AllowNullChanged;
-               public event EventHandler FalseValueChanged;
-               public event EventHandler TrueValueChanged;
+               static object AllowNullChangedEvent = new object ();
+               static object FalseValueChangedEvent = new object ();
+               static object TrueValueChangedEvent = new object ();
+
+               public event EventHandler AllowNullChanged {
+                       add { Events.AddHandler (AllowNullChangedEvent, value); }
+                       remove { Events.RemoveHandler (AllowNullChangedEvent, value); }
+               }
+
+               public event EventHandler FalseValueChanged {
+                       add { Events.AddHandler (FalseValueChangedEvent, value); }
+                       remove { Events.RemoveHandler (FalseValueChangedEvent, value); }
+               }
+
+               public event EventHandler TrueValueChanged {
+                       add { Events.AddHandler (TrueValueChangedEvent, value); }
+                       remove { Events.RemoveHandler (TrueValueChangedEvent, value); }
+               }
                #endregion      // Events
        }
 }