Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ImageList.cs
index 734c6c5c0e701273d9ec2219c0932bd2adad8371..b0f0c4a0272aadd341da2e62cc2c569b0c8d6606 100644 (file)
 // 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.
 //
@@ -78,22 +74,16 @@ namespace System.Windows.Forms
 {
        [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
 
@@ -103,67 +93,31 @@ namespace System.Windows.Forms
                {
                        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;
@@ -176,7 +130,7 @@ namespace System.Windows.Forms
 
                                        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);
@@ -186,8 +140,8 @@ namespace System.Windows.Forms
                                        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;
                                                }
 
@@ -246,17 +200,13 @@ namespace System.Windows.Forms
 
                        #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
 
@@ -329,36 +279,30 @@ namespace System.Windows.Forms
                                        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
                                        }
                                }
                        }
@@ -420,7 +364,6 @@ namespace System.Windows.Forms
                                }
                        }
 
-#if NET_2_0
                        public Image this[string key] {
                                get {
                                        int index;
@@ -445,11 +388,9 @@ namespace System.Windows.Forms
                                        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
@@ -460,20 +401,13 @@ namespace System.Windows.Forms
 
                                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);
@@ -485,19 +419,22 @@ namespace System.Windows.Forms
                                        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;
@@ -590,26 +527,23 @@ namespace System.Windows.Forms
                        {
                                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;
                        }
 
@@ -633,7 +567,7 @@ namespace System.Windows.Forms
                                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);
@@ -644,7 +578,7 @@ namespace System.Windows.Forms
                                                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;
@@ -685,9 +619,7 @@ namespace System.Windows.Forms
                                        this.list = new ArrayList();
                                        this.count = 0;
                                        this.handleCreated = false;
-#if NET_2_0
                                        keys = new ArrayList();
-#endif
                                }
                        }
 
@@ -717,32 +649,19 @@ namespace System.Windows.Forms
                        #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.
@@ -765,7 +684,6 @@ namespace System.Windows.Forms
                                for (index = 0; index < images.Length; index++)
                                        Add(images[index]);
                        }
-#endif
 
                        public int AddStrip(Image value)
                        {
@@ -781,37 +699,27 @@ namespace System.Windows.Forms
                                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()
                        {
@@ -829,15 +737,12 @@ namespace System.Windows.Forms
                                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;
@@ -859,11 +764,8 @@ namespace System.Windows.Forms
 
                                return this.lastKeyIndex = -1;
                        }
-#endif
 
-#if NET_2_0
                        [EditorBrowsable(EditorBrowsableState.Never)]
-#endif
                        public void Remove(Image image)
                        {
                                throw new NotSupportedException();
@@ -876,12 +778,11 @@ namespace System.Windows.Forms
 
                                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;
@@ -898,7 +799,6 @@ namespace System.Windows.Forms
 
                                keys[index] = name;
                        }
-#endif
                        #endregion // ImageCollection Public Instance Methods
 
                        #region ImageCollection Interface Properties
@@ -947,14 +847,14 @@ namespace System.Windows.Forms
                                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)
@@ -962,18 +862,16 @@ namespace System.Windows.Forms
                                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
                }
@@ -994,57 +892,54 @@ namespace System.Windows.Forms
                #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;
@@ -1106,7 +1001,6 @@ namespace System.Windows.Forms
                        }
                }
 
-#if NET_2_0
                [Bindable(true)]
                [DefaultValue(null)]
                [Localizable(false)]
@@ -1120,7 +1014,6 @@ namespace System.Windows.Forms
                                this.tag = value;
                        }
                }
-#endif
 
                public Color TransparentColor {
                        get {
@@ -1151,7 +1044,7 @@ namespace System.Windows.Forms
 
                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
 
@@ -1166,16 +1059,13 @@ namespace System.Windows.Forms
                #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
        }