using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Drawing.Drawing2D; using System.Text; namespace DevComponents.Instrumentation { public class GaugeStrip : GaugeItem, IDisposable { #region Events [Description("Occurs when the coverage of a Strip changes.")] public event EventHandler StripCoverChanged; #endregion #region Private variables private double _StartValue; private double _EndValue; private float _ScaleOffset; private GradientFillColor _FillColor; private Color _LabelColor; private GradientFillColor _CapFillColor; private GradientFillColor _PointerFillColor; private GradientFillColor _MajorTickMarkFillColor; private GradientFillColor _MinorTickMarkFillColor; private GaugeScale _Scale; private float _StartAngle; private float _SweepAngle; private double _MinValue; private double _MaxValue; private Rectangle _Bounds; private GraphicsPath _StripePath; #endregion public GaugeStrip(GaugeScale scale) : this() { _Scale = scale; } public GaugeStrip() { FillColor = new GradientFillColor(); _StartValue = double.NaN; _EndValue = double.NaN; } #region Public properties #region CapFillColor /// /// Gets or sets the Cap Fill Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the Cap Fill Color.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public GradientFillColor CapFillColor { get { if (_CapFillColor == null) { _CapFillColor = new GradientFillColor(); _CapFillColor.ColorTableChanged += PointerFillColor_ColorTableChanged; } return (_CapFillColor); } set { if (_CapFillColor != null) _CapFillColor.ColorTableChanged -= PointerFillColor_ColorTableChanged; _CapFillColor = value; if (_CapFillColor != null) _CapFillColor.ColorTableChanged += PointerFillColor_ColorTableChanged; OnGaugeItemChanged(true); } } #endregion #region EndValue /// /// Gets or sets the Ending value for the area /// [Browsable(true), Category("Layout"), DefaultValue(double.NaN)] [Description("Indicates the Ending value for the area.")] public double EndValue { get { return (_EndValue); } set { if (_EndValue != value) { _EndValue = value; OnStripCoverChanged(); } } } #endregion #region PointerFillColor /// /// Gets or sets the Pointer Fill Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the Pointer Fill Color.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public GradientFillColor PointerFillColor { get { if (_PointerFillColor == null) { _PointerFillColor = new GradientFillColor(); _PointerFillColor.ColorTableChanged += PointerFillColor_ColorTableChanged; } return (_PointerFillColor); } set { if (_PointerFillColor != null) _PointerFillColor.ColorTableChanged -= PointerFillColor_ColorTableChanged; _PointerFillColor = value; if (_PointerFillColor != null) _PointerFillColor.ColorTableChanged += PointerFillColor_ColorTableChanged; OnGaugeItemChanged(true); } } #endregion #region FillColor /// /// Gets or sets the area Fill Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the area Fill Color.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public GradientFillColor FillColor { get { if (_FillColor == null) { _FillColor = new GradientFillColor(); _FillColor.ColorTableChanged += FillColor_ColorTableChanged; } return (_FillColor); } set { if (_FillColor != null) _FillColor.ColorTableChanged -= FillColor_ColorTableChanged; _FillColor = value; if (_FillColor != null) _FillColor.ColorTableChanged += FillColor_ColorTableChanged; OnGaugeItemChanged(); } } #endregion #region LabelColor /// /// Gets or sets the Section Label Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the Section Label Color.")] public Color LabelColor { get { return (_LabelColor); } set { if (_LabelColor != value) { _LabelColor = value; OnGaugeItemChanged(); } } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal virtual bool ShouldSerializeLabelColor() { return (_LabelColor.IsEmpty == false); } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal virtual void ResetLabelColor() { LabelColor = Color.Empty; } #endregion #region MajorTickMarkFillColor /// /// Gets or sets the MajorTickMark Fill Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the MajorTickMark Fill Color.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public GradientFillColor MajorTickMarkFillColor { get { if (_MajorTickMarkFillColor == null) { _MajorTickMarkFillColor = new GradientFillColor(); _MajorTickMarkFillColor.ColorTableChanged += TickMarkFillColor_ColorTableChanged; } return (_MajorTickMarkFillColor); } set { if (_MajorTickMarkFillColor != null) _MajorTickMarkFillColor.ColorTableChanged -= TickMarkFillColor_ColorTableChanged; _MajorTickMarkFillColor = value; if (_MajorTickMarkFillColor != null) _MajorTickMarkFillColor.ColorTableChanged += TickMarkFillColor_ColorTableChanged; OnGaugeItemChanged(true); } } #endregion #region MinorTickMarkFillColor /// /// Gets or sets the MinorTickMark Fill Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the MinorTickMark Fill Color.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public GradientFillColor MinorTickMarkFillColor { get { if (_MinorTickMarkFillColor == null) { _MinorTickMarkFillColor = new GradientFillColor(); _MinorTickMarkFillColor.ColorTableChanged += TickMarkFillColor_ColorTableChanged; } return (_MinorTickMarkFillColor); } set { if (_MinorTickMarkFillColor != null) _MinorTickMarkFillColor.ColorTableChanged -= TickMarkFillColor_ColorTableChanged; _MinorTickMarkFillColor = value; if (_MinorTickMarkFillColor != null) _MinorTickMarkFillColor.ColorTableChanged += TickMarkFillColor_ColorTableChanged; OnGaugeItemChanged(true); } } #endregion #region Scale /// /// Gets the associated Scale /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public GaugeScale Scale { get { return (_Scale); } internal set { _Scale = value; } } #endregion #region ScaleOffset /// /// Gets or sets the distance from the Scale, measured as a percentage /// [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 Scale, measured as a percentage.")] public float ScaleOffset { get { return (_ScaleOffset); } set { if (_ScaleOffset != value) { if (value < -1 || value > 1) throw new ArgumentException("Scale Offset must be bwtween -1 and +1"); _ScaleOffset = value; OnGaugeItemChanged(true); } } } #endregion #region StartValue /// /// Gets or sets the Starting value for the area /// [Browsable(true), Category("Layout"), DefaultValue(double.NaN)] [Description("Indicates the Starting value for the area.")] public double StartValue { get { return (_StartValue); } set { if (_StartValue != value) { _StartValue = value; OnStripCoverChanged(); } } } private void OnStripCoverChanged() { if (StripCoverChanged != null) StripCoverChanged(this, EventArgs.Empty); OnGaugeItemChanged(true); } #endregion #region Visible /// /// Gets or sets the item Visibility state. /// [Browsable(true), Category("Appearance"), DefaultValue(true)] [Description("Indicates the item Visibility state.")] [ParenthesizePropertyName(true)] public override bool Visible { get { return (base.Visible); } set { if (base.Visible != value) { base.Visible = value; OnStripCoverChanged(); } } } #endregion #endregion #region Internal properties #region Bounds internal Rectangle Bounds { get { return (_Bounds); } set { _Bounds = value; } } #endregion #region HasCapFillColor internal bool HasCapFillColor { get { return (_CapFillColor != null && _CapFillColor.IsEmpty == false); } } #endregion #region HasMajorTickMarkFillColor internal bool HasMajorTickMarkFillColor { get { return (_MajorTickMarkFillColor != null && _MajorTickMarkFillColor.IsEmpty == false); } } #endregion #region HasMinorTickMarkFillColor internal bool HasMinorTickMarkFillColor { get { return (_MinorTickMarkFillColor != null && _MinorTickMarkFillColor.IsEmpty == false); } } #endregion #region HasPointerFillColor internal bool HasPointerFillColor { get { return (_PointerFillColor != null && _PointerFillColor.IsEmpty == false); } } #endregion #region MaxValue internal double MaxValue { get { return (_MaxValue); } set { _MaxValue = value; } } #endregion #region MinValue internal double MinValue { get { return (_MinValue); } set { _MinValue = value; } } #endregion #region StartAngle internal float StartAngle { get { return (_StartAngle); } } #endregion #region StripePath internal GraphicsPath StripePath { get { return (_StripePath); } set { if (_StripePath != value) { if (_StripePath != null) _StripePath.Dispose(); _StripePath = value; } } } #endregion #region SweepAngle internal float SweepAngle { get { return (_SweepAngle); } } #endregion #endregion #region Event processing void FillColor_ColorTableChanged(object sender, EventArgs e) { OnGaugeItemChanged(true); } void TickMarkFillColor_ColorTableChanged(object sender, EventArgs e) { OnGaugeItemChanged(true); } void PointerFillColor_ColorTableChanged(object sender, EventArgs e) { OnGaugeItemChanged(true); } #endregion #region RecalcLayout public override void RecalcLayout() { if (NeedRecalcLayout == true) { base.RecalcLayout(); CalcStripMetrics(); _Scale.NeedTickMarkRecalcLayout = true; _Scale.NeedPointerRecalcLayout = true; StripePath = null; } } #region CalcStripMetrics private void CalcStripMetrics() { _MinValue = (_StartValue.Equals(double.NaN) ? _Scale.MinValue : _StartValue); _MaxValue = (_EndValue.Equals(double.NaN) ? _Scale.MaxValue : _EndValue); if (_MinValue > _Scale.MaxValue) _MinValue = _Scale.MaxValue; _MinValue -= _Scale.MinValue; if (_MinValue < 0) _MinValue = 0; if (_MaxValue < _Scale.MinValue) _MaxValue = _Scale.MinValue; _MaxValue -= _Scale.MinValue; if (_MaxValue > _Scale.MaxValue - _Scale.MinValue) _MaxValue = _Scale.MaxValue - _Scale.MinValue; if (Scale is GaugeCircularScale) CalcCircularMetrics(Scale as GaugeCircularScale); } #region CalcCircularMetrics private void CalcCircularMetrics(GaugeCircularScale scale) { float spread = (float)Math.Abs(scale.MaxValue - scale.MinValue); if (spread == 0) spread = 1; float dv = scale.SweepAngle / spread; _StartAngle = (float)(dv * _MinValue) + scale.StartAngle; _SweepAngle = (float)(dv * (_MaxValue - _MinValue)); if (scale.Reversed == true) { _StartAngle = (scale.StartAngle + scale.SweepAngle) - (_StartAngle - scale.StartAngle); _SweepAngle = -_SweepAngle; } } #endregion #endregion #endregion #region GetPoint protected PointF GetPoint(float radius, float angle) { PointF pt = new PointF(); // Normalize the angle and calculate some // working vars if (angle < 0) angle += 360; angle = angle % 360; // Determine the angle quadrant, and then calculate // the intersecting coordinate accordingly double radians = GetRadians(angle % 90); if (angle < 90) { pt.X = (float)(Math.Cos(radians) * radius); pt.Y = (float)(Math.Sin(radians) * radius); } else if (angle < 180) { pt.X = -(float)(Math.Sin(radians) * radius); pt.Y = (float)(Math.Cos(radians) * radius); } else if (angle < 270) { pt.X = -(float)(Math.Cos(radians) * radius); pt.Y = -(float)(Math.Sin(radians) * radius); } else { pt.X = (float)(Math.Sin(radians) * radius); pt.Y = -(float)(Math.Cos(radians) * radius); } pt.X += _Scale.Center.X; pt.Y += _Scale.Center.Y; return (pt); } #endregion #region GetRadians /// /// Converts Degrees to Radians /// /// Degrees /// Radians protected double GetRadians(float theta) { return (theta * Math.PI / 180); } #endregion #region ValueInRange internal bool ValueInRange(double value) { RecalcLayout(); double startValue = (_StartValue.Equals(double.NaN) ? MinValue : _StartValue); double endValue = (_EndValue.Equals(double.NaN) ? MaxValue : _EndValue); if (startValue > endValue) { double temp = startValue; startValue = endValue; endValue = temp; } return (value >= startValue && value <= endValue); } #endregion #region ProcessTemplateText protected override void ProcessTemplateText( GaugeControl gauge, StringBuilder sb, string key, string data) { switch (key) { case "StartValue": sb.Append(string.IsNullOrEmpty(data) ? _StartValue.ToString() : String.Format("{0:" + data + "}", _StartValue)); break; case "EndValue": sb.Append(string.IsNullOrEmpty(data) ? _EndValue.ToString() : String.Format("{0:" + data + "}", _EndValue)); break; default: base.ProcessTemplateText(gauge, sb, key, data); break; } } #endregion #region IDisposable Members void IDisposable.Dispose() { StripePath = null; } #endregion #region ICloneable Members public override object Clone() { GaugeStrip copy = new GaugeStrip(); CopyToItem(copy); return (copy); } #endregion #region CopyToItem public override void CopyToItem(GaugeItem copy) { GaugeStrip c = copy as GaugeStrip; if (c != null) { base.CopyToItem(c); if (_CapFillColor != null) c.CapFillColor = (GradientFillColor)_CapFillColor.Clone(); c.EndValue = _EndValue; if (_PointerFillColor != null) c.PointerFillColor = (GradientFillColor)_PointerFillColor.Clone(); if (_FillColor != null) c.FillColor = (GradientFillColor)_FillColor.Clone(); c.LabelColor = _LabelColor; if (_MajorTickMarkFillColor != null) c.MajorTickMarkFillColor = (GradientFillColor)_MajorTickMarkFillColor.Clone(); if (_MinorTickMarkFillColor != null) c.MinorTickMarkFillColor = (GradientFillColor)_MinorTickMarkFillColor.Clone(); c.ScaleOffset = _ScaleOffset; c.StartValue = _StartValue; } } #endregion } }