* X11Keyboard.cs: Detect and use the num lock mask.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ImageList.cs
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:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
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.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25 //
26 // $Log: ImageList.cs,v $
27 // Revision 1.7  2004/11/04 11:04:40  ravindra
28 // Implemented the missing overload for Draw method.
29 //
30 // Revision 1.6  2004/08/21 01:50:52  ravindra
31 // Changed draw method to use the arguments passed in to draw the image.
32 //
33 // Revision 1.5  2004/08/19 21:39:09  pbartok
34 // - Added missing Draw() method
35 // - Added missing RecreateHandle event
36 //
37 // Revision 1.4  2004/08/11 17:43:08  pbartok
38 // - Removed disposing of the actual images when the list is disposed
39 //
40 // Revision 1.3  2004/08/11 13:43:13  pbartok
41 // - Added missing creation of the collection list
42 //
43 // Revision 1.2  2004/08/09 23:12:13  pbartok
44 // - Fixed several bugs Ravindra pointed out
45 //
46 // Revision 1.1  2004/07/15 20:05:28  pbartok
47 // - Implemented ImageList and ImageList.ImageCollection classes
48 // - Added ColorDepth enumeration
49 // - Updated SWF VS.Net project
50 //
51 //
52
53 // COMPLETE
54
55 using System.Collections;
56 using System.ComponentModel;
57 using System.Drawing;
58 using System.Drawing.Imaging;
59
60 namespace System.Windows.Forms {
61         public sealed class ImageList : System.ComponentModel.Component {
62                 #region Local Variables
63                 private ColorDepth              color_depth;
64                 private ImageCollection         image_collection;
65                 private Size                    size;
66                 private Color                   transparency_color;
67                 private Delegate                handler;
68                 private ImageListStreamer       image_stream;
69                 #endregion      // Local Variables
70
71                 #region Sub-classes
72                 public sealed class ImageCollection : IList, ICollection, IEnumerable {
73                         #region ImageCollection Local Variables
74                         private ImageList       owner;
75                         private ArrayList       list;
76                         #endregion      // ImageCollection Local Variables
77
78                         #region ImageCollection Private Constructors
79                         internal ImageCollection(ImageList owner) {
80                                 this.owner=owner;
81                                 this.list=new ArrayList();
82                         }
83                         #endregion      // ImageCollection Private Constructor
84
85                         #region ImageCollection Public Instance Properties
86                         public int Count {
87                                 get {
88                                         return list.Count;
89                                 }
90                         }
91
92                         public bool Empty {
93                                 get {
94                                         return list.Count==0;
95                                 }
96                         }
97
98                         public bool IsReadOnly {
99                                 get {
100                                         return list.IsReadOnly;
101                                 }
102                         }
103
104                         public Image this[int index] {
105                                 get {
106                                         if (index<0 || index>=list.Count) {
107                                                 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
108                                         }
109                                         return (Image)list[index];
110                                 }
111
112                                 set {
113                                         if (index<0 || index>=list.Count) {
114                                                 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
115                                         }
116
117                                         if (value==null) {
118                                                 throw new ArgumentOutOfRangeException("value", value, "Image cannot be null");
119                                         }
120
121                                         list[index]=value;
122                                         // What happens if the bitmap had a previous 'MakeTransparent' done to it?
123                                         ((Bitmap)list[index]).MakeTransparent(owner.transparency_color);
124                                 }
125                         }
126                         #endregion      // ImageCollection Public Instance Properties
127
128                         #region ImageCollection Private Instance Methods
129                         private int AddInternal(Image image) {
130                                 int             width;
131                                 int             height;
132                                 PixelFormat     format;
133
134                                 width=owner.ImageSize.Width;
135                                 height=owner.ImageSize.Height;
136                                 switch(owner.color_depth) {
137                                         case ColorDepth.Depth4Bit:      format=PixelFormat.Format4bppIndexed; break;
138                                         case ColorDepth.Depth8Bit:      format=PixelFormat.Format8bppIndexed; break;
139                                         case ColorDepth.Depth16Bit:     format=PixelFormat.Format16bppRgb555; break;
140                                         case ColorDepth.Depth24Bit:     format=PixelFormat.Format24bppRgb; break;
141                                         case ColorDepth.Depth32Bit:     format=PixelFormat.Format32bppRgb; break;
142                                         default:                        format=PixelFormat.Format32bppRgb; break;
143                                 }
144
145                                 // Check if we can add straight or if we have to resize
146                                 if (image.Width!=width || image.Height!=height || image.PixelFormat!=format) {
147                                         Graphics        g;
148                                         Bitmap          reformatted_image;
149
150                                         reformatted_image = new Bitmap(width, height, format);
151                                         g=Graphics.FromImage(reformatted_image);
152
153                                         g.DrawImage(image, new Rectangle(0, 0, width, height), 0, 0, width, height, GraphicsUnit.Pixel);
154                                         g.Dispose();
155
156                                         return list.Add(reformatted_image);
157                                 } else {
158                                         return list.Add(image);
159                                 }
160                         }
161
162                         internal void Dispose() {
163 #if dontwantthis
164                                 if (list!=null) {
165                                         for (int i=0; i<list.Count; i++) {
166                                                 ((Image)list[i]).Dispose();
167                                         }
168                                 }
169 #endif
170                         }
171                         #endregion      // ImageCollection Private Instance Methods
172
173                         #region ImageCollection Public Instance Methods
174                         public int Add(Image value, Color transparentColor) {
175                                 if (value==null) {
176                                         throw new ArgumentNullException("value", "Cannot add null image");
177                                 }
178
179                                 ((Bitmap)value).MakeTransparent(owner.transparency_color);
180                                 return AddInternal(value);
181                                 
182                         }
183
184                         public void Add(Icon value) {
185                                 Image image;
186
187                                 image = value.ToBitmap();
188
189                                 if (value==null || image==null) {
190                                         throw new ArgumentNullException("value", "Cannot add null icon");
191                                 }
192
193                                 ((Bitmap)image).MakeTransparent(owner.transparency_color);
194                                 AddInternal(image);
195                         }
196
197                         public void Add(Image value) {
198                                 if (value==null) {
199                                         throw new ArgumentNullException("value", "Cannot add null image");
200                                 }
201                                 ((Bitmap)value).MakeTransparent(owner.transparency_color);
202                                 AddInternal(value);
203                         }
204
205                         public int AddStrip(Image value) {
206                                 int             image_count;
207                                 int             width;
208                                 int             height;
209                                 Bitmap          image;
210                                 Graphics        g;
211
212                                 if (value==null) {
213                                         throw new ArgumentNullException("value", "Cannot add null images");
214                                 }
215
216                                 if ((value.Width % owner.ImageSize.Width) != 0) {
217                                         throw new ArgumentException("Strip is not a multiple of the ImageList with", "value");
218                                 }
219
220                                 // MSDN: The number of images is inferred from the width. A strip is multiple images side-by-side
221                                 width=owner.ImageSize.Width;
222                                 height=owner.ImageSize.Height;
223                                 image_count=value.Width/width;
224                                 for (int i=0; i<image_count; i++) {
225                                         image = new Bitmap(value, width, height);
226                                         g = Graphics.FromImage(image);
227
228                                         g.DrawImage(value, new Rectangle(0, 0, width, height), i*width, 0, width, height, GraphicsUnit.Pixel);
229                                         AddInternal(image);
230
231                                         g.Dispose();
232                                         image.Dispose();
233                                 }
234
235                                 // FIXME - is this right? MSDN says to return the index, but we might have multiple...
236                                 return image_count;
237                         }
238
239                         public void Clear() {
240                                 list.Clear();
241                         }
242
243                         public bool Contains(Image image) {
244                                 return list.Contains(image);
245                         }
246
247                         public IEnumerator GetEnumerator() {
248                                 return list.GetEnumerator();
249                         }
250
251                         public int IndexOf(Image image) {
252                                 return list.IndexOf(image);
253                         }
254
255                         public void Remove(Image image) {
256                                 list.Remove(image);
257                         }
258
259                         public void RemoveAt(int index) {
260                                 if (index<0 || index>=list.Count) {
261                                         throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
262                                 }
263
264                                 list.RemoveAt(index);
265                         }
266                         #endregion      // ImageCollection Public Instance Methods
267
268                         #region ImageCollection Interface Properties
269                         object IList.this[int index] {
270                                 get {
271                                         if (index<0 || index>=list.Count) {
272                                                 throw new ArgumentOutOfRangeException("index", index, "ImageCollection does not have that many images");
273                                         }
274                                         return this[index];
275                                 }
276
277                                 set {
278                                         if (!(value is Bitmap)) {
279                                                 throw new ArgumentException("Object of type Image required", "value");
280                                         }
281
282                                         this[index]=(Image)value;
283                                 }
284                         }
285
286                         bool IList.IsFixedSize {
287                                 get {
288                                         return false;
289                                 }
290                         }
291
292                         bool IList.IsReadOnly {
293                                 get {
294                                         return list.IsReadOnly;
295                                 }
296                         }
297
298                         bool ICollection.IsSynchronized {
299                                 get {
300                                         return list.IsSynchronized;
301                                 }
302                         }
303
304                         object ICollection.SyncRoot {
305                                 get {
306                                         return list.SyncRoot;
307                                 }
308                         }
309                         #endregion      // ImageCollection Interface Properties
310
311                         #region ImageCollection Interface Methods
312                         int IList.Add(object value) {
313                                 if (value == null) {
314                                         throw new ArgumentNullException("value", "Cannot add null images");
315                                 }
316
317                                 if (!(value is Bitmap)) {
318                                         throw new ArgumentException("Object of type Image required", "value");
319                                 }
320
321                                 return list.Add(value);
322                         }
323
324                         bool IList.Contains(object value) {
325                                 if (!(value is Bitmap)) {
326                                         throw new ArgumentException("Object of type Image required", "value");
327                                 }
328
329                                 return this.Contains((Image) value);
330                         }
331
332                         int IList.IndexOf(object value) {
333                                 if (!(value is Bitmap)) {
334                                         throw new ArgumentException("Object of type Image required", "value");
335                                 }
336
337                                 return this.IndexOf((Image) value);
338                         }
339
340                         void IList.Insert(int index, object value) {
341                                 if (!(value is Bitmap)) {
342                                         throw new ArgumentException("Object of type Image required", "value");
343                                 }
344                                 list.Insert(index, value);
345                         }
346
347                         void IList.Remove(object value) {
348                                 if (!(value is Bitmap)) {
349                                         throw new ArgumentException("Object of type Image required", "value");
350                                 }
351                                 list.Remove(value);
352                         }
353
354                         void ICollection.CopyTo(Array array, int index) {
355                                 if (list.Count>0) {
356                                         list.CopyTo(array, index);
357                                 }
358                         }
359                         #endregion      // ImageCollection Interface Methods
360                 }
361                 #endregion      // Sub-classes
362
363                 #region Public Constructors
364                 public ImageList() {
365                         color_depth = ColorDepth.Depth8Bit;
366                         transparency_color = Color.Transparent;
367                         size = new Size(16, 16);
368                         image_collection = new ImageCollection(this);
369                 }
370
371                 [MonoTODO]
372                 public ImageList(System.ComponentModel.IContainer container) {
373                         throw new NotImplementedException();
374                 }
375                 #endregion      // Public Constructors
376
377                 #region Public Instance Properties
378                 public ColorDepth ColorDepth {
379                         get {
380                                 return this.color_depth;
381                         }
382
383                         set {
384                                 this.color_depth=value;
385                         }
386                 }
387
388                 [MonoTODO("Determine if we support HBITMAP handles, this would involve XplatUI")]
389                 public IntPtr Handle {
390                         get {
391                                 if (RecreateHandle!=null) RecreateHandle(this, EventArgs.Empty);
392                                 return IntPtr.Zero;
393                         }
394                 }
395
396                 [MonoTODO("Determine if we support HBITMAP handles, this would involve XplatUI")]
397                 public bool HandleCreated {
398                         get {
399                                 return false;
400                         }
401                 }
402
403                 public ImageCollection Images {
404                         get {
405                                 return this.image_collection;
406                         }
407                 }
408
409                 public Size ImageSize {
410                         get {
411                                 return this.size;
412                         }
413
414                         set {
415                                 if (value.Width<1 || value.Width>256 || value.Height<1 || value.Height>256) {
416                                         throw new ArgumentException("ImageSize width and height must be between 1 and 255", "value");
417                                 }
418                                 this.size=value;
419                         }
420                 }
421
422                 public ImageListStreamer ImageStream {
423                         get {
424                                 return image_stream;
425                         }
426
427                         set {
428                                 image_stream = value;
429                         }
430                 }
431
432                 public Color TransparentColor {
433                         get {
434                                 return this.transparency_color;
435                         }
436
437                         set {
438                                 this.transparency_color=value;
439                         }
440                 }
441                 #endregion      // Public Instance Properties
442
443                 #region Public Instance Methods
444                 public void Draw(Graphics g, Point pt, int index) {
445                         this.Draw(g, pt.X, pt.Y, index);
446                 }
447
448                 public void Draw(Graphics g, int x, int y, int index) {
449                         this.Draw(g, x, y, this.size.Width, this.size.Height, index);
450                 }
451
452                 public void Draw(Graphics g, int x, int y, int width, int height, int index) {
453                         Image   i;
454
455                         if ((index < 0) || (index >= this.Images.Count)) {
456                                 throw new ArgumentOutOfRangeException("index", index, "ImageList does not contain that many images");
457                         }
458                         i = this.Images[index];
459                         g.DrawImage(i, x, y, width, height);
460                 }
461
462                 public override string ToString() {\r
463                         return "ImageList Size "+this.size.Width.ToString()+"x"+this.size.Height.ToString()+", Depth "+this.color_depth.ToString()+", Transparency color "+this.transparency_color.ToString();\r
464                 }
465                 #endregion      // Public Instance Methods
466
467                 #region Protected Instance Methods
468                 protected override void Dispose(bool disposing) {\r
469                         if (image_collection!=null) {\r
470                                 image_collection.Dispose();\r
471                         }\r
472                 }\r
473
474                 #endregion      // Protected Instance Methods
475
476                 #region Events
477                 public event EventHandler RecreateHandle;
478                 #endregion      // Events
479         }
480 }