522 lines
13 KiB
C#
522 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
|
|
namespace DevComponents.Instrumentation
|
|
{
|
|
internal class GaugeMarker : IDisposable
|
|
{
|
|
#region Private variables
|
|
|
|
private List<BitmapEntry> _Bitmaps;
|
|
|
|
#endregion
|
|
|
|
public GaugeMarker()
|
|
{
|
|
_Bitmaps = new List<BitmapEntry>();
|
|
}
|
|
|
|
#region Clear
|
|
|
|
public void Clear()
|
|
{
|
|
foreach (BitmapEntry entry in _Bitmaps)
|
|
entry.Bitmap.Dispose();
|
|
|
|
_Bitmaps.Clear();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region FindBitmap
|
|
|
|
public Bitmap FindBitmap(GradientFillColor fillColor)
|
|
{
|
|
foreach (BitmapEntry entry in _Bitmaps)
|
|
{
|
|
if (entry.FillColor.IsEqualTo(fillColor) == true)
|
|
return (entry.Bitmap);
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMarkerBitmap
|
|
|
|
public Bitmap GetMarkerBitmap(Graphics g,
|
|
GaugeMarkerStyle style, GradientFillColor fillColor, int width, int length)
|
|
{
|
|
Bitmap bitmap = FindBitmap(fillColor);
|
|
|
|
if (bitmap == null)
|
|
{
|
|
width = Math.Max(width, 3);
|
|
length = Math.Max(length, 3);
|
|
|
|
bitmap = new Bitmap(width, length, g);
|
|
|
|
_Bitmaps.Add(new BitmapEntry(fillColor, bitmap));
|
|
|
|
using (Graphics gBmp = Graphics.FromImage(bitmap))
|
|
{
|
|
gBmp.SmoothingMode = SmoothingMode.AntiAlias;
|
|
|
|
Rectangle r = new Rectangle();
|
|
r.Height = length;
|
|
r.Width = width;
|
|
|
|
using (GraphicsPath path = GetMarkerPath(style, r))
|
|
FillMarkerPath(gBmp, path, r, style, fillColor);
|
|
}
|
|
}
|
|
|
|
return (bitmap);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region FillMarkerPath
|
|
|
|
internal void FillMarkerPath(Graphics g, GraphicsPath path,
|
|
Rectangle r, GaugeMarkerStyle style, GradientFillColor fillColor)
|
|
{
|
|
GradientFillType fillType = GetMarkerFillType(style, fillColor);
|
|
|
|
switch (fillType)
|
|
{
|
|
case GradientFillType.Angle:
|
|
using (Brush br = fillColor.GetBrush(r))
|
|
{
|
|
if (br is LinearGradientBrush)
|
|
((LinearGradientBrush)br).WrapMode = WrapMode.TileFlipXY;
|
|
|
|
g.FillPath(br, path);
|
|
}
|
|
break;
|
|
|
|
case GradientFillType.StartToEnd:
|
|
using (Brush br = fillColor.GetBrush(r, 90))
|
|
{
|
|
if (br is LinearGradientBrush)
|
|
((LinearGradientBrush)br).WrapMode = WrapMode.TileFlipXY;
|
|
|
|
g.FillPath(br, path);
|
|
}
|
|
break;
|
|
|
|
case GradientFillType.HorizontalCenter:
|
|
r.Height /= 2;
|
|
|
|
if (r.Height <= 0)
|
|
r.Height = 1;
|
|
|
|
using (LinearGradientBrush br = new
|
|
LinearGradientBrush(r, fillColor.Start, fillColor.End, 90))
|
|
{
|
|
br.WrapMode = WrapMode.TileFlipXY;
|
|
|
|
g.FillPath(br, path);
|
|
}
|
|
break;
|
|
|
|
case GradientFillType.VerticalCenter:
|
|
r.Width /= 2;
|
|
|
|
if (r.Width <= 0)
|
|
r.Width = 1;
|
|
|
|
using (LinearGradientBrush br = new
|
|
LinearGradientBrush(r, fillColor.Start, fillColor.End, 0f))
|
|
{
|
|
br.WrapMode = WrapMode.TileFlipXY;
|
|
|
|
g.FillPath(br, path);
|
|
}
|
|
break;
|
|
|
|
case GradientFillType.Center:
|
|
using (PathGradientBrush br = new PathGradientBrush(path))
|
|
{
|
|
br.CenterColor = fillColor.Start;
|
|
br.SurroundColors = new Color[] { fillColor.End };
|
|
|
|
g.FillPath(br, path);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
using (Brush br = new SolidBrush(fillColor.Start))
|
|
g.FillPath(br, path);
|
|
|
|
break;
|
|
}
|
|
|
|
if (fillColor.BorderWidth > 0)
|
|
{
|
|
using (Pen pen = new Pen(fillColor.BorderColor, fillColor.BorderWidth))
|
|
{
|
|
pen.Alignment = PenAlignment.Inset;
|
|
|
|
g.DrawPath(pen, path);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMarkerFillType
|
|
|
|
private GradientFillType GetMarkerFillType(GaugeMarkerStyle style, GradientFillColor fillColor)
|
|
{
|
|
if (fillColor.End.IsEmpty == true)
|
|
return (GradientFillType.None);
|
|
|
|
if (fillColor.GradientFillType == GradientFillType.Auto)
|
|
{
|
|
switch (style)
|
|
{
|
|
case GaugeMarkerStyle.Circle:
|
|
case GaugeMarkerStyle.Star5:
|
|
case GaugeMarkerStyle.Star7:
|
|
return (GradientFillType.Center);
|
|
|
|
default:
|
|
return (GradientFillType.VerticalCenter);
|
|
}
|
|
}
|
|
|
|
return (fillColor.GradientFillType);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMarkerPath
|
|
|
|
internal GraphicsPath GetMarkerPath(GaugeMarkerStyle style, Rectangle r)
|
|
{
|
|
r.Inflate(-1, -1);
|
|
|
|
if (r.Width > 0 && r.Height > 0)
|
|
{
|
|
switch (style)
|
|
{
|
|
case GaugeMarkerStyle.Circle:
|
|
return (GetCirclePath(r));
|
|
|
|
case GaugeMarkerStyle.Diamond:
|
|
return (GetDiamondPath(r));
|
|
|
|
case GaugeMarkerStyle.Hexagon:
|
|
return (GetPolygonPath(r, 6, 90));
|
|
|
|
case GaugeMarkerStyle.Pentagon:
|
|
return (GetPolygonPath(r, 5, 90));
|
|
|
|
case GaugeMarkerStyle.Rectangle:
|
|
return (GetRectanglePath(r));
|
|
|
|
case GaugeMarkerStyle.Star5:
|
|
return (GetStarPath(r, 5));
|
|
|
|
case GaugeMarkerStyle.Star7:
|
|
return (GetStarPath(r, 7));
|
|
|
|
case GaugeMarkerStyle.Trapezoid:
|
|
return (GetTrapezoidPath(r));
|
|
|
|
case GaugeMarkerStyle.Triangle:
|
|
return (GetTrianglePath(r));
|
|
|
|
case GaugeMarkerStyle.Wedge:
|
|
return (GetWedgePath(r));
|
|
|
|
default:
|
|
return (GetRectanglePath(r));
|
|
}
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#region GetCirclePath
|
|
|
|
private GraphicsPath GetCirclePath(Rectangle r)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
path.AddEllipse(r);
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetDiamondPath
|
|
|
|
private GraphicsPath GetDiamondPath(Rectangle r)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
int dx = r.Width / 2;
|
|
int dy = r.Height / 2;
|
|
|
|
Point[] pts = {
|
|
new Point(r.Left + dx, r.Top),
|
|
new Point(r.Right, r.Top + dy),
|
|
new Point(r.Left + dx, r.Bottom),
|
|
new Point(r.Left, r.Top + dy),
|
|
};
|
|
|
|
path.AddPolygon(pts);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetPolygonPath
|
|
|
|
private GraphicsPath GetPolygonPath(Rectangle r, int sides, float angle)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
double dx = (double)r.Width / 2;
|
|
double radians = GetRadians(angle);
|
|
double delta = GetRadians((float)360 / sides);
|
|
|
|
Point[] pts = new Point[sides];
|
|
|
|
for (int i = 0; i < sides; i++)
|
|
{
|
|
pts[i] = new Point(
|
|
(int)(dx * Math.Cos(radians) + dx + r.X),
|
|
(int)(dx * Math.Sin(radians) + dx + r.Y));
|
|
|
|
radians += delta;
|
|
}
|
|
|
|
path.AddPolygon(pts);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetRectanglePath
|
|
|
|
private GraphicsPath GetRectanglePath(Rectangle r)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
path.AddRectangle(r);
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetStarPath
|
|
|
|
private GraphicsPath GetStarPath(Rectangle r, int points)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
PointF[] pts = new PointF[2 * points];
|
|
|
|
double rx1 = r.Width / 2;
|
|
double ry1 = r.Height / 2;
|
|
|
|
if (rx1 < 2)
|
|
rx1 = 2;
|
|
|
|
if (ry1 < 2)
|
|
ry1 = 2;
|
|
|
|
double rx2 = rx1 / 2;
|
|
double ry2 = ry1 / 2;
|
|
|
|
double cx = r.X + rx1;
|
|
double cy = r.Y + ry1;
|
|
|
|
double theta = GetRadians(90);
|
|
double dtheta = Math.PI / points;
|
|
|
|
for (int i = 0; i < 2 * points; i += 2)
|
|
{
|
|
pts[i] = new PointF(
|
|
(float)(cx + rx1 * Math.Cos(theta)),
|
|
(float)(cy + ry1 * Math.Sin(theta)));
|
|
|
|
theta += dtheta;
|
|
|
|
pts[i + 1] = new PointF(
|
|
(float)(cx + rx2 * Math.Cos(theta)),
|
|
(float)(cy + ry2 * Math.Sin(theta)));
|
|
|
|
theta += dtheta;
|
|
}
|
|
|
|
path.AddPolygon(pts);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetTrianglePath
|
|
|
|
private GraphicsPath GetTrianglePath(Rectangle r)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
int dx = r.Width / 2;
|
|
|
|
Point[] pts = {
|
|
new Point(r.Left, r.Top),
|
|
new Point(r.Right, r.Top),
|
|
new Point(r.Left + dx, r.Bottom),
|
|
};
|
|
|
|
path.AddPolygon(pts);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetTrapezoidPath
|
|
|
|
private GraphicsPath GetTrapezoidPath(Rectangle r)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
int dx = (int)(r.Width * .28f);
|
|
|
|
if (dx <= 0)
|
|
dx = 1;
|
|
|
|
Point[] pts = {
|
|
new Point(r.Left, r.Top),
|
|
new Point(r.Right, r.Top),
|
|
new Point(r.Right - dx, r.Bottom),
|
|
new Point(r.Left + dx, r.Bottom),
|
|
};
|
|
|
|
path.AddPolygon(pts);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetWedgePath
|
|
|
|
private GraphicsPath GetWedgePath(Rectangle r)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
int dx = r.Width / 2;
|
|
|
|
if ((r.Width % 2) == 1)
|
|
dx++;
|
|
|
|
if (dx <= 0)
|
|
dx = 1;
|
|
|
|
int dy = (int)Math.Sqrt((r.Width * r.Width) - (dx * dx));
|
|
|
|
int y = Math.Max(r.Y, r.Bottom - dy);
|
|
|
|
Point[] pts = {
|
|
new Point(r.X, r.Top),
|
|
new Point(r.Right, r.Top),
|
|
new Point(r.Right, y),
|
|
new Point(r.X + dx, r.Bottom),
|
|
new Point(r.X, y)
|
|
};
|
|
|
|
path.AddPolygon(pts);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return (path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetRadians
|
|
|
|
/// <summary>
|
|
/// Converts Degrees to Radians
|
|
/// </summary>
|
|
/// <param name="theta">Degrees</param>
|
|
/// <returns>Radians</returns>
|
|
internal double GetRadians(float theta)
|
|
{
|
|
return (theta * Math.PI / 180);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region BitmapEntry
|
|
|
|
private class BitmapEntry
|
|
{
|
|
public GradientFillColor FillColor;
|
|
public Bitmap Bitmap;
|
|
|
|
public BitmapEntry(GradientFillColor fillColor, Bitmap bitmap)
|
|
{
|
|
FillColor = (GradientFillColor)fillColor.Clone();
|
|
Bitmap = bitmap;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDisposable Members
|
|
|
|
public void Dispose()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#region Enums
|
|
|
|
public enum GaugeMarkerStyle
|
|
{
|
|
Circle,
|
|
Diamond,
|
|
Hexagon,
|
|
Pentagon,
|
|
Rectangle,
|
|
Star5,
|
|
Star7,
|
|
Trapezoid,
|
|
Triangle,
|
|
Wedge,
|
|
None
|
|
}
|
|
|
|
#endregion
|
|
}
|