564 lines
14 KiB
C#
564 lines
14 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Windows.Forms;
|
|
|
|
namespace DevComponents.Instrumentation
|
|
{
|
|
internal abstract class GaugePointerRenderer
|
|
{
|
|
#region Private variables
|
|
|
|
private GaugePointer _GaugePointer;
|
|
|
|
private int _Width;
|
|
private int _Length;
|
|
|
|
private float _IntervalAngle;
|
|
private Point _IntervalPoint;
|
|
|
|
private double _Dpt;
|
|
|
|
private GraphicsPath _PointerPath;
|
|
|
|
#endregion
|
|
|
|
protected GaugePointerRenderer(GaugePointer gaugePointer)
|
|
{
|
|
_GaugePointer = gaugePointer;
|
|
}
|
|
|
|
#region Abstract methods
|
|
|
|
public abstract void RenderCircular(PaintEventArgs e);
|
|
public abstract void RenderLinear(PaintEventArgs e);
|
|
public abstract GraphicsPath GetPointerPath();
|
|
|
|
#endregion
|
|
|
|
#region Protected properties
|
|
|
|
#region GaugePointer
|
|
|
|
protected GaugePointer GaugePointer
|
|
{
|
|
get { return (_GaugePointer); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IntervalAngle
|
|
|
|
internal float IntervalAngle
|
|
{
|
|
get { return (_IntervalAngle); }
|
|
set { _IntervalAngle = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IntervalPoint
|
|
|
|
internal Point IntervalPoint
|
|
{
|
|
get { return (_IntervalPoint); }
|
|
set { _IntervalPoint = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Length
|
|
|
|
protected int Length
|
|
{
|
|
get { return (_Length); }
|
|
set { _Length = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MarkerStyle
|
|
|
|
protected GaugeMarkerStyle MarkerStyle
|
|
{
|
|
get { return (_GaugePointer.MarkerStyle); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PointerPath
|
|
|
|
internal GraphicsPath PointerPath
|
|
{
|
|
get { return (_PointerPath); }
|
|
|
|
set
|
|
{
|
|
if (_PointerPath != value)
|
|
{
|
|
if (_PointerPath != null)
|
|
_PointerPath.Dispose();
|
|
|
|
_PointerPath = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Radius
|
|
|
|
protected int Radius
|
|
{
|
|
get { return (_GaugePointer.Radius); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Scale
|
|
|
|
protected GaugeScale Scale
|
|
{
|
|
get { return (_GaugePointer.Scale); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Value
|
|
|
|
protected double Value
|
|
{
|
|
get { return (_GaugePointer.DValue); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Width
|
|
|
|
protected int Width
|
|
{
|
|
get { return (_Width); }
|
|
set { _Width = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Internal properties
|
|
|
|
#region Dpt
|
|
|
|
internal double Dpt
|
|
{
|
|
get { return (_Dpt > 0 ? _Dpt : 1); }
|
|
set { _Dpt = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetCapFillColor
|
|
|
|
protected GradientFillColor GetCapFillColor(double interval)
|
|
{
|
|
const ColorSourceFillEntry entry = ColorSourceFillEntry.Cap;
|
|
|
|
GradientFillColor fillColor = (Scale.GetRangeFillColor(interval, entry) ??
|
|
Scale.GetSectionFillColor(interval, entry)) ?? GaugePointer.CapFillColor;
|
|
|
|
return (fillColor);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetPointerFillColor
|
|
|
|
protected GradientFillColor GetPointerFillColor(double interval)
|
|
{
|
|
const ColorSourceFillEntry entry = ColorSourceFillEntry.Pointer;
|
|
|
|
GradientFillColor fillColor = (Scale.GetRangeFillColor(interval, entry) ??
|
|
Scale.GetSectionFillColor(interval, entry)) ?? GaugePointer.FillColor;
|
|
|
|
return (fillColor);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetInterval
|
|
|
|
internal double GetInterval(double interval)
|
|
{
|
|
bool pegged;
|
|
|
|
return (GetIntervalEx(interval, out pegged));
|
|
}
|
|
|
|
internal double GetInterval(double interval, out bool pegged)
|
|
{
|
|
double min, max;
|
|
GetRange(out min, out max);
|
|
|
|
pegged = true;
|
|
|
|
if (interval.Equals(double.NaN))
|
|
return (min);
|
|
|
|
if (interval < min)
|
|
interval = min;
|
|
|
|
else if (interval > max)
|
|
interval = max;
|
|
else
|
|
pegged = false;
|
|
|
|
return (interval);
|
|
}
|
|
|
|
internal double GetIntervalEx(double interval, out bool pegged)
|
|
{
|
|
int n = (GaugePointer.Scale is GaugeLinearScale)
|
|
? ((GaugeLinearScale) Scale).AbsLength
|
|
: 360;
|
|
|
|
double minPinValue = GaugePointer.HonorMinPin ? (Scale.MinPinEndOffset*n)/Dpt : 0;
|
|
double maxPinValue = GaugePointer.HonorMaxPin ? (Scale.MaxPinEndOffset*n)/Dpt : 0;
|
|
|
|
double min = Scale.MinValue;
|
|
double max = Scale.MaxValue;
|
|
|
|
if (Scale.MinValue <= Scale.AbsMinLimit)
|
|
min -= minPinValue;
|
|
|
|
if (Scale.MaxValue >= Scale.AbsMaxLimit)
|
|
max += maxPinValue;
|
|
|
|
pegged = true;
|
|
|
|
if (interval.Equals(double.NaN))
|
|
return (min);
|
|
|
|
if (interval < min)
|
|
{
|
|
interval = Scale.MinValue > Scale.AbsMinLimit
|
|
? Math.Max(min - 1, Scale.AbsMinLimit)
|
|
: min;
|
|
}
|
|
else if (interval > max)
|
|
{
|
|
interval = Scale.MaxValue < Scale.AbsMaxLimit
|
|
? Math.Min(max + 1, Scale.AbsMaxLimit)
|
|
: max;
|
|
}
|
|
else
|
|
{
|
|
pegged = false;
|
|
}
|
|
|
|
return (interval);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetRange
|
|
|
|
internal void GetRange(out double min, out double max)
|
|
{
|
|
int n = (GaugePointer.Scale is GaugeLinearScale)
|
|
? ((GaugeLinearScale) Scale).AbsLength
|
|
: 360;
|
|
|
|
double minPinValue = GaugePointer.HonorMinPin ? (Scale.MinPinEndOffset * n) / Dpt : 0;
|
|
double maxPinValue = GaugePointer.HonorMaxPin ? (Scale.MaxPinEndOffset * n) / Dpt : 0;
|
|
|
|
min = Scale.MinValue - minPinValue;
|
|
max = Scale.MaxValue + maxPinValue;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetRangeEx
|
|
|
|
internal void GetRangeEx(out double min, out double max)
|
|
{
|
|
int n = (GaugePointer.Scale is GaugeLinearScale)
|
|
? ((GaugeLinearScale)Scale).AbsLength
|
|
: 360;
|
|
|
|
double minPinValue = GaugePointer.HonorMinPin ? (Scale.MinPinEndOffset * n) / Dpt : 0;
|
|
double maxPinValue = GaugePointer.HonorMaxPin ? (Scale.MaxPinEndOffset * n) / Dpt : 0;
|
|
|
|
min = Scale.AbsMinLimit - minPinValue;
|
|
max = Scale.AbsMaxLimit + maxPinValue;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SwapDoubles
|
|
|
|
protected void SwapDoubles(ref double marker, ref double origin)
|
|
{
|
|
double temp = marker;
|
|
|
|
marker = origin;
|
|
origin = temp;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RecalcLayout
|
|
|
|
public virtual void RecalcLayout()
|
|
{
|
|
PointerPath = null;
|
|
|
|
if (Scale is GaugeCircularScale)
|
|
CalcCircularMetrics(Scale as GaugeCircularScale);
|
|
|
|
else if (Scale is GaugeLinearScale)
|
|
CalcLinearMetrics(Scale as GaugeLinearScale);
|
|
}
|
|
|
|
#region CalcCircularMetrics
|
|
|
|
private void CalcCircularMetrics(GaugeCircularScale scale)
|
|
{
|
|
_Width = (int)(scale.AbsRadius * GaugePointer.Width);
|
|
_Length = (int)(scale.AbsRadius * GaugePointer.Length);
|
|
|
|
if (_Width % 2 != 0)
|
|
_Width++;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CalcLinearMetrics
|
|
|
|
private void CalcLinearMetrics(GaugeLinearScale scale)
|
|
{
|
|
int n = scale.AbsWidth;
|
|
|
|
_Width = (int)(n * GaugePointer.Width);
|
|
_Length = (int)(n * GaugePointer.Length);
|
|
|
|
if (_Width % 2 != 0)
|
|
_Width++;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetValueFromPoint
|
|
|
|
public virtual double GetValueFromPoint(Point pt)
|
|
{
|
|
if (Scale is GaugeCircularScale)
|
|
return (GetCValueFromPoint(Scale as GaugeCircularScale, pt));
|
|
|
|
return (GetLValueFromPoint(Scale as GaugeLinearScale, pt));
|
|
}
|
|
|
|
#region GetCValueFromPoint
|
|
|
|
private double GetCValueFromPoint(GaugeCircularScale scale, Point pt)
|
|
{
|
|
double minValue = scale.MinValue;
|
|
double maxValue = scale.MaxValue;
|
|
|
|
double startAngle = scale.StartAngle;
|
|
double sweepAngle = scale.SweepAngle;
|
|
|
|
double radians = GetPointRadians(pt);
|
|
|
|
double spread = scale.MaxValue - scale.MinValue;
|
|
double dpt = spread / scale.SweepAngle;
|
|
|
|
if (minValue <= scale.AbsMinLimit)
|
|
minValue -= GetCMinPinOffset(dpt, ref startAngle, ref sweepAngle);
|
|
|
|
if (maxValue >= scale.AbsMaxLimit)
|
|
maxValue += GetCMaxPinOffset(dpt, ref startAngle, ref sweepAngle);
|
|
|
|
double angle = (GaugePointer.MouseDownAngle +
|
|
scale.GetDegrees(radians - GaugePointer.MouseDownRadians) - startAngle) % 360;
|
|
|
|
if (angle < 0)
|
|
angle += 360;
|
|
|
|
if (scale.Reversed == true)
|
|
{
|
|
angle = sweepAngle - angle;
|
|
|
|
if (angle < 0)
|
|
angle += 360;
|
|
}
|
|
|
|
if (angle < sweepAngle)
|
|
{
|
|
double value = angle * dpt + minValue;
|
|
|
|
if (GaugePointer.SnapInterval > 0)
|
|
value = (int)(value / GaugePointer.SnapInterval) * GaugePointer.SnapInterval;
|
|
|
|
return (value);
|
|
}
|
|
|
|
if (angle > sweepAngle + (360 - sweepAngle) / 2)
|
|
{
|
|
double limit = minValue;
|
|
|
|
if (limit > scale.AbsMinLimit)
|
|
limit = Math.Max(limit - 1, scale.AbsMinLimit);
|
|
|
|
return (limit);
|
|
}
|
|
|
|
double limit2 = maxValue;
|
|
|
|
if (limit2 < scale.AbsMaxLimit)
|
|
limit2 = Math.Min(limit2 + 1, scale.AbsMaxLimit);
|
|
|
|
return (limit2);
|
|
}
|
|
|
|
#region GetCMinPinOffset
|
|
|
|
private double GetCMinPinOffset(
|
|
double dpt, ref double startAngle, ref double sweepAngle)
|
|
{
|
|
if (GaugePointer.HonorMinPin == true)
|
|
{
|
|
double d = Scale.MinPinEndOffset * 360;
|
|
|
|
if (Scale.Reversed == false)
|
|
startAngle -= d;
|
|
|
|
sweepAngle += d;
|
|
|
|
return (d * dpt);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetCMaxPinOffset
|
|
|
|
private double GetCMaxPinOffset(
|
|
double dpt, ref double startAngle, ref double sweepAngle)
|
|
{
|
|
if (GaugePointer.HonorMaxPin == true)
|
|
{
|
|
double d = Scale.MaxPinEndOffset * 360;
|
|
|
|
if (Scale.Reversed == true)
|
|
startAngle -= d;
|
|
|
|
sweepAngle += d;
|
|
|
|
return (d * dpt);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetPointRadians
|
|
|
|
internal double GetPointRadians(Point pt)
|
|
{
|
|
int dx = pt.X - Scale.Center.X;
|
|
int dy = pt.Y - Scale.Center.Y;
|
|
|
|
if (dx >= 0)
|
|
{
|
|
if (dy >= 0)
|
|
return (Math.Atan((double)dy / dx));
|
|
|
|
return (-Math.Atan((double)dx / dy) + Math.PI * 1.5);
|
|
}
|
|
|
|
if (dy >= 0)
|
|
return (-Math.Atan((double)dx / dy) + Math.PI / 2);
|
|
|
|
return (Math.Atan((double)dy / dx) + Math.PI);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetLValueFromPoint
|
|
|
|
private double GetLValueFromPoint(GaugeLinearScale scale, Point pt)
|
|
{
|
|
bool pegged;
|
|
|
|
double value = (scale.Orientation == Orientation.Horizontal)
|
|
? GetLhValueFromPoint(scale, pt, out pegged)
|
|
: GetLvValueFromPoint(scale, pt, out pegged);
|
|
|
|
if (GaugePointer.SnapInterval > 0)
|
|
{
|
|
if (pegged == false)
|
|
value = (int)(value / GaugePointer.SnapInterval) * GaugePointer.SnapInterval;
|
|
}
|
|
|
|
return (value);
|
|
}
|
|
|
|
#region GetLhValueFromPoint
|
|
|
|
private double GetLhValueFromPoint(GaugeLinearScale scale, Point pt, out bool pegged)
|
|
{
|
|
double spread = scale.MaxValue - scale.MinValue;
|
|
double tpd = spread / scale.ScaleBounds.Width;
|
|
|
|
double interval = (pt.X - scale.ScaleBounds.X) * tpd;
|
|
|
|
if (scale.Reversed == true)
|
|
return (GetIntervalEx(scale.MaxValue - interval, out pegged));
|
|
|
|
return (GetIntervalEx(scale.MinValue + interval, out pegged));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetLvValueFromPoint
|
|
|
|
private double GetLvValueFromPoint(GaugeLinearScale scale, Point pt, out bool pegged)
|
|
{
|
|
double spread = scale.MaxValue - scale.MinValue;
|
|
double tpd = spread / scale.ScaleBounds.Height;
|
|
|
|
double interval = (pt.Y - scale.ScaleBounds.Y) * tpd;
|
|
|
|
if (scale.Reversed == true)
|
|
return (GetIntervalEx(scale.MinValue + interval, out pegged));
|
|
|
|
return (GetIntervalEx(scale.MaxValue - interval, out pegged));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region OnMouseDown
|
|
|
|
internal virtual void OnMouseDown(MouseEventArgs e)
|
|
{
|
|
GaugePointer.MouseDownAngle = 0;
|
|
GaugePointer.MouseDownRadians = 0;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|