376 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Globalization;
namespace DevComponents.DotNetBar.Layout
{
[TypeConverter(typeof(BackgroundConvertor))]
public class Background : INotifyPropertyChanged
{
#region Constructor
/// <summary>
/// Initializes a new instance of the Background class.
/// </summary>
public Background()
{
}
/// <summary>
/// Initializes a new instance of the Background class with single solid backgruond color.
/// </summary>
public Background(Color backColor)
{
_Colors = new Color[] { backColor };
}
/// <summary>
/// Initializes a new instance of the Background class.
/// </summary>
/// <param name="colors"></param>
public Background(Color[] colors)
{
_Colors = colors;
}
/// <summary>
/// Initializes a new instance of the Background class.
/// </summary>
/// <param name="colors"></param>
/// <param name="positions"></param>
public Background(Color[] colors, float[] positions)
{
_Colors = colors;
_Positions = positions;
}
/// <summary>
/// Initializes a new instance of the Background class.
/// </summary>
/// <param name="colors"></param>
/// <param name="positions"></param>
/// <param name="gradientType"></param>
public Background(Color[] colors, float[] positions, eGradientType gradientType)
{
_Colors = colors;
_Positions = positions;
_GradientType = gradientType;
}
/// <summary>
/// Initializes a new instance of the Background class.
/// </summary>
/// <param name="colors"></param>
/// <param name="positions"></param>
/// <param name="gradientType"></param>
/// <param name="linearGradientAngle"></param>
public Background(Color[] colors, float[] positions, eGradientType gradientType, int linearGradientAngle)
{
_Colors = colors;
_Positions = positions;
_GradientType = gradientType;
_LinearGradientAngle = linearGradientAngle;
}
#endregion
#region Implementation
/// <summary>
/// Gets whether class is empty.
/// </summary>
[Browsable(false)]
public bool IsEmpty
{
get
{
return (_Colors == null || _Colors.Length == 0) &&
(_Positions == null || _Positions.Length == 0);
}
}
/// <summary>
/// Gets whether background is visible, i.e. colors are assigned.
/// </summary>
[Browsable(false)]
public bool IsBackgroundSet
{
get
{
return !(_Colors == null || _Colors.Length == 0);
}
}
/// <summary>
/// Creates the brush which represents the background.
/// </summary>
/// <param name="r">Bounds for the brush.</param>
/// <returns>New instance of the brush or null if brush cannot be created.</returns>
public Brush CreateBrush(Rectangle r)
{
if (!IsBackgroundSet)
return null;
if (_Colors.Length == 1)
return new SolidBrush(_Colors[0]);
if (_GradientType == eGradientType.LinearGradient)
{
LinearGradientBrush brush = null;
if (_Colors.Length == 2)
{
brush = new LinearGradientBrush(r, _Colors[0], _Colors[1], _LinearGradientAngle);
if (_Positions != null && _Positions.Length != 2) return brush;
}
else
brush = new LinearGradientBrush(r, _Colors[0], _Colors[_Colors.Length - 1], _LinearGradientAngle);
ColorBlend cb = GetColorBlend();
if (cb != null)
brush.InterpolationColors = cb;
return brush;
}
else
{
int n = (int)Math.Sqrt(r.Width * r.Width + r.Height * r.Height) + 4;
using (GraphicsPath path = new GraphicsPath())
{
path.AddEllipse(r.X - (n - r.Width) / 2, r.Y - (n - r.Height) / 2, n, n);
PathGradientBrush pbr = new PathGradientBrush(path);
pbr.CenterColor = _Colors[0];
pbr.SurroundColors = new Color[] { _Colors[_Colors.Length - 1] };
ColorBlend cb = GetColorBlend();
if (cb != null)
pbr.InterpolationColors = cb;
return (pbr);
}
}
}
private ColorBlend GetColorBlend()
{
if (_Colors != null &&
_Colors != null && _Colors.Length > 0)
{
ColorBlend cb = new ColorBlend(_Colors.Length);
cb.Colors = _Colors;
cb.Positions = GetPositions();
return (cb);
}
return (null);
}
private float[] GetPositions()
{
float[] cp = _Positions;
if (cp == null || cp.Length != _Colors.Length)
{
cp = new float[_Colors.Length];
float f = 1f / _Colors.Length;
for (int i = 0; i < cp.Length; i++)
cp[i] = i * f;
cp[_Colors.Length - 1] = 1;
}
return (cp);
}
private Color[] _Colors = null;
/// <summary>
/// Indicates the array of colors that make up background.
/// </summary>
[DefaultValue(null), Category("Appearance"), Description("Indicates the array of colors that make up background."), TypeConverter(typeof(ArrayConverter))]
public Color[] Colors
{
get
{
return _Colors;
}
set
{
if (_Colors != value)
{
_Colors = value;
OnPropertyChanged(new PropertyChangedEventArgs("Colors"));
}
}
}
private float[] _Positions = null;
/// <summary>
/// Indicates the positions for the gradient colors when multiple colors are set to Colors property. When not set
/// the gradient color positions are evenly distributed.
/// </summary>
[DefaultValue(null), Category("Appearance"), Description("Indicates the positions for the gradient colors when multiple colors are set to Colors property."), TypeConverter(typeof(ArrayConverter))]
public float[] Positions
{
get
{
return _Positions;
}
set
{
_Positions = value;
OnPropertyChanged(new PropertyChangedEventArgs("Positions"));
}
}
private eGradientType _GradientType = eGradientType.LinearGradient;
/// <summary>
/// Indicates the gradient type used when multiple Colors are specified.
/// </summary>
[DefaultValue(eGradientType.LinearGradient), Category("Appearance"), Description("Indicates the gradient type used when multiple Colors are specified.")]
public eGradientType GradientType
{
get { return _GradientType; }
set { _GradientType = value; OnPropertyChanged(new PropertyChangedEventArgs("GradientType")); }
}
private int _LinearGradientAngle = 90;
/// <summary>
/// Indicates the linear gradient angle.
/// </summary>
[DefaultValue(90), Description("Indicates the linear gradient angle."), Category("Appearance")]
public int LinearGradientAngle
{
get { return _LinearGradientAngle; }
set { _LinearGradientAngle = value; OnPropertyChanged(new PropertyChangedEventArgs("LinearGradientAngle")); }
}
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when property value has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler eh = PropertyChanged;
if (eh != null)
eh(this, e);
}
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="s">Event arguments</param>
protected virtual void OnPropertyChangedEx(string s)
{
PropertyChangedEventHandler eh = PropertyChanged;
if (eh != null)
{
PropertyChangedEventArgs e =
new PropertyChangedEventArgs(s);
eh(this, e);
}
}
#endregion
}
public enum eGradientType
{
LinearGradient,
RadialGradient
}
#region BackgroundConvertor
///<summary>
/// BackgroundConvertor
///</summary>
public class BackgroundConvertor : ExpandableObjectConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return ((sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType));
}
public override object ConvertTo(
ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
Background gc = value as Background;
if (gc != null)
{
if (gc.IsEmpty)
return "(Empty)";
if (gc.Colors != null && gc.Colors.Length == 1)
return ColorHelpers.ToArgbString(gc.Colors[0]);
if (gc.Colors != null && gc.Colors.Length > 1)
return ("Blended");
return "";
}
}
return (base.ConvertTo(context, culture, value, destinationType));
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string str = value as string;
if (string.IsNullOrEmpty(str))
{
return new BorderColors();
}
string str2 = str.Trim();
if (str2.Length == 0)
{
return null;
}
if (culture == null)
{
culture = CultureInfo.CurrentCulture;
}
if (str2.IndexOf(culture.TextInfo.ListSeparator[0]) == -1)
{
Color c = Color.FromName(str2);
if (c.IsEmpty)
c = ColorHelpers.GetColor(str2);
return new Background(c);
}
throw new ArgumentException("Text Parsing Failed");
//char ch = culture.TextInfo.ListSeparator[0];
//string[] strArray = str2.Split(new char[] { ch });
//Color[] numArray = new Color[strArray.Length];
////TypeConverter converter = TypeDescriptor.GetConverter(typeof(Color));
//for (int i = 0; i < numArray.Length; i++)
//{
// numArray[i] = ColorHelpers.GetColor(strArray[i]);// (Color)converter.ConvertFromString(context, culture, strArray[i]);
//}
//if (numArray.Length == 1)
//{
// return new BorderColors(numArray[0]);
//}
//if (numArray.Length != 4)
//{
// throw new ArgumentException("Text Parsing Failed");
//}
//return new BorderColors(numArray[0], numArray[1], numArray[2], numArray[3]);
}
}
#endregion
}