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