using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace DevComponents.Instrumentation { public class NumericIndicator : GaugeIndicator { #region Private variables private NumericIndicatorStyle _Style; private int _NumberOfDigits; private int _NumberOfDecimals; private NumericElement[] _Digits; private Color _DigitColor; private Color _DigitDimColor; private Color _DecimalColor; private Color _DecimalDimColor; private float _SegmentWidth; private float _SeparatorWidth; private GradientFillColor _SeparatorColor; private DisplayPlacement _DigitPlacement; private string _FormatString; private Font _AbsFont; private bool _ShowDecimalPoint; private bool _ShowLeadingZeros; private bool _ShowDimColonPoints; private bool _ShowDimDecimalPoint; private bool _ShowDimSegments; private SignVisibility _SignVisibility; private float _ShearFactor; private Padding _Padding; private NumericRangeCollection _Ranges; #endregion public NumericIndicator() { InitIndicator(); } #region InitIndicator private void InitIndicator() { _NumberOfDigits = 6; _NumberOfDecimals = 2; _DecimalColor = Color.Firebrick; _DigitColor = Color.SteelBlue; _DigitPlacement = DisplayPlacement.Far; _Padding = new Padding(0); _SegmentWidth = .5f; _SeparatorWidth = .01f; _ShearFactor = -0.1f; _ShowDimColonPoints = true; _ShowDimDecimalPoint = true; _ShowDimSegments = true; _SignVisibility = SignVisibility.WhenNegative; _Style = NumericIndicatorStyle.Mechanical; AllocateElements(); } #endregion #region Public properties #region DecimalColor /// /// Gets or sets the default Decimal Color /// [Browsable(true), Category("Appearance"), DefaultValue(typeof(Color), "FireBrick")] [Description("Indicates the default Decimal Color.")] public Color DecimalColor { get { return (_DecimalColor); } set { if (_DecimalColor != value) { _DecimalColor = value; OnGaugeItemChanged(true); } } } #endregion #region DecimalDimColor /// /// Gets or sets the default Decimal Dim Color (Dim LED color) /// [Browsable(true), Category("Appearance")] [Description("Indicates the default Decimal Dim Color (Dim LED color).")] public Color DecimalDimColor { get { return (_DecimalDimColor); } set { if (_DecimalDimColor != value) { _DecimalDimColor = value; OnGaugeItemChanged(true); } } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal bool ShouldSerializeDecimalDimColor() { return (_DecimalDimColor.IsEmpty == false); } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal void ResetDecimalDimColor() { _DecimalDimColor = Color.Empty; } #endregion #region DigitColor /// /// Gets or sets the default Digit Color /// [Browsable(true), Category("Appearance"), DefaultValue(typeof(Color), "SteelBlue")] [Description("Indicates the default Digit Color.")] public Color DigitColor { get { return (_DigitColor); } set { if (_DigitColor != value) { _DigitColor = value; OnGaugeItemChanged(true); } } } #endregion #region DigitDimColor /// /// Gets or sets the default Digit Dim Color (Dim LED color) /// [Browsable(true), Category("Appearance")] [Description("Indicates the default Digit Dim Color (Dim LED color).")] public Color DigitDimColor { get { return (_DigitDimColor); } set { if (_DigitDimColor != value) { _DigitDimColor = value; OnGaugeItemChanged(true); } } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal bool ShouldSerializeDigitDimColor() { return (_DigitDimColor.IsEmpty == false); } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal void ResetDigitDimColor() { _DigitDimColor = Color.Empty; } #endregion #region DigitPlacement /// /// Gets or sets the Placement of the digits within the indicator /// [Browsable(true)] [Category("Appearance"), DefaultValue(DisplayPlacement.Far)] [Description("Indicates the Alignment of the digits.")] public DisplayPlacement DigitPlacement { get { return (_DigitPlacement); } set { if (_DigitPlacement != value) { _DigitPlacement = value; OnGaugeItemChanged(true); } } } #endregion #region Digits /// /// Gets the array of defined digits (units and decimals). /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public NumericElement[] Digits { get { return (_Digits); } } #endregion #region FormatString /// /// Gets or sets the .Net format string to use when displaying the indicator value. /// [Browsable(true), Category("Behavior"), DefaultValue(null)] [Description("Indicates the .Net format string to use when displaying the indicator value.")] [Editor("DevComponents.Instrumentation.Design.FormatStringEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))] public string FormatString { get { return (_FormatString); } set { if (_FormatString != value) { _FormatString = value; OnGaugeItemChanged(true); } } } #endregion #region NumberOfDecimals /// /// Gets or sets the number of decimals to display. /// [Browsable(true)] [Category("Appearance"), DefaultValue(2)] [Description("Determines the number of decimals to display.")] public int NumberOfDecimals { get { return (_NumberOfDecimals); } set { if (_NumberOfDecimals != value) { if (value > _NumberOfDigits) throw new ArgumentException("Number of decimals can not exceed NumberOfDigits."); _NumberOfDecimals = value; OnGaugeItemChanged(true); } } } #endregion #region NumberOfDigits /// /// Gets or sets the number of total digits to display (units and decimals). /// [Browsable(true)] [Category("Appearance"), DefaultValue(6)] [Description("Determines the number of total digits to display (units and decimals).")] public int NumberOfDigits { get { return (_NumberOfDigits); } set { if (_NumberOfDigits != value) { if (value < _NumberOfDecimals) throw new ArgumentException("Number of digits can not be less than NumberOfDecimals."); _NumberOfDigits = value; AbsFont = null; AllocateElements(); OnGaugeItemChanged(true); } } } #endregion #region Padding /// /// Gets or sets the indicator padding. /// [Browsable(true), Category("Layout")] [Description("Indicates the indicator padding.")] public Padding Padding { get { return (_Padding); } set { if (_Padding != value) { _Padding = value; OnGaugeItemChanged(true); } } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal bool ShouldSerializePadding() { return (_Padding.All != 0); } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal void ResetPadding() { _Padding = new Padding(0); } #endregion #region Ranges /// /// Gets the collection of Ranges associated with the Indicator /// [Browsable(true), Category("Behavior")] [Description("Indicates the collection of Ranges associated with the Indicator.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Editor("DevComponents.Instrumentation.Design.GaugeCollectionEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))] public NumericRangeCollection Ranges { get { if (_Ranges == null) { _Ranges = new NumericRangeCollection(); _Ranges.CollectionChanged += NumericRanges_CollectionChanged; } return (_Ranges); } set { if (_Ranges != null) _Ranges.CollectionChanged -= NumericRanges_CollectionChanged; _Ranges = value; if (_Ranges != null) _Ranges.CollectionChanged += NumericRanges_CollectionChanged; OnGaugeItemChanged(true); } } #endregion #region SegmentWidth /// /// Gets or sets the Digital segment width, specified as a percentage /// [Browsable(true), Category("Layout"), DefaultValue(.5f)] [Editor("DevComponents.Instrumentation.Design.RangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))] [Description("Indicates the Digital element width, specified as a percentage.")] public float SegmentWidth { get { return (_SegmentWidth); } set { if (_SegmentWidth != value) { if (value < 0 || value > 1) throw new ArgumentException("Value must be between 0 and +1."); _SegmentWidth = value; if (_Style != NumericIndicatorStyle.Mechanical) SetRecalcSegments(); OnGaugeItemChanged(true); } } } #endregion #region SeparatorColor /// /// Gets or sets the Digit Separator Color /// [Browsable(true), Category("Appearance")] [Description("Indicates the Digit Separator Color.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public GradientFillColor SeparatorColor { get { if (_SeparatorColor == null) { _SeparatorColor = new GradientFillColor(); _SeparatorColor.ColorTableChanged += Color_ColorTableChanged; } return (_SeparatorColor); } set { if (_SeparatorColor != null) _SeparatorColor.ColorTableChanged -= Color_ColorTableChanged; _SeparatorColor = value; if (_SeparatorColor != null) _SeparatorColor.ColorTableChanged += Color_ColorTableChanged; OnGaugeItemChanged(); } } #endregion #region SeparatorWidth /// /// Gets or sets the Length of the Pin, specified as a percentage /// [Browsable(true), Category("Layout"), DefaultValue(.01f)] [Editor("DevComponents.Instrumentation.Design.RangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))] [Description("Indicates the width of the Mechanical Style Digits Separator, specified as a percentage.")] public float SeparatorWidth { get { return (_SeparatorWidth); } set { if (_SeparatorWidth != value) { if (value < 0 || value > 1) throw new ArgumentException("Value must be between 0 and +1."); _SeparatorWidth = value; AbsFont = null; OnGaugeItemChanged(true); } } } #endregion #region ShearFactor /// /// Gets or Sets the shear coefficient for italicizing the Digits display /// [Browsable(true), Category("Appearance"), DefaultValue(-0.1F)] [Description("Indicates the shear coefficient for italicizing the Digits display. Default is -0.1")] public float ShearFactor { get { return (_ShearFactor); } set { if (_ShearFactor != value) { _ShearFactor = value; OnGaugeItemChanged(true); } } } #endregion #region ShowDecimalPoint /// /// Gets or sets whether the decimal point should be displayed /// [Browsable(true), Category("Appearance"), DefaultValue(false)] [Description("Indicates whether the decimal point should be displayed.")] public bool ShowDecimalPoint { get { return (_ShowDecimalPoint); } set { if (_ShowDecimalPoint != value) { _ShowDecimalPoint = value; OnGaugeItemChanged(true); } } } #endregion #region ShowDimColonPoints /// /// Gets or sets whether dim colon points should be displayed /// [Browsable(true), Category("Appearance"), DefaultValue(true)] [Description("Indicates whether dim colon points should be displayed.")] public bool ShowDimColonPoints { get { return (_ShowDimColonPoints); } set { if (_ShowDimColonPoints != value) { _ShowDimColonPoints = value; OnGaugeItemChanged(true); } } } #endregion #region ShowDimDecimalPoint /// /// Gets or sets whether dim decimal points should be displayed /// [Browsable(true), Category("Appearance"), DefaultValue(true)] [Description("Indicates whether dim decimal points should be displayed.")] public bool ShowDimDecimalPoint { get { return (_ShowDimDecimalPoint); } set { if (_ShowDimDecimalPoint != value) { _ShowDimDecimalPoint = value; OnGaugeItemChanged(true); } } } #endregion #region ShowDimSegments /// /// Gets or sets whether dim segments should be displayed /// [Browsable(true), Category("Appearance"), DefaultValue(true)] [Description("Indicates whether dim segments should be displayed.")] public bool ShowDimSegments { get { return (_ShowDimSegments); } set { if (_ShowDimSegments != value) { _ShowDimSegments = value; OnGaugeItemChanged(true); } } } #endregion #region ShowLeadingZeros /// /// Gets or sets whether leading zeros should be displayed /// [Browsable(true), Category("Appearance"), DefaultValue(false)] [Description("Indicates whether leading zeros should be displayed.")] public bool ShowLeadingZeros { get { return (_ShowLeadingZeros); } set { if (_ShowLeadingZeros != value) { _ShowLeadingZeros = value; OnGaugeItemChanged(true); } } } #endregion #region SignVisibility /// /// Gets or sets when the +/- sign should be displayed /// [Browsable(true), Category("Appearance"), DefaultValue(SignVisibility.WhenNegative)] [Description("Indicates when the +/- sign should be displayed.")] public SignVisibility SignVisibility { get { return (_SignVisibility); } set { if (_SignVisibility != value) { _SignVisibility = value; OnGaugeItemChanged(true); } } } #endregion #region Style /// /// Gets or sets the Indicator Style /// [Browsable(true), Category("Behavior"), DefaultValue(NumericIndicatorStyle.Mechanical)] [Description("Indicates the Indicator Style.")] public NumericIndicatorStyle Style { get { return (_Style); } set { if (_Style != value) { _Style = value; OnGaugeItemChanged(true); AllocateElements(); } } } #endregion #endregion #region Internal properties #region AbsFont internal override Font AbsFont { get { if (AutoSize == false || _NumberOfDigits <= 0) return (Font); if (_AbsFont == null) AbsFont = GetNewAbsFont(); return (_AbsFont); } set { if (_AbsFont != null) _AbsFont.Dispose(); _AbsFont = value; } } #region GetNewAbsFont private Font GetNewAbsFont() { int sepWidth = AbsSeparatorWidth; int width = (Bounds.Width - (_Padding.Left + _Padding.Right + BackColor.BorderWidth * 2)); int height = (Bounds.Height - (_Padding.Top + _Padding.Bottom + BackColor.BorderWidth * 2)); int n = (width - (_NumberOfDigits - 1) * sepWidth) / _NumberOfDigits; if (n <= 0) n = 2; int low = 2; int high = 128; while (low <= high) { int mid = (low + high) / 2; using (Font font = new Font(Font.FontFamily, mid, Font.Style)) { Size size = TextRenderer.MeasureText( string.IsNullOrEmpty(Text) ? "8" : "M", font); if (size.Height > height || size.Width > n) high = mid - 1; else if (size.Height < height && size.Width < n) low = mid + 1; else { low = mid; break; } } } return (new Font(Font.FontFamily, low, Font.Style)); } #endregion #endregion #region AbsSeparatorWidth internal int AbsSeparatorWidth { get { return ((int)(Bounds.Width * _SeparatorWidth)); } } #endregion #endregion #region Event processing #region Color_ColorTableChanged processing void Color_ColorTableChanged(object sender, EventArgs e) { OnGaugeItemChanged(true); } #endregion #region NumericRange processing void NumericRanges_CollectionChanged(object sender, EventArgs e) { foreach (NumericRange range in _Ranges) { range.NumericIndicator = this; range.IndicatorRangeChanged -= NumericRange_ItemChanged; range.IndicatorRangeChanged += NumericRange_ItemChanged; } } void NumericRange_ItemChanged(object sender, EventArgs e) { OnGaugeItemChanged(true); } #endregion #endregion #region SetRecalcSegments private void SetRecalcSegments() { if (_Digits != null) { foreach (DigitalElement item in _Digits) { if (item != null) { item.NeedRecalcLayout = true; item.NeedRecalcSegments = true; } } } } #endregion #region RecalcLayout public override void RecalcLayout() { if (NeedRecalcLayout == true) { base.RecalcLayout(); NeedRecalcLayout = true; AbsFont = null; if (_NumberOfDigits > 0) { LayoutElements(); UpdateElements(); } NeedRecalcLayout = false; } } #region AllocateElements private void AllocateElements() { NumericElement[] digit = new NumericElement[_NumberOfDigits]; for (int i = 0; i < _NumberOfDigits; i++) { NumericElement d; switch (_Style) { case NumericIndicatorStyle.Mechanical: d = new MechanicalElement(this); break; case NumericIndicatorStyle.Digital7Segment: d = new Seg7Element(this); break; default: d = new Seg16Element(this); break; } digit[i] = d; if (_Digits != null) { if (i < _Digits.Length) _Digits[i].CopyToItem(d); } } if (_Digits != null) { for (int i = _NumberOfDigits; i < _Digits.Length; i++) _Digits[i].Dispose(); } _Digits = digit; } #endregion #region LayoutElements private void LayoutElements() { if (_NumberOfDigits > 0) { int sepWidth = AbsSeparatorWidth; int width = Bounds.Width - (_Padding.Left + _Padding.Right + BackColor.BorderWidth * 2); int height = Bounds.Height - (_Padding.Top + _Padding.Bottom + BackColor.BorderWidth * 2); int shear = 0; if (Style != NumericIndicatorStyle.Mechanical) { int w = width / _NumberOfDigits; if (ShearFactor > 0) width -= (int)(w * _SegmentWidth); if (ShearFactor != 0) { shear = (int)(w * ShearFactor); width -= Math.Abs(shear); } } int ewidth = (width - (_NumberOfDigits - 1) * sepWidth) / _NumberOfDigits; int espread = width - ((ewidth + sepWidth) * _NumberOfDigits - sepWidth); Rectangle r = new Rectangle( Bounds.X + BackColor.BorderWidth + _Padding.Left, Bounds.Y + BackColor.BorderWidth + _Padding.Top, ewidth, height); if (shear < 0) r.X += -shear; for (int i = 0; i < _NumberOfDigits; i++) { r.Width = (ewidth + (i < espread ? 1 : 0)); _Digits[i].Bounds = r; r.X += (r.Width + sepWidth); } } } #endregion #region UpdateElements private void UpdateElements() { bool numeric; string s = GetOutputString(out numeric); if (s != null) { if (_Style == NumericIndicatorStyle.Mechanical) UpdateMechanicalElements(s, numeric); else UpdateSegmentedElements(s, numeric); } } #region GetOutputString private string GetOutputString(out bool numeric) { numeric = false; string s = GetOverrideString(); int nDigits; if (s != null) return (AlignOutputString(s, false, out nDigits)); numeric = true; return (GetValueString()); } #region GetValueString private string GetValueString() { int n = _NumberOfDigits; if ((_Style != NumericIndicatorStyle.Mechanical) || _ShowDecimalPoint == false) n++; string s = ""; if (String.IsNullOrEmpty(_FormatString) == false) { try { switch (_FormatString[0]) { case 'X': case 'x': s = String.Format("{0:" + _FormatString + "}", (int)DValue); break; default: s = String.Format("{0:" + _FormatString + "}", DValue); break; } } catch { } } else { string t = ".".PadLeft(Math.Max(1, n - _NumberOfDecimals), _ShowLeadingZeros ? '0' : '#') + "".PadLeft(_NumberOfDecimals, '0'); s = String.Format("{0:" + t + "}", Math.Abs(DValue)); s = ProcessSign(s); } int nDigits; s = AlignOutputString(s, _ShowDecimalPoint == false, out nDigits); if (s.Length > nDigits) return ("".PadRight(_NumberOfDigits, '-')); return (s); } #endregion #region ProcessSign private string ProcessSign(string s) { char sign = '\0'; if (Value < 0) { if (_SignVisibility == SignVisibility.Always || _SignVisibility == SignVisibility.WhenNegative) { sign = '-'; } } else { if (_SignVisibility == SignVisibility.Always || _SignVisibility == SignVisibility.WhenPositive) { sign = '+'; } } if (sign != '\0') { if (_ShowLeadingZeros == true) { if (s[0] != '0') return ("".PadRight(_NumberOfDigits, '-')); return (sign + s.Substring(1)); } return (sign + s); } return (s); } #endregion #region AlignOutputString private string AlignOutputString( string s, bool removeDp, out int nDigits) { nDigits = _NumberOfDigits; if (string.IsNullOrEmpty(s) == false) { if (Style != NumericIndicatorStyle.Mechanical && removeDp == false) { removeDp = true; if (s[0] == '.' || s[0] == ':') s = " " + s; } if (removeDp == true) { foreach (char c in s) { if (c == '.' || c == ':') nDigits++; } } switch (_DigitPlacement) { case DisplayPlacement.Center: int n = (nDigits - s.Length)/2; if (n > 0) s = s.PadLeft(s.Length + n, ' '); break; case DisplayPlacement.Far: if (s.Length < nDigits) s = s.PadLeft(nDigits, ' '); break; } } return (s); } #endregion #endregion #region UpdateMechanicalElements private void UpdateMechanicalElements(string s, bool numeric) { Color color, decimalColor; GetIndColors(out color, out decimalColor); int index = 0; for (int i = 0; i < s.Length; i++) { if (index >= _NumberOfDigits) break; if (numeric == true && s[i] == '.') { color = decimalColor; if (_ShowDecimalPoint == false) continue; } NumericElement element = _Digits[index++]; element.Value = s[i]; element.DigitColor = color; } for (int i = index; i < _NumberOfDigits; i++) { _Digits[i].Value = ' '; _Digits[i].DigitColor = color; } } #endregion #region UpdateSegmentedElements private void UpdateSegmentedElements(string s, bool numeric) { Color color, dimColor; Color decimalColor, decimalDimColor; GetIndColors(out color, out dimColor, out decimalColor, out decimalDimColor); int index = 0; for (int i = 0; i < s.Length; i++) { if (s[i] == '.') { if (numeric == true) { color = decimalColor; dimColor = decimalDimColor; if (_ShowDecimalPoint == false) continue; } if (index > 0) _Digits[index - 1].DecimalPointOn = true; } else if (s[i] == ':') { if (index > 0) _Digits[index - 1].ColonPointsOn = true; } else { if (index >= _NumberOfDigits) break; InitElement(_Digits[index++], s[i], color, dimColor); } } for (int i = index; i < _NumberOfDigits; i++) InitElement(_Digits[i], ' ', color, dimColor); } #region InitElement private void InitElement(NumericElement element, char value, Color color, Color dimColor) { element.Value = value; element.DigitColor = color; element.DigitDimColor = dimColor; element.ColonPointsOn = false; element.DecimalPointOn = false; element.ShowDimColonPoints = _ShowDimColonPoints; element.ShowDimDecimalPoint = _ShowDimDecimalPoint; element.ShowDimSegments = _ShowDimSegments; } #endregion #endregion #endregion #endregion #region OnPaint public override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; RecalcLayout(); Region rgn = g.Clip; Rectangle r = Bounds; r.Width++; r.Height++; g.SetClip(r, CombineMode.Intersect); if (GaugeControl.OnPreRenderIndicator(e, this) == false) { FillBackground(g, Bounds, GetBackColor()); DrawElements(e); DrawBorder(e); GaugeControl.OnPostRenderIndicator(e, this); } g.Clip = rgn; } #region FillBackground private void FillBackground(Graphics g, Rectangle bounds, GradientFillColor fillColor) { Rectangle r = bounds; GradientFillType fillType = fillColor.End.IsEmpty ? GradientFillType.None : fillColor.GradientFillType; switch (fillType) { case GradientFillType.Angle: using (Brush br = fillColor.GetBrush(r)) { if (br is LinearGradientBrush) ((LinearGradientBrush)br).WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, r); } break; case GradientFillType.StartToEnd: using (Brush br = fillColor.GetBrush(r, 90)) { if (br is LinearGradientBrush) ((LinearGradientBrush)br).WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, r); } break; case GradientFillType.HorizontalCenter: r.Height /= 2; if (r.Height <= 0) r.Height = 1; using (LinearGradientBrush br = new LinearGradientBrush(r, fillColor.Start, fillColor.End, 90)) { br.WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, bounds); } break; case GradientFillType.VerticalCenter: r.Width /= 2; if (r.Width <= 0) r.Width = 1; using (LinearGradientBrush br = new LinearGradientBrush(r, fillColor.Start, fillColor.End, 0f)) { br.WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, bounds); } break; case GradientFillType.Center: using (GraphicsPath path = new GraphicsPath()) { path.AddRectangle(r); using (PathGradientBrush br = new PathGradientBrush(path)) { br.CenterColor = fillColor.Start; br.SurroundColors = new Color[] { fillColor.End }; g.FillRectangle(br, r); } } break; default: using (Brush br = new SolidBrush(fillColor.Start)) g.FillRectangle(br, r); break; } } #endregion #region DrawElements private void DrawElements(PaintEventArgs e) { if (_Digits != null) { for (int i = 0; i < _Digits.Length; i++) { if (GaugeControl.OnPreRenderIndicatorDigit(e, this, _Digits[i], i) == false) { _Digits[i].OnPaint(e); GaugeControl.OnPostRenderIndicatorDigit(e, this, _Digits[i], i); } } } } #endregion #region DrawBorder private void DrawBorder(PaintEventArgs e) { Graphics g = e.Graphics; if (_Digits != null && _Style == NumericIndicatorStyle.Mechanical) { int sepWidth = AbsSeparatorWidth; if (sepWidth > 0 && _SeparatorColor != null) { for (int i = 0; i < _Digits.Length - 1; i++) { Rectangle r = _Digits[i].Bounds; r.X = r.Right + 1; r.Y = Bounds.Y + BackColor.BorderWidth; r.Width = sepWidth; r.Height = Bounds.Height - (BackColor.BorderWidth * 2); FillBackground(g, r, _SeparatorColor); if (_SeparatorColor.BorderWidth > 0) { using (Pen pen = new Pen(_SeparatorColor.BorderColor, _SeparatorColor.BorderWidth)) { pen.Alignment = PenAlignment.Inset; g.DrawLine(pen, r.X, r.Y, r.X, r.Bottom); g.DrawLine(pen, r.Right, r.Y, r.Right, r.Bottom); } } } } } if (BackColor.BorderWidth > 0) { using (Pen pen = new Pen(BackColor.BorderColor, BackColor.BorderWidth)) { pen.Alignment = PenAlignment.Inset; g.DrawRectangle(pen, Bounds); } } } #endregion #endregion #region GetBackColor private GradientFillColor GetBackColor() { if (_Ranges != null) { NumericRange range = _Ranges.GetValueRange(Value); if (range != null && (range.BackColor.IsEmpty == false)) return (range.BackColor); } return (BackColor); } #endregion #region GetIndColors private void GetIndColors(out Color digitColor, out Color decimalColor) { digitColor = _DigitColor; decimalColor = _DecimalColor; if (_Ranges != null) { foreach (NumericRange range in _Ranges) { if (Value >= range.StartValue && Value <= range.EndValue) { if (range.DigitColor.IsEmpty == false) digitColor = range.DigitColor; if (range.DecimalColor.IsEmpty == false) decimalColor = range.DecimalColor; break; } } } } private void GetIndColors(out Color digitColor, out Color digitDimColor, out Color decimalColor,out Color decimalDimColor) { digitColor = _DigitColor; decimalColor = _DecimalColor; digitDimColor = _DigitDimColor; decimalDimColor = _DecimalDimColor; if (_Ranges != null) { foreach (NumericRange range in _Ranges) { if (Value >= range.StartValue && Value <= range.EndValue) { if (range.DigitColor.IsEmpty == false) digitColor = range.DigitColor; if (range.DecimalColor.IsEmpty == false) decimalColor = range.DecimalColor; if (range.DigitDimColor.IsEmpty == false) digitDimColor = range.DigitDimColor; if (range.DecimalDimColor.IsEmpty == false) decimalDimColor = range.DecimalDimColor; break; } } } } #endregion #region Refresh internal void Refresh() { if (NeedRecalcLayout == false) OnGaugeItemChanged(false); } #endregion #region RefreshElements public void RefreshElements() { if (_Digits != null) { foreach (NumericElement item in _Digits) item.RefreshElements(); Refresh(); } } #endregion #region CopyToItem public override void CopyToItem(GaugeItem copy) { NumericIndicator c = copy as NumericIndicator; if (c != null) { base.CopyToItem(c); c.DecimalColor = _DecimalColor; c.DecimalDimColor = _DecimalDimColor; c.DigitColor = _DigitColor; c.DigitDimColor = _DigitDimColor; c.DigitPlacement = _DigitPlacement; c.FormatString = _FormatString; c.NumberOfDecimals = _NumberOfDecimals; c.NumberOfDigits = _NumberOfDigits; c.Padding = _Padding; if (_Ranges != null) c.Ranges = (NumericRangeCollection)_Ranges.Clone(); c.SegmentWidth = _SegmentWidth; if (_SeparatorColor != null) c.SeparatorColor = (GradientFillColor)_SeparatorColor.Clone(); c.SeparatorWidth = _SeparatorWidth; c.ShearFactor = _ShearFactor; c.ShowDecimalPoint = _ShowDecimalPoint; c.ShowDimColonPoints = _ShowDimColonPoints; c.ShowDimDecimalPoint = _ShowDimDecimalPoint; c.ShowDimSegments = _ShowDimSegments; c.ShowLeadingZeros = _ShowLeadingZeros; c.SignVisibility = _SignVisibility; c.Style = _Style; } } #endregion } #region Enums public enum NumericIndicatorStyle { Mechanical, Digital7Segment, Digital16Segment } public enum SignVisibility { Never, WhenNegative, WhenPositive, Always } #endregion }