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
}
}