2006-02-28 Mike Kestner <mkestner@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListViewItem.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. (http://www.novell.com)
21 //
22 // Author:
23 //      Ravindra (rkumar@novell.com)
24 //
25 // Todo:
26 //     - Drawing of focus rectangle
27
28
29
30 // NOT COMPLETE
31
32
33 using System.Collections;
34 using System.ComponentModel;
35 using System.Drawing;
36 using System.Runtime.Serialization;
37
38 namespace System.Windows.Forms
39 {
40         [DefaultProperty ("Text")]
41         [DesignTimeVisible (false)]
42         [Serializable]
43         [ToolboxItem (false)]
44         [TypeConverter (typeof (ListViewItemConverter))]
45         public class ListViewItem : ICloneable, ISerializable
46         {
47                 #region Instance Variables
48                 private int image_index = -1;
49                 private bool is_checked = false;
50                 private bool is_focused = false;
51                 private int state_image_index = -1;
52                 private ListViewSubItemCollection sub_items;
53                 private object tag;
54                 private bool use_item_style = true;
55
56                 Rectangle bounds;
57                 Rectangle checkbox_rect;        // calculated by CalcListViewItem method
58                 Rectangle icon_rect;
59                 Rectangle item_rect;
60                 Rectangle label_rect;
61                 ListView owner;
62                 bool selected;
63
64                 #endregion Instance Variables
65
66                 #region Public Constructors
67                 public ListViewItem ()
68                 {
69                         this.sub_items = new ListViewSubItemCollection (this);
70                         this.sub_items.Add ("");                        
71                 }
72
73                 public ListViewItem (string text) : this (text, -1)
74                 {
75                 }
76
77                 public ListViewItem (string [] items) : this (items, -1)
78                 {
79                 }
80
81                 public ListViewItem (ListViewItem.ListViewSubItem [] subItems, int imageIndex)
82                 {
83                         this.sub_items = new ListViewSubItemCollection (this);
84                         this.sub_items.AddRange (subItems);
85                         this.image_index = imageIndex;
86                 }
87
88                 public ListViewItem (string text, int imageIndex)
89                 {
90                         this.image_index = imageIndex;
91                         this.sub_items = new ListViewSubItemCollection (this);
92                         this.sub_items.Add (text);
93                 }
94
95                 public ListViewItem (string [] items, int imageIndex)
96                 {
97                         this.sub_items = new ListViewSubItemCollection (this);
98                         this.sub_items.AddRange (items);
99                         this.image_index = imageIndex;
100                 }
101
102                 public ListViewItem (string [] items, int imageIndex, Color foreColor, 
103                                      Color backColor, Font font)
104                 {
105                         this.sub_items = new ListViewSubItemCollection (this);
106                         this.sub_items.AddRange (items);
107                         this.image_index = imageIndex;
108                         ForeColor = foreColor;
109                         BackColor = backColor;
110                         Font = font;
111                 }
112                 #endregion      // Public Constructors
113
114                 #region Public Instance Properties
115                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
116                 public Color BackColor {
117                         get {
118                                 if (sub_items.Count > 0)
119                                         return sub_items[0].BackColor;
120
121                                 if (owner != null)
122                                         return owner.BackColor;
123                                 
124                                 return ThemeEngine.Current.ColorWindow;
125                         }
126
127                         set { sub_items[0].BackColor = value; }
128                 }
129
130                 [Browsable (false)]
131                 public Rectangle Bounds {
132                         get {
133                                 return GetBounds (ItemBoundsPortion.Entire);
134                         }
135                 }
136
137                 [DefaultValue (false)]
138                 [RefreshProperties (RefreshProperties.Repaint)]
139                 public bool Checked {
140                         get { return is_checked; }
141                         set { 
142                                 if (is_checked == value)
143                                         return;
144                                 
145                                 is_checked = value;
146
147                                 if (owner != null) {
148                                         if (is_checked) {
149                                                 if (owner.CheckedItems.Contains (this) == false) {
150                                                         owner.CheckedItems.list.Add (this);
151                                                         owner.CheckedIndices.list.Add (this.Index);
152                                                 }
153                                         }
154                                         else {
155                                                 owner.CheckedItems.list.Remove (this);
156                                                 owner.CheckedIndices.list.Remove (this.Index);
157                                         }
158                                         
159                                         Layout ();
160                                 }                       
161                                 Invalidate ();
162                         }
163                 }
164
165                 [Browsable (false)]
166                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
167                 public bool Focused {
168                         get { return is_focused; }
169                         set {   
170                                 if (is_focused == value)
171                                         return;
172
173                                 is_focused = value; 
174
175                                 if (owner != null)
176                                         Layout ();
177                                 Invalidate ();
178                         }
179                 }
180
181                 [Localizable (true)]
182                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
183                 public Font Font {
184                         get {
185                                 if (sub_items.Count > 0)
186                                         return sub_items[0].Font;
187
188                                 if (owner != null)
189                                         return owner.Font;
190
191                                 return ThemeEngine.Current.DefaultFont;
192                         }
193                         set {   
194                                 if (sub_items[0].Font == value)
195                                         return;
196
197                                 sub_items[0].Font = value; 
198
199                                 if (owner != null)
200                                         Layout ();
201                                 Invalidate ();
202                         }
203                 }
204
205                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
206                 public Color ForeColor {
207                         get {
208                                 if (sub_items.Count > 0)
209                                         return sub_items[0].ForeColor;
210
211                                 if (owner != null)
212                                         return owner.ForeColor;
213
214                                 return ThemeEngine.Current.ColorWindowText;
215                         }
216                         set { sub_items[0].ForeColor = value; }
217                 }
218
219                 [DefaultValue (-1)]
220                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
221                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
222                          typeof (System.Drawing.Design.UITypeEditor))]
223                 [Localizable (true)]
224                 [TypeConverter (typeof (ImageIndexConverter))]
225                 public int ImageIndex {
226                         get { return image_index; }
227                         set {
228                                 if (value < -1)
229                                         throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
230                                 
231                                 image_index = value;
232
233                                 if (owner != null)
234                                         Layout ();
235                                 Invalidate ();
236                         }
237                 }
238
239                 [Browsable (false)]
240                 public ImageList ImageList {
241                         get {
242                                 if (owner == null)
243                                         return null;
244                                 else if (owner.View == View.LargeIcon)
245                                         return owner.large_image_list;
246                                 else
247                                         return owner.small_image_list;
248                         }
249                 }
250
251                 [Browsable (false)]
252                 public int Index {
253                         get {
254                                 if (owner == null)
255                                         return -1;
256                                 else
257                                         return owner.Items.IndexOf (this);
258                         }
259                 }
260
261                 [Browsable (false)]
262                 public ListView ListView {
263                         get { return owner; }
264                 }
265
266                 [Browsable (false)]
267                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
268                 public bool Selected {
269                         get { return selected; }
270                         set {
271                                 if (selected == value)
272                                         return;
273
274                                 selected = value;
275
276                                 if (owner != null) {
277                                         owner.UpdateSelection (this);
278                                         Layout ();
279                                 }
280                                 Invalidate ();
281                         }
282                 }
283
284                 [DefaultValue (-1)]
285                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
286                          typeof (System.Drawing.Design.UITypeEditor))]
287                 [Localizable (true)]
288                 [TypeConverter (typeof (ImageIndexConverter))]
289                 public int StateImageIndex {
290                         get { return state_image_index; }
291                         set {
292                                 if (value < -1 || value > 14)
293                                         throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
294
295                                 state_image_index = value;
296                         }
297                 }
298
299                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300                 public ListViewSubItemCollection SubItems {
301                         get { return sub_items; }
302                 }
303
304                 [Bindable (true)]
305                 [DefaultValue (null)]
306                 [Localizable (false)]
307                 [TypeConverter (typeof (StringConverter))]
308                 public object Tag {
309                         get { return tag; }
310                         set { tag = value; }
311                 }
312
313                 [Localizable (true)]
314                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
315                 public string Text {
316                         get {
317                                 if (this.sub_items.Count > 0)
318                                         return this.sub_items [0].Text;
319                                 else
320                                         return "";
321                         }
322                         set { 
323                                 if (sub_items [0].Text == value)
324                                         return;
325
326                                 sub_items [0].Text = value; 
327
328                                 if (owner != null)
329                                         Layout ();
330                                 Invalidate ();
331                         }
332                 }
333
334                 [DefaultValue (true)]
335                 public bool UseItemStyleForSubItems {
336                         get { return use_item_style; }
337                         set { use_item_style = value; }
338                 }
339                 #endregion      // Public Instance Properties
340
341                 #region Public Instance Methods
342                 public void BeginEdit ()
343                 {
344                         // FIXME: TODO
345                         // if (owner != null && owner.LabelEdit 
346                         //    && owner.Activation == ItemActivation.Standard)
347                         // allow editing
348                         // else
349                         // throw new InvalidOperationException ();
350                 }
351
352                 public virtual object Clone ()
353                 {
354                         ListViewItem clone = new ListViewItem ();
355                         clone.image_index = this.image_index;
356                         clone.is_checked = this.is_checked;
357                         clone.is_focused = this.is_focused;
358                         clone.selected = this.selected;
359                         clone.state_image_index = this.state_image_index;
360                         clone.sub_items = new ListViewSubItemCollection (this);
361                         
362                         foreach (ListViewSubItem subItem in this.sub_items)
363                                 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
364                                                      subItem.BackColor, subItem.Font);
365                         clone.tag = this.tag;
366                         clone.use_item_style = this.use_item_style;
367                         clone.owner = null;
368
369                         return clone;
370                 }
371
372                 public virtual void EnsureVisible ()
373                 {
374                         if (this.owner != null) {
375                                 owner.EnsureVisible (owner.Items.IndexOf (this));
376                         }
377                 }
378
379                 public Rectangle GetBounds (ItemBoundsPortion portion)
380                 {
381                         if (owner == null)
382                                 return Rectangle.Empty;
383                                 
384                         Rectangle rect;
385
386                         switch (portion) {
387                         case ItemBoundsPortion.Icon:
388                                 rect = icon_rect;
389                                 break;
390
391                         case ItemBoundsPortion.Label:
392                                 rect = label_rect;
393                                 break;
394
395                         case ItemBoundsPortion.ItemOnly:
396                                 rect = item_rect;
397                                 break;
398
399                         case ItemBoundsPortion.Entire:
400                                 rect = bounds;
401                                 rect.X -= owner.h_marker;
402                                 rect.Y -= owner.v_marker;
403                                 return rect;                            
404
405                         default:
406                                 throw new ArgumentException ("Invalid value for portion.");
407                         }
408
409                         rect.X += bounds.X - owner.h_marker;
410                         rect.Y += bounds.Y - owner.v_marker;
411                         return rect;
412                 }
413
414                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
415                 {
416                         // FIXME: TODO
417                 }
418
419                 public virtual void Remove ()
420                 {
421                         if (owner != null)
422                                 owner.Items.Remove (this);
423                         owner = null;
424                 }
425
426                 public override string ToString ()
427                 {
428                         return string.Format ("ListViewItem: {0}", this.Text);
429                 }
430                 #endregion      // Public Instance Methods
431
432                 #region Protected Methods
433                 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
434                 {
435                         // FIXME: TODO
436                 }
437
438                 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
439                 {
440                         // FIXME: TODO
441                 }
442                 #endregion      // Protected Methods
443
444                 #region Private Internal Methods
445                 internal Rectangle CheckRectReal {
446                         get {
447                                 Rectangle rect = checkbox_rect;
448                                 rect.X += bounds.X - owner.h_marker;
449                                 rect.Y += bounds.Y - owner.v_marker;
450                                 return rect;
451                         }
452                 }
453                 
454                 Rectangle CheckRect {
455                         get { return this.checkbox_rect; }
456                 }
457
458                 Rectangle IconRect {
459                         get { return this.icon_rect; }
460                 }
461
462                 Rectangle LabelRect {
463                         get { return this.label_rect; }
464                 }
465
466                 internal Point Location {
467                         set {
468                                 if (bounds.X == value.X && bounds.Y == value.Y)
469                                         return;
470
471                                 Rectangle prev = Bounds;
472                                 bounds.X = value.X;
473                                 bounds.Y = value.Y;
474                                 if (owner != null) {
475                                         if (prev != Rectangle.Empty)
476                                                 owner.Invalidate (prev);
477                                         owner.Invalidate (Bounds);
478                                 }
479                         }
480                 }
481
482                 internal ListView Owner {
483                         set {
484                                 if (owner == value)
485                                         return;
486
487                                 owner = value;
488                                 if (owner != null)
489                                         Layout ();
490                                 Invalidate ();
491                         }
492                 }
493
494                 private void Invalidate ()
495                 {
496                         if (owner == null)
497                                 return;
498
499                         owner.Invalidate (Bounds);
500                 }
501
502                 internal void Layout ()
503                 {
504                         int item_ht;
505                         Rectangle total;
506                         Size text_size = owner.text_size;
507                         
508                         checkbox_rect = Rectangle.Empty;
509                         if (owner.CheckBoxes)
510                                 checkbox_rect.Size = owner.CheckBoxSize;
511
512                         switch (owner.View) {
513                         case View.Details:
514                                 // LAMESPEC: MSDN says, "In all views except the details
515                                 // view of the ListView, this value specifies the same
516                                 // bounding rectangle as the Entire value." Actually, it
517                                 // returns same bounding rectangles for Item and Entire
518                                 // values in the case of Details view.
519
520                                 icon_rect = label_rect = Rectangle.Empty;
521                                 icon_rect.X = checkbox_rect.Width + 2;
522                                 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
523
524                                 if (owner.SmallImageList != null) {
525                                         item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
526                                         icon_rect.Width = owner.SmallImageList.ImageSize.Width;
527                                 }
528
529                                 label_rect.Height = icon_rect.Height = item_ht;
530                                 checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height - 1;
531
532                                 label_rect.X = icon_rect.Right + 1;
533
534                                 if (owner.Columns.Count > 0)
535                                         label_rect.Width = Math.Max (text_size.Width, owner.Columns[0].Wd);
536                                 else
537                                         label_rect.Width = text_size.Width;
538
539                                 item_rect = total = Rectangle.Union
540                                         (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
541                                 bounds.Size = total.Size;
542
543                                 // Take into account the rest of columns. First column
544                                 // is already taken into account above.
545                                 for (int i = 1; i < owner.Columns.Count; i++) {
546                                         item_rect.Width += owner.Columns [i].Wd;
547                                         bounds.Width += owner.Columns [i].Wd;
548                                 }
549                                 break;
550
551                         case View.LargeIcon:
552                                 label_rect = icon_rect = Rectangle.Empty;
553
554                                 if (owner.LargeImageList != null) {
555                                         icon_rect.Width = owner.LargeImageList.ImageSize.Width;
556                                         icon_rect.Height = owner.LargeImageList.ImageSize.Height;
557                                 }
558
559                                 checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height - 1;
560
561                                 if (text_size.Width <= (checkbox_rect.Width + icon_rect.Width)) {
562                                         icon_rect.X = checkbox_rect.Width + 1;
563                                         label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
564                                         label_rect.Y = Math.Max (checkbox_rect.Bottom, icon_rect.Bottom) + 2;
565                                         label_rect.Size = text_size;
566                                 } else {
567                                         int centerX = text_size.Width / 2;
568                                         icon_rect.X = centerX - icon_rect.Width / 2;
569                                         checkbox_rect.X = (icon_rect.X - checkbox_rect.Width);
570                                         label_rect.Y = Math.Max (checkbox_rect.Bottom, icon_rect.Bottom) + 2;
571                                         label_rect.Size = text_size;
572                                 }
573
574                                 item_rect = Rectangle.Union (icon_rect, label_rect);
575                                 total = Rectangle.Union (item_rect, checkbox_rect);
576                                 bounds.Size = total.Size;
577                                 break;
578
579                         case View.List:
580                         case View.SmallIcon:
581                                 label_rect = icon_rect = Rectangle.Empty;
582                                 icon_rect.X = checkbox_rect.Width + 1;
583                                 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
584
585                                 if (owner.SmallImageList != null) {
586                                         item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
587                                         icon_rect.Width = owner.SmallImageList.ImageSize.Width;
588                                         icon_rect.Height = owner.SmallImageList.ImageSize.Height;
589                                 }
590
591                                 checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height + 1;
592                                 label_rect.X = icon_rect.Right + 1;
593                                 label_rect.Width = text_size.Width;
594                                 label_rect.Height = icon_rect.Height = item_ht;
595
596                                 item_rect = Rectangle.Union (icon_rect, label_rect);
597                                 total = Rectangle.Union (item_rect, checkbox_rect);
598                                 bounds.Size = total.Size;
599                                 break;
600                         }
601                         
602                 }
603                 #endregion      // Private Internal Methods
604
605                 #region Subclasses
606
607                 [DefaultProperty ("Text")]
608                 [DesignTimeVisible (false)]
609                 [Serializable]
610                 [ToolboxItem (false)]
611                 [TypeConverter (typeof(ListViewSubItemConverter))]
612                 public class ListViewSubItem
613                 {
614                         private Color back_color;
615                         private Font font;
616                         private Color fore_color;
617                         internal ListViewItem owner;
618                         private string text;
619                         
620                         #region Public Constructors
621                         public ListViewSubItem ()
622                         {
623                         }
624
625                         public ListViewSubItem (ListViewItem owner, string text)
626                                 : this (owner, text, ThemeEngine.Current.ColorWindowText,
627                                         ThemeEngine.Current.ColorWindow,
628                                         ThemeEngine.Current.DefaultFont)
629                         {
630                         }
631
632                         public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
633                                                 Color backColor, Font font)
634                         {
635                                 this.owner = owner;
636                                 this.text = text;
637                                 this.fore_color = foreColor;
638                                 this.back_color = backColor;
639                                 this.font = font;
640                         }
641                         #endregion // Public Constructors
642
643                         #region Public Instance Properties
644                         public Color BackColor {
645                                 get { return back_color; }
646                                 set { 
647                                         back_color = value; 
648                                         Invalidate ();
649                                     }
650                         }
651
652                         [Localizable (true)]
653                         public Font Font {
654                                 get {
655                                         if (font != null)
656                                                 return font;
657                                         else if (owner != null)
658                                                 return owner.Font;
659                                         return font;
660                                 }
661                                 set { 
662                                         font = value; 
663                                         Invalidate ();
664                                     }
665                         }
666
667                         public Color ForeColor {
668                                 get { return fore_color; }
669                                 set { 
670                                         fore_color = value; 
671                                         Invalidate ();
672                                     }
673                         }
674
675                         [Localizable (true)]
676                         public string Text {
677                                 get { return text; }
678                                 set { 
679                                         text = value; 
680                                         Invalidate ();
681                                     }
682                         }
683                         #endregion // Public Instance Properties
684
685                         #region Public Methods
686                         public void ResetStyle ()
687                         {
688                                 font = ThemeEngine.Current.DefaultFont;
689                                 back_color = ThemeEngine.Current.DefaultControlBackColor;
690                                 fore_color = ThemeEngine.Current.DefaultControlForeColor;
691                                 Invalidate ();
692                         }
693
694                         public override string ToString ()
695                         {
696                                 return string.Format ("ListViewSubItem {{0}}", text);
697                         }
698                         #endregion // Public Methods
699
700                         
701                         #region Private Methods
702                         private void Invalidate ()
703                         {
704                                 if (owner == null || owner.owner == null)
705                                         return;
706
707                                 owner.owner.Invalidate ();
708                         }
709                         #endregion // Private Methods
710                 }
711
712                 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
713                 {
714                         private ArrayList list;
715                         internal ListViewItem owner;
716
717                         #region Public Constructors
718                         public ListViewSubItemCollection (ListViewItem owner)
719                         {
720                                 this.owner = owner;
721                                 this.list = new ArrayList ();
722                         }
723                         #endregion // Public Constructors
724
725                         #region Public Properties
726                         [Browsable (false)]
727                         public virtual int Count {
728                                 get { return list.Count; }
729                         }
730
731                         public virtual bool IsReadOnly {
732                                 get { return false; }
733                         }
734
735                         public ListViewSubItem this [int index] {
736                                 get { return (ListViewSubItem) list [index]; }
737                                 set { 
738                                         value.owner = this.owner;
739                                         list [index] = value;
740                                 }
741                         }
742
743                         bool ICollection.IsSynchronized {
744                                 get { return list.IsSynchronized; }
745                         }
746
747                         object ICollection.SyncRoot {
748                                 get { return list.SyncRoot; }
749                         }
750
751                         bool IList.IsFixedSize {
752                                 get { return list.IsFixedSize; }
753                         }
754
755                         object IList.this [int index] {
756                                 get { return this [index]; }
757                                 set {
758                                         if (! (value is ListViewSubItem))
759                                                 throw new ArgumentException ("Not of type ListViewSubItem", "value");
760                                         this [index] = (ListViewSubItem) value;
761                                 }
762                         }
763                         #endregion // Public Properties
764
765                         #region Public Methods
766                         public ListViewSubItem Add (ListViewSubItem item)
767                         {
768                                 item.owner = this.owner;
769                                 list.Add (item);
770                                 return item;
771                         }
772
773                         public ListViewSubItem Add (string text)
774                         {
775                                 ListViewSubItem item = new ListViewSubItem (this.owner, text);
776                                 list.Add (item);
777                                 return item;
778                         }
779
780                         public ListViewSubItem Add (string text, Color foreColor,
781                                                     Color backColor, Font font)
782                         {
783                                 ListViewSubItem item = new ListViewSubItem (this.owner, text,
784                                                                             foreColor, backColor, font);
785                                 list.Add (item);
786                                 return item;
787                         }
788
789                         public void AddRange (ListViewSubItem [] items)
790                         {
791                                 this.Clear ();
792                                 foreach (ListViewSubItem item in items)
793                                         this.Add (item);
794                         }
795
796                         public void AddRange (string [] items)
797                         {
798                                 this.Clear ();
799                                 foreach (string item in items)
800                                         this.Add (item);
801                         }
802
803                         public void AddRange (string [] items, Color foreColor,
804                                               Color backColor, Font font)
805                         {
806                                 this.Clear ();
807                                 foreach (string item in items)
808                                         this.Add (item, foreColor, backColor, font);
809                         }
810
811                         public virtual void Clear ()
812                         {
813                                 list.Clear ();
814                         }
815
816                         public bool Contains (ListViewSubItem item)
817                         {
818                                 return list.Contains (item);
819                         }
820
821                         public virtual IEnumerator GetEnumerator ()
822                         {
823                                 return list.GetEnumerator ();
824                         }
825
826                         void ICollection.CopyTo (Array dest, int index)
827                         {
828                                 list.CopyTo (dest, index);
829                         }
830
831                         int IList.Add (object item)
832                         {
833                                 if (! (item is ListViewSubItem)) {
834                                         throw new ArgumentException ("Not of type ListViewSubItem", "item");
835                                 }
836
837                                 ListViewSubItem sub_item = (ListViewSubItem) item;
838                                 sub_item.owner = this.owner;
839                                 return list.Add (sub_item);
840                         }
841
842                         bool IList.Contains (object subItem)
843                         {
844                                 if (! (subItem is ListViewSubItem)) {
845                                         throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
846                                 }
847
848                                 return this.Contains ((ListViewSubItem) subItem);
849                         }
850
851                         int IList.IndexOf (object subItem)
852                         {
853                                 if (! (subItem is ListViewSubItem)) {
854                                         throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
855                                 }
856
857                                 return this.IndexOf ((ListViewSubItem) subItem);
858                         }
859
860                         void IList.Insert (int index, object item)
861                         {
862                                 if (! (item is ListViewSubItem)) {
863                                         throw new ArgumentException ("Not of type ListViewSubItem", "item");
864                                 }
865
866                                 this.Insert (index, (ListViewSubItem) item);
867                         }
868
869                         void IList.Remove (object item)
870                         {
871                                 if (! (item is ListViewSubItem)) {
872                                         throw new ArgumentException ("Not of type ListViewSubItem", "item");
873                                 }
874
875                                 this.Remove ((ListViewSubItem) item);
876                         }
877
878                         public int IndexOf (ListViewSubItem subItem)
879                         {
880                                 return list.IndexOf (subItem);
881                         }
882
883                         public void Insert (int index, ListViewSubItem item)
884                         {
885                                 item.owner = this.owner;
886                                 list.Insert (index, item);
887                         }
888
889                         public void Remove (ListViewSubItem item)
890                         {
891                                 list.Remove (item);
892                         }
893
894                         public virtual void RemoveAt (int index)
895                         {
896                                 list.RemoveAt (index);
897                         }
898                         #endregion // Public Methods
899                 }
900                 #endregion // Subclasses
901         }
902 }