#region Disclaimer / License
// Copyright (C) 2009, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.Windows.Forms;
using System.Drawing;
namespace Maestro.Editors.Common
{
///
/// A combo box customised for selection of colors
///
[Serializable]
public class ColorComboBox
: CustomCombo
{
private bool m_allowTransparent = false;
private SpecialCell m_currentColor;
private ColorDialog m_colorPicker;
private static ColorDialog m_sharedColorPicker;
///
/// Initializes a new instance of the class.
///
public ColorComboBox()
: base()
{
if (!this.DesignMode)
{
m_currentColor = new SpecialCell(SpecialCell.CellTypes.CurrentColor);
base.SetCustomRender(new RenderCustomItem(ColorComboRender));
//ResetColors();
}
}
///
/// Resets the colors.
///
public void ResetColors()
{
base.Items.Clear();
if (m_allowTransparent)
base.Items.Add(SpecialCell.Transparent);
foreach (Color c in KnownColors)
base.Items.Add(c);
base.Items.Add(m_currentColor);
base.Items.Add(SpecialCell.MoreColors);
}
///
/// Gets or sets a value indicating whether [allow transparent].
///
/// true if [allow transparent]; otherwise, false.
[ System.ComponentModel.Browsable(false), System.ComponentModel.ReadOnly(true) ]
public bool AllowTransparent
{
get { return m_allowTransparent; }
set { m_allowTransparent = value; }
}
///
/// Gets or sets a value indicating whether [transparent selected].
///
/// true if [transparent selected]; otherwise, false.
[ System.ComponentModel.Browsable(false), System.ComponentModel.ReadOnly(true) ]
public bool TransparentSelected
{
get { return this.SelectedItem == SpecialCell.Transparent; }
set
{
if (value)
this.SelectedItem = SpecialCell.Transparent;
else
this.SelectedItem = m_currentColor;
}
}
///
/// Gets or sets the color of the current.
///
/// The color of the current.
[ System.ComponentModel.Browsable(false), System.ComponentModel.ReadOnly(true) ]
public Color CurrentColor
{
get
{
if (this.SelectedItem == null)
return m_currentColor.Color;
else if (this.SelectedItem.GetType() == typeof(SpecialCell))
return ((SpecialCell)this.SelectedItem).Color;
else
return (Color)this.SelectedItem;
}
set
{
if (Array.IndexOf(KnownColors, value) > 0)
this.SelectedItem = value;
else if (value == SpecialCell.Transparent.Color && this.AllowTransparent)
this.SelectedItem = SpecialCell.Transparent;
else
{
m_currentColor.Color = value;
this.SelectedItem = m_currentColor;
}
}
}
///
/// Raises the event.
///
/// The that was raised.
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
if (e.Index < 0)
return;
if (this.Items[e.Index].GetType() == typeof(SpecialCell))
{
SpecialCell c = (SpecialCell)this.Items[e.Index];
if (c.CellType == SpecialCell.CellTypes.CurrentColor)
e.ItemHeight = 0;
else if (c.CellType == SpecialCell.CellTypes.Transparent && !m_allowTransparent)
e.ItemHeight = 0;
else
base.OnMeasureItem(e);
}
else
base.OnMeasureItem (e);
}
///
/// Raises the event.
///
/// An that contains the event data.
protected override void OnSelectedIndexChanged(EventArgs e)
{
if (this.SelectedItem != null && this.SelectedItem.ToString() == Properties.Resources.MoreColorsName)
{
ColorDialog dlg = this.ColorPicker;
dlg.FullOpen = true;
dlg.SolidColorOnly = true;
dlg.AllowFullOpen = true;
dlg.Color = m_currentColor.Color;
this.SelectedItem = m_currentColor;
if (dlg.ShowDialog(this) == DialogResult.OK)
{
if (Array.IndexOf(KnownColors, dlg.Color) > 0)
this.SelectedItem = dlg.Color;
else
m_currentColor.Color = dlg.Color;
}
}
else
m_currentColor.Color = this.CurrentColor;
base.OnSelectedIndexChanged (e);
}
private const int MARGIN = 2;
private readonly Color[] KnownColors =
{
Color.Black,
Color.White,
Color.DarkRed,
Color.DarkGreen,
Color.Goldenrod,
Color.DarkBlue,
Color.DarkMagenta,
Color.DarkCyan,
Color.LightGray,
Color.Gray,
Color.Red,
Color.Green,
Color.Yellow,
Color.Blue,
Color.Magenta,
Color.Cyan
};
///
/// Gets an object representing the collection of the items contained in this .
///
///
///
/// A representing the items in the .
///
[ System.ComponentModel.Browsable(false), System.ComponentModel.ReadOnly(true) ]
public new ComboBox.ObjectCollection Items
{
get
{
return base.Items;
}
}
private class SpecialCell
{
public enum CellTypes
{
Transparent,
MoreColors,
CurrentColor
}
private CellTypes m_cellType;
private Color m_color;
public SpecialCell(CellTypes celltype)
{
m_cellType = celltype;
if (celltype == CellTypes.Transparent)
m_color = System.Drawing.Color.Transparent;
}
public Color Color
{
get { return m_color; }
set { m_color = value; }
}
public CellTypes CellType
{
get { return m_cellType; }
}
public override string ToString()
{
if (m_cellType == CellTypes.MoreColors)
return Properties.Resources.MoreColorsName;
else if (m_cellType == CellTypes.Transparent)
return Properties.Resources.TransparentName;
else
return base.ToString ();
}
public static readonly SpecialCell MoreColors = new SpecialCell(CellTypes.MoreColors);
public static readonly SpecialCell Transparent = new SpecialCell(CellTypes.Transparent);
}
private bool ColorComboRender(DrawItemEventArgs e, object value)
{
Color color;
if (value == null)
return false;
if (value.GetType() == typeof(SpecialCell))
{
if (value == m_currentColor)
color = ((SpecialCell)value).Color;
else
return false;
}
else if (value.GetType() != typeof(Color))
return false;
else
color = (Color)value;
if (!this.Enabled)
{
int median = (color.R + color.G + color.B) / 3;
median = Math.Max(Math.Min(median, 205), 50);
color = Color.FromArgb(median, median, median);
}
e.DrawBackground();
Rectangle r = new Rectangle(e.Bounds.X + MARGIN, e.Bounds.Y + MARGIN, e.Bounds.Width - MARGIN * 2, e.Bounds.Height - MARGIN * 2);
using (Brush b = new SolidBrush(color))
e.Graphics.FillRectangle(b, r);
e.Graphics.DrawRectangle(Pens.Black, r);
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
e.DrawFocusRectangle();
return true;
}
///
/// Gets or sets the color picker.
///
/// The color picker.
public ColorDialog ColorPicker
{
get
{
if (m_colorPicker == null)
{
if (m_sharedColorPicker == null)
m_sharedColorPicker = new ColorDialog();
m_colorPicker = m_sharedColorPicker;
}
return m_colorPicker;
}
set { m_colorPicker = value; }
}
}
}