using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Windows.Forms.Design; namespace DevComponents.Charts.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 PointF _PivotPoint; private Rectangle _DotBounds; private Rectangle _FrameBounds; private Rectangle _ScaleBounds; private double _ScaleRadius; private double _StartAngle; private double _SweepAngle; private bool _InFrame; private bool _InPivotDot; private bool _PivotMoving; private bool _EscapePressed; private IWindowsFormsEditorService _EditorService; private ITypeDescriptorContext _Context; #endregion public PivotPointDropDown(PointF value, double scaleRadius, double startAngle, double sweepAngle, IWindowsFormsEditorService editorService, ITypeDescriptorContext context) { _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); int n2 = n / 2; _ScaleBounds.Width = radius * 2; _ScaleBounds.Height = radius * 2; int x = _FrameBounds.X + (int)(_PivotPoint.X * _FrameBounds.Width + n2); int y = _FrameBounds.Y + (int)(_PivotPoint.Y * _FrameBounds.Height + n2); _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) { DrawBlankFrame(g); } #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, (float)_StartAngle, (float)_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) { int n = Math.Min(Bounds.Width - 4, Bounds.Height - 4); int n2 = n / 2; PivotPoint = new PointF( (float)(e.X - _FrameBounds.X - n2) / _FrameBounds.Width, (float)(e.Y - _FrameBounds.Y - n2) / _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) { PointF pt = PivotPoint; int n = Math.Min(Bounds.Width - 4, Bounds.Height - 4) / 2; switch (e.KeyCode) { case Keys.Escape: _EscapePressed = true; break; case Keys.Home: PivotPoint = PointF.Empty; break; case Keys.Left: pt.X -= (float)(_ScaleRadius / 20); PivotPoint = pt; break; case Keys.Right: pt.X += (float)(_ScaleRadius / 20); PivotPoint = pt; break; case Keys.Up: pt.Y -= (float)(_ScaleRadius / 20); PivotPoint = pt; break; case Keys.Down: pt.Y += (float)(_ScaleRadius / 20); PivotPoint = pt; break; } } #endregion } }