using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;
namespace ViperBytes
{
/// <summary>
/// Special progress bar is a kind of iTunes bar
/// Text member: The token {0} will be replaced with the difference between starting and ending value.
/// </summary>
public class SpecialProgressBar : Control
{
#region SpecialProgressBarStyle enumeration
/// <summary>
/// Lists possible styles
/// </summary>
public enum SpecialProgressBarStyle
{
Square,
Round,
Peaked,
Slang
}
#endregion
#region private fields
/// <summary>
/// Style of progress bar ends
/// </summary>
private SpecialProgressBarStyle style = SpecialProgressBarStyle.Square;
/// <summary>
/// Color of border
/// </summary>
private Color borderColor = Color.Gray;
/// <summary>
/// Light fill color of gradient
/// </summary>
private Color lightFillColor = Color.LightGreen;
/// <summary>
/// Dark fill color of gradient
/// </summary>
private Color darkFillColor = Color.DarkGreen;
/// <summary>
/// Light background color of gradient
/// </summary>
private Color lightBackColor = Color.LightGray;
/// <summary>
/// Dark background color of gradient
/// </summary>
private Color darkBackColor = Color.DarkGray;
/// <summary>
/// Number of separators
/// </summary>
private int separators = 10;
/// <summary>
/// Starting value of fillage
/// </summary>
private int startValue = 0;
/// <summary>
/// Ending value of fillage
/// </summary>
private int endValue = 0;
#endregion
#region public events
/// <summary>
/// Fired, when border color changed
/// </summary>
public event EventHandler BorderColorChanged;
/// <summary>
/// Fired, when light fill color changed
/// </summary>
public event EventHandler LightFillColorChanged;
/// <summary>
/// Fired, when dark fill color changed
/// </summary>
public event EventHandler DarkFillColorChanged;
/// <summary>
/// Fired, when light background color changed
/// </summary>
public event EventHandler LightBackColorChanged;
/// <summary>
/// Fired, when dark background color changed
/// </summary>
public event EventHandler DarkBackColorChanged;
/// <summary>
/// Fired, when number of separators changed
/// </summary>
public event EventHandler SeparatorsChanged;
/// <summary>
/// Fired, when starting value changed
/// </summary>
public event EventHandler StartValueChanged;
/// <summary>
/// Fired, when ending value changed
/// </summary>
public event EventHandler EndValueChanged;
#endregion
#region properties
/// <summary>
/// Specifyes the ending's style
/// </summary>
[DefaultValue(typeof(SpecialProgressBar.SpecialProgressBarStyle), "Square")]
public SpecialProgressBarStyle Style
{
get
{
return this.style;
}
set
{
if (this.style != value)
{
this.style = value;
Invalidate();
OnStyleChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes the border color
/// </summary>
[DefaultValue(typeof(Color), "Gray")]
public Color BorderColor
{
get
{
return this.borderColor;
}
set
{
if (this.borderColor != value)
{
this.borderColor = value;
Invalidate();
OnBorderColorChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes the light fill color of gradient
/// </summary>
[DefaultValue(typeof(Color), "LightGreen")]
public Color LightFillColor
{
get
{
return this.lightFillColor;
}
set
{
if (this.lightFillColor != value)
{
this.lightFillColor = value;
Invalidate();
OnLightFillColorChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes the dark fill color of gradient
/// </summary>
[DefaultValue(typeof(Color), "DarkGreen")]
public Color DarkFillColor
{
get
{
return this.darkFillColor;
}
set
{
if (this.darkFillColor != value)
{
this.darkFillColor = value;
Invalidate();
OnDarkFillColorChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes the light background color of gradient
/// </summary>
[DefaultValue(typeof(Color), "LightGray")]
public Color LightBackColor
{
get
{
return this.lightBackColor;
}
set
{
if (this.lightBackColor != value)
{
this.lightBackColor = value;
Invalidate();
OnLightBackColorChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes the dark background color of gradient
/// </summary>
[DefaultValue(typeof(Color), "DarkGray")]
public Color DarkBackColor
{
get
{
return this.darkBackColor;
}
set
{
if (this.darkBackColor != value)
{
this.darkBackColor = value;
Invalidate();
OnDarkBackColorChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes the number of separators
/// </summary>
[DefaultValue(10)]
public int Separators
{
get
{
return this.separators;
}
set
{
if (this.separators != value)
{
this.separators = value;
Invalidate();
OnSeparatorsChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes starting value
/// </summary>
[DefaultValue(0)]
public int StartValue
{
get
{
return this.startValue;
}
set
{
if (this.startValue != value)
{
this.startValue = value;
Invalidate();
OnStartValueChanged(EventArgs.Empty);
}
}
}
/// <summary>
/// Specifyes ending value
/// </summary>
[DefaultValue(0)]
public int EndValue
{
get
{
return this.endValue;
}
set
{
if (this.endValue != value)
{
this.endValue = value;
Invalidate();
OnEndValueChanged(EventArgs.Empty);
}
}
}
#endregion
#region Constructor
/// <summary>
/// Constructor
/// </summary>
public SpecialProgressBar()
: base()
{
Size = new Size(320, 32);
DoubleBuffered = true;
Text = "{0} %";
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="text">Text member</param>
public SpecialProgressBar(string text)
: base(text)
{
Size = new Size(320, 32);
DoubleBuffered = true;
Text = "{0} %";
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="parent">Parent control</param>
/// <param name="text">Text members</param>
public SpecialProgressBar(Control parent, string text)
: base(parent, text)
{
Size = new Size(320, 32);
DoubleBuffered = true;
Text = "{0} %";
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="text">Text member</param>
/// <param name="left">X-coordinate</param>
/// <param name="top">Y-coordinate</param>
/// <param name="width">Width member</param>
/// <param name="height">Height member</param>
public SpecialProgressBar(string text, int left, int top, int width, int height)
: base(text, left, top, width, height)
{
DoubleBuffered = true;
Text = "{0} %";
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="parent">Parent control</param>
/// <param name="text">Text member</param>
/// <param name="left">X-coordinate</param>
/// <param name="top">Y-coordinate</param>
/// <param name="width">Width member</param>
/// <param name="height">Height member</param>
public SpecialProgressBar(Control parent, string text, int left, int top, int width, int height)
: base(parent, text, left, top, width, height)
{
DoubleBuffered = true;
Text = "{0} %";
}
#endregion
#region protected members
/// <summary>
/// Fired, when border color changed
/// </summary>
protected void OnBorderColorChanged(EventArgs e)
{
if (BorderColorChanged != null)
BorderColorChanged(this, e);
}
/// <summary>
/// Fired, when light fill color changed
/// </summary>
protected void OnLightFillColorChanged(EventArgs e)
{
if (LightFillColorChanged != null)
LightFillColorChanged(this, e);
}
/// <summary>
/// Fired, when dark fill color changed
/// </summary>
protected void OnDarkFillColorChanged(EventArgs e)
{
if (DarkFillColorChanged != null)
DarkFillColorChanged(this, e);
}
/// <summary>
/// Fired, when light background color changed
/// </summary>
protected void OnLightBackColorChanged(EventArgs e)
{
if (LightBackColorChanged != null)
LightBackColorChanged(this, e);
}
/// <summary>
/// Fired, when dark background color changed
/// </summary>
protected void OnDarkBackColorChanged(EventArgs e)
{
if (DarkBackColorChanged != null)
DarkBackColorChanged(this, e);
}
/// <summary>
/// Fired, when number of separators changed
/// </summary>
protected void OnSeparatorsChanged(EventArgs e)
{
if (SeparatorsChanged != null)
SeparatorsChanged(this, e);
}
/// <summary>
/// Fired, when starting value changed
/// </summary>
protected void OnStartValueChanged(EventArgs e)
{
if (StartValueChanged != null)
StartValueChanged(this, e);
}
/// <summary>
/// Fired, when ending value changed
/// </summary>
protected void OnEndValueChanged(EventArgs e)
{
if (EndValueChanged != null)
EndValueChanged(this, e);
}
/// <summary>
/// Fired, when size changed
/// </summary>
/// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e)
{
if (Height > Width)
Width = Height;
base.OnSizeChanged(e);
}
/// <summary>
/// Fired, when text changed
/// </summary>
/// <param name="e"></param>
protected override void OnTextChanged(EventArgs e)
{
Invalidate();
base.OnTextChanged(e);
}
/// <summary>
/// Fired on paint event
/// </summary>
/// <param name="e">Event arguments</param>
protected override void OnPaint(PaintEventArgs e)
{
Rectangle rect = new Rectangle(1, 1, Width - 2, Height - 2);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
GraphicsPath path = GetPath(rect);
// Draw back gradient
using (LinearGradientBrush brush = new LinearGradientBrush(rect, LightBackColor, DarkBackColor, LinearGradientMode.Vertical))
{
g.FillPath(brush, path);
}
if (EndValue - StartValue != 0)
{
// Draw fill gradient
using (LinearGradientBrush brush = new LinearGradientBrush(rect, LightFillColor, DarkFillColor, LinearGradientMode.Vertical))
{
RectangleF clip = new RectangleF(rect.X + (float)rect.Width * (float)StartValue / 100F, rect.Y, (float)rect.Width * (float)(EndValue - StartValue) / 100F, rect.Height);
g.SetClip(clip);
g.FillPath(brush, path);
g.ResetClip();
}
}
using (Pen pen = new Pen(BorderColor, 1))
{
if (EndValue - StartValue != 0)
{
float startSplit = rect.X + (float)rect.Width * (float)StartValue / 100F - 0.5F;
float endSplit = rect.X + (float)rect.Width * (float)EndValue / 100F - 0.5F;
g.SetClip(path);
g.DrawLine(pen, startSplit, rect.Y - 0.5F, startSplit, rect.Y + rect.Height - 0.5F);
g.DrawLine(pen, endSplit, rect.Y - 0.5F, endSplit, rect.Y + rect.Height - 0.5F);
g.ResetClip();
}
// draw Border
Matrix matrix = new Matrix();
matrix.Translate(-0.5F, -0.5F);
path.Transform(matrix);
g.DrawPath(pen, path);
}
if (Separators > 0)
{
using (Pen pen1 = new Pen(Color.FromArgb(48, Color.Black), 1))
{
using (Pen pen2 = new Pen(Color.FromArgb(48, Color.White), 1))
{
float step = (float)rect.Width / (float)(Separators + 1);
g.SetClip(path);
for (float split = rect.X + step - 0.5F; split < rect.X + rect.Width - 0.5F; split += step)
{
g.DrawLine(pen1, split - 0.5F, rect.Y - 0.5F, split - 0.5F, rect.Y + rect.Height - 0.5F);
g.DrawLine(pen2, split + 0.5F, rect.Y - 0.5F, split + 0.5F, rect.Y + rect.Height - 0.5F);
}
g.ResetClip();
}
}
}
// draw light
using (SolidBrush brush = new SolidBrush(Color.FromArgb(48, Color.White)))
{
g.SetClip(path);
g.FillRectangle(brush, new RectangleF(rect.X, rect.Y, rect.Width, rect.Height / 2F));
g.ResetClip();
}
string text;
if (Text.Contains("{0}"))
text = Text.Replace("{0}", ((int)Math.Abs(EndValue - StartValue)).ToString());
else
text = Text;
if (text.Length > 0)
{
SizeF fontSize = g.MeasureString(text, Font);
RectangleF fontRect = new RectangleF(
rect.X + rect.Width / 2F - fontSize.Width / 2F,
rect.Y + rect.Height / 2F - fontSize.Height / 2F,
fontSize.Width,
fontSize.Height);
g.DrawString(text, Font, new SolidBrush(ForeColor), fontRect);
}
base.OnPaint(e);
}
#endregion
#region private members
private GraphicsPath GetPath(RectangleF rect)
{
GraphicsPath path = new GraphicsPath();
switch (Style)
{
case SpecialProgressBarStyle.Square:
path.AddRectangle(rect);
break;
case SpecialProgressBarStyle.Round:
path.AddArc(new RectangleF(rect.X, rect.Y, rect.Height, rect.Height), 90, 180);
path.AddArc(new RectangleF(rect.X + rect.Width - rect.Height, rect.Y, rect.Height, rect.Height), 270, 180);
path.CloseFigure();
break;
case SpecialProgressBarStyle.Peaked:
{
PointF[] points = new PointF[] {
new PointF(rect.X, rect.Y + rect.Height / 2F),
new PointF(rect.X + rect.Height / 2F, rect.Y),
new PointF(rect.X + rect.Width - rect.Height / 2F, rect.Y),
new PointF(rect.X + rect.Width, rect.Y + rect.Height / 2F),
new PointF(rect.X + rect.Width - rect.Height / 2F, rect.Y + rect.Height),
new PointF(rect.X + rect.Height / 2F, rect.Y + rect.Height)
};
path.AddLines(points);
path.CloseFigure();
}
break;
case SpecialProgressBarStyle.Slang:
{
PointF[] points = new PointF[] {
new PointF(rect.X, rect.Y),
new PointF(rect.X + rect.Width - rect.Height / 2F, rect.Y),
new PointF(rect.X + rect.Width, rect.Y + rect.Height),
new PointF(rect.X + rect.Height / 2F, rect.Y + rect.Height)
};
path.AddLines(points);
path.CloseFigure();
}
break;
}
return path;
}
#endregion
}
}