1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
29 using System.Collections;
30 using System.ComponentModel;
32 using System.Drawing.Imaging;
34 namespace System.Windows.Forms {
35 [DefaultProperty("Images")]
36 [Designer("System.Windows.Forms.Design.ImageListDesigner, " + Consts.AssemblySystem_Design)]
37 [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow)]
38 [TypeConverter("System.Windows.Forms.ImageListConverter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
39 public sealed class ImageList : System.ComponentModel.Component {
40 #region Local Variables
41 private ColorDepth color_depth;
42 private ImageCollection image_collection;
44 private Color transparency_color;
45 private Delegate handler;
46 private ImageListStreamer image_stream;
47 #endregion // Local Variables
50 [Editor("System.Windows.Forms.Design.ImageCollectionEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
51 public sealed class ImageCollection : IList, ICollection, IEnumerable {
52 #region ImageCollection Local Variables
53 private ImageList owner;
54 private ArrayList list;
55 #endregion // ImageCollection Local Variables
57 #region ImageCollection Private Constructors
58 internal ImageCollection(ImageList owner) {
60 this.list=new ArrayList();
62 #endregion // ImageCollection Private Constructor
64 #region ImageCollection Public Instance Properties
78 public bool IsReadOnly {
80 return list.IsReadOnly;
85 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
86 public Image this[int index] {
88 if (index<0 || index>=list.Count) {
89 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
91 return (Image)list[index];
95 if (index<0 || index>=list.Count) {
96 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
100 throw new ArgumentOutOfRangeException("value", value, "Image cannot be null");
104 // What happens if the bitmap had a previous 'MakeTransparent' done to it?
105 ((Bitmap)list[index]).MakeTransparent(owner.transparency_color);
108 #endregion // ImageCollection Public Instance Properties
110 #region ImageCollection Private Instance Methods
111 private int AddInternal(Image image) {
116 width=owner.ImageSize.Width;
117 height=owner.ImageSize.Height;
118 switch(owner.color_depth) {
119 case ColorDepth.Depth4Bit: format=PixelFormat.Format4bppIndexed; break;
120 case ColorDepth.Depth8Bit: format=PixelFormat.Format8bppIndexed; break;
121 case ColorDepth.Depth16Bit: format=PixelFormat.Format16bppRgb555; break;
122 case ColorDepth.Depth24Bit: format=PixelFormat.Format24bppRgb; break;
123 case ColorDepth.Depth32Bit: format=PixelFormat.Format32bppArgb; break;
124 default: format=PixelFormat.Format32bppArgb; break;
127 // Check if we can add straight or if we have to resize
128 if (image.Width!=width || image.Height!=height || image.PixelFormat!=format) {
130 Bitmap reformatted_image;
132 reformatted_image = new Bitmap(width, height, format);
133 g=Graphics.FromImage(reformatted_image);
135 g.DrawImage(image, new Rectangle(0, 0, width, height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
138 return list.Add(reformatted_image);
140 return list.Add(image);
144 internal void Dispose() {
147 for (int i=0; i<list.Count; i++) {
148 ((Image)list[i]).Dispose();
153 #endregion // ImageCollection Private Instance Methods
155 #region ImageCollection Public Instance Methods
156 public int Add(Image value, Color transparentColor) {
158 throw new ArgumentNullException("value", "Cannot add null image");
161 ((Bitmap)value).MakeTransparent(owner.transparency_color);
162 return AddInternal(value);
166 public void Add(Icon value) {
169 image = value.ToBitmap();
171 if (value==null || image==null) {
172 throw new ArgumentNullException("value", "Cannot add null icon");
175 ((Bitmap)image).MakeTransparent(owner.transparency_color);
179 public void Add(Image value) {
181 throw new ArgumentNullException("value", "Cannot add null image");
183 ((Bitmap)value).MakeTransparent(owner.transparency_color);
187 public int AddStrip(Image value) {
195 throw new ArgumentNullException("value", "Cannot add null images");
198 if ((value.Width % owner.ImageSize.Width) != 0) {
199 throw new ArgumentException("Strip is not a multiple of the ImageList with", "value");
202 // MSDN: The number of images is inferred from the width. A strip is multiple images side-by-side
203 width=owner.ImageSize.Width;
204 height=owner.ImageSize.Height;
205 image_count=value.Width/width;
206 for (int i=0; i<image_count; i++) {
207 image = new Bitmap(value, width, height);
208 g = Graphics.FromImage(image);
210 g.DrawImage(value, new Rectangle(0, 0, width, height), i*width, 0, width, height, GraphicsUnit.Pixel);
217 // FIXME - is this right? MSDN says to return the index, but we might have multiple...
221 public void Clear() {
225 public bool Contains(Image image) {
226 return list.Contains(image);
229 public IEnumerator GetEnumerator() {
230 return list.GetEnumerator();
233 public int IndexOf(Image image) {
234 return list.IndexOf(image);
237 public void Remove(Image image) {
241 public void RemoveAt(int index) {
242 if (index<0 || index>=list.Count) {
243 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
246 list.RemoveAt(index);
248 #endregion // ImageCollection Public Instance Methods
250 #region ImageCollection Interface Properties
251 object IList.this[int index] {
253 if (index<0 || index>=list.Count) {
254 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
260 if (!(value is Bitmap)) {
261 throw new ArgumentException("Object of type Image required", "value");
264 this[index]=(Image)value;
268 bool IList.IsFixedSize {
274 bool IList.IsReadOnly {
276 return list.IsReadOnly;
280 bool ICollection.IsSynchronized {
282 return list.IsSynchronized;
286 object ICollection.SyncRoot {
288 return list.SyncRoot;
291 #endregion // ImageCollection Interface Properties
293 #region ImageCollection Interface Methods
294 int IList.Add(object value) {
296 throw new ArgumentNullException("value", "Cannot add null images");
299 if (!(value is Bitmap)) {
300 throw new ArgumentException("Object of type Image required", "value");
303 return list.Add(value);
306 bool IList.Contains(object value) {
307 if (!(value is Bitmap)) {
308 throw new ArgumentException("Object of type Image required", "value");
311 return this.Contains((Image) value);
314 int IList.IndexOf(object value) {
315 if (!(value is Bitmap)) {
316 throw new ArgumentException("Object of type Image required", "value");
319 return this.IndexOf((Image) value);
322 void IList.Insert(int index, object value) {
323 if (!(value is Bitmap)) {
324 throw new ArgumentException("Object of type Image required", "value");
326 list.Insert(index, value);
329 void IList.Remove(object value) {
330 if (!(value is Bitmap)) {
331 throw new ArgumentException("Object of type Image required", "value");
336 void ICollection.CopyTo(Array array, int index) {
338 list.CopyTo(array, index);
341 #endregion // ImageCollection Interface Methods
343 #endregion // Sub-classes
345 #region Public Constructors
347 color_depth = ColorDepth.Depth8Bit;
348 transparency_color = Color.Transparent;
349 size = new Size(16, 16);
350 image_collection = new ImageCollection(this);
353 public ImageList(System.ComponentModel.IContainer container) : this ()
355 color_depth = ColorDepth.Depth8Bit;
356 transparency_color = Color.Transparent;
357 size = new Size(16, 16);
358 container.Add (this);
360 #endregion // Public Constructors
362 #region Public Instance Properties
363 [DefaultValue(ColorDepth.Depth8Bit)]
364 public ColorDepth ColorDepth {
366 return this.color_depth;
370 this.color_depth=value;
374 [MonoTODO("Determine if we support HBITMAP handles, this would involve XplatUI")]
376 [EditorBrowsable(EditorBrowsableState.Advanced)]
377 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
378 public IntPtr Handle {
380 if (RecreateHandle!=null) RecreateHandle(this, EventArgs.Empty);
385 [MonoTODO("Determine if we support HBITMAP handles, this would involve XplatUI")]
387 [EditorBrowsable(EditorBrowsableState.Advanced)]
388 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
389 public bool HandleCreated {
396 [MergableProperty(false)]
397 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
398 public ImageCollection Images {
400 return this.image_collection;
405 public Size ImageSize {
411 if (value.Width<1 || value.Width>256 || value.Height<1 || value.Height>256) {
412 throw new ArgumentException("ImageSize width and height must be between 1 and 255", "value");
420 [EditorBrowsable(EditorBrowsableState.Advanced)]
421 public ImageListStreamer ImageStream {
427 image_stream = value;
429 size = image_stream.ImageSize;
430 color_depth = image_stream.ImageColorDepth;
431 transparency_color = image_stream.BackColor;
433 image_collection.Clear ();
435 foreach (Image image in image_stream.Images)
436 image_collection.Add (image);
440 public Color TransparentColor {
442 return this.transparency_color;
446 this.transparency_color=value;
449 #endregion // Public Instance Properties
451 #region Public Instance Methods
452 public void Draw(Graphics g, Point pt, int index) {
453 this.Draw(g, pt.X, pt.Y, index);
456 public void Draw(Graphics g, int x, int y, int index) {
457 this.Draw(g, x, y, this.size.Width, this.size.Height, index);
460 public void Draw(Graphics g, int x, int y, int width, int height, int index) {
463 if ((index < 0) || (index >= this.Images.Count)) {
464 throw new ArgumentOutOfRangeException("index", index, "ImageList does not contain that many images");
466 i = this.Images[index];
467 g.DrawImage(i, x, y, width, height);
470 public override string ToString() {
\r
471 return "ImageList Size "+this.size.Width.ToString()+"x"+this.size.Height.ToString()+", Depth "+this.color_depth.ToString()+", Transparency color "+this.transparency_color.ToString();
\r
473 #endregion // Public Instance Methods
475 #region Protected Instance Methods
476 protected override void Dispose(bool disposing) {
\r
477 if (image_collection!=null) {
\r
478 image_collection.Dispose();
\r
482 #endregion // Protected Instance Methods
486 [EditorBrowsable(EditorBrowsableState.Advanced)]
487 public event EventHandler RecreateHandle;