1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005-2007 Novell, Inc. (http://www.novell.com)
23 // Jordi Mas i Hernandez <jordi@ximian.com>
24 // Chris toshok <toshok@ximian.com>
28 using System.ComponentModel;
30 using System.Runtime.InteropServices;
31 using System.Diagnostics;
32 using System.Collections;
34 namespace System.Windows.Forms
36 public class DataGridBoolColumn : DataGridColumnStyle
39 private enum CheckState {
41 UnChecked = 0x00000002,
46 #region Local Variables
47 private bool allow_null;
48 private object false_value;
49 private object null_value;
50 private object true_value;
52 CheckState editing_state;
53 CheckState model_state;
56 #endregion // Local Variables
59 public DataGridBoolColumn () : this (null, false)
63 public DataGridBoolColumn (PropertyDescriptor prop) : this (prop, false)
67 public DataGridBoolColumn (PropertyDescriptor prop, bool isDefault) : base (prop)
73 is_default = isDefault;
74 checkbox_size = new Size (ThemeEngine.Current.DataGridMinimumColumnCheckBoxWidth, ThemeEngine.Current.DataGridMinimumColumnCheckBoxHeight);
78 #region Public Instance Properties
80 public bool AllowNull {
85 if (value != allow_null) {
88 EventHandler eh = (EventHandler)(Events [AllowNullChangedEvent]);
90 eh (this, EventArgs.Empty);
95 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
96 [DefaultValue (false)]
97 public object FalseValue {
102 if (value != false_value) {
105 EventHandler eh = (EventHandler)(Events [FalseValueChangedEvent]);
107 eh (this, EventArgs.Empty);
112 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
113 public object NullValue {
118 if (value != null_value) {
121 // XXX no NullValueChangedEvent? lame.
126 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
127 [DefaultValue (true)]
128 public object TrueValue {
133 if (value != true_value) {
136 EventHandler eh = (EventHandler)(Events [TrueValueChangedEvent]);
138 eh (this, EventArgs.Empty);
142 #endregion // Public Instance Properties
144 #region Public Instance Methods
145 protected internal override void Abort (int rowNum)
147 if (rowNum == editing_row) {
149 // this needs to not use the current cell
150 // bounds, but the bounds of the cell for this
152 grid.Invalidate (grid.GetCurrentCellBounds ());
157 protected internal override bool Commit (CurrencyManager dataSource, int rowNum)
159 if (rowNum == editing_row) {
160 SetColumnValueAtRow (dataSource, rowNum, FromStateToValue (editing_state));
162 // this needs to not use the current cell
163 // bounds, but the bounds of the cell for this
165 grid.Invalidate (grid.GetCurrentCellBounds ());
171 [MonoTODO ("Stub, does nothing")]
172 protected internal override void ConcedeFocus ()
174 base.ConcedeFocus ();
177 protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string displayText, bool cellIsVisible)
179 editing_row = rowNum;
180 model_state = FromValueToState (GetColumnValueAtRow (source, rowNum));
181 editing_state = model_state | CheckState.Selected;
183 // this needs to not use the current cell
184 // bounds, but the bounds of the cell for this
186 grid.Invalidate (grid.GetCurrentCellBounds ());
189 [MonoTODO ("Stub, does nothing")]
190 protected internal override void EnterNullValue ()
192 base.EnterNullValue ();
195 private bool ValueEquals (object value, object obj)
197 return value == null ? obj == null : value.Equals (obj);
200 protected internal override object GetColumnValueAtRow (CurrencyManager lm, int row)
202 object obj = base.GetColumnValueAtRow (lm, row);
204 if (ValueEquals (DBNull.Value, obj))
207 if (ValueEquals (true, obj))
213 protected internal override int GetMinimumHeight ()
215 return checkbox_size.Height;
218 protected internal override int GetPreferredHeight (Graphics g, object value)
220 return checkbox_size.Height;
223 protected internal override Size GetPreferredSize (Graphics g, object value)
225 return checkbox_size;
228 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum)
230 Paint (g, bounds, source, rowNum, false);
233 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
235 Paint (g, bounds, source, rowNum, ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.BackColor),
236 ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.ForeColor), alignToRight);
239 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
241 Rectangle rect = new Rectangle ();
243 CheckState check_state;
245 if (rowNum == editing_row)
246 check_state = editing_state;
248 check_state = FromValueToState (GetColumnValueAtRow (source, rowNum));
250 rect.X = bounds.X + ((bounds.Width - checkbox_size.Width - 2) / 2);
251 rect.Y = bounds.Y + ((bounds.Height - checkbox_size.Height - 2) / 2);
252 rect.Width = checkbox_size.Width - 2;
253 rect.Height = checkbox_size.Height - 2;
255 // If the cell is selected
256 if ((check_state & CheckState.Selected) == CheckState.Selected) {
257 backBrush = ThemeEngine.Current.ResPool.GetSolidBrush (grid.SelectionBackColor);
258 check_state &= ~CheckState.Selected;
261 g.FillRectangle (backBrush, bounds);
263 switch (check_state) {
264 case CheckState.Checked:
265 state = ButtonState.Checked;
267 case CheckState.Null:
268 state = ButtonState.Checked | ButtonState.Inactive;
270 case CheckState.UnChecked:
272 state = ButtonState.Normal;
276 ThemeEngine.Current.CPDrawCheckBox (g, rect, state);
277 PaintGridLine (g, bounds);
280 protected internal override void SetColumnValueAtRow (CurrencyManager lm, int row, object value)
282 object final_value = null;
284 if (ValueEquals (null_value, value))
285 final_value = DBNull.Value;
286 else if (ValueEquals (true_value, value))
288 else if (ValueEquals (false_value, value))
292 base.SetColumnValueAtRow (lm, row, final_value);
294 #endregion // Public Instance Methods
296 #region Private Instance Methods
297 private object FromStateToValue (CheckState state)
299 if ((state & CheckState.Checked) == CheckState.Checked)
301 else if ((state & CheckState.Null) == CheckState.Null)
307 private CheckState FromValueToState (object obj)
309 if (ValueEquals (true_value, obj))
310 return CheckState.Checked;
311 else if (ValueEquals (null_value, obj))
312 return CheckState.Null;
314 return CheckState.UnChecked;
317 private CheckState GetNextState (CheckState state)
319 CheckState new_state;
321 switch (state & ~CheckState.Selected) {
322 case CheckState.Checked:
324 new_state = CheckState.Null;
326 new_state = CheckState.UnChecked;
328 case CheckState.Null:
329 new_state = CheckState.UnChecked;
331 case CheckState.UnChecked:
333 new_state = CheckState.Checked;
337 new_state |= (state & CheckState.Selected);
342 internal override void OnKeyDown (KeyEventArgs ke, int row, int column)
344 switch (ke.KeyCode) {
346 NextState (row, column);
351 internal override void OnMouseDown (MouseEventArgs e, int row, int column)
353 NextState (row, column);
356 private void NextState (int row, int column)
358 grid.ColumnStartedEditing (new Rectangle());
360 editing_state = GetNextState (editing_state);
362 grid.Invalidate (grid.GetCellBounds (row, column));
365 #endregion Private Instance Methods
368 static object AllowNullChangedEvent = new object ();
369 static object FalseValueChangedEvent = new object ();
370 static object TrueValueChangedEvent = new object ();
372 public event EventHandler AllowNullChanged {
373 add { Events.AddHandler (AllowNullChangedEvent, value); }
374 remove { Events.RemoveHandler (AllowNullChangedEvent, value); }
377 public event EventHandler FalseValueChanged {
378 add { Events.AddHandler (FalseValueChangedEvent, value); }
379 remove { Events.RemoveHandler (FalseValueChangedEvent, value); }
382 public event EventHandler TrueValueChanged {
383 add { Events.AddHandler (TrueValueChangedEvent, value); }
384 remove { Events.RemoveHandler (TrueValueChangedEvent, value); }