- Initial check-in
[mono.git] / mcs / class / Managed.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 Novell, Inc.
21 //
22 // Authors:
23 //      Dennis Hayes    dennish@raytek.com
24 //      Peter Bartok    pbartok@novell.com
25 //
26 //
27 // $Revision: 1.1 $
28 // $Modtime: $
29 // $Log: CheckBox.cs,v $
30 // Revision 1.1  2004/07/09 05:21:25  pbartok
31 // - Initial check-in
32 //
33 //
34
35 // NOT COMPLETE
36
37 namespace System.Windows.Forms {
38         public class CreateParams {
39                 #region Public Constructors
40                 #endregion      // Public Constructors
41
42                 #region Public Instance Properties
43                 #endregion      // Public Instance Properties
44
45                 #region Public Instance Methods
46                 #endregion      // Public Instance Methods
47         }
48 }
49 //
50 // System.Windows.Forms.CheckBox.cs
51 //
52 // Author:
53 //   stubbed out by Jaak Simm (jaaksimm@firm.ee)
54 //   Dennis Hayes (dennish@Raytek.com)
55 //
56 // (C) Ximian, Inc., 2002
57 //
58
59 using System.Drawing;
60
61 namespace System.Windows.Forms {
62
63         /// <summary>
64         /// Represents a Windows check box.
65         /// </summary>
66
67         [MonoTODO]
68         public class CheckBox : ButtonBase {
69
70                 // private fields
71                 Appearance                      appearance;
72                 bool                                    autoCheck;
73                 ContentAlignment        checkAlign;
74                 bool                                    _checked;
75                 CheckState                      checkState;
76                 bool                                    threeState;
77                 ContentAlignment        textAlign;
78                 Rectangle                       textRect;
79                 Rectangle                       checkRect;
80                 StringFormat            textFormat;
81                 int                                     checkMarkSize=13;               // Keep it configurable for accessability
82                 Graphics                                canvasDC;
83                 Bitmap                          canvasBmp;
84                 
85                 // --- Constructor ---
86                 public CheckBox() : base() 
87                 {
88
89                         appearance = Appearance.Normal;
90                         autoCheck = true;
91                         checkAlign = ContentAlignment.MiddleLeft;
92                         _checked = false;
93                         checkState = CheckState.Unchecked;
94                         threeState = false;
95
96                         canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
97                         canvasDC = Graphics.FromImage(canvasBmp);
98
99                         /* Set defaults for drawing text... */
100                         textAlign = ContentAlignment.MiddleLeft;
101                         textFormat = new StringFormat();
102                         textFormat.Alignment=StringAlignment.Near;
103                         textFormat.LineAlignment=StringAlignment.Center;
104                         textRect = ClientRectangle;
105                         textRect.X+=checkMarkSize;
106                         textRect.Width-=checkMarkSize;
107
108                         /* ... and for drawing our checkbox */
109                         checkRect.X=ClientRectangle.Left;
110                         checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
111                         checkRect.Width=checkMarkSize;
112                         checkRect.Height=checkMarkSize;
113
114                         SizeChanged+=new System.EventHandler(CheckboxSizeChanged);
115                         GotFocus+=new System.EventHandler(CheckboxUpdate);
116                         LostFocus+=new System.EventHandler(CheckboxUpdate);
117                         TextChanged+=new System.EventHandler(CheckboxUpdate);
118
119                         SubClassWndProc_ = true;
120                         SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
121                         callWinControlProcMask &= ~(CallWinControlProcMask.MOUSE_MESSAGES | CallWinControlProcMask.KEYBOARD_MESSAGES);
122                 }
123                 
124                 // --- CheckBox Properties ---
125                 public Appearance Appearance {
126                         get { return appearance; }
127                         set { appearance=value; }
128                 }
129                 
130                 public bool AutoCheck {
131                         get { return autoCheck; }
132                         set { autoCheck = value; }
133                 }
134                 
135                 public ContentAlignment CheckAlign {
136                         get { return checkAlign; }
137                         set {
138                                 checkAlign=value;
139                                 UpdateCheckbox();
140                         }
141                 }
142                 
143                 public bool Checked {
144                         get { return _checked; }
145                         set { 
146                                 if( _checked != value) {
147                                         CheckState = (value) ? CheckState.Checked : CheckState.Unchecked;
148                                 }
149                         }
150                 }
151                 
152                 public CheckState CheckState {
153                         get { return checkState; }
154                         set { 
155                                 if( checkState != value) {
156
157                                         checkState = value; 
158                                         bool oldChecked = _checked;
159
160                                         if( checkState == CheckState.Unchecked) {
161                                                 _checked = false;
162                                         }
163                                         else {
164                                                 _checked = true;
165                                         }
166
167                                         if( oldChecked != _checked) { 
168                                                 OnCheckedChanged(new EventArgs());
169                                         }
170
171                                         OnCheckStateChanged(new EventArgs());
172                                 }
173                         }
174                 }
175                 
176                 [MonoTODO]
177                 protected override CreateParams CreateParams {
178                         get {
179                                 CreateParams createParams = base.CreateParams;
180         
181                                 createParams.ClassName = "BUTTON";
182
183                                 createParams.Style = (int) (
184                                         (int)WindowStyles.WS_CHILD | 
185                                         (int)WindowStyles.WS_VISIBLE | 
186                                         (int)ButtonStyles.BS_CHECKBOX |
187                                         (int)ButtonStyles.BS_NOTIFY |
188                                         (int)WindowStyles.WS_CLIPSIBLINGS |
189                                         (int)WindowStyles.WS_CLIPCHILDREN |
190                                         (int)WindowStyles.WS_TABSTOP |
191                                         (int)SS_Static_Control_Types.SS_LEFT );
192
193                                 if (autoCheck) {
194                                         createParams.Style |= (int)ButtonStyles.BS_AUTOCHECKBOX;
195                                 }
196
197                                 /* We need this, we draw ourselves */
198                                 createParams.Style |= (int) ButtonStyles.BS_OWNERDRAW;
199
200                                 return createParams;
201                         }
202                 }
203                 
204                 [MonoTODO]
205                 protected override Size DefaultSize {
206                         get { return new Size(100,checkMarkSize); }
207                 }
208                 
209                 [MonoTODO]
210                 public override ContentAlignment TextAlign {
211                         get {
212                                 return textAlign;
213                         }
214                         set {
215                                 textAlign = value;
216                                 UpdateCheckbox();
217                         }
218                 }
219                 
220                 public bool ThreeState {
221                         get {
222                                 return threeState;
223                         }
224
225                         set {
226                                 threeState = value;
227                         }
228                 }       
229                 
230                 // --- CheckBox methods ---
231
232                 protected override AccessibleObject CreateAccessibilityInstance() 
233                 {
234                         throw new NotImplementedException ();
235                 }
236                 
237                 
238                 // [event methods]
239                 [MonoTODO]
240                 protected virtual void OnAppearanceChanged(EventArgs e) 
241                 {
242                         if (AppearanceChanged != null) {
243                                 AppearanceChanged(this, e);
244                         }
245                 }
246                 
247                 [MonoTODO]
248                 protected virtual void OnCheckedChanged(EventArgs e) 
249                 {
250                         //FIXME:
251                         if(CheckedChanged != null) {
252                                 CheckedChanged( this, e);
253                         }
254                 }
255                 
256                 [MonoTODO]
257                 protected virtual void OnCheckStateChanged(EventArgs e) 
258                 {
259                         //FIXME:
260                         if(CheckStateChanged != null) {
261                                 CheckStateChanged( this, e);
262                         }
263                 }
264                 
265                 [MonoTODO]
266                 protected override void OnClick(EventArgs e) 
267                 {
268                         CheckState = (CheckState)Win32.SendMessage(Handle, (int)ButtonMessages.BM_GETCHECK, 0, 0);
269                         base.OnClick(e);
270                 }
271                 
272                 [MonoTODO]
273                 protected override void OnHandleCreated(EventArgs e) 
274                 {
275                         //FIXME:
276                         base.OnHandleCreated(e);
277                         Win32.SendMessage(Handle, (int)ButtonMessages.BM_SETCHECK, (int)checkState, 0);
278                 }
279                 
280 //              protected override void OnMouseDown (MouseEventArgs e) 
281 //              {
282 //                      base.OnMouseDown (e);
283 //              }
284                 
285                 [MonoTODO]
286                 protected override void OnMouseUp(MouseEventArgs mevent) 
287                 {
288                         if (ThreeState) {
289                                 switch (CheckState) {
290                                         case CheckState.Unchecked: {
291                                                 CheckState = CheckState.Checked;
292                                                 break;
293                                         }
294
295                                         case CheckState.Indeterminate: {
296                                                 CheckState = CheckState.Unchecked;
297                                                 break;
298                                         }
299
300                                         case CheckState.Checked: {
301                                                 CheckState = CheckState.Indeterminate;
302                                                 break;
303                                         }
304                                 }
305                         } else {
306                                 Checked = Checked ? false : true;
307                         }
308                         CheckboxRedraw();
309                         Invalidate();
310                         base.OnMouseUp(mevent);
311                 }
312                 // end of [event methods]
313                 
314                 
315                 [MonoTODO]
316                 protected override bool ProcessMnemonic(char charCode) 
317                 {
318                         //FIXME:
319                         return base.ProcessMnemonic(charCode);
320                 }
321                 
322                 [MonoTODO]
323                 //FIXME: do a better tostring
324                 public override string ToString() 
325                 {
326                         if (Checked) {
327                                 return "CheckBox" + " Checked";
328                         } else {
329                                 return "CheckBox" +  " Unchecked";
330                         }
331                 }
332                 
333                 internal override void ButtonPaint (PaintEventArgs e) 
334                 {
335                         if (canvasBmp!=null) {
336                                 e.Graphics.DrawImage(canvasBmp, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
337                         }
338                 }
339                 
340                 /// --- CheckBox events ---
341                 public event EventHandler AppearanceChanged;
342                 public event EventHandler CheckedChanged;
343                 public event EventHandler CheckStateChanged;
344                 
345                 /// --- public class CheckBox.CheckBoxAccessibleObject : AccessibleObject ---
346                 /// the class is only used for .NET framework
347                 /// 
348                 public class CheckBoxAccessibleObject : AccessibleObject {
349                 }
350
351                 private void UpdateCheckbox() {
352                         /* Calculate the position of text and checkbox rectangle */
353                         if (appearance!=Appearance.Button) {
354                                 switch(checkAlign) {
355                                         case ContentAlignment.BottomCenter: {
356                                                 if (ClientRectangle.Height<checkMarkSize*2) {
357                                                         ClientSize=new Size(ClientRectangle.Width, checkMarkSize*2);
358                                                 }
359                                                 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
360                                                 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
361                                                 textRect.X=ClientRectangle.X;
362                                                 textRect.Width=ClientRectangle.Width;
363                                                 break;
364                                         }
365
366                                         case ContentAlignment.BottomLeft: {
367                                                 checkRect.X=ClientRectangle.Left;
368                                                 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
369                                                 textRect.X=ClientRectangle.X+checkMarkSize;
370                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
371                                                 break;
372                                         }
373
374                                         case ContentAlignment.BottomRight: {
375                                                 checkRect.X=ClientRectangle.Right-checkMarkSize;
376                                                 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
377                                                 textRect.X=ClientRectangle.X;
378                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
379                                                 break;
380                                         }
381
382                                         case ContentAlignment.MiddleCenter: {
383                                                 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
384                                                 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
385                                                 textRect.X=ClientRectangle.X;
386                                                 textRect.Width=ClientRectangle.Width;
387                                                 break;
388                                         }
389
390                                         default:
391                                         case ContentAlignment.MiddleLeft: {
392                                                 checkRect.X=ClientRectangle.Left;
393                                                 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
394                                                 textRect.X=ClientRectangle.X+checkMarkSize;
395                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
396                                                 break;
397                                         }
398
399                                         case ContentAlignment.MiddleRight: {
400                                                 checkRect.X=ClientRectangle.Right-checkMarkSize;
401                                                 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
402                                                 textRect.X=ClientRectangle.X;
403                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
404                                                 break;
405                                         }
406
407                                         case ContentAlignment.TopCenter: {
408                                                 if (ClientRectangle.Height<checkMarkSize*2) {
409                                                         ClientSize=new Size(ClientRectangle.Width, checkMarkSize*2);
410                                                 }
411                                                 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
412                                                 checkRect.Y=ClientRectangle.Top;
413                                                 textRect.X=ClientRectangle.X;
414                                                 textRect.Y=checkMarkSize;
415                                                 textRect.Width=ClientRectangle.Width;
416                                                 textRect.Height=ClientRectangle.Height-checkMarkSize;
417                                                 break;
418                                         }
419
420                                         case ContentAlignment.TopLeft: {
421                                                 checkRect.X=ClientRectangle.Left;
422                                                 checkRect.Y=ClientRectangle.Top;
423                                                 textRect.X=ClientRectangle.X+checkMarkSize;
424                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
425                                                 break;
426                                         }
427
428                                         case ContentAlignment.TopRight: {
429                                                 checkRect.X=ClientRectangle.Right-checkMarkSize;
430                                                 checkRect.Y=ClientRectangle.Top;
431                                                 textRect.X=ClientRectangle.X;
432                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
433                                                 break;
434                                         }
435                                 }
436                         } else {
437                                 textRect.X=ClientRectangle.X;
438                                 textRect.Width=ClientRectangle.Width;
439                         }
440
441                         /* Set the horizontal alignment of our text */
442                         switch(textAlign) {
443                                 case ContentAlignment.BottomLeft:
444                                 case ContentAlignment.MiddleLeft:
445                                 case ContentAlignment.TopLeft: {
446                                         textFormat.Alignment=StringAlignment.Near;
447                                         break;
448                                 }
449
450                                 case ContentAlignment.BottomCenter:
451                                 case ContentAlignment.MiddleCenter:
452                                 case ContentAlignment.TopCenter: {
453                                         textFormat.Alignment=StringAlignment.Center;
454                                         break;
455                                 }
456
457                                 case ContentAlignment.BottomRight:
458                                 case ContentAlignment.MiddleRight:
459                                 case ContentAlignment.TopRight: {
460                                         textFormat.Alignment=StringAlignment.Far;
461                                         break;
462                                 }
463                         }
464
465                         /* Set the vertical alignment of our text */
466                         switch(textAlign) {
467                                 case ContentAlignment.TopLeft: 
468                                 case ContentAlignment.TopCenter: 
469                                 case ContentAlignment.TopRight: {
470                                         textFormat.LineAlignment=StringAlignment.Near;
471                                         break;
472                                 }
473
474                                 case ContentAlignment.BottomLeft:
475                                 case ContentAlignment.BottomCenter:
476                                 case ContentAlignment.BottomRight: {
477                                         textFormat.LineAlignment=StringAlignment.Far;
478                                         break;
479                                 }
480
481                                 case ContentAlignment.MiddleLeft:
482                                 case ContentAlignment.MiddleCenter:
483                                 case ContentAlignment.MiddleRight: {
484                                         textFormat.LineAlignment=StringAlignment.Center;
485                                         break;
486                                 }
487                         }
488                         CheckboxRedraw();
489                         Invalidate();
490                 }
491
492                 private void CheckboxRedraw() {
493                         SolidBrush      sb;
494
495                         /* Build the image representing the control */
496
497                         if (canvasDC!=null) {
498                                 canvasDC.Dispose();
499                         }
500                         if (canvasBmp!=null) {
501                                 canvasBmp.Dispose();
502                         }
503
504                         if (ClientRectangle.Width<1 || ClientRectangle.Height<1) {
505                                 return;
506                         }
507                         canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
508                         canvasDC = Graphics.FromImage(canvasBmp);
509
510                         sb=new SolidBrush(BackColor);
511                         canvasDC.FillRectangle(sb, ClientRectangle);
512                         sb.Dispose();
513
514                         ButtonState state = ButtonState.Normal;
515                         if (FlatStyle == FlatStyle.Flat) {
516                                 state |= ButtonState.Flat;
517                         }
518                         
519                         if (Checked) {
520                                 state |= ButtonState.Checked;
521                         }
522                         
523                         if (ThreeState && (CheckState == CheckState.Indeterminate)) {
524                                 state |= ButtonState.Checked;
525                                 state |= ButtonState.Pushed;
526                         }
527
528                         if (appearance!=Appearance.Button) {
529                                 ControlPaint.DrawCheckBox(canvasDC, checkRect, state);
530                         } else {
531                                 ControlPaint.DrawButton(canvasDC, textRect, state);
532                         }
533
534                         /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
535                         sb=new SolidBrush(base.foreColor);
536                         canvasDC.DrawString(Text, Font, sb, textRect, textFormat);
537                         sb.Dispose();
538
539                         if (Focused) {
540                                 ControlPaint.DrawFocusRectangle(canvasDC, textRect);
541                         }
542                 }
543
544                 private void CheckboxUpdate(object sender, System.EventArgs e) {
545                         /* Force recalculation of text & checkbox rectangles */
546                         UpdateCheckbox();
547                 }
548
549                 private void CheckboxSizeChanged(object sender, System.EventArgs e)
550                 {
551                         /* Force recalculation of text & checkbox rectangles */
552                         textRect.Y=ClientRectangle.Y;
553                         textRect.Height=ClientRectangle.Height;
554                         UpdateCheckbox();
555                 }
556         }
557
558
559 }