using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Drawing.Drawing2D; using System.Globalization; using System.Windows.Forms; using DevComponents.Instrumentation.Primitives; namespace DevComponents.Instrumentation { /// /// Collection of GaugeSections /// public class GaugeSectionCollection : GenericCollection { #region ICloneable Members public override object Clone() { GaugeSectionCollection copy = new GaugeSectionCollection(); CopyToItem(copy); return (copy); } #endregion #region CopyToItem internal void CopyToItem(GaugeSectionCollection copy) { foreach (GaugeSection item in this) { GaugeSection ic = new GaugeSection(); item.CopyToItem(ic); copy.Add(ic); } } #endregion } [TypeConverter(typeof(GaugeSectionConvertor))] public class GaugeSection : GaugeStrip { #region Private variables private float _Width; private int _AbsWidth; #endregion public GaugeSection(GaugeScale scale) : base(scale) { } public GaugeSection() { } #region Public properties #region Width /// /// Gets or sets the Width of the Section, specified as a percentage /// [Browsable(true)] [Category("Layout"), DefaultValue(.0f)] [Editor("DevComponents.Instrumentation.Design.WidthRangeValueEditor, DevComponents.Instrumentation.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=76cb4c6eb576bca5", typeof(UITypeEditor))] [Description("Indicates the Width of the Section, specified as a percentage.")] public float Width { get { return (_Width); } set { if (value < 0 || value > 1) throw new ArgumentException("Width must be between 0 and 1."); if (_Width != value) { _Width = value; OnGaugeItemChanged(); } } } #endregion #endregion #region RecalcLayout public override void RecalcLayout() { base.RecalcLayout(); if (Scale is GaugeCircularScale) CalcCircularLayout(Scale as GaugeCircularScale); else if (Scale is GaugeLinearScale) CalcLinearLayout(Scale as GaugeLinearScale); } #region CalcCircularLayout private void CalcCircularLayout(GaugeCircularScale scale) { int radius = scale.AbsRadius; int scaleOffset = (int)(radius * ScaleOffset); _AbsWidth = (int)(radius * (_Width > 0 ? _Width : scale.Width)); Rectangle r = scale.Bounds; r.Inflate(scaleOffset, scaleOffset); Bounds = r; } #endregion #region CalcLinearLayout #region CalcLinearLayout private void CalcLinearLayout(GaugeLinearScale scale) { float spread = (float)(scale.MaxValue - scale.MinValue); if (spread == 0) spread = 1; if (scale.Orientation == Orientation.Horizontal) CalcHorizontalLayout(scale, spread); else CalcVerticalLayout(scale, spread); } #endregion #region CalcHorizontalLayout private void CalcHorizontalLayout(GaugeLinearScale scale, float spread) { int length = scale.ScaleBounds.Width; int width = scale.ScaleBounds.Height; float dl = length / spread; int start = (int)(dl * MinValue); int len = (int)(dl * (MaxValue - MinValue)); int offset = (int)(width * ScaleOffset); _AbsWidth = (int)(_Width > 0 ? width * _Width : width); Rectangle r = scale.Bounds; if (scale.Reversed == true) r.X = r.Right - (start + len); else r.X += start; r.Width = len; r.Y = scale.Center.Y - (_AbsWidth / 2) + offset; r.Height = _AbsWidth; Bounds = r; } #endregion #region CalcVerticalLayout private void CalcVerticalLayout(GaugeLinearScale scale, float spread) { int length = scale.ScaleBounds.Height; int width = scale.ScaleBounds.Width; int n = width; float dl = length / spread; int start = (int)(dl * MinValue); int len = (int)(dl * (MaxValue - MinValue)); int offset = (int)(length * ScaleOffset); _AbsWidth = (int)(_Width > 0 ? n * _Width : n); Rectangle r = scale.Bounds; if (scale.Reversed == true) r.Y += start; else r.Y = r.Bottom - (start + len); r.X = scale.Center.X - (_AbsWidth / 2) + offset; r.Width = _AbsWidth; r.Height = len; Bounds = r; } #endregion #endregion #endregion #region OnPaint public override void OnPaint(PaintEventArgs e) { RecalcLayout(); if (Scale.GaugeControl.OnPreRenderScaleSection(e, this) == false) { if (Scale is GaugeCircularScale) { if (SweepAngle != 0) PaintCircularSection(e, Scale as GaugeCircularScale); } else if (Scale is GaugeLinearScale) { PaintLinearSection(e, Scale as GaugeLinearScale); } Scale.GaugeControl.OnPostRenderScaleSection(e, this); } } #endregion #region PaintCircularSection #region PaintCircularSection private void PaintCircularSection(PaintEventArgs e, GaugeCircularScale scale) { Graphics g = e.Graphics; int radius = scale.AbsRadius; int n = (int)(radius * (_Width > 0 ? _Width : scale.Width)); if (n > 0 && Bounds.Width > 0 && Bounds.Height > 0 && Math.Abs(SweepAngle) > .05) { if (FillColor.End.IsEmpty == true || FillColor.Color1 == FillColor.Color2 || FillColor.GradientFillType == GradientFillType.None) { using (Pen pen = new Pen(FillColor.Color1, n)) g.DrawArc(pen, Bounds, StartAngle, SweepAngle); } else { switch (FillColor.GradientFillType) { case GradientFillType.Auto: case GradientFillType.StartToEnd: PaintCircularStartToEnd(g, Bounds, n, scale); break; case GradientFillType.Angle: PaintCircularByAngle(g, Bounds, n); break; case GradientFillType.Center: PaintCircularByCenter(g, Bounds, n); break; case GradientFillType.HorizontalCenter: PaintCircularByHc(g, Bounds, n); break; case GradientFillType.VerticalCenter: PaintCircularByVc(g, Bounds, n); break; } } } } #endregion #region PaintCircularStartToEnd private void PaintCircularStartToEnd(Graphics g, Rectangle r, int n, GaugeCircularScale scale) { using (PathGradientBrush br = scale.CreateGradient( Scale.GaugeControl.Frame.Bounds, StartAngle, SweepAngle, FillColor, 10)) { using (Pen pen = new Pen(br, n)) g.DrawArc(pen, r, StartAngle, SweepAngle); } } #endregion #region PaintCircularByAngle private void PaintCircularByAngle(Graphics g, Rectangle r, int n) { Rectangle t = r; t.Inflate(10, 10); using (Brush br = FillColor.GetBrush(t)) { using (Pen pen = new Pen(br, n)) g.DrawArc(pen, r, StartAngle, SweepAngle); } } #endregion #region PaintCircularByCenter private void PaintCircularByCenter(Graphics g, Rectangle r, int n) { using (GraphicsPath path = new GraphicsPath()) { path.AddArc(r, StartAngle, SweepAngle); using (Pen pen = new Pen(Color.Black, n)) path.Widen(pen); using (PathGradientBrush br = new PathGradientBrush(path)) { br.CenterColor = FillColor.Color1; br.SurroundColors = new Color[] {FillColor.Color2}; br.CenterPoint = Scale.Center; float m = (float)n / (r.Width / 2); Blend blnd = new Blend(); blnd.Positions = new float[] { 0f, m, 1f }; blnd.Factors = new float[] { 1f, 0f, 0f }; br.Blend = blnd; g.FillPath(br, path); } } } #endregion #region PaintCircularByHc private void PaintCircularByHc(Graphics g, Rectangle r, int n) { Rectangle t = r; t.Height /= 2; using (LinearGradientBrush br = new LinearGradientBrush(t, FillColor.Color1, FillColor.Color2, 90)) { br.WrapMode = WrapMode.TileFlipXY; using (Pen pen = new Pen(br, n)) g.DrawArc(pen, r, StartAngle, SweepAngle); } } #endregion #region PaintCircularByVc private void PaintCircularByVc(Graphics g, Rectangle r, int n) { Rectangle t = r; t.Width /= 2; using (LinearGradientBrush br = new LinearGradientBrush(t, FillColor.Color1, FillColor.Color2, 0f)) { br.WrapMode = WrapMode.TileFlipXY; using (Pen pen = new Pen(br, n)) g.DrawArc(pen, r, StartAngle, SweepAngle); } } #endregion #endregion #region PaintLinearSection #region PaintLinearSection private void PaintLinearSection(PaintEventArgs e, GaugeLinearScale scale) { Graphics g = e.Graphics; if (Bounds.Width > 0 && Bounds.Height > 0) { if (FillColor.End.IsEmpty == true || FillColor.Color1 == FillColor.Color2 || FillColor.GradientFillType == GradientFillType.None) { using (Brush br = new SolidBrush(FillColor.Color1)) g.FillRectangle(br, Bounds); } else { switch (FillColor.GradientFillType) { case GradientFillType.Auto: case GradientFillType.StartToEnd: PaintLinearStartToEnd(g, Bounds, scale); break; case GradientFillType.Angle: PaintLinearByAngle(g, Bounds); break; case GradientFillType.Center: PaintLinearByCenter(g, Bounds); break; case GradientFillType.HorizontalCenter: PaintLinearByHc(g, Bounds); break; case GradientFillType.VerticalCenter: PaintLinearByVc(g, Bounds); break; } } } } #endregion #region PaintLinearStartToEnd private void PaintLinearStartToEnd( Graphics g, Rectangle r, GaugeLinearScale scale) { int angle = scale.Orientation == Orientation.Horizontal ? 0 : -90; if (scale.Reversed == true) angle += 180; using (Brush br = FillColor.GetBrush(r, angle)) g.FillRectangle(br, r); } #endregion #region PaintLinearByAngle private void PaintLinearByAngle(Graphics g, Rectangle r) { using (Brush br = FillColor.GetBrush(r)) g.FillRectangle(br, r); } #endregion #region PaintLinearByCenter private void PaintLinearByCenter(Graphics g, Rectangle r) { using (GraphicsPath path = new GraphicsPath()) { path.AddRectangle(r); using (PathGradientBrush br = new PathGradientBrush(path)) { Point pt = new Point(r.X + r.Width / 2, r.Y + r.Height / 2); br.CenterColor = FillColor.Color1; br.SurroundColors = new Color[] { FillColor.Color2 }; br.CenterPoint = pt; g.FillPath(br, path); } } } #endregion #region PaintLinearByHc private void PaintLinearByHc(Graphics g, Rectangle r) { Rectangle t = r; if (r.Height >= 2) t.Height /= 2; using (LinearGradientBrush br = new LinearGradientBrush(t, FillColor.Color1, FillColor.Color2, 90)) { br.WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, r); } } #endregion #region PaintLinearByVc private void PaintLinearByVc(Graphics g, Rectangle r) { Rectangle t = r; if (t.Width >= 2) t.Width /= 2; using (LinearGradientBrush br = new LinearGradientBrush(t, FillColor.Color1, FillColor.Color2, 0f)) { br.WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, r); } } #endregion #endregion #region FindItem internal override GaugeItem FindItem(Point pt) { GraphicsPath path = GetSectionPath(); if (path != null) { if (path.IsVisible(pt) == true) return (this); } return (null); } #endregion #region GetSectionPath public GraphicsPath GetSectionPath() { if (StripePath == null) { if (Scale is GaugeCircularScale) StripePath = GetCSectionPath(Scale as GaugeCircularScale); else StripePath = GetLSectionPath(); } return (StripePath); } #endregion #region GetCSectionPath private GraphicsPath GetCSectionPath(GaugeCircularScale scale) { int radius = scale.AbsRadius; int n = (int)(radius * (_Width > 0 ? _Width : scale.Width)); if (n > 0 && Bounds.Width > 0 && Bounds.Height > 0) { GraphicsPath path = new GraphicsPath(); Rectangle r = Bounds; r.Inflate(n / 2, n / 2); path.AddArc(r, StartAngle, SweepAngle); r.Inflate(-n, -n); path.AddArc(r, StartAngle + SweepAngle, -SweepAngle); path.CloseAllFigures(); return (path); } return (null); } #endregion #region GetLSectionPath private GraphicsPath GetLSectionPath() { if (Bounds.Width > 0 && Bounds.Height > 0) { GraphicsPath path = new GraphicsPath(); path.AddRectangle(Bounds); return (path); } return (null); } #endregion #region ICloneable Members public override object Clone() { GaugeSection copy = new GaugeSection(); CopyToItem(copy); return (copy); } #endregion #region CopyToItem public override void CopyToItem(GaugeItem copy) { GaugeSection c = copy as GaugeSection; if (c != null) { base.CopyToItem(c); c.Width = _Width; } } #endregion } #region GaugeScaleConvertor public class GaugeSectionConvertor : ExpandableObjectConverter { public override object ConvertTo( ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string)) { GaugeSection section = value as GaugeSection; if (section != 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 }