using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using FastReport.Utils;
namespace FastReport.Gauge.Radial
{
#region Enums
///
/// Radial Gauge types
///
[Flags]
public enum RadialGaugeType
{
///
/// Full sized gauge
///
Circle = 1,
///
/// Half of the radial gauge
///
Semicircle = 2,
///
/// Quarter of the radial gauge
///
Quadrant = 4
}
///
/// Radial Gauge position types
///
[Flags]
public enum RadialGaugePosition
{
///
/// None
///
None = 0,
///
/// Top
///
Top = 1,
///
/// Bottom
///
Bottom = 2,
///
/// Left
///
Left = 4,
///
/// Right
///
Right = 8
}
#endregion // Enums
///
/// Represents a linear gauge.
///
public partial class RadialGauge : GaugeObject
{
private const double RAD = Math.PI / 180.0;
private PointF center;
private RadialGaugeType type;
private RadialGaugePosition position;
private float semicircleOffsetRatio;
#region Properties
///
public override float Width
{
get { return base.Width; }
set
{
base.Width = value;
if (base.Height != base.Width)
{
base.Height = Width;
}
}
}
///
public override float Height
{
get { return base.Height; }
set
{
base.Height = value;
if (base.Width != base.Height)
{
base.Width = Height;
}
}
}
///
/// Returns centr of the gauge
///
[Browsable(false)]
public PointF Center
{
get { return center; }
set { center = value; }
}
///
/// The number of radians in one degree
///
public static double Radians
{
get { return RAD; }
}
///
/// Gets or sets the Radial Gauge type
///
[Browsable(true)]
[Category("Appearance")]
public RadialGaugeType Type
{
get { return type; }
set
{
if (value == RadialGaugeType.Circle)
{
position = RadialGaugePosition.None;
type = value;
}
if (value == RadialGaugeType.Semicircle &&
!(Position == RadialGaugePosition.Bottom ||
Position == RadialGaugePosition.Left ||
Position == RadialGaugePosition.Right ||
Position == RadialGaugePosition.Top))
{
position = RadialGaugePosition.Top;
type = value;
}
else if (value == RadialGaugeType.Quadrant &&
!(
((Position & RadialGaugePosition.Left) != 0 && (Position & RadialGaugePosition.Top) != 0 &&
(Position & RadialGaugePosition.Right) == 0 && (Position & RadialGaugePosition.Bottom) == 0) ||
((Position & RadialGaugePosition.Right) != 0 && (Position & RadialGaugePosition.Top) != 0 &&
(Position & RadialGaugePosition.Left) == 0 && (Position & RadialGaugePosition.Bottom) == 0) ||
((Position & RadialGaugePosition.Left) != 0 && (Position & RadialGaugePosition.Bottom) != 0 &&
(Position & RadialGaugePosition.Right) == 0 && (Position & RadialGaugePosition.Top) == 0) ||
((Position & RadialGaugePosition.Right) != 0 && (Position & RadialGaugePosition.Bottom) != 0 &&
(Position & RadialGaugePosition.Left) == 0 && (Position & RadialGaugePosition.Top) == 0)
))
{
position = RadialGaugePosition.Top | RadialGaugePosition.Left;
type = value;
}
}
}
///
/// Gats or sets the Radial Gauge position. Doesn't work for Full Radial Gauge.
///
[Category("Appearance")]
[Editor("FastReport.TypeEditors.FlagsEditor, FastReport", typeof(UITypeEditor))]
public RadialGaugePosition Position
{
get { return position; }
set
{
if(Type == RadialGaugeType.Semicircle &&
(value == RadialGaugePosition.Bottom ||
value == RadialGaugePosition.Left ||
value == RadialGaugePosition.Right ||
value == RadialGaugePosition.Top))
position = value;
else if (Type == RadialGaugeType.Quadrant &&
(
((value & RadialGaugePosition.Left) != 0 && (value & RadialGaugePosition.Top) != 0 &&
(value & RadialGaugePosition.Right) == 0 && (value & RadialGaugePosition.Bottom) == 0) ||
((value & RadialGaugePosition.Right) != 0 && (value & RadialGaugePosition.Top) != 0 &&
(value & RadialGaugePosition.Left) == 0 && (value & RadialGaugePosition.Bottom) == 0) ||
((value & RadialGaugePosition.Left) != 0 && (value & RadialGaugePosition.Bottom) != 0 &&
(value & RadialGaugePosition.Right) == 0 && (value & RadialGaugePosition.Top) == 0) ||
((value & RadialGaugePosition.Right) != 0 && (value & RadialGaugePosition.Bottom) != 0 &&
(value & RadialGaugePosition.Left) == 0 && (value & RadialGaugePosition.Top) == 0)
))
position = value;
else if (Type == RadialGaugeType.Circle)
position = 0;
}
}
///
/// Gets or sets the semicircles offset
///
[Category("Appearance")]
public float SemicircleOffsetRatio
{
get { return semicircleOffsetRatio; }
set { semicircleOffsetRatio = value; }
}
#endregion // Properties
#region Constructors
///
/// Initializes a new instance of the class.
///
public RadialGauge() : base()
{
InitializeComponent();
Scale = new RadialScale(this);
Pointer = new RadialPointer(this, Scale as RadialScale);
Label = new RadialLabel(this);
Height = 4.0f * Units.Centimeters;
Width = 4.0f * Units.Centimeters;
semicircleOffsetRatio = type == RadialGaugeType.Semicircle &&
(position == RadialGaugePosition.Left || position == RadialGaugePosition.Right) ? 1.5f : 1;
Type = RadialGaugeType.Circle;
Border.Lines = BorderLines.None;
}
#endregion // Constructor
#region Public Methods
///
public override void Assign(Base source)
{
base.Assign(source);
RadialGauge src = source as RadialGauge;
Type = src.Type;
Position = src.Position;
}
///
public override void Draw(FRPaintEventArgs e)
{
IGraphics g = e.Graphics;
float x = (AbsLeft + Border.Width / 2) * e.ScaleX;
float y = (AbsTop + Border.Width / 2) * e.ScaleY;
float dx = (Width - Border.Width) * e.ScaleX - 1;
float dy = (Height - Border.Width) * e.ScaleY - 1;
float x1 = x + dx;
float y1 = y + dy;
Pen pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleX, Border.DashStyle);
Brush brush;
if (Fill is SolidFill)
brush = e.Cache.GetBrush((Fill as SolidFill).Color);
else
brush = Fill.CreateBrush(new RectangleF(x, y, dx, dy), e.ScaleX, e.ScaleY);
center = new PointF(x + dx / 2, y + dy / 2);
if (type == RadialGaugeType.Circle)
{
g.FillAndDrawEllipse(pen, brush, x, y, dx, dy);
}
else if (type == RadialGaugeType.Semicircle)
{
float semiOffset = (Width / 16f /2f + 2f) * semicircleOffsetRatio * e.ScaleY;
PointF[] points = new PointF[4];
if (position == RadialGaugePosition.Top)
{
g.FillPie(brush, x, y, dx, dy, -180, 180);
g.DrawArc(pen, x, y, dx, dy, -180, 180);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, -90 * RAD, center)[0];
points[0] = new PointF(startPoint.X, startPoint.Y - 1 * e.ScaleY);
points[1] = new PointF(startPoint.X, startPoint.Y + semiOffset);
points[2] = new PointF(startPoint.X + dx, startPoint.Y + semiOffset);
points[3] = new PointF(startPoint.X + dx, startPoint.Y - 1 * e.ScaleY);
}
else if(position == RadialGaugePosition.Bottom)
{
g.FillPie(brush, x, y, dx, dy, 0, 180);
g.DrawArc(pen, x, y, dx, dy, 0, 180);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, 90 * RAD, center)[0];
points[0] = new PointF(startPoint.X, startPoint.Y + 1 * e.ScaleY);
points[1] = new PointF(startPoint.X, startPoint.Y - semiOffset);
points[2] = new PointF(startPoint.X - dx, startPoint.Y - semiOffset);
points[3] = new PointF(startPoint.X - dx, startPoint.Y + 1 * e.ScaleY);
}
else if (position == RadialGaugePosition.Left)
{
g.FillPie(brush, x, y, dx, dy, 90, 180);
g.DrawArc(pen, x, y, dx, dy, 90, 180);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, 180 * RAD, center)[0];
points[0] = new PointF(startPoint.X - 1 * e.ScaleX, startPoint.Y);
points[1] = new PointF(startPoint.X + semiOffset, startPoint.Y);
points[2] = new PointF(startPoint.X + semiOffset, startPoint.Y - dy);
points[3] = new PointF(startPoint.X - 1 * e.ScaleX, startPoint.Y - dy);
}
else if (position == RadialGaugePosition.Right)
{
g.FillPie(brush, x, y, dx, dy, -90, 180);
g.DrawArc(pen, x, y, dx, dy, -90, 180);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, -180 * RAD, center)[0];
points[0] = new PointF(startPoint.X + 1 * e.ScaleX, startPoint.Y);
points[1] = new PointF(startPoint.X - semiOffset, startPoint.Y);
points[2] = new PointF(startPoint.X - semiOffset, startPoint.Y - dy);
points[3] = new PointF(startPoint.X + 1 * e.ScaleX, startPoint.Y - dy);
}
if(position != RadialGaugePosition.None)
{
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
g.FillAndDrawPath(pen, brush, path);
}
}
else if (type == RadialGaugeType.Quadrant)
{
float semiOffset = (Width / 16f / 2f + 2f) * semicircleOffsetRatio * e.ScaleY;
if (RadialUtils.IsTop(this) && RadialUtils.IsLeft(this))
{
g.FillPie(brush, x, y, dx, dy, -180, 90);
g.DrawArc(pen, x, y, dx, dy, -180, 90);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, -90 * RAD, center)[0];
PointF[] points = new PointF[5];
points[0] = new PointF(startPoint.X, startPoint.Y - 1 * e.ScaleY);
points[1] = new PointF(startPoint.X, startPoint.Y + semiOffset);
points[2] = new PointF(startPoint.X + dx / 2 + semiOffset, startPoint.Y + semiOffset);
points[3] = new PointF(startPoint.X + dx / 2 + semiOffset, y);
points[4] = new PointF(startPoint.X + dx / 2 - 1 * e.ScaleX, y);
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
g.FillAndDrawPath(pen, brush, path);
}
else if (RadialUtils.IsBottom(this) && RadialUtils.IsLeft(this))
{
g.FillPie(brush, x, y, dx, dy, -270, 90);
g.DrawArc(pen, x, y, dx, dy, -270, 90);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, -90 * RAD, center)[0];
PointF[] points = new PointF[5];
points[0] = new PointF(startPoint.X, startPoint.Y + 1 * e.ScaleY);
points[1] = new PointF(startPoint.X, startPoint.Y - semiOffset);
points[2] = new PointF(startPoint.X + dx / 2 + semiOffset, startPoint.Y - semiOffset);
points[3] = new PointF(startPoint.X + dx / 2 + semiOffset, y + dy);
points[4] = new PointF(x + dx / 2 - 1 * e.ScaleX, y + dy);
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
g.FillAndDrawPath(pen, brush, path);
}
else if (RadialUtils.IsTop(this) && RadialUtils.IsRight(this))
{
g.FillPie(brush, x, y, dx, dy, -90, 90);
g.DrawArc(pen, x, y, dx, dy, -90, 90);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, 90 * RAD, center)[0];
PointF[] points = new PointF[5];
points[0] = new PointF(startPoint.X, startPoint.Y - 1 * e.ScaleY);
points[1] = new PointF(startPoint.X, startPoint.Y + semiOffset);
points[2] = new PointF(startPoint.X - dx / 2 - semiOffset, startPoint.Y + semiOffset);
points[3] = new PointF(x + dx / 2 - semiOffset , y);
points[4] = new PointF(x + dx / 2 + 1 * e.ScaleX, y);
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
g.FillAndDrawPath(pen, brush, path);
}
else if (RadialUtils.IsBottom(this) && RadialUtils.IsRight(this))
{
g.FillPie(brush, x, y, dx, dy, 0, 90);
g.DrawArc(pen, x, y, dx, dy, 0, 90);
PointF startPoint = RadialUtils.RotateVector(new PointF[] { new PointF(x + dx / 2, y), center }, 90 * RAD, center)[0];
PointF[] points = new PointF[5];
points[0] = new PointF(startPoint.X, startPoint.Y + 1 * e.ScaleY);
points[1] = new PointF(startPoint.X, startPoint.Y - semiOffset);
points[2] = new PointF(x + dx / 2 - semiOffset, startPoint.Y - semiOffset);
points[3] = new PointF(x + dx / 2 - semiOffset, y + dy);
points[4] = new PointF(x + dx / 2 + 1 * e.ScaleX, y + dy);
GraphicsPath path = new GraphicsPath();
path.AddLines(points);
g.FillAndDrawPath(pen, brush, path);
}
}
Scale.Draw(e);
Pointer.Draw(e);
Label.Draw(e);
DrawMarkers(e);
if (!(Fill is SolidFill))
brush.Dispose();
if (Report != null && Report.SmoothGraphics)
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
}
}
///
public override void Serialize(FRWriter writer)
{
RadialGauge c = writer.DiffObject as RadialGauge;
base.Serialize(writer);
if (Type != c.Type)
{
writer.WriteValue("Type", Type);
}
if (Position != c.Position)
{
writer.WriteValue("Position", Position);
}
}
#endregion // Public Methods
}
}