using SmartCoalApplication.Core; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SmartCoalApplication.PluginAssemblys { internal class ColorWheel : UserControl { /// /// Required designer variable. /// private System.ComponentModel.Container components = null; private Bitmap renderBitmap = null; private bool tracking = false; private Point lastMouseXY; // this number controls what you might call the tesselation of the color wheel. higher #'s = slower, lower #'s = looks worse private const int colorTesselation = 60; private PictureBox wheelPictureBox; private HsvColor hsvColor; public HsvColor HsvColor { get { return hsvColor; } set { if (hsvColor != value) { HsvColor oldColor = hsvColor; hsvColor = value; this.OnColorChanged(); Refresh(); } } } public ColorWheel() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); //wheelRegion = new PdnRegion(); hsvColor = new HsvColor(0, 0, 0); } private static PointF SphericalToCartesian(float r, float theta) { float x; float y; x = r * (float)Math.Cos(theta); y = r * (float)Math.Sin(theta); return new PointF(x, y); } private static PointF[] GetCirclePoints(float r, PointF center) { PointF[] points = new PointF[colorTesselation]; for (int i = 0; i < colorTesselation; i++) { float theta = ((float)i / (float)colorTesselation) * 2 * (float)Math.PI; points[i] = SphericalToCartesian(r, theta); points[i].X += center.X; points[i].Y += center.Y; } return points; } private Color[] GetColors() { Color[] colors = new Color[colorTesselation]; for (int i = 0; i < colorTesselation; i++) { int hue = (i * 360) / colorTesselation; colors[i] = new HsvColor(hue, 100, 100).ToColor(); } return colors; } protected override void OnLoad(EventArgs e) { InitRendering(); base.OnLoad(e); } protected override void OnPaint(PaintEventArgs e) { InitRendering(); base.OnPaint(e); } private void InitRendering() { if (this.renderBitmap == null) { InitRenderSurface(); this.wheelPictureBox.SizeMode = PictureBoxSizeMode.StretchImage; int size = (int)Math.Ceiling(ComputeDiameter(this.Size)); this.wheelPictureBox.Size = new Size(size, size); this.wheelPictureBox.Image = this.renderBitmap; } } private void WheelPictureBox_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { float radius = ComputeRadius(Size); float theta = ((float)HsvColor.Hue / 360.0f) * 2.0f * (float)Math.PI; float alpha = ((float)HsvColor.Saturation / 100.0f); float x = (alpha * (radius - 1) * (float)Math.Cos(theta)) + radius; float y = (alpha * (radius - 1) * (float)Math.Sin(theta)) + radius; int ix = (int)x; int iy = (int)y; // Draw the 'target rectangle' GraphicsContainer container = e.Graphics.BeginContainer(); e.Graphics.PixelOffsetMode = PixelOffsetMode.None; e.Graphics.SmoothingMode = SmoothingMode.HighQuality; e.Graphics.DrawRectangle(Pens.Black, ix - 1, iy - 1, 3, 3); e.Graphics.DrawRectangle(Pens.White, ix, iy, 1, 1); e.Graphics.EndContainer(container); } private void InitRenderSurface() { if (renderBitmap != null) { renderBitmap.Dispose(); } int wheelDiameter = (int)ComputeDiameter(Size); renderBitmap = new Bitmap(Math.Max(1, (wheelDiameter * 4) / 3), Math.Max(1, (wheelDiameter * 4) / 3), PixelFormat.Format24bppRgb); using (Graphics g1 = Graphics.FromImage(renderBitmap)) { g1.Clear(this.BackColor); DrawWheel(g1, renderBitmap.Width, renderBitmap.Height); } } private void DrawWheel(Graphics g, int width, int height) { float radius = ComputeRadius(new Size(width, height)); PointF[] points = GetCirclePoints(Math.Max(1.0f, (float)radius - 1), new PointF(radius, radius)); using (PathGradientBrush pgb = new PathGradientBrush(points)) { pgb.CenterColor = new HsvColor(0, 0, 100).ToColor(); pgb.CenterPoint = new PointF(radius, radius); pgb.SurroundColors = GetColors(); g.FillEllipse(pgb, 0, 0, radius * 2, radius * 2); } } private static float ComputeRadius(Size size) { return Math.Min((float)size.Width / 2, (float)size.Height / 2); } private static float ComputeDiameter(Size size) { return Math.Min((float)size.Width, (float)size.Height); } protected override void OnResize(EventArgs e) { base.OnResize(e); if (renderBitmap != null && (ComputeRadius(Size) != ComputeRadius(renderBitmap.Size))) { renderBitmap.Dispose(); renderBitmap = null; } Invalidate(); } public event EventHandler ColorChanged; protected virtual void OnColorChanged() { if (ColorChanged != null) { ColorChanged(this, EventArgs.Empty); } } private void GrabColor(Point mouseXY) { // center our coordinate system so the middle is (0,0), and positive Y is facing up int cx = mouseXY.X - (Width / 2); int cy = mouseXY.Y - (Height / 2); double theta = Math.Atan2(cy, cx); if (theta < 0) { theta += 2 * Math.PI; } double alpha = Math.Sqrt((cx * cx) + (cy * cy)); int h = (int)((theta / (Math.PI * 2)) * 360.0); int s = (int)Math.Min(100.0, (alpha / (double)(Width / 2)) * 100); int v = 100; hsvColor = new HsvColor(h, s, v); OnColorChanged(); Invalidate(true); } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left) { tracking = true; } } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (tracking) { GrabColor(new Point(e.X, e.Y)); } tracking = false; } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); lastMouseXY = new Point(e.X, e.Y); if (tracking) { GrabColor(new Point(e.X, e.Y)); } } /// /// Clean up any resources being used. /// protected override void Dispose(bool disposing) { if (disposing) { if (components != null) { components.Dispose(); components = null; } } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.wheelPictureBox = new System.Windows.Forms.PictureBox(); this.SuspendLayout(); // // wheelPictureBox // this.wheelPictureBox.Location = new System.Drawing.Point(0, 0); this.wheelPictureBox.Name = "wheelPictureBox"; this.wheelPictureBox.TabIndex = 0; this.wheelPictureBox.TabStop = false; this.wheelPictureBox.Click += new System.EventHandler(this.wheelPictureBox_Click); this.wheelPictureBox.Paint += new System.Windows.Forms.PaintEventHandler(this.WheelPictureBox_Paint); this.wheelPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.wheelPictureBox_MouseUp); this.wheelPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.wheelPictureBox_MouseMove); this.wheelPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.wheelPictureBox_MouseDown); // // ColorWheel // this.Controls.Add(this.wheelPictureBox); this.Name = "ColorWheel"; this.ResumeLayout(false); } #endregion private void wheelPictureBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { OnMouseMove(e); } private void wheelPictureBox_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { OnMouseUp(e); } private void wheelPictureBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { OnMouseDown(e); } private void wheelPictureBox_Click(object sender, System.EventArgs e) { OnClick(e); } } }