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))]
97 [DefaultValue (false)]
99 public object FalseValue {
104 if (value != false_value) {
107 EventHandler eh = (EventHandler)(Events [FalseValueChangedEvent]);
109 eh (this, EventArgs.Empty);
114 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
115 public object NullValue {
120 if (value != null_value) {
123 // XXX no NullValueChangedEvent? lame.
128 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
130 [DefaultValue (true)]
132 public object TrueValue {
137 if (value != true_value) {
140 EventHandler eh = (EventHandler)(Events [TrueValueChangedEvent]);
142 eh (this, EventArgs.Empty);
146 #endregion // Public Instance Properties
148 #region Public Instance Methods
149 protected internal override void Abort (int rowNum)
151 if (rowNum == editing_row) {
153 // this needs to not use the current cell
154 // bounds, but the bounds of the cell for this
156 grid.Invalidate (grid.GetCurrentCellBounds ());
161 protected internal override bool Commit (CurrencyManager dataSource, int rowNum)
163 if (rowNum == editing_row) {
164 SetColumnValueAtRow (dataSource, rowNum, FromStateToValue (editing_state));
166 // this needs to not use the current cell
167 // bounds, but the bounds of the cell for this
169 grid.Invalidate (grid.GetCurrentCellBounds ());
176 protected internal override void ConcedeFocus ()
181 protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string displayText, bool cellIsVisible)
184 protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
187 editing_row = rowNum;
188 model_state = FromValueToState (GetColumnValueAtRow (source, rowNum));
189 editing_state = model_state | CheckState.Selected;
191 // this needs to not use the current cell
192 // bounds, but the bounds of the cell for this
194 grid.Invalidate (grid.GetCurrentCellBounds ());
198 protected internal override void EnterNullValue ()
203 private bool ValueEquals (object value, object obj)
205 return value == null ? obj == null : value.Equals (obj);
208 protected internal override object GetColumnValueAtRow (CurrencyManager lm, int row)
210 object obj = base.GetColumnValueAtRow (lm, row);
212 if (ValueEquals (DBNull.Value, obj))
215 if (ValueEquals (true, obj))
221 protected internal override int GetMinimumHeight ()
223 return checkbox_size.Height;
226 protected internal override int GetPreferredHeight (Graphics g, object value)
228 return checkbox_size.Height;
231 protected internal override Size GetPreferredSize (Graphics g, object value)
233 return checkbox_size;
236 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum)
238 Paint (g, bounds, source, rowNum, false);
241 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
243 Paint (g, bounds, source, rowNum, ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.BackColor),
244 ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.ForeColor), alignToRight);
247 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
249 Rectangle rect = new Rectangle ();
251 CheckState check_state;
253 if (rowNum == editing_row)
254 check_state = editing_state;
256 check_state = FromValueToState (GetColumnValueAtRow (source, rowNum));
258 rect.X = bounds.X + ((bounds.Width - checkbox_size.Width - 2) / 2);
259 rect.Y = bounds.Y + ((bounds.Height - checkbox_size.Height - 2) / 2);
260 rect.Width = checkbox_size.Width - 2;
261 rect.Height = checkbox_size.Height - 2;
263 // If the cell is selected
264 if ((check_state & CheckState.Selected) == CheckState.Selected) {
265 backBrush = ThemeEngine.Current.ResPool.GetSolidBrush (grid.SelectionBackColor);
266 check_state &= ~CheckState.Selected;
269 g.FillRectangle (backBrush, bounds);
271 switch (check_state) {
272 case CheckState.Checked:
273 state = ButtonState.Checked;
275 case CheckState.Null:
276 state = ButtonState.Checked | ButtonState.Inactive;
278 case CheckState.UnChecked:
280 state = ButtonState.Normal;
284 ThemeEngine.Current.CPDrawCheckBox (g, rect, state);
285 PaintGridLine (g, bounds);
288 protected internal override void SetColumnValueAtRow (CurrencyManager lm, int row, object value)
290 object final_value = null;
292 if (ValueEquals (null_value, value))
293 final_value = DBNull.Value;
294 else if (ValueEquals (true_value, value))
296 else if (ValueEquals (false_value, value))
300 base.SetColumnValueAtRow (lm, row, final_value);
302 #endregion // Public Instance Methods
304 #region Private Instance Methods
305 private object FromStateToValue (CheckState state)
307 if ((state & CheckState.Checked) == CheckState.Checked)
309 else if ((state & CheckState.Null) == CheckState.Null)
315 private CheckState FromValueToState (object obj)
317 if (ValueEquals (true_value, obj))
318 return CheckState.Checked;
319 else if (ValueEquals (null_value, obj))
320 return CheckState.Null;
322 return CheckState.UnChecked;
325 private CheckState GetNextState (CheckState state)
327 CheckState new_state;
329 switch (state & ~CheckState.Selected) {
330 case CheckState.Checked:
332 new_state = CheckState.Null;
334 new_state = CheckState.UnChecked;
336 case CheckState.Null:
337 new_state = CheckState.UnChecked;
339 case CheckState.UnChecked:
341 new_state = CheckState.Checked;
345 new_state |= (state & CheckState.Selected);
350 internal override void OnKeyDown (KeyEventArgs ke, int row, int column)
352 switch (ke.KeyCode) {
354 NextState (row, column);
359 internal override void OnMouseDown (MouseEventArgs e, int row, int column)
361 NextState (row, column);
364 private void NextState (int row, int column)
366 grid.ColumnStartedEditing (new Rectangle());
368 editing_state = GetNextState (editing_state);
370 grid.Invalidate (grid.GetCellBounds (row, column));
373 #endregion Private Instance Methods
376 static object AllowNullChangedEvent = new object ();
377 static object FalseValueChangedEvent = new object ();
378 static object TrueValueChangedEvent = new object ();
380 public event EventHandler AllowNullChanged {
381 add { Events.AddHandler (AllowNullChangedEvent, value); }
382 remove { Events.RemoveHandler (AllowNullChangedEvent, value); }
385 public event EventHandler FalseValueChanged {
386 add { Events.AddHandler (FalseValueChangedEvent, value); }
387 remove { Events.RemoveHandler (FalseValueChangedEvent, value); }
390 public event EventHandler TrueValueChanged {
391 add { Events.AddHandler (TrueValueChangedEvent, value); }
392 remove { Events.RemoveHandler (TrueValueChangedEvent, value); }