2188 lines
58 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using DevComponents.Instrumentation.Primitives;
namespace DevComponents.Instrumentation
{
/// <summary>
/// Collection of GaugePointers
/// </summary>
public class GaugePointerCollection : GenericCollection<GaugePointer>
{
#region ICloneable Members
public override object Clone()
{
GaugePointerCollection copy = new GaugePointerCollection();
CopyToItem(copy);
return (copy);
}
#endregion
#region CopyToItem
internal void CopyToItem(GaugePointerCollection copy)
{
foreach (GaugePointer item in this)
{
GaugePointer ic = new GaugePointer();
item.CopyToItem(ic);
copy.Add(ic);
}
}
#endregion
}
public class GaugePointer : GaugeItem
{
#region Private variables
private PointerStyle _Style;
private BarPointerStyle _BarStyle;
private GaugeMarkerStyle _MarkerStyle;
private NeedlePointerStyle _NeedleStyle;
private NeedlePointerCapStyle _CapStyle;
private BulbStyle _BulbStyle;
private DisplayPlacement _Placement;
private float _ScaleOffset;
private int _Radius;
private int _Offset;
private float _Width;
private float _Length;
private bool _UnderTickMarks;
private GradientFillColor _FillColor;
private GradientFillColor _FillColorEx;
private GradientFillColor _CapFillColor;
private GradientFillColor _CapFillColorEx;
private bool _AllowUserChange;
private Cursor _ChangeCursor;
private double _Value;
private double _DValue;
private double _SnapInterval;
private double _DampeningSweepTime;
private Image _Image;
private GradientFillColor _ThermoBackColor;
private PointerOrigin _Origin;
private double _OriginInterval;
private float _BulbSize;
private float _BulbOffset;
private Image _CapImage;
private bool _CapOnTop;
private float _CapWidth;
private float _CapOuterBevel;
private float _CapInnerBevel;
private bool _RotateCap;
private bool _HonorMinPin;
private bool _HonorMaxPin;
private bool _Dampening;
private double _DeltaValue;
private long _DStartTicks;
private double _DStartValue;
private double _DEndValue;
private bool _DShowMinLabel;
private bool _DShowMaxLabel;
private bool _DSlideScale;
private GaugePointerRenderer _Renderer;
private GaugeScale _Scale;
private List<GaugeStrip> _RangeList;
private List<GaugeStrip> _SectionList;
private bool _InScale;
private double _MouseDownAngle;
private double _MouseDownRadians;
#endregion
public GaugePointer(GaugeScale scale)
: this()
{
_Scale = scale;
InitGaugePointer();
}
public GaugePointer()
{
InitGaugePointer();
}
#region InitGaugePointer
private void InitGaugePointer()
{
Style = PointerStyle.Marker;
FillColor = new GradientFillColor();
_BarStyle = BarPointerStyle.Square;
_Origin = PointerOrigin.Minimum;
_OriginInterval = double.NaN;
_BulbSize = .14f;
_BulbStyle = BulbStyle.Bulb;
_CapInnerBevel = .14f;
_CapOuterBevel = .1f;
_CapOnTop = true;
_CapStyle = NeedlePointerCapStyle.Style2;
_CapWidth = .3f;
_ChangeCursor = Cursors.Hand;
_DampeningSweepTime = 1;
_HonorMaxPin = true;
_HonorMinPin = true;
_MarkerStyle = GaugeMarkerStyle.Triangle;
_NeedleStyle = NeedlePointerStyle.Style1;
_Placement = DisplayPlacement.Center;
_Value = double.NaN;
_Length = .14f;
_Width = .14f;
_DValue = double.NaN;
}
#endregion
#region Public properties
#region AllowUserChange
/// <summary>
/// Gets or sets whether the user can change the pointer interactively by the mouse
/// </summary>
[Browsable(true)]
[Category("Behavior"), DefaultValue(false)]
[Description("Indicates whether the user can change the pointer interactively by the mouse.")]
public bool AllowUserChange
{
get { return (_AllowUserChange); }
set
{
if (_AllowUserChange != value)
{
_AllowUserChange = value;
OnGaugeItemChanged();
}
}
}
#endregion
#region BarStyle
/// <summary>
/// Gets or sets the Bar Style
/// </summary>
[Browsable(true), Category("Style Specific"), DefaultValue(BarPointerStyle.Square)]
[Description("Indicates the Bar Style.")]
public BarPointerStyle BarStyle
{
get { return (_BarStyle); }
set
{
if (_BarStyle != value)
{
_BarStyle = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region BulbOffset
/// <summary>
/// Gets or sets the distance of the thermometer bulb from the start of the scale, measured as a percentage
/// </summary>
[Browsable(true)]
[Category("Style Specific"), DefaultValue(0f)]
[Editor("DevComponents.Instrumentation.Design.WidthMaxRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
[Description("Indicates the distance of the thermometer bulb from the start of the scale, measured as a percentage.")]
public float BulbOffset
{
get { return (_BulbOffset); }
set
{
if (_BulbOffset != value)
{
if (value < 0 || value > 1)
throw new ArgumentException("Value must be betweel 0 and +1.");
_BulbOffset = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region BulbSize
/// <summary>
/// Gets or sets the size of the thermometer bulb, measured as a percentage
/// </summary>
[Browsable(true)]
[Category("Style Specific"), DefaultValue(.14f)]
[Editor("DevComponents.Instrumentation.Design.OffsetPosRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
[Description("Indicates the size of the thermometer bulb, measured as a percentage.")]
public float BulbSize
{
get { return (_BulbSize); }
set
{
if (_BulbSize != value)
{
_BulbSize = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region BulbStyle
/// <summary>
/// Gets or sets the Thermometer Bulb Style
/// </summary>
[Browsable(true), Category("Style Specific"), DefaultValue(BulbStyle.Bulb)]
[Description("Indicates the Thermometer Bulb Style.")]
public BulbStyle BulbStyle
{
get { return (_BulbStyle); }
set
{
if (_BulbStyle != value)
{
_BulbStyle = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region CapBounds
/// <summary>
/// Gets the CapBounds
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Rectangle CapBounds
{
get
{
if (_Renderer != null && _Renderer is GaugeNeedleRenderer)
return (((GaugeNeedleRenderer)_Renderer).CapBounds);
return (Rectangle.Empty);
}
}
#endregion
#region CapFillColor
/// <summary>
/// Gets or sets the Needle Cap Fill Color
/// </summary>
[Browsable(true), Category("Needle Cap")]
[Description("Indicates the Needle Cap Fill Color.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public GradientFillColor CapFillColor
{
get
{
if (_CapFillColor == null)
{
_CapFillColor = new GradientFillColor(Color.WhiteSmoke, Color.DimGray, 90);
_CapFillColor.BorderColor = Color.DimGray;
_CapFillColor.BorderWidth = 1;
_CapFillColor.ColorTableChanged += FillColorColorTableChanged;
}
return (_CapFillColor);
}
set
{
if (_CapFillColor != null)
_CapFillColor.ColorTableChanged -= FillColorColorTableChanged;
_CapFillColor = value;
if (_CapFillColor != null)
_CapFillColor.ColorTableChanged += FillColorColorTableChanged;
UpdateFillColors();
OnGaugeItemChanged(true);
}
}
#endregion
#region CapFillColorEx
/// <summary>
/// Gets the range/section adjusted Pointer CapFillColor
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GradientFillColor CapFillColorEx
{
get { return (_CapFillColorEx ?? _CapFillColor); }
}
#endregion
#region CapImage
/// <summary>
/// Gets or sets the Image to use for the Needle Cap
/// </summary>
[Browsable(true), Category("Needle Cap"), DefaultValue(null)]
[Description("Indicates the Image to use for the Needle Cap.")]
public Image CapImage
{
get { return (_CapImage); }
set
{
if (_CapImage != value)
{
_CapImage = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region CapInnerBevel
/// <summary>
/// Gets or sets the width of the needle cap's inner bevel, measured as a percentage of the cap width
/// </summary>
[Browsable(true), Category("Needle Cap"), DefaultValue(.14f)]
[Description("Indicates the width of the needle cap's inner bevel, measured as a percentage of the cap width.")]
[Editor("DevComponents.Instrumentation.Design.HalfRadiusRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
public float CapInnerBevel
{
get { return (_CapInnerBevel); }
set
{
if (_CapInnerBevel != value)
{
if (value < 0 || value > .5f)
throw new ArgumentException("Value must be between 0 and .5");
_CapInnerBevel = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region CapOnTop
/// <summary>
/// Gets or sets whether the cap is ontop of the needle
/// </summary>
[Browsable(true), Category("Needle Cap"), DefaultValue(true)]
[Description("Indicates whether the cap is ontop of the needle.")]
public bool CapOnTop
{
get { return (_CapOnTop); }
set
{
if (_CapOnTop != value)
{
_CapOnTop = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region CapOuterBevel
/// <summary>
/// Gets or sets the width of the needle cap's outer bevel, measured as a percentage of the cap width
/// </summary>
[Browsable(true), Category("Needle Cap"), DefaultValue(.1f)]
[Description("Indicates the width of the needle cap's outer bevel, measured as a percentage of the cap width.")]
[Editor("DevComponents.Instrumentation.Design.HalfRadiusRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
public float CapOuterBevel
{
get { return (_CapOuterBevel); }
set
{
if (_CapOuterBevel != value)
{
if (value < 0 || value > .5f)
throw new ArgumentException("Value must be between 0 and .5");
_CapOuterBevel = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region CapStyle
/// <summary>
/// Gets or sets the style of the needle cap
/// </summary>
[Browsable(true), Category("Needle Cap"), DefaultValue(NeedlePointerCapStyle.Style2)]
[Description("Indicates the style of the needle cap.")]
[ParenthesizePropertyName(true)]
public NeedlePointerCapStyle CapStyle
{
get { return (_CapStyle); }
set
{
if (_CapStyle != value)
{
_CapStyle = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region CapWidth
/// <summary>
/// Gets or sets the width of the needle cap
/// </summary>
[Browsable(true), Category("Needle Cap"), DefaultValue(.3f)]
[Description("Indicates the width of the needle cap.")]
[Editor("DevComponents.Instrumentation.Design.CapWidthRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
public float CapWidth
{
get { return (_CapWidth); }
set
{
if (_CapWidth != value)
{
_CapWidth = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region ChangeCursor
/// <summary>
/// Gets or sets the Cursor displayed when the user can change the Pointer
/// </summary>
[Browsable(true), Category("Behavior")]
[Description("Indicates the Cursor displayed when the user can change the Pointer.")]
public Cursor ChangeCursor
{
get { return (_ChangeCursor); }
set
{
if (_ChangeCursor != value)
{
_ChangeCursor = value;
OnGaugeItemChanged();
}
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
internal bool ShouldSerializeChangeCursor()
{
return (_ChangeCursor != Cursors.Hand);
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
internal void ResetChangeCursor()
{
_ChangeCursor = Cursors.Hand;
}
#endregion
#region DampeningSweepTime
/// <summary>
/// Gets or sets the time it takes for the pointer to travel the entire scale, measured in seconds
/// </summary>
[Browsable(true)]
[Category("Behavior"), DefaultValue(1d)]
[Description("Indicates the time it takes for the pointer to travel the entire scale, measured in seconds.")]
public double DampeningSweepTime
{
get { return (_DampeningSweepTime); }
set
{
if (_DampeningSweepTime != value)
{
_DampeningSweepTime = value;
OnGaugeItemChanged();
}
}
}
#endregion
#region FillColor
/// <summary>
/// Gets or sets the Pointer FillColor
/// </summary>
[Browsable(true), Category("Appearance")]
[Description("Indicates the Pointer FillColor.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public GradientFillColor FillColor
{
get
{
if (_FillColor == null)
{
_FillColor = new GradientFillColor();
_FillColor.ColorTableChanged += FillColorColorTableChanged;
}
return (_FillColor);
}
set
{
if (_FillColor != null)
_FillColor.ColorTableChanged -= FillColorColorTableChanged;
_FillColor = value;
if (_FillColor != null)
_FillColor.ColorTableChanged += FillColorColorTableChanged;
UpdateFillColors();
OnGaugeItemChanged(true);
}
}
#endregion
#region FillColorEx
/// <summary>
/// Gets the range/section adjusted Pointer FillColor
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GradientFillColor FillColorEx
{
get { return (_FillColorEx ?? _FillColor); }
}
#endregion
#region HonorMaxPin
/// <summary>
/// Gets or sets whether the pointer honors the Maximum Pin
/// </summary>
[Browsable(true), Category("Behavior"), DefaultValue(true)]
[Description("Indicates whether the pointer honors the Maximum Pin.")]
public bool HonorMaxPin
{
get { return (_HonorMaxPin); }
set
{
if (_HonorMaxPin != value)
{
_HonorMaxPin = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region HonorMinPin
/// <summary>
/// Gets or sets whether the pointer honors the Minimum Pin
/// </summary>
[Browsable(true), Category("Behavior"), DefaultValue(true)]
[Description("Indicates whether the pointer honors the Minimum Pin.")]
public bool HonorMinPin
{
get { return (_HonorMinPin); }
set
{
if (_HonorMinPin != value)
{
_HonorMinPin = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region Image
/// <summary>
/// Gets or sets the Image to use for the Pointer
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(null)]
[Description("Indicates the Image to use for the Pointer.")]
public Image Image
{
get { return (_Image); }
set
{
if (_Image != value)
{
_Image = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region IntervalPoint
/// <summary>
/// Gets the Pointer Interval Point for the current Value
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Point IntervalPoint
{
get
{
if (NeedRecalcLayout == true)
RecalcLayout();
return (_Renderer.IntervalPoint);
}
}
#endregion
#region IntervalAngle
/// <summary>
/// Gets the Pointer Interval Angle for the current Value
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public float IntervalAngle
{
get
{
if (NeedRecalcLayout == true)
RecalcLayout();
return (_Renderer.IntervalAngle);
}
}
#endregion
#region Length
/// <summary>
/// Gets or sets the Pointer length, specified as a percentage
/// </summary>
[Browsable(true)]
[Category("Layout"), DefaultValue(.14f)]
[Editor("DevComponents.Instrumentation.Design.WidthMaxRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
[Description("Indicates the Pointer length, specified as a percentage.")]
public float Length
{
get { return (_Length); }
set
{
if (_Length != value)
{
_Length = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region MarkerStyle
/// <summary>
/// Gets or sets the Marker style
/// </summary>
[Browsable(true), Category("Style Specific"), DefaultValue(GaugeMarkerStyle.Triangle)]
[Description("Indicates the Marker style.")]
public GaugeMarkerStyle MarkerStyle
{
get { return (_MarkerStyle); }
set
{
if (_MarkerStyle != value)
{
_MarkerStyle = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region NeedleStyle
/// <summary>
/// Gets or sets the width of the needle cap
/// </summary>
[Browsable(true), Category("Style Specific"), DefaultValue(NeedlePointerStyle.Style1)]
[Description("Indicates the width of the needle cap.")]
public NeedlePointerStyle NeedleStyle
{
get { return (_NeedleStyle); }
set
{
if (_NeedleStyle != value)
{
_NeedleStyle = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region Origin
/// <summary>
/// Gets or sets the Bar/Thermometer Pointer origin
/// </summary>
[Browsable(true)]
[Category("Style Specific"), DefaultValue(PointerOrigin.Minimum)]
[Description("Indicates the Bar/Thermometer Pointer origin.")]
public PointerOrigin Origin
{
get { return (_Origin); }
set
{
if (_Origin != value)
{
_Origin = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region OriginInterval
/// <summary>
/// Gets or sets the custom Bar/Thermometer origin interval
/// </summary>
[Browsable(true)]
[Category("Style Specific"), DefaultValue(double.NaN)]
[Description("Indicates the custom Bar/Thermometer origin interval.")]
public double OriginInterval
{
get { return (_OriginInterval); }
set
{
if (_OriginInterval != value)
{
_OriginInterval = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region Placement
/// <summary>
/// Gets or sets the Placement of the pointer with respect to the Scale
/// </summary>
[Browsable(true)]
[Category("Layout"), DefaultValue(DisplayPlacement.Center)]
[Description("Indicates the Placement of the pointer with respect to the Scale.")]
public DisplayPlacement Placement
{
get { return (_Placement); }
set
{
if (_Placement != value)
{
_Placement = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region RotateCapImage
/// <summary>
/// Gets or sets whether the needle cap is rotated to match the needle angle
/// </summary>
[Browsable(true)]
[Category("Needle Cap"), DefaultValue(false)]
[Description("Indicates whether the needle cap is rotated to match the needle angle.")]
public bool RotateCap
{
get { return (_RotateCap); }
set
{
if (_RotateCap != value)
{
_RotateCap = value;
OnGaugeItemChanged();
}
}
}
#endregion
#region Scale
/// <summary>
/// Gets the pointer's associated Scale
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GaugeScale Scale
{
get { return (_Scale); }
internal set
{
_Scale = value;
UpdateStripData();
OnGaugeItemChanged(true);
}
}
#endregion
#region ScaleOffset
/// <summary>
/// Gets or sets the distance from the Pointer to the Scale, measured as a percentage
/// </summary>
[Browsable(true)]
[Category("Layout"), DefaultValue(0f)]
[Editor("DevComponents.Instrumentation.Design.OffsetRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
[Description("Indicates the distance from the Pointer to the Scale, measured as a percentage.")]
public float ScaleOffset
{
get { return (_ScaleOffset); }
set
{
if (_ScaleOffset != value)
{
_ScaleOffset = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region SnapInterval
/// <summary>
/// Gets or sets the interval to use to Snap user input values to
/// </summary>
[Browsable(true)]
[Category("Behavior"), DefaultValue(0d)]
[Description("Indicates the interval to use to Snap user input values to.")]
public double SnapInterval
{
get { return (_SnapInterval); }
set
{
if (_SnapInterval != value)
{
_SnapInterval = value;
OnGaugeItemChanged();
}
}
}
#endregion
#region Style
/// <summary>
/// Gets or sets the Pointer style
/// </summary>
[Browsable(true), Category("Style Specific"), DefaultValue(PointerStyle.Marker)]
[Description("Indicates the Pointer style.")]
[ParenthesizePropertyName(true)]
public PointerStyle Style
{
get { return (_Style); }
set
{
if (_Style != value)
{
_Style = value;
SetPointerRenderer();
OnGaugeItemChanged(true);
}
}
}
#region SetPointerRenderer
private void SetPointerRenderer()
{
switch (_Style)
{
case PointerStyle.Bar:
_Renderer = new GaugeBarRenderer(this);
break;
case PointerStyle.Marker:
_Renderer = new GaugeMarkerRenderer(this);
break;
case PointerStyle.Needle:
_Renderer = new GaugeNeedleRenderer(this);
break;
case PointerStyle.Thermometer:
_Renderer = new GaugeThermoRenderer(this);
break;
}
}
#endregion
#endregion
#region ThermoBackColor
/// <summary>
/// Gets or sets the Thermometers's Background "tube" Color
/// </summary>
[Browsable(true), Category("Appearance")]
[Description("Indicates the Thermometers's Background \"tube\" Color.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public GradientFillColor ThermoBackColor
{
get
{
if (_ThermoBackColor == null)
{
_ThermoBackColor = new GradientFillColor();
_ThermoBackColor.ColorTableChanged += FillColorColorTableChanged;
}
return (_ThermoBackColor);
}
set
{
if (_ThermoBackColor != null)
_ThermoBackColor.ColorTableChanged -= FillColorColorTableChanged;
_ThermoBackColor = value;
if (_ThermoBackColor != null)
_ThermoBackColor.ColorTableChanged += FillColorColorTableChanged;
OnGaugeItemChanged(true);
}
}
#endregion
#region UnderTickMarks
/// <summary>
/// Gets or sets whether the marker is under all TickMarks
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(false)]
[Description("Indicates whether the marker is under all TickMarks.")]
public bool UnderTickMarks
{
get { return (_UnderTickMarks); }
set
{
if (_UnderTickMarks != value)
{
_UnderTickMarks = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region Value
/// <summary>
/// Gets or sets the Pointer value
/// </summary>
[Browsable(true)]
[Category("Behavior"), DefaultValue(double.NaN)]
[Description("Indicates the Pointer value.")]
public double Value
{
get { return (_Value); }
set
{
if (_Value != value)
{
double oldValue = _Value;
_Value = value;
OnValueChanged(oldValue, true);
}
}
}
#endregion
#region ValueEx
/// <summary>
/// Gets or sets the value of the pointer - but with no dampening
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public double ValueEx
{
get { return (_Value); }
set
{
if (_Value != value)
{
double oldValue = _Value;
_Value = value;
OnValueChanged(oldValue, false);
}
}
}
#endregion
#region Width
/// <summary>
/// Gets or sets the Pointer width, specified as a percentage
/// </summary>
[Browsable(true)]
[Category("Layout"), DefaultValue(.14f)]
[Editor("DevComponents.Instrumentation.Design.WidthRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))]
[Description("Indicates the Pointer width, specified as a percentage.")]
public float Width
{
get { return (_Width); }
set
{
if (_Width != value)
{
_Width = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#endregion
#region Internal properties
#region AbsScaleOffset
internal int AbsScaleOffset
{
get
{
if (Scale is GaugeCircularScale)
return (GetAbsScaleOffset(Scale as GaugeCircularScale));
return (GetAbsScaleOffset(Scale as GaugeLinearScale));
}
}
#region GetAbsScaleOffset
private int GetAbsScaleOffset(GaugeCircularScale scale)
{
return ((int)(scale.AbsRadius * ScaleOffset));
}
#endregion
#region GetAbsScaleOffset
private int GetAbsScaleOffset(GaugeLinearScale scale)
{
return ((int)(scale.AbsWidth * ScaleOffset));
}
#endregion
#endregion
#region DValue
internal double DValue
{
get { return (_DValue); }
set
{
_DValue = value;
if (_Scale != null)
_Scale.GaugeControl.DValueChange = true;
OnGaugeItemChanged(true);
}
}
#endregion
#region MouseDownAngle
internal double MouseDownAngle
{
get { return (_MouseDownAngle); }
set { _MouseDownAngle = value; }
}
#endregion
#region MouseDownRadians
internal double MouseDownRadians
{
get { return (_MouseDownRadians); }
set { _MouseDownRadians = value; }
}
#endregion
#region Offset
internal int Offset
{
get { return (_Offset); }
}
#endregion
#region Radius
internal int Radius
{
get { return (_Radius); }
}
#endregion
#endregion
#region Event processing
void FillColorColorTableChanged(object sender, EventArgs e)
{
OnGaugeItemChanged(true);
}
#endregion
#region RecalcLayout
public override void RecalcLayout()
{
if (NeedRecalcLayout == true)
{
base.RecalcLayout();
if (Scale is GaugeCircularScale)
CalcCircularMetrics(Scale as GaugeCircularScale);
else if (Scale is GaugeLinearScale)
CalcLinearMetrics(Scale as GaugeLinearScale);
if (_Renderer != null)
_Renderer.RecalcLayout();
}
}
#region CalcCircularMetrics
private void CalcCircularMetrics(GaugeCircularScale scale)
{
int radius = scale.AbsRadius;
int offset = AbsScaleOffset;
int scaleWidth = (int)(radius * scale.Width);
switch (_Placement)
{
case DisplayPlacement.Near:
_Radius = radius - (scaleWidth / 2) + offset;
break;
case DisplayPlacement.Center:
_Radius = radius + offset;
break;
case DisplayPlacement.Far:
_Radius = radius + (scaleWidth / 2) + offset;
break;
}
}
#endregion
#region CalcLinearMetrics
private void CalcLinearMetrics(GaugeLinearScale scale)
{
int n = scale.AbsWidth;
int offset = AbsScaleOffset;
int scaleWidth = (int)(n * scale.Width);
switch (_Placement)
{
case DisplayPlacement.Near:
_Offset = (-scaleWidth / 2) - offset;
break;
case DisplayPlacement.Center:
_Offset = -offset;
break;
case DisplayPlacement.Far:
_Offset = (scaleWidth / 2) + offset;
break;
}
}
#endregion
#endregion
#region OnPaint
public override void OnPaint(PaintEventArgs e)
{
RecalcLayout();
if (Scale.GaugeControl.OnPreRenderScalePointer(e, this) == false)
{
if (_Renderer != null)
{
switch (_Scale.Style)
{
case GaugeScaleStyle.Circular:
_Renderer.RenderCircular(e);
break;
case GaugeScaleStyle.Linear:
_Renderer.RenderLinear(e);
break;
}
}
Scale.GaugeControl.OnPostRenderScalePointer(e, this);
}
}
#endregion
#region OnValueChanged
private void OnValueChanged(double oldValue, bool canDampen)
{
if (_Scale != null)
{
_Scale.GaugeControl.OnPointerValueChanged(this, oldValue, _Value);
if (_Scale.Visible == true)
{
UpdateStripData();
if (InitiateDampening(canDampen) == true)
return;
}
}
SetFinalOffsets();
DValue = _Value;
}
#endregion
#region Dampening support
#region InitiateDampening
private bool InitiateDampening(bool canDampen)
{
if (_Scale.GaugeControl.IsHandleCreated &&
_Scale.GaugeControl.InDesignMode == false)
{
if (_Renderer != null)
{
double min, max;
_Renderer.GetRangeEx(out min, out max);
if (_DValue < _Value)
{
double start = Math.Max(min, _DValue);
if (start < max)
{
if (StartDampening(canDampen, start, Math.Min(max, _Value)))
return (true);
}
}
else if (_DValue > _Value)
{
double start = Math.Min(max, _DValue);
if (start > min)
{
if (StartDampening(canDampen, start, Math.Max(min, _Value)))
return (true);
}
}
}
}
return (false);
}
#endregion
#region StartDampening
private bool StartDampening(bool canDampen, double start, double end)
{
double dampenTime = _DampeningSweepTime;
if (ValueInView(end) == false)
{
canDampen = true;
dampenTime = (_MouseDown == true || dampenTime <= 0)
? 2 : dampenTime;
}
if (canDampen == true && dampenTime > 0)
{
_DStartValue = start;
_DEndValue = end;
_DeltaValue = Scale.Spread / (dampenTime * 1000);
_DStartTicks = DateTime.Now.Ticks;
if (_Dampening == false)
{
_Dampening = true;
_DSlideScale = false;
_DShowMinLabel = _Scale.Labels.ShowMinLabel;
_DShowMaxLabel = _Scale.Labels.ShowMaxLabel;
_Scale.GaugeControl.DampeningUpdate += DampeningUpdate;
_Scale.GaugeControl.StartDampening();
}
return (true);
}
return (false);
}
#endregion
#region DampeningUpdate
void DampeningUpdate(object sender, EventArgs e)
{
SetScaleValue();
SetInterimOffsets();
if (_DValue == _DEndValue)
{
if (_MouseDown == true && _AllowUserChange == true)
{
if (_Renderer != null)
{
Point pt = Control.MousePosition;
Point pt2 = Scale.GaugeControl.PointToClient(pt);
ValueEx = _Renderer.GetValueFromPoint(pt2);
}
}
else
{
SetFinalOffsets();
}
}
}
#endregion
#region SetScaleValue
private void SetScaleValue()
{
double ms = new TimeSpan(DateTime.Now.Ticks - _DStartTicks).TotalMilliseconds;
double delta = _DeltaValue * ms;
double n = _DValue;
if (n < _Value)
n = Math.Min(_DStartValue + delta, _DEndValue);
else if (n > _Value)
n = Math.Max(_DStartValue - delta, _DEndValue);
SetScaleValue(n);
}
private void SetScaleValue(double n)
{
if (_DValue != _Value)
{
double spread = _Scale.Spread;
if (n > _Scale.MaxValue)
{
_Scale.MaxValue = Math.Min(n, _Scale.AbsMaxLimit);
_Scale.MinValue = _Scale.MaxValue - spread;
_DSlideScale = true;
}
else if (n < _Scale.MinValue)
{
_Scale.MinValue = Math.Max(n, _Scale.AbsMinLimit);
_Scale.MaxValue = _Scale.MinValue + spread;
_DSlideScale = true;
}
}
DValue = n;
}
#endregion
#region SetInterimOffsets
private void SetInterimOffsets()
{
if (_DSlideScale == true)
{
GaugeTickMark major = _Scale.MajorTickMarks;
GaugeTickMark minor = _Scale.MinorTickMarks;
major.IntervalOffset = GetIntervalOffset(major.Interval);
minor.IntervalOffset = GetIntervalOffset(minor.Interval);
if (_DShowMinLabel == true)
{
if (minor.Visible && minor.Interval > 0)
{
_Scale.Labels.ShowMinLabel =
(minor.IntervalOffset == 0);
}
else if (major.Visible && major.Interval > 0)
{
_Scale.Labels.ShowMinLabel =
(major.IntervalOffset == 0);
}
}
if (_DShowMaxLabel == true)
{
if (minor.Visible && minor.Interval > 0)
{
_Scale.Labels.ShowMaxLabel =
(_Scale.MaxValue % minor.Interval == 0);
}
else if (major.Visible && major.Interval > 0)
{
_Scale.Labels.ShowMaxLabel =
(_Scale.MaxValue % major.Interval == 0);
}
}
}
}
#endregion
#region SetFinalOffsets
private void SetFinalOffsets()
{
if (_DSlideScale == true)
{
GaugeTickMark major = _Scale.MajorTickMarks;
GaugeTickMark minor = _Scale.MinorTickMarks;
double interval;
if (_SnapInterval > 0)
{
interval = _SnapInterval;
}
else
{
interval = ((minor.Visible && minor.Interval > 0)
? minor.Interval : (major.Visible && major.Interval > 0)
? major.Interval : 1);
if ((int)interval == interval)
interval = 1;
}
double minLimit = _Scale.AbsMinLimit;
double k = (int)((_Scale.MinValue - minLimit) / interval) * interval + minLimit;
double spread = _Scale.Spread;
if (_DStartValue < _DEndValue && (k + spread < _Scale.MaxValue))
k += interval;
_Scale.MinValue = k;
_Scale.MaxValue = k + spread;
if (minor.Visible && minor.Interval > 0)
minor.IntervalOffset = GetIntervalOffset(minor.Interval);
if (major.Visible && major.Interval > 0)
major.IntervalOffset = GetIntervalOffset(major.Interval);
_Scale.Labels.ShowMinLabel = _DShowMinLabel;
_Scale.Labels.ShowMaxLabel = _DShowMaxLabel;
}
if (_Dampening == true)
{
_Scale.GaugeControl.StopDampening();
_Scale.GaugeControl.DampeningUpdate -= DampeningUpdate;
_Dampening = false;
}
}
#endregion
#region GetIntervalOffset
private double GetIntervalOffset(double interval)
{
double n = _Scale.MinValue - _Scale.AbsMinLimit;
return (Math.Ceiling(n / interval) * interval - n);
}
#endregion
#region ValueInView
private bool ValueInView(double value)
{
return ((_Scale.MinValue <= _Scale.AbsMinLimit || value >= _Scale.MinValue) &&
((_Scale.MaxValue >= _Scale.AbsMaxLimit || value <= _Scale.MaxValue)));
}
#endregion
#endregion
#region UpdateStripData
#region UpdateStripData
internal void UpdateStripData()
{
if (_Scale != null)
{
ProcessScaleChanges();
ProcessSectionChanges();
ProcessRangeChanges();
}
UpdateFillColors();
}
#endregion
#region ProcessScaleChanges
private void ProcessScaleChanges()
{
bool oldInScale = _InScale;
_InScale = (_Value >= Scale.MinValue && _Value <= Scale.MaxValue);
if (_Scale.GaugeControl != null)
{
if (_InScale != oldInScale)
{
if (_InScale == true)
Scale.GaugeControl.OnScaleEnter(this, Scale);
else
Scale.GaugeControl.OnScaleExit(this, Scale);
}
}
}
#endregion
#region ProcessSectionChanges
private void ProcessSectionChanges()
{
if (Scale.HasSections == true)
{
List<GaugeStrip> list = new List<GaugeStrip>();
foreach (GaugeSection section in Scale.Sections)
{
if (section.Visible == true)
{
if (section.ValueInRange(_Value) == true)
list.Add(section);
}
}
if (_Scale.GaugeControl != null)
{
if (_SectionList != null)
{
foreach (GaugeSection section in _SectionList)
{
if (list.Contains(section) == false)
Scale.GaugeControl.OnSectionExit(this, section);
}
}
foreach (GaugeSection section in list)
{
if (_SectionList == null || _SectionList.Contains(section) == false)
Scale.GaugeControl.OnSectionEnter(this, section);
}
}
_SectionList = list;
}
}
#endregion
#region ProcessRangeChanges
private void ProcessRangeChanges()
{
if (Scale.HasRanges == true)
{
List<GaugeStrip> list = new List<GaugeStrip>();
foreach (GaugeRange range in Scale.Ranges)
{
if (range.Visible == true)
{
if (range.ValueInRange(_Value) == true)
list.Add(range);
}
}
if (_Scale.GaugeControl != null)
{
if (_RangeList != null)
{
foreach (GaugeRange range in _RangeList)
{
if (list.Contains(range) == false)
Scale.GaugeControl.OnRangeExit(this, range);
}
}
foreach (GaugeRange range in list)
{
if (_RangeList == null || _RangeList.Contains(range) == false)
Scale.GaugeControl.OnRangeEnter(this, range);
}
}
_RangeList = list;
}
}
#endregion
#region UpdateFillColors
#region UpdateFillColors
private void UpdateFillColors()
{
_FillColorEx = GetFillColorEx(_RangeList)
?? (GetFillColorEx(_SectionList) ?? FillColor);
if (_Style == PointerStyle.Needle)
{
_CapFillColorEx = (GetCapFillColorEx(_RangeList)
?? GetCapFillColorEx(_SectionList)) ?? CapFillColor;
}
}
#endregion
#region GetFillColorEx
private GradientFillColor GetFillColorEx(List<GaugeStrip> list)
{
if (list != null)
{
for (int i = list.Count - 1; i >= 0; i--)
{
if (list[i].HasPointerFillColor == true)
return (list[i].PointerFillColor);
}
}
return (null);
}
#endregion
#region GetCapFillColorEx
private GradientFillColor GetCapFillColorEx(List<GaugeStrip> list)
{
if (list != null)
{
for (int i = list.Count - 1; i >= 0; i--)
{
if (list[i].HasCapFillColor == true)
return (list[i].CapFillColor);
}
}
return (null);
}
#endregion
#endregion
#endregion
#region EndInit
internal void EndInit()
{
UpdateStripData();
}
#endregion
#region FindItem
internal override GaugeItem FindItem(Point pt)
{
if (_Renderer != null)
{
GraphicsPath path = _Renderer.GetPointerPath();
if (path != null)
{
if (path.IsVisible(pt) == true)
return (this);
}
else
{
GaugeBarRenderer bar = _Renderer as GaugeBarRenderer;
if (bar != null)
{
Rectangle r;
if (Scale is GaugeCircularScale)
{
r = new Rectangle(
bar.IntervalPoint.X - 5, bar.IntervalPoint.Y - 5, 10, 10);
}
else
{
r = bar.Bounds;
if (r.Width < 10)
{
r.X -= 5;
r.Width = 10;
}
if (r.Height < 10)
{
r.Y -= 5;
r.Height = 10;
}
}
if (r.Contains(pt) == true)
return (this);
}
}
}
return (null);
}
#endregion
#region GetPointerPath
/// <summary>
/// Gets the Pointers GraphicsPath
/// </summary>
/// <returns>Pointers GraphicsPath</returns>
public GraphicsPath GetPointerPath()
{
if (_Renderer != null)
return (_Renderer.GetPointerPath());
return (null);
}
#endregion
#region GetCapBounds
/// <summary>
/// Gets the Pointer's Needle Cap bounds
/// </summary>
/// <returns></returns>
public Rectangle GetCapBounds()
{
if (_Renderer != null && _Renderer is GaugeNeedleRenderer)
return (((GaugeNeedleRenderer)_Renderer).CapBounds);
return (Rectangle.Empty);
}
#endregion
#region GetValueFromPoint
/// <summary>
/// Gets the value of the pointer from the given Point
/// </summary>
/// <param name="point">Point</param>
/// <returns>Value</returns>
public double GetValueFromPoint(Point point)
{
if (_Renderer != null)
return (_Renderer.GetValueFromPoint(point));
return (double.NaN);
}
#endregion
#region AppendTemplateText
protected override void ProcessTemplateText(
GaugeControl gauge, StringBuilder sb, string key, string data)
{
if (key.Equals("Value") == true)
{
sb.Append(string.IsNullOrEmpty(data)
? _Value.ToString()
: String.Format("{0:" + data + "}", _Value));
}
else
{
base.ProcessTemplateText(gauge, sb, key, data);
}
}
#endregion
#region Mouse processing
#region OnMouseEnter
internal override void OnMouseEnter()
{
base.OnMouseEnter();
if (_AllowUserChange == true)
Scale.GaugeControl.Cursor = _ChangeCursor;
}
#endregion
#region OnMouseMove
internal override void OnMouseMove(MouseEventArgs e, bool mouseDown)
{
base.OnMouseMove(e, mouseDown);
if (mouseDown == true)
{
if (_AllowUserChange == true)
{
if (_Renderer != null)
{
double oldValue = Value;
double newValue = _Renderer.GetValueFromPoint(e.Location);
if (newValue != oldValue)
{
if (Scale.GaugeControl.OnPointerChanging(this, oldValue, ref newValue) == false)
{
ValueEx = newValue;
Scale.GaugeControl.OnPointerChanged(this, oldValue, newValue);
}
}
}
}
}
}
#endregion
#region OnMouseDown
private bool _MouseDown;
internal override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (_AllowUserChange == true)
{
_MouseDown = true;
if (_Renderer != null)
_Renderer.OnMouseDown(e);
}
}
#endregion
#region OnMouseUp
internal override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
_MouseDown = false;
}
#endregion
#endregion
#region ICloneable Members
public override object Clone()
{
GaugePointer copy = new GaugePointer();
CopyToItem(copy);
return (copy);
}
#endregion
#region CopyToItem
public override void CopyToItem(GaugeItem copy)
{
GaugePointer c = copy as GaugePointer;
if (c != null)
{
base.CopyToItem(c);
c.AllowUserChange = _AllowUserChange;
c.BarStyle = _BarStyle;
c.BulbOffset = _BulbOffset;
c.BulbSize = _BulbSize;
if (_CapFillColor != null)
c.CapFillColor = (GradientFillColor) _CapFillColor.Clone();
c.CapImage = _CapImage;
c.CapInnerBevel = _CapInnerBevel;
c.CapOnTop = _CapOnTop;
c.CapOuterBevel = _CapOuterBevel;
c.CapStyle = _CapStyle;
c.CapWidth = _CapWidth;
c.ChangeCursor = _ChangeCursor;
c.DampeningSweepTime = _DampeningSweepTime;
if (_FillColor != null)
c.FillColor = (GradientFillColor)_FillColor.Clone();
c.HonorMaxPin = _HonorMaxPin;
c.HonorMinPin = _HonorMinPin;
c.Image = _Image;
c.Length = _Length;
c.MarkerStyle = _MarkerStyle;
c.NeedleStyle = _NeedleStyle;
c.Origin = _Origin;
c.OriginInterval = _OriginInterval;
c.Placement = _Placement;
c.RotateCap = _RotateCap;
c.ScaleOffset = _ScaleOffset;
c.SnapInterval = _SnapInterval;
c.Style = _Style;
if (_ThermoBackColor != null)
c.ThermoBackColor = (GradientFillColor)_ThermoBackColor.Clone();
c.UnderTickMarks = _UnderTickMarks;
c.Value = _Value;
c.Width = _Width;
}
}
#endregion
}
#region Enums
public enum PointerStyle
{
Bar,
Marker,
Needle,
Thermometer
}
public enum PointerOrigin
{
Minimum,
Maximum,
Custom
}
#endregion
}