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