333 lines
8.0 KiB
C#
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
|
|
}
|
|
}
|