426 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			426 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.ComponentModel;
 | 
						|
using System.Drawing;
 | 
						|
using System.Drawing.Drawing2D;
 | 
						|
using System.Windows.Forms;
 | 
						|
using System.Windows.Forms.Design;
 | 
						|
 | 
						|
namespace DevComponents.Instrumentation.Design
 | 
						|
{
 | 
						|
    [ToolboxItem(false)]
 | 
						|
    public partial class PivotPointDropDown : UserControl
 | 
						|
    {
 | 
						|
        #region Constants
 | 
						|
 | 
						|
        private const int DotRadius = 4;
 | 
						|
        private const int ScaleWidth = 3;
 | 
						|
        private const float BevelInside = .035f;
 | 
						|
        private const float BevelOutside = .05f;
 | 
						|
        private const float RoundRectangleArc = .125f;
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Private variables
 | 
						|
 | 
						|
        private GaugeFrameStyle _Style;
 | 
						|
 | 
						|
        private PointF _PivotPoint;
 | 
						|
        private Rectangle _DotBounds;
 | 
						|
        private Rectangle _FrameBounds;
 | 
						|
        private Rectangle _ScaleBounds;
 | 
						|
 | 
						|
        private float _ScaleRadius;
 | 
						|
        private float _StartAngle;
 | 
						|
        private float _SweepAngle;
 | 
						|
 | 
						|
        private bool _InFrame;
 | 
						|
        private bool _InPivotDot;
 | 
						|
        private bool _PivotMoving;
 | 
						|
 | 
						|
        private bool _EscapePressed;
 | 
						|
 | 
						|
        private IWindowsFormsEditorService _EditorService;
 | 
						|
        private ITypeDescriptorContext _Context;
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        public PivotPointDropDown(PointF value, GaugeFrameStyle style,
 | 
						|
            float scaleRadius, float startAngle, float sweepAngle,
 | 
						|
            IWindowsFormsEditorService editorService, ITypeDescriptorContext context)
 | 
						|
        {
 | 
						|
            _Style = style;
 | 
						|
            _ScaleRadius = scaleRadius;
 | 
						|
            _StartAngle = startAngle;
 | 
						|
            _SweepAngle = sweepAngle;
 | 
						|
 | 
						|
            _ScaleRadius = Math.Max(_ScaleRadius, .07f);
 | 
						|
 | 
						|
            Initialize();
 | 
						|
 | 
						|
            _EditorService = editorService;
 | 
						|
            _Context = context;
 | 
						|
 | 
						|
            PivotPoint = value;
 | 
						|
        }
 | 
						|
 | 
						|
        public PivotPointDropDown()
 | 
						|
        {
 | 
						|
            Initialize();
 | 
						|
        }
 | 
						|
 | 
						|
        #region Initialize
 | 
						|
 | 
						|
        private void Initialize()
 | 
						|
        {
 | 
						|
            InitializeComponent();
 | 
						|
 | 
						|
            SetStyle(ControlStyles.UserPaint, true);
 | 
						|
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
 | 
						|
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Public properties
 | 
						|
 | 
						|
        #region EditorService
 | 
						|
 | 
						|
        public IWindowsFormsEditorService EditorService
 | 
						|
        {
 | 
						|
            get { return (_EditorService); }
 | 
						|
            set { _EditorService = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region EscapePressed
 | 
						|
 | 
						|
        public bool EscapePressed
 | 
						|
        {
 | 
						|
            get { return (_EscapePressed); }
 | 
						|
            set { _EscapePressed = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PivotPoint
 | 
						|
 | 
						|
        public PointF PivotPoint
 | 
						|
        {
 | 
						|
            get { return (_PivotPoint); }
 | 
						|
 | 
						|
            set
 | 
						|
            {
 | 
						|
                _PivotPoint = value;
 | 
						|
 | 
						|
                RecalcLayout();
 | 
						|
                Invalidate();
 | 
						|
 | 
						|
                _Context.OnComponentChanging();
 | 
						|
                _Context.PropertyDescriptor.SetValue(_Context.Instance, value);
 | 
						|
                _Context.OnComponentChanged();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region RecalcLayout
 | 
						|
 | 
						|
        private void RecalcLayout()
 | 
						|
        {
 | 
						|
            int n = Math.Min(Bounds.Width - 4, Bounds.Height - 4);
 | 
						|
 | 
						|
            _FrameBounds = new Rectangle(2, 2, n, n);
 | 
						|
            _FrameBounds.X = (Bounds.Width - n) / 2;
 | 
						|
            _FrameBounds.Y = (Bounds.Height - n) / 2;
 | 
						|
 | 
						|
            int radius = (int)(n * _ScaleRadius);
 | 
						|
 | 
						|
            _ScaleBounds.Width = radius * 2;
 | 
						|
            _ScaleBounds.Height = radius * 2;
 | 
						|
 | 
						|
            int x = _FrameBounds.X + (int)(_PivotPoint.X * _FrameBounds.Width);
 | 
						|
            int y = _FrameBounds.Y + (int)(_PivotPoint.Y * _FrameBounds.Height);
 | 
						|
 | 
						|
            _ScaleBounds.X = x - radius;
 | 
						|
            _ScaleBounds.Y = y - radius;
 | 
						|
 | 
						|
            _DotBounds = new Rectangle(x - DotRadius, y - DotRadius, DotRadius * 2, DotRadius * 2);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Paint support
 | 
						|
 | 
						|
        #region OnPaint
 | 
						|
 | 
						|
        protected override void OnPaint(PaintEventArgs e)
 | 
						|
        {
 | 
						|
            base.OnPaint(e);
 | 
						|
 | 
						|
            Graphics g = e.Graphics;
 | 
						|
 | 
						|
            g.SmoothingMode = SmoothingMode.AntiAlias;
 | 
						|
 | 
						|
            RecalcLayout();
 | 
						|
 | 
						|
            DrawFrame(g);
 | 
						|
            DrawScale(g);
 | 
						|
            DrawPivotDot(g);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DrawFrame
 | 
						|
 | 
						|
        private void DrawFrame(Graphics g)
 | 
						|
        {
 | 
						|
            switch (_Style)
 | 
						|
            {
 | 
						|
                case GaugeFrameStyle.Circular:
 | 
						|
                    DrawCircularFrame(g);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case GaugeFrameStyle.Rectangular:
 | 
						|
                    DrawRectangularFrame(g);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case GaugeFrameStyle.RoundedRectangular:
 | 
						|
                    DrawRoundedRectFrame(g);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
                    DrawBlankFrame(g);
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region DrawCircularFrame
 | 
						|
 | 
						|
        private void DrawCircularFrame(Graphics g)
 | 
						|
        {
 | 
						|
            using (LinearGradientBrush br = new LinearGradientBrush(_FrameBounds, Color.WhiteSmoke, Color.Gray, 45))
 | 
						|
                g.FillEllipse(br, _FrameBounds);
 | 
						|
 | 
						|
            int bevelIn = (int)(_FrameBounds.Width * BevelInside);
 | 
						|
            int bevelOut = (int)(_FrameBounds.Width * BevelOutside);
 | 
						|
 | 
						|
            Rectangle r = _FrameBounds;
 | 
						|
            r.Inflate(-bevelOut, -bevelOut);
 | 
						|
 | 
						|
            using (LinearGradientBrush br = new LinearGradientBrush(r, Color.Silver, Color.Gray, 45 + 180))
 | 
						|
                g.FillEllipse(br, r);
 | 
						|
 | 
						|
            r.Inflate(-bevelIn, -bevelIn);
 | 
						|
 | 
						|
            using (LinearGradientBrush br = new LinearGradientBrush(r, Color.Silver, Color.LightGray, 45))
 | 
						|
                g.FillEllipse(br, r);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DrawRectangularFrame
 | 
						|
 | 
						|
        private void DrawRectangularFrame(Graphics g)
 | 
						|
        {
 | 
						|
            using (LinearGradientBrush br = new LinearGradientBrush(_FrameBounds, Color.WhiteSmoke, Color.Gray, 45))
 | 
						|
                g.FillRectangle(br, _FrameBounds);
 | 
						|
 | 
						|
            int bevelIn = (int)(_FrameBounds.Width * BevelInside);
 | 
						|
            int bevelOut = (int)(_FrameBounds.Width * BevelOutside);
 | 
						|
 | 
						|
            Rectangle r = _FrameBounds;
 | 
						|
            r.Inflate(-bevelOut, -bevelOut);
 | 
						|
 | 
						|
            using (LinearGradientBrush br = new LinearGradientBrush(r, Color.Silver, Color.Gray, 45 + 180))
 | 
						|
                g.FillRectangle(br, r);
 | 
						|
 | 
						|
            r.Inflate(-bevelIn, -bevelIn);
 | 
						|
 | 
						|
            using (LinearGradientBrush br = new LinearGradientBrush(r, Color.Silver, Color.LightGray, 45))
 | 
						|
                g.FillRectangle(br, r);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DrawRoundedRectFrame
 | 
						|
 | 
						|
        private void DrawRoundedRectFrame(Graphics g)
 | 
						|
        {
 | 
						|
            using (GraphicsPath path = GetRoundRectPath(_FrameBounds))
 | 
						|
            {
 | 
						|
                using (LinearGradientBrush br = new LinearGradientBrush(_FrameBounds, Color.WhiteSmoke, Color.Gray, 45))
 | 
						|
                    g.FillPath(br, path);
 | 
						|
            }
 | 
						|
 | 
						|
            int bevelIn = (int)(_FrameBounds.Width * BevelInside);
 | 
						|
            int bevelOut = (int)(_FrameBounds.Width * BevelOutside);
 | 
						|
 | 
						|
            Rectangle r = _FrameBounds;
 | 
						|
            r.Inflate(-bevelOut, -bevelOut);
 | 
						|
 | 
						|
            using (GraphicsPath path = GetRoundRectPath(r))
 | 
						|
            {
 | 
						|
                using (LinearGradientBrush br = new LinearGradientBrush(r, Color.Silver, Color.Gray, 45 + 180))
 | 
						|
                    g.FillPath(br, path);
 | 
						|
            }
 | 
						|
 | 
						|
            r.Inflate(-bevelIn, -bevelIn);
 | 
						|
 | 
						|
            using (GraphicsPath path = GetRoundRectPath(r))
 | 
						|
            {
 | 
						|
                using (LinearGradientBrush br = new LinearGradientBrush(r, Color.Silver, Color.LightGray, 45))
 | 
						|
                    g.FillPath(br, path);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #region GetRoundRectPath
 | 
						|
 | 
						|
        private GraphicsPath GetRoundRectPath(Rectangle r)
 | 
						|
        {
 | 
						|
            GraphicsPath path = new GraphicsPath();
 | 
						|
 | 
						|
            int m = Math.Min(r.Width, r.Height);
 | 
						|
            int n = (int)(m * RoundRectangleArc * 2) + 1;
 | 
						|
 | 
						|
            Rectangle t = new Rectangle(r.Right - n, r.Bottom - n, n, n);
 | 
						|
            path.AddArc(t, 0, 90);
 | 
						|
 | 
						|
            t.X = r.X;
 | 
						|
            path.AddArc(t, 90, 90);
 | 
						|
 | 
						|
            t.Y = r.Y;
 | 
						|
            path.AddArc(t, 180, 90);
 | 
						|
 | 
						|
            t.X = r.Right - n;
 | 
						|
            path.AddArc(t, 270, 90);
 | 
						|
 | 
						|
            path.CloseAllFigures();
 | 
						|
 | 
						|
            return (path);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DrawBlankFrame
 | 
						|
 | 
						|
        private void DrawBlankFrame(Graphics g)
 | 
						|
        {
 | 
						|
            using (Brush br = new SolidBrush(Color.LightGray))
 | 
						|
                g.FillRectangle(br, _FrameBounds);
 | 
						|
 | 
						|
            g.DrawRectangle(Pens.DimGray, _FrameBounds);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DrawScale
 | 
						|
 | 
						|
        private void DrawScale(Graphics g)
 | 
						|
        {
 | 
						|
            using (Brush br = new SolidBrush(Color.CornflowerBlue))
 | 
						|
            {
 | 
						|
                using (Pen pen = new Pen(br, ScaleWidth))
 | 
						|
                    g.DrawArc(pen, _ScaleBounds, _StartAngle, _SweepAngle);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region DrawPivotDot
 | 
						|
 | 
						|
        private void DrawPivotDot(Graphics g)
 | 
						|
        {
 | 
						|
            g.FillEllipse(Brushes.SkyBlue, _DotBounds);
 | 
						|
            g.DrawEllipse(Pens.DimGray, _DotBounds);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Mouse support
 | 
						|
 | 
						|
        #region OnMouseMove
 | 
						|
 | 
						|
        protected override void OnMouseMove(MouseEventArgs e)
 | 
						|
        {
 | 
						|
            base.OnMouseMove(e);
 | 
						|
 | 
						|
            _InFrame = (_FrameBounds.Contains(e.Location) == true);
 | 
						|
 | 
						|
            if (_PivotMoving == true && _InFrame == true)
 | 
						|
            {
 | 
						|
                PivotPoint = new PointF(
 | 
						|
                    (float)(e.X - _FrameBounds.X) / _FrameBounds.Width,
 | 
						|
                    (float)(e.Y - _FrameBounds.Y) / _FrameBounds.Height);
 | 
						|
            }
 | 
						|
 | 
						|
            _InPivotDot = (_DotBounds.Contains(e.Location) == true);
 | 
						|
 | 
						|
            Cursor = (_InPivotDot == true) ? Cursors.Hand : Cursors.Default;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region OnMouseLeave
 | 
						|
 | 
						|
        protected override void OnMouseLeave(EventArgs e)
 | 
						|
        {
 | 
						|
            base.OnMouseLeave(e);
 | 
						|
 | 
						|
            _InFrame = false;
 | 
						|
            _InPivotDot = false;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region OnMouseDown
 | 
						|
 | 
						|
        protected override void OnMouseDown(MouseEventArgs e)
 | 
						|
        {
 | 
						|
            base.OnMouseDown(e);
 | 
						|
 | 
						|
            if (e.Button == MouseButtons.Left)
 | 
						|
            {
 | 
						|
                if (_InPivotDot == true)
 | 
						|
                    _PivotMoving = true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region OnMouseUp
 | 
						|
 | 
						|
        protected override void OnMouseUp(MouseEventArgs e)
 | 
						|
        {
 | 
						|
            base.OnMouseUp(e);
 | 
						|
 | 
						|
            _PivotMoving = false;
 | 
						|
 | 
						|
            _InFrame = (_FrameBounds.Contains(e.Location) == true);
 | 
						|
            _InPivotDot = (_DotBounds.Contains(e.Location) == true);
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region PivotPointDropDown_PreviewKeyDown
 | 
						|
 | 
						|
        private void PivotPointDropDown_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
 | 
						|
        {
 | 
						|
            if (e.KeyCode == Keys.Escape)
 | 
						|
                _EscapePressed = true;
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion
 | 
						|
    }
 | 
						|
}
 |