* X11Keyboard.cs: Detect and use the num lock mask.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListView.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 //   - Keys to be handled ENTER/PAGE UP/PAGE DOWN/HOME/END/ARROWS/CTRL/SHIFT
27 //   - Item text editing
28 //   - Column resizing/reodering
29 //   - Feedback for item activation, change in cursor types as mouse moves.
30 //   - HideSelection
31 //
32 // $Revision: 1.9 $
33 // $Modtime: $
34 // $Log: ListView.cs,v $
35 // Revision 1.9  2004/11/05 14:00:50  ravindra
36 // Implemented some methods and fixed scrolling.
37 //
38 // Revision 1.8  2004/11/04 11:29:38  ravindra
39 //      - Changed default value signatures (prefixed all with ListView).
40 //      - Fixed/implemented layout LargeIcon, SmallIcon and List views for ListView.
41 //      - Fixed calculations for ListViewItem and implemented Clone() method.
42 //
43 // Revision 1.7  2004/10/30 10:21:14  ravindra
44 // Added support for scrolling and fixed calculations.
45 //
46 // Revision 1.6  2004/10/26 19:51:20  jordi
47 // removes warning
48 //
49 // Revision 1.5  2004/10/26 09:55:48  ravindra
50 // Some formatting for my last checkins.
51 //
52 // Revision 1.4  2004/10/26 09:31:35  ravindra
53 // Added some internal members and calculations for ListView.
54 //
55 // Revision 1.3  2004/10/15 15:03:39  ravindra
56 // Implemented Paint method and fixed coding style.
57 //
58 // Revision 1.2  2004/10/02 11:32:01  ravindra
59 // Added attributes.
60 //
61 // Revision 1.1  2004/09/30 13:24:25  ravindra
62 // Initial implementation.
63 //
64 //
65 // NOT COMPLETE
66 //
67
68 using System.Collections;
69 using System.ComponentModel;
70 using System.ComponentModel.Design;
71 using System.Drawing;
72 using System.Runtime.InteropServices;
73
74 namespace System.Windows.Forms
75 {
76         [DefaultEvent ("SelectedIndexChanged")]
77         [DefaultProperty ("Items")]
78         [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design,
79                    typeof (IDesigner))]
80         public class ListView : Control
81         {
82                 private ItemActivation activation = ItemActivation.Standard;
83                 private ListViewAlignment alignment = ListViewAlignment.Top;
84                 private bool allow_column_reorder = false;
85                 private bool auto_arrange = true;
86                 private BorderStyle border_style = BorderStyle.Fixed3D;
87                 private bool check_boxes = false;
88                 private CheckedIndexCollection checked_indices;
89                 private CheckedListViewItemCollection checked_items;
90                 private ColumnHeader clicked_column;
91                 private ListViewItem clicked_item;
92                 private ListViewItem last_clicked_item;
93                 private ColumnHeaderCollection columns;
94                 private bool ctrl_pressed;
95                 private bool shift_pressed;
96                 private bool draw_headers = true; // Used for painting. Do we need to draw column headers ?
97                 private ListViewItem focused_item;
98                 private bool full_row_select = false;
99                 private bool grid_lines = false;
100                 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
101                 private bool hide_selection = true;
102                 private bool hover_selection = false;
103                 private IComparer item_sorter;
104                 private ListViewItemCollection items;
105                 private bool label_edit = false;
106                 private bool label_wrap = true;
107                 private bool multiselect = true;
108                 private bool redraw = true;
109                 private bool scrollable = true;
110                 private SelectedIndexCollection selected_indices;
111                 private SelectedListViewItemCollection selected_items;
112                 private SortOrder sort_order = SortOrder.None;
113                 private ImageList state_image_list;
114                 private bool updating = false;
115                 private View view = View.LargeIcon;
116                 private int layout_wd;    // We might draw more than our client area
117                 private int layout_ht;    // therefore we need to have these two.
118                 //private TextBox editor;   // Used for editing an item text
119                 private ScrollBar h_scroll; // used for scrolling horizontally
120                 private ScrollBar v_scroll; // used for scrolling vertically
121                 private int h_marker;           // Position markers for scrolling
122                 private int v_marker;
123
124                 // internal variables
125                 internal ImageList large_image_list;
126                 internal ImageList small_image_list;
127                 internal Size text_size = Size.Empty;
128
129                 #region Events
130                 public event LabelEditEventHandler AfterLabelEdit;
131
132                 [Browsable (false)]
133                 [EditorBrowsable (EditorBrowsableState.Never)]
134                 public new event EventHandler BackgroundImageChanged;
135
136                 public event LabelEditEventHandler BeforeLabelEdit;
137                 public event ColumnClickEventHandler ColumnClick;
138                 public event EventHandler ItemActivate;
139                 public event ItemCheckEventHandler ItemCheck;
140                 public event ItemDragEventHandler ItemDrag;
141
142                 [Browsable (false)]
143                 [EditorBrowsable (EditorBrowsableState.Never)]
144                 public new event PaintEventHandler Paint;
145
146                 public event EventHandler SelectedIndexChanged;
147
148                 [Browsable (false)]
149                 [EditorBrowsable (EditorBrowsableState.Never)]
150                 public new event EventHandler TextChanged;
151                 #endregion // Events
152
153                 #region Public Constructors
154                 public ListView ()
155                 {
156                         background_color = ThemeEngine.Current.ColorWindow;
157                         checked_indices = new CheckedIndexCollection (this);
158                         checked_items = new CheckedListViewItemCollection (this);
159                         columns = new ColumnHeaderCollection (this);
160                         foreground_color = SystemColors.WindowText;
161                         items = new ListViewItemCollection (this);
162                         selected_indices = new SelectedIndexCollection (this);
163                         selected_items = new SelectedListViewItemCollection (this);
164
165                         // we are mostly scrollable
166                         h_scroll = new HScrollBar ();
167                         v_scroll = new VScrollBar ();
168                         h_marker = v_marker = 0;
169
170                         // scroll bars are disabled initially
171                         h_scroll.Visible = false;
172                         h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
173                         v_scroll.Visible = false;
174                         v_scroll.ValueChanged += new EventHandler(VerticalScroller);
175
176                         // event handlers
177                         base.DoubleClick += new EventHandler(ListView_DoubleClick);
178                         base.KeyDown += new KeyEventHandler(ListView_KeyDown);
179                         base.KeyUp += new KeyEventHandler(ListView_KeyUp);
180                         base.MouseDown += new MouseEventHandler(ListView_MouseDown);
181                         base.MouseHover += new EventHandler(ListView_MouseHover);
182                         base.MouseUp += new MouseEventHandler(ListView_MouseUp);
183                         base.MouseMove += new MouseEventHandler(ListView_MouseMove);
184                         base.Paint += new PaintEventHandler (ListView_Paint);
185                 }
186                 #endregion      // Public Constructors
187
188                 #region Private Internal Properties
189                 internal Size CheckBoxSize {
190                         get {
191                                 if (this.check_boxes) {
192                                         if (this.state_image_list != null)
193                                                 return this.state_image_list.ImageSize;
194                                         else
195                                                 return ThemeEngine.Current.ListViewCheckBoxSize;
196                                 }
197                                 return Size.Empty;
198                         }
199                 }
200
201                 internal bool CanMultiselect {
202                         get {
203                                 if (this.multiselect &&
204                                         (this.ctrl_pressed || this.shift_pressed))
205                                         return true;
206                                 else
207                                         return false;
208                         }
209                 }
210                 #endregion      // Private Internal Properties
211
212                 #region  Protected Properties
213                 protected override CreateParams CreateParams {
214                         get { return base.CreateParams; }
215                 }
216
217                 protected override Size DefaultSize {
218                         get { return ThemeEngine.Current.ListViewDefaultSize; }
219                 }
220                 #endregion      // Protected Properties
221
222                 #region Public Instance Properties
223                 [DefaultValue (ItemActivation.Standard)]
224                 public ItemActivation Activation {
225                         get { return activation; }
226                         set { activation = value; }
227                 }
228
229                 [DefaultValue (ListViewAlignment.Top)]
230                 [Localizable (true)]
231                 public ListViewAlignment Alignment {
232                         get { return alignment; }
233                         set {
234                                 if (this.alignment != value) {
235                                         alignment = value;
236                                         // alignment does not matter in Details/List views
237                                         if (this.view == View.LargeIcon ||
238                                             this.View == View.SmallIcon)
239                                                 this.Redraw (true);
240                                 }
241                         }
242                 }
243
244                 [DefaultValue (false)]
245                 public bool AllowColumnReorder {
246                         get { return allow_column_reorder; }
247                         set {
248                                 if (this.allow_column_reorder != value) {
249                                         allow_column_reorder = value;
250                                         // column reorder does not matter in Details view
251                                         if (this.view != View.Details)
252                                                 this.Redraw (true);
253                                 }
254                         }
255                 }
256
257                 [DefaultValue (true)]
258                 public bool AutoArrange {
259                         get { return auto_arrange; }
260                         set {
261                                 if (auto_arrange != value) {
262                                         auto_arrange = value;
263                                         // autoarrange does not matter in Details/List views
264                                         if (this.view == View.LargeIcon || this.View == View.SmallIcon)
265                                                 this.Redraw (true);
266                                 }
267                         }
268                 }
269
270                 public override Color BackColor {
271                         get {
272                                 if (background_color.IsEmpty)
273                                         return ThemeEngine.Current.ColorWindow;
274                                 else
275                                         return background_color;
276                         }
277                         set { background_color = value; }
278                 }
279
280                 [Browsable (false)]
281                 [EditorBrowsable (EditorBrowsableState.Never)]
282                 public override Image BackgroundImage {
283                         get { return background_image; }
284                         set {
285                                 if (value == background_image)
286                                         return;
287
288                                 background_image = value;
289                                 if (BackgroundImageChanged != null)
290                                         BackgroundImageChanged (this, new EventArgs ());
291                         }
292                 }
293
294                 [DefaultValue (BorderStyle.Fixed3D)]
295                 [DispId (-504)]
296                 public BorderStyle BorderStyle {
297                         get { return border_style; }
298                         set {
299                                 if (border_style != value) {
300                                         border_style = value;
301                                         this.Redraw (false);
302                                 }
303                         }
304                 }
305
306                 [DefaultValue (false)]
307                 public bool CheckBoxes {
308                         get { return check_boxes; }
309                         set {
310                                 if (check_boxes != value) {
311                                         check_boxes = value;
312                                         this.Redraw (true);
313                                 }
314                         }
315                 }
316
317                 [Browsable (false)]
318                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
319                 public CheckedIndexCollection CheckedIndices {
320                         get { return checked_indices; }
321                 }
322
323                 [Browsable (false)]
324                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
325                 public CheckedListViewItemCollection CheckedItems {
326                         get { return checked_items; }
327                 }
328
329                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
330                 [Localizable (true)]
331                 [MergableProperty (false)]
332                 public ColumnHeaderCollection Columns {
333                         get { return columns; }
334                 }
335
336                 [Browsable (false)]
337                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
338                 public ListViewItem FocusedItem {
339                         get { return focused_item; }
340                 }
341
342                 public override Color ForeColor {
343                         get {
344                                 if (foreground_color.IsEmpty)
345                                         return ThemeEngine.Current.ColorWindowText;
346                                 else
347                                         return foreground_color;
348                         }
349                         set { foreground_color = value; }
350                 }
351
352                 [DefaultValue (false)]
353                 public bool FullRowSelect {
354                         get { return full_row_select; }
355                         set { full_row_select = value; }
356                 }
357
358                 [DefaultValue (false)]
359                 public bool GridLines {
360                         get { return grid_lines; }
361                         set {
362                                 if (grid_lines != value) {
363                                         grid_lines = value;
364                                         this.Redraw (false);
365                                 }
366                         }
367                 }
368
369                 [DefaultValue (ColumnHeaderStyle.Clickable)]
370                 public ColumnHeaderStyle HeaderStyle {
371                         get { return header_style; }
372                         set {
373                                 if (header_style != value) {
374                                         header_style = value;
375                                         // header style matters only in Details view
376                                         if (this.view == View.Details)
377                                                 this.Redraw (false);
378                                 }
379                         }
380                 }
381
382                 [DefaultValue (true)]
383                 public bool HideSelection {
384                         get { return hide_selection; }
385                         set {
386                                 if (hide_selection != value) {
387                                         hide_selection = value;
388                                         this.Redraw (false);
389                                 }
390                         }
391                 }
392
393                 [DefaultValue (false)]
394                 public bool HoverSelection {
395                         get { return hover_selection; }
396                         set { hover_selection = value; }
397                 }
398
399                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
400                 [Localizable (true)]
401                 [MergableProperty (false)]              
402                 public ListViewItemCollection Items {
403                         get { return items; }
404                 }
405
406                 [DefaultValue (false)]
407                 public bool LabelEdit {
408                         get { return label_edit; }
409                         set { label_edit = value; }
410                 }
411
412                 [DefaultValue (false)]
413                 [Localizable (true)]
414                 public bool LabelWrap {
415                         get { return label_wrap; }
416                         set {
417                                 if (label_wrap != value) {
418                                         label_wrap = value;
419                                         this.Redraw (true);
420                                 }
421                         }
422                 }
423
424                 [DefaultValue (null)]
425                 public ImageList LargeImageList {
426                         get { return large_image_list; }
427                         set {
428                                 large_image_list = value;
429                                 this.Redraw (true);
430                         }
431                 }
432
433                 [Browsable (false)]
434                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
435                 public IComparer ListViewItemSorter {
436                         get { return item_sorter; }
437                         set { item_sorter = value; }
438                 }
439
440                 [DefaultValue (true)]
441                 public bool MultiSelect {
442                         get { return multiselect; }
443                         set { multiselect = value; }
444                 }
445
446                 [DefaultValue (true)]
447                 public bool Scrollable {
448                         get { return scrollable; }
449                         set {
450                                 if (scrollable != value) {
451                                         scrollable = value;
452                                         this.Redraw (true);
453                                 }
454                         }
455                 }
456
457                 [Browsable (false)]
458                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
459                 public SelectedIndexCollection SelectedIndices {
460                         get { return selected_indices; }
461                 }
462
463                 [Browsable (false)]
464                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
465                 public SelectedListViewItemCollection SelectedItems {
466                         get { return selected_items; }
467                 }
468
469                 [DefaultValue (null)]
470                 public ImageList SmallImageList {
471                         get { return small_image_list; }
472                         set {
473                                 small_image_list = value;
474                                 this.Redraw (true);
475                         }
476                 }
477
478                 [DefaultValue (SortOrder.None)]
479                 public SortOrder Sorting {
480                         get { return sort_order; }
481                         set { sort_order = value; }
482                 }
483
484                 [DefaultValue (null)]
485                 public ImageList StateImageList {
486                         get { return state_image_list; }
487                         set {
488                                 state_image_list = value;
489                                 this.Redraw (true);
490                         }
491                 }
492
493                 [Bindable (false)]
494                 [Browsable (false)]
495                 [EditorBrowsable (EditorBrowsableState.Never)]
496                 public override string Text {
497                         get { return text; } 
498                         set {
499                                 if (value == text)
500                                         return;
501
502                                 text = value;
503                                 this.Redraw (true);
504
505                                 if (TextChanged != null)
506                                         TextChanged (this, new EventArgs ());
507                         }
508                 }
509
510                 [Browsable (false)]
511                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
512                 public ListViewItem TopItem {
513                         get {
514                                 // there is no item
515                                 if (this.items.Count == 0)
516                                         return null;
517                                 // if contents are not scrolled
518                                 // it is the first item
519                                 else if (h_marker == 0 && v_marker == 0)
520                                         return this.items [0];
521                                 // do a hit test for the scrolled position
522                                 else {
523                                         foreach (ListViewItem item in this.items) {
524                                                 if (item.EntireRect.Contains (h_marker, v_marker))
525                                                         return item;
526                                         }
527                                         return null;
528                                 }
529                         }
530                 }
531
532                 [DefaultValue (View.LargeIcon)]
533                 public View View {
534                         get { return view; }
535                         set { view = value; }
536                 }
537                 #endregion      // Public Instance Properties
538
539                 #region Internal Methods Properties
540                 internal int TotalWidth {
541                         get { return Math.Max (this.Width, this.layout_wd); }
542                 }
543
544                 internal int TotalHeight {
545                         get { return Math.Max (this.Height, this.layout_ht); }
546                 }
547
548                 internal void Redraw (bool recalculate)
549                 {
550                         // Avoid calculations when control is being updated
551                         if (this.updating)
552                                 return;
553
554                         if (recalculate)
555                                 CalculateListView (this.alignment);
556
557                         redraw = true;
558                         Refresh ();
559                 }
560
561                 internal Size GetChildColumnSize (int index)
562                 {
563                         Size ret_size = Size.Empty;
564                         ColumnHeader col = this.columns [index];
565
566                         if (col.Width == -2) { // autosize = max(items, columnheader)
567                                 Size size = Size.Ceiling (this.DeviceContext.MeasureString
568                                                           (col.Text, this.Font));
569                                 ret_size = BiggestItem (index);
570                                 if (size.Width > ret_size.Width)
571                                         ret_size = size;
572                         }
573                         else { // -1 and all the values < -2 are put under one category
574                                 ret_size = BiggestItem (index);
575                                 // fall back to empty columns' width if no subitem is available for a column
576                                 if (ret_size.IsEmpty) {
577                                         ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
578                                         if (col.Text.Length > 0)
579                                                 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
580                                                                                 (col.Text, this.Font)).Height;
581                                         else
582                                                 ret_size.Height = this.Font.Height;
583                                 }
584                         }
585
586                         // adjust the size for icon and checkbox for 0th column
587                         if (index == 0) {
588                                 ret_size.Width += (this.CheckBoxSize.Width + 4);
589                                 if (this.small_image_list != null)
590                                         ret_size.Width += this.small_image_list.ImageSize.Width;
591                         }
592                         return ret_size;
593                 }
594
595                 // Returns the size of biggest item text in a column.
596                 private Size BiggestItem (int col)
597                 {
598                         Size temp = Size.Empty;
599                         Size ret_size = Size.Empty;
600
601                         // 0th column holds the item text, we check the size of
602                         // the various subitems falling in that column and get
603                         // the biggest one's size.
604                         foreach (ListViewItem item in items) {
605                                 if (col >= item.SubItems.Count)
606                                         continue;
607
608                                 temp = Size.Ceiling (this.DeviceContext.MeasureString
609                                                      (item.SubItems [col].Text, this.Font));
610                                 if (temp.Width > ret_size.Width)
611                                         ret_size = temp;
612                         }
613
614                         // adjustment for space
615                         if (!ret_size.IsEmpty)
616                                 ret_size.Width += 4;
617
618                         return ret_size;
619                 }
620
621                 // Sets the size of the biggest item text as per the view
622                 private void CalcTextSize ()
623                 {                       
624                         // clear the old value
625                         text_size = Size.Empty;
626
627                         if (items.Count == 0)
628                                 return;
629
630                         text_size = BiggestItem (0);
631
632                         if (view == View.LargeIcon && this.label_wrap) {
633                                 Size temp = Size.Empty;
634                                 if (this.check_boxes)
635                                         temp.Width += 2 * this.CheckBoxSize.Width;
636                                 if (large_image_list != null)
637                                         temp.Width += large_image_list.ImageSize.Width;
638                                 if (temp.Width == 0)
639                                         temp.Width = 43;
640                                 // wrapping is done for two lines only
641                                 if (text_size.Width > temp.Width) {
642                                         text_size.Width = temp.Width;
643                                         text_size.Height *= 2;
644                                 }
645                         }
646                         else if (view == View.List) {
647                                 // in list view max text shown in determined by the
648                                 // control width, even if scolling is enabled.
649                                 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
650                                 if (this.small_image_list != null)
651                                         max_wd -= this.small_image_list.ImageSize.Width;
652
653                                 if (text_size.Width > max_wd)
654                                         text_size.Width = max_wd;
655                         }
656
657                         // we do the default settings, if we have got 0's
658                         if (text_size.Height <= 0)
659                                 text_size.Height = this.Font.Height;
660                         if (text_size.Width <= 0)
661                                 text_size.Width = this.Width;
662
663                         // little adjustment
664                         text_size.Width += 4;
665                         text_size.Height += 2;
666                 }
667
668                 // Sets the location of every item on
669                 // the ListView as per the view
670                 private void CalculateListView (ListViewAlignment align)
671                 {
672                         int current_pos_x = 0; // our x-position marker
673                         int current_pos_y = 0; // our y-position marker
674                         int item_ht;
675                         int item_wd;
676                         int max;         // max x_pos or y_pos depending on the alignment
677                         int current = 0; // current row or column
678                         int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
679                         int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
680
681                         CalcTextSize ();
682
683                         switch (view) {
684
685                         case View.Details:
686                                 // ColumnHeaders are not drawn if headerstyle is none
687                                 int ht = (this.header_style == ColumnHeaderStyle.None) ? 
688                                         2 : this.Font.Height + 2;
689                                 if (columns.Count > 0) {
690                                         foreach (ColumnHeader col in columns) {
691                                                 col.X = current_pos_x;
692                                                 col.Y = 0;
693                                                 col.CalcColumnHeader ();
694                                                 current_pos_x += col.Wd;
695                                         }
696                                         this.layout_wd = current_pos_x;
697                                 }
698                                 // set the position marker for placing items
699                                 // vertically down
700                                 current_pos_y = ht;
701
702                                 if (items.Count > 0) {
703                                         foreach (ListViewItem item in items) {
704                                                 item.location.X = 0;
705                                                 item.location.Y = current_pos_y;
706                                                 item.CalcListViewItem ();
707                                                 current_pos_y += item.EntireRect.Height;
708                                         }
709                                         this.layout_ht = current_pos_y;
710
711                                         // some space for bottom gridline
712                                         if (this.grid_lines)
713                                                 this.layout_ht += 2;
714                                 }
715                                 break;
716
717                         case View.SmallIcon:
718                                 vertical_spacing = 0;
719                                 horizontal_spacing = 0;
720                                 goto case View.LargeIcon;
721
722                         case View.LargeIcon:
723                                 if (items.Count > 0) {
724                                         items [0].CalcListViewItem ();
725                                         item_ht = items [0].EntireRect.Height;
726                                         item_wd = items [0].EntireRect.Width;
727
728                                         // top (default) and snaptogrid alignments are handled same way
729                                         if (align == ListViewAlignment.Left) {
730                                                 max = this.Height;
731                                                 foreach (ListViewItem item in items) {
732                                                         item.location.X = current_pos_x +
733                                                                 horizontal_spacing;
734                                                         item.location.Y = current_pos_y;
735                                                         item.CalcListViewItem ();
736                                                         current_pos_y += item_ht;
737
738                                                         current ++; // just to know about the last element
739                                                         // we just did the last item
740                                                         if (current == items.Count) {
741                                                                 if (max < current_pos_y)
742                                                                         max = current_pos_y;
743                                                                 current_pos_x = item.EntireRect.Right;
744                                                                 break;
745                                                         }
746                                                         else {
747                                                                 // is there enough space for another row ?
748                                                                 if ((current_pos_y + vertical_spacing
749                                                                      + item_ht) <= this.Height)
750                                                                         current_pos_y += vertical_spacing;
751                                                                 else {
752                                                                         // start another column
753                                                                         // make current_pos_y as the
754                                                                         // max value and reset
755                                                                         // current_pos_y value.
756                                                                         max = current_pos_y;
757                                                                         current_pos_x += item_wd;
758                                                                         current_pos_y = 0;
759                                                                 }
760                                                         }
761                                                 }
762                                                 // adjust the layout dimensions
763                                                 this.layout_ht = max;
764                                                 this.layout_wd = current_pos_x;
765                                         }
766                                         else { // other default/top alignment
767                                                 max = this.Width;
768                                                 foreach (ListViewItem item in items) {
769                                                         item.location.X = current_pos_x +
770                                                                 horizontal_spacing;
771
772                                                         item.location.Y = current_pos_y;
773                                                         item.CalcListViewItem ();
774                                                         current_pos_x += item_wd;
775
776                                                         current ++; // just to know about the last element
777                                                         // we just did the last item
778                                                         if (current == items.Count) {
779                                                                 if (max < current_pos_x)
780                                                                         max = current_pos_x;
781                                                                 current_pos_y = item.EntireRect.Bottom;
782                                                                 break;
783                                                         }
784                                                         else {
785                                                                 // is there enough space for another column?
786                                                                 if ((current_pos_x + horizontal_spacing
787                                                                      + item_wd) <= this.Width)
788                                                                         continue;
789                                                                 else {
790                                                                         // start another row
791                                                                         // make current_pos_x as the
792                                                                         // max value and reset
793                                                                         // current_pos_x value.
794                                                                         max = current_pos_x;
795                                                                         current_pos_y += (item_ht +
796                                                                                           vertical_spacing);
797                                                                         current_pos_x = 0;
798                                                                 }
799                                                         }
800                                                 }
801                                                 // adjust the layout dimensions
802                                                 this.layout_wd = max;
803                                                 this.layout_ht = current_pos_y;
804                                         }
805                                 }
806                                 break;
807
808                         case View.List:
809                                 if (items.Count > 0) {
810                                         items [0].CalcListViewItem ();
811                                         item_ht = items [0].EntireRect.Height;
812                                         item_wd = items [0].EntireRect.Width;
813
814                                         max = this.Height / item_ht;
815                                         if (max == 0)
816                                                 max = 1; // we draw at least one row
817
818                                         foreach (ListViewItem item in items) {
819                                                 item.location.X = current_pos_x;
820                                                 item.location.Y = current_pos_y;
821                                                 item.CalcListViewItem ();
822                                                 current ++;
823                                                 if (current == max) {
824                                                         current_pos_x += item_wd;
825                                                         current_pos_y = 0;
826                                                         current = 0;
827                                                 }
828                                                 else
829                                                         current_pos_y += item_ht;
830                                         }
831
832                                         // adjust the layout dimensions
833                                         this.layout_ht = max * item_ht;
834                                         if (current == 0) // we have fully filled layout
835                                                 this.layout_wd = current_pos_x;
836                                         else
837                                                 this.layout_wd = current_pos_x + item_wd;
838                                 }
839                                 break;
840                         }
841
842                         if (this.scrollable && this.items.Count > 0) {
843                                 // making a scroll bar visible might make
844                                 // other scroll bar visible
845                                 if (this.layout_wd > this.Width) {
846                                         this.h_scroll.Visible = true;
847                                         if ((this.layout_ht + this.h_scroll.Height) > this.Height)
848                                                 this.v_scroll.Visible = true;
849                                 }
850                                 else if (this.layout_ht > this.Height) {
851                                         this.v_scroll.Visible = true;
852                                         if ((this.layout_wd + this.v_scroll.Width) > this.Width)
853                                                 this.h_scroll.Visible = true;
854                                 }
855
856                                 // create big enough buffers
857                                 if (this.layout_wd > this.Width ||
858                                     this.layout_ht > this.Height)
859                                         this.CreateBuffers (this.TotalWidth, this.TotalHeight);
860
861                                 if (this.h_scroll.Visible) {
862                                         this.h_scroll.Location = new Point (0, this.Height 
863                                                                             - this.h_scroll.Height);
864                                         
865                                         this.h_scroll.Minimum = 0;
866
867                                         // if v_scroll is visible, adjust the maximum of the
868                                         // h_scroll to account for the width of v_scroll
869                                         if (this.v_scroll.Visible) {
870                                                 this.h_scroll.Maximum = this.layout_wd + this.v_scroll.Width;
871                                                 this.h_scroll.Width = this.Width - this.v_scroll.Width;
872                                         }
873                                         else {
874                                                 this.h_scroll.Maximum = this.layout_wd;
875                                                 this.h_scroll.Width = this.Width;
876                                         }
877    
878                                         this.h_scroll.LargeChange = this.Width;
879                                         this.h_scroll.SmallChange = this.Font.Height;
880                                 }
881
882                                 // vertical scrollbar
883                                 if (this.v_scroll.Visible) {
884                                         this.v_scroll.Location = new Point (this.Width 
885                                                                             - this.v_scroll.Width, 0);
886
887                                         this.v_scroll.Minimum = 0;
888
889                                         // if h_scroll is visible, adjust the maximum of the
890                                         // v_scroll to account for the height of h_scroll
891                                         if (this.h_scroll.Visible) {
892                                                 this.v_scroll.Maximum = this.layout_ht + this.h_scroll.Height;
893                                                 this.v_scroll.Height = this.Height - this.h_scroll.Height;
894                                         }
895                                         else {
896                                                 this.v_scroll.Maximum = this.layout_ht;
897                                                 this.v_scroll.Height = this.Height;
898                                         }
899
900                                         this.v_scroll.LargeChange = this.Height;
901                                         this.v_scroll.SmallChange = this.Font.Height;
902                                 }
903                         }
904                         else {
905                                 this.h_scroll.Visible = false;
906                                 this.v_scroll.Visible = false;
907                         }
908                 }
909
910                 // Event Handlers
911                 private void ListView_DoubleClick (object sender, EventArgs e)
912                 {
913                         if (this.activation == ItemActivation.Standard
914                             && this.ItemActivate != null)
915                                 this.ItemActivate (this, e);
916                 }
917
918                 private void ListView_KeyDown (object sender, KeyEventArgs ke)
919                 {
920                         int index = -1;
921                         if (ke.Handled)
922                                 return;
923
924                         ke.Handled = true;
925
926                         switch (ke.KeyCode) {
927
928                         case Keys.ControlKey:
929                                 this.ctrl_pressed = true;
930                                 break;
931
932                         case Keys.Down:
933                                 // FIXME:TODO
934                                 break;
935
936                         case Keys.End:
937                                 this.v_scroll.Value = this.v_scroll.Maximum;
938                                 break;
939
940                         case Keys.Home:
941                                 this.v_scroll.Value = this.v_scroll.Minimum;
942                                 break;
943
944                         case Keys.Left:
945                                 index = -1;
946                                 if (this.last_clicked_item != null)
947                                         index = this.last_clicked_item.Index;
948                                 else
949                                         break;
950
951                                 if (index > 0)
952                                         index -= 1;
953
954                                 this.last_clicked_item = this.items [index];
955                                 this.last_clicked_item.Selected = true;
956                                 this.EnsureVisible (index);
957                                 break;
958
959                         case Keys.Right:
960                                 if (this.last_clicked_item != null)
961                                         index = this.last_clicked_item.Index + 1;
962                                 else
963                                         index = 1;
964
965                                 if (index == this.items.Count)
966                                         break;
967
968                                 this.last_clicked_item = this.items [index];
969                                 this.last_clicked_item.Selected = true;
970                                 this.EnsureVisible (index);
971                                 break;
972
973                         case Keys.ShiftKey:
974                                 this.shift_pressed = true;
975                                 break;
976
977                         case Keys.Up:
978                                 // FIXME:TODO
979                                 break;
980
981                         default:
982                                 ke.Handled = false;
983                                 break;
984                         }
985                 }
986
987                 private void ListView_KeyUp (object sender, KeyEventArgs ke)
988                 {
989                         if (!ke.Handled) {
990                                 if (ke.KeyCode == Keys.ControlKey)
991                                         this.ctrl_pressed = false;
992
993                                 if (ke.KeyCode == Keys.ShiftKey)
994                                         this.shift_pressed = false;
995                                 ke.Handled = true;
996                         }
997                 }
998
999                 private void ListView_MouseDown (object sender, MouseEventArgs me)
1000                 {
1001                         if (items.Count == 0)
1002                                 return;
1003
1004                         Point hit = Point.Empty;
1005                         if (this.HeaderStyle != ColumnHeaderStyle.None) {
1006                                 // take horizontal scrolling into account
1007                                 hit = new Point (me.X + h_marker, me.Y);
1008
1009                                 // hit test on columns
1010                                 if (this.view == View.Details && this.columns.Count > 0) {
1011                                         foreach (ColumnHeader col in this.columns) {
1012                                                 if (col.Rect.Contains (hit)) {
1013                                                         this.clicked_column = col;
1014                                                         this.Capture = true;
1015                                                         break;
1016                                                 }
1017                                         }
1018
1019                                         if (this.clicked_column != null) {
1020                                                 this.clicked_column.pressed = true;
1021                                                 this.draw_headers = true;
1022                                                 this.Redraw (false);
1023                                                 return;
1024                                         }
1025                                 }
1026                         }
1027
1028                         // hit test on items
1029                         // we need to take scrolling into account
1030                         hit = new Point (me.X + h_marker, me.Y + v_marker);
1031                         foreach (ListViewItem item in this.items) {
1032                                 if (item.CheckRect.Contains (hit)) {
1033                                         CheckState curr_state = item.Checked ?
1034                                                 CheckState.Checked : CheckState.Unchecked;
1035                                         if (item.Checked)
1036                                                 item.Checked = false;
1037                                         else
1038                                                 item.Checked = true;
1039
1040                                         CheckState new_state = item.Checked ?
1041                                                 CheckState.Checked : CheckState.Unchecked;
1042                                         this.Redraw (false);
1043
1044                                         // Raise the ItemCheck event
1045                                         ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1046                                                                                          curr_state,
1047                                                                                          new_state);
1048                                         this.OnItemCheck (ice);
1049                                         break;
1050                                 }
1051
1052                                 if (this.view == View.Details &&
1053                                     this.FullRowSelect == false) {
1054                                         if (item.LabelRect.Contains (hit)) {
1055                                                 this.clicked_item = item;
1056                                                 break;
1057                                         }
1058                                 }
1059                                 else {
1060                                         if (item.EntireRect.Contains (hit)) {
1061                                                 this.clicked_item = item;
1062                                                 break;
1063                                         }
1064                                 }
1065                         }
1066
1067                         if (this.clicked_item != null) {
1068                                 this.clicked_item.Selected = true;
1069                                 // Raise the event
1070                                 this.OnSelectedIndexChanged (new EventArgs ());
1071
1072                                 this.Redraw (false);
1073                         }
1074
1075                         // set the FocusedItem to be the current clicked_item
1076                         this.focused_item = this.clicked_item;
1077                 }
1078
1079                 private void ListView_MouseHover (object sender, EventArgs e)
1080                 {
1081                         // handle the hover events only when the mouse
1082                         // is not captured.
1083                         if (this.hover_selection == false || this.Capture)
1084                                 return;
1085
1086                         // hit test for the items
1087                         Point hit = this.PointToClient (Control.MousePosition);
1088                         ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1089
1090                         if (item != null) {
1091                                 item.Selected = true;
1092                                 // Raise the event
1093                                 this.OnSelectedIndexChanged (new EventArgs ());
1094
1095                                 this.Redraw (false);
1096                         }
1097                 }
1098
1099                 private void ListView_MouseMove (object sender, MouseEventArgs me)
1100                 {
1101                         // Column header is always at the top. It can
1102                         // scroll only horizontally. So, we have to take
1103                         // only horizontal scrolling into account
1104                         Point hit = new Point (me.X + h_marker, me.Y);
1105
1106                         // non-null clicked_col means mouse down has happened
1107                         // on a column
1108                         if (this.clicked_column != null) {
1109                                 if (this.clicked_column.pressed == false &&
1110                                     this.clicked_column.Rect.Contains (hit)) {
1111                                         this.clicked_column.pressed = true;
1112                                         this.draw_headers = true;
1113                                         this.Redraw (false);
1114                                 }
1115                                 else if (this.clicked_column.pressed && 
1116                                          ! this.clicked_column.Rect.Contains (hit)) {
1117                                         this.clicked_column.pressed = false;
1118                                         this.draw_headers = true;
1119                                         this.Redraw (false);
1120                                 }
1121                         }
1122                 }
1123
1124                 private void ListView_MouseUp (object sender, MouseEventArgs me)
1125                 {
1126                         this.Capture = false;
1127                         if (items.Count == 0)
1128                                 return;
1129
1130                         Point hit = new Point (me.X, me.Y);
1131
1132                         if (this.clicked_column != null) {
1133                                 if (this.clicked_column.pressed) {
1134                                         this.clicked_column.pressed = false;
1135                                         this.draw_headers = true;
1136                                         this.Redraw (false);
1137
1138                                         // Raise the ColumnClick event
1139                                         this.OnColumnClick (new ColumnClickEventArgs
1140                                                             (this.clicked_column.Index));
1141                                 }
1142                         }
1143
1144                         // Raise the ItemActivate event
1145                         Rectangle rect = Rectangle.Empty;
1146                         if (this.clicked_item != null) {
1147                                 if (this.view == View.Details && !this.full_row_select)
1148                                         rect = this.clicked_item.LabelRect;
1149                                 else
1150                                         rect = this.clicked_item.EntireRect;
1151
1152                                 // We handle double click in a separate handler
1153                                 if (this.activation != ItemActivation.Standard &&
1154                                     rect.Contains (hit)) {
1155                                         if (this.activation == ItemActivation.OneClick)
1156                                                 this.ItemActivate (this, EventArgs.Empty);
1157
1158                                         // ItemActivate is raised on the second click on the same item
1159                                         else if (this.activation == ItemActivation.TwoClick) {
1160                                                 if (this.last_clicked_item == this.clicked_item) {
1161                                                         this.ItemActivate (this, EventArgs.Empty);
1162                                                         this.last_clicked_item = null;
1163                                                 }
1164                                                 else
1165                                                         this.last_clicked_item = this.clicked_item;
1166                                         }
1167                                 }
1168                         }
1169
1170                         this.clicked_column = null;
1171                         this.clicked_item = null;
1172                 }
1173
1174                 private void ListView_Paint (object sender, PaintEventArgs pe)
1175                 {
1176                         if (this.Width <= 0 || this.Height <=  0 ||
1177                             this.Visible == false || this.updating == true)
1178                                 return;
1179
1180                         if (redraw) {
1181                                 ThemeEngine.Current.DrawListView (this.DeviceContext,
1182                                                                   pe.ClipRectangle, this);
1183                                 redraw = false;
1184                         }
1185
1186                         // We paint on the screen as per the location set
1187                         // by the two scrollbars. In case of details view
1188                         // since column headers can scroll only horizontally
1189                         // and items can scroll in both directions, paiting is
1190                         // done separtely for the column header and the items.
1191
1192                         Rectangle srcRect = this.ClientRectangle;
1193                         Rectangle dstRect = this.ClientRectangle;
1194
1195                         // set the visible starting point
1196                         if (scrollable) {
1197                                 srcRect.X += h_marker;
1198                                 srcRect.Y += v_marker;
1199
1200                                 if (h_scroll.Visible) {
1201                                         srcRect.Height -= h_scroll.Height;
1202                                         dstRect.Height -= h_scroll.Height;
1203                                 }
1204
1205                                 if (v_scroll.Visible) {
1206                                         srcRect.Width -= v_scroll.Width;
1207                                         dstRect.Width -= v_scroll.Width;
1208                                 }
1209                         }
1210
1211                         // We paint the column headers always at the top, in case
1212                         // of vertical scrolling. Therefore, we advance the painting
1213                         // by the amount equal to the column height.
1214                         if (this.view == View.Details &&
1215                             this.Columns.Count > 0 &&
1216                             this.header_style != ColumnHeaderStyle.None &&
1217                             v_marker > 0) {
1218
1219                                 int col_ht = this.Columns [0].Ht;
1220
1221                                 if (this.draw_headers) {
1222                                         this.draw_headers = false;
1223                                         // Move the source rect by the amount of horizontal
1224                                         // scrolling done so far.
1225                                         Rectangle headerSrc = new Rectangle (h_marker, 0,
1226                                                                              srcRect.Width, col_ht);
1227                                         // dest rect is always stable at 0,0
1228                                         Rectangle headerDst = new Rectangle (0, 0, srcRect.Width, col_ht);
1229                                         pe.Graphics.DrawImage (this.ImageBuffer, headerDst,
1230                                                                headerSrc, GraphicsUnit.Pixel);
1231                                 }
1232
1233                                 dstRect.Y += col_ht;
1234                                 srcRect.Y += col_ht;
1235                         }
1236
1237                         // Paint the items
1238                         pe.Graphics.DrawImage (this.ImageBuffer, dstRect,
1239                                                srcRect, GraphicsUnit.Pixel);
1240
1241                         // Draw the border of the list view
1242                         // The border is painted here separately, because
1243                         // our imagebuffer might be scrollable
1244                         ThemeEngine.Current.CPDrawBorderStyle (pe.Graphics,
1245                                                                this.ClientRectangle,
1246                                                                this.BorderStyle);
1247
1248                         // Raise the Paint event
1249                         if (Paint != null)
1250                                 Paint (this, pe);
1251                 }
1252
1253                 private void HorizontalScroller (object sender, EventArgs e)
1254                 {
1255                         // Avoid unnecessary flickering, when button is
1256                         // kept pressed at the end
1257                         if (h_marker != h_scroll.Value) {
1258                                 h_marker = h_scroll.Value;
1259                                 // draw the headers again
1260                                 this.draw_headers = true;
1261                                 this.Refresh ();
1262                         }
1263                 }
1264
1265                 private void VerticalScroller (object sender, EventArgs e)
1266                 {
1267                         // Avoid unnecessary flickering, when button is
1268                         // kept pressed at the end
1269                         if (v_marker != v_scroll.Value) {
1270                                 v_marker = v_scroll.Value;
1271                                 this.Refresh ();
1272                         }
1273                 }
1274                 #endregion      // Internal Methods Properties
1275
1276                 #region Protected Methods
1277                 protected override void CreateHandle ()
1278                 {
1279                         base.CreateHandle ();
1280                 }
1281
1282                 protected override void Dispose (bool disposing)
1283                 {
1284                         // FIXME: TODO
1285                 }
1286
1287                 protected override bool IsInputKey (Keys keyData)
1288                 {
1289                         return base.IsInputKey (keyData);
1290                 }
1291
1292                 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1293                 {
1294                         if (AfterLabelEdit != null)
1295                                 AfterLabelEdit (this, e);
1296                 }
1297
1298                 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1299                 {
1300                         if (BeforeLabelEdit != null)
1301                                 BeforeLabelEdit (this, e);
1302                 }
1303
1304                 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1305                 {
1306                         if (ColumnClick != null)
1307                                 ColumnClick (this, e);
1308                 }
1309
1310                 protected override void OnEnabledChanged (EventArgs e)
1311                 {
1312                         base.OnEnabledChanged (e);
1313                 }
1314
1315                 protected override void OnFontChanged (EventArgs e)
1316                 {
1317                         base.OnFontChanged (e);
1318                 }
1319
1320                 protected override void OnHandleCreated (EventArgs e)
1321                 {
1322                         base.OnHandleCreated (e);
1323                         this.Controls.Add (this.v_scroll);
1324                         this.Controls.Add (this.h_scroll);
1325                         this.SetStyle (ControlStyles.UserPaint |
1326                                        ControlStyles.AllPaintingInWmPaint, true);
1327                 }
1328
1329                 protected override void OnHandleDestroyed (EventArgs e)
1330                 {
1331                         base.OnHandleDestroyed (e);
1332                 }
1333
1334                 protected virtual void OnItemActivate (EventArgs e)
1335                 {
1336                         if (ItemActivate != null)
1337                                 ItemActivate (this, e);
1338                 }
1339
1340                 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1341                 {
1342                         if (ItemCheck != null)
1343                                 ItemCheck (this, ice);
1344                 }
1345
1346                 protected virtual void OnItemDrag (ItemDragEventArgs e)
1347                 {
1348                         if (ItemDrag != null)
1349                                 ItemDrag (this, e);
1350                 }
1351
1352                 protected virtual void OnSelectedIndexChanged (EventArgs e)
1353                 {
1354                         if (SelectedIndexChanged != null)
1355                                 SelectedIndexChanged (this, e);
1356                 }
1357
1358                 protected override void OnSystemColorsChanged (EventArgs e)
1359                 {
1360                         base.OnSystemColorsChanged (e);
1361                 }
1362
1363                 protected void RealizeProperties ()
1364                 {
1365                         // FIXME: TODO
1366                 }
1367
1368                 protected void UpdateExtendedStyles ()
1369                 {
1370                         // FIXME: TODO
1371                 }
1372
1373                 protected override void WndProc (ref Message m)
1374                 {
1375                         base.WndProc (ref m);
1376                 }
1377                 #endregion // Protected Methods
1378
1379                 #region Public Instance Methods
1380                 public void ArrangeIcons ()
1381                 {
1382                         ArrangeIcons (this.alignment);
1383                 }
1384
1385                 public void ArrangeIcons (ListViewAlignment alignment)
1386                 {
1387                         // Icons are arranged only if view is set to LargeIcon or SmallIcon
1388                         if (view == View.LargeIcon || view == View.SmallIcon) {
1389                                 this.CalculateListView (alignment);
1390                                 // we have done the calculations already
1391                                 this.Redraw (false);
1392                         }
1393                 }
1394
1395                 public void BeginUpdate ()
1396                 {
1397                         // flag to avoid painting
1398                         updating = true;
1399                 }
1400
1401                 public void Clear ()
1402                 {
1403                         columns.Clear ();
1404                         items.Clear ();
1405                         this.Redraw (true);
1406                 }
1407
1408                 public void EndUpdate ()
1409                 {
1410                         // flag to avoid painting
1411                         updating = false;
1412
1413                         // probably, now we need a redraw with recalculations
1414                         this.Redraw (true);
1415                 }
1416
1417                 public void EnsureVisible (int index)
1418                 {
1419                         if (index < 0 || index >= this.items.Count || this.scrollable == false)
1420                                 return;
1421
1422                         // dimensions of visible area
1423                         int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1424                         int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1425                         // visible area is decided by the h_marker and v_marker
1426                         Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1427
1428                         // an item's bounding rect
1429                         Rectangle rect = this.items [index].EntireRect;
1430
1431                         // we don't need to do anything if item is visible.
1432                         // visible area is represented by (0,0,view_wd,view_ht)
1433                         if (view_rect.Contains (rect))
1434                                 return;
1435
1436                         // Scroll Left or Up
1437                         if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1438                                 if (rect.Left < view_rect.Left)
1439                                         this.h_scroll.Value -= (view_rect.Left - rect.Left);
1440                                 if (rect.Top < view_rect.Top)
1441                                         this.v_scroll.Value -= (view_rect.Top - rect.Top);
1442                         }
1443                         // Scroll Right or Down
1444                         else {
1445                                 if (rect.Right > view_rect.Right)
1446                                         this.h_scroll.Value += (rect.Right - view_rect.Right);
1447                                 if (rect.Bottom > view_rect.Bottom)
1448                                         this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1449                         }
1450                 }
1451                 
1452                 public ListViewItem GetItemAt (int x, int y)
1453                 {
1454                         foreach (ListViewItem item in items) {
1455                                 if (item.Bounds.Contains (x, y))
1456                                         return item;
1457                         }
1458                         return null;
1459                 }
1460
1461                 public Rectangle GetItemRect (int index)
1462                 {
1463                         return GetItemRect (index, ItemBoundsPortion.Entire);
1464                 }
1465
1466                 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1467                 {
1468                         if (index < 0 || index >= items.Count)
1469                                 throw new IndexOutOfRangeException ("Invalid Index");
1470
1471                         return items [index].GetBounds (portion);
1472                 }
1473
1474                 public void Sort ()
1475                 {
1476                         if (sort_order != SortOrder.None)
1477                                 items.list.Sort (item_sorter);
1478
1479                         if (sort_order == SortOrder.Descending)
1480                                 items.list.Reverse ();
1481
1482                         this.Redraw (true);
1483                 }
1484
1485                 public override string ToString ()
1486                 {
1487                         int count = this.Items.Count;
1488
1489                         if (count == 0)
1490                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1491                         else
1492                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1493                 }
1494                 #endregion      // Public Instance Methods
1495
1496
1497                 #region Subclasses
1498                 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1499                 {
1500                         internal ArrayList list;
1501                         private ListView owner;
1502
1503                         #region Public Constructor
1504                         public CheckedIndexCollection (ListView owner)
1505                         {
1506                                 list = new ArrayList ();
1507                                 this.owner = owner;
1508                         }
1509                         #endregion      // Public Constructor
1510
1511                         #region Public Properties
1512                         [Browsable (false)]
1513                         public virtual int Count {
1514                                 get { return list.Count; }
1515                         }
1516
1517                         public virtual bool IsReadOnly {
1518                                 get { return true; }
1519                         }
1520
1521                         public int this [int index] {
1522                                 get {
1523                                         if (index < 0 || index >= list.Count)
1524                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1525                                         return (int) list [index];
1526                                 }
1527                         }
1528
1529                         bool ICollection.IsSynchronized {
1530                                 get { return list.IsSynchronized; }
1531                         }
1532
1533                         object ICollection.SyncRoot {
1534                                 get { return list.SyncRoot; }
1535                         }
1536
1537                         bool IList.IsFixedSize {
1538                                 get { return list.IsFixedSize; }
1539                         }
1540
1541                         object IList.this [int index] {
1542                                 get { return this [index]; }
1543                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1544                         }
1545                         #endregion      // Public Properties
1546
1547                         #region Public Methods
1548                         public bool Contains (int checkedIndex)
1549                         {
1550                                 return list.Contains (checkedIndex);
1551                         }
1552
1553                         public virtual IEnumerator GetEnumerator ()
1554                         {
1555                                 return list.GetEnumerator ();
1556                         }
1557
1558                         void ICollection.CopyTo (Array dest, int index)
1559                         {
1560                                 list.CopyTo (dest, index);
1561                         }
1562
1563                         int IList.Add (object value)
1564                         {
1565                                 throw new NotSupportedException ("Add operation is not supported.");
1566                         }
1567
1568                         void IList.Clear ()
1569                         {
1570                                 throw new NotSupportedException ("Clear operation is not supported.");
1571                         }
1572
1573                         bool IList.Contains (object checkedIndex)
1574                         {
1575                                 return list.Contains (checkedIndex);
1576                         }
1577
1578                         int IList.IndexOf (object checkedIndex)
1579                         {
1580                                 return list.IndexOf (checkedIndex);
1581                         }
1582
1583                         void IList.Insert (int index, object value)
1584                         {
1585                                 throw new NotSupportedException ("Insert operation is not supported.");
1586                         }
1587
1588                         void IList.Remove (object value)
1589                         {
1590                                 throw new NotSupportedException ("Remove operation is not supported.");
1591                         }
1592
1593                         void IList.RemoveAt (int index)
1594                         {
1595                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
1596                         }
1597
1598                         public int IndexOf (int checkedIndex)
1599                         {
1600                                 return list.IndexOf (checkedIndex);
1601                         }
1602                         #endregion      // Public Methods
1603
1604                 }       // CheckedIndexCollection
1605
1606                 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1607                 {
1608                         internal ArrayList list;
1609                         private ListView owner;
1610
1611                         #region Public Constructor
1612                         public CheckedListViewItemCollection (ListView owner)
1613                         {
1614                                 list = new ArrayList ();
1615                                 this.owner = owner;
1616                         }
1617                         #endregion      // Public Constructor
1618
1619                         #region Public Properties
1620                         [Browsable (false)]
1621                         public virtual int Count {
1622                                 get { return list.Count; }
1623                         }
1624
1625                         public virtual bool IsReadOnly {
1626                                 get { return true; }
1627                         }
1628
1629                         public ListViewItem this [int index] {
1630                                 get {
1631                                         if (index < 0 || index >= list.Count)
1632                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1633                                         return (ListViewItem) list [index];
1634                                 }
1635                         }
1636
1637                         bool ICollection.IsSynchronized {
1638                                 get { return list.IsSynchronized; }
1639                         }
1640
1641                         object ICollection.SyncRoot {
1642                                 get { return list.SyncRoot; }
1643                         }
1644
1645                         bool IList.IsFixedSize {
1646                                 get { return list.IsFixedSize; }
1647                         }
1648
1649                         object IList.this [int index] {
1650                                 get { return this [index]; }
1651                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1652                         }
1653                         #endregion      // Public Properties
1654
1655                         #region Public Methods
1656                         public bool Contains (ListViewItem item)
1657                         {
1658                                 return list.Contains (item);
1659                         }
1660
1661                         public virtual void CopyTo (Array dest, int index)
1662                         {
1663                                 list.CopyTo (dest, index);
1664                         }
1665
1666                         public virtual IEnumerator GetEnumerator ()
1667                         {
1668                                 return list.GetEnumerator ();
1669                         }
1670
1671                         int IList.Add (object value)
1672                         {
1673                                 throw new NotSupportedException ("Add operation is not supported.");
1674                         }
1675
1676                         void IList.Clear ()
1677                         {
1678                                 throw new NotSupportedException ("Clear operation is not supported.");
1679                         }
1680
1681                         bool IList.Contains (object item)
1682                         {
1683                                 return list.Contains (item);
1684                         }
1685
1686                         int IList.IndexOf (object item)
1687                         {
1688                                 return list.IndexOf (item);
1689                         }
1690
1691                         void IList.Insert (int index, object value)
1692                         {
1693                                 throw new NotSupportedException ("Insert operation is not supported.");
1694                         }
1695
1696                         void IList.Remove (object value)
1697                         {
1698                                 throw new NotSupportedException ("Remove operation is not supported.");
1699                         }
1700
1701                         void IList.RemoveAt (int index)
1702                         {
1703                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
1704                         }
1705
1706                         public int IndexOf (ListViewItem item)
1707                         {
1708                                 return list.IndexOf (item);
1709                         }
1710                         #endregion      // Public Methods
1711
1712                 }       // CheckedListViewItemCollection
1713
1714                 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1715                 {
1716                         internal ArrayList list;
1717                         private ListView owner;
1718
1719                         #region Public Constructor
1720                         public ColumnHeaderCollection (ListView owner)
1721                         {
1722                                 list = new ArrayList ();
1723                                 this.owner = owner;
1724                         }
1725                         #endregion      // Public Constructor
1726
1727                         #region Public Properties
1728                         [Browsable (false)]
1729                         public virtual int Count {
1730                                 get { return list.Count; }
1731                         }
1732
1733                         public virtual bool IsReadOnly {
1734                                 get { return false; }
1735                         }
1736
1737                         public virtual ColumnHeader this [int index] {
1738                                 get {
1739                                         if (index < 0 || index >= list.Count)
1740                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1741                                         return (ColumnHeader) list [index];
1742                                 }
1743                         }
1744
1745                         bool ICollection.IsSynchronized {
1746                                 get { return list.IsSynchronized; }
1747                         }
1748
1749                         object ICollection.SyncRoot {
1750                                 get { return list.SyncRoot; }
1751                         }
1752
1753                         bool IList.IsFixedSize {
1754                                 get { return list.IsFixedSize; }
1755                         }
1756
1757                         object IList.this [int index] {
1758                                 get { return this [index]; }
1759                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1760                         }
1761                         #endregion      // Public Properties
1762
1763                         #region Public Methods
1764                         public virtual int Add (ColumnHeader value)
1765                         {
1766                                 return list.Add (value);
1767                         }
1768
1769                         public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1770                         {
1771                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1772                                 this.Add (colHeader);
1773
1774                                 return colHeader;
1775                         }
1776
1777                         public virtual void AddRange (ColumnHeader [] values)
1778                         {
1779                                 foreach (ColumnHeader colHeader in values)
1780                                         this.Add (colHeader);
1781                         }
1782
1783                         public virtual void Clear ()
1784                         {
1785                                 list.Clear ();
1786                         }
1787
1788                         public bool Contains (ColumnHeader value)
1789                         {
1790                                 return list.Contains (value);
1791                         }
1792
1793                         public virtual IEnumerator GetEnumerator ()
1794                         {
1795                                 return list.GetEnumerator ();
1796                         }
1797
1798                         void ICollection.CopyTo (Array dest, int index)
1799                         {
1800                                 list.CopyTo (dest, index);
1801                         }
1802
1803                         int IList.Add (object value)
1804                         {
1805                                 if (! (value is ColumnHeader)) {
1806                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1807                                 }
1808
1809                                 return this.Add ((ColumnHeader) value);
1810                         }
1811
1812                         bool IList.Contains (object value)
1813                         {
1814                                 if (! (value is ColumnHeader)) {
1815                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1816                                 }
1817
1818                                 return this.Contains ((ColumnHeader) value);
1819                         }
1820
1821                         int IList.IndexOf (object value)
1822                         {
1823                                 if (! (value is ColumnHeader)) {
1824                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1825                                 }
1826
1827                                 return this.IndexOf ((ColumnHeader) value);
1828                         }
1829
1830                         void IList.Insert (int index, object value)
1831                         {
1832                                 if (! (value is ColumnHeader)) {
1833                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1834                                 }
1835
1836                                 this.Insert (index, (ColumnHeader) value);
1837                         }
1838
1839                         void IList.Remove (object value)
1840                         {
1841                                 if (! (value is ColumnHeader)) {
1842                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1843                                 }
1844
1845                                 this.Remove ((ColumnHeader) value);
1846                         }
1847
1848                         public int IndexOf (ColumnHeader value)
1849                         {
1850                                 return list.IndexOf (value);
1851                         }
1852
1853                         public void Insert (int index, ColumnHeader value)
1854                         {
1855                                 if (index < 0 || index >= list.Count)
1856                                         throw new ArgumentOutOfRangeException ("Index out of range.");
1857
1858                                 list.Insert (index, value);
1859                         }
1860
1861                         public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1862                         {
1863                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1864                                 this.Insert (index, colHeader);
1865                         }
1866
1867                         public virtual void Remove (ColumnHeader column)
1868                         {
1869                                 list.Remove (column);
1870                         }
1871
1872                         public virtual void RemoveAt (int index)
1873                         {
1874                                 if (index < 0 || index >= list.Count)
1875                                         throw new ArgumentOutOfRangeException ("Index out of range.");
1876
1877                                 list.RemoveAt (index);
1878                         }
1879                         #endregion      // Public Methods
1880
1881                 }       // ColumnHeaderCollection
1882
1883                 public class ListViewItemCollection : IList, ICollection, IEnumerable
1884                 {
1885                         internal ArrayList list;
1886                         private ListView owner;
1887
1888                         #region Public Constructor
1889                         public ListViewItemCollection (ListView owner)
1890                         {
1891                                 list = new ArrayList ();
1892                                 this.owner = owner;
1893                         }
1894                         #endregion      // Public Constructor
1895
1896                         #region Public Properties
1897                         [Browsable (false)]
1898                         public virtual int Count {
1899                                 get { return list.Count; }
1900                         }
1901
1902                         public virtual bool IsReadOnly {
1903                                 get { return false; }
1904                         }
1905
1906                         public virtual ListViewItem this [int displayIndex] {
1907                                 get {
1908                                         if (displayIndex < 0 || displayIndex >= list.Count)
1909                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1910                                         return (ListViewItem) list [displayIndex];
1911                                 }
1912
1913                                 set {
1914                                         if (displayIndex < 0 || displayIndex >= list.Count)
1915                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1916
1917                                         if (list.Contains (value))
1918                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1919
1920                                         value.owner = this.owner;
1921                                         list [displayIndex] = value;
1922
1923                                         owner.Redraw (true);
1924                                 }
1925                         }
1926
1927                         bool ICollection.IsSynchronized {
1928                                 get { return list.IsSynchronized; }
1929                         }
1930
1931                         object ICollection.SyncRoot {
1932                                 get { return list.SyncRoot; }
1933                         }
1934
1935                         bool IList.IsFixedSize {
1936                                 get { return list.IsFixedSize; }
1937                         }
1938
1939                         object IList.this [int index] {
1940                                 get { return this [index]; }
1941                                 set {
1942                                         if (value is ListViewItem)
1943                                                 this [index] = (ListViewItem) value;
1944                                         else
1945                                                 this [index] = new ListViewItem (value.ToString ());
1946                                 }
1947                         }
1948                         #endregion      // Public Properties
1949
1950                         #region Public Methods
1951                         public virtual ListViewItem Add (ListViewItem value)
1952                         {
1953                                 if (list.Contains (value))
1954                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1955
1956                                 value.owner = this.owner;
1957                                 list.Add (value);
1958
1959                                 if (owner.Sorting != SortOrder.None)
1960                                         owner.Sort ();
1961
1962                                 owner.Redraw (true);
1963
1964                                 return value;
1965                         }
1966
1967                         public virtual ListViewItem Add (string text)
1968                         {
1969                                 ListViewItem item = new ListViewItem (text);
1970                                 return this.Add (item);
1971                         }
1972
1973                         public virtual ListViewItem Add (string text, int imageIndex)
1974                         {
1975                                 ListViewItem item = new ListViewItem (text, imageIndex);
1976                                 return this.Add (item);
1977                         }
1978
1979                         public void AddRange (ListViewItem [] values)
1980                         {
1981                                 list.Clear ();
1982
1983                                 foreach (ListViewItem item in values) {
1984                                         item.owner = this.owner;
1985                                         list.Add (item);
1986                                 }
1987
1988                                 if (owner.Sorting != SortOrder.None)
1989                                         owner.Sort ();
1990
1991                                 owner.Redraw (true);
1992                         }
1993
1994                         public virtual void Clear ()
1995                         {
1996                                 list.Clear ();
1997                         }
1998
1999                         public bool Contains (ListViewItem item)
2000                         {
2001                                 return list.Contains (item);
2002                         }
2003
2004                         public virtual void CopyTo (Array dest, int index)
2005                         {
2006                                 list.CopyTo (dest, index);
2007                         }
2008
2009                         public virtual IEnumerator GetEnumerator ()
2010                         {
2011                                 return list.GetEnumerator ();
2012                         }
2013
2014                         int IList.Add (object item)
2015                         {
2016                                 int result;
2017                                 ListViewItem li;
2018
2019                                 if (item is ListViewItem) {
2020                                         li = (ListViewItem) item;
2021                                         if (list.Contains (li))
2022                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2023                                 }
2024                                 else
2025                                         li = new ListViewItem (item.ToString ());
2026
2027                                 li.owner = this.owner;
2028                                 result = list.Add (li);
2029                                 owner.Redraw (true);
2030
2031                                 return result;
2032                         }
2033
2034                         bool IList.Contains (object item)
2035                         {
2036                                 return list.Contains (item);
2037                         }
2038
2039                         int IList.IndexOf (object item)
2040                         {
2041                                 return list.IndexOf (item);
2042                         }
2043
2044                         void IList.Insert (int index, object item)
2045                         {
2046                                 if (item is ListViewItem)
2047                                         this.Insert (index, (ListViewItem) item);
2048                                 else
2049                                         this.Insert (index, item.ToString ());
2050                         }
2051
2052                         void IList.Remove (object item)
2053                         {
2054                                 if (list.Contains (item)) {
2055                                         list.Remove (item);
2056                                         owner.Redraw (true);
2057                                 }
2058                         }
2059
2060                         public int IndexOf (ListViewItem item)
2061                         {
2062                                 return list.IndexOf (item);
2063                         }
2064
2065                         public ListViewItem Insert (int index, ListViewItem item)
2066                         {
2067                                 if (index < 0 || index >= list.Count)
2068                                         throw new ArgumentOutOfRangeException ("Index out of range.");
2069
2070                                 if (list.Contains (item))
2071                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2072
2073                                 item.owner = this.owner;
2074                                 list.Insert (index, item);
2075                                 owner.Redraw (true);
2076                                 return item;
2077                         }
2078
2079                         public ListViewItem Insert (int index, string text)
2080                         {
2081                                 return this.Insert (index, new ListViewItem (text));
2082                         }
2083
2084                         public ListViewItem Insert (int index, string text, int imageIndex)
2085                         {
2086                                 return this.Insert (index, new ListViewItem (text, imageIndex));
2087                         }
2088
2089                         public virtual void Remove (ListViewItem item)
2090                         {
2091                                 if (list.Contains (item)) {
2092                                         list.Remove (item);
2093                                         owner.Redraw (true);
2094                                 }
2095                         }
2096
2097                         public virtual void RemoveAt (int index)
2098                         {
2099                                 if (index < 0 || index >= list.Count)
2100                                         throw new ArgumentOutOfRangeException ("Index out of range.");
2101
2102                                 list.RemoveAt (index);
2103                                 owner.Redraw (false);
2104                         }
2105                         #endregion      // Public Methods
2106
2107                 }       // ListViewItemCollection
2108
2109                 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2110                 {
2111                         internal ArrayList list;
2112                         private ListView owner;
2113
2114                         #region Public Constructor
2115                         public SelectedIndexCollection (ListView owner)
2116                         {
2117                                 list = new ArrayList ();
2118                                 this.owner = owner;
2119                         }
2120                         #endregion      // Public Constructor
2121
2122                         #region Public Properties
2123                         [Browsable (false)]
2124                         public virtual int Count {
2125                                 get { return list.Count; }
2126                         }
2127
2128                         public virtual bool IsReadOnly {
2129                                 get { return true; }
2130                         }
2131
2132                         public int this [int index] {
2133                                 get {
2134                                         if (index < 0 || index >= list.Count)
2135                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
2136                                         return (int) list [index];
2137                                 }
2138                         }
2139
2140                         bool ICollection.IsSynchronized {
2141                                 get { return list.IsSynchronized; }
2142                         }
2143
2144                         object ICollection.SyncRoot {
2145                                 get { return list.SyncRoot; }
2146                         }
2147
2148                         bool IList.IsFixedSize {
2149                                 get { return list.IsFixedSize; }
2150                         }
2151
2152                         object IList.this [int index] {
2153                                 get { return this [index]; }
2154                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2155                         }
2156                         #endregion      // Public Properties
2157
2158                         #region Public Methods
2159                         public bool Contains (int selectedIndex)
2160                         {
2161                                 return list.Contains (selectedIndex);
2162                         }
2163
2164                         public virtual void CopyTo (Array dest, int index)
2165                         {
2166                                 list.CopyTo (dest, index);
2167                         }
2168
2169                         public virtual IEnumerator GetEnumerator ()
2170                         {
2171                                 return list.GetEnumerator ();
2172                         }
2173
2174                         int IList.Add (object value)
2175                         {
2176                                 throw new NotSupportedException ("Add operation is not supported.");
2177                         }
2178
2179                         void IList.Clear ()
2180                         {
2181                                 throw new NotSupportedException ("Clear operation is not supported.");
2182                         }
2183
2184                         bool IList.Contains (object selectedIndex)
2185                         {
2186                                 return list.Contains (selectedIndex);
2187                         }
2188
2189                         int IList.IndexOf (object selectedIndex)
2190                         {
2191                                 return list.IndexOf (selectedIndex);
2192                         }
2193
2194                         void IList.Insert (int index, object value)
2195                         {
2196                                 throw new NotSupportedException ("Insert operation is not supported.");
2197                         }
2198
2199                         void IList.Remove (object value)
2200                         {
2201                                 throw new NotSupportedException ("Remove operation is not supported.");
2202                         }
2203
2204                         void IList.RemoveAt (int index)
2205                         {
2206                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
2207                         }
2208
2209                         public int IndexOf (int selectedIndex)
2210                         {
2211                                 return list.IndexOf (selectedIndex);
2212                         }
2213                         #endregion      // Public Methods
2214
2215                 }       // SelectedIndexCollection
2216
2217                 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2218                 {
2219                         internal ArrayList list;
2220                         private ListView owner;
2221
2222                         #region Public Constructor
2223                         public SelectedListViewItemCollection (ListView owner)
2224                         {
2225                                 list = new ArrayList ();
2226                                 this.owner = owner;
2227                         }
2228                         #endregion      // Public Constructor
2229
2230                         #region Public Properties
2231                         [Browsable (false)]
2232                         public virtual int Count {
2233                                 get { return list.Count; }
2234                         }
2235
2236                         public virtual bool IsReadOnly {
2237                                 get { return true; }
2238                         }
2239
2240                         public ListViewItem this [int index] {
2241                                 get {
2242                                         if (index < 0 || index >= list.Count)
2243                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
2244                                         return (ListViewItem) list [index];
2245                                 }
2246                         }
2247
2248                         bool ICollection.IsSynchronized {
2249                                 get { return list.IsSynchronized; }
2250                         }
2251
2252                         object ICollection.SyncRoot {
2253                                 get { return list.SyncRoot; }
2254                         }
2255
2256                         bool IList.IsFixedSize {
2257                                 get { return list.IsFixedSize; }
2258                         }
2259
2260                         object IList.this [int index] {
2261                                 get { return this [index]; }
2262                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2263                         }
2264                         #endregion      // Public Properties
2265
2266                         #region Public Methods
2267                         public virtual void Clear ()
2268                         {
2269                                 // mark the items as unselected before clearing the list
2270                                 for (int i = 0; i < list.Count; i++)
2271                                         ((ListViewItem) list [i]).selected = false;
2272
2273                                 list.Clear ();
2274                         }
2275
2276                         public bool Contains (ListViewItem item)
2277                         {
2278                                 return list.Contains (item);
2279                         }
2280
2281                         public virtual void CopyTo (Array dest, int index)
2282                         {
2283                                 list.CopyTo (dest, index);
2284                         }
2285
2286                         public virtual IEnumerator GetEnumerator ()
2287                         {
2288                                 return list.GetEnumerator ();
2289                         }
2290
2291                         int IList.Add (object value)
2292                         {
2293                                 throw new NotSupportedException ("Add operation is not supported.");
2294                         }
2295
2296                         bool IList.Contains (object item)
2297                         {
2298                                 return list.Contains (item);
2299                         }
2300
2301                         int IList.IndexOf (object item)
2302                         {
2303                                 return list.IndexOf (item);
2304                         }
2305
2306                         void IList.Insert (int index, object value)
2307                         {
2308                                 throw new NotSupportedException ("Insert operation is not supported.");
2309                         }
2310
2311                         void IList.Remove (object value)
2312                         {
2313                                 throw new NotSupportedException ("Remove operation is not supported.");
2314                         }
2315
2316                         void IList.RemoveAt (int index)
2317                         {
2318                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
2319                         }
2320
2321                         public int IndexOf (ListViewItem item)
2322                         {
2323                                 return list.IndexOf (item);
2324                         }
2325                         #endregion      // Public Methods
2326
2327                 }       // SelectedListViewItemCollection
2328
2329                 #endregion // Subclasses
2330         }
2331 }