Merge pull request #2102 from AdamBurgess/master
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / CheckBox.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) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Dennis Hayes    dennish@raytek.com
24 //      Peter Bartok    pbartok@novell.com
25 //
26
27 using System;
28 using System.ComponentModel;
29 using System.Drawing;
30 using System.Runtime.InteropServices;
31
32 namespace System.Windows.Forms {
33         [DefaultProperty("Checked")]
34         [DefaultEvent("CheckedChanged")]
35         [ComVisible (true)]
36         [ClassInterface (ClassInterfaceType.AutoDispatch)]
37         [DefaultBindingProperty ("CheckState")]
38         [ToolboxItem ("System.Windows.Forms.Design.AutoSizeToolboxItem," + Consts.AssemblySystem_Design)]
39         public class CheckBox : ButtonBase {
40                 #region Local Variables
41                 internal Appearance             appearance;
42                 internal bool                   auto_check;
43                 internal ContentAlignment       check_alignment;
44                 internal CheckState             check_state;
45                 internal bool                   three_state;
46                 #endregion      // Local Variables
47
48                 #region CheckBoxAccessibleObject Subclass
49                 [ComVisible(true)]
50                 public class CheckBoxAccessibleObject : ButtonBaseAccessibleObject {
51                         #region CheckBoxAccessibleObject Local Variables
52                         private new CheckBox owner;
53                         #endregion      // CheckBoxAccessibleObject Local Variables
54
55                         #region CheckBoxAccessibleObject Constructors
56                         public CheckBoxAccessibleObject(Control owner) : base(owner) {
57                                 this.owner = (CheckBox)owner;
58                         }
59                         #endregion      // CheckBoxAccessibleObject Constructors
60
61                         #region CheckBoxAccessibleObject Properties
62                         public override string DefaultAction {
63                                 get {
64                                         return "Select";
65                                 }
66                         }
67
68                         public override AccessibleRole Role {
69                                 get {
70                                         return AccessibleRole.CheckButton;
71                                 }
72                         }
73
74                         public override AccessibleStates State {
75                                 get {
76                                         AccessibleStates        retval;
77
78                                         retval = AccessibleStates.Default;
79
80                                         if (owner.check_state == CheckState.Checked) {
81                                                 retval |= AccessibleStates.Checked;
82                                         }
83
84                                         if (owner.Focused) {
85                                                 retval |= AccessibleStates.Focused;
86                                         }
87
88                                         if (owner.CanFocus) {
89                                                 retval |= AccessibleStates.Focusable;
90                                         }
91
92                                         return retval;
93                                 }
94                         }
95                         #endregion      // CheckBoxAccessibleObject Properties
96
97                         #region CheckBoxAccessibleObject Methods
98                         public override void DoDefaultAction ()
99                         {
100                                 owner.Checked = !owner.Checked;
101                         }
102                         #endregion      // CheckBoxAccessibleObject Methods
103                 }
104                 #endregion      // CheckBoxAccessibleObject Sub-class
105
106                 #region Public Constructors
107                 public CheckBox() {
108                         appearance = Appearance.Normal;
109                         auto_check = true;
110                         check_alignment = ContentAlignment.MiddleLeft;
111                         TextAlign = ContentAlignment.MiddleLeft;
112                         SetStyle(ControlStyles.StandardDoubleClick, false);
113                         SetAutoSizeMode (AutoSizeMode.GrowAndShrink);
114                 }
115                 #endregion      // Public Constructors
116
117                 #region Internal Methods
118                 internal override void Draw (PaintEventArgs pe) {
119                         // FIXME: This should be called every time something that can affect it
120                         // is changed, not every paint.  Can only change so many things at a time.
121
122                         // Figure out where our text and image should go
123                         Rectangle glyph_rectangle;
124                         Rectangle text_rectangle;
125                         Rectangle image_rectangle;
126
127                         ThemeEngine.Current.CalculateCheckBoxTextAndImageLayout (this, Point.Empty, out glyph_rectangle, out text_rectangle, out image_rectangle);
128
129                         // Draw our button
130                         if (FlatStyle != FlatStyle.System)
131                                 ThemeEngine.Current.DrawCheckBox (pe.Graphics, this, glyph_rectangle, text_rectangle, image_rectangle, pe.ClipRectangle);
132                         else
133                                 ThemeEngine.Current.DrawCheckBox (pe.Graphics, this.ClientRectangle, this);
134                 }
135
136                 internal override Size GetPreferredSizeCore (Size proposedSize)
137                 {
138                         if (this.AutoSize)
139                                 return ThemeEngine.Current.CalculateCheckBoxAutoSize (this);
140
141                         return base.GetPreferredSizeCore (proposedSize);
142                 }
143
144                 internal override void HaveDoubleClick() {
145                         if (DoubleClick != null) DoubleClick(this, EventArgs.Empty);
146                 }
147                 #endregion      // Internal Methods
148
149                 #region Public Instance Properties
150                 [DefaultValue(Appearance.Normal)]
151                 [Localizable(true)]
152                 public Appearance Appearance {
153                         get {
154                                 return appearance;
155                         }
156
157                         set {
158                                 if (value != appearance) {
159                                         appearance = value;
160                                         OnAppearanceChanged (EventArgs.Empty);
161
162                                         if (Parent != null)
163                                                 Parent.PerformLayout (this, "Appearance");
164                                         Invalidate();
165                                 }
166                         }
167                 }
168
169                 [DefaultValue(true)]
170                 public bool AutoCheck {
171                         get {
172                                 return auto_check;
173                         }
174
175                         set {
176                                 auto_check = value;
177                         }
178                 }
179
180                 [Bindable(true)]
181                 [Localizable(true)]
182                 [DefaultValue(ContentAlignment.MiddleLeft)]
183                 public ContentAlignment CheckAlign {
184                         get {
185                                 return check_alignment;
186                         }
187
188                         set {
189                                 if (value != check_alignment) {
190                                         check_alignment = value;
191                                         if (Parent != null)
192                                                 Parent.PerformLayout (this, "CheckAlign");
193                                         Invalidate();
194                                 }
195                         }
196                 }
197
198                 [Bindable(true)]
199                 [RefreshProperties(RefreshProperties.All)]
200                 [DefaultValue(false)]
201                 [SettingsBindable (true)]
202                 public bool Checked {
203                         get {
204                                 if (check_state != CheckState.Unchecked) {
205                                         return true;
206                                 }
207                                 return false;
208                         }
209
210                         set {
211                                 if (value && (check_state != CheckState.Checked)) {
212                                         check_state = CheckState.Checked;
213                                         Invalidate();
214                                         OnCheckedChanged(EventArgs.Empty);
215                                 } else if (!value && (check_state != CheckState.Unchecked)) {
216                                         check_state = CheckState.Unchecked;
217                                         Invalidate();
218                                         OnCheckedChanged(EventArgs.Empty);
219                                 }
220                         }
221                 }
222
223                 [DefaultValue(CheckState.Unchecked)]
224                 [RefreshProperties(RefreshProperties.All)]
225                 [Bindable(true)]
226                 public CheckState CheckState {
227                         get {
228                                 return check_state;
229                         }
230
231                         set {
232                                 if (value != check_state) {
233                                         bool    was_checked = (check_state != CheckState.Unchecked);
234
235                                         check_state = value;
236
237                                         if (was_checked != (check_state != CheckState.Unchecked)) {
238                                                 OnCheckedChanged(EventArgs.Empty);
239                                         }
240
241                                         OnCheckStateChanged(EventArgs.Empty);
242                                         Invalidate();
243                                 }
244                         }
245                 }
246
247                 [DefaultValue(ContentAlignment.MiddleLeft)]
248                 [Localizable(true)]
249                 public override ContentAlignment TextAlign {
250                         get { return base.TextAlign; }
251                         set { base.TextAlign = value; }
252                 }
253
254
255                 [DefaultValue(false)]
256                 public bool ThreeState {
257                         get {
258                                 return three_state;
259                         }
260
261                         set {
262                                 three_state = value;
263                         }
264                 }
265                 #endregion      // Public Instance Properties
266
267                 #region Protected Instance Properties
268                 protected override CreateParams CreateParams {
269                         get {
270                                 return base.CreateParams;
271                         }
272                 }
273
274                 protected override Size DefaultSize {
275                         get {
276                                 return new Size(104, 24);
277                         }
278                 }
279                 #endregion      // Protected Instance Properties
280
281                 #region Public Instance Methods
282                 public override string ToString() {
283                         return base.ToString() + ", CheckState: " + (int)check_state;
284                 }
285                 #endregion      // Public Instance Methods
286
287                 #region Protected Instance Methods
288                 protected override AccessibleObject CreateAccessibilityInstance() {
289                         AccessibleObject        ao;
290
291                         ao = base.CreateAccessibilityInstance ();
292                         ao.role = AccessibleRole.CheckButton;
293
294                         return ao;
295                 }
296
297                 protected virtual void OnAppearanceChanged(EventArgs e) {
298                         EventHandler eh = (EventHandler)(Events [AppearanceChangedEvent]);
299                         if (eh != null)
300                                 eh (this, e);
301                 }
302
303                 protected virtual void OnCheckedChanged(EventArgs e) {
304                         EventHandler eh = (EventHandler)(Events [CheckedChangedEvent]);
305                         if (eh != null)
306                                 eh (this, e);
307                 }
308
309                 protected virtual void OnCheckStateChanged(EventArgs e) {
310                         EventHandler eh = (EventHandler)(Events [CheckStateChangedEvent]);
311                         if (eh != null)
312                                 eh (this, e);
313                 }
314
315                 protected override void OnClick(EventArgs e) {
316                         if (auto_check) {
317                                 switch(check_state) {
318                                         case CheckState.Unchecked: {
319                                                 if (three_state) {
320                                                         CheckState = CheckState.Indeterminate;
321                                                 } else {
322                                                         CheckState = CheckState.Checked;
323                                                 }
324                                                 break;
325                                         }
326
327                                         case CheckState.Indeterminate: {
328                                                 CheckState = CheckState.Checked;
329                                                 break;
330                                         }
331
332                                         case CheckState.Checked: {
333                                                 CheckState = CheckState.Unchecked;
334                                                 break;
335                                         }
336                                 }
337                         }
338                         
339                         base.OnClick (e);
340                 }
341
342                 protected override void OnHandleCreated(EventArgs e) {
343                         base.OnHandleCreated (e);
344                 }
345
346                 protected override void OnKeyDown (KeyEventArgs e)
347                 {
348                         base.OnKeyDown (e);
349                 }
350
351                 protected override void OnMouseUp(MouseEventArgs mevent) {
352                         base.OnMouseUp (mevent);
353                 }
354
355                 protected override bool ProcessMnemonic(char charCode) {
356                         if (IsMnemonic(charCode, Text) == true) {
357                                 Select();
358                                 OnClick(EventArgs.Empty);
359                                 return true;
360                         }
361                         
362                         return base.ProcessMnemonic(charCode);
363                 }
364                 #endregion      // Protected Instance Methods
365
366                 #region Events
367                 static object AppearanceChangedEvent = new object ();
368                 static object CheckedChangedEvent = new object ();
369                 static object CheckStateChangedEvent = new object ();
370
371                 public event EventHandler AppearanceChanged {
372                         add { Events.AddHandler (AppearanceChangedEvent, value); }
373                         remove { Events.RemoveHandler (AppearanceChangedEvent, value); }
374                 }
375
376                 public event EventHandler CheckedChanged {
377                         add { Events.AddHandler (CheckedChangedEvent, value); }
378                         remove { Events.RemoveHandler (CheckedChangedEvent, value); }
379                 }
380
381                 public event EventHandler CheckStateChanged {
382                         add { Events.AddHandler (CheckStateChangedEvent, value); }
383                         remove { Events.RemoveHandler (CheckStateChangedEvent, value); }
384                 }
385                 
386                 [Browsable (false)]
387                 [EditorBrowsable (EditorBrowsableState.Never)]
388                 public new event MouseEventHandler MouseDoubleClick {
389                         add { base.MouseDoubleClick += value; }
390                         remove { base.MouseDoubleClick -= value; }
391                 }
392                 #endregion      // Events
393
394                 #region Events
395                 // XXX have a look at this and determine if it
396                 // manipulates base.DoubleClick, and see if
397                 // HaveDoubleClick can just call OnDoubleClick.
398                 [Browsable(false)]
399                 [EditorBrowsable (EditorBrowsableState.Never)]
400                 public new event EventHandler DoubleClick;
401                 #endregion      // Events
402         }
403 }