333 lines
8.0 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.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
}
}