// and ColorDepth that are treated as bugs and MS.NET 2.0 behavior is
// implemented.
//
-// MS.NET 2.0 initializes TransparentColor to Color.Transparent in
-// constructors but ResetTransparentColor and ShouldSerializeTransparentColor
-// default to Color.LightGray that is treated as a bug.
-//
// MS.NET 2.0 does not clear keys when handle is destroyed that is treated as
// a bug.
//
{
[DefaultProperty("Images")]
[Designer("System.Windows.Forms.Design.ImageListDesigner, " + Consts.AssemblySystem_Design)]
-#if NET_2_0
[DesignerSerializer("System.Windows.Forms.Design.ImageListCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
-#endif
[ToolboxItemFilter("System.Windows.Forms")]
[TypeConverter(typeof(ImageListConverter))]
public sealed class ImageList : System.ComponentModel.Component
{
#region Private Fields
private const ColorDepth DefaultColorDepth = ColorDepth.Depth8Bit;
- private static readonly Color DefaultTransparentColor = Color.Transparent;
private static readonly Size DefaultImageSize = new Size(16, 16);
-
-#if NET_2_0
+ private static readonly Color DefaultTransparentColor = Color.Transparent;
private object tag;
-#endif
- private EventHandler recreateHandle;
private readonly ImageCollection images;
#endregion // Private Fields
{
private const int AlphaMask = unchecked((int)0xFF000000);
- [StructLayout(LayoutKind.Explicit)]
- private struct ArgbColor
- {
- [FieldOffset(0)]
- internal int Argb;
- [FieldOffset(0)]
- internal byte Blue;
- [FieldOffset(1)]
- internal byte Green;
- [FieldOffset(2)]
- internal byte Red;
- [FieldOffset(3)]
- internal byte Alpha;
- }
-
- private
-#if NET_2_0
- static
-#else
- sealed
-#endif
- class IndexedColorDepths
+ private static class IndexedColorDepths
{
-#if !NET_2_0
- private IndexedColorDepths()
- {
- }
-#endif
- internal static readonly ArgbColor[] Palette4Bit;
- internal static readonly ArgbColor[] Palette8Bit;
+ internal static readonly ColorPalette Palette4Bit;
+ internal static readonly ColorPalette Palette8Bit;
private static readonly int[] squares;
static IndexedColorDepths()
{
- Color[] palette;
Bitmap bitmap;
int index;
- int count;
bitmap = new Bitmap(1, 1, PixelFormat.Format4bppIndexed);
- palette = bitmap.Palette.Entries;
+ Palette4Bit = bitmap.Palette;
bitmap.Dispose();
- Palette4Bit = new ArgbColor[count = palette.Length];
- for (index = 0; index < count; index++)
- Palette4Bit[index].Argb = palette[index].ToArgb();
-
bitmap = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
- palette = bitmap.Palette.Entries;
+ Palette8Bit = bitmap.Palette;
bitmap.Dispose();
- Palette8Bit = new ArgbColor[count = palette.Length];
- for (index = 0; index < count; index++)
- Palette8Bit[index].Argb = palette[index].ToArgb();
-
squares = new int[511];
for (index = 0; index < 256; index++)
squares[255 + index] = squares[255 - index] = index * index;
}
- internal static int GetNearestColor(ArgbColor[] palette, int color)
+ internal static int GetNearestColor(Color[] palette, int color)
{
int index;
int count;
count = palette.Length;
for (index = 0; index < count; index++)
- if (palette[index].Argb == color)
+ if (palette[index].ToArgb() == color)
return color;
red = unchecked((int)(unchecked((uint)color) >> 16) & 0xFF);
minDistance = int.MaxValue;
for (index = 0; index < count; index++)
- if ((distance = squares[255 + palette[index].Red - red] + squares[255 + palette[index].Green - green] + squares[255 + palette[index].Blue - blue]) < minDistance) {
- nearestColor = palette[index].Argb;
+ if ((distance = squares[255 + palette[index].R - red] + squares[255 + palette[index].G - green] + squares[255 + palette[index].B - blue]) < minDistance) {
+ nearestColor = palette[index].ToArgb();
minDistance = distance;
}
#region ImageCollection Private Fields
private ColorDepth colorDepth = DefaultColorDepth;
- private Color transparentColor = DefaultTransparentColor;
private Size imageSize = DefaultImageSize;
+ private Color transparentColor = DefaultTransparentColor;
private ArrayList list = new ArrayList();
-#if NET_2_0
private ArrayList keys = new ArrayList();
-#endif
private int count;
private bool handleCreated;
-#if NET_2_0
private int lastKeyIndex = -1;
-#endif
private readonly ImageList owner;
#endregion // ImageCollection Private Fields
Image[] streamImages;
if (value == null) {
-#if NET_2_0
if (this.handleCreated)
DestroyHandle();
else
this.Clear();
-#endif
}
// Only deserialized ImageListStreamers are used.
else if ((streamImages = value.Images) != null) {
this.list = new ArrayList(streamImages.Length);
this.count = 0;
this.handleCreated = true;
-#if NET_2_0
this.keys = new ArrayList(streamImages.Length);
-#endif
for (index = 0; index < streamImages.Length; index++) {
list.Add((Image)streamImages[index].Clone());
-#if NET_2_0
keys.Add(null);
-#endif
}
+ // Invalid ColorDepth values are ignored.
+ if (Enum.IsDefined(typeof(ColorDepth), value.ColorDepth))
+ this.colorDepth = (ColorDepth)value.ColorDepth;
this.imageSize = value.ImageSize;
- this.colorDepth = value.ColorDepth;
-#if NET_2_0
// Event is raised even when handle was not created yet.
owner.OnRecreateHandle();
-#endif
}
}
}
}
}
-#if NET_2_0
public Image this[string key] {
get {
int index;
return keyCollection;
}
}
-#endif
#endregion // ImageCollection Public Instance Properties
#region ImageCollection Private Static Methods
-#if NET_2_0
private static bool CompareKeys(string key1, string key2)
{
// Keys are case-insensitive and keys with different length
return string.Compare(key1, key2, true, CultureInfo.InvariantCulture) == 0;
}
-#endif
#endregion // ImageCollection Private Static Methods
#region ImageCollection Private Instance Methods
-#if NET_2_0
private int AddItem(string key, ImageListItem item)
-#else
- private int AddItem(ImageListItem item)
-#endif
{
int itemIndex;
-#if NET_2_0
int index;
-#endif
if (this.handleCreated)
itemIndex = AddItemInternal(item);
this.count += item.ImageCount;
}
-#if NET_2_0
if ((item.Flags & ItemFlags.ImageStrip) == 0)
keys.Add(key);
else
for (index = 0; index < item.ImageCount; index++)
keys.Add(null);
-#endif
return itemIndex;
}
+ internal event EventHandler Changed;
+
private int AddItemInternal(ImageListItem item)
{
+ if (Changed != null)
+ Changed (this, EventArgs.Empty);
+
if (item.Image is Icon) {
int imageWidth;
int imageHeight;
{
int imageWidth;
int imageHeight;
- Bitmap bitmap;
- Graphics graphics;
ImageAttributes imageAttributes;
if (transparentColor.A == 0)
imageAttributes = null;
else {
imageAttributes = new ImageAttributes();
- imageAttributes.SetColorKey(transparentColor, transparentColor);
+ imageAttributes.SetColorKey (transparentColor, transparentColor);
}
- bitmap = new Bitmap(imageWidth = this.imageSize.Width, imageHeight = this.imageSize.Height, PixelFormat.Format32bppArgb);
- graphics = Graphics.FromImage(bitmap);
- graphics.DrawImage(value, new Rectangle(0, 0, imageWidth, imageHeight), 0, 0, value.Width, value.Height, GraphicsUnit.Pixel, imageAttributes);
- graphics.Dispose();
+ var bitmap = new Bitmap (imageWidth = this.imageSize.Width, imageHeight = this.imageSize.Height, PixelFormat.Format32bppArgb);
+ using (var graphics = Graphics.FromImage (bitmap))
+ graphics.DrawImage (value, new Rectangle(0, 0, imageWidth, imageHeight), 0, 0, value.Width, value.Height, GraphicsUnit.Pixel, imageAttributes);
if (imageAttributes != null)
- imageAttributes.Dispose();
+ imageAttributes.Dispose ();
- ReduceColorDepth(bitmap);
+ ReduceColorDepth (bitmap);
return bitmap;
}
int widthBytes;
int stride;
BitmapData bitmapData;
- ArgbColor[] palette;
+ Color[] palette;
if (this.colorDepth < ColorDepth.Depth32Bit) {
bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
stride = bitmapData.Stride;
if (this.colorDepth < ColorDepth.Depth16Bit) {
- palette = this.colorDepth < ColorDepth.Depth8Bit ? IndexedColorDepths.Palette4Bit : IndexedColorDepths.Palette8Bit;
+ palette = (this.colorDepth < ColorDepth.Depth8Bit ? IndexedColorDepths.Palette4Bit : IndexedColorDepths.Palette8Bit).Entries;
for (line = 0; line < height; line++) {
lineEndPtr = linePtr + widthBytes;
this.list = new ArrayList();
this.count = 0;
this.handleCreated = false;
-#if NET_2_0
keys = new ArrayList();
-#endif
}
}
#region ImageCollection Public Instance Methods
public void Add(Icon value)
{
-#if NET_2_0
Add(null, value);
-#else
- AddItem(new ImageListItem(value));
-#endif
}
public void Add(Image value)
{
-#if NET_2_0
Add(null, value);
-#else
- AddItem(new ImageListItem(value));
-#endif
}
public int Add(Image value, Color transparentColor)
{
-#if NET_2_0
return AddItem(null, new ImageListItem(value, transparentColor));
-#else
- return AddItem(new ImageListItem(value, transparentColor));
-#endif
}
-#if NET_2_0
public void Add(string key, Icon icon)
{
// Argument has name icon but exceptions use name value.
for (index = 0; index < images.Length; index++)
Add(images[index]);
}
-#endif
public int AddStrip(Image value)
{
if (value.Height != this.imageSize.Height)
throw new ArgumentException("Height of image strip must be equal to ImageSize.Height.", "value");
-#if NET_2_0
return AddItem(null, new ImageListItem(value, width / imageWidth));
-#else
- return AddItem(new ImageListItem(value, width / imageWidth));
-#endif
}
public void Clear()
{
list.Clear();
- if (this.handleCreated)
+ if (!this.handleCreated)
this.count = 0;
-#if NET_2_0
keys.Clear();
-#endif
}
-#if NET_2_0
[EditorBrowsable(EditorBrowsableState.Never)]
-#endif
public bool Contains(Image image)
{
throw new NotSupportedException();
}
-#if NET_2_0
public bool ContainsKey(string key)
{
return IndexOfKey(key) != -1;
}
-#endif
public IEnumerator GetEnumerator()
{
return images.GetEnumerator();
}
-#if NET_2_0
[EditorBrowsable(EditorBrowsableState.Never)]
-#endif
public int IndexOf(Image image)
{
throw new NotSupportedException();
}
-#if NET_2_0
public int IndexOfKey(string key)
{
int index;
return this.lastKeyIndex = -1;
}
-#endif
-#if NET_2_0
[EditorBrowsable(EditorBrowsableState.Never)]
-#endif
public void Remove(Image image)
{
throw new NotSupportedException();
CreateHandle();
list.RemoveAt(index);
-#if NET_2_0
keys.RemoveAt(index);
-#endif
+ if (Changed != null)
+ Changed (this, EventArgs.Empty);
}
-#if NET_2_0
public void RemoveByKey(string key)
{
int index;
keys[index] = name;
}
-#endif
#endregion // ImageCollection Public Instance Methods
#region ImageCollection Interface Properties
return index;
}
- bool IList.Contains(object value)
+ bool IList.Contains(object image)
{
- return value is Image ? this.Contains((Image)value) : false;
+ return image is Image ? this.Contains ((Image) image) : false;
}
- int IList.IndexOf(object value)
+ int IList.IndexOf (object image)
{
- return value is Image ? this.IndexOf((Image)value) : -1;
+ return image is Image ? this.IndexOf ((Image) image) : -1;
}
void IList.Insert(int index, object value)
throw new NotSupportedException();
}
- void IList.Remove(object value)
+ void IList.Remove (object image)
{
- if (value is Image)
- this.Remove((Image)value);
+ if (image is Image)
+ this.Remove ((Image) image);
}
- void ICollection.CopyTo(Array array, int index)
+ void ICollection.CopyTo(Array dest, int index)
{
- int imageIndex;
-
- for (imageIndex = 0; imageIndex < this.Count; imageIndex++)
- array.SetValue(this[index], index++);
+ for (int imageIndex = 0; imageIndex < this.Count; imageIndex++)
+ dest.SetValue (this[imageIndex], index++);
}
#endregion // ImageCollection Interface Methods
}
#region Private Instance Methods
private void OnRecreateHandle()
{
- if (recreateHandle != null)
- recreateHandle(this, EventArgs.Empty);
- }
-
-#if NET_2_0
- // For use in Designers
- private void ResetColorDepth()
- {
- this.ColorDepth = DefaultColorDepth;
+ EventHandler eh = (EventHandler)(Events [RecreateHandleEvent]);
+ if (eh != null)
+ eh (this, EventArgs.Empty);
}
- // For use in Designers
- private void ResetImageSize()
- {
- this.ImageSize = DefaultImageSize;
- }
+ // MS's TypeDescriptor stuff apparently uses
+ // non-public ShouldSerialize* methods, because it
+ // picks up this behavior even though the methods
+ // aren't public. we can't make them private, though,
+ // without adding compiler warnings. so, make then
+ // internal instead.
- // For use in Designers
- private void ResetTransparentColor()
+ internal bool ShouldSerializeTransparentColor ()
{
- this.TransparentColor = DefaultTransparentColor;
+ return this.TransparentColor != Color.LightGray;
}
- // For use in Designers
- private bool ShouldSerializeColorDepth()
+ internal bool ShouldSerializeColorDepth()
{
// ColorDepth is serialized in ImageStream when non-empty.
// It is serialized even if it has its default value when empty.
return images.Empty;
- }
+ }
- // For use in Designers
- private bool ShouldSerializeImageSize()
+ internal bool ShouldSerializeImageSize()
{
// ImageSize is serialized in ImageStream when non-empty.
// It is serialized even if it has its default value when empty.
return images.Empty;
}
- // For use in Designers
- private bool ShouldSerializeTransparentColor()
+ internal void ResetColorDepth ()
{
- return this.TransparentColor != DefaultTransparentColor;
+ this.ColorDepth = DefaultColorDepth;
+ }
+
+ internal void ResetImageSize ()
+ {
+ this.ImageSize = DefaultImageSize;
+ }
+
+ internal void ResetTransparentColor ()
+ {
+ this.TransparentColor = Color.LightGray;
}
-#endif
#endregion // Private Instance Methods
#region Public Instance Properties
-#if !NET_2_0
- [DefaultValue(DefaultColorDepth)]
-#endif
public ColorDepth ColorDepth {
get {
return images.ColorDepth;
}
}
-#if NET_2_0
[Bindable(true)]
[DefaultValue(null)]
[Localizable(false)]
this.tag = value;
}
}
-#endif
public Color TransparentColor {
get {
public override string ToString()
{
- return base.ToString() + " Images.Count: " + images.Count.ToString() + ", ImageSize: " + images.ImageSize.ToString();
+ return base.ToString() + " Images.Count: " + images.Count.ToString() + ", ImageSize: " + this.ImageSize.ToString();
}
#endregion // Public Instance Methods
#endregion // Protected Instance Methods
#region Events
+ static object RecreateHandleEvent = new object ();
+
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler RecreateHandle {
- add {
- recreateHandle += value;
- }
-
- remove {
- recreateHandle -= value;
- }
+ add { Events.AddHandler (RecreateHandleEvent, value); }
+ remove { Events.RemoveHandler (RecreateHandleEvent, value); }
}
#endregion // Events
}