123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- namespace Optimizer.Controls
- {
- [DefaultProperty("Color")]
- [DefaultEvent("ColorChanged")]
- public partial class ColorPicker : Control
- {
- #region Fields
- private Brush _brush;
- private PointF _centerPoint;
- private Color _color;
- private int _colorStep;
- private bool _dragStartedWithinWheel;
- private HslColor _hslColor;
- private int _largeChange;
- private float _radius;
- private int _selectionSize;
- private int _smallChange;
- private int _updateCount;
- #endregion
- #region Constructors
- public ColorPicker()
- {
- this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Selectable | ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true);
- this.Color = Color.Black;
- this.ColorStep = 4;
- this.SelectionSize = 10;
- this.SmallChange = 1;
- this.LargeChange = 5;
- this.SelectionGlyph = this.CreateSelectionGlyph();
- }
- #endregion
- #region Events
- [Category("Property Changed")]
- public event EventHandler ColorChanged;
- [Category("Property Changed")]
- public event EventHandler ColorStepChanged;
- [Category("Property Changed")]
- public event EventHandler HslColorChanged;
- [Category("Property Changed")]
- public event EventHandler LargeChangeChanged;
- [Category("Property Changed")]
- public event EventHandler SelectionSizeChanged;
- [Category("Property Changed")]
- public event EventHandler SmallChangeChanged;
- #endregion
- #region Overridden Methods
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_brush != null)
- {
- _brush.Dispose();
- }
- if (this.SelectionGlyph != null)
- {
- this.SelectionGlyph.Dispose();
- }
- }
- base.Dispose(disposing);
- }
- protected override bool IsInputKey(Keys keyData)
- {
- bool result;
- if ((keyData & Keys.Left) == Keys.Left || (keyData & Keys.Up) == Keys.Up || (keyData & Keys.Down) == Keys.Down || (keyData & Keys.Right) == Keys.Right || (keyData & Keys.PageUp) == Keys.PageUp || (keyData & Keys.PageDown) == Keys.PageDown)
- {
- result = true;
- }
- else
- {
- result = base.IsInputKey(keyData);
- }
- return result;
- }
- protected override void OnGotFocus(EventArgs e)
- {
- base.OnGotFocus(e);
- this.Invalidate();
- }
- protected override void OnKeyDown(KeyEventArgs e)
- {
- HslColor color;
- double hue;
- int step;
- color = this.HslColor;
- hue = color.H;
- step = e.Shift ? this.LargeChange : this.SmallChange;
- switch (e.KeyCode)
- {
- case Keys.Right:
- case Keys.Up:
- hue += step;
- break;
- case Keys.Left:
- case Keys.Down:
- hue -= step;
- break;
- case Keys.PageUp:
- hue += this.LargeChange;
- break;
- case Keys.PageDown:
- hue -= this.LargeChange;
- break;
- }
- if (hue >= 360)
- {
- hue = 0;
- }
- if (hue < 0)
- {
- hue = 359;
- }
- if (hue != color.H)
- {
- color.H = hue;
- this.LockUpdates = true;
- this.Color = color.ToRgbColor();
- this.HslColor = color;
- this.LockUpdates = false;
- e.Handled = true;
- }
- base.OnKeyDown(e);
- }
- protected override void OnLostFocus(EventArgs e)
- {
- base.OnLostFocus(e);
- this.Invalidate();
- }
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- if (!this.Focused && this.TabStop)
- {
- this.Focus();
- }
- if (e.Button == MouseButtons.Left && this.IsPointInWheel(e.Location))
- {
- _dragStartedWithinWheel = true;
- this.SetColor(e.Location);
- }
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- if (e.Button == MouseButtons.Left && _dragStartedWithinWheel)
- {
- this.SetColor(e.Location);
- }
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- base.OnMouseUp(e);
- _dragStartedWithinWheel = false;
- }
- protected override void OnPaddingChanged(EventArgs e)
- {
- base.OnPaddingChanged(e);
- this.RefreshWheel();
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- base.OnPaint(e);
- if (this.AllowPainting)
- {
- base.OnPaintBackground(e);
- if (this.BackgroundImage == null && this.Parent != null && (this.BackColor == this.Parent.BackColor || this.Parent.BackColor.A != 255))
- {
- ButtonRenderer.DrawParentBackground(e.Graphics, this.DisplayRectangle, this);
- }
- if (_brush != null)
- {
- e.Graphics.FillPie(_brush, this.ClientRectangle, 0, 360);
- }
- e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
- using (Pen pen = new Pen(this.BackColor, 2))
- {
- e.Graphics.DrawEllipse(pen, new RectangleF(_centerPoint.X - _radius, _centerPoint.Y - _radius, _radius * 2, _radius * 2));
- }
- if (!this.Color.IsEmpty)
- {
- this.PaintCurrentColor(e);
- }
- }
- }
- protected override void OnResize(EventArgs e)
- {
- base.OnResize(e);
- this.RefreshWheel();
- }
- #endregion
- #region Public Properties
- [Category("Appearance")]
- [DefaultValue(typeof(Color), "Black")]
- public virtual Color Color
- {
- get { return _color; }
- set
- {
- if (this.Color != value)
- {
- _color = value;
- this.OnColorChanged(EventArgs.Empty);
- }
- }
- }
- [Category("Appearance")]
- [DefaultValue(4)]
- public virtual int ColorStep
- {
- get { return _colorStep; }
- set
- {
- if (value < 1 || value > 359)
- {
- throw new ArgumentOutOfRangeException("value", value, "Value must be between 1 and 359");
- }
- if (this.ColorStep != value)
- {
- _colorStep = value;
- this.OnColorStepChanged(EventArgs.Empty);
- }
- }
- }
- [Category("Appearance")]
- [DefaultValue(typeof(HslColor), "0, 0, 0")]
- [Browsable(false)]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public virtual HslColor HslColor
- {
- get { return _hslColor; }
- set
- {
- if (this.HslColor != value)
- {
- _hslColor = value;
- this.OnHslColorChanged(EventArgs.Empty);
- }
- }
- }
- [Category("Behavior")]
- [DefaultValue(5)]
- public virtual int LargeChange
- {
- get { return _largeChange; }
- set
- {
- if (this.LargeChange != value)
- {
- _largeChange = value;
- this.OnLargeChangeChanged(EventArgs.Empty);
- }
- }
- }
- [Category("Appearance")]
- [DefaultValue(10)]
- public virtual int SelectionSize
- {
- get { return _selectionSize; }
- set
- {
- if (this.SelectionSize != value)
- {
- _selectionSize = value;
- this.OnSelectionSizeChanged(EventArgs.Empty);
- }
- }
- }
- [Category("Behavior")]
- [DefaultValue(1)]
- public virtual int SmallChange
- {
- get { return _smallChange; }
- set
- {
- if (this.SmallChange != value)
- {
- _smallChange = value;
- this.OnSmallChangeChanged(EventArgs.Empty);
- }
- }
- }
- #endregion
- #region Protected Properties
- protected virtual bool AllowPainting
- {
- get { return _updateCount == 0; }
- }
- protected Color[] Colors { get; set; }
- protected bool LockUpdates { get; set; }
- protected PointF[] Points { get; set; }
- protected Image SelectionGlyph { get; set; }
- #endregion
- #region Public Members
- public virtual void BeginUpdate()
- {
- _updateCount++;
- }
- public virtual void EndUpdate()
- {
- if (_updateCount > 0)
- {
- _updateCount--;
- }
- if (this.AllowPainting)
- {
- this.Invalidate();
- }
- }
- #endregion
- #region Protected Members
- protected virtual void CalculateWheel()
- {
- List<PointF> points;
- List<Color> colors;
- points = new List<PointF>();
- colors = new List<Color>();
- if (this.ClientSize.Width > 16 && this.ClientSize.Height > 16)
- {
- int w;
- int h;
- w = this.ClientSize.Width;
- h = this.ClientSize.Height;
- _centerPoint = new PointF(w / 2.0F, h / 2.0F);
- _radius = this.GetRadius(_centerPoint);
- for (double angle = 0; angle < 360; angle += this.ColorStep)
- {
- double angleR;
- PointF location;
- angleR = angle * (Math.PI / 180);
- location = this.GetColorLocation(angleR, _radius);
- points.Add(location);
- colors.Add(new HslColor(angle, 1, 0.5).ToRgbColor());
- }
- }
- this.Points = points.ToArray();
- this.Colors = colors.ToArray();
- }
- protected virtual Brush CreateGradientBrush()
- {
- Brush result;
- if (this.Points.Length != 0 && this.Points.Length == this.Colors.Length)
- {
- result = new PathGradientBrush(this.Points, WrapMode.Clamp)
- {
- CenterPoint = _centerPoint,
- CenterColor = Color.White,
- SurroundColors = this.Colors
- };
- }
- else
- {
- result = null;
- }
- return result;
- }
- protected virtual Color GetContrastColor(Color c)
- {
- double brightness = c.R * 0.299 + c.G * 0.587 + c.B * 0.114;
- return brightness > 149 ? Color.Black : Color.White;
- }
- protected virtual Image CreateSelectionGlyph()
- {
- Image image;
- int halfSize;
- halfSize = this.SelectionSize / 2;
- image = new Bitmap(this.SelectionSize + 1, this.SelectionSize + 1);
- using (Graphics g = Graphics.FromImage(image))
- {
- g.SmoothingMode = SmoothingMode.AntiAlias;
- g.PixelOffsetMode = PixelOffsetMode.HighQuality;
- g.InterpolationMode = InterpolationMode.High;
- g.DrawEllipse(new Pen(GetContrastColor(Color)), halfSize - 4.5f, halfSize - 4.5f, 4.5f + 4.5f, 4.5f + 4.5f);
- g.FillEllipse(new SolidBrush(this.Color), halfSize - 4, halfSize - 4, 4 + 4, 4 + 4);
- }
- return image;
- }
- protected PointF GetColorLocation(Color color)
- {
- return this.GetColorLocation(new HslColor(color));
- }
- protected virtual PointF GetColorLocation(HslColor color)
- {
- double angle;
- double radius;
- angle = color.H * Math.PI / 180;
- radius = _radius * color.S;
- return this.GetColorLocation(angle, radius);
- }
- protected PointF GetColorLocation(double angleR, double radius)
- {
- double x;
- double y;
- x = this.Padding.Left + _centerPoint.X + Math.Cos(angleR) * radius;
- y = this.Padding.Top + _centerPoint.Y - Math.Sin(angleR) * radius;
- return new PointF((float)x, (float)y);
- }
- protected float GetRadius(PointF centerPoint)
- {
- return Math.Min(centerPoint.X, centerPoint.Y) - (Math.Max(this.Padding.Horizontal, this.Padding.Vertical) + (this.SelectionSize / 2));
- }
- protected bool IsPointInWheel(Point point)
- {
- PointF normalized;
- normalized = new PointF(point.X - _centerPoint.X, point.Y - _centerPoint.Y);
- return (normalized.X * normalized.X + normalized.Y * normalized.Y) <= (_radius * _radius);
- }
- protected virtual void OnColorChanged(EventArgs e)
- {
- EventHandler handler;
- if (!this.LockUpdates)
- {
- this.HslColor = new HslColor(this.Color);
- }
- this.SelectionGlyph = this.CreateSelectionGlyph();
- this.Refresh();
- handler = this.ColorChanged;
- if (handler != null)
- {
- handler(this, e);
- }
- }
- protected virtual void OnColorStepChanged(EventArgs e)
- {
- EventHandler handler;
- this.RefreshWheel();
- handler = this.ColorStepChanged;
- if (handler != null)
- {
- handler(this, e);
- }
- }
- protected virtual void OnHslColorChanged(EventArgs e)
- {
- EventHandler handler;
- if (!this.LockUpdates)
- {
- this.Color = this.HslColor.ToRgbColor();
- }
- this.Invalidate();
- handler = this.HslColorChanged;
- if (handler != null)
- {
- handler(this, e);
- }
- }
- protected virtual void OnLargeChangeChanged(EventArgs e)
- {
- EventHandler handler;
- handler = this.LargeChangeChanged;
- if (handler != null)
- {
- handler(this, e);
- }
- }
- protected virtual void OnSelectionSizeChanged(EventArgs e)
- {
- EventHandler handler;
- if (this.SelectionGlyph != null)
- {
- this.SelectionGlyph.Dispose();
- }
- this.SelectionGlyph = this.CreateSelectionGlyph();
- this.RefreshWheel();
- handler = this.SelectionSizeChanged;
- if (handler != null)
- {
- handler(this, e);
- }
- }
- protected virtual void OnSmallChangeChanged(EventArgs e)
- {
- EventHandler handler;
- handler = this.SmallChangeChanged;
- if (handler != null)
- {
- handler(this, e);
- }
- }
- protected void PaintColor(PaintEventArgs e, HslColor color)
- {
- this.PaintColor(e, color, false);
- }
- protected virtual void PaintColor(PaintEventArgs e, HslColor color, bool includeFocus)
- {
- PointF location;
- location = this.GetColorLocation(color);
- if (!float.IsNaN(location.X) && !float.IsNaN(location.Y))
- {
- int x;
- int y;
- x = (int)location.X - (this.SelectionSize / 2);
- y = (int)location.Y - (this.SelectionSize / 2);
- if (this.SelectionGlyph == null)
- {
- e.Graphics.DrawRectangle(Pens.Black, x, y, this.SelectionSize, this.SelectionSize);
- }
- else
- {
- e.Graphics.DrawImage(this.SelectionGlyph, x, y);
- }
- }
- }
- protected virtual void PaintCurrentColor(PaintEventArgs e)
- {
- this.PaintColor(e, this.HslColor, true);
- }
- protected virtual void SetColor(Point point)
- {
- double dx;
- double dy;
- double angle;
- double distance;
- double saturation;
- dx = Math.Abs(point.X - _centerPoint.X - this.Padding.Left);
- dy = Math.Abs(point.Y - _centerPoint.Y - this.Padding.Top);
- angle = Math.Atan(dy / dx) / Math.PI * 180;
- distance = Math.Pow((Math.Pow(dx, 2) + (Math.Pow(dy, 2))), 0.5);
- saturation = distance / _radius;
- if (distance < 6)
- {
- saturation = 0;
- }
- if (point.X < _centerPoint.X)
- {
- angle = 180 - angle;
- }
- if (point.Y > _centerPoint.Y)
- {
- angle = 360 - angle;
- }
- this.LockUpdates = true;
- this.HslColor = new HslColor(angle, saturation, 0.5);
- this.Color = this.HslColor.ToRgbColor();
- this.LockUpdates = false;
- }
- #endregion
- #region Private Members
- private void RefreshWheel()
- {
- if (_brush != null)
- {
- _brush.Dispose();
- }
- this.CalculateWheel();
- _brush = this.CreateGradientBrush();
- this.Invalidate();
- }
- #endregion
- }
- }
|