2009-01-09 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridViewCheckBoxCell.cs
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:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
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.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Author:
23 //      Pedro Martínez Juliá <pedromj@gmail.com>
24 //
25
26
27 #if NET_2_0
28
29 using System;
30 using System.ComponentModel;
31 using System.Drawing;
32 using System.Windows.Forms.VisualStyles;
33
34 namespace System.Windows.Forms {
35
36         public class DataGridViewCheckBoxCell : DataGridViewCell, IDataGridViewEditingCell {
37
38                 private object editingCellFormattedValue;
39                 private bool editingCellValueChanged;
40                 private object falseValue;
41                 private FlatStyle flatStyle;
42                 private object indeterminateValue;
43                 private bool threeState;
44                 private object trueValue;
45 //              private Type valueType;
46                 private PushButtonState check_state;
47
48                 public DataGridViewCheckBoxCell ()
49                 {
50                         check_state = PushButtonState.Normal;
51                         editingCellFormattedValue = false;
52                         editingCellValueChanged = false;
53                         falseValue = null;
54                         flatStyle = FlatStyle.Standard;
55                         indeterminateValue = null;
56                         threeState = false;
57                         trueValue = null;
58                         ValueType = null;
59                 }
60
61                 public DataGridViewCheckBoxCell (bool threeState) : this()
62                 {
63                         this.threeState = threeState;
64                         editingCellFormattedValue = CheckState.Unchecked;
65                 }
66
67                 public virtual object EditingCellFormattedValue {
68                         get { return editingCellFormattedValue; }
69                         set {
70                                 if (FormattedValueType == null || value == null || value.GetType() != FormattedValueType || !(value is Boolean) || !(value is CheckState)) {
71                                         throw new ArgumentException("Cannot set this property.");
72                                 }
73                                 editingCellFormattedValue = value;
74                         }
75                 }
76
77                 public virtual bool EditingCellValueChanged {
78                         get { return editingCellValueChanged; }
79                         set { editingCellValueChanged = value; }
80                 }
81
82                 public override Type EditType {
83                         get { return null; }
84                 }
85
86                 [DefaultValue (null)]
87                 public object FalseValue {
88                         get { return falseValue; }
89                         set { falseValue = value; }
90                 }
91
92                 [DefaultValue (FlatStyle.Standard)]
93                 public FlatStyle FlatStyle {
94                         get { return flatStyle; }
95                         set {
96                                 if (!Enum.IsDefined(typeof(FlatStyle), value)) {
97                                         throw new InvalidEnumArgumentException("Value is not valid FlatStyle.");
98                                 }
99                                 if (value == FlatStyle.Popup) {
100                                         throw new Exception("FlatStyle cannot be set to Popup in this control.");
101                                 }
102                         }
103                 }
104
105                 public override Type FormattedValueType {
106                         get {
107                                 if (ThreeState) {
108                                         return typeof(CheckState);
109                                 }
110                                 return typeof(Boolean);
111                         }
112                 }
113
114                 [DefaultValue (null)]
115                 public object IndeterminateValue {
116                         get { return indeterminateValue; }
117                         set { indeterminateValue = value; }
118                 }
119
120                 [DefaultValue (false)]
121                 public bool ThreeState {
122                         get { return threeState; }
123                         set { threeState = value; }
124                 }
125
126                 [DefaultValue (null)]
127                 public object TrueValue {
128                         get { return trueValue; }
129                         set { trueValue = value; }
130                 }
131
132                 public override Type ValueType {
133                         get {
134                                 if (base.ValueType == null) {
135                                         if (OwningColumn != null && OwningColumn.ValueType != null) {
136                                                 return OwningColumn.ValueType;
137                                         }
138                                         if (ThreeState) {
139                                                 return typeof(CheckState);
140                                         }
141                                         return typeof(Boolean);
142                                 }
143                                 return base.ValueType;
144                         }
145                         set { base.ValueType = value; }
146                 }
147
148                 public override object Clone ()
149                 {
150                         DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell) base.Clone();
151                         cell.editingCellValueChanged = this.editingCellValueChanged;
152                         cell.editingCellFormattedValue = this.editingCellFormattedValue;
153                         cell.falseValue = this.falseValue;
154                         cell.flatStyle = this.flatStyle;
155                         cell.indeterminateValue = this.indeterminateValue;
156                         cell.threeState = this.threeState;
157                         cell.trueValue = this.trueValue;
158                         cell.ValueType = this.ValueType;
159                         return cell;
160                 }
161
162                 public virtual object GetEditingCellFormattedValue (DataGridViewDataErrorContexts context)
163                 {
164                         if (FormattedValueType == null) {
165                                 throw new InvalidOperationException("FormattedValueType is null.");
166                         }
167                         if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) {
168                                 return Convert.ToString(Value);
169                         }
170
171                         if (editingCellFormattedValue == null)
172                                 if (threeState)
173                                         return CheckState.Indeterminate;
174                                 else
175                                         return false;
176
177                         return editingCellFormattedValue;
178                 }
179
180                 public override object ParseFormattedValue (object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
181                 {
182                         if (cellStyle == null) {
183                                 throw new ArgumentNullException("CellStyle is null");
184                         }
185                         if (FormattedValueType == null) {
186                                 throw new FormatException("FormattedValueType is null.");
187                         }
188                         if (formattedValue == null || formattedValue.GetType() != FormattedValueType) {
189                                 throw new ArgumentException("FormattedValue is null or is not instance of FormattedValueType.");
190                         }
191                         
192                         return base.ParseFormattedValue (formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
193                 }
194
195                 public virtual void PrepareEditingCellForEdit (bool selectAll)
196                 {
197                         editingCellFormattedValue = GetCurrentValue ();
198                 }
199
200                 public override string ToString ()
201                 {
202                         return string.Format ("DataGridViewCheckBoxCell {{ ColumnIndex={0}, RowIndex={1} }}", ColumnIndex, RowIndex);
203                 }
204
205                 protected override bool ContentClickUnsharesRow (DataGridViewCellEventArgs e)
206                 {
207                         return this.IsInEditMode;
208                 }
209
210                 protected override bool ContentDoubleClickUnsharesRow (DataGridViewCellEventArgs e)
211                 {
212                         return this.IsInEditMode;
213                 }
214
215                 protected override AccessibleObject CreateAccessibilityInstance ()
216                 {
217                         return new DataGridViewCheckBoxCellAccessibleObject(this);
218                 }
219
220                 protected override Rectangle GetContentBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
221                 {
222                         if (DataGridView == null)
223                                 return Rectangle.Empty;
224
225                         return new Rectangle ((Size.Width - 13) / 2, (Size.Height - 13) / 2, 13, 13);
226                 }
227
228                 protected override Rectangle GetErrorIconBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
229                 {
230                         if (DataGridView == null || string.IsNullOrEmpty (ErrorText))
231                                 return Rectangle.Empty;
232
233                         Size error_icon = new Size (12, 11);
234                         return new Rectangle (new Point (Size.Width - error_icon.Width - 5, (Size.Height - error_icon.Height) / 2), error_icon);
235                 }
236
237                 protected override object GetFormattedValue (object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
238                 {
239                         if (DataGridView == null || value == null)
240                                 if (threeState)
241                                         return CheckState.Indeterminate;
242                                 else
243                                         return false;
244                                         
245                         return value;
246                 }
247
248                 protected override Size GetPreferredSize (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
249                 {
250                         return new Size (21, 20);
251                 }
252
253                 protected override bool KeyDownUnsharesRow (KeyEventArgs e, int rowIndex)
254                 {
255                         // true if the user pressed the SPACE key without modifier keys; otherwise, false
256                         return e.KeyData == Keys.Space;
257                 }
258
259                 protected override bool KeyUpUnsharesRow (KeyEventArgs e, int rowIndex)
260                 {
261                         // true if the user released the SPACE key; otherwise false
262                         return e.KeyData == Keys.Space;
263                 }
264
265                 protected override bool MouseDownUnsharesRow (DataGridViewCellMouseEventArgs e)
266                 {
267                         return (e.Button == MouseButtons.Left);
268                 }
269
270                 protected override bool MouseEnterUnsharesRow (int rowIndex)
271                 {
272                         // true if the cell was the last cell receiving a mouse click; otherwise, false.
273                         return false;
274                 }
275
276                 protected override bool MouseLeaveUnsharesRow (int rowIndex)
277                 {
278                         // true if the button displayed by the cell is in the pressed state; otherwise, false.
279                         return check_state == PushButtonState.Pressed;
280                 }
281
282                 protected override bool MouseUpUnsharesRow (DataGridViewCellMouseEventArgs e)
283                 {
284                         // true if the mouse up was caused by the release of the left mouse button; otherwise false.
285                         return e.Button == MouseButtons.Left;
286                 }
287
288                 protected override void OnContentClick (DataGridViewCellEventArgs e)
289                 {
290                         if (!IsInEditMode)
291                                 DataGridView.BeginEdit (false);
292                                 
293                         CheckState cs = GetCurrentValue ();
294
295                         if (threeState) {
296                                 if (cs == CheckState.Indeterminate)
297                                         editingCellFormattedValue = CheckState.Unchecked;
298                                 else if (cs == CheckState.Checked)
299                                         editingCellFormattedValue = CheckState.Indeterminate;
300                                 else
301                                         editingCellFormattedValue = CheckState.Checked;
302                         } else {
303                                 if (cs == CheckState.Checked)
304                                         editingCellFormattedValue = false;
305                                 else
306                                         editingCellFormattedValue = true;
307                         }
308
309                         editingCellValueChanged = true;
310                 }
311
312                 protected override void OnContentDoubleClick (DataGridViewCellEventArgs e)
313                 {
314                 }
315
316                 protected override void OnKeyDown (KeyEventArgs e, int rowIndex)
317                 {
318                         // when activated by the SPACE key, this method updates the cell's user interface
319                         if ((e.KeyData & Keys.Space) == Keys.Space) {
320                                 check_state = PushButtonState.Pressed;
321                                 DataGridView.InvalidateCell (this);
322                         }
323                 }
324
325                 protected override void OnKeyUp (KeyEventArgs e, int rowIndex)
326                 {
327                         // when activated by the SPACE key, this method updates the cell's user interface
328                         if ((e.KeyData & Keys.Space) == Keys.Space) {
329                                 check_state = PushButtonState.Normal;
330                                 DataGridView.InvalidateCell (this);
331                         }
332                 }
333
334                 protected override void OnLeave (int rowIndex, bool throughMouseClick)
335                 {
336                         if (check_state != PushButtonState.Normal) {
337                                 check_state = PushButtonState.Normal;
338                                 DataGridView.InvalidateCell (this);
339                         }
340                 }
341
342                 protected override void OnMouseDown (DataGridViewCellMouseEventArgs e)
343                 {
344                         // if activated by depresing the left mouse button, this method updates the cell's user interface
345                         if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
346                                 check_state = PushButtonState.Pressed;
347                                 DataGridView.InvalidateCell (this);
348                         }
349                 }
350
351                 protected override void OnMouseLeave (int rowIndex)
352                 {
353                         // if the cell's button is not in its normal state, this method causes the cell's user interface to be updated.
354                         if (check_state != PushButtonState.Normal) {
355                                 check_state = PushButtonState.Normal;
356                                 DataGridView.InvalidateCell (this);
357                         }
358                 }
359
360                 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e)
361                 {
362                         if (check_state != PushButtonState.Normal && check_state != PushButtonState.Hot) {
363                                 check_state = PushButtonState.Hot;
364                                 DataGridView.InvalidateCell (this);
365                         }
366                 }
367
368                 protected override void OnMouseUp (DataGridViewCellMouseEventArgs e)
369                 {
370                         // if activated by the left mouse button, this method updates the cell's user interface
371                         if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
372                                 check_state = PushButtonState.Normal;
373                                 DataGridView.InvalidateCell (this);
374                         }
375                 }
376
377                 protected override void Paint (Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
378                 {
379                         base.Paint (graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
380                 }
381
382                 internal override void PaintPartContent (Graphics graphics, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, object formattedValue)
383                 {
384                         CheckBoxState state;
385                         CheckState value = GetCurrentValue ();
386
387                         if ((CheckState)value == CheckState.Unchecked)
388                                 state = (CheckBoxState)check_state;
389                         else if ((CheckState)value == CheckState.Checked)
390                                 state = (CheckBoxState)((int)check_state + 4);
391                         else if (threeState)
392                                 state = (CheckBoxState)((int)check_state + 8);
393                         else
394                                 state = (CheckBoxState)check_state;
395                                         
396                         Point p = new Point (cellBounds.X + (Size.Width - 13) / 2, cellBounds.Y + (Size.Height - 13) / 2);
397                         CheckBoxRenderer.DrawCheckBox (graphics, p, state);
398                 }
399                 
400                 private CheckState GetCurrentValue ()
401                 {
402                         CheckState cs = CheckState.Indeterminate;
403                         
404                         object current_obj;
405                         
406                         if (editingCellValueChanged)
407                                 current_obj = editingCellFormattedValue;
408                         else
409                                 current_obj = Value;
410
411                         if (current_obj == null)
412                                 cs = CheckState.Indeterminate;
413                         else if (current_obj is bool)
414                         {
415                                 if ((bool)current_obj == true)
416                                         cs = CheckState.Checked;
417                                 else if ((bool)current_obj == false)
418                                         cs = CheckState.Unchecked;
419                         }
420                         else if (current_obj is CheckState)
421                                 cs = (CheckState)current_obj;
422
423                         return cs;
424                 }
425                 
426                 protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject {
427
428                         public DataGridViewCheckBoxCellAccessibleObject (DataGridViewCell owner) : base(owner)
429                         {
430                         }
431
432                         public override string DefaultAction {
433                                 get {
434                                         if (Owner.ReadOnly) {
435                                                 return "";
436                                         }
437                                         // return "Press to check" if the check box is not selected
438                                         // and "Press to uncheck" if the check box is selected
439                                         throw new NotImplementedException();
440                                 }
441                         }
442
443                         public override void DoDefaultAction ()
444                         {
445                                 // change the state of the check box
446                         }
447
448                         public override int GetChildCount ()
449                         {
450                                 return -1;
451                         }
452
453                 }
454
455         }
456
457 }
458
459 #endif