* TabControl.cs: Show the tooltip depending on the value
[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 (ReadOnly)
291                                 return;
292
293                         if (!IsInEditMode)
294                                 DataGridView.BeginEdit (false);
295                         
296                         ToggleCheckState ();
297                 }
298
299                 private void ToggleCheckState ()
300                 {
301                         CheckState cs = GetCurrentValue ();
302
303                         if (threeState) {
304                                 if (cs == CheckState.Indeterminate)
305                                         editingCellFormattedValue = CheckState.Unchecked;
306                                 else if (cs == CheckState.Checked)
307                                         editingCellFormattedValue = CheckState.Indeterminate;
308                                 else
309                                         editingCellFormattedValue = CheckState.Checked;
310                         } else {
311                                 if (cs == CheckState.Checked)
312                                         editingCellFormattedValue = false;
313                                 else
314                                         editingCellFormattedValue = true;
315                         }
316
317                         editingCellValueChanged = true;
318                         DataGridView.InvalidateCell (this);
319                 }
320
321                 protected override void OnContentDoubleClick (DataGridViewCellEventArgs e)
322                 {
323                 }
324
325                 protected override void OnKeyDown (KeyEventArgs e, int rowIndex)
326                 {
327                         // when activated by the SPACE key, this method updates the cell's user interface
328                         if (!ReadOnly && (e.KeyData & Keys.Space) == Keys.Space) {
329                                 check_state = PushButtonState.Pressed;
330                                 DataGridView.InvalidateCell (this);
331                         }
332                 }
333
334                 protected override void OnKeyUp (KeyEventArgs e, int rowIndex)
335                 {
336                         // when activated by the SPACE key, this method updates the cell's user interface
337                         if (!ReadOnly && (e.KeyData & Keys.Space) == Keys.Space) {
338                                 check_state = PushButtonState.Normal;
339                                 if (!IsInEditMode)
340                                         DataGridView.BeginEdit (false);
341                                 ToggleCheckState ();
342                         }
343                 }
344
345                 protected override void OnLeave (int rowIndex, bool throughMouseClick)
346                 {
347                         if (!ReadOnly && check_state != PushButtonState.Normal) {
348                                 check_state = PushButtonState.Normal;
349                                 DataGridView.InvalidateCell (this);
350                         }
351                 }
352
353                 protected override void OnMouseDown (DataGridViewCellMouseEventArgs e)
354                 {
355                         // if activated by depresing the left mouse button, this method updates the cell's user interface
356                         if (!ReadOnly && (e.Button & MouseButtons.Left) == MouseButtons.Left) {
357                                 check_state = PushButtonState.Pressed;
358                                 DataGridView.InvalidateCell (this);
359                         }
360                 }
361
362                 protected override void OnMouseLeave (int rowIndex)
363                 {
364                         // if the cell's button is not in its normal state, this method causes the cell's user interface to be updated.
365                         if (!ReadOnly && check_state != PushButtonState.Normal) {
366                                 check_state = PushButtonState.Normal;
367                                 DataGridView.InvalidateCell (this);
368                         }
369                 }
370
371                 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e)
372                 {
373                         if (!ReadOnly && check_state != PushButtonState.Normal && check_state != PushButtonState.Hot) {
374                                 check_state = PushButtonState.Hot;
375                                 DataGridView.InvalidateCell (this);
376                         }
377                 }
378
379                 protected override void OnMouseUp (DataGridViewCellMouseEventArgs e)
380                 {
381                         // if activated by the left mouse button, this method updates the cell's user interface
382                         if (!ReadOnly && (e.Button & MouseButtons.Left) == MouseButtons.Left) {
383                                 check_state = PushButtonState.Normal;
384                                 DataGridView.InvalidateCell (this);
385                         }
386                 }
387
388                 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)
389                 {
390                         base.Paint (graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
391                 }
392
393                 internal override void PaintPartContent (Graphics graphics, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, object formattedValue)
394                 {
395                         CheckBoxState state;
396                         CheckState value = GetCurrentValue ();
397
398                         if ((CheckState)value == CheckState.Unchecked)
399                                 state = (CheckBoxState)check_state;
400                         else if ((CheckState)value == CheckState.Checked)
401                                 state = (CheckBoxState)((int)check_state + 4);
402                         else if (threeState)
403                                 state = (CheckBoxState)((int)check_state + 8);
404                         else
405                                 state = (CheckBoxState)check_state;
406                                         
407                         Point p = new Point (cellBounds.X + (Size.Width - 13) / 2, cellBounds.Y + (Size.Height - 13) / 2);
408                         CheckBoxRenderer.DrawCheckBox (graphics, p, state);
409                 }
410                 
411                 private CheckState GetCurrentValue ()
412                 {
413                         CheckState cs = CheckState.Indeterminate;
414                         
415                         object current_obj;
416                         
417                         if (editingCellValueChanged)
418                                 current_obj = editingCellFormattedValue;
419                         else
420                                 current_obj = Value;
421
422                         if (current_obj == null)
423                                 cs = CheckState.Indeterminate;
424                         else if (current_obj is bool)
425                         {
426                                 if ((bool)current_obj == true)
427                                         cs = CheckState.Checked;
428                                 else if ((bool)current_obj == false)
429                                         cs = CheckState.Unchecked;
430                         }
431                         else if (current_obj is CheckState)
432                                 cs = (CheckState)current_obj;
433
434                         return cs;
435                 }
436                 
437                 protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject {
438
439                         public DataGridViewCheckBoxCellAccessibleObject (DataGridViewCell owner) : base(owner)
440                         {
441                         }
442
443                         public override string DefaultAction {
444                                 get {
445                                         if (Owner.ReadOnly) {
446                                                 return "";
447                                         }
448                                         // return "Press to check" if the check box is not selected
449                                         // and "Press to uncheck" if the check box is selected
450                                         throw new NotImplementedException();
451                                 }
452                         }
453
454                         public override void DoDefaultAction ()
455                         {
456                                 // change the state of the check box
457                         }
458
459                         public override int GetChildCount ()
460                         {
461                                 return -1;
462                         }
463
464                 }
465
466         }
467
468 }
469
470 #endif