using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace Core.Mes.ClientFrameWork
{
public partial class BusyControl : UserControl
{
#region Constants
private const int DEFAULT_INTERVAL = 60;
private readonly Color DEFAULT_TICK_COLOR = Color.FromArgb(58, 58, 58);
private const int DEFAULT_TICK_WIDTH = 2;
private const int MINIMUM_INNER_RADIUS = 4;
private const int MINIMUM_OUTER_RADIUS = 8;
private Size MINIMUM_CONTROL_SIZE = new Size(28, 28);
private const int MINIMUM_PEN_WIDTH = 2;
#endregion
#region Enums
public enum Direction
{
CLOCKWISE,
ANTICLOCKWISE
}
#endregion
#region Members
private int m_Interval;
Pen m_Pen = null;
PointF m_CentrePt = new PointF();
int m_InnerRadius = 0;
int m_OuterRadius = 0;
int m_StartAngle = 0;
int m_AlphaStartValue = 0;
int m_SpokesCount = 0;
int m_AngleIncrement = 0;
int m_AlphaDecrement = 0;
Timer m_Timer = null;
#endregion
#region Properties
///
/// Time interval for each tick.
///
public int Interval
{
get
{
return m_Interval;
}
set
{
if (value > 0)
{
m_Interval = value;
}
else
{
m_Interval = DEFAULT_INTERVAL;
}
}
}
private Color m_TickColor;
///
/// Color of the tick
///
public Color TickColor
{
get { return m_TickColor; }
set { m_TickColor = value; }
}
private Direction m_Rotation;
///
/// Direction of rotation - CLOCKWISE/ANTICLOCKWISE
///
public Direction Rotation
{
get { return m_Rotation; }
set { m_Rotation = value; }
}
///
/// Angle at which the tick should start
///
public int StartAngle
{
get
{
return m_StartAngle;
}
set
{
m_StartAngle = value;
}
}
#endregion
#region Construction/Initialization
///
/// Ctor
///
public BusyControl()
{
this.DoubleBuffered = true;
InitializeComponent();
this.BackColor = Color.Transparent;
this.TickColor = DEFAULT_TICK_COLOR;
this.MinimumSize = MINIMUM_CONTROL_SIZE;
this.Interval = DEFAULT_INTERVAL;
// Default rotation direction is clockwise
this.Rotation = Direction.CLOCKWISE;
// Default starting angle is 12 o'clock
this.StartAngle = 270;
// Default number of Spokes in this control is 12
m_SpokesCount = 12;
// Default alpha value of the first spoke is 255
m_AlphaStartValue = 255;
// Calculate the angle between adjacent spokes
m_AngleIncrement = (int)(360 / m_SpokesCount);
// Calculate the change in alpha between adjacent spokes
m_AlphaDecrement = (int)((m_AlphaStartValue - 15) / m_SpokesCount);
m_Pen = new Pen(TickColor, DEFAULT_TICK_WIDTH);
m_Pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
m_Pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
m_Timer = new Timer();
m_Timer.Interval = this.Interval;
m_Timer.Tick += new EventHandler(OnTimerTick);
}
#endregion
#region EventHandlers
///
/// Handle the Tick event
///
/// Timer
/// EventArgs
void OnTimerTick(object sender, EventArgs e)
{
if (Rotation == Direction.CLOCKWISE)
{
m_StartAngle += m_AngleIncrement;
if (m_StartAngle >= 360)
m_StartAngle = 0;
}
else if (Rotation == Direction.ANTICLOCKWISE)
{
m_StartAngle -= m_AngleIncrement;
if (m_StartAngle <= -360)
m_StartAngle = 0;
}
Invalidate();
}
///
/// Handles the Paint Event of the control
///
/// PaintEventArgs
protected override void OnPaint(PaintEventArgs e)
{
// All the painting will be handled by us.
//base.OnPaint(e);
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
// Since the Rendering of the spokes is dependent upon the current size of the
// control, the following calculation needs to be done within the Paint eventhandler.
int alpha = m_AlphaStartValue;
int angle = m_StartAngle;
// Calculate the location around which the spokes will be drawn
int width = (this.Width < this.Height) ? this.Width : this.Height;
m_CentrePt = new PointF(this.Width / 2, this.Height / 2);
// Calculate the width of the pen which will be used to draw the spokes
m_Pen.Width = (int)(width / 15);
if (m_Pen.Width < MINIMUM_PEN_WIDTH)
m_Pen.Width = MINIMUM_PEN_WIDTH;
// Calculate the inner and outer radii of the control. The radii should not be less than the
// Minimum values
m_InnerRadius = (int)(width * (140 / (float)800));
if (m_InnerRadius < MINIMUM_INNER_RADIUS)
m_InnerRadius = MINIMUM_INNER_RADIUS;
m_OuterRadius = (int)(width * (250 / (float)800));
if (m_OuterRadius < MINIMUM_OUTER_RADIUS)
m_OuterRadius = MINIMUM_OUTER_RADIUS;
// Render the spokes
for (int i = 0; i < m_SpokesCount; i++)
{
PointF pt1 = new PointF(m_InnerRadius * (float)Math.Cos(ConvertDegreesToRadians(angle)), m_InnerRadius * (float)Math.Sin(ConvertDegreesToRadians(angle)));
PointF pt2 = new PointF(m_OuterRadius * (float)Math.Cos(ConvertDegreesToRadians(angle)), m_OuterRadius * (float)Math.Sin(ConvertDegreesToRadians(angle)));
pt1.X += m_CentrePt.X;
pt1.Y += m_CentrePt.Y;
pt2.X += m_CentrePt.X;
pt2.Y += m_CentrePt.Y;
m_Pen.Color = Color.FromArgb(alpha, this.TickColor);
e.Graphics.DrawLine(m_Pen, pt1, pt2);
if (Rotation == Direction.CLOCKWISE)
{
angle -= m_AngleIncrement;
}
else if (Rotation == Direction.ANTICLOCKWISE)
{
angle += m_AngleIncrement;
}
//if (i < 5)
// alpha -= 45;
alpha -= m_AlphaDecrement;
}
}
#endregion
#region Helpers
///
/// Converts Degrees to Radians
///
/// Degrees
///
private double ConvertDegreesToRadians(int degrees)
{
return ((Math.PI / (double)180) * degrees);
}
#endregion
#region APIs
///
/// Start the Tick Control rotation
///
public void Start()
{
if (m_Timer != null)
{
m_Timer.Interval = this.Interval;
m_Timer.Enabled = true;
}
}
///
/// Stop the Tick Control rotation
///
public void Stop()
{
if (m_Timer != null)
{
m_Timer.Enabled = false;
}
}
#endregion
}
}