- Updated to fix broken build. Not complete yet.
[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.2 $
28 // $Modtime: $
29 // $Log: CheckBox.cs,v $
30 // Revision 1.2  2004/08/30 15:44:20  pbartok
31 // - Updated to fix broken build. Not complete yet.
32 //
33 // Revision 1.1  2004/07/09 05:21:25  pbartok
34 // - Initial check-in
35 //
36 //
37
38 // NOT COMPLETE
39
40 using System;
41 using System.Drawing;
42
43 namespace System.Windows.Forms {
44         public class CheckBox : ButtonBase {
45                 private Appearance              appearance;
46                 private bool                    auto_check;
47                 private ContentAlignment        check_alignment;
48                 private ContentAlignment        text_alignment;
49                 private CheckState              check_state;
50                 private bool                    three_state;
51
52                 #region Public Constructors
53                 public CheckBox() {
54                         appearance = Appearance.Normal;
55                         auto_check = true;
56                         check_alignment = ContentAlignment.MiddleLeft;
57                 }
58                 #endregion      // Public Constructors
59
60                 #region Public Instance Properties
61                 public Appearance Appearance {
62                         get {
63                                 return appearance;
64                         }
65
66                         set {
67                                 if (value != appearance) {
68                                         value = appearance;
69                                         if (AppearanceChanged != null) {
70                                                 AppearanceChanged(this, EventArgs.Empty);
71                                         }
72                                 }
73                         }
74                 }
75
76                 public bool AutoCheck {
77                         get {
78                                 return auto_check;
79                         }
80
81                         set {
82                                 auto_check = value;
83                         }
84                 }
85
86                 public ContentAlignment CheckAlign {
87                         get {
88                                 return check_alignment;
89                         }
90
91                         set {
92                                 if (value != check_alignment) {
93                                         check_alignment = value;
94
95                                         Redraw();
96                                 }
97                         }
98                 }
99
100                 public bool Checked {
101                         get {
102                                 if (check_state != CheckState.Unchecked) {
103                                         return true;
104                                 }
105                                 return false;
106                         }
107
108                         set {
109                                 if (value && (check_state != CheckState.Checked)) {
110                                         check_state = CheckState.Checked;
111                                         Redraw();
112                                         OnCheckedChanged(EventArgs.Empty);
113                                 } else if (!value && (check_state != CheckState.Unchecked)) {
114                                         check_state = CheckState.Unchecked;
115                                         Redraw();
116                                         OnCheckedChanged(EventArgs.Empty);
117                                 }
118                         }
119                 }
120
121                 public CheckState CheckState {
122                         get {
123                                 return check_state;
124                         }
125
126                         set {
127                                 if (value != check_state) {
128                                         bool    was_checked = (check_state != CheckState.Unchecked);
129
130                                         check_state = value;
131
132                                         if (was_checked != (check_state != CheckState.Unchecked)) {
133                                                 OnCheckedChanged(EventArgs.Empty);
134                                         }
135
136                                         OnCheckStateChanged(EventArgs.Empty);
137                                         Redraw();
138                                 }
139                         }
140                 }
141
142                 public override ContentAlignment TextAlign {
143                         get {
144                                 return text_alignment;
145                         }
146
147                         set {
148                                 if (value != text_alignment) {
149                                         text_alignment = value;
150                                         Redraw();
151                                 }
152                         }
153                 }
154
155
156                 public bool ThreeState {
157                         get {
158                                 return three_state;
159                         }
160
161                         set {
162                                 three_state = value;
163                         }
164                 }
165                 #endregion      // Public Instance Properties
166
167                 #region Protected Instance Properties
168                 protected override CreateParams CreateParams {
169                         get {
170                                 return base.CreateParams;
171                         }
172                 }
173
174                 protected override Size DefaultSize {
175                         get {
176                                 return new Size(104, 24);
177                         }
178                 }
179                 #endregion      // Protected Instance Properties
180
181                 #region Public Instance Methods
182                 public override string ToString() {
183                         if (CheckState == CheckState.Unchecked) {
184                                 return "CheckBox (unchecked)";
185                         } else if (CheckState == CheckState.Checked) {
186                                 return "CheckBox (checked)";
187                         } else {
188                                 return "CheckBox (state indeterminate)";
189                         }
190                 }
191                 #endregion      // Public Instance Methods
192
193                 #region Protected Instance Methods
194                 protected override AccessibleObject CreateAccessibilityInstance() {
195                         return base.CreateAccessibilityInstance ();
196                 }
197
198                 protected virtual void OnAppearanceChanged(EventArgs e) {
199                         if (AppearanceChanged != null) {
200                                 AppearanceChanged(this, e);
201                         }
202                 }
203
204                 protected virtual void OnCheckedChanged(EventArgs e) {
205 Console.WriteLine("Checked changed");
206                         if (CheckedChanged != null) {
207                                 CheckedChanged(this, e);
208                         }
209                 }
210
211                 protected virtual void OnCheckStateChanged(EventArgs e) {
212 Console.WriteLine("CheckState changed");
213                         if (CheckStateChanged != null) {
214                                 CheckStateChanged(this, e);
215                         }
216                 }
217
218                 protected override void OnClick(EventArgs e) {
219 Console.WriteLine("Got click");
220                         base.OnClick (e);
221                 }
222
223                 protected override void OnHandleCreated(EventArgs e) {
224                         base.OnHandleCreated (e);
225                 }
226
227                 protected override void OnMouseUp(MouseEventArgs e) {
228                         base.OnMouseUp (e);
229                 }
230
231                 protected override bool ProcessMnemonic(char charCode) {
232                         return base.ProcessMnemonic (charCode);
233                 }
234
235                 #endregion      // Protected Instance Methods
236
237                 #region Events
238                 public event EventHandler       AppearanceChanged;
239                 public event EventHandler       CheckedChanged;
240                 public event EventHandler       CheckStateChanged;
241                 #endregion      // Events
242         }
243 }
244 #if not
245         public class CheckBox : ButtonBase {
246
247                 // private fields
248                 Appearance                      appearance;
249                 bool                                    autoCheck;
250                 ContentAlignment        checkAlign;
251                 bool                                    _checked;
252                 CheckState                      checkState;
253                 bool                                    threeState;
254                 ContentAlignment        textAlign;
255                 Rectangle                       textRect;
256                 Rectangle                       checkRect;
257                 StringFormat            textFormat;
258                 int                                     checkMarkSize=13;               // Keep it configurable for accessability
259                 Graphics                                canvasDC;
260                 Bitmap                          canvasBmp;
261                 
262                 // --- Constructor ---
263                 public CheckBox() : base() 
264                 {
265
266                         appearance = Appearance.Normal;
267                         autoCheck = true;
268                         checkAlign = ContentAlignment.MiddleLeft;
269                         _checked = false;
270                         checkState = CheckState.Unchecked;
271                         threeState = false;
272
273                         canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
274                         canvasDC = Graphics.FromImage(canvasBmp);
275
276                         /* Set defaults for drawing text... */
277                         textAlign = ContentAlignment.MiddleLeft;
278                         textFormat = new StringFormat();
279                         textFormat.Alignment=StringAlignment.Near;
280                         textFormat.LineAlignment=StringAlignment.Center;
281                         textRect = ClientRectangle;
282                         textRect.X+=checkMarkSize;
283                         textRect.Width-=checkMarkSize;
284
285                         /* ... and for drawing our checkbox */
286                         checkRect.X=ClientRectangle.Left;
287                         checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
288                         checkRect.Width=checkMarkSize;
289                         checkRect.Height=checkMarkSize;
290
291                         SizeChanged+=new System.EventHandler(CheckboxSizeChanged);
292                         GotFocus+=new System.EventHandler(CheckboxUpdate);
293                         LostFocus+=new System.EventHandler(CheckboxUpdate);
294                         TextChanged+=new System.EventHandler(CheckboxUpdate);
295
296                         SubClassWndProc_ = true;
297                         SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
298                         callWinControlProcMask &= ~(CallWinControlProcMask.MOUSE_MESSAGES | CallWinControlProcMask.KEYBOARD_MESSAGES);
299                 }
300                 
301                 // --- CheckBox Properties ---
302         
303                 public CheckState CheckState {
304                         get { return checkState; }
305                         set { 
306                                 if( checkState != value) {
307
308                                         checkState = value; 
309                                         bool oldChecked = _checked;
310
311                                         if( checkState == CheckState.Unchecked) {
312                                                 _checked = false;
313                                         }
314                                         else {
315                                                 _checked = true;
316                                         }
317
318                                         if( oldChecked != _checked) { 
319                                                 OnCheckedChanged(new EventArgs());
320                                         }
321
322                                         OnCheckStateChanged(new EventArgs());
323                                 }
324                         }
325                 }
326                 
327                 [MonoTODO]
328                 protected override CreateParams CreateParams {
329                         get {
330                                 CreateParams createParams = base.CreateParams;
331         
332                                 createParams.ClassName = "BUTTON";
333
334                                 createParams.Style = (int) (
335                                         (int)WindowStyles.WS_CHILD | 
336                                         (int)WindowStyles.WS_VISIBLE | 
337                                         (int)ButtonStyles.BS_CHECKBOX |
338                                         (int)ButtonStyles.BS_NOTIFY |
339                                         (int)WindowStyles.WS_CLIPSIBLINGS |
340                                         (int)WindowStyles.WS_CLIPCHILDREN |
341                                         (int)WindowStyles.WS_TABSTOP |
342                                         (int)SS_Static_Control_Types.SS_LEFT );
343
344                                 if (autoCheck) {
345                                         createParams.Style |= (int)ButtonStyles.BS_AUTOCHECKBOX;
346                                 }
347
348                                 /* We need this, we draw ourselves */
349                                 createParams.Style |= (int) ButtonStyles.BS_OWNERDRAW;
350
351                                 return createParams;
352                         }
353                 }
354                 
355                 [MonoTODO]
356                 protected override Size DefaultSize {
357                         get { return new Size(100,checkMarkSize); }
358                 }
359                 
360                 [MonoTODO]
361                 public override ContentAlignment TextAlign {
362                         get {
363                                 return textAlign;
364                         }
365                         set {
366                                 textAlign = value;
367                                 UpdateCheckbox();
368                         }
369                 }
370                 
371                 public bool ThreeState {
372                         get {
373                                 return threeState;
374                         }
375
376                         set {
377                                 threeState = value;
378                         }
379                 }       
380                 
381                 // --- CheckBox methods ---
382
383                 protected override AccessibleObject CreateAccessibilityInstance() 
384                 {
385                         throw new NotImplementedException ();
386                 }
387                 
388                 
389                 // [event methods]
390                 [MonoTODO]
391                 protected virtual void OnAppearanceChanged(EventArgs e) 
392                 {
393                         if (AppearanceChanged != null) {
394                                 AppearanceChanged(this, e);
395                         }
396                 }
397                 
398                 [MonoTODO]
399                 protected virtual void OnCheckedChanged(EventArgs e) 
400                 {
401                         //FIXME:
402                         if(CheckedChanged != null) {
403                                 CheckedChanged( this, e);
404                         }
405                 }
406                 
407                 [MonoTODO]
408                 protected virtual void OnCheckStateChanged(EventArgs e) 
409                 {
410                         //FIXME:
411                         if(CheckStateChanged != null) {
412                                 CheckStateChanged( this, e);
413                         }
414                 }
415                 
416                 [MonoTODO]
417                 protected override void OnClick(EventArgs e) 
418                 {
419                         CheckState = (CheckState)Win32.SendMessage(Handle, (int)ButtonMessages.BM_GETCHECK, 0, 0);
420                         base.OnClick(e);
421                 }
422                 
423                 [MonoTODO]
424                 protected override void OnHandleCreated(EventArgs e) 
425                 {
426                         //FIXME:
427                         base.OnHandleCreated(e);
428                         Win32.SendMessage(Handle, (int)ButtonMessages.BM_SETCHECK, (int)checkState, 0);
429                 }
430                 
431 //              protected override void OnMouseDown (MouseEventArgs e) 
432 //              {
433 //                      base.OnMouseDown (e);
434 //              }
435                 
436                 [MonoTODO]
437                 protected override void OnMouseUp(MouseEventArgs mevent) 
438                 {
439                         if (ThreeState) {
440                                 switch (CheckState) {
441                                         case CheckState.Unchecked: {
442                                                 CheckState = CheckState.Checked;
443                                                 break;
444                                         }
445
446                                         case CheckState.Indeterminate: {
447                                                 CheckState = CheckState.Unchecked;
448                                                 break;
449                                         }
450
451                                         case CheckState.Checked: {
452                                                 CheckState = CheckState.Indeterminate;
453                                                 break;
454                                         }
455                                 }
456                         } else {
457                                 Checked = Checked ? false : true;
458                         }
459                         CheckboxRedraw();
460                         Invalidate();
461                         base.OnMouseUp(mevent);
462                 }
463                 // end of [event methods]
464                 
465                 
466                 [MonoTODO]
467                 protected override bool ProcessMnemonic(char charCode) 
468                 {
469                         //FIXME:
470                         return base.ProcessMnemonic(charCode);
471                 }
472                 
473                 [MonoTODO]
474                 //FIXME: do a better tostring
475                 public override string ToString() 
476                 {
477                         if (Checked) {
478                                 return "CheckBox" + " Checked";
479                         } else {
480                                 return "CheckBox" +  " Unchecked";
481                         }
482                 }
483                 
484                 internal override void ButtonPaint (PaintEventArgs e) 
485                 {
486                         if (canvasBmp!=null) {
487                                 e.Graphics.DrawImage(canvasBmp, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
488                         }
489                 }
490                 
491                 /// --- CheckBox events ---
492                 public event EventHandler AppearanceChanged;
493                 public event EventHandler CheckedChanged;
494                 public event EventHandler CheckStateChanged;
495                 
496                 /// --- public class CheckBox.CheckBoxAccessibleObject : AccessibleObject ---
497                 /// the class is only used for .NET framework
498                 /// 
499                 public class CheckBoxAccessibleObject : AccessibleObject {
500                 }
501
502                 private void UpdateCheckbox() {
503                         /* Calculate the position of text and checkbox rectangle */
504                         if (appearance!=Appearance.Button) {
505                                 switch(checkAlign) {
506                                         case ContentAlignment.BottomCenter: {
507                                                 if (ClientRectangle.Height<checkMarkSize*2) {
508                                                         ClientSize=new Size(ClientRectangle.Width, checkMarkSize*2);
509                                                 }
510                                                 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
511                                                 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
512                                                 textRect.X=ClientRectangle.X;
513                                                 textRect.Width=ClientRectangle.Width;
514                                                 break;
515                                         }
516
517                                         case ContentAlignment.BottomLeft: {
518                                                 checkRect.X=ClientRectangle.Left;
519                                                 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
520                                                 textRect.X=ClientRectangle.X+checkMarkSize;
521                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
522                                                 break;
523                                         }
524
525                                         case ContentAlignment.BottomRight: {
526                                                 checkRect.X=ClientRectangle.Right-checkMarkSize;
527                                                 checkRect.Y=ClientRectangle.Bottom-checkMarkSize;
528                                                 textRect.X=ClientRectangle.X;
529                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
530                                                 break;
531                                         }
532
533                                         case ContentAlignment.MiddleCenter: {
534                                                 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
535                                                 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
536                                                 textRect.X=ClientRectangle.X;
537                                                 textRect.Width=ClientRectangle.Width;
538                                                 break;
539                                         }
540
541                                         default:
542                                         case ContentAlignment.MiddleLeft: {
543                                                 checkRect.X=ClientRectangle.Left;
544                                                 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
545                                                 textRect.X=ClientRectangle.X+checkMarkSize;
546                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
547                                                 break;
548                                         }
549
550                                         case ContentAlignment.MiddleRight: {
551                                                 checkRect.X=ClientRectangle.Right-checkMarkSize;
552                                                 checkRect.Y=(ClientRectangle.Bottom-ClientRectangle.Top)/2-checkMarkSize/2;
553                                                 textRect.X=ClientRectangle.X;
554                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
555                                                 break;
556                                         }
557
558                                         case ContentAlignment.TopCenter: {
559                                                 if (ClientRectangle.Height<checkMarkSize*2) {
560                                                         ClientSize=new Size(ClientRectangle.Width, checkMarkSize*2);
561                                                 }
562                                                 checkRect.X=(ClientRectangle.Right-ClientRectangle.Left)/2-checkMarkSize/2;
563                                                 checkRect.Y=ClientRectangle.Top;
564                                                 textRect.X=ClientRectangle.X;
565                                                 textRect.Y=checkMarkSize;
566                                                 textRect.Width=ClientRectangle.Width;
567                                                 textRect.Height=ClientRectangle.Height-checkMarkSize;
568                                                 break;
569                                         }
570
571                                         case ContentAlignment.TopLeft: {
572                                                 checkRect.X=ClientRectangle.Left;
573                                                 checkRect.Y=ClientRectangle.Top;
574                                                 textRect.X=ClientRectangle.X+checkMarkSize;
575                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
576                                                 break;
577                                         }
578
579                                         case ContentAlignment.TopRight: {
580                                                 checkRect.X=ClientRectangle.Right-checkMarkSize;
581                                                 checkRect.Y=ClientRectangle.Top;
582                                                 textRect.X=ClientRectangle.X;
583                                                 textRect.Width=ClientRectangle.Width-checkMarkSize;
584                                                 break;
585                                         }
586                                 }
587                         } else {
588                                 textRect.X=ClientRectangle.X;
589                                 textRect.Width=ClientRectangle.Width;
590                         }
591
592                         /* Set the horizontal alignment of our text */
593                         switch(textAlign) {
594                                 case ContentAlignment.BottomLeft:
595                                 case ContentAlignment.MiddleLeft:
596                                 case ContentAlignment.TopLeft: {
597                                         textFormat.Alignment=StringAlignment.Near;
598                                         break;
599                                 }
600
601                                 case ContentAlignment.BottomCenter:
602                                 case ContentAlignment.MiddleCenter:
603                                 case ContentAlignment.TopCenter: {
604                                         textFormat.Alignment=StringAlignment.Center;
605                                         break;
606                                 }
607
608                                 case ContentAlignment.BottomRight:
609                                 case ContentAlignment.MiddleRight:
610                                 case ContentAlignment.TopRight: {
611                                         textFormat.Alignment=StringAlignment.Far;
612                                         break;
613                                 }
614                         }
615
616                         /* Set the vertical alignment of our text */
617                         switch(textAlign) {
618                                 case ContentAlignment.TopLeft: 
619                                 case ContentAlignment.TopCenter: 
620                                 case ContentAlignment.TopRight: {
621                                         textFormat.LineAlignment=StringAlignment.Near;
622                                         break;
623                                 }
624
625                                 case ContentAlignment.BottomLeft:
626                                 case ContentAlignment.BottomCenter:
627                                 case ContentAlignment.BottomRight: {
628                                         textFormat.LineAlignment=StringAlignment.Far;
629                                         break;
630                                 }
631
632                                 case ContentAlignment.MiddleLeft:
633                                 case ContentAlignment.MiddleCenter:
634                                 case ContentAlignment.MiddleRight: {
635                                         textFormat.LineAlignment=StringAlignment.Center;
636                                         break;
637                                 }
638                         }
639                         CheckboxRedraw();
640                         Invalidate();
641                 }
642
643                 private void CheckboxRedraw() {
644                         SolidBrush      sb;
645
646                         /* Build the image representing the control */
647
648                         if (canvasDC!=null) {
649                                 canvasDC.Dispose();
650                         }
651                         if (canvasBmp!=null) {
652                                 canvasBmp.Dispose();
653                         }
654
655                         if (ClientRectangle.Width<1 || ClientRectangle.Height<1) {
656                                 return;
657                         }
658                         canvasBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
659                         canvasDC = Graphics.FromImage(canvasBmp);
660
661                         sb=new SolidBrush(BackColor);
662                         canvasDC.FillRectangle(sb, ClientRectangle);
663                         sb.Dispose();
664
665                         ButtonState state = ButtonState.Normal;
666                         if (FlatStyle == FlatStyle.Flat) {
667                                 state |= ButtonState.Flat;
668                         }
669                         
670                         if (Checked) {
671                                 state |= ButtonState.Checked;
672                         }
673                         
674                         if (ThreeState && (CheckState == CheckState.Indeterminate)) {
675                                 state |= ButtonState.Checked;
676                                 state |= ButtonState.Pushed;
677                         }
678
679                         if (appearance!=Appearance.Button) {
680                                 ControlPaint.DrawCheckBox(canvasDC, checkRect, state);
681                         } else {
682                                 ControlPaint.DrawButton(canvasDC, textRect, state);
683                         }
684
685                         /* Place the text; to be compatible with Windows place it after the checkbox has been drawn */
686                         sb=new SolidBrush(base.foreColor);
687                         canvasDC.DrawString(Text, Font, sb, textRect, textFormat);
688                         sb.Dispose();
689
690                         if (Focused) {
691                                 ControlPaint.DrawFocusRectangle(canvasDC, textRect);
692                         }
693                 }
694
695                 private void CheckboxUpdate(object sender, System.EventArgs e) {
696                         /* Force recalculation of text & checkbox rectangles */
697                         UpdateCheckbox();
698                 }
699
700                 private void CheckboxSizeChanged(object sender, System.EventArgs e)
701                 {
702                         /* Force recalculation of text & checkbox rectangles */
703                         textRect.Y=ClientRectangle.Y;
704                         textRect.Height=ClientRectangle.Height;
705                         UpdateCheckbox();
706                 }
707         }
708
709
710 }
711 #endif