UltimateZoneBuilder/Source/Core/GZBuilder/Controls/AngleControl.cs

195 lines
5.3 KiB
C#

#region Namespaces
//Downloaded from
//Visual C# Kicks - http://vckicks.110mb.com
//The Code Project - http://www.codeproject.com
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Geometry;
#endregion
namespace CodeImp.DoomBuilder.GZBuilder.Controls
{
public partial class AngleControl : UserControl
{
#region Variables
private int angle;
private int angleoffset;
private Rectangle drawRegion;
private const int drawOffset = 2;
private const int markScaler = 5;
private Point origin;
//UI colors
private readonly Color fillColor = SystemColors.Window;
private readonly Color fillInactiveColor = SystemColors.Control;
private readonly Color outlineColor = SystemColors.ActiveCaption;
private readonly Color outlineInactiveColor = SystemColors.ControlDarkDark;
private readonly Color needleColor = SystemColors.ControlText;
private readonly Color needleInactiveColor = SystemColors.ControlDarkDark;
private readonly Color marksColor = SystemColors.ActiveBorder;
private readonly Color marksInactiveColor = SystemColors.ControlDark;
#endregion
#region Properties
public delegate void AngleChangedDelegate();
public event AngleChangedDelegate AngleChanged;
public int Angle { get { return angle - angleoffset; } set { angle = value + angleoffset; this.Refresh(); } }
public int AngleOffset { get { return angleoffset; } set { angleoffset = value; this.Refresh(); } }
#endregion
public AngleControl()
{
InitializeComponent();
this.DoubleBuffered = true;
}
#region Methods
private void setDrawRegion()
{
drawRegion = new Rectangle(0, 0, this.Width, this.Height);
drawRegion.X += 2;
drawRegion.Y += 2;
drawRegion.Width -= 4;
drawRegion.Height -= 4;
origin = new Point(drawRegion.Width / 2 + drawOffset, drawRegion.Height / 2 + drawOffset);
this.Refresh();
}
private static PointF DegreesToXY(float degrees, float radius, Point origin)
{
PointF xy = new PointF();
float radians = degrees * Angle2D.PI / 180.0f;
xy.X = (float)Math.Cos(radians) * radius + origin.X;
xy.Y = (float)Math.Sin(-radians) * radius + origin.Y;
return xy;
}
private static int XYToDegrees(Point xy, Point origin)
{
float xDiff = xy.X - origin.X;
float yDiff = xy.Y - origin.Y;
return ((int)Math.Round(Math.Atan2(-yDiff, xDiff) * 180.0 / Angle2D.PI) + 360) % 360;
}
#endregion
#region Events
private void AngleSelector_Load(object sender, EventArgs e)
{
setDrawRegion();
}
private void AngleSelector_SizeChanged(object sender, EventArgs e)
{
this.Height = this.Width; // Keep it there and keep it square!
setDrawRegion();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen outline;
Pen needle;
Pen marks;
SolidBrush fill;
Brush center;
if (this.Enabled) {
outline = new Pen(outlineColor, 2.0f);
fill = new SolidBrush(fillColor);
needle = new Pen(needleColor);
center = new SolidBrush(needleColor);
marks = new Pen(marksColor);
} else {
outline = new Pen(outlineInactiveColor, 2.0f);
fill = new SolidBrush(fillInactiveColor);
needle = new Pen(needleInactiveColor);
center = new SolidBrush(needleInactiveColor);
marks = new Pen(marksInactiveColor);
}
Rectangle originSquare = new Rectangle(origin.X - 1, origin.Y - 1, 3, 3);
//Draw circle
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawEllipse(outline, drawRegion);
g.FillEllipse(fill, drawRegion);
// Draw angle marks
int offset = this.Height / markScaler;
for(int i = 0; i < 360; i += 45) {
PointF p1 = DegreesToXY(i, origin.X - 6, origin);
PointF p2 = DegreesToXY(i, origin.X - offset, origin);
g.DrawLine(marks, p1, p2);
}
// Draw needle
if(angle != int.MinValue) {
PointF anglePoint = DegreesToXY(angle, origin.X - 4, origin);
g.DrawLine(needle, origin, anglePoint);
}
g.SmoothingMode = SmoothingMode.HighSpeed; //Make the square edges sharp
g.FillRectangle(center, originSquare);
fill.Dispose();
outline.Dispose();
base.OnPaint(e);
}
private void AngleSelector_MouseDown(object sender, MouseEventArgs e)
{
int thisAngle = XYToDegrees(new Point(e.X, e.Y), origin);
if (e.Button == MouseButtons.Left) {
thisAngle = (int)Math.Round(thisAngle / 45f) * 45;
if(thisAngle == 360) thisAngle = 0;
}
if(thisAngle != angle) {
angle = thisAngle;
if(!this.DesignMode && AngleChanged != null) AngleChanged(); //Raise event
this.Refresh();
}
}
private void AngleSelector_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right) {
int thisAngle = XYToDegrees(new Point(e.X, e.Y), origin);
if(e.Button == MouseButtons.Left) {
thisAngle = (int)Math.Round(thisAngle / 45f) * 45;
if(thisAngle == 360) thisAngle = 0;
}
if(thisAngle != angle) {
angle = thisAngle;
if(!this.DesignMode && AngleChanged != null) AngleChanged(); //Raise event
this.Refresh();
}
}
}
#endregion
}
}