Click here to Skip to main content
15,885,366 members
Articles / Multimedia / GDI+

Adobe Color Picker Clone

Rate me:
Please Sign up or sign in to vote.
4.96/5 (32 votes)
14 Apr 2009CPOL4 min read 69K   2.6K   67  
A simple but powerful .NET color picker dialog.
using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Reflection;

namespace DrawingEx.Drawing3D
{
	/// <summary>
	/// representing an angle
	/// </summary>
	[StructLayout(LayoutKind.Sequential),
	TypeConverter(typeof(AngleTypeConverter))]
	public struct Angle
	{
		public static readonly Angle Empty=new Angle();
		/// <summary>
		/// two times the value of PI
		/// </summary>
		public const double DoublePI=Math.PI*2.0;
		#region variables
		private double _value;
		#endregion
		#region ctor
		/// <summary>
		/// constructs an angle from a radiant value
		/// </summary>
		public Angle(double radiants)
		{
			_value=ClampAngle(radiants);
		}
		/// <summary>
		/// not needet, use constructor instead
		/// </summary>
		public static Angle FromRadiants(double radiants)
		{
			return new Angle(radiants);
		}
		/// <summary>
		/// constructs an angle from a degree value
		/// </summary>
		public static Angle FromDegree(int degree)
		{
			return new Angle(Math.PI*(double)degree/180f);
		}
		/// <summary>
		/// constructs an angle from a grad value
		/// </summary>
		public static Angle FromGrad(int grad)
		{
			return new Angle(Math.PI*(double)grad/200f);
		}
		#endregion
		#region operators
		//operators
		public static Angle operator+(Angle a, Angle b)
		{
			return new Angle(a._value+b._value);
		}
		public static Angle operator-(Angle a, Angle b)
		{
			return new Angle(a._value-b._value);
		}
		public static bool operator==(Angle a, Angle b)
		{
			return a._value==b._value;
		}
		public static bool operator !=(Angle a, Angle b)
		{
			return !(b==a);
		}
		//override object derived
		public override bool Equals(object obj)
		{
			if(obj is Angle)
			{
				return ((Angle)obj)._value==_value;
			}
			return false;
		}
		public override int GetHashCode()
		{
			return _value.GetHashCode();
		}
		//conversion
		public static implicit operator double (Angle value)
		{
			return value._value;
		}
		public static implicit operator Angle (double value)
		{
			return new Angle(value);
		}
		#endregion
		#region static members
		public static double ClampAngle(double radiants)
		{
			if(double.IsInfinity(radiants) ||
				double.IsNaN(radiants))
				return 0.0;
			radiants=radiants%DoublePI;
			if(radiants<0f)
				return DoublePI+radiants;
			else
				return radiants;
		}
		public static double GetNearestEigth(double value)
		{
			return ClampAngle(value-Math.IEEERemainder(value,Math.PI/4.0));
		}
		#endregion
		#region conversion
		/// <summary>
		/// not needet, use value-propery instead
		/// </summary>
		public double ToRadiants()
		{
			return _value;
		}
		/// <summary>
		/// returns angle value in degree
		/// </summary>
		public int ToDegree()
		{
			return (int)Math.Round(180f*_value/Math.PI);
		}
		/// <summary>
		/// returns angle value in grad
		/// </summary>
		public int ToGrad()
		{
			return (int)Math.Round(200f*_value/Math.PI);
		}
		/// <summary>
		/// returns a human readable string representing the angle
		/// </summary>
		public override string ToString()
		{
			return _value.ToString()+" rad";
		}
		/// <summary>
		/// maps the angle to an ellipse
		/// </summary>
		public PointF MapToEllipse(RectangleF bounds)
		{
			return new PointF(
				bounds.X+bounds.Width*(1f+(float)Math.Cos(_value))/2f,
				bounds.Y+bounds.Height*(1f+(float)Math.Sin(_value))/2f);
		}
		#endregion
	}
	/// <summary>
	/// used to convert an angle value
	/// </summary>
	public class AngleTypeConverter:TypeConverter
	{
		#region convert from
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			return (sourceType==typeof(string)) ||
				base.CanConvertFrom (context, sourceType);
		}
		public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
		{
			string text=value as string;
			if(text==null)
				return base.ConvertFrom (context, culture, value);
			//remove trailing spaces
			text=text.Trim();
			if(text=="") return null;
			//locate culture
			if(culture==null)
				culture=CultureInfo.CurrentCulture;
			//parse radiants
			if(text.EndsWith("rad"))
			{
				text=text.Remove(text.Length-3,3);
				text=text.Trim();
				if(text=="") return null;
				return Angle.FromRadiants(double.Parse(text,NumberStyles.Float,culture));
			}
			//parse degree
			else if(text.EndsWith("�"))
			{
				text=text.Remove(text.Length-1,1);
				text=text.Trim();
				if(text=="") return null;
				return Angle.FromDegree(int.Parse(text,NumberStyles.Integer,culture));
			}
			return null;
		}
		#endregion
		#region convert to
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			return (destinationType==typeof(InstanceDescriptor)) ||
				base.CanConvertTo (context, destinationType);
		}
		public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
		{
			if(value is Angle)
			{
				Angle angle=(Angle)value;
				if(destinationType==null)
					//destinationtype is needed
					throw new ArgumentNullException("destinationType");
				else if(destinationType==typeof(string))
					//string representation in degree
					return angle.ToDegree().ToString()+"�";
				else if (destinationType==typeof(InstanceDescriptor))
				{
					//get constructor for property grid
					ConstructorInfo member=typeof(Angle).GetConstructor(new Type[]{typeof(double)});
					if(member!=null)
						return new InstanceDescriptor(member,new object[]{angle.ToRadiants()});
				}
			}
			return base.ConvertTo (context, culture, value, destinationType);
		}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Other VariSoft Industries
Germany Germany
my name is ramon van blech

Comments and Discussions