[ after removing all warning suppressions, this cleans up over 100 warnings. ]
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridBoolColumn.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 //      Jordi Mas i Hernandez <jordi@ximian.com>
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System.ComponentModel;
30 using System.Drawing;
31 using System.Runtime.InteropServices;
32 using System.Diagnostics;
33 using System.Collections;
34
35 namespace System.Windows.Forms
36 {
37         public class DataGridBoolColumn : DataGridColumnStyle
38         {
39                 [Flags]
40                 private enum CheckState {
41                         Checked         = 0x00000001,
42                         UnChecked       = 0x00000002,
43                         Null            = 0x00000004,
44                         Selected        = 0x00000008
45                 }
46
47                 #region Local Variables
48                 private bool allownull;
49                 private object falsevalue;
50                 private object nullvalue;
51                 private object truevalue;
52                 private Hashtable checkboxes_state;
53                 CheckState oldState;
54
55                 #endregion      // Local Variables
56
57                 #region Constructors
58                 public DataGridBoolColumn () : this (null, false)
59                 {
60                 }
61
62                 public DataGridBoolColumn (PropertyDescriptor prop) : this (prop, false)
63                 {
64                 }
65
66                 public DataGridBoolColumn (PropertyDescriptor prop, bool isDefault)  : base (prop)
67                 {
68                         falsevalue = false;
69                         nullvalue = null;
70                         truevalue = true;
71                         allownull = true;
72                         checkboxes_state = new Hashtable ();                    
73                         is_default = isDefault;
74                 }
75                 #endregion
76
77                 #region Public Instance Properties
78                 [DefaultValue(true)]
79                 public bool AllowNull {
80                         get {
81                                 return allownull;
82                         }
83                         set {
84                                 if (value != allownull) {
85                                         allownull = value;
86
87                                         EventHandler eh = (EventHandler)(Events [AllowNullChangedEvent]);
88                                         if (eh != null)
89                                                 eh (this, EventArgs.Empty);
90                                 }
91                         }
92                 }
93
94                 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
95                 public object FalseValue {
96                         get {
97                                 return falsevalue;
98                         }
99                         set {
100                                 if (value != falsevalue) {
101                                         falsevalue = value;
102
103                                         EventHandler eh = (EventHandler)(Events [FalseValueChangedEvent]);
104                                         if (eh != null)
105                                                 eh (this, EventArgs.Empty);
106                                 }
107                         }
108                 }
109
110                 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
111                 public object NullValue {
112                         get {
113                                 return nullvalue;
114                         }
115                         set {
116                                 if (value != nullvalue) {
117                                         nullvalue = value;
118
119                                         // XXX no NullValueChangedEvent?  lame.
120                                 }
121                         }
122                 }
123
124                 [TypeConverter(typeof(System.ComponentModel.StringConverter))]
125                 public object TrueValue {
126                         get {
127                                 return truevalue;
128                         }
129                         set {
130                                 if (value != truevalue) {
131                                         truevalue = value;
132
133                                         EventHandler eh = (EventHandler)(Events [TrueValueChangedEvent]);
134                                         if (eh != null)
135                                                 eh (this, EventArgs.Empty);
136                                 }
137                         }
138                 }
139                 #endregion      // Public Instance Properties
140
141                 #region Public Instance Methods
142                 protected internal override void Abort (int rowNum)
143                 {
144                         SetState (rowNum, oldState & ~CheckState.Selected);                     
145                         grid.Invalidate (grid.GetCurrentCellBounds ());
146                 }
147
148                 protected internal override bool Commit (CurrencyManager source, int rowNum)
149                 {
150                         CheckState newState = GetState (source, rowNum);
151                         SetColumnValueAtRow (source, rowNum, FromStateToValue (newState));
152                         SetState (rowNum, newState & ~CheckState.Selected);
153                         grid.Invalidate (grid.GetCurrentCellBounds ());
154                         return true;
155                 }
156
157                 [MonoTODO]
158                 protected internal override void ConcedeFocus ()
159                 {
160                 }
161
162                 protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string instantText,  bool cellIsVisible)
163                 {
164                         oldState = GetState (source, rowNum);
165                         SetState (rowNum, oldState | CheckState.Selected);
166                         grid.Invalidate (grid.GetCurrentCellBounds ());
167                 }
168
169                 [MonoTODO]
170                 protected internal override void EnterNullValue ()
171                 {
172
173                 }
174
175                 private bool ValueEquals (object value, object obj)
176                 {
177                         return value == null ? obj == null : value.Equals (obj);
178                 }
179
180                 protected internal override object GetColumnValueAtRow (CurrencyManager lm, int row)
181                 {
182                         object obj = base.GetColumnValueAtRow (lm, row);
183
184                         if (ValueEquals (nullvalue, obj)) {
185                                 return Convert.DBNull;
186                         }
187
188                         if (ValueEquals (truevalue, obj)) {
189                                 return true;
190                         }
191
192                         return false;
193                 }
194
195                 protected internal override int GetMinimumHeight ()
196                 {
197                         return ThemeEngine.Current.DataGridMinimumColumnCheckBoxHeight;
198                 }
199
200                 protected internal override int GetPreferredHeight (Graphics g, object value)
201                 {
202                         return ThemeEngine.Current.DataGridMinimumColumnCheckBoxHeight;
203                 }
204
205                 protected internal override Size GetPreferredSize (Graphics g, object value)
206                 {
207                         return new Size (ThemeEngine.Current.DataGridMinimumColumnCheckBoxWidth, ThemeEngine.Current.DataGridMinimumColumnCheckBoxHeight);
208                 }
209
210                 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum)
211                 {
212                         Paint (g, bounds, source, rowNum, false);
213                 }
214
215                 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
216                 {
217                         Paint (g, bounds, source, rowNum, ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.BackColor),
218                                 ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.ForeColor), alignToRight);
219                 }
220
221                 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
222                 {
223                         Size chkbox_size = GetPreferredSize (g, null);
224                         Rectangle rect = new Rectangle ();                      
225                         ButtonState state;
226                         CheckState check_state = GetState (source, rowNum);
227
228                         chkbox_size.Width -= 2;
229                         chkbox_size.Height -= 2;
230
231                         rect.X = bounds.X + ((bounds.Width - chkbox_size.Width) / 2);
232                         rect.Y = bounds.Y + ((bounds.Height - chkbox_size.Height) / 2);
233                         rect.Width = chkbox_size.Width;
234                         rect.Height = chkbox_size.Height;                       
235                         
236                         // If the cell is selected
237                         if ((check_state & CheckState.Selected) == CheckState.Selected) { 
238                                 backBrush = ThemeEngine.Current.ResPool.GetSolidBrush (grid.SelectionBackColor);
239                                 check_state &= ~CheckState.Selected;
240                         }
241                                                 
242                         g.FillRectangle (backBrush, bounds);                    
243                         
244                         switch (check_state) {
245                         case CheckState.Checked:
246                                 state = ButtonState.Checked;
247                                 break;
248                         case CheckState.Null:
249                                 state = ButtonState.Checked | ButtonState.Inactive;
250                                 break;
251                         case CheckState.UnChecked:
252                         default:
253                                 state = ButtonState.Normal;
254                                 break;
255                         }
256
257                         ThemeEngine.Current.CPDrawCheckBox (g, rect, state);
258                         PaintGridLine (g, bounds);
259                 }
260
261                 protected internal override void SetColumnValueAtRow (CurrencyManager lm, int row, object obj)
262                 {
263                         object value = null;
264
265                         if (ValueEquals (nullvalue, obj))
266                                 value = Convert.DBNull;
267                         else if (ValueEquals (truevalue, obj))
268                                 value = true;
269                         else if (ValueEquals (falsevalue, obj))
270                                 value = false;
271                         /* else error? */
272
273                         base.SetColumnValueAtRow (lm, row, value);
274                 }
275                 #endregion      // Public Instance Methods
276
277                 #region Private Instance Methods
278                 private object FromStateToValue (CheckState state)
279                 {
280                         if ((state & CheckState.Checked) == CheckState.Checked)
281                                 return truevalue;
282                         else if ((state & CheckState.Null) == CheckState.Null)
283                                 return nullvalue;
284                         else
285                                 return falsevalue;
286                 }
287
288                 private CheckState FromValueToState (object obj)
289                 {
290                         if (ValueEquals (truevalue, obj))
291                                 return CheckState.Checked;
292                         else if (ValueEquals (nullvalue, obj))
293                                 return CheckState.Null;
294                         else
295                                 return CheckState.UnChecked;
296                 }
297
298                 private CheckState GetState (CurrencyManager source, int row)
299                 {
300                         CheckState state;
301
302                         if (checkboxes_state[row] == null) {
303                                 object value = GetColumnValueAtRow (source, row);
304                                 state = FromValueToState (value);
305                                 checkboxes_state.Add (row, state);
306                         } else {
307                                 state = (CheckState) checkboxes_state[row];
308                         }
309
310                         return state;
311                 }
312
313                 private CheckState GetNextState (CheckState state)
314                 {
315                         CheckState new_state;
316                         bool selected = ((state & CheckState.Selected) == CheckState.Selected);
317
318                         switch (state & ~CheckState.Selected) {
319                         case CheckState.Checked:
320                                 new_state = CheckState.Null;
321                                 break;
322                         case CheckState.Null:
323                                 new_state = CheckState.UnChecked;
324                                 break;
325                         case CheckState.UnChecked:
326                         default:
327                                 new_state = CheckState.Checked;
328                                 break;
329                         }
330                         
331                         if (selected) {
332                                 new_state = new_state | CheckState.Selected;
333                         }
334
335                         return new_state;
336                 }
337
338                 internal override void OnKeyDown (KeyEventArgs ke, int row, int column)
339                 {
340                         switch (ke.KeyCode) {
341                         case Keys.Space:
342                                 NextState (row, column);
343                                 break;
344                         }
345                 }
346
347                 internal override void OnMouseDown (MouseEventArgs e, int row, int column)
348                 {
349                         NextState (row, column);
350                 }
351
352                 private void NextState (int row, int column)
353                 {
354                         grid.ColumnStartedEditing (new Rectangle());
355
356                         SetState (row, GetNextState (GetState (null, row)));
357
358                         grid.Invalidate (grid.GetCellBounds (row, column));
359                 }
360
361                 private void SetState (int row, CheckState state)
362                 {
363                         checkboxes_state[row] = state;
364                 }
365
366                 #endregion Private Instance Methods
367
368                 #region Events
369                 static object AllowNullChangedEvent = new object ();
370                 static object FalseValueChangedEvent = new object ();
371                 static object TrueValueChangedEvent = new object ();
372
373                 public event EventHandler AllowNullChanged {
374                         add { Events.AddHandler (AllowNullChangedEvent, value); }
375                         remove { Events.RemoveHandler (AllowNullChangedEvent, value); }
376                 }
377
378                 public event EventHandler FalseValueChanged {
379                         add { Events.AddHandler (FalseValueChangedEvent, value); }
380                         remove { Events.RemoveHandler (FalseValueChangedEvent, value); }
381                 }
382
383                 public event EventHandler TrueValueChanged {
384                         add { Events.AddHandler (TrueValueChangedEvent, value); }
385                         remove { Events.RemoveHandler (TrueValueChangedEvent, value); }
386                 }
387                 #endregion      // Events
388         }
389 }