/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ImageList.cs
C# | 1072 lines | 787 code | 175 blank | 110 comment | 137 complexity | e49a5889817b2fa55ebbc091cf80a698 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
- //
- // System.Windows.Forms.ImageList.cs
- //
- // Authors:
- // Peter Bartok <pbartok@novell.com>
- // Kornél Pál <http://www.kornelpal.hu/>
- //
- // Copyright (C) 2004-2005 Novell, Inc.
- // Copyright (C) 2005 Kornél Pál
- //
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // COMPLETE
- //
- // Differences between MS.NET ImageList and this implementation:
- //
- // This is a fully managed image list implementation.
- //
- // Images are stored as Format32bppArgb internally but ColorDepth is applied
- // to the colors of images. Images[index] returns a Format32bppArgb copy of
- // the image so this difference is only internal.
- //
- // MS.NET has no alpha channel support (except for icons in 32-bit mode with
- // comctl32.dll version 6.0) but this implementation has full alpha channel
- // support in 32-bit mode.
- //
- // Handle should be an HIMAGELIST returned by ImageList_Create. This
- // implementation uses (IntPtr)(-1) that is a non-zero but invalid handle.
- //
- // MS.NET destroys handles using the garbage collector this implementation
- // does the same with Image objects stored in an ArrayList.
- //
- // MS.NET 1.x shares the same HIMAGELIST between ImageLists that were
- // initialized from the same ImageListStreamer and doesn't update ImageSize
- // and ColorDepth that are treated as bugs and MS.NET 2.0 behavior is
- // implemented.
- //
- // MS.NET 2.0 does not clear keys when handle is destroyed that is treated as
- // a bug.
- //
- using System.Collections;
- using System.Collections.Specialized;
- using System.ComponentModel;
- using System.ComponentModel.Design.Serialization;
- using System.Drawing;
- using System.Drawing.Design;
- using System.Drawing.Imaging;
- using System.Globalization;
- using System.Runtime.InteropServices;
- namespace System.Windows.Forms
- {
- [DefaultProperty("Images")]
- [Designer("System.Windows.Forms.Design.ImageListDesigner, " + Consts.AssemblySystem_Design)]
- [DesignerSerializer("System.Windows.Forms.Design.ImageListCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
- [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 Size DefaultImageSize = new Size(16, 16);
- private static readonly Color DefaultTransparentColor = Color.Transparent;
- private object tag;
- private readonly ImageCollection images;
- #endregion // Private Fields
- #region Sub-classes
- [Editor("System.Windows.Forms.Design.ImageCollectionEditor, " + Consts.AssemblySystem_Design, typeof(UITypeEditor))]
- public sealed class ImageCollection : IList, ICollection, IEnumerable
- {
- private const int AlphaMask = unchecked((int)0xFF000000);
- private static class IndexedColorDepths
- {
- internal static readonly ColorPalette Palette4Bit;
- internal static readonly ColorPalette Palette8Bit;
- private static readonly int[] squares;
- static IndexedColorDepths()
- {
- Bitmap bitmap;
- int index;
- bitmap = new Bitmap(1, 1, PixelFormat.Format4bppIndexed);
- Palette4Bit = bitmap.Palette;
- bitmap.Dispose();
- bitmap = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
- Palette8Bit = bitmap.Palette;
- bitmap.Dispose();
- squares = new int[511];
- for (index = 0; index < 256; index++)
- squares[255 + index] = squares[255 - index] = index * index;
- }
- internal static int GetNearestColor(Color[] palette, int color)
- {
- int index;
- int count;
- int red;
- int green;
- int blue;
- int nearestColor;
- int minDistance;
- int distance;
- count = palette.Length;
- for (index = 0; index < count; index++)
- if (palette[index].ToArgb() == color)
- return color;
- red = unchecked((int)(unchecked((uint)color) >> 16) & 0xFF);
- green = unchecked((int)(unchecked((uint)color) >> 8) & 0xFF);
- blue = color & 0xFF;
- nearestColor = AlphaMask;
- minDistance = int.MaxValue;
- for (index = 0; index < count; index++)
- 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;
- }
- return nearestColor;
- }
- }
- [Flags()]
- private enum ItemFlags
- {
- None = 0,
- UseTransparentColor = 1,
- ImageStrip = 2
- }
- private sealed class ImageListItem
- {
- internal readonly object Image;
- internal readonly ItemFlags Flags;
- internal readonly Color TransparentColor;
- internal readonly int ImageCount = 1;
- internal ImageListItem(Icon value)
- {
- if (value == null)
- throw new ArgumentNullException("value");
- // Icons are cloned.
- this.Image = (Icon)value.Clone();
- }
- internal ImageListItem(Image value)
- {
- if (value == null)
- throw new ArgumentNullException("value");
- if (!(value is Bitmap))
- throw new ArgumentException("Image must be a Bitmap.");
- // Images are not cloned.
- this.Image = value;
- }
- internal ImageListItem(Image value, Color transparentColor) : this(value)
- {
- this.Flags = ItemFlags.UseTransparentColor;
- this.TransparentColor = transparentColor;
- }
- internal ImageListItem(Image value, int imageCount) : this(value)
- {
- this.Flags = ItemFlags.ImageStrip;
- this.ImageCount = imageCount;
- }
- }
- #region ImageCollection Private Fields
- private ColorDepth colorDepth = DefaultColorDepth;
- private Size imageSize = DefaultImageSize;
- private Color transparentColor = DefaultTransparentColor;
- private ArrayList list = new ArrayList();
- private ArrayList keys = new ArrayList();
- private int count;
- private bool handleCreated;
- private int lastKeyIndex = -1;
- private readonly ImageList owner;
- #endregion // ImageCollection Private Fields
- #region ImageCollection Internal Constructors
- // For use in ImageList
- internal ImageCollection(ImageList owner)
- {
- this.owner = owner;
- }
- #endregion // ImageCollection Internal Constructor
- #region ImageCollection Internal Instance Properties
- // For use in ImageList
- internal ColorDepth ColorDepth {
- get {
- return this.colorDepth;
- }
- set {
- if (!Enum.IsDefined(typeof(ColorDepth), value))
- throw new InvalidEnumArgumentException("value", (int)value, typeof(ColorDepth));
- if (this.colorDepth != value) {
- this.colorDepth = value;
- RecreateHandle();
- }
- }
- }
- // For use in ImageList
- internal IntPtr Handle {
- get {
- CreateHandle();
- return (IntPtr)(-1);
- }
- }
- // For use in ImageList
- internal bool HandleCreated {
- get {
- return this.handleCreated;
- }
- }
- // For use in ImageList
- internal Size ImageSize {
- get {
- return this.imageSize;
- }
- set {
- if (value.Width < 1 || value.Width > 256 || value.Height < 1 || value.Height > 256)
- throw new ArgumentException("ImageSize.Width and Height must be between 1 and 256", "value");
- if (this.imageSize != value) {
- this.imageSize = value;
- RecreateHandle();
- }
- }
- }
- // For use in ImageList
- internal ImageListStreamer ImageStream {
- get {
- return this.Empty ? null : new ImageListStreamer(this);
- }
- set {
- int index;
- Image[] streamImages;
- if (value == null) {
- if (this.handleCreated)
- DestroyHandle();
- else
- this.Clear();
- }
- // Only deserialized ImageListStreamers are used.
- else if ((streamImages = value.Images) != null) {
- this.list = new ArrayList(streamImages.Length);
- this.count = 0;
- this.handleCreated = true;
- this.keys = new ArrayList(streamImages.Length);
- for (index = 0; index < streamImages.Length; index++) {
- list.Add((Image)streamImages[index].Clone());
- keys.Add(null);
- }
- // Invalid ColorDepth values are ignored.
- if (Enum.IsDefined(typeof(ColorDepth), value.ColorDepth))
- this.colorDepth = (ColorDepth)value.ColorDepth;
- this.imageSize = value.ImageSize;
- // Event is raised even when handle was not created yet.
- owner.OnRecreateHandle();
- }
- }
- }
- // For use in ImageList
- internal Color TransparentColor {
- get {
- return this.transparentColor;
- }
- set {
- this.transparentColor = value;
- }
- }
- #endregion // ImageCollection Internal Instance Properties
- #region ImageCollection Public Instance Properties
- [Browsable(false)]
- public int Count {
- get {
- return this.handleCreated ? list.Count : this.count;
- }
- }
- public bool Empty {
- get {
- return this.Count == 0;
- }
- }
- public bool IsReadOnly {
- get {
- return false;
- }
- }
- [Browsable(false)]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public Image this[int index] {
- get {
- return (Image)GetImage(index).Clone();
- }
- set {
- Image image;
- if (index < 0 || index >= this.Count)
- throw new ArgumentOutOfRangeException("index");
- if (value == null)
- throw new ArgumentNullException("value");
- if (!(value is Bitmap))
- throw new ArgumentException("Image must be a Bitmap.");
- image = CreateImage(value, this.transparentColor);
- CreateHandle();
- list[index] = image;
- }
- }
- public Image this[string key] {
- get {
- int index;
- return (index = IndexOfKey(key)) == -1 ? null : this[index];
- }
- }
- public StringCollection Keys {
- get {
- int index;
- string key;
- StringCollection keyCollection;
- // Returns all keys even when there are more keys than
- // images. Null keys are returned as empty strings.
- keyCollection = new StringCollection();
- for (index = 0; index < keys.Count; index++)
- keyCollection.Add(((key = (string)keys[index]) == null || key.Length == 0) ? string.Empty : key);
- return keyCollection;
- }
- }
- #endregion // ImageCollection Public Instance Properties
- #region ImageCollection Private Static Methods
- private static bool CompareKeys(string key1, string key2)
- {
- // Keys are case-insensitive and keys with different length
- // are not equal even when string.Compare treats them equal.
- if (key1 == null || key2 == null || key1.Length != key2.Length)
- return false;
- return string.Compare(key1, key2, true, CultureInfo.InvariantCulture) == 0;
- }
- #endregion // ImageCollection Private Static Methods
- #region ImageCollection Private Instance Methods
- private int AddItem(string key, ImageListItem item)
- {
- int itemIndex;
- int index;
- if (this.handleCreated)
- itemIndex = AddItemInternal(item);
- else {
- // Image strips are counted as a single item in the return
- // value of Add and AddStrip until handle is created.
- itemIndex = list.Add(item);
- this.count += item.ImageCount;
- }
- if ((item.Flags & ItemFlags.ImageStrip) == 0)
- keys.Add(key);
- else
- for (index = 0; index < item.ImageCount; index++)
- keys.Add(null);
- 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;
- Bitmap bitmap;
- Graphics graphics;
- bitmap = new Bitmap(imageWidth = this.imageSize.Width, imageHeight = this.imageSize.Height, PixelFormat.Format32bppArgb);
- graphics = Graphics.FromImage(bitmap);
- graphics.DrawIcon((Icon)item.Image, new Rectangle(0, 0, imageWidth, imageHeight));
- graphics.Dispose();
- ReduceColorDepth(bitmap);
- return list.Add(bitmap);
- }
- else if ((item.Flags & ItemFlags.ImageStrip) == 0)
- return list.Add(CreateImage((Image)item.Image, (item.Flags & ItemFlags.UseTransparentColor) == 0 ? this.transparentColor : item.TransparentColor));
- else {
- int imageX;
- int width;
- int imageWidth;
- int imageHeight;
- int index;
- Image image;
- Bitmap bitmap;
- Graphics graphics;
- Rectangle imageRect;
- ImageAttributes imageAttributes;
- // When ImageSize was changed after adding image strips
- // Count will return invalid values based on old ImageSize
- // but when creating handle either ArgumentException will
- // be thrown or image strip will be added according to the
- // new ImageSize. This can result in image count
- // difference that can result in exceptions in methods
- // that use Count before creating handle. In addition this
- // can result in the loss of sync with keys. When doing
- // the same after handle was created there are no problems
- // as handle will be recreated after changing ImageSize
- // that results in the loss of images added previously.
- if ((width = (image = (Image)item.Image).Width) == 0 || (width % (imageWidth = this.imageSize.Width)) != 0)
- throw new ArgumentException("Width of image strip must be a positive multiple of ImageSize.Width.", "value");
- if (image.Height != (imageHeight = this.imageSize.Height))
- throw new ArgumentException("Height of image strip must be equal to ImageSize.Height.", "value");
- imageRect = new Rectangle(0, 0, imageWidth, imageHeight);
- if (this.transparentColor.A == 0)
- imageAttributes = null;
- else {
- imageAttributes = new ImageAttributes();
- imageAttributes.SetColorKey(this.transparentColor, this.transparentColor);
- }
- index = list.Count;
- for (imageX = 0; imageX < width; imageX += imageWidth) {
- bitmap = new Bitmap(imageWidth, imageHeight, PixelFormat.Format32bppArgb);
- graphics = Graphics.FromImage(bitmap);
- graphics.DrawImage(image, imageRect, imageX, 0, imageWidth, imageHeight, GraphicsUnit.Pixel, imageAttributes);
- graphics.Dispose();
- ReduceColorDepth(bitmap);
- list.Add(bitmap);
- }
- if (imageAttributes != null)
- imageAttributes.Dispose();
- return index;
- }
- }
- private void CreateHandle()
- {
- int index;
- ArrayList items;
- if (!this.handleCreated) {
- items = this.list;
- this.list = new ArrayList(this.count);
- this.count = 0;
- this.handleCreated = true;
- for (index = 0; index < items.Count; index++)
- AddItemInternal((ImageListItem)items[index]);
- }
- }
- private Image CreateImage(Image value, Color transparentColor)
- {
- int imageWidth;
- int imageHeight;
- ImageAttributes imageAttributes;
- if (transparentColor.A == 0)
- imageAttributes = null;
- else {
- imageAttributes = new ImageAttributes();
- imageAttributes.SetColorKey (transparentColor, transparentColor);
- }
- 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 ();
- ReduceColorDepth (bitmap);
- return bitmap;
- }
- private void RecreateHandle()
- {
- if (this.handleCreated) {
- DestroyHandle();
- this.handleCreated = true;
- owner.OnRecreateHandle();
- }
- }
- private unsafe void ReduceColorDepth(Bitmap bitmap)
- {
- byte* pixelPtr;
- byte* lineEndPtr;
- byte* linePtr;
- int line;
- int pixel;
- int height;
- int widthBytes;
- int stride;
- BitmapData bitmapData;
- Color[] palette;
- if (this.colorDepth < ColorDepth.Depth32Bit) {
- bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
- try {
- linePtr = (byte*)bitmapData.Scan0;
- height = bitmapData.Height;
- widthBytes = bitmapData.Width << 2;
- stride = bitmapData.Stride;
- if (this.colorDepth < ColorDepth.Depth16Bit) {
- palette = (this.colorDepth < ColorDepth.Depth8Bit ? IndexedColorDepths.Palette4Bit : IndexedColorDepths.Palette8Bit).Entries;
- for (line = 0; line < height; line++) {
- lineEndPtr = linePtr + widthBytes;
- for (pixelPtr = linePtr; pixelPtr < lineEndPtr; pixelPtr += 4)
- *(int*)pixelPtr = ((pixel = *(int*)pixelPtr) & AlphaMask) == 0 ? 0x00000000 : IndexedColorDepths.GetNearestColor(palette, pixel | AlphaMask);
- linePtr += stride;
- }
- }
- else if (this.colorDepth < ColorDepth.Depth24Bit) {
- for (line = 0; line < height; line++) {
- lineEndPtr = linePtr + widthBytes;
- for (pixelPtr = linePtr; pixelPtr < lineEndPtr; pixelPtr += 4)
- *(int*)pixelPtr = ((pixel = *(int*)pixelPtr) & AlphaMask) == 0 ? 0x00000000 : (pixel & 0x00F8F8F8) | AlphaMask;
- linePtr += stride;
- }
- }
- else {
- for (line = 0; line < height; line++) {
- lineEndPtr = linePtr + widthBytes;
- for (pixelPtr = linePtr; pixelPtr < lineEndPtr; pixelPtr += 4)
- *(int*)pixelPtr = ((pixel = *(int*)pixelPtr) & AlphaMask) == 0 ? 0x00000000 : pixel | AlphaMask;
- linePtr += stride;
- }
- }
- }
- finally {
- bitmap.UnlockBits(bitmapData);
- }
- }
- }
- #endregion // ImageCollection Private Instance Methods
- #region ImageCollection Internal Instance Methods
- // For use in ImageList
- internal void DestroyHandle()
- {
- if (this.handleCreated) {
- this.list = new ArrayList();
- this.count = 0;
- this.handleCreated = false;
- keys = new ArrayList();
- }
- }
- // For use in ImageList
- internal Image GetImage(int index)
- {
- if (index < 0 || index >= this.Count)
- throw new ArgumentOutOfRangeException("index");
- CreateHandle();
- return (Image)list[index];
- }
- // For use in ImageListStreamer
- internal Image[] ToArray()
- {
- Image[] images;
- // Handle is created even when the list is empty.
- CreateHandle();
- images = new Image[list.Count];
- list.CopyTo(images);
- return images;
- }
- #endregion // ImageCollection Internal Instance Methods
- #region ImageCollection Public Instance Methods
- public void Add(Icon value)
- {
- Add(null, value);
- }
- public void Add(Image value)
- {
- Add(null, value);
- }
- public int Add(Image value, Color transparentColor)
- {
- return AddItem(null, new ImageListItem(value, transparentColor));
- }
- public void Add(string key, Icon icon)
- {
- // Argument has name icon but exceptions use name value.
- AddItem(key, new ImageListItem(icon));
- }
- public void Add(string key, Image image)
- {
- // Argument has name image but exceptions use name value.
- AddItem(key, new ImageListItem(image));
- }
- public void AddRange(Image[] images)
- {
- int index;
- if (images == null)
- throw new ArgumentNullException("images");
- for (index = 0; index < images.Length; index++)
- Add(images[index]);
- }
- public int AddStrip(Image value)
- {
- int width;
- int imageWidth;
- if (value == null)
- throw new ArgumentNullException("value");
- if ((width = value.Width) == 0 || (width % (imageWidth = this.imageSize.Width)) != 0)
- throw new ArgumentException("Width of image strip must be a positive multiple of ImageSize.Width.", "value");
- if (value.Height != this.imageSize.Height)
- throw new ArgumentException("Height of image strip must be equal to ImageSize.Height.", "value");
- return AddItem(null, new ImageListItem(value, width / imageWidth));
- }
- public void Clear()
- {
- list.Clear();
- if (!this.handleCreated)
- this.count = 0;
- keys.Clear();
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool Contains(Image image)
- {
- throw new NotSupportedException();
- }
- public bool ContainsKey(string key)
- {
- return IndexOfKey(key) != -1;
- }
- public IEnumerator GetEnumerator()
- {
- Image[] images = new Image[this.Count];
- int index;
- if (images.Length != 0) {
- // Handle is created only when there are images.
- CreateHandle();
- for (index = 0; index < images.Length; index++)
- images[index] = (Image)((Image)list[index]).Clone();
- }
- return images.GetEnumerator();
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public int IndexOf(Image image)
- {
- throw new NotSupportedException();
- }
- public int IndexOfKey(string key)
- {
- int index;
- if (key != null && key.Length != 0) {
- // When last IndexOfKey was successful and the same key was
- // assigned to an image with a lower index than the last
- // result and the key of the last result equals to key
- // argument the last result is returned.
- if (this.lastKeyIndex >= 0 && this.lastKeyIndex < this.Count && CompareKeys((string)keys[this.lastKeyIndex], key))
- return this.lastKeyIndex;
- // Duplicate keys are allowed and first match is returned.
- for (index = 0; index < this.Count; index++)
- if (CompareKeys((string)keys[index], key))
- return this.lastKeyIndex = index;
- }
- return this.lastKeyIndex = -1;
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public void Remove(Image image)
- {
- throw new NotSupportedException();
- }
- public void RemoveAt(int index)
- {
- if (index < 0 || index >= this.Count)
- throw new ArgumentOutOfRangeException("index");
- CreateHandle();
- list.RemoveAt(index);
- keys.RemoveAt(index);
- if (Changed != null)
- Changed (this, EventArgs.Empty);
- }
- public void RemoveByKey(string key)
- {
- int index;
- if ((index = IndexOfKey(key)) != -1)
- RemoveAt(index);
- }
- public void SetKeyName(int index, string name)
- {
- // Only SetKeyName throws IndexOutOfRangeException.
- if (index < 0 || index >= this.Count)
- throw new IndexOutOfRangeException();
- keys[index] = name;
- }
- #endregion // ImageCollection Public Instance Methods
- #region ImageCollection Interface Properties
- object IList.this[int index] {
- get {
- return this[index];
- }
- set {
- if (!(value is Image))
- throw new ArgumentException("value");
- this[index] = (Image)value;
- }
- }
- bool IList.IsFixedSize {
- get {
- return false;
- }
- }
- bool ICollection.IsSynchronized {
- get {
- return false;
- }
- }
- object ICollection.SyncRoot {
- get {
- return this;
- }
- }
- #endregion // ImageCollection Interface Properties
- #region ImageCollection Interface Methods
- int IList.Add(object value)
- {
- int index;
- if (!(value is Image))
- throw new ArgumentException("value");
- index = this.Count;
- this.Add((Image)value);
- return index;
- }
- bool IList.Contains(object image)
- {
- return image is Image ? this.Contains ((Image) image) : false;
- }
- int IList.IndexOf (object image)
- {
- return image is Image ? this.IndexOf ((Image) image) : -1;
- }
- void IList.Insert(int index, object value)
- {
- throw new NotSupportedException();
- }
- void IList.Remove (object image)
- {
- if (image is Image)
- this.Remove ((Image) image);
- }
- void ICollection.CopyTo(Array dest, int index)
- {
- for (int imageIndex = 0; imageIndex < this.Count; imageIndex++)
- dest.SetValue (this[imageIndex], index++);
- }
- #endregion // ImageCollection Interface Methods
- }
- #endregion // Sub-classes
- #region Public Constructors
- public ImageList()
- {
- images = new ImageCollection(this);
- }
- public ImageList(System.ComponentModel.IContainer container) : this()
- {
- container.Add(this);
- }
- #endregion // Public Constructors
- #region Private Instance Methods
- private void OnRecreateHandle()
- {
- EventHandler eh = (EventHandler)(Events [RecreateHandleEvent]);
- if (eh != null)
- eh (this, EventArgs.Empty);
- }
- // 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.
- internal bool ShouldSerializeTransparentColor ()
- {
- return this.TransparentColor != Color.LightGray;
- }
- 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;
- }
- 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;
- }
- internal void ResetColorDepth ()
- {
- this.ColorDepth = DefaultColorDepth;
- }
- internal void ResetImageSize ()
- {
- this.ImageSize = DefaultImageSize;
- }
- internal void ResetTransparentColor ()
- {
- this.TransparentColor = Color.LightGray;
- }
- #endregion // Private Instance Methods
- #region Public Instance Properties
- public ColorDepth ColorDepth {
- get {
- return images.ColorDepth;
- }
- set {
- images.ColorDepth = value;
- }
- }
- [Browsable(false)]
- [EditorBrowsable(EditorBrowsableState.Advanced)]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public IntPtr Handle {
- get {
- return images.Handle;
- }
- }
- [Browsable(false)]
- [EditorBrowsable(EditorBrowsableState.Advanced)]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public bool HandleCreated {
- get {
- return images.HandleCreated;
- }
- }
- [DefaultValue(null)]
- [MergableProperty(false)]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public ImageCollection Images {
- get {
- return this.images;
- }
- }
- [Localizable(true)]
- public Size ImageSize {
- get {
- return images.ImageSize;
- }
- set {
- images.ImageSize = value;
- }
- }
- [Browsable(false)]
- [DefaultValue(null)]
- [EditorBrowsable(EditorBrowsableState.Advanced)]
- public ImageListStreamer ImageStream {
- get {
- return images.ImageStream;
- }
- set {
- images.ImageStream = value;
- }
- }
- [Bindable(true)]
- [DefaultValue(null)]
- [Localizable(false)]
- [TypeConverter(typeof(StringConverter))]
- public object Tag {
- get {
- return this.tag;
- }
- set {
- this.tag = value;
- }
- }
- public Color TransparentColor {
- get {
- return images.TransparentColor;
- }
- set {
- images.TransparentColor = value;
- }
- }
- #endregion // Public Instance Properties
- #region Public Instance Methods
- public void Draw(Graphics g, Point pt, int index)
- {
- this.Draw(g, pt.X, pt.Y, index);
- }
- public void Draw(Graphics g, int x, int y, int index)
- {
- g.DrawImage(images.GetImage(index), x, y);
- }
- public void Draw(Graphics g, int x, int y, int width, int height, int index)
- {
- g.DrawImage(images.GetImage(index), x, y, width, height);
- }
- public override string ToString()
- {
- return base.ToString() + " Images.Count: " + images.Count.ToString() + ", ImageSize: " + this.ImageSize.ToString();
- }
- #endregion // Public Instance Methods
- #region Protected Instance Methods
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- images.DestroyHandle();
- base.Dispose(disposing);
- }
- #endregion // Protected Instance Methods
- #region Events
- static object RecreateHandleEvent = new object ();
- [Browsable(false)]
- [EditorBrowsable(EditorBrowsableState.Advanced)]
- public event EventHandler RecreateHandle {
- add { Events.AddHandler (RecreateHandleEvent, value); }
- remove { Events.RemoveHandler (RecreateHandleEvent, value); }
- }
- #endregion // Events
- }
- }