using System; using System.ComponentModel; using System.Drawing; using System.Globalization; using System.Windows.Forms; namespace DevComponents.Instrumentation { [TypeConverter(typeof(GaugeTickMarkBaseConvertor))] public class GaugeTickMarkBase : GaugeItem { #region Private variables private int _Radius; private int _Width; private int _Length; private int _Offset; private Rectangle _Bounds; private TickMarkLayout _Layout; private GaugeTickMarkRank _Rank; private GaugeMarker _GaugeMarker; private GaugeScale _Scale; #endregion public GaugeTickMarkBase(GaugeScale scale, GaugeTickMarkRank rank, GaugeMarkerStyle style, float width, float length) : this(scale, rank, new TickMarkLayout(style, width, length)) { } public GaugeTickMarkBase(GaugeScale scale, GaugeTickMarkRank rank, TickMarkLayout layout) { _Scale = scale; _Rank = rank; _Layout = layout; _GaugeMarker = new GaugeMarker(); HookEvents(true); } #region Hidden properties #region Name [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new string Name { get { return (base.Name); } set { base.Name = value; } } #endregion #region Tooltip [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public new string Tooltip { get { return (base.Tooltip); } set { base.Tooltip = value; } } #endregion #endregion #region Public properties #region Scale /// /// Gets the associated Scale /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public GaugeScale Scale { get { return (_Scale); } internal set { _Scale = value; } } #endregion #region Layout /// /// Gets the Tickmark leyout /// [Browsable(true), Category("Layout")] [Description("Specifies the TickMark layout properties.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public TickMarkLayout Layout { get { return (_Layout); } } #endregion #region Visible public override bool Visible { get { return (base.Visible); } set { if (base.Visible != value) { base.Visible = value; if (_Scale != null) _Scale.Labels.NeedRecalcLayout = true; } } } #endregion #endregion #region Internal properties #region Bounds internal Rectangle Bounds { get { return (_Bounds); } set { _Bounds = value; } } #endregion #region Length internal int Length { get { return (_Length); } set { _Length = value; } } #endregion #region Offset internal int Offset { get { return (_Offset); } set { _Offset = value; } } #endregion #region Radius internal int Radius { get { return (_Radius); } } #endregion #region Rank internal GaugeTickMarkRank Rank { get { return (_Rank); } } #endregion #region Width internal int Width { get { return (_Width); } set { _Width = value; } } #endregion #endregion #region HookEvents private void HookEvents(bool hook) { if (hook == true) { _Layout.TickMarkLayoutChanged += TickMarkLayout_TickMarkLayoutChanged; } else { _Layout.TickMarkLayoutChanged -= TickMarkLayout_TickMarkLayoutChanged; } } #endregion #region Event processing void TickMarkLayout_TickMarkLayoutChanged(object sender, EventArgs e) { OnGaugeItemChanged(true); } #endregion #region RecalcLayout public override void RecalcLayout() { if (NeedRecalcLayout == true) { base.RecalcLayout(); CalcTickMarkMetrics(); _GaugeMarker.Clear(); } } #region CalcTickMarkMetrics private void CalcTickMarkMetrics() { if (Scale is GaugeCircularScale) CalcCircularMetrics(Scale as GaugeCircularScale); else if (Scale is GaugeLinearScale) CalcLinearMetrics(Scale as GaugeLinearScale); } #region CalcCircularMetrics private void CalcCircularMetrics(GaugeCircularScale scale) { _Radius = scale.AbsRadius; _Length = (int)(_Radius * _Layout.Length); _Width = (int)(_Radius * _Layout.Width); int m = scale.AbsScaleWidth; int offset = (int)(scale.AbsRadius * _Layout.ScaleOffset); switch (_Layout.Placement) { case DisplayPlacement.Near: _Radius -= ((_Length + m / 2) + offset); break; case DisplayPlacement.Center: _Radius += ((_Length / 2) + offset + 1); break; case DisplayPlacement.Far: _Radius += ((_Length + m / 2) + offset); break; } } #endregion #region CalcLinearMetrics private void CalcLinearMetrics(GaugeLinearScale scale) { if (scale.Orientation == Orientation.Horizontal) CalcHorizontalLayout(scale); else CalcVerticalLayout(scale); } #region CalcHorizontalLayout private void CalcHorizontalLayout(GaugeLinearScale scale) { int n = scale.AbsWidth; _Length = (int)(n * _Layout.Length); _Width = (int)(n * _Layout.Width); if (_Layout.Length > 0 && _Length < 2) _Length = 2; if (_Layout.Width > 0 && _Width < 2) _Width = 2; int offset = (int) (n * _Layout.ScaleOffset); _Bounds = scale.ScaleBounds; _Bounds.Height = _Length; switch (_Layout.Placement) { case DisplayPlacement.Near: _Bounds.Y = scale.ScaleBounds.Top - _Length - offset; break; case DisplayPlacement.Center: _Bounds.Y = scale.Center.Y - _Length / 2 - offset; break; case DisplayPlacement.Far: _Bounds.Y = scale.ScaleBounds.Bottom + offset; break; } _Offset = _Bounds.Y - scale.ScaleBounds.Y; } #endregion #region CalcVerticalLayout private void CalcVerticalLayout(GaugeLinearScale scale) { int n = scale.AbsWidth; _Length = (int)(n * _Layout.Length); _Width = (int)(n * _Layout.Width); if (_Layout.Length > 0 && _Length < 2) _Length = 2; if (_Layout.Width > 0 && _Width < 2) _Width = 2; int offset = (int)(n * _Layout.ScaleOffset); _Bounds = scale.ScaleBounds; _Bounds.Width = _Length; switch (_Layout.Placement) { case DisplayPlacement.Near: _Bounds.X = scale.ScaleBounds.Left - _Length - offset; break; case DisplayPlacement.Center: _Bounds.X = scale.Center.X - _Length / 2 - offset; break; case DisplayPlacement.Far: _Bounds.X = scale.ScaleBounds.Right + offset; break; } _Offset = _Bounds.X - scale.ScaleBounds.X; } #endregion #endregion #endregion #endregion #region Paint support #region PaintTickPoint #region PaintTickPoint internal void PaintTickPoint(Graphics g, TickPoint tp) { Image image = _Layout.Image ?? GetTickMarkBitmap(g, tp); if (image != null) { if (Scale is GaugeCircularScale) PaintCircularTickPoint(g, tp, image); else if (Scale is GaugeLinearScale) PaintLinearTickPoint(g, tp, image, Scale as GaugeLinearScale); } } #endregion #region PaintCircularTickPoint private void PaintCircularTickPoint(Graphics g, TickPoint tp, Image image) { Rectangle r = new Rectangle(0, 0, _Width, _Length); float angle = tp.Angle + 90; if (_Layout.Placement == DisplayPlacement.Near) angle += 180; g.TranslateTransform(tp.Point.X, tp.Point.Y); g.RotateTransform(angle % 360); r.X -= _Width / 2; g.DrawImage(image, r); g.ResetTransform(); } #endregion #region PaintLinearTickPoint private void PaintLinearTickPoint(Graphics g, TickPoint tp, Image image, GaugeLinearScale scale) { if (scale.Orientation == Orientation.Horizontal) PaintHorizontalTickPoint(g, tp, image); else PaintVerticalTickPoint(g, tp, image); } #region PaintHorizontalTickPoint private void PaintHorizontalTickPoint(Graphics g, TickPoint tp, Image image) { if (_Layout.Placement != DisplayPlacement.Far) { Rectangle r = new Rectangle(tp.Point.X, tp.Point.Y, _Width, _Length); r.X -= _Width / 2; g.DrawImage(image, r); } else { Rectangle r = new Rectangle(0, 0, _Width, _Length); g.TranslateTransform(tp.Point.X, tp.Point.Y + _Length - (_Length % 2)); g.RotateTransform(180); r.X -= _Width / 2; g.DrawImage(image, r); g.ResetTransform(); } } #endregion #region PaintVerticalTickPoint private void PaintVerticalTickPoint(Graphics g, TickPoint tp, Image image) { Rectangle r = new Rectangle(0, 0, _Width, _Length); if (_Layout.Placement == DisplayPlacement.Far) { g.TranslateTransform(tp.Point.X + _Length - (_Length % 2), tp.Point.Y); g.RotateTransform(90); } else { g.TranslateTransform(tp.Point.X, tp.Point.Y); g.RotateTransform(-90); } r.X -= (_Width / 2); g.DrawImage(image, r); g.ResetTransform(); } #endregion #endregion #endregion #region GetTickMarkBitmap internal Bitmap GetTickMarkBitmap(Graphics g, TickPoint tp) { if (_Layout.Style != GaugeMarkerStyle.None) { if (_Width > 0 && _Length > 0) { return (_GaugeMarker.GetMarkerBitmap(g, _Layout.Style, GetTickMarkFillColor(tp), _Width, _Length)); } } return (null); } #endregion #region GetTickMarkFillColor private GradientFillColor GetTickMarkFillColor(TickPoint tp) { if (_Rank == GaugeTickMarkRank.Custom) return (Layout.FillColor); ColorSourceFillEntry entry = (_Rank == GaugeTickMarkRank.Major) ? ColorSourceFillEntry.MajorTickMark : ColorSourceFillEntry.MinorTickMark; GradientFillColor fillColor = (Scale.GetRangeFillColor(tp.Interval, entry) ?? Scale.GetSectionFillColor(tp.Interval, entry)) ?? Layout.FillColor; return (fillColor); } #endregion #endregion #region OnDispose protected override void OnDispose() { HookEvents(false); _GaugeMarker.Dispose(); base.OnDispose(); } #endregion #region ICloneable Members public override object Clone() { GaugeTickMarkBase copy = new GaugeTickMarkBase( _Scale, _Rank, _Layout.Style, _Layout.Width, _Layout.Length); CopyToItem(copy); return (copy); } #endregion #region CopyToItem public override void CopyToItem(GaugeItem copy) { GaugeTickMarkBase c = copy as GaugeTickMarkBase; if (c != null) { base.CopyToItem(c); _Layout.CopyToItem(c.Layout); } } #endregion } #region GaugeTickMarkBaseConvertor public class GaugeTickMarkBaseConvertor : ExpandableObjectConverter { public override object ConvertTo( ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string)) { GaugeTickMarkBase tickMark = value as GaugeTickMarkBase; if (tickMark != null) { return (String.Empty); } } return (base.ConvertTo(context, culture, value, destinationType)); } } #endregion #region Enums public enum GaugeTickMarkRank { Major, Minor, Custom } public enum GaugeTickMarkOverlap { ReplaceNone, ReplaceLast, ReplaceAll } #endregion }