586 lines
16 KiB
C#

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Windows.Forms;
namespace DevComponents.Instrumentation
{
[TypeConverter(typeof(GaugeLabelConvertor))]
public class GaugeIntervalLabel : GaugeBaseLabel
{
#region Private variables
private double _Interval;
private double _IntervalOffset;
private LabelPoint[] _LabelPoints;
private bool _ShowMaxLabel;
private bool _ShowMinLabel;
private string _FormatString;
#endregion
public GaugeIntervalLabel(GaugeScale scale)
{
Scale = scale;
_Interval = double.NaN;
_IntervalOffset = double.NaN;
_ShowMinLabel = true;
_ShowMaxLabel = true;
}
#region Hidden properties
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new string Name
{
get { return (base.Name); }
set { base.Name = value; }
}
#endregion
#region Public properties
#region FormatString
/// <summary>
/// Gets or sets the .Net format string used to display all non-custom defined labels.
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(null)]
[Description("Indicates the .Net format string used to display all non-custom defined labels.")]
[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 Interval
/// <summary>
/// Gets or sets the Label Interval
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(double.NaN)]
[Description("Indicates the Label Interval.")]
public double Interval
{
get { return (_Interval); }
set
{
if (value < 0)
throw new ArgumentException("Value can not be less than zero.");
if (_Interval != value)
{
_Interval = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region IntervalOffset
/// <summary>
/// Gets or sets the Label Interval Offset
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(double.NaN)]
[Description("Indicates the Label Interval Offset.")]
public double IntervalOffset
{
get { return (_IntervalOffset); }
set
{
if (value < 0)
throw new ArgumentException("Value can not be less than zero.");
if (_IntervalOffset != value)
{
_IntervalOffset = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region ShowMaxLabel
/// <summary>
/// Gets or sets whether to show the Maximum Scale label
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(true)]
[Description("Indicates whether to show the Maximum Scale label.")]
public bool ShowMaxLabel
{
get { return (_ShowMaxLabel); }
set
{
if (_ShowMaxLabel != value)
{
_ShowMaxLabel = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#region ShowMinLabel
/// <summary>
/// Gets or sets whether to show the Minimum Scale label
/// </summary>
[Browsable(true), Category("Appearance"), DefaultValue(true)]
[Description("Indicates whether to show the Minimum Scale label.")]
public bool ShowMinLabel
{
get { return (_ShowMinLabel); }
set
{
if (_ShowMinLabel != value)
{
_ShowMinLabel = value;
OnGaugeItemChanged(true);
}
}
}
#endregion
#endregion
#region RecalcLayout
public override void RecalcLayout()
{
if (NeedRecalcLayout == true)
{
base.RecalcLayout();
CalcLabelPoints();
}
}
#region CalcLabelPoints
private void CalcLabelPoints()
{
if (Scale is GaugeCircularScale)
CalcCircularLabelPoints(Scale as GaugeCircularScale);
else if (Scale is GaugeLinearScale)
CalcLinearLabelPoints(Scale as GaugeLinearScale);
}
#region CalcCircularLabelPoints
private void CalcCircularLabelPoints(GaugeCircularScale scale)
{
double labelInterval = (_Interval.Equals(double.NaN) ?
scale.MajorTickMarks.Interval : _Interval);
double labelIntervalOffset = (_IntervalOffset.Equals(double.NaN) ?
scale.MajorTickMarks.IntervalOffset : _IntervalOffset);
double spread = scale.MaxValue - scale.MinValue;
double dpt = scale.SweepAngle / spread;
int n = GetPointCount(spread, labelInterval, labelIntervalOffset);
if (n > 0)
{
double startAngle = scale.StartAngle;
double interval = (_ShowMinLabel == true ? 0 : labelIntervalOffset > 0 ? labelIntervalOffset : labelInterval);
int dir = (scale.Reversed ? -1 : 1);
if (scale.Reversed == true)
startAngle += scale.SweepAngle;
_LabelPoints = new LabelPoint[n];
for (int i = 0; i < n; i++)
{
_LabelPoints[i] = new LabelPoint();
if (interval + scale.MinValue > scale.MaxValue)
interval = scale.MaxValue - scale.MinValue;
_LabelPoints[i].Angle = (float)(startAngle + (interval * dpt) * dir);
_LabelPoints[i].Point = scale.GetPoint(Radius, _LabelPoints[i].Angle);
_LabelPoints[i].Interval = interval;
if (interval >= labelIntervalOffset)
interval += labelInterval;
else
interval = labelIntervalOffset;
}
}
else
{
_LabelPoints = null;
}
}
#endregion
#region CalcLinearLabelPoints
private void CalcLinearLabelPoints(GaugeLinearScale scale)
{
double labelInterval = (_Interval.Equals(double.NaN) ?
scale.MajorTickMarks.Interval : _Interval);
double labelIntervalOffset = (_IntervalOffset.Equals(double.NaN) ?
scale.MajorTickMarks.IntervalOffset : _IntervalOffset);
double spread = Math.Abs(scale.MaxValue - scale.MinValue);
double dpt = scale.AbsScaleLength / spread;
int n = GetPointCount(spread, labelInterval, labelIntervalOffset);
if (n > 0)
{
if (scale.Orientation == Orientation.Horizontal)
CalcHorizontalLabelPoints(scale, n, dpt, labelInterval, labelIntervalOffset);
else
CalcVerticalLabelPoints(scale, n, dpt, labelInterval, labelIntervalOffset);
}
else
{
_LabelPoints = null;
}
}
#region CalcHorizontalLabelPoints
private void CalcHorizontalLabelPoints(GaugeLinearScale scale,
int n, double dpt, double labelInterval, double labelIntervalOffset)
{
double interval = (_ShowMinLabel == true ?
0 : labelIntervalOffset > 0 ? labelIntervalOffset : labelInterval);
int y = scale.ScaleBounds.Y + Offset;
_LabelPoints = new LabelPoint[n];
for (int i = 0; i < n; i++)
{
_LabelPoints[i] = new LabelPoint();
if (interval + Scale.MinValue > Scale.MaxValue)
interval = Scale.MaxValue - Scale.MinValue;
int x = (scale.Reversed == true)
? (int)(Scale.Bounds.Right - dpt * interval)
: (int)(Scale.Bounds.X + dpt * interval);
_LabelPoints[i].Point = new Point(x, y);
_LabelPoints[i].Interval = interval;
if (interval >= labelIntervalOffset)
interval += labelInterval;
else
interval = labelIntervalOffset;
}
}
#endregion
#region CalcVerticalLabelPoints
private void CalcVerticalLabelPoints(GaugeLinearScale scale,
int n, double dpt, double labelInterval, double labelIntervalOffset)
{
double interval = (_ShowMinLabel == true ?
0 : labelIntervalOffset > 0 ? labelIntervalOffset : labelInterval);
int x = scale.ScaleBounds.X + Offset;
_LabelPoints = new LabelPoint[n];
for (int i = 0; i < n; i++)
{
_LabelPoints[i] = new LabelPoint();
if (interval + Scale.MinValue > Scale.MaxValue)
interval = Scale.MaxValue - Scale.MinValue;
int y = (scale.Reversed == true)
? (int)(Scale.Bounds.Top + dpt * interval)
: (int)(Scale.Bounds.Bottom - dpt * interval);
_LabelPoints[i].Point = new Point(x, y);
_LabelPoints[i].Interval = interval;
if (interval >= labelIntervalOffset)
interval += labelInterval;
else
interval = labelIntervalOffset;
}
}
#endregion
#endregion
#region GetPointCount
private int GetPointCount(double spread,
double labelInterval, double labelIntervalOffset)
{
int n = (int)Math.Ceiling((spread - labelIntervalOffset) / labelInterval) + 1;
if (labelIntervalOffset == 0)
{
if (_ShowMinLabel == false)
n--;
}
else
{
if (_ShowMinLabel == true)
n++;
}
if (_ShowMaxLabel == false)
n--;
return (n);
}
#endregion
#endregion
#endregion
#region OnPaint
public override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
RecalcLayout();
if (Scale.GaugeControl.OnPreRenderScaleTickMarkLabels(e, Scale) == false)
{
if (_LabelPoints != null)
{
Font font = AbsFont;
SolidBrush br = null;
try
{
foreach (LabelPoint lp in _LabelPoints)
{
if (CanDisplayLabel(lp) == true)
{
br = GetLabelBrush(br, lp);
PaintLabel(g, GetLabelText(lp), br, lp, font);
}
}
}
finally
{
if (br != null)
br.Dispose();
}
}
Scale.GaugeControl.OnPostRenderScaleTickMarkLabels(e, Scale);
}
}
#region GetLabelText
private string GetLabelText(LabelPoint labelPoint)
{
double n = Scale.GetIntervalValue(labelPoint.Interval);
if (String.IsNullOrEmpty(_FormatString) == false)
{
try
{
switch (_FormatString[0])
{
case 'X':
case 'x':
return (String.Format("{0:" + _FormatString + "}", (int) n));
default:
return (String.Format("{0:" + _FormatString + "}", n));
}
}
catch
{
}
}
return (n.ToString());
}
#endregion
#region GetLabelBrush
private SolidBrush GetLabelBrush(SolidBrush br, LabelPoint lp)
{
Color color = GetLabelColor(lp);
if (br == null || br.Color != color)
{
if (br != null)
br.Dispose();
br = new SolidBrush(color);
}
return (br);
}
#endregion
#region GetLabelColor
private Color GetLabelColor(LabelPoint lp)
{
Color labelColor = Scale.GetRangeLabelColor(lp.Interval);
if (labelColor.IsEmpty == true)
labelColor = Scale.GetSectionLabelColor(lp.Interval);
if (labelColor.IsEmpty == true)
labelColor = Layout.ForeColor;
return (labelColor);
}
#endregion
#region CanDisplayLabel
private bool CanDisplayLabel(LabelPoint labelPoint)
{
if (labelPoint.Visible == false)
return (false);
if (Scale.HasCustomLabels == true)
{
foreach (GaugeCustomLabel label in Scale.CustomLabels)
{
if (label.Visible == true)
{
if (label.Layout.Placement == Layout.Placement)
{
if (label.Value == Scale.MinValue + labelPoint.Interval)
return (false);
}
}
}
}
return (true);
}
#endregion
#endregion
#region ICloneable Members
public override object Clone()
{
GaugeIntervalLabel copy = new GaugeIntervalLabel(Scale);
CopyToItem(copy);
return (copy);
}
#endregion
#region CopyToItem
public override void CopyToItem(GaugeItem copy)
{
GaugeIntervalLabel c = copy as GaugeIntervalLabel;
if (c != null)
{
base.CopyToItem(c);
c.FormatString = _FormatString;
c.Interval = _Interval;
c.IntervalOffset = _IntervalOffset;
c.ShowMaxLabel = _ShowMaxLabel;
c.ShowMinLabel = _ShowMinLabel;
}
}
#endregion
}
#region GaugeLabelConvertor
public class GaugeLabelConvertor : ExpandableObjectConverter
{
public override object ConvertTo(
ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
GaugeIntervalLabel label = value as GaugeIntervalLabel;
if (label != null)
{
//ColorConverter cvt = new ColorConverter();
//if (lct.Start != Color.Empty)
// return (cvt.ConvertToString(lct.Start));
//if (lct.End != Color.Empty)
// return (cvt.ConvertToString(lct.End));
//if (lct.GradientAngle != 90)
// return (lct.GradientAngle.ToString());
return (String.Empty);
}
}
return (base.ConvertTo(context, culture, value, destinationType));
}
}
#endregion
}