/*
* CheckBox.cs - Implementation of the
* "System.Windows.Forms.CheckBox" class.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* Contributions from Simon Guindon
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.ComponentModel;
using System.Windows.Forms;
namespace System.Windows.Forms
{
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultProperty("Checked")]
[DefaultEvent("CheckedChanged")]
#endif
public class CheckBox : ButtonBase
{
// Internal result.
private Appearance appearance;
private ContentAlignment checkAlign;
private bool autoCheck;
private bool threeState;
private CheckState state;
private const int normalCheckSize = 13;
private const int flatCheckSize = 13;
// Contructor.
public CheckBox()
{
Appearance = Appearance.Normal;
checkAlign = ContentAlignment.MiddleLeft;
TextAlign = ContentAlignment.MiddleLeft;
autoCheck = true;
SetStyle(ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, false);
}
// Calculate the current state of the button for its visual appearance.
internal override ButtonState CalculateState()
{
ButtonState checkState;
if(state == CheckState.Unchecked)
{
checkState = ButtonState.Normal;
}
else if(state == CheckState.Checked)
{
checkState = ButtonState.Checked;
}
else //state == CheckState.Indeterminate
{
// Special flag for "IThemePainter.DrawCheckBox".
checkState = ButtonState.Checked | (ButtonState)0x10000;
}
if(pressed && entered)
{
checkState |= ButtonState.Pushed;
}
if(!Enabled)
{
checkState |= ButtonState.Inactive;
}
if(FlatStyle == FlatStyle.Flat)
{
checkState |= ButtonState.Flat;
}
if(hasFocus)
{
// Special flag that indicates a focus rectangle.
checkState |= (ButtonState)0x20000;
}
return checkState;
}
// Draw the contents of this check box.
internal override void Draw(Graphics graphics)
{
DrawBox(graphics);
DrawText(graphics);
}
private void DrawBox(Graphics graphics)
{
int checkX = 0;
int checkY = 0;
int checkSize;
if(FlatStyle == FlatStyle.Flat)
{
checkSize = flatCheckSize;
}
else
{
checkSize = normalCheckSize;
}
switch (checkAlign)
{
case ContentAlignment.BottomCenter:
checkX = (Width / 2) - (checkSize / 2);
checkY = Height - checkSize - 1;
break;
case ContentAlignment.BottomLeft:
checkX = 0;
checkY = Height - checkSize - 1;
break;
case ContentAlignment.BottomRight:
checkX = Width - checkSize - 1;
checkY = Height - checkSize - 1;
break;
case ContentAlignment.MiddleCenter:
checkX = (Width / 2) - (checkSize / 2);
checkY = (Height / 2) - (checkSize / 2);
break;
case ContentAlignment.MiddleLeft:
checkX = 0;
checkY = (Height / 2) - (checkSize / 2);
break;
case ContentAlignment.MiddleRight:
checkX = Width - checkSize - 1;
checkY = (Height / 2) - (checkSize / 2);
break;
case ContentAlignment.TopCenter:
checkX = (Width / 2) - (checkSize / 2);
checkY = 0;
break;
case ContentAlignment.TopLeft:
checkX = 0;
checkY = 0;
break;
case ContentAlignment.TopRight:
checkX = Width - checkSize - 1;
checkY = 0;
break;
}
ButtonState checkState = CalculateState();
ControlPaint.DrawCheckBox
(graphics, checkX, checkY,
checkSize, checkSize, checkState);
}
private void DrawText(Graphics graphics)
{
int x = 0;
int y = 2;
int width = Width - 2;
int height = Height - 4;
int checkSize;
if(FlatStyle == FlatStyle.Flat)
{
checkSize = flatCheckSize;
}
else
{
checkSize = normalCheckSize;
}
SizeF textSize = graphics.MeasureString(Text, Font);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Near;
format.LineAlignment = StringAlignment.Far;
format.HotkeyPrefix = HotkeyPrefix.Show;
switch (checkAlign)
{
case ContentAlignment.BottomCenter:
height = 2;
break;
case ContentAlignment.BottomLeft:
x = checkSize + 3;
width -= x;
break;
case ContentAlignment.BottomRight:
width -= checkSize;
break;
case ContentAlignment.MiddleCenter:
break;
case ContentAlignment.MiddleLeft:
x = checkSize + 3;
width -= x;
break;
case ContentAlignment.MiddleRight:
x = checkSize + 3;
width -= x;
break;
case ContentAlignment.TopCenter:
y = checkSize + 3;
height -= y - 2;
break;
case ContentAlignment.TopLeft:
x = checkSize + 3;
width -= x;
break;
case ContentAlignment.TopRight:
width -= checkSize;
break;
}
switch (TextAlign)
{
case ContentAlignment.BottomCenter:
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Far;
break;
case ContentAlignment.BottomLeft:
format.Alignment = StringAlignment.Near;
format.LineAlignment = StringAlignment.Far;
break;
case ContentAlignment.BottomRight:
format.Alignment = StringAlignment.Far;
format.LineAlignment = StringAlignment.Far;
break;
case ContentAlignment.MiddleCenter:
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
break;
case ContentAlignment.MiddleLeft:
format.LineAlignment = StringAlignment.Center;
break;
case ContentAlignment.MiddleRight:
format.Alignment = StringAlignment.Far;
format.LineAlignment = StringAlignment.Center;
break;
case ContentAlignment.TopCenter:
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Near;
break;
case ContentAlignment.TopLeft:
format.Alignment = StringAlignment.Near;
format.LineAlignment = StringAlignment.Near;
break;
case ContentAlignment.TopRight:
format.Alignment = StringAlignment.Far;
format.LineAlignment = StringAlignment.Near;
break;
}
RectangleF rect = new RectangleF(x, y, width, height);
String text = Text;
Font font = Font;
if((TextAlign & (ContentAlignment.MiddleLeft |
ContentAlignment.MiddleCenter |
ContentAlignment.MiddleRight)) != 0)
{
rect.Offset(0.0f, GetDescent(graphics, font) / 2.0f);
}
if(text != null && text != String.Empty)
{
if(Enabled)
{
Brush brush = new SolidBrush(ForeColor);
graphics.DrawString(text, font, brush, rect, format);
brush.Dispose();
}
else
{
ControlPaint.DrawStringDisabled
(graphics, text, font, BackColor, rect, format);
}
}
}
// Gets or sets the check box appearance.
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(Appearance.Normal)]
#endif
#if CONFIG_COMPONENT_MODEL
[Localizable(true)]
#endif
public Appearance Appearance
{
get
{
return appearance;
}
set
{
if(appearance != value)
{
appearance = value;
Redraw();
OnAppearanceChanged(EventArgs.Empty);
}
}
}
// Get or set the "auto check" style for this check box.
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(true)]
#endif
public bool AutoCheck
{
get
{
return autoCheck;
}
set
{
autoCheck = value;
}
}
// Gets or set alignment of a check box on a check box control.
#if CONFIG_COMPONENT_MODEL
[Localizable(true)]
#endif
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(ContentAlignment.MiddleLeft)]
#endif
public ContentAlignment CheckAlign
{
get
{
return checkAlign;
}
set
{
if(checkAlign != value)
{
checkAlign = value;
Invalidate();
}
}
}
// Get or set the checked state as a simple boolean value.
#if CONFIG_COMPONENT_MODEL
[Bindable(true)]
[RefreshProperties(RefreshProperties.All)]
#endif
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(false)]
#endif
public bool Checked
{
get
{
return (CheckState != CheckState.Unchecked);
}
set
{
if(value)
{
CheckState = CheckState.Checked;
}
else
{
CheckState = CheckState.Unchecked;
}
}
}
// Get or set the check box state.
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(CheckState.Unchecked)]
#endif
#if CONFIG_COMPONENT_MODEL
[RefreshProperties(RefreshProperties.All)]
[Bindable(true)]
#endif
public CheckState CheckState
{
get
{
return state;
}
set
{
if(state != value)
{
bool checkedBefore = (state != CheckState.Unchecked);
state = value;
bool checkedAfter = (state != CheckState.Unchecked);
RedrawIfChanged();
if(checkedBefore != checkedAfter)
{
OnCheckedChanged(EventArgs.Empty);
}
OnCheckStateChanged(EventArgs.Empty);
}
}
}
// Gets or sets the site of the control.
#if CONFIG_COMPONENT_MODEL
public override ISite Site
{
get
{
return base.Site;
}
set
{
base.Site = value;
}
}
#endif
// Gets or sets the alignment of the text on the checkbox control.
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(ContentAlignment.MiddleLeft)]
#endif
#if CONFIG_COMPONENT_MODEL
[Localizable(true)]
#endif
public override ContentAlignment TextAlign
{
get
{
return base.TextAlign;
}
set
{
base.TextAlign = value;
Invalidate();
}
}
// Get or set the "three state" style for this check box.
#if CONFIG_COMPONENT_MODEL || CONFIG_EXTENDED_DIAGNOSTICS
[DefaultValue(false)]
#endif
public bool ThreeState
{
get
{
return threeState;
}
set
{
threeState = value;
}
}
// Occurs when the value of the Appearance property changes.
public event EventHandler AppearanceChanged
{
add
{
AddHandler(EventId.AppearanceChanged, value);
}
remove
{
RemoveHandler(EventId.AppearanceChanged, value);
}
}
// Occurs when the value of the Checked property changes.
public event EventHandler CheckedChanged
{
add
{
AddHandler(EventId.CheckedChanged, value);
}
remove
{
RemoveHandler(EventId.CheckedChanged, value);
}
}
// Event that is emitted when the check state changes.
public event EventHandler CheckStateChanged
{
add
{
AddHandler(EventId.CheckStateChanged, value);
}
remove
{
RemoveHandler(EventId.CheckStateChanged, value);
}
}
// Gets the required creation parameters when the control handle is created.
protected override CreateParams CreateParams
{
get
{
return base.CreateParams;
}
}
// Gets the default size of the control.
protected override Size DefaultSize
{
get
{
return new Size(104, 24);
}
}
// Create an accessibility object.
protected override AccessibleObject CreateAccessibilityInstance()
{
return base.CreateAccessibilityInstance();
}
// Raises the AppearanceChanged event.
protected virtual void OnAppearanceChanged(EventArgs e)
{
EventHandler handler;
handler = (EventHandler)(GetHandler(EventId.AppearanceChanged));
if(handler != null)
{
handler(this, e);
}
}
// Raises the CheckedChanged event.
protected virtual void OnCheckedChanged(EventArgs e)
{
EventHandler handler;
handler = (EventHandler)(GetHandler(EventId.CheckedChanged));
if(handler != null)
{
handler(this, e);
}
}
// Emit the CheckStateChanged event.
protected virtual void OnCheckStateChanged(EventArgs e)
{
EventHandler handler;
handler = (EventHandler)(GetHandler(EventId.CheckStateChanged));
if(handler != null)
{
handler(this, e);
}
}
// Raises the Click event.
protected override void OnClick(EventArgs e)
{
if(autoCheck)
{
CheckState newState;
if(state == CheckState.Unchecked)
{
newState = CheckState.Checked;
}
else if(state == CheckState.Checked)
{
if(threeState)
{
newState = CheckState.Indeterminate;
}
else
{
newState = CheckState.Unchecked;
}
}
else
{
newState = CheckState.Unchecked;
}
CheckState = newState;
}
base.OnClick(e);
}
// Raises the HandleCreated event.
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
}
// Raises the MouseUp event.
protected override void OnMouseUp(MouseEventArgs mevent)
{
if(button == mevent.Button)
{
bool clicked = (entered && pressed);
base.OnMouseUp(mevent);
if(clicked)
{
OnClick(EventArgs.Empty);
}
}
else
{
base.OnMouseUp(mevent);
}
}
// Processes a mnemonic character.
protected override bool ProcessMnemonic(char charCode)
{
if(IsMnemonic(charCode, Text))
{
if(CanSelect)
{
OnClick(EventArgs.Empty);
return true;
}
}
return false;
}
public override String ToString()
{
return base.ToString() + ", CheckState: " +
(state == CheckState.Unchecked ? "0" : "1");
}
}; // class CheckBox
}; // namespace System.Windows.Forms