**** Merged from MCS ****
[mono-project.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / CheckBox.cs
blob52cd086fef67cc4ccd6d33bfdb983853ea82cf4f
1 //
2 // System.Windows.Forms.CheckBox.cs
3 //
4 // Author:
5 // stubbed out by Jaak Simm (jaaksimm@firm.ee)
6 // Dennis Hayes (dennish@Raytek.com)
7 //
8 // (C) Ximian, Inc., 2002
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Drawing;
34 namespace System.Windows.Forms {
36 /// <summary>
37 /// Represents a Windows check box.
38 /// </summary>
40 [MonoTODO]
41 public class CheckBox : ButtonBase {
43 // private fields
44 Appearance appearance;
45 bool autoCheck;
46 ContentAlignment checkAlign;
47 bool _checked;
48 CheckState checkState;
49 bool threeState;
50 ContentAlignment textAlign;
51 Rectangle textRect;
52 Rectangle checkRect;
53 StringFormat textFormat;
54 int checkMarkSize=13; // Keep it configurable for accessability
55 Graphics canvasDC;
56 Bitmap canvasBmp;
58 // --- Constructor ---
59 public CheckBox() : base()
62 appearance = Appearance.Normal;
63 autoCheck = true;
64 checkAlign = ContentAlignment.MiddleLeft;
65 _checked = false;
66 checkState = CheckState.Unchecked;
67 threeState = false;
69 canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
70 canvasDC = Graphics.FromImage(canvasBmp);
72 /* Set defaults for drawing text... */
73 textAlign = ContentAlignment.MiddleLeft;
74 textFormat = new StringFormat();
75 textFormat.Alignment=StringAlignment.Near;
76 textFormat.LineAlignment=StringAlignment.Center;
77 textRect = ClientRectangle;
78 textRect.X+=checkMarkSize;
79 textRect.Width-=checkMarkSize;
81 /* ... and for drawing our checkbox */
82 checkRect.X=ClientRectangle.Left;
83 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
84 checkRect.Width=checkMarkSize;
85 checkRect.Height=checkMarkSize;
87 SizeChanged+=new System.EventHandler(CheckboxSizeChanged);
88 GotFocus+=new System.EventHandler(CheckboxUpdate);
89 LostFocus+=new System.EventHandler(CheckboxUpdate);
90 TextChanged+=new System.EventHandler(CheckboxUpdate);
92 SubClassWndProc_ = true;
93 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
94 callWinControlProcMask &= ~(CallWinControlProcMask.MOUSE_MESSAGES | CallWinControlProcMask.KEYBOARD_MESSAGES);
97 // --- CheckBox Properties ---
98 public Appearance Appearance {
99 get { return appearance; }
100 set { appearance=value; }
103 public bool AutoCheck {
104 get { return autoCheck; }
105 set { autoCheck = value; }
108 public ContentAlignment CheckAlign {
109 get { return checkAlign; }
110 set {
111 checkAlign=value;
112 UpdateCheckbox();
116 public bool Checked {
117 get { return _checked; }
118 set {
119 if( _checked != value) {
120 CheckState = (value) ? CheckState.Checked : CheckState.Unchecked;
125 public CheckState CheckState {
126 get { return checkState; }
127 set {
128 if( checkState != value) {
130 checkState = value;
131 bool oldChecked = _checked;
133 if( checkState == CheckState.Unchecked) {
134 _checked = false;
136 else {
137 _checked = true;
140 if( oldChecked != _checked) {
141 OnCheckedChanged(new EventArgs());
144 OnCheckStateChanged(new EventArgs());
149 [MonoTODO]
150 protected override CreateParams CreateParams {
151 get {
152 CreateParams createParams = base.CreateParams;
154 createParams.ClassName = "BUTTON";
156 createParams.Style = (int) (
157 (int)WindowStyles.WS_CHILD |
158 (int)WindowStyles.WS_VISIBLE |
159 (int)ButtonStyles.BS_CHECKBOX |
160 (int)ButtonStyles.BS_NOTIFY |
161 (int)WindowStyles.WS_CLIPSIBLINGS |
162 (int)WindowStyles.WS_CLIPCHILDREN |
163 (int)WindowStyles.WS_TABSTOP |
164 (int)SS_Static_Control_Types.SS_LEFT );
166 if (autoCheck) {
167 createParams.Style |= (int)ButtonStyles.BS_AUTOCHECKBOX;
170 /* We need this, we draw ourselves */
171 createParams.Style |= (int) ButtonStyles.BS_OWNERDRAW;
173 return createParams;
177 [MonoTODO]
178 protected override Size DefaultSize {
179 get { return new Size(100,checkMarkSize); }
182 [MonoTODO]
183 public override ContentAlignment TextAlign {
184 get {
185 return textAlign;
187 set {
188 textAlign = value;
189 UpdateCheckbox();
193 public bool ThreeState {
194 get {
195 return threeState;
198 set {
199 threeState = value;
203 // --- CheckBox methods ---
205 protected override AccessibleObject CreateAccessibilityInstance()
207 throw new NotImplementedException ();
211 // [event methods]
212 [MonoTODO]
213 protected virtual void OnAppearanceChanged(EventArgs e)
215 if (AppearanceChanged != null) {
216 AppearanceChanged(this, e);
220 [MonoTODO]
221 protected virtual void OnCheckedChanged(EventArgs e)
223 //FIXME:
224 if(CheckedChanged != null) {
225 CheckedChanged( this, e);
229 [MonoTODO]
230 protected virtual void OnCheckStateChanged(EventArgs e)
232 //FIXME:
233 if(CheckStateChanged != null) {
234 CheckStateChanged( this, e);
238 [MonoTODO]
239 protected override void OnClick(EventArgs e)
241 CheckState = (CheckState)Win32.SendMessage(Handle, (int)ButtonMessages.BM_GETCHECK, 0, 0);
242 base.OnClick(e);
245 [MonoTODO]
246 protected override void OnHandleCreated(EventArgs e)
248 //FIXME:
249 base.OnHandleCreated(e);
250 Win32.SendMessage(Handle, (int)ButtonMessages.BM_SETCHECK, (int)checkState, 0);
253 // protected override void OnMouseDown (MouseEventArgs e)
254 // {
255 // base.OnMouseDown (e);
256 // }
258 [MonoTODO]
259 protected override void OnMouseUp(MouseEventArgs mevent)
261 if (ThreeState) {
262 switch (CheckState) {
263 case CheckState.Unchecked: {
264 CheckState = CheckState.Checked;
265 break;
268 case CheckState.Indeterminate: {
269 CheckState = CheckState.Unchecked;
270 break;
273 case CheckState.Checked: {
274 CheckState = CheckState.Indeterminate;
275 break;
278 } else {
279 Checked = Checked ? false : true;
281 CheckboxRedraw();
282 Invalidate();
283 base.OnMouseUp(mevent);
285 // end of [event methods]
288 [MonoTODO]
289 protected override bool ProcessMnemonic(char charCode)
291 //FIXME:
292 return base.ProcessMnemonic(charCode);
295 [MonoTODO]
296 //FIXME: do a better tostring
297 public override string ToString()
299 if (Checked) {
300 return "CheckBox" + " Checked";
301 } else {
302 return "CheckBox" + " Unchecked";
306 internal override void ButtonPaint (PaintEventArgs e)
308 if (canvasBmp!=null) {
309 e.Graphics.DrawImage(canvasBmp, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
313 /// --- CheckBox events ---
314 public event EventHandler AppearanceChanged;
315 public event EventHandler CheckedChanged;
316 public event EventHandler CheckStateChanged;
318 /// --- public class CheckBox.CheckBoxAccessibleObject : AccessibleObject ---
319 /// the class is only used for .NET framework
320 ///
321 public class CheckBoxAccessibleObject : AccessibleObject {
324 private void UpdateCheckbox() {
325 /* Calculate the position of text and checkbox rectangle */
326 if (appearance!=Appearance.Button) {
327 switch(checkAlign) {
328 case ContentAlignment.BottomCenter: {
329 if (ClientRectangle.Height<checkMarkSize*2) {
330 ClientSize=new Size(ClientRectangle.Width, checkMarkSize*2);
332 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
333 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
334 textRect.X=ClientRectangle.X;
335 textRect.Width=ClientRectangle.Width;
336 break;
339 case ContentAlignment.BottomLeft: {
340 checkRect.X=ClientRectangle.Left;
341 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
342 textRect.X=ClientRectangle.X+checkMarkSize;
343 textRect.Width=ClientRectangle.Width-checkMarkSize;
344 break;
347 case ContentAlignment.BottomRight: {
348 checkRect.X=ClientRectangle.Right-checkMarkSize;
349 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
350 textRect.X=ClientRectangle.X;
351 textRect.Width=ClientRectangle.Width-checkMarkSize;
352 break;
355 case ContentAlignment.MiddleCenter: {
356 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
357 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
358 textRect.X=ClientRectangle.X;
359 textRect.Width=ClientRectangle.Width;
360 break;
363 default:
364 case ContentAlignment.MiddleLeft: {
365 checkRect.X=ClientRectangle.Left;
366 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
367 textRect.X=ClientRectangle.X+checkMarkSize;
368 textRect.Width=ClientRectangle.Width-checkMarkSize;
369 break;
372 case ContentAlignment.MiddleRight: {
373 checkRect.X=ClientRectangle.Right-checkMarkSize;
374 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
375 textRect.X=ClientRectangle.X;
376 textRect.Width=ClientRectangle.Width-checkMarkSize;
377 break;
380 case ContentAlignment.TopCenter: {
381 if (ClientRectangle.Height<checkMarkSize*2) {
382 ClientSize=new Size(ClientRectangle.Width, checkMarkSize*2);
384 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
385 checkRect.Y=ClientRectangle.Top;
386 textRect.X=ClientRectangle.X;
387 textRect.Y=checkMarkSize;
388 textRect.Width=ClientRectangle.Width;
389 textRect.Height=ClientRectangle.Height-checkMarkSize;
390 break;
393 case ContentAlignment.TopLeft: {
394 checkRect.X=ClientRectangle.Left;
395 checkRect.Y=ClientRectangle.Top;
396 textRect.X=ClientRectangle.X+checkMarkSize;
397 textRect.Width=ClientRectangle.Width-checkMarkSize;
398 break;
401 case ContentAlignment.TopRight: {
402 checkRect.X=ClientRectangle.Right-checkMarkSize;
403 checkRect.Y=ClientRectangle.Top;
404 textRect.X=ClientRectangle.X;
405 textRect.Width=ClientRectangle.Width-checkMarkSize;
406 break;
409 } else {
410 textRect.X=ClientRectangle.X;
411 textRect.Width=ClientRectangle.Width;
414 /* Set the horizontal alignment of our text */
415 switch(textAlign) {
416 case ContentAlignment.BottomLeft:
417 case ContentAlignment.MiddleLeft:
418 case ContentAlignment.TopLeft: {
419 textFormat.Alignment=StringAlignment.Near;
420 break;
423 case ContentAlignment.BottomCenter:
424 case ContentAlignment.MiddleCenter:
425 case ContentAlignment.TopCenter: {
426 textFormat.Alignment=StringAlignment.Center;
427 break;
430 case ContentAlignment.BottomRight:
431 case ContentAlignment.MiddleRight:
432 case ContentAlignment.TopRight: {
433 textFormat.Alignment=StringAlignment.Far;
434 break;
438 /* Set the vertical alignment of our text */
439 switch(textAlign) {
440 case ContentAlignment.TopLeft:
441 case ContentAlignment.TopCenter:
442 case ContentAlignment.TopRight: {
443 textFormat.LineAlignment=StringAlignment.Near;
444 break;
447 case ContentAlignment.BottomLeft:
448 case ContentAlignment.BottomCenter:
449 case ContentAlignment.BottomRight: {
450 textFormat.LineAlignment=StringAlignment.Far;
451 break;
454 case ContentAlignment.MiddleLeft:
455 case ContentAlignment.MiddleCenter:
456 case ContentAlignment.MiddleRight: {
457 textFormat.LineAlignment=StringAlignment.Center;
458 break;
461 CheckboxRedraw();
462 Invalidate();
465 private void CheckboxRedraw() {
466 SolidBrush sb;
468 /* Build the image representing the control */
470 if (canvasDC!=null) {
471 canvasDC.Dispose();
473 if (canvasBmp!=null) {
474 canvasBmp.Dispose();
477 if (ClientRectangle.Width<1 || ClientRectangle.Height<1) {
478 return;
480 canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
481 canvasDC = Graphics.FromImage(canvasBmp);
483 sb=new SolidBrush(BackColor);
484 canvasDC.FillRectangle(sb, ClientRectangle);
485 sb.Dispose();
487 ButtonState state = ButtonState.Normal;
488 if (FlatStyle == FlatStyle.Flat) {
489 state |= ButtonState.Flat;
492 if (Checked) {
493 state |= ButtonState.Checked;
496 if (ThreeState && (CheckState == CheckState.Indeterminate)) {
497 state |= ButtonState.ThreeState;
500 if (appearance!=Appearance.Button) {
501 ControlPaint.DrawCheckBox(canvasDC, checkRect, state);
502 } else {
503 ControlPaint.DrawButton(canvasDC, textRect, state);
506 /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
507 sb=new SolidBrush(base.foreColor);
508 canvasDC.DrawString(Text, Font, sb, textRect, textFormat);
509 sb.Dispose();
511 if (Focused) {
512 ControlPaint.DrawFocusRectangle(canvasDC, textRect);
516 private void CheckboxUpdate(object sender, System.EventArgs e) {
517 /* Force recalculation of text & checkbox rectangles */
518 UpdateCheckbox();
521 private void CheckboxSizeChanged(object sender, System.EventArgs e)
523 /* Force recalculation of text & checkbox rectangles */
524 textRect.Y=ClientRectangle.Y;
525 textRect.Height=ClientRectangle.Height;
526 UpdateCheckbox();