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
|
|
}
|
|
}
|