2009-10-07 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[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-2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Ravindra Kumar (rkumar@novell.com)
24 //      Jordi Mas i Hernandez, jordi@ximian.com
25 //      Mike Kestner (mkestner@novell.com)
26 //      Daniel Nauck (dna(at)mono-project(dot)de)
27 //      Carlos Alberto Cortez <calberto.cortez@gmail.com>
28 //
29
30
31 // NOT COMPLETE
32
33
34 using System.Collections;
35 using System.ComponentModel;
36 using System.ComponentModel.Design;
37 using System.Drawing;
38 using System.Runtime.InteropServices;
39 using System.Globalization;
40 #if NET_2_0
41 using System.Collections.Generic;
42 #endif
43
44 namespace System.Windows.Forms
45 {
46         [DefaultEvent ("SelectedIndexChanged")]
47         [DefaultProperty ("Items")]
48         [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
49 #if NET_2_0
50         [ClassInterface (ClassInterfaceType.AutoDispatch)]
51         [ComVisible (true)]
52         [Docking (DockingBehavior.Ask)]
53 #endif
54         public class ListView : Control
55         {
56                 private ItemActivation activation = ItemActivation.Standard;
57                 private ListViewAlignment alignment = ListViewAlignment.Top;
58                 private bool allow_column_reorder;
59                 private bool auto_arrange = true;
60                 private bool check_boxes;
61                 private readonly CheckedIndexCollection checked_indices;
62                 private readonly CheckedListViewItemCollection checked_items;
63                 private readonly ColumnHeaderCollection columns;
64                 internal int focused_item_index = -1;
65                 private bool full_row_select;
66                 private bool grid_lines;
67                 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
68                 private bool hide_selection = true;
69                 private bool hover_selection;
70                 private IComparer item_sorter;
71                 private readonly ListViewItemCollection items;
72 #if NET_2_0
73                 private readonly ListViewGroupCollection groups;
74                 private bool owner_draw;
75                 private bool show_groups = true;
76 #endif
77                 private bool label_edit;
78                 private bool label_wrap = true;
79                 private bool multiselect = true;
80                 private bool scrollable = true;
81                 private bool hover_pending;
82                 private readonly SelectedIndexCollection selected_indices;
83                 private readonly SelectedListViewItemCollection selected_items;
84                 private SortOrder sort_order = SortOrder.None;
85                 private ImageList state_image_list;
86                 internal bool updating;
87                 private View view = View.LargeIcon;
88                 private int layout_wd;    // We might draw more than our client area
89                 private int layout_ht;    // therefore we need to have these two.
90                 internal HeaderControl header_control;
91                 internal ItemControl item_control;
92                 internal ScrollBar h_scroll; // used for scrolling horizontally
93                 internal ScrollBar v_scroll; // used for scrolling vertically
94                 internal int h_marker;          // Position markers for scrolling
95                 internal int v_marker;
96                 private int keysearch_tickcnt;
97                 private string keysearch_text;
98                 static private readonly int keysearch_keydelay = 1000;
99                 private int[] reordered_column_indices;
100                 private int[] reordered_items_indices;
101                 private Point [] items_location;
102                 private ItemMatrixLocation [] items_matrix_location;
103                 private Size item_size; // used for caching item size
104                 private int custom_column_width; // used when using Columns with SmallIcon/List views
105                 private int hot_item_index = -1;
106 #if NET_2_0
107                 private bool hot_tracking;
108                 private ListViewInsertionMark insertion_mark;
109                 private bool show_item_tooltips;
110                 private ToolTip item_tooltip;
111                 private Size tile_size;
112                 private bool virtual_mode;
113                 private int virtual_list_size;
114                 private bool right_to_left_layout;
115 #endif
116
117                 // internal variables
118                 internal ImageList large_image_list;
119                 internal ImageList small_image_list;
120                 internal Size text_size = Size.Empty;
121
122                 #region Events
123                 static object AfterLabelEditEvent = new object ();
124                 static object BeforeLabelEditEvent = new object ();
125                 static object ColumnClickEvent = new object ();
126                 static object ItemActivateEvent = new object ();
127                 static object ItemCheckEvent = new object ();
128                 static object ItemDragEvent = new object ();
129                 static object SelectedIndexChangedEvent = new object ();
130 #if NET_2_0
131                 static object DrawColumnHeaderEvent = new object();
132                 static object DrawItemEvent = new object();
133                 static object DrawSubItemEvent = new object();
134                 static object ItemCheckedEvent = new object ();
135                 static object ItemMouseHoverEvent = new object ();
136                 static object ItemSelectionChangedEvent = new object ();
137                 static object CacheVirtualItemsEvent = new object ();
138                 static object RetrieveVirtualItemEvent = new object ();
139                 static object RightToLeftLayoutChangedEvent = new object ();
140                 static object SearchForVirtualItemEvent = new object ();
141                 static object VirtualItemsSelectionRangeChangedEvent = new object ();
142 #endif
143
144                 public event LabelEditEventHandler AfterLabelEdit {
145                         add { Events.AddHandler (AfterLabelEditEvent, value); }
146                         remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
147                 }
148
149 #if !NET_2_0
150                 [Browsable (false)]
151                 [EditorBrowsable (EditorBrowsableState.Never)]
152                 public new event EventHandler BackgroundImageChanged {
153                         add { base.BackgroundImageChanged += value; }
154                         remove { base.BackgroundImageChanged -= value; }
155                 }
156 #endif
157
158 #if NET_2_0
159                 [Browsable (false)]
160                 [EditorBrowsable (EditorBrowsableState.Never)]
161                 public new event EventHandler BackgroundImageLayoutChanged {
162                         add { base.BackgroundImageLayoutChanged += value; }
163                         remove { base.BackgroundImageLayoutChanged -= value; }
164                 }
165 #endif
166
167                 public event LabelEditEventHandler BeforeLabelEdit {
168                         add { Events.AddHandler (BeforeLabelEditEvent, value); }
169                         remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
170                 }
171
172                 public event ColumnClickEventHandler ColumnClick {
173                         add { Events.AddHandler (ColumnClickEvent, value); }
174                         remove { Events.RemoveHandler (ColumnClickEvent, value); }
175                 }
176
177 #if NET_2_0
178                 public event DrawListViewColumnHeaderEventHandler DrawColumnHeader {
179                         add { Events.AddHandler(DrawColumnHeaderEvent, value); }
180                         remove { Events.RemoveHandler(DrawColumnHeaderEvent, value); }
181                 }
182
183                 public event DrawListViewItemEventHandler DrawItem {
184                         add { Events.AddHandler(DrawItemEvent, value); }
185                         remove { Events.RemoveHandler(DrawItemEvent, value); }
186                 }
187
188                 public event DrawListViewSubItemEventHandler DrawSubItem {
189                         add { Events.AddHandler(DrawSubItemEvent, value); }
190                         remove { Events.RemoveHandler(DrawSubItemEvent, value); }
191                 }
192 #endif
193
194                 public event EventHandler ItemActivate {
195                         add { Events.AddHandler (ItemActivateEvent, value); }
196                         remove { Events.RemoveHandler (ItemActivateEvent, value); }
197                 }
198
199                 public event ItemCheckEventHandler ItemCheck {
200                         add { Events.AddHandler (ItemCheckEvent, value); }
201                         remove { Events.RemoveHandler (ItemCheckEvent, value); }
202                 }
203
204 #if NET_2_0
205                 public event ItemCheckedEventHandler ItemChecked {
206                         add { Events.AddHandler (ItemCheckedEvent, value); }
207                         remove { Events.RemoveHandler (ItemCheckedEvent, value); }
208                 }
209 #endif
210
211                 public event ItemDragEventHandler ItemDrag {
212                         add { Events.AddHandler (ItemDragEvent, value); }
213                         remove { Events.RemoveHandler (ItemDragEvent, value); }
214                 }
215
216 #if NET_2_0
217                 public event ListViewItemMouseHoverEventHandler ItemMouseHover {
218                         add { Events.AddHandler (ItemMouseHoverEvent, value); }
219                         remove { Events.RemoveHandler (ItemMouseHoverEvent, value); }
220                 }
221
222                 public event ListViewItemSelectionChangedEventHandler ItemSelectionChanged {
223                         add { Events.AddHandler (ItemSelectionChangedEvent, value); }
224                         remove { Events.RemoveHandler (ItemSelectionChangedEvent, value); }
225                 }
226
227                 [Browsable (false)]
228                 [EditorBrowsable (EditorBrowsableState.Never)]
229                 public new event EventHandler PaddingChanged {
230                         add { base.PaddingChanged += value; }
231                         remove { base.PaddingChanged -= value; }
232                 }
233 #endif
234
235                 [Browsable (false)]
236                 [EditorBrowsable (EditorBrowsableState.Never)]
237                 public new event PaintEventHandler Paint {
238                         add { base.Paint += value; }
239                         remove { base.Paint -= value; }
240                 }
241
242                 public event EventHandler SelectedIndexChanged {
243                         add { Events.AddHandler (SelectedIndexChangedEvent, value); }
244                         remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
245                 }
246
247                 [Browsable (false)]
248                 [EditorBrowsable (EditorBrowsableState.Never)]
249                 public new event EventHandler TextChanged {
250                         add { base.TextChanged += value; }
251                         remove { base.TextChanged -= value; }
252                 }
253
254 #if NET_2_0
255                 public event CacheVirtualItemsEventHandler CacheVirtualItems {
256                         add { Events.AddHandler (CacheVirtualItemsEvent, value); }
257                         remove { Events.RemoveHandler (CacheVirtualItemsEvent, value); }
258                 }
259
260                 public event RetrieveVirtualItemEventHandler RetrieveVirtualItem {
261                         add { Events.AddHandler (RetrieveVirtualItemEvent, value); }
262                         remove { Events.RemoveHandler (RetrieveVirtualItemEvent, value); }
263                 }
264
265                 public event EventHandler RightToLeftLayoutChanged {
266                         add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
267                         remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
268                 }
269
270                 public event SearchForVirtualItemEventHandler SearchForVirtualItem {
271                         add { Events.AddHandler (SearchForVirtualItemEvent, value); }
272                         remove { Events.AddHandler (SearchForVirtualItemEvent, value); }
273                 }
274                 
275                 public event ListViewVirtualItemsSelectionRangeChangedEventHandler VirtualItemsSelectionRangeChanged {
276                         add { Events.AddHandler (VirtualItemsSelectionRangeChangedEvent, value); }
277                         remove { Events.RemoveHandler (VirtualItemsSelectionRangeChangedEvent, value); }
278                 }
279 #endif
280
281                 #endregion // Events
282
283                 #region Public Constructors
284                 public ListView ()
285                 {
286                         background_color = ThemeEngine.Current.ColorWindow;
287 #if NET_2_0
288                         groups = new ListViewGroupCollection (this);
289 #endif
290                         items = new ListViewItemCollection (this);
291                         items.Changed += new CollectionChangedHandler (OnItemsChanged);
292                         checked_indices = new CheckedIndexCollection (this);
293                         checked_items = new CheckedListViewItemCollection (this);
294                         columns = new ColumnHeaderCollection (this);
295                         foreground_color = SystemColors.WindowText;
296                         selected_indices = new SelectedIndexCollection (this);
297                         selected_items = new SelectedListViewItemCollection (this);
298                         items_location = new Point [16];
299                         items_matrix_location = new ItemMatrixLocation [16];
300                         reordered_items_indices = new int [16];
301 #if NET_2_0
302                         item_tooltip = new ToolTip ();
303                         item_tooltip.Active = false;
304                         insertion_mark = new ListViewInsertionMark (this);
305 #endif
306
307                         InternalBorderStyle = BorderStyle.Fixed3D;
308
309                         header_control = new HeaderControl (this);
310                         header_control.Visible = false;
311                         Controls.AddImplicit (header_control);
312
313                         item_control = new ItemControl (this);
314                         Controls.AddImplicit (item_control);
315
316                         h_scroll = new ImplicitHScrollBar ();
317                         Controls.AddImplicit (this.h_scroll);
318
319                         v_scroll = new ImplicitVScrollBar ();
320                         Controls.AddImplicit (this.v_scroll);
321
322                         h_marker = v_marker = 0;
323                         keysearch_tickcnt = 0;
324
325                         // scroll bars are disabled initially
326                         h_scroll.Visible = false;
327                         h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
328                         v_scroll.Visible = false;
329                         v_scroll.ValueChanged += new EventHandler(VerticalScroller);
330
331                         // event handlers
332                         base.KeyDown += new KeyEventHandler(ListView_KeyDown);
333                         SizeChanged += new EventHandler (ListView_SizeChanged);
334                         GotFocus += new EventHandler (FocusChanged);
335                         LostFocus += new EventHandler (FocusChanged);
336                         MouseWheel += new MouseEventHandler(ListView_MouseWheel);
337                         MouseEnter += new EventHandler (ListView_MouseEnter);
338                         Invalidated += new InvalidateEventHandler (ListView_Invalidated);
339
340 #if NET_2_0
341                         BackgroundImageTiled = false;
342 #endif
343
344                         this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
345 #if NET_2_0
346                                 | ControlStyles.UseTextForAccessibility
347 #endif
348                                 , false);
349                 }
350                 #endregion      // Public Constructors
351
352                 #region Private Internal Properties
353                 internal Size CheckBoxSize {
354                         get {
355                                 if (this.check_boxes) {
356                                         if (this.state_image_list != null)
357                                                 return this.state_image_list.ImageSize;
358                                         else
359                                                 return ThemeEngine.Current.ListViewCheckBoxSize;
360                                 }
361                                 return Size.Empty;
362                         }
363                 }
364
365                 internal Size ItemSize {
366                         get {
367                                 if (view != View.Details)
368                                         return item_size;
369
370                                 Size size = new Size ();
371                                 size.Height = item_size.Height;
372                                 for (int i = 0; i < columns.Count; i++)
373                                         size.Width += columns [i].Wd;
374
375                                 return size;
376                         }
377                         set {
378                                 item_size = value;
379                         }
380                 }
381
382                 internal int HotItemIndex {
383                         get {
384                                 return hot_item_index;
385                         }
386                         set {
387                                 hot_item_index = value;
388                         }
389                 }
390
391 #if NET_2_0
392                 internal bool UsingGroups {
393                         get {
394                                 return show_groups && groups.Count > 0 && view != View.List && 
395                                         Application.VisualStylesEnabled;
396                         }
397                 }
398 #endif
399
400                 internal override bool ScaleChildrenInternal {
401                         get { return false; }
402                 }
403
404                 internal bool UseCustomColumnWidth {
405                         get {
406                                 return (view == View.List || view == View.SmallIcon) && columns.Count > 0;
407                         }
408                 }
409
410                 internal ColumnHeader EnteredColumnHeader {
411                         get {
412                                 return header_control.EnteredColumnHeader;
413                         }
414                 }
415                 #endregion      // Private Internal Properties
416
417                 #region  Protected Properties
418                 protected override CreateParams CreateParams {
419                         get { return base.CreateParams; }
420                 }
421
422                 protected override Size DefaultSize {
423                         get { return ThemeEngine.Current.ListViewDefaultSize; }
424                 }
425 #if NET_2_0
426                 protected override bool DoubleBuffered {
427                         get {
428                                 return base.DoubleBuffered;
429                         }
430                         set {
431                                 base.DoubleBuffered = value;
432                         }
433                 }
434 #endif
435                 #endregion      // Protected Properties
436
437                 #region Public Instance Properties
438                 [DefaultValue (ItemActivation.Standard)]
439                 public ItemActivation Activation {
440                         get { return activation; }
441                         set { 
442                                 if (value != ItemActivation.Standard && value != ItemActivation.OneClick && 
443                                         value != ItemActivation.TwoClick) {
444                                         throw new InvalidEnumArgumentException (string.Format
445                                                 ("Enum argument value '{0}' is not valid for Activation", value));
446                                 }
447 #if NET_2_0
448                                 if (hot_tracking && value != ItemActivation.OneClick)
449                                         throw new ArgumentException ("When HotTracking is on, activation must be ItemActivation.OneClick");
450 #endif
451                                 
452                                 activation = value;
453                         }
454                 }
455
456                 [DefaultValue (ListViewAlignment.Top)]
457                 [Localizable (true)]
458                 public ListViewAlignment Alignment {
459                         get { return alignment; }
460                         set {
461                                 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left && 
462                                         value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
463                                         throw new InvalidEnumArgumentException (string.Format 
464                                                 ("Enum argument value '{0}' is not valid for Alignment", value));
465                                 }
466                                 
467                                 if (this.alignment != value) {
468                                         alignment = value;
469                                         // alignment does not matter in Details/List views
470                                         if (this.view == View.LargeIcon || this.View == View.SmallIcon)
471                                                 this.Redraw (true);
472                                 }
473                         }
474                 }
475
476                 [DefaultValue (false)]
477                 public bool AllowColumnReorder {
478                         get { return allow_column_reorder; }
479                         set { allow_column_reorder = value; }
480                 }
481
482                 [DefaultValue (true)]
483                 public bool AutoArrange {
484                         get { return auto_arrange; }
485                         set {
486                                 if (auto_arrange != value) {
487                                         auto_arrange = value;
488                                         // autoarrange does not matter in Details/List views
489                                         if (this.view == View.LargeIcon || this.View == View.SmallIcon)
490                                                 this.Redraw (true);
491                                 }
492                         }
493                 }
494
495                 public override Color BackColor {
496                         get {
497                                 if (background_color.IsEmpty)
498                                         return ThemeEngine.Current.ColorWindow;
499                                 else
500                                         return background_color;
501                         }
502                         set { 
503                                 background_color = value;
504                                 item_control.BackColor = value;
505                         }
506                 }
507
508 #if !NET_2_0
509                 [Browsable (false)]
510                 [EditorBrowsable (EditorBrowsableState.Never)]
511                 public override Image BackgroundImage {
512                         get { return base.BackgroundImage; }
513                         set { base.BackgroundImage = value; }
514                 }
515 #endif
516
517 #if NET_2_0
518                 [Browsable (false)]
519                 [EditorBrowsable (EditorBrowsableState.Never)]
520                 public override ImageLayout BackgroundImageLayout {
521                         get {
522                                 return base.BackgroundImageLayout;
523                         }
524                         set {
525                                 base.BackgroundImageLayout = value;
526                         }
527                 }
528
529                 [DefaultValue (false)]
530                 public bool BackgroundImageTiled {
531                         get {
532                                 return item_control.BackgroundImageLayout == ImageLayout.Tile;
533                         }
534                         set {
535                                 ImageLayout new_image_layout = value ? ImageLayout.Tile : ImageLayout.None;
536                                 if (new_image_layout == item_control.BackgroundImageLayout)
537                                         return;
538
539                                 item_control.BackgroundImageLayout = new_image_layout;
540                         }
541                 }
542 #endif
543
544                 [DefaultValue (BorderStyle.Fixed3D)]
545                 [DispId (-504)]
546                 public BorderStyle BorderStyle {
547                         get { return InternalBorderStyle; }
548                         set { InternalBorderStyle = value; }
549                 }
550
551                 [DefaultValue (false)]
552                 public bool CheckBoxes {
553                         get { return check_boxes; }
554                         set {
555                                 if (check_boxes != value) {
556 #if NET_2_0
557                                         if (value && View == View.Tile)
558                                                 throw new NotSupportedException ("CheckBoxes are not"
559                                                         + " supported in Tile view. Choose a different"
560                                                         + " view or set CheckBoxes to false.");
561 #endif
562
563                                         check_boxes = value;
564                                         this.Redraw (true);
565
566 #if NET_2_0
567                                         //UIA Framework: Event used by ListView to set/unset Toggle Pattern
568                                         OnUIACheckBoxesChanged ();
569 #endif
570                                 }
571                         }
572                 }
573
574                 [Browsable (false)]
575                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
576                 public CheckedIndexCollection CheckedIndices {
577                         get { return checked_indices; }
578                 }
579
580                 [Browsable (false)]
581                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
582                 public CheckedListViewItemCollection CheckedItems {
583                         get { return checked_items; }
584                 }
585
586 #if NET_2_0
587                 [Editor ("System.Windows.Forms.Design.ColumnHeaderCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
588 #endif
589                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
590                 [Localizable (true)]
591                 [MergableProperty (false)]
592                 public ColumnHeaderCollection Columns {
593                         get { return columns; }
594                 }
595
596                 [Browsable (false)]
597                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
598                 public ListViewItem FocusedItem {
599                         get {
600                                 if (focused_item_index == -1)
601                                         return null;
602
603                                 return GetItemAtDisplayIndex (focused_item_index);
604                         }
605 #if NET_2_0
606                         set {
607                                 if (value == null || value.ListView != this || 
608                                                 !IsHandleCreated)
609                                         return;
610
611                                 SetFocusedItem (value.DisplayIndex);
612                         }
613 #endif
614                 }
615
616                 public override Color ForeColor {
617                         get {
618                                 if (foreground_color.IsEmpty)
619                                         return ThemeEngine.Current.ColorWindowText;
620                                 else
621                                         return foreground_color;
622                         }
623                         set { foreground_color = value; }
624                 }
625
626                 [DefaultValue (false)]
627                 public bool FullRowSelect {
628                         get { return full_row_select; }
629                         set { 
630                                 if (full_row_select != value) {
631                                         full_row_select = value;
632                                         InvalidateSelection ();
633                                 }
634                         }
635                 }
636
637                 [DefaultValue (false)]
638                 public bool GridLines {
639                         get { return grid_lines; }
640                         set {
641                                 if (grid_lines != value) {
642                                         grid_lines = value;
643                                         this.Redraw (false);
644                                 }
645                         }
646                 }
647
648                 [DefaultValue (ColumnHeaderStyle.Clickable)]
649                 public ColumnHeaderStyle HeaderStyle {
650                         get { return header_style; }
651                         set {
652                                 if (header_style == value)
653                                         return;
654
655                                 switch (value) {
656                                 case ColumnHeaderStyle.Clickable:
657                                 case ColumnHeaderStyle.Nonclickable:
658                                 case ColumnHeaderStyle.None:
659                                         break;
660                                 default:
661                                         throw new InvalidEnumArgumentException (string.Format 
662                                                 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
663                                 }
664                                 
665                                 header_style = value;
666                                 if (view == View.Details)
667                                         Redraw (true);
668                         }
669                 }
670
671                 [DefaultValue (true)]
672                 public bool HideSelection {
673                         get { return hide_selection; }
674                         set {
675                                 if (hide_selection != value) {
676                                         hide_selection = value;
677                                         InvalidateSelection ();
678                                 }
679                         }
680                 }
681
682 #if NET_2_0
683                 [DefaultValue (false)]
684                 public bool HotTracking {
685                         get {
686                                 return hot_tracking;
687                         }
688                         set {
689                                 if (hot_tracking == value)
690                                         return;
691                                 
692                                 hot_tracking = value;
693                                 if (hot_tracking) {
694                                         hover_selection = true;
695                                         activation = ItemActivation.OneClick;
696                                 }
697                         }
698                 }
699 #endif
700
701                 [DefaultValue (false)]
702                 public bool HoverSelection {
703                         get { return hover_selection; }
704                         set { 
705 #if NET_2_0
706                                 if (hot_tracking && value == false)
707                                         throw new ArgumentException ("When HotTracking is on, hover selection must be true");
708 #endif
709                                 hover_selection = value; 
710                         }
711                 }
712
713 #if NET_2_0
714                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
715                 [Browsable (false)]
716                 public ListViewInsertionMark InsertionMark {
717                         get {
718                                 return insertion_mark;
719                         }
720                 }
721 #endif
722
723 #if NET_2_0
724                 [Editor ("System.Windows.Forms.Design.ListViewItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
725 #endif
726                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
727                 [Localizable (true)]
728                 [MergableProperty (false)]
729                 public ListViewItemCollection Items {
730                         get { return items; }
731                 }
732
733                 [DefaultValue (false)]
734                 public bool LabelEdit {
735                         get { return label_edit; }
736                         set { 
737                                 if (value != label_edit) {
738                                         label_edit = value; 
739
740 #if NET_2_0
741                                         // UIA Framework: Event used by Value Pattern in ListView.ListItem provider
742                                         OnUIALabelEditChanged ();
743 #endif
744                                 }
745
746                         }
747                 }
748
749                 [DefaultValue (true)]
750                 [Localizable (true)]
751                 public bool LabelWrap {
752                         get { return label_wrap; }
753                         set {
754                                 if (label_wrap != value) {
755                                         label_wrap = value;
756                                         this.Redraw (true);
757                                 }
758                         }
759                 }
760
761                 [DefaultValue (null)]
762                 public ImageList LargeImageList {
763                         get { return large_image_list; }
764                         set {
765                                 large_image_list = value;
766                                 this.Redraw (true);
767                         }
768                 }
769
770                 [Browsable (false)]
771                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
772                 public IComparer ListViewItemSorter {
773                         get {
774                                 if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
775                                         return null;
776                                 return item_sorter;
777                         }
778                         set {
779                                 if (item_sorter != value) {
780                                         item_sorter = value;
781                                         Sort ();
782                                 }
783                         }
784                 }
785
786                 [DefaultValue (true)]
787                 public bool MultiSelect {
788                         get { return multiselect; }
789                         set {
790                                 if (value != multiselect) {
791                                         multiselect = value; 
792
793 #if NET_2_0
794                                         // UIA Framework: Event used by Selection Pattern in ListView.ListItem provider
795                                         OnUIAMultiSelectChanged ();
796 #endif
797                                 }
798                         }
799                 }
800
801
802 #if NET_2_0
803                 [DefaultValue(false)]
804                 public bool OwnerDraw {
805                         get { return owner_draw; }
806                         set { 
807                                 owner_draw = value;
808                                 Redraw (true);
809                         }
810                 }
811
812                 [Browsable (false)]
813                 [EditorBrowsable (EditorBrowsableState.Never)]
814                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
815                 public new Padding Padding {
816                         get {
817                                 return base.Padding;
818                         }
819                         set {
820                                 base.Padding = value;
821                         }
822                 }
823                 
824                 [MonoTODO ("RTL not supported")]
825                 [Localizable (true)]
826                 [DefaultValue (false)]
827                 public virtual bool RightToLeftLayout {
828                         get { return right_to_left_layout; }
829                         set { 
830                                 if (right_to_left_layout != value) {
831                                         right_to_left_layout = value;
832                                         OnRightToLeftLayoutChanged (EventArgs.Empty);
833                                 }
834                         }
835                 }
836 #endif
837
838                 [DefaultValue (true)]
839                 public bool Scrollable {
840                         get { return scrollable; }
841                         set {
842                                 if (scrollable != value) {
843                                         scrollable = value;
844                                         this.Redraw (true);
845                                 }
846                         }
847                 }
848
849                 [Browsable (false)]
850                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
851                 public SelectedIndexCollection SelectedIndices {
852                         get { return selected_indices; }
853                 }
854
855                 [Browsable (false)]
856                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
857                 public SelectedListViewItemCollection SelectedItems {
858                         get { return selected_items; }
859                 }
860
861 #if NET_2_0
862                 [DefaultValue(true)]
863                 public bool ShowGroups {
864                         get { return show_groups; }
865                         set {
866                                 if (show_groups != value) {
867                                         show_groups = value;
868                                         Redraw(true);
869
870                                         // UIA Framework: Used to update a11y Tree
871                                         OnUIAShowGroupsChanged ();
872                                 }
873                         }
874                 }
875
876                 [LocalizableAttribute (true)]
877                 [MergableProperty (false)]
878                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
879                 [Editor ("System.Windows.Forms.Design.ListViewGroupCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
880                 public ListViewGroupCollection Groups {
881                         get { return groups; }
882                 }
883
884                 [DefaultValue (false)]
885                 public bool ShowItemToolTips {
886                         get {
887                                 return show_item_tooltips;
888                         }
889                         set {
890                                 show_item_tooltips = value;
891                                 item_tooltip.Active = false;
892                         }
893                 }
894 #endif
895
896                 [DefaultValue (null)]
897                 public ImageList SmallImageList {
898                         get { return small_image_list; }
899                         set {
900                                 small_image_list = value;
901                                 this.Redraw (true);
902                         }
903                 }
904
905                 [DefaultValue (SortOrder.None)]
906                 public SortOrder Sorting {
907                         get { return sort_order; }
908                         set { 
909                                 if (!Enum.IsDefined (typeof (SortOrder), value)) {
910                                         throw new InvalidEnumArgumentException ("value", (int) value,
911                                                 typeof (SortOrder));
912                                 }
913                                 
914                                 if (sort_order == value)
915                                         return;
916
917                                 sort_order = value;
918
919 #if NET_2_0
920                                 if (virtual_mode) // Sorting is not allowed in virtual mode
921                                         return;
922 #endif
923
924                                 if (value == SortOrder.None) {
925                                         if (item_sorter != null) {
926                                                 // ListViewItemSorter should never be reset for SmallIcon
927                                                 // and LargeIcon view
928                                                 if (View != View.SmallIcon && View != View.LargeIcon)
929 #if NET_2_0
930                                                         item_sorter = null;
931 #else
932                                                         // in .NET 1.1, only internal IComparer would be
933                                                         // set to null
934                                                         if (item_sorter is ItemComparer)
935                                                                 item_sorter = null;
936 #endif
937                                         }
938                                         this.Redraw (false);
939                                 } else {
940                                         if (item_sorter == null)
941                                                 item_sorter = new ItemComparer (value);
942                                         if (item_sorter is ItemComparer) {
943 #if NET_2_0
944                                                 item_sorter = new ItemComparer (value);
945 #else
946                                                 // in .NET 1.1, the sort order is not updated for
947                                                 // SmallIcon and LargeIcon views if no custom IComparer
948                                                 // is set
949                                                 if (View != View.SmallIcon && View != View.LargeIcon)
950                                                         item_sorter = new ItemComparer (value);
951 #endif
952                                         }
953                                         Sort ();
954                                 }
955                         }
956                 }
957
958                 private void OnImageListChanged (object sender, EventArgs args)
959                 {
960                         item_control.Invalidate ();
961                 }
962
963                 [DefaultValue (null)]
964                 public ImageList StateImageList {
965                         get { return state_image_list; }
966                         set {
967                                 if (state_image_list == value)
968                                         return;
969
970                                 if (state_image_list != null)
971                                         state_image_list.Images.Changed -= new EventHandler (OnImageListChanged);
972
973                                 state_image_list = value;
974
975                                 if (state_image_list != null)
976                                         state_image_list.Images.Changed += new EventHandler (OnImageListChanged);
977
978                                 this.Redraw (true);
979                         }
980                 }
981
982                 [Bindable (false)]
983                 [Browsable (false)]
984                 [EditorBrowsable (EditorBrowsableState.Never)]
985                 public override string Text {
986                         get { return base.Text; } 
987                         set {
988                                 if (value == base.Text)
989                                         return;
990
991                                 base.Text = value;
992                                 this.Redraw (true);
993                         }
994                 }
995
996 #if NET_2_0
997                 [Browsable (true)]
998                 public Size TileSize {
999                         get {
1000                                 return tile_size;
1001                         }
1002                         set {
1003                                 if (value.Width <= 0 || value.Height <= 0)
1004                                         throw new ArgumentOutOfRangeException ("value");
1005
1006                                 tile_size = value;
1007                                 if (view == View.Tile)
1008                                         Redraw (true);
1009                         }
1010                 }
1011 #endif
1012
1013                 [Browsable (false)]
1014                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1015                 public ListViewItem TopItem {
1016                         get {
1017 #if NET_2_0
1018                                 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
1019                                         throw new InvalidOperationException ("Cannot get the top item in LargeIcon, SmallIcon or Tile view.");
1020 #endif
1021                                 // there is no item
1022                                 if (this.items.Count == 0)
1023                                         return null;
1024                                 // if contents are not scrolled
1025                                 // it is the first item
1026                                 else if (h_marker == 0 && v_marker == 0)
1027                                         return this.items [0];
1028                                 // do a hit test for the scrolled position
1029                                 else {
1030                                         for (int i = 0; i < items.Count; i++) {
1031                                                 Point item_loc = GetItemLocation (i);
1032                                                 if (item_loc.X >= 0 && item_loc.Y >= 0)
1033                                                         return items [i];
1034                                         }
1035                                         return null;
1036                                 }
1037                         }
1038 #if NET_2_0
1039                         set {
1040                                 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
1041                                         throw new InvalidOperationException ("Cannot set the top item in LargeIcon, SmallIcon or Tile view.");
1042
1043                                 // .Net doesn't throw any exception in the cases below
1044                                 if (value == null || value.ListView != this)
1045                                         return;
1046
1047                                 EnsureVisible (value.Index);
1048                         }
1049 #endif
1050                 }
1051
1052 #if NET_2_0
1053                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1054                 [DefaultValue (true)]
1055                 [Browsable (false)]
1056                 [MonoInternalNote ("Stub, not implemented")]
1057                 public bool UseCompatibleStateImageBehavior {
1058                         get {
1059                                 return false;
1060                         }
1061                         set {
1062                         }
1063                 }
1064 #endif
1065
1066                 [DefaultValue (View.LargeIcon)]
1067                 public View View {
1068                         get { return view; }
1069                         set { 
1070                                 if (!Enum.IsDefined (typeof (View), value))
1071                                         throw new InvalidEnumArgumentException ("value", (int) value,
1072                                                 typeof (View));
1073
1074                                 if (view != value) {
1075 #if NET_2_0
1076                                         if (CheckBoxes && value == View.Tile)
1077                                                 throw new NotSupportedException ("CheckBoxes are not"
1078                                                         + " supported in Tile view. Choose a different"
1079                                                         + " view or set CheckBoxes to false.");
1080                                         if (VirtualMode && value == View.Tile)
1081                                                 throw new NotSupportedException ("VirtualMode is"
1082                                                         + " not supported in Tile view. Choose a different"
1083                                                         + " view or set ViewMode to false.");
1084 #endif
1085
1086                                         h_scroll.Value = v_scroll.Value = 0;
1087                                         view = value; 
1088                                         Redraw (true);
1089
1090 #if NET_2_0
1091                                         // UIA Framework: Event used to update UIA Tree.
1092                                         OnUIAViewChanged ();
1093 #endif
1094                                 }
1095                         }
1096                 }
1097
1098 #if NET_2_0
1099                 [DefaultValue (false)]
1100                 [RefreshProperties (RefreshProperties.Repaint)]
1101                 public bool VirtualMode {
1102                         get {
1103                                 return virtual_mode;
1104                         }
1105                         set {
1106                                 if (virtual_mode == value)
1107                                         return;
1108
1109                                 if (!virtual_mode && items.Count > 0)
1110                                         throw new InvalidOperationException ();
1111                                 if (value && view == View.Tile)
1112                                         throw new NotSupportedException ("VirtualMode is"
1113                                                 + " not supported in Tile view. Choose a different"
1114                                                 + " view or set ViewMode to false.");
1115
1116                                 virtual_mode = value;
1117                                 Redraw (true);
1118                         }
1119                 }
1120
1121                 [DefaultValue (0)]
1122                 [RefreshProperties (RefreshProperties.Repaint)]
1123                 public int VirtualListSize {
1124                         get {
1125                                 return virtual_list_size;
1126                         }
1127                         set {
1128                                 if (value < 0)
1129                                         throw new ArgumentException ("value");
1130
1131                                 if (virtual_list_size == value)
1132                                         return;
1133
1134                                 virtual_list_size = value;
1135                                 if (virtual_mode) {
1136                                         selected_indices.Reset ();
1137                                         Redraw (true);
1138                                 }
1139                         }
1140                 }
1141 #endif
1142                 #endregion      // Public Instance Properties
1143
1144                 #region Internal Methods Properties
1145                 
1146                 internal int FirstVisibleIndex {
1147                         get {
1148                                 // there is no item
1149                                 if (this.items.Count == 0)
1150                                         return 0;
1151                                 
1152                                 if (h_marker == 0 && v_marker == 0)
1153                                         return 0;
1154                                 
1155                                 Size item_size = ItemSize;
1156                                 for (int i = 0; i < items.Count; i++) {
1157                                         Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
1158                                         if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
1159                                                 return i;
1160                                 }
1161
1162                                 return 0;
1163                         }
1164                 }
1165
1166                 
1167                 internal int LastVisibleIndex {
1168                         get {
1169                                 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
1170                                         if (View == View.List || Alignment == ListViewAlignment.Left) {
1171                                                 if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
1172                                                         return i - 1;
1173                                         } else {
1174                                                 if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
1175                                                         return i - 1;
1176                                         }
1177                                 }
1178                                 
1179                                 return Items.Count - 1;
1180                         }
1181                 }
1182
1183                 internal void OnSelectedIndexChanged ()
1184                 {
1185                         if (IsHandleCreated)
1186                                 OnSelectedIndexChanged (EventArgs.Empty);
1187                 }
1188
1189                 internal int TotalWidth {
1190                         get { return Math.Max (this.Width, this.layout_wd); }
1191                 }
1192
1193                 internal int TotalHeight {
1194                         get { return Math.Max (this.Height, this.layout_ht); }
1195                 }
1196
1197                 internal void Redraw (bool recalculate)
1198                 {
1199                         // Avoid calculations when control is being updated
1200                         if (updating)
1201                                 return;
1202 #if NET_2_0
1203                         // VirtualMode doesn't do any calculations until handle is created
1204                         if (virtual_mode && !IsHandleCreated)
1205                                 return;
1206 #endif
1207
1208
1209                         if (recalculate)
1210                                 CalculateListView (this.alignment);
1211
1212                         Invalidate (true);
1213                 }
1214
1215                 void InvalidateSelection ()
1216                 {
1217                         foreach (int selected_index in SelectedIndices)
1218                                 items [selected_index].Invalidate ();
1219                 }
1220
1221                 const int text_padding = 15;
1222
1223                 internal Size GetChildColumnSize (int index)
1224                 {
1225                         Size ret_size = Size.Empty;
1226                         ColumnHeader col = this.columns [index];
1227
1228                         if (col.Width == -2) { // autosize = max(items, columnheader)
1229                                 Size size = Size.Ceiling (TextRenderer.MeasureString
1230                                         (col.Text, this.Font));
1231                                 size.Width += text_padding;
1232                                 ret_size = BiggestItem (index);
1233                                 if (size.Width > ret_size.Width)
1234                                         ret_size = size;
1235                         }
1236                         else { // -1 and all the values < -2 are put under one category
1237                                 ret_size = BiggestItem (index);
1238                                 // fall back to empty columns' width if no subitem is available for a column
1239                                 if (ret_size.IsEmpty) {
1240                                         ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
1241                                         if (col.Text.Length > 0)
1242                                                 ret_size.Height = Size.Ceiling (TextRenderer.MeasureString
1243                                                                                 (col.Text, this.Font)).Height;
1244                                         else
1245                                                 ret_size.Height = this.Font.Height;
1246                                 }
1247                         }
1248
1249                         ret_size.Height += text_padding;
1250
1251                         // adjust the size for icon and checkbox for 0th column
1252                         if (index == 0) {
1253                                 ret_size.Width += (this.CheckBoxSize.Width + 4);
1254                                 if (this.small_image_list != null)
1255                                         ret_size.Width += this.small_image_list.ImageSize.Width;
1256                         }
1257                         return ret_size;
1258                 }
1259
1260                 // Returns the size of biggest item text in a column
1261                 // or the sum of the text and indent count if we are on 2.0
1262                 private Size BiggestItem (int col)
1263                 {
1264                         Size temp = Size.Empty;
1265                         Size ret_size = Size.Empty;
1266 #if NET_2_0
1267                         bool use_indent_count = small_image_list != null;
1268
1269                         // VirtualMode uses the first item text size
1270                         if (virtual_mode && items.Count > 0) {
1271                                 ListViewItem item = items [0];
1272                                 ret_size = Size.Ceiling (TextRenderer.MeasureString (item.SubItems[col].Text,
1273                                                         Font));
1274
1275                                 if (use_indent_count)
1276                                         ret_size.Width += item.IndentCount * small_image_list.ImageSize.Width;
1277                         } else {
1278 #endif
1279                                 // 0th column holds the item text, we check the size of
1280                                 // the various subitems falling in that column and get
1281                                 // the biggest one's size.
1282                                 foreach (ListViewItem item in items) {
1283                                         if (col >= item.SubItems.Count)
1284                                                 continue;
1285
1286                                         temp = Size.Ceiling (TextRenderer.MeasureString
1287                                                                 (item.SubItems [col].Text, Font));
1288
1289 #if NET_2_0
1290                                         if (use_indent_count)
1291                                                 temp.Width += item.IndentCount * small_image_list.ImageSize.Width;
1292 #endif
1293     
1294                                         if (temp.Width > ret_size.Width)
1295                                                 ret_size = temp;
1296                                 }
1297 #if NET_2_0
1298                         }
1299 #endif
1300
1301                         // adjustment for space in Details view
1302                         if (!ret_size.IsEmpty && view == View.Details)
1303                                 ret_size.Width += ThemeEngine.Current.ListViewItemPaddingWidth;
1304
1305                         return ret_size;
1306                 }
1307
1308                 const int max_wrap_padding = 30;
1309
1310                 // Sets the size of the biggest item text as per the view
1311                 private void CalcTextSize ()
1312                 {
1313                         // clear the old value
1314                         text_size = Size.Empty;
1315
1316                         if (items.Count == 0)
1317                                 return;
1318
1319                         text_size = BiggestItem (0);
1320
1321                         if (view == View.LargeIcon && this.label_wrap) {
1322                                 Size temp = Size.Empty;
1323                                 if (this.check_boxes)
1324                                         temp.Width += 2 * this.CheckBoxSize.Width;
1325                                 int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1326                                 temp.Width += icon_w + max_wrap_padding;
1327                                 // wrapping is done for two lines only
1328                                 if (text_size.Width > temp.Width) {
1329                                         text_size.Width = temp.Width;
1330                                         text_size.Height *= 2;
1331                                 }
1332                         }
1333                         else if (view == View.List) {
1334                                 // in list view max text shown in determined by the
1335                                 // control width, even if scolling is enabled.
1336                                 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
1337                                 if (this.small_image_list != null)
1338                                         max_wd -= this.small_image_list.ImageSize.Width;
1339
1340                                 if (text_size.Width > max_wd)
1341                                         text_size.Width = max_wd;
1342                         }
1343
1344                         // we do the default settings, if we have got 0's
1345                         if (text_size.Height <= 0)
1346                                 text_size.Height = this.Font.Height;
1347                         if (text_size.Width <= 0)
1348                                 text_size.Width = this.Width;
1349
1350                         // little adjustment
1351                         text_size.Width += 2;
1352                         text_size.Height += 2;
1353                 }
1354
1355                 private void Scroll (ScrollBar scrollbar, int delta)
1356                 {
1357                         if (delta == 0 || !scrollbar.Visible)
1358                                 return;
1359
1360                         int max;
1361                         if (scrollbar == h_scroll)
1362                                 max = h_scroll.Maximum - item_control.Width;
1363                         else
1364                                 max = v_scroll.Maximum - item_control.Height;
1365
1366                         int val = scrollbar.Value + delta;
1367                         if (val > max)
1368                                 val = max;
1369                         else if (val < scrollbar.Minimum)
1370                                 val = scrollbar.Minimum;
1371                         scrollbar.Value = val;
1372                 }
1373
1374                 private void CalculateScrollBars ()
1375                 {
1376                         Rectangle client_area = ClientRectangle;
1377                         int height = client_area.Height;
1378                         int width = client_area.Width;
1379                         
1380                         if (!scrollable) {
1381                                 h_scroll.Visible = false;
1382                                 v_scroll.Visible = false;
1383                                 item_control.Size = new Size (width, height);
1384                                 header_control.Width = width;
1385                                 return;
1386                         }
1387
1388                         // Don't calculate if the view is not displayable
1389                         if (client_area.Height < 0 || client_area.Width < 0)
1390                                 return;
1391
1392                         // making a scroll bar visible might make
1393                         // other scroll bar visible
1394                         if (layout_wd > client_area.Right) {
1395                                 h_scroll.Visible = true;
1396                                 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
1397                                         v_scroll.Visible = true;
1398                                 else
1399                                         v_scroll.Visible = false;
1400                         } else if (layout_ht > client_area.Bottom) {
1401                                 v_scroll.Visible = true;
1402                                 if ((layout_wd + v_scroll.Width) > client_area.Right)
1403                                         h_scroll.Visible = true;
1404                                 else
1405                                         h_scroll.Visible = false;
1406                         } else {
1407                                 h_scroll.Visible = false;
1408                                 v_scroll.Visible = false;
1409                         }
1410
1411
1412                         if (h_scroll.is_visible) {
1413                                 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
1414                                 h_scroll.Minimum = 0;
1415
1416                                 // if v_scroll is visible, adjust the maximum of the
1417                                 // h_scroll to account for the width of v_scroll
1418                                 if (v_scroll.Visible) {
1419                                         h_scroll.Maximum = layout_wd + v_scroll.Width;
1420                                         h_scroll.Width = client_area.Width - v_scroll.Width;
1421                                 }
1422                                 else {
1423                                         h_scroll.Maximum = layout_wd;
1424                                         h_scroll.Width = client_area.Width;
1425                                 }
1426
1427                                 h_scroll.LargeChange = client_area.Width;
1428                                 h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing;
1429                                 height -= h_scroll.Height;
1430                         }
1431
1432                         if (v_scroll.is_visible) {
1433                                 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
1434                                 v_scroll.Minimum = 0;
1435                                 v_scroll.Maximum = layout_ht;
1436
1437                                 // if h_scroll is visible, adjust the height of
1438                                 // v_scroll to account for the height of h_scroll
1439                                 if (h_scroll.Visible)
1440                                         v_scroll.Height = client_area.Height - h_scroll.Height;
1441                                 else
1442                                         v_scroll.Height = client_area.Height;
1443
1444                                 v_scroll.LargeChange = client_area.Height;
1445                                 v_scroll.SmallChange = Font.Height;
1446                                 width -= v_scroll.Width;
1447                         }
1448                         
1449                         item_control.Size = new Size (width, height);
1450
1451                         if (header_control.is_visible)
1452                                 header_control.Width = width;
1453                 }
1454
1455 #if NET_2_0
1456                 internal int GetReorderedColumnIndex (ColumnHeader column)
1457                 {
1458                         if (reordered_column_indices == null)
1459                                 return column.Index;
1460
1461                         for (int i = 0; i < Columns.Count; i++)
1462                                 if (reordered_column_indices [i] == column.Index)
1463                                         return i;
1464
1465                         return -1;
1466                 }
1467 #endif
1468
1469                 internal ColumnHeader GetReorderedColumn (int index)
1470                 {
1471                         if (reordered_column_indices == null)
1472                                 return Columns [index];
1473                         else
1474                                 return Columns [reordered_column_indices [index]];
1475                 }
1476
1477                 internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent)
1478                 {
1479 #if NET_2_0
1480                         if (fireEvent) {
1481                                 ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
1482                                 if (eh != null){
1483                                         ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
1484
1485                                         eh (this, args);
1486                                         if (args.Cancel) {
1487                                                 header_control.Invalidate ();
1488                                                 item_control.Invalidate ();
1489                                                 return;
1490                                         }
1491                                 }
1492                         }
1493 #endif
1494                         int column_count = Columns.Count;
1495
1496                         if (reordered_column_indices == null) {
1497                                 reordered_column_indices = new int [column_count];
1498                                 for (int i = 0; i < column_count; i++)
1499                                         reordered_column_indices [i] = i;
1500                         }
1501
1502                         if (reordered_column_indices [index] == col.Index)
1503                                 return;
1504
1505                         int[] curr = reordered_column_indices;
1506                         int [] result = new int [column_count];
1507                         int curr_idx = 0;
1508                         for (int i = 0; i < column_count; i++) {
1509                                 if (curr_idx < column_count && curr [curr_idx] == col.Index)
1510                                         curr_idx++;
1511
1512                                 if (i == index)
1513                                         result [i] = col.Index;
1514                                 else
1515                                         result [i] = curr [curr_idx++];
1516                         }
1517
1518                         ReorderColumns (result, true);
1519                 }
1520
1521                 internal void ReorderColumns (int [] display_indices, bool redraw)
1522                 {
1523                         reordered_column_indices = display_indices;
1524                         for (int i = 0; i < Columns.Count; i++) {
1525                                 ColumnHeader col = Columns [i];
1526                                 col.InternalDisplayIndex = reordered_column_indices [i];
1527                         }
1528                         if (redraw && view == View.Details && IsHandleCreated) {
1529                                 LayoutDetails ();
1530                                 header_control.Invalidate ();
1531                                 item_control.Invalidate ();
1532                         }
1533                 }
1534
1535                 internal void AddColumn (ColumnHeader newCol, int index, bool redraw)
1536                 {
1537                         int column_count = Columns.Count;
1538                         newCol.SetListView (this);
1539
1540                         int [] display_indices = new int [column_count];
1541                         for (int i = 0; i < column_count; i++) {
1542                                 ColumnHeader col = Columns [i];
1543                                 if (i == index) {
1544                                         display_indices [i] = index;
1545                                 } else {
1546                                         int display_index = col.InternalDisplayIndex;
1547                                         if (display_index < index) {
1548                                                 display_indices [i] = display_index;
1549                                         } else {
1550                                                 display_indices [i] = (display_index + 1);
1551                                         }
1552                                 }
1553                         }
1554
1555                         ReorderColumns (display_indices, redraw);
1556                         Invalidate ();
1557                 }
1558
1559                 Size LargeIconItemSize
1560                 {
1561                         get {
1562                                 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1563                                 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
1564                                 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
1565                                 int w = Math.Max (text_size.Width, image_w);
1566
1567                                 if (check_boxes)
1568                                         w += 2 + CheckBoxSize.Width;
1569
1570                                 return new Size (w, h);
1571                         }
1572                 }
1573
1574                 Size SmallIconItemSize {
1575                         get {
1576                                 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
1577                                 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1578                                 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
1579                                 int w = text_size.Width + image_w;
1580
1581                                 if (check_boxes)
1582                                         w += 2 + CheckBoxSize.Width;
1583
1584                                 return new Size (w, h);
1585                         }
1586                 }
1587
1588 #if NET_2_0
1589                 Size TileItemSize {
1590                         get {
1591                                 // Calculate tile size if needed
1592                                 // It appears that using Font.Size instead of a SizeF value can give us
1593                                 // a slightly better approach to the proportions defined in .Net
1594                                 if (tile_size == Size.Empty) {
1595                                         int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
1596                                         int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
1597                                         int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
1598                                         int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
1599                                 
1600                                         tile_size = new Size (w, h);
1601                                 }
1602                         
1603                                 return tile_size;
1604                         }
1605                 }
1606 #endif
1607
1608                 int GetDetailsItemHeight ()
1609                 {
1610                         int item_height;
1611                         int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
1612                         int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1613                         item_height = Math.Max (checkbox_height, text_size.Height);
1614                         item_height = Math.Max (item_height, small_image_height);
1615                         return item_height;
1616                 }
1617
1618                 void SetItemLocation (int index, int x, int y, int row, int col)
1619                 {
1620                         Point old_location = items_location [index];
1621                         if (old_location.X == x && old_location.Y == y)
1622                                 return;
1623
1624                         items_location [index] = new Point (x, y);
1625                         items_matrix_location [index] = new ItemMatrixLocation (row, col);
1626
1627                         //
1628                         // Initial position matches item's position in ListViewItemCollection
1629                         //
1630                         reordered_items_indices [index] = index;
1631                 }
1632
1633 #if NET_2_0
1634                 void ShiftItemsPositions (int from, int to, bool forward)
1635                 {
1636                         if (forward) {
1637                                 for (int i = to + 1; i > from; i--) {
1638                                         reordered_items_indices [i] = reordered_items_indices [i - 1];
1639
1640                                         ListViewItem item = items [reordered_items_indices [i]];
1641                                         item.Invalidate ();
1642                                         item.DisplayIndex = i;
1643                                         item.Invalidate ();
1644                                 }
1645                         } else {
1646                                 for (int i = from - 1; i < to; i++) {
1647                                         reordered_items_indices [i] = reordered_items_indices [i + 1];
1648
1649                                         ListViewItem item = items [reordered_items_indices [i]];
1650                                         item.Invalidate ();
1651                                         item.DisplayIndex = i;
1652                                         item.Invalidate ();
1653                                 }
1654                         }
1655                 }
1656
1657                 internal void ChangeItemLocation (int display_index, Point new_pos)
1658                 {
1659                         int new_display_index = GetDisplayIndexFromLocation (new_pos);
1660                         if (new_display_index == display_index)
1661                                 return;
1662
1663                         int item_index = reordered_items_indices [display_index];
1664                         ListViewItem item = items [item_index];
1665
1666                         bool forward = new_display_index < display_index;
1667                         int index_from, index_to;
1668                         if (forward) {
1669                                 index_from = new_display_index;
1670                                 index_to = display_index - 1;
1671                         } else {
1672                                 index_from = display_index + 1;
1673                                 index_to = new_display_index;
1674                         }
1675
1676                         ShiftItemsPositions (index_from, index_to, forward);
1677
1678                         reordered_items_indices [new_display_index] = item_index;
1679
1680                         item.Invalidate ();
1681                         item.DisplayIndex = new_display_index;
1682                         item.Invalidate ();
1683                 }
1684
1685                 int GetDisplayIndexFromLocation (Point loc)
1686                 {
1687                         int display_index = -1;
1688                         Rectangle item_area;
1689
1690                         // First item
1691                         if (loc.X < 0 || loc.Y < 0)
1692                                 return 0;
1693
1694                         // Adjustment to put in the next position refered by 'loc'
1695                         loc.X -= item_size.Width / 2;
1696                         if (loc.X < 0)
1697                                 loc.X = 0;
1698
1699                         for (int i = 0; i < items.Count; i++) {
1700                                 item_area = new Rectangle (GetItemLocation (i), item_size);
1701                                 item_area.Inflate (ThemeEngine.Current.ListViewHorizontalSpacing,
1702                                                 ThemeEngine.Current.ListViewVerticalSpacing);
1703
1704                                 if (item_area.Contains (loc)) {
1705                                         display_index = i;
1706                                         break;
1707                                 }
1708                         }
1709
1710                         // Put in in last position
1711                         if (display_index == -1)
1712                                 display_index = items.Count - 1;
1713
1714                         return display_index;
1715                 }
1716
1717                 // When using groups, the items with no group assigned
1718                 // belong to the DefaultGroup
1719                 int GetDefaultGroupItems ()
1720                 {
1721                         int count = 0;
1722                         foreach (ListViewItem item in items)
1723                                 if (item.Group == null)
1724                                         count++;
1725
1726                         return count;
1727                 }
1728 #endif
1729
1730 #if NET_2_0
1731                 // cache the spacing to let virtualmode compute the positions on the fly
1732                 int x_spacing;
1733                 int y_spacing;
1734 #endif
1735                 int rows;
1736                 int cols;
1737                 int[,] item_index_matrix;
1738
1739                 void CalculateRowsAndCols (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1740                 {
1741                         Rectangle area = ClientRectangle;
1742
1743                         if (UseCustomColumnWidth)
1744                                 CalculateCustomColumnWidth ();
1745 #if NET_2_0
1746                         if (UsingGroups) {
1747                                 // When groups are used the alignment is always top-aligned
1748                                 rows = 0;
1749                                 cols = 0;
1750                                 int items = 0;
1751
1752                                 groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1753                                 for (int i = 0; i < groups.InternalCount; i++) {
1754                                         ListViewGroup group = groups.GetInternalGroup (i);
1755                                         int items_in_group = group.GetActualItemCount ();
1756
1757                                         if (items_in_group == 0)
1758                                                 continue;
1759
1760                                         int group_cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1761                                         if (group_cols <= 0)
1762                                                 group_cols = 1;
1763                                         int group_rows = (int) Math.Ceiling ((double)items_in_group / (double)group_cols);
1764
1765                                         group.starting_row = rows;
1766                                         group.rows = group_rows;
1767                                         group.starting_item = items;
1768                                         group.current_item = 0; // Reset layout
1769
1770                                         cols = Math.Max (group_cols, cols);
1771                                         rows += group_rows;
1772                                         items += items_in_group;
1773                                 }
1774                         } else
1775 #endif
1776                         {
1777                                 // Simple matrix if no groups are used
1778                                 if (left_aligned) {
1779                                         rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(item_size.Height + y_spacing));
1780                                         if (rows <= 0)
1781                                                 rows = 1;
1782                                         cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
1783                                 } else {
1784                                         if (UseCustomColumnWidth)
1785                                                 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width) / (double)(custom_column_width));
1786                                         else
1787                                                 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1788
1789                                         if (cols < 1)
1790                                                 cols = 1;
1791
1792                                         rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
1793                                 }
1794                         }
1795
1796                         item_index_matrix = new int [rows, cols];
1797                 }
1798
1799                 // When using custom column width, we look for the minimum one
1800                 void CalculateCustomColumnWidth ()
1801                 {
1802                         int min_width = Int32.MaxValue;
1803                         for (int i = 0; i < columns.Count; i++) {
1804                                 int col_width = columns [i].Width;
1805
1806                                 if (col_width < min_width)
1807                                         min_width = col_width;
1808                         }
1809
1810                         custom_column_width = min_width;
1811                 }
1812
1813                 void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1814                 {
1815                         header_control.Visible = false;
1816                         header_control.Size = Size.Empty;
1817                         item_control.Visible = true;
1818                         item_control.Location = Point.Empty;
1819                         ItemSize = item_size; // Cache item size
1820 #if NET_2_0
1821                         this.x_spacing = x_spacing;
1822                         this.y_spacing = y_spacing;
1823 #endif
1824
1825                         if (items.Count == 0)
1826                                 return;
1827
1828                         Size sz = item_size;
1829
1830                         CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing);
1831
1832                         layout_wd = UseCustomColumnWidth ? cols * custom_column_width : cols * (sz.Width + x_spacing) - x_spacing;
1833                         layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
1834
1835 #if NET_2_0
1836                         if (virtual_mode) { // no actual assignment is needed on items for virtual mode
1837                                 item_control.Size = new Size (layout_wd, layout_ht);
1838                                 return;
1839                         }
1840
1841                         bool using_groups = UsingGroups;
1842                         if (using_groups) // the groups layout will override layout_ht
1843                                 CalculateGroupsLayout (sz, y_spacing, 0);
1844 #endif
1845
1846                         int row = 0, col = 0;
1847                         int x = 0, y = 0;
1848                         int display_index = 0;
1849
1850                         for (int i = 0; i < items.Count; i++) {
1851                                 ListViewItem item = items [i];
1852 #if NET_2_0
1853                                 if (using_groups) {
1854                                         ListViewGroup group = item.Group;
1855                                         if (group == null)
1856                                                 group = groups.DefaultGroup;
1857
1858                                         Point group_items_loc = group.items_area_location;
1859                                         int current_item = group.current_item++;
1860                                         int starting_row = group.starting_row;
1861
1862                                         display_index = group.starting_item + current_item;
1863                                         row = (current_item / cols);
1864                                         col = current_item % cols;
1865
1866                                         x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
1867                                         y = row * (item_size.Height + y_spacing) + group_items_loc.Y;
1868
1869                                         SetItemLocation (display_index, x, y, row + starting_row, col);
1870                                         SetItemAtDisplayIndex (display_index, i);
1871                                         item_index_matrix [row + starting_row, col] = i;
1872
1873                                 } else
1874 #endif
1875                                 {
1876                                         x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
1877                                         y = row * (item_size.Height + y_spacing);
1878                                         display_index = i; // Same as item index in Items
1879
1880                                         SetItemLocation (i, x, y, row, col);
1881                                         item_index_matrix [row, col] = i;
1882
1883                                         if (left_aligned) {
1884                                                 row++;
1885                                                 if (row == rows) {
1886                                                         row = 0;
1887                                                         col++;
1888                                                 }
1889                                         } else {
1890                                                 if (++col == cols) {
1891                                                         col = 0;
1892                                                         row++;
1893                                                 }
1894                                         }
1895                                 }
1896
1897                                 item.Layout ();
1898                                 item.DisplayIndex = display_index;
1899 #if NET_2_0                                     
1900                                 item.SetPosition (new Point (x, y));
1901 #endif                                  
1902                         }
1903
1904                         item_control.Size = new Size (layout_wd, layout_ht);
1905                 }
1906
1907 #if NET_2_0
1908                 void CalculateGroupsLayout (Size item_size, int y_spacing, int y_origin)
1909                 {
1910                         int y = y_origin;
1911                         bool details = view == View.Details;
1912
1913                         for (int i = 0; i < groups.InternalCount; i++) {
1914                                 ListViewGroup group = groups.GetInternalGroup (i);
1915                                 if (group.ItemCount == 0)
1916                                         continue;
1917
1918                                 y += LayoutGroupHeader (group, y, item_size.Height, y_spacing, details ? group.ItemCount : group.rows);
1919                         }
1920
1921                         layout_ht = y; // Update height taking into account Groups' headers heights
1922                 }
1923
1924                 int LayoutGroupHeader (ListViewGroup group, int y_origin, int item_height, int y_spacing, int rows)
1925                 {
1926                         Rectangle client_area = ClientRectangle;
1927                         int header_height = Font.Height + 15; // one line height + some padding
1928
1929                         group.HeaderBounds = new Rectangle (0, y_origin, client_area.Width - v_scroll.Width, header_height);
1930                         group.items_area_location = new Point (0, y_origin + header_height);
1931
1932                         int items_area_height = ((item_height + y_spacing) * rows);
1933                         return header_height + items_area_height + 10; // Add a small bottom margin
1934                 }
1935
1936                 void CalculateDetailsGroupItemsCount ()
1937                 {
1938                         int items = 0;
1939
1940                         groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1941                         for (int i = 0; i < groups.InternalCount; i++) {
1942                                 ListViewGroup group = groups.GetInternalGroup (i);
1943                                 int items_in_group = group.GetActualItemCount ();
1944
1945                                 if (items_in_group == 0)
1946                                         continue;
1947
1948                                 group.starting_item = items;
1949                                 group.current_item = 0; // Reset layout.
1950                                 items += items_in_group;
1951                         }
1952                 }
1953 #endif
1954
1955                 void LayoutHeader ()
1956                 {
1957                         int x = 0;
1958                         for (int i = 0; i < Columns.Count; i++) {
1959                                 ColumnHeader col = GetReorderedColumn (i);
1960                                 col.X = x;
1961                                 col.Y = 0;
1962                                 col.CalcColumnHeader ();
1963                                 x += col.Wd;
1964                         }
1965
1966                         layout_wd = x;
1967
1968                         if (x < ClientRectangle.Width)
1969                                 x = ClientRectangle.Width;
1970
1971                         if (header_style == ColumnHeaderStyle.None) {
1972                                 header_control.Visible = false;
1973                                 header_control.Size = Size.Empty;
1974                                 layout_wd = ClientRectangle.Width;
1975                         } else {
1976                                 header_control.Width = x;
1977                                 header_control.Height = columns.Count > 0 ? columns [0].Ht : ThemeEngine.Current.ListViewGetHeaderHeight (this, Font);
1978                                 header_control.Visible = true;
1979                         }
1980                 }
1981
1982                 void LayoutDetails ()
1983                 {
1984                         LayoutHeader ();
1985
1986                         if (columns.Count == 0) {
1987                                 item_control.Visible = false;
1988                                 layout_wd = ClientRectangle.Width;
1989                                 layout_ht = ClientRectangle.Height;
1990                                 return;
1991                         }
1992
1993                         item_control.Visible = true;
1994                         item_control.Location = Point.Empty;
1995                         item_control.Width = ClientRectangle.Width;
1996
1997                         int item_height = GetDetailsItemHeight ();
1998                         ItemSize = new Size (0, item_height); // We only cache Height for details view
1999                         int y = header_control.Height;
2000                         layout_ht = y + (item_height * items.Count);
2001                         if (items.Count > 0 && grid_lines) // some space for bottom gridline
2002                                 layout_ht += 2;
2003
2004 #if NET_2_0
2005                         bool using_groups = UsingGroups;
2006                         if (using_groups) {
2007                                 // Observe that this routines will override our layout_ht value
2008                                 CalculateDetailsGroupItemsCount ();
2009                                 CalculateGroupsLayout (ItemSize, 2, y);
2010                         }
2011
2012                         if (virtual_mode) // no assgination on items is needed
2013                                 return;
2014 #endif
2015
2016                         for (int i = 0; i < items.Count; i++) {
2017                                 ListViewItem item = items [i];
2018
2019                                 int display_index;
2020                                 int item_y;
2021
2022 #if NET_2_0
2023                                 if (using_groups) {
2024                                         ListViewGroup group = item.Group;
2025                                         if (group == null)
2026                                                 group = groups.DefaultGroup;
2027
2028                                         int current_item = group.current_item++;
2029                                         Point group_items_loc = group.items_area_location;
2030                                         display_index = group.starting_item + current_item;
2031
2032                                         y = item_y = current_item * (item_height + 2) + group_items_loc.Y;
2033                                         SetItemLocation (display_index, 0, item_y, 0, 0);
2034                                         SetItemAtDisplayIndex (display_index, i);
2035                                 } else
2036 #endif
2037                                 {
2038                                         display_index = i;
2039                                         item_y = y;
2040                                         SetItemLocation (i, 0, item_y, 0, 0);
2041                                         y += item_height;
2042                                 }
2043
2044                                 item.Layout ();
2045                                 item.DisplayIndex = display_index;
2046 #if NET_2_0                                     
2047                                 item.SetPosition (new Point (0, item_y));
2048 #endif                                  
2049                         }
2050                 }
2051
2052                 private void AdjustItemsPositionArray (int count)
2053                 {
2054 #if  NET_2_0
2055                         // In virtual mode we compute the positions on the fly.
2056                         if (virtual_mode)
2057                                 return;
2058 #endif
2059                         if (items_location.Length >= count)
2060                                 return;
2061
2062                         // items_location, items_matrix_location and reordered_items_indices must keep the same length
2063                         count = Math.Max (count, items_location.Length * 2);
2064                         items_location = new Point [count];
2065                         items_matrix_location = new ItemMatrixLocation [count];
2066                         reordered_items_indices = new int [count];
2067                 }
2068
2069                 private void CalculateListView (ListViewAlignment align)
2070                 {
2071                         CalcTextSize ();
2072
2073                         AdjustItemsPositionArray (items.Count);
2074
2075                         switch (view) {
2076                         case View.Details:
2077                                 LayoutDetails ();
2078                                 break;
2079
2080                         case View.SmallIcon:
2081                                 LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left, 
2082                                                 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
2083                                 break;
2084
2085                         case View.LargeIcon:
2086                                 LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
2087                                         ThemeEngine.Current.ListViewHorizontalSpacing,
2088                                         ThemeEngine.Current.ListViewVerticalSpacing);
2089                                 break;
2090
2091                         case View.List:
2092                                 LayoutIcons (SmallIconItemSize, true, 
2093                                                 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
2094                                 break;
2095 #if NET_2_0
2096                         case View.Tile:
2097                                 if (!Application.VisualStylesEnabled)
2098                                         goto case View.LargeIcon;
2099
2100                                 LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left, 
2101                                                 ThemeEngine.Current.ListViewHorizontalSpacing,
2102                                                 ThemeEngine.Current.ListViewVerticalSpacing);
2103                                 break;
2104 #endif
2105                         }
2106
2107                         CalculateScrollBars ();
2108                 }
2109
2110                 internal Point GetItemLocation (int index)
2111                 {
2112                         Point loc = Point.Empty;
2113 #if NET_2_0
2114                         if (virtual_mode)
2115                                 loc = GetFixedItemLocation (index);
2116                         else
2117 #endif
2118                                 loc = items_location [index];
2119
2120                         loc.X -= h_marker; // Adjust to scroll
2121                         loc.Y -= v_marker;
2122
2123                         return loc;
2124                 }
2125
2126 #if NET_2_0
2127                 Point GetFixedItemLocation (int index)
2128                 {
2129                         Point loc = Point.Empty;
2130
2131                         switch (view) {
2132                                 case View.LargeIcon:
2133                                 case View.SmallIcon:
2134                                         loc.X = index % cols * (item_size.Width + x_spacing);
2135                                         loc.Y = index / cols * (item_size.Height + y_spacing);
2136                                         break;
2137                                 case View.List:
2138                                         loc.X = index / rows * (item_size.Width + x_spacing);
2139                                         loc.Y = index % rows * (item_size.Height + y_spacing);
2140                                         break;
2141                                 case View.Details:
2142                                         loc.Y = header_control.Height + (index * item_size.Height);
2143                                         break;
2144                         }
2145
2146                         return loc;
2147                 }
2148 #endif
2149
2150                 internal int GetItemIndex (int display_index)
2151                 {
2152 #if NET_2_0
2153                         if (virtual_mode)
2154                                 return display_index; // no reordering in virtual mode.
2155 #endif
2156                         return reordered_items_indices [display_index];
2157                 }
2158
2159                 internal ListViewItem GetItemAtDisplayIndex (int display_index)
2160                 {
2161 #if NET_2_0
2162                         // in virtual mode there's no reordering at all.
2163                         if (virtual_mode)
2164                                 return items [display_index];
2165 #endif
2166                         return items [reordered_items_indices [display_index]];
2167                 }
2168
2169                 internal void SetItemAtDisplayIndex (int display_index, int index)
2170                 {
2171                         reordered_items_indices [display_index] = index;
2172                 }
2173
2174                 private bool KeySearchString (KeyEventArgs ke)
2175                 {
2176                         int current_tickcnt = Environment.TickCount;
2177                         if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
2178                                 keysearch_text = string.Empty;
2179                         }
2180                         
2181                         if (!Char.IsLetterOrDigit ((char)ke.KeyCode))
2182                                 return false;
2183
2184                         keysearch_text += (char)ke.KeyCode;
2185                         keysearch_tickcnt = current_tickcnt;
2186
2187                         int prev_focused = FocusedItem == null ? 0 : FocusedItem.DisplayIndex;
2188                         int start = prev_focused + 1 < Items.Count ? prev_focused + 1 : 0;
2189
2190                         ListViewItem item = FindItemWithText (keysearch_text, false, start, true, true);
2191                         if (item != null && prev_focused != item.DisplayIndex) {
2192                                 selected_indices.Clear ();
2193
2194                                 SetFocusedItem (item.DisplayIndex);
2195                                 item.Selected = true;
2196                                 EnsureVisible (GetItemIndex (item.DisplayIndex));
2197                         }
2198
2199                         return true;
2200                 }
2201
2202                 private void OnItemsChanged ()
2203                 {
2204                         ResetSearchString ();
2205                 }
2206
2207                 private void ResetSearchString ()
2208                 {
2209                         keysearch_text = String.Empty;
2210                 }
2211
2212                 int GetAdjustedIndex (Keys key)
2213                 {
2214                         int result = -1;
2215
2216                         if (View == View.Details) {
2217                                 switch (key) {
2218                                 case Keys.Up:
2219                                         result = FocusedItem.DisplayIndex - 1;
2220                                         break;
2221                                 case Keys.Down:
2222                                         result = FocusedItem.DisplayIndex + 1;
2223                                         if (result == items.Count)
2224                                                 result = -1;
2225                                         break;
2226                                 case Keys.PageDown:
2227                                         int last_index = LastVisibleIndex;
2228                                         Rectangle item_rect = new Rectangle (GetItemLocation (last_index), ItemSize);
2229                                         if (item_rect.Bottom > item_control.ClientRectangle.Bottom)
2230                                                 last_index--;
2231                                         if (FocusedItem.DisplayIndex == last_index) {
2232                                                 if (FocusedItem.DisplayIndex < Items.Count - 1) {
2233                                                         int page_size = item_control.Height / ItemSize.Height - 1;
2234                                                         result = FocusedItem.DisplayIndex + page_size - 1;
2235                                                         if (result >= Items.Count)
2236                                                                 result = Items.Count - 1;
2237                                                 }
2238                                         } else
2239                                                 result = last_index;
2240                                         break;
2241                                 case Keys.PageUp:
2242                                         int first_index = FirstVisibleIndex;
2243                                         if (GetItemLocation (first_index).Y < 0)
2244                                                 first_index++;
2245                                         if (FocusedItem.DisplayIndex == first_index) {
2246                                                 if (first_index > 0) {
2247                                                         int page_size = item_control.Height / ItemSize.Height - 1;
2248                                                         result = first_index - page_size + 1;
2249                                                         if (result < 0)
2250                                                                 result = 0;
2251                                                 }
2252                                         } else
2253                                                 result = first_index;
2254                                         break;
2255                                 }
2256                                 return result;
2257                         }
2258
2259                         ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.DisplayIndex];
2260                         int row = item_matrix_location.Row;
2261                         int col = item_matrix_location.Col;
2262
2263                         int adjusted_index = -1;
2264
2265                         switch (key) {
2266                         case Keys.Left:
2267                                 if (col == 0)
2268                                         return -1;
2269                                 adjusted_index = item_index_matrix [row, col - 1];
2270                                 break;
2271
2272                         case Keys.Right:
2273                                 if (col == (cols - 1))
2274                                         return -1;
2275                                 while (item_index_matrix [row, col + 1] == 0) {
2276                                         row--;
2277                                         if (row < 0)
2278                                                 return -1;
2279                                 }
2280                                 adjusted_index = item_index_matrix [row, col + 1];
2281                                 break;
2282
2283                         case Keys.Up:
2284                                 if (row == 0)
2285                                         return -1;
2286                                 while (item_index_matrix [row - 1, col] == 0 && row != 1) {
2287                                         col--;
2288                                         if (col < 0)
2289                                                 return -1;
2290                                 }
2291                                 adjusted_index = item_index_matrix [row - 1, col];
2292                                 break;
2293
2294                         case Keys.Down:
2295                                 if (row == (rows - 1) || row == Items.Count - 1)
2296                                         return -1;
2297                                 while (item_index_matrix [row + 1, col] == 0) {
2298                                         col--;
2299                                         if (col < 0)
2300                                                 return -1;
2301                                 }
2302                                 adjusted_index = item_index_matrix [row + 1, col];
2303                                 break;
2304
2305                         default:
2306                                 return -1;
2307                         }
2308
2309                         return items [adjusted_index].DisplayIndex;
2310                 }
2311
2312                 ListViewItem selection_start;
2313
2314                 private bool SelectItems (ArrayList sel_items)
2315                 {
2316                         bool changed = false;
2317                         foreach (ListViewItem item in SelectedItems)
2318                                 if (!sel_items.Contains (item)) {
2319                                         item.Selected = false;
2320                                         changed = true;
2321                                 }
2322                         foreach (ListViewItem item in sel_items)
2323                                 if (!item.Selected) {
2324                                         item.Selected = true;
2325                                         changed = true;
2326                                 }
2327                         return changed;
2328                 }
2329
2330                 private void UpdateMultiSelection (int index, bool reselect)
2331                 {
2332                         bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
2333                         bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
2334                         ListViewItem item = GetItemAtDisplayIndex (index);
2335
2336                         if (shift_pressed && selection_start != null) {
2337                                 ArrayList list = new ArrayList ();
2338                                 int start_index = selection_start.DisplayIndex;
2339                                 int start = Math.Min (start_index, index);
2340                                 int end = Math.Max (start_index, index);
2341                                 if (View == View.Details) {
2342                                         for (int i = start; i <= end; i++)
2343                                                 list.Add (GetItemAtDisplayIndex (i));
2344                                 } else {
2345                                         ItemMatrixLocation start_item_matrix_location = items_matrix_location [start];
2346                                         ItemMatrixLocation end_item_matrix_location = items_matrix_location [end];
2347                                         int left = Math.Min (start_item_matrix_location.Col, end_item_matrix_location.Col);
2348                                         int right = Math.Max (start_item_matrix_location.Col, end_item_matrix_location.Col);
2349                                         int top = Math.Min (start_item_matrix_location.Row, end_item_matrix_location.Row);
2350                                         int bottom = Math.Max (start_item_matrix_location.Row, end_item_matrix_location.Row);
2351
2352                                         for (int i = 0; i < items.Count; i++) {
2353                                                 ItemMatrixLocation item_matrix_loc = items_matrix_location [i];
2354
2355                                                 if (item_matrix_loc.Row >= top && item_matrix_loc.Row <= bottom &&
2356                                                                 item_matrix_loc.Col >= left && item_matrix_loc.Col <= right)
2357                                                         list.Add (GetItemAtDisplayIndex (i));
2358                                         }
2359                                 }
2360                                 SelectItems (list);
2361                         } else if (ctrl_pressed) {
2362                                 item.Selected = !item.Selected;
2363                                 selection_start = item;
2364                         } else {
2365                                 if (!reselect) {
2366                                         // do not unselect, and reselect the item
2367                                         foreach (int itemIndex in SelectedIndices) {
2368                                                 if (index == itemIndex)
2369                                                         continue;
2370                                                 items [itemIndex].Selected = false;
2371                                         }
2372                                 } else {
2373                                         SelectedItems.Clear ();
2374                                         item.Selected = true;
2375                                 }
2376                                 selection_start = item;
2377                         }
2378                 }
2379
2380                 internal override bool InternalPreProcessMessage (ref Message msg)
2381                 {
2382                         if (msg.Msg == (int)Msg.WM_KEYDOWN) {
2383                                 Keys key_data = (Keys)msg.WParam.ToInt32();
2384                                 
2385                                 HandleNavKeys (key_data);
2386                         } 
2387                         
2388                         return base.InternalPreProcessMessage (ref msg);
2389                 }
2390
2391                 bool HandleNavKeys (Keys key_data)
2392                 {
2393                         if (Items.Count == 0 || !item_control.Visible)
2394                                 return false;
2395
2396                         if (FocusedItem == null)
2397                                 SetFocusedItem (0);
2398
2399                         switch (key_data) {
2400                         case Keys.End:
2401                                 SelectIndex (Items.Count - 1);
2402                                 break;
2403
2404                         case Keys.Home:
2405                                 SelectIndex (0);
2406                                 break;
2407
2408                         case Keys.Left:
2409                         case Keys.Right:
2410                         case Keys.Up:
2411                         case Keys.Down:
2412                         case Keys.PageUp:
2413                         case Keys.PageDown:
2414                                 SelectIndex (GetAdjustedIndex (key_data));
2415                                 break;
2416
2417                         case Keys.Space:
2418                                 SelectIndex (focused_item_index);
2419                                 ToggleItemsCheckState ();
2420                                 break;
2421                         case Keys.Enter:
2422                                 if (selected_indices.Count > 0)
2423                                         OnItemActivate (EventArgs.Empty);
2424                                 break;
2425
2426                         default:
2427                                 return false;
2428                         }
2429
2430                         return true;
2431                 }
2432
2433                 void ToggleItemsCheckState ()
2434                 {
2435                         if (!CheckBoxes)
2436                                 return;
2437
2438                         // Don't modify check state if StateImageList has less than 2 elements
2439                         if (StateImageList != null && StateImageList.Images.Count < 2)
2440                                 return;
2441
2442                         if (SelectedIndices.Count > 0) {
2443                                 for (int i = 0; i < SelectedIndices.Count; i++) {
2444                                         ListViewItem item = Items [SelectedIndices [i]];
2445                                         item.Checked = !item.Checked;
2446                                 }
2447                                 return;
2448                         } 
2449                         
2450                         if (FocusedItem != null) {
2451                                 FocusedItem.Checked = !FocusedItem.Checked;
2452                                 SelectIndex (FocusedItem.Index);
2453                         }
2454                 }
2455
2456                 void SelectIndex (int display_index)
2457                 {
2458                         if (display_index == -1)
2459                                 return;
2460
2461                         if (MultiSelect)
2462                                 UpdateMultiSelection (display_index, true);
2463                         else if (!GetItemAtDisplayIndex (display_index).Selected)
2464                                 GetItemAtDisplayIndex (display_index).Selected = true;
2465
2466                         SetFocusedItem (display_index);
2467                         EnsureVisible (GetItemIndex (display_index)); // Index in Items collection, not display index
2468                 }
2469
2470                 private void ListView_KeyDown (object sender, KeyEventArgs ke)
2471                 {
2472                         if (ke.Handled || Items.Count == 0 || !item_control.Visible)
2473                                 return;
2474
2475                         if (ke.Alt || ke.Control)
2476                                 return;
2477                                 
2478                         ke.Handled = KeySearchString (ke);
2479                 }
2480
2481                 private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
2482                 {
2483                         Point loc = PointToClient (Control.MousePosition);
2484                         return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
2485                 }
2486
2487                 internal class ItemControl : Control {
2488
2489                         ListView owner;
2490                         ListViewItem clicked_item;
2491                         ListViewItem last_clicked_item;
2492                         bool hover_processed = false;
2493                         bool checking = false;
2494                         ListViewItem prev_hovered_item;
2495 #if NET_2_0
2496                         ListViewItem prev_tooltip_item;
2497 #endif
2498                         int clicks;
2499                         Point drag_begin = new Point (-1, -1);
2500                         internal int dragged_item_index = -1;
2501                         
2502                         ListViewLabelEditTextBox edit_text_box;
2503                         internal ListViewItem edit_item;
2504                         LabelEditEventArgs edit_args;
2505
2506                         public ItemControl (ListView owner)
2507                         {
2508                                 this.owner = owner;
2509                                 this.SetStyle (ControlStyles.DoubleBuffer, true);
2510                                 DoubleClick += new EventHandler(ItemsDoubleClick);
2511                                 MouseDown += new MouseEventHandler(ItemsMouseDown);
2512                                 MouseMove += new MouseEventHandler(ItemsMouseMove);
2513                                 MouseHover += new EventHandler(ItemsMouseHover);
2514                                 MouseUp += new MouseEventHandler(ItemsMouseUp);
2515                         }
2516
2517                         void ItemsDoubleClick (object sender, EventArgs e)
2518                         {
2519                                 if (owner.activation == ItemActivation.Standard)
2520                                         owner.OnItemActivate (EventArgs.Empty);
2521                         }
2522
2523                         enum BoxSelect {
2524                                 None,
2525                                 Normal,
2526                                 Shift,
2527                                 Control
2528                         }
2529
2530                         BoxSelect box_select_mode = BoxSelect.None;
2531                         IList prev_selection;
2532                         Point box_select_start;
2533
2534                         Rectangle box_select_rect;
2535                         internal Rectangle BoxSelectRectangle {
2536                                 get { return box_select_rect; }
2537                                 set {
2538                                         if (box_select_rect == value)
2539                                                 return;
2540
2541                                         InvalidateBoxSelectRect ();
2542                                         box_select_rect = value;
2543                                         InvalidateBoxSelectRect ();
2544                                 }
2545                         }
2546
2547                         void InvalidateBoxSelectRect ()
2548                         {
2549                                 if (BoxSelectRectangle.Size.IsEmpty)
2550                                         return;
2551
2552                                 Rectangle edge = BoxSelectRectangle;
2553                                 edge.X -= 1;
2554                                 edge.Y -= 1;
2555                                 edge.Width += 2;
2556                                 edge.Height = 2;
2557                                 Invalidate (edge);
2558                                 edge.Y = BoxSelectRectangle.Bottom - 1;
2559                                 Invalidate (edge);
2560                                 edge.Y = BoxSelectRectangle.Y - 1;
2561                                 edge.Width = 2;
2562                                 edge.Height = BoxSelectRectangle.Height + 2;
2563                                 Invalidate (edge);
2564                                 edge.X = BoxSelectRectangle.Right - 1;
2565                                 Invalidate (edge);
2566                         }
2567
2568                         private Rectangle CalculateBoxSelectRectangle (Point pt)
2569                         {
2570                                 int left = Math.Min (box_select_start.X, pt.X);
2571                                 int right = Math.Max (box_select_start.X, pt.X);
2572                                 int top = Math.Min (box_select_start.Y, pt.Y);
2573                                 int bottom = Math.Max (box_select_start.Y, pt.Y);
2574                                 return Rectangle.FromLTRB (left, top, right, bottom);
2575                         }
2576
2577                         bool BoxIntersectsItem (int index)
2578                         {
2579                                 Rectangle r = new Rectangle (owner.GetItemLocation (index), owner.ItemSize);
2580                                 if (owner.View != View.Details) {
2581                                         r.X += r.Width / 4;
2582                                         r.Y += r.Height / 4;
2583                                         r.Width /= 2;
2584                                         r.Height /= 2;
2585                                 }
2586                                 return BoxSelectRectangle.IntersectsWith (r);
2587                         }
2588
2589                         bool BoxIntersectsText (int index)
2590                         {
2591                                 Rectangle r = owner.GetItemAtDisplayIndex (index).TextBounds;
2592                                 return BoxSelectRectangle.IntersectsWith (r);
2593                         }
2594
2595                         ArrayList BoxSelectedItems {
2596                                 get {
2597                                         ArrayList result = new ArrayList ();
2598                                         for (int i = 0; i < owner.Items.Count; i++) {
2599                                                 bool intersects;
2600 #if NET_2_0
2601                                                 // Can't iterate over specific items properties in virtualmode
2602                                                 if (owner.View == View.Details && !owner.FullRowSelect && !owner.VirtualMode)
2603 #else
2604                                                 if (owner.View == View.Details && !owner.FullRowSelect)
2605 #endif
2606                                                         intersects = BoxIntersectsText (i);
2607                                                 else
2608                                                         intersects = BoxIntersectsItem (i);
2609
2610                                                 if (intersects)
2611                                                         result.Add (owner.GetItemAtDisplayIndex (i));
2612                                         }
2613                                         return result;
2614                                 }
2615                         }
2616
2617                         private bool PerformBoxSelection (Point pt)
2618                         {
2619                                 if (box_select_mode == BoxSelect.None)
2620                                         return false;
2621
2622                                 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
2623                                 
2624                                 ArrayList box_items = BoxSelectedItems;
2625
2626                                 ArrayList items;
2627
2628                                 switch (box_select_mode) {
2629
2630                                 case BoxSelect.Normal:
2631                                         items = box_items;
2632                                         break;
2633
2634                                 case BoxSelect.Control:
2635                                         items = new ArrayList ();
2636                                         foreach (int index in prev_selection)
2637                                                 if (!box_items.Contains (owner.Items [index]))
2638                                                         items.Add (owner.Items [index]);
2639                                         foreach (ListViewItem item in box_items)
2640                                                 if (!prev_selection.Contains (item.Index))
2641                                                         items.Add (item);
2642                                         break;
2643
2644                                 case BoxSelect.Shift:
2645                                         items = box_items;
2646                                         foreach (ListViewItem item in box_items)
2647                                                 prev_selection.Remove (item.Index);
2648                                         foreach (int index in prev_selection)
2649                                                 items.Add (owner.Items [index]);
2650                                         break;
2651
2652                                 default:
2653                                         throw new Exception ("Unexpected Selection mode: " + box_select_mode);
2654                                 }
2655
2656                                 SuspendLayout ();
2657                                 owner.SelectItems (items);
2658                                 ResumeLayout ();
2659
2660                                 return true;
2661                         }
2662
2663                         private void ItemsMouseDown (object sender, MouseEventArgs me)
2664                         {
2665                                 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
2666                                 if (owner.items.Count == 0)
2667                                         return;
2668
2669                                 bool box_selecting = false;
2670                                 Size item_size = owner.ItemSize;
2671                                 Point pt = new Point (me.X, me.Y);
2672                                 for (int i = 0; i < owner.items.Count; i++) {
2673                                         Rectangle item_rect = new Rectangle (owner.GetItemLocation (i), item_size);
2674                                         if (!item_rect.Contains (pt))
2675                                                 continue;
2676
2677                                         // Actual item in 'i' position
2678                                         ListViewItem item = owner.GetItemAtDisplayIndex (i);
2679
2680                                         if (item.CheckRectReal.Contains (pt)) {
2681                                                 // Don't modify check state if we have only one image
2682                                                 // and if we are in 1.1 profile only take into account
2683                                                 // double clicks
2684                                                 if (owner.StateImageList != null && owner.StateImageList.Images.Count < 2 
2685 #if !NET_2_0
2686                                                                 && me.Clicks == 1
2687 #endif
2688                                                                 )
2689                                                         return;
2690
2691                                                 // Generate an extra ItemCheck event when we got two clicks
2692                                                 // (Match weird .Net behaviour)
2693                                                 if (me.Clicks == 2)
2694                                                         item.Checked = !item.Checked;
2695
2696                                                 item.Checked = !item.Checked;
2697                                                 checking = true;
2698                                                 return;
2699                                         }
2700                                         
2701                                         if (owner.View == View.Details) {
2702                                                 bool over_text = item.TextBounds.Contains (pt);
2703                                                 if (owner.FullRowSelect) {
2704                                                         clicked_item = item;
2705                                                         bool over_item_column = (me.X > owner.Columns[0].X && me.X < owner.Columns[0].X + owner.Columns[0].Width);
2706                                                         if (!over_text && over_item_column && owner.MultiSelect)
2707                                                                 box_selecting = true;
2708                                                 } else if (over_text)
2709                                                         clicked_item = item;
2710                                                 else
2711                                                         owner.SetFocusedItem (i);
2712                                         } else
2713                                                 clicked_item = item;
2714
2715                                         break;
2716                                 }
2717
2718
2719                                 if (clicked_item != null) {
2720                                         bool changed = !clicked_item.Selected;
2721                                         if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2722                                                 owner.SetFocusedItem (clicked_item.DisplayIndex);
2723
2724                                         if (owner.MultiSelect) {
2725                                                 bool reselect = (!owner.LabelEdit || changed);
2726                                                 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2727                                                         owner.UpdateMultiSelection (clicked_item.DisplayIndex, reselect);
2728                                         } else {
2729                                                 clicked_item.Selected = true;
2730                                         }
2731
2732 #if NET_2_0
2733                                         if (owner.VirtualMode && changed) {
2734                                                 // Broken event - It's not fired from Item.Selected also
2735                                                 ListViewVirtualItemsSelectionRangeChangedEventArgs args = 
2736                                                         new ListViewVirtualItemsSelectionRangeChangedEventArgs (0, owner.items.Count - 1, false);
2737
2738                                                 owner.OnVirtualItemsSelectionRangeChanged (args);
2739                                         }
2740 #endif
2741                                         // Report clicks only if the item was clicked. On MS the
2742                                         // clicks are only raised if you click an item
2743                                         clicks = me.Clicks;
2744                                         if (me.Clicks > 1) {
2745                                                 if (owner.CheckBoxes)
2746                                                         clicked_item.Checked = !clicked_item.Checked;
2747                                         } else if (me.Clicks == 1) {
2748                                                 if (owner.LabelEdit && !changed)
2749                                                         BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
2750                                         }
2751                                 } else {
2752                                         if (owner.MultiSelect)
2753                                                 box_selecting = true;
2754                                         else if (owner.SelectedItems.Count > 0)
2755                                                 owner.SelectedItems.Clear ();
2756                                 }
2757
2758                                 if (box_selecting) {
2759                                         Keys mods = XplatUI.State.ModifierKeys;
2760                                         if ((mods & Keys.Shift) != 0)
2761                                                 box_select_mode = BoxSelect.Shift;
2762                                         else if ((mods & Keys.Control) != 0)
2763                                                 box_select_mode = BoxSelect.Control;
2764                                         else
2765                                                 box_select_mode = BoxSelect.Normal;
2766                                         box_select_start = pt; 
2767                                         prev_selection = owner.SelectedIndices.List.Clone () as IList;
2768                                 }
2769                         }
2770
2771                         private void ItemsMouseMove (object sender, MouseEventArgs me)
2772                         {
2773                                 bool done = PerformBoxSelection (new Point (me.X, me.Y));
2774
2775                                 owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
2776
2777                                 if (done)
2778                                         return;
2779                                 if ((me.Button != MouseButtons.Left && me.Button != MouseButtons.Right) &&
2780                                         !hover_processed && owner.Activation != ItemActivation.OneClick
2781 #if NET_2_0
2782                                         && !owner.ShowItemToolTips
2783 #endif
2784                                                 )
2785                                         return;
2786
2787                                 Point pt = PointToClient (Control.MousePosition);
2788                                 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2789
2790                                 if (hover_processed && item != null && item != prev_hovered_item) {
2791                                         hover_processed = false;
2792                                         XplatUI.ResetMouseHover (Handle);
2793                                 }
2794
2795                                 // Need to invalidate the item in HotTracking to show/hide the underline style
2796                                 if (owner.Activation == ItemActivation.OneClick) {
2797                                         if (item == null && owner.HotItemIndex != -1) {
2798 #if NET_2_0
2799                                                 if (owner.HotTracking)
2800                                                         Invalidate (owner.Items [owner.HotItemIndex].Bounds); // Previous one
2801 #endif
2802
2803                                                 Cursor = Cursors.Default;
2804                                                 owner.HotItemIndex = -1;
2805                                         } else if (item != null && owner.HotItemIndex == -1) {
2806 #if NET_2_0
2807                                                 if (owner.HotTracking)
2808                                                         Invalidate (item.Bounds);
2809 #endif
2810
2811                                                 Cursor = Cursors.Hand;
2812                                                 owner.HotItemIndex = item.Index;
2813                                         }
2814                                 }
2815
2816                                 if (me.Button == MouseButtons.Left || me.Button == MouseButtons.Right) {
2817                                         if (drag_begin.X == -1 && drag_begin.Y == -1) {
2818                                                 if (item != null) {
2819                                                         drag_begin = new Point (me.X, me.Y);
2820                                                         dragged_item_index = item.Index;
2821                                                 }
2822
2823                                         } else {
2824                                                 Rectangle r = new Rectangle (drag_begin, SystemInformation.DragSize);
2825                                                 if (!r.Contains (me.X, me.Y)) {
2826                                                         ListViewItem dragged_item  = owner.items [dragged_item_index];
2827                                                         owner.OnItemDrag (new ItemDragEventArgs (me.Button, dragged_item));
2828
2829                                                         drag_begin = new Point (-1, -1);
2830                                                         dragged_item_index = -1;
2831                                                 }
2832                                         }
2833                                 }
2834
2835 #if NET_2_0
2836                                 if (owner.ShowItemToolTips) {
2837                                         if (item == null) {
2838                                                 owner.item_tooltip.Active = false;
2839                                                 prev_tooltip_item = null;
2840                                         } else if (item != prev_tooltip_item && item.ToolTipText.Length > 0) {
2841                                                 owner.item_tooltip.Active = true;
2842                                                 owner.item_tooltip.SetToolTip (owner, item.ToolTipText);
2843                                                 prev_tooltip_item = item;
2844                                         }
2845                                 }
2846 #endif
2847
2848                         }
2849
2850                         private void ItemsMouseHover (object sender, EventArgs e)
2851                         {
2852                                 if (owner.hover_pending) {
2853                                         owner.OnMouseHover (e);
2854                                         owner.hover_pending = false;
2855                                 }
2856
2857                                 if (Capture)
2858                                         return;
2859
2860                                 hover_processed = true;
2861                                 Point pt = PointToClient (Control.MousePosition);
2862                                 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2863                                 if (item == null)
2864                                         return;
2865
2866                                 prev_hovered_item = item;
2867
2868                                 if (owner.HoverSelection) {
2869                                         if (owner.MultiSelect)
2870                                                 owner.UpdateMultiSelection (item.Index, true);
2871                                         else
2872                                                 item.Selected = true;
2873                                         
2874                                         owner.SetFocusedItem (item.DisplayIndex);
2875                                         Select (); // Make sure we have the focus, since MouseHover doesn't give it to us
2876                                 }
2877
2878 #if NET_2_0
2879                                 owner.OnItemMouseHover (new ListViewItemMouseHoverEventArgs (item));
2880 #endif
2881                         }
2882
2883                         void HandleClicks (MouseEventArgs me)
2884                         {
2885                                 // if the click is not on an item,
2886                                 // clicks remains as 0
2887                                 if (clicks > 1) {
2888 #if !NET_2_0
2889                                         owner.OnDoubleClick (EventArgs.Empty);
2890                                 } else if (clicks == 1) {
2891                                         owner.OnClick (EventArgs.Empty);
2892 #else
2893                                         owner.OnDoubleClick (EventArgs.Empty);
2894                                         owner.OnMouseDoubleClick (me);
2895                                 } else if (clicks == 1) {
2896                                         owner.OnClick (EventArgs.Empty);
2897                                         owner.OnMouseClick (me);
2898 #endif
2899                                 }
2900
2901                                 clicks = 0;
2902                         }
2903
2904                         private void ItemsMouseUp (object sender, MouseEventArgs me)
2905                         {
2906                                 MouseEventArgs owner_me = owner.TranslateMouseEventArgs (me);
2907                                 HandleClicks (owner_me);
2908
2909                                 Capture = false;
2910                                 if (owner.Items.Count == 0) {
2911                                         ResetMouseState ();
2912                                         owner.OnMouseUp (owner_me);
2913                                         return;
2914                                 }
2915
2916                                 Point pt = new Point (me.X, me.Y);
2917
2918                                 Rectangle rect = Rectangle.Empty;
2919                                 if (clicked_item != null) {
2920                                         if (owner.view == View.Details && !owner.full_row_select)
2921                                                 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
2922                                         else
2923                                                 rect = clicked_item.Bounds;
2924
2925                                         if (rect.Contains (pt)) {
2926                                                 switch (owner.activation) {
2927                                                 case ItemActivation.OneClick:
2928                                                         owner.OnItemActivate (EventArgs.Empty);
2929                                                         break;
2930
2931                                                 case ItemActivation.TwoClick:
2932                                                         if (last_clicked_item == clicked_item) {
2933                                                                 owner.OnItemActivate (EventArgs.Empty);
2934                                                                 last_clicked_item = null;
2935                                                         } else
2936                                                                 last_clicked_item = clicked_item;
2937                                                         break;
2938                                                 default:
2939                                                         // DoubleClick activation is handled in another handler
2940                                                         break;
2941                                                 }
2942                                         }
2943                                 } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
2944                                         // Need this to clean up background clicks
2945                                         owner.SelectedItems.Clear ();
2946                                 }
2947
2948                                 ResetMouseState ();
2949                                 owner.OnMouseUp (owner_me);
2950                         }
2951
2952                         private void ResetMouseState ()
2953                         {                               
2954                                 clicked_item = null;
2955                                 box_select_start = Point.Empty;
2956                                 BoxSelectRectangle = Rectangle.Empty;
2957                                 prev_selection = null;
2958                                 box_select_mode = BoxSelect.None;
2959                                 checking = false;
2960
2961                                 // Clean these bits in case the mouse buttons were
2962                                 // released before firing ItemDrag
2963                                 dragged_item_index = -1;
2964                                 drag_begin = new Point (-1, -1);
2965                         }
2966                         
2967                         private void LabelEditFinished (object sender, EventArgs e)
2968                         {
2969                                 EndEdit (edit_item);
2970                         }
2971
2972                         private void LabelEditCancelled (object sender, EventArgs e)
2973                         {
2974                                 edit_args.SetLabel (null);
2975                                 EndEdit (edit_item);
2976                         }
2977
2978                         private void LabelTextChanged (object sender, EventArgs e)
2979                         {
2980                                 if (edit_args != null)
2981                                         edit_args.SetLabel (edit_text_box.Text);
2982                         }
2983
2984                         internal void BeginEdit (ListViewItem item)
2985                         {
2986                                 if (edit_item != null)
2987                                         EndEdit (edit_item);
2988                                 
2989                                 if (edit_text_box == null) {
2990                                         edit_text_box = new ListViewLabelEditTextBox ();
2991                                         edit_text_box.BorderStyle = BorderStyle.FixedSingle;
2992                                         edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
2993                                         edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
2994                                         edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
2995                                         edit_text_box.Visible = false;
2996                                         Controls.Add (edit_text_box);
2997                                 }
2998                                 
2999                                 item.EnsureVisible();
3000                                 
3001                                 edit_text_box.Reset ();
3002                                 
3003                                 switch (owner.view) {
3004                                         case View.List:
3005                                         case View.SmallIcon:
3006                                         case View.Details:
3007                                                 edit_text_box.TextAlign = HorizontalAlignment.Left;
3008                                                 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
3009                                                 SizeF sizef = TextRenderer.MeasureString (item.Text, item.Font);
3010                                                 edit_text_box.Width = (int)sizef.Width + 4;
3011                                                 edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
3012                                                 edit_text_box.WordWrap = false;
3013                                                 edit_text_box.Multiline = false;
3014                                                 break;
3015                                         case View.LargeIcon:
3016                                                 edit_text_box.TextAlign = HorizontalAlignment.Center;
3017                                                 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
3018                                                 sizef = TextRenderer.MeasureString (item.Text, item.Font);
3019                                                 edit_text_box.Width = (int)sizef.Width + 4;
3020                                                 edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
3021                                                 edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
3022                                                 edit_text_box.WordWrap = true;
3023                                                 edit_text_box.Multiline = true;
3024                                                 break;
3025                                 }
3026
3027                                 edit_item = item;
3028
3029                                 edit_text_box.Text = item.Text;
3030                                 edit_text_box.Font = item.Font;
3031                                 edit_text_box.Visible = true;
3032                                 edit_text_box.Focus ();
3033                                 edit_text_box.SelectAll ();
3034
3035                                 edit_args = new LabelEditEventArgs (owner.Items.IndexOf (edit_item));
3036                                 owner.OnBeforeLabelEdit (edit_args);
3037
3038                                 if (edit_args.CancelEdit)
3039                                         EndEdit (item);
3040                         }
3041
3042                         internal void CancelEdit (ListViewItem item)
3043                         {
3044                                 // do nothing if there's no item being edited, or if the
3045                                 // item being edited is not the one passed in
3046                                 if (edit_item == null || edit_item != item)
3047                                         return;
3048
3049                                 edit_args.SetLabel (null);
3050                                 EndEdit (item);
3051                         }
3052
3053                         internal void EndEdit (ListViewItem item)
3054                         {
3055                                 // do nothing if there's no item being edited, or if the
3056                                 // item being edited is not the one passed in
3057                                 if (edit_item == null || edit_item != item)
3058                                         return;
3059
3060                                 if (edit_text_box != null) {
3061                                         if (edit_text_box.Visible)
3062                                                 edit_text_box.Visible = false;
3063                                         // ensure listview gets focus
3064                                         owner.Focus ();
3065                                 }
3066
3067                                 // Same as TreeView.EndEdit: need to have focus in synch
3068                                 Application.DoEvents ();
3069
3070                                 // 
3071                                 // Create a new instance, since we could get a call to BeginEdit
3072                                 // from the handler and have fields out of synch
3073                                 //
3074                                 LabelEditEventArgs args = new LabelEditEventArgs (item.Index, edit_args.Label);
3075                                 edit_item = null;
3076
3077                                 owner.OnAfterLabelEdit (args);
3078                                 if (!args.CancelEdit && args.Label != null)
3079                                         item.Text = args.Label;
3080                         }
3081
3082                         internal override void OnPaintInternal (PaintEventArgs pe)
3083                         {
3084                                 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
3085                         }
3086
3087                         protected override void WndProc (ref Message m)
3088                         {
3089                                 switch ((Msg)m.Msg) {
3090                                 case Msg.WM_KILLFOCUS:
3091                                         owner.Select (false, true);
3092                                         break;
3093                                 case Msg.WM_SETFOCUS:
3094                                         owner.Select (false, true);
3095                                         break;
3096                                 case Msg.WM_LBUTTONDOWN:
3097                                         if (!Focused)
3098                                                 owner.Select (false, true);
3099                                         break;
3100                                 case Msg.WM_RBUTTONDOWN:
3101                                         if (!Focused)
3102                                                 owner.Select (false, true);
3103                                         break;
3104                                 default:
3105                                         break;
3106                                 }
3107                                 base.WndProc (ref m);
3108                         }
3109                 }
3110                 
3111                 internal class ListViewLabelEditTextBox : TextBox
3112                 {
3113                         int max_width = -1;
3114                         int min_width = -1;
3115                         
3116                         int max_height = -1;
3117                         int min_height = -1;
3118                         
3119                         int old_number_lines = 1;
3120                         
3121                         SizeF text_size_one_char;
3122                         
3123                         public ListViewLabelEditTextBox ()
3124                         {
3125                                 min_height = DefaultSize.Height;
3126                                 text_size_one_char = TextRenderer.MeasureString ("B", Font);
3127                         }
3128                         
3129                         public int MaxWidth {
3130                                 set {
3131                                         if (value < min_width)
3132                                                 max_width = min_width;
3133                                         else
3134                                                 max_width = value;
3135                                 }
3136                         }
3137                         
3138                         public int MaxHeight {
3139                                 set {
3140                                         if (value < min_height)
3141                                                 max_height = min_height;
3142                                         else
3143                                                 max_height = value;
3144                                 }
3145                         }
3146                         
3147                         public new int Width {
3148                                 get {
3149                                         return base.Width;
3150                                 }
3151                                 set {
3152                                         min_width = value;
3153                                         base.Width = value;
3154                                 }
3155                         }
3156                         
3157                         public override Font Font {
3158                                 get {
3159                                         return base.Font;
3160                                 }
3161                                 set {
3162                                         base.Font = value;
3163                                         text_size_one_char = TextRenderer.MeasureString ("B", Font);
3164                                 }
3165                         }
3166                         
3167                         protected override void OnTextChanged (EventArgs e)
3168                         {
3169                                 SizeF text_size = TextRenderer.MeasureString (Text, Font);
3170                                 
3171                                 int new_width = (int)text_size.Width + 8;
3172                                 
3173                                 if (!Multiline)
3174                                         ResizeTextBoxWidth (new_width);
3175                                 else {
3176                                         if (Width != max_width)
3177                                                 ResizeTextBoxWidth (new_width);
3178                                         
3179                                         int number_lines = Lines.Length;
3180                                         
3181                                         if (number_lines != old_number_lines) {
3182                                                 int new_height = number_lines * (int)text_size_one_char.Height + 4;
3183                                                 old_number_lines = number_lines;
3184                                                 
3185                                                 ResizeTextBoxHeight (new_height);
3186                                         }
3187                                 }
3188                                 
3189                                 base.OnTextChanged (e);
3190                         }
3191                         
3192                         protected override bool IsInputKey (Keys key_data)
3193                         {
3194                                 if ((key_data & Keys.Alt) == 0) {
3195                                         switch (key_data & Keys.KeyCode) {
3196                                                 case Keys.Enter:
3197                                                         return true;
3198                                                 case Keys.Escape:
3199                                                         return true;
3200                                         }
3201                                 }
3202                                 return base.IsInputKey (key_data);
3203                         }
3204                         
3205                         protected override void OnKeyDown (KeyEventArgs e)
3206                         {
3207                                 if (!Visible)
3208                                         return;
3209
3210                                 switch (e.KeyCode) {
3211                                 case Keys.Return:
3212                                         Visible = false;
3213                                         e.Handled = true;
3214                                         OnEditingFinished (e);
3215                                         break;
3216                                 case Keys.Escape:
3217                                         Visible = false;
3218                                         e.Handled = true;
3219                                         OnEditingCancelled (e);
3220                                         break;
3221                                 }
3222                         }
3223                         
3224                         protected override void OnLostFocus (EventArgs e)
3225                         {
3226                                 if (Visible) {
3227                                         OnEditingFinished (e);
3228                                 }
3229                         }
3230
3231                         protected void OnEditingCancelled (EventArgs e)
3232                         {
3233                                 EventHandler eh = (EventHandler)(Events [EditingCancelledEvent]);
3234                                 if (eh != null)
3235                                         eh (this, e);
3236                         }
3237                         
3238                         protected void OnEditingFinished (EventArgs e)
3239                         {
3240                                 EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
3241                                 if (eh != null)
3242                                         eh (this, e);
3243                         }
3244                         
3245                         private void ResizeTextBoxWidth (int new_width)
3246                         {
3247                                 if (new_width > max_width)
3248                                         base.Width = max_width;
3249                                 else 
3250                                 if (new_width >= min_width)
3251                                         base.Width = new_width;
3252                                 else
3253                                         base.Width = min_width;
3254                         }
3255                         
3256                         private void ResizeTextBoxHeight (int new_height)
3257                         {
3258                                 if (new_height > max_height)
3259                                         base.Height = max_height;
3260                                 else 
3261                                 if (new_height >= min_height)
3262                                         base.Height = new_height;
3263                                 else
3264                                         base.Height = min_height;
3265                         }
3266                         
3267                         public void Reset ()
3268                         {
3269                                 max_width = -1;
3270                                 min_width = -1;
3271                                 
3272                                 max_height = -1;
3273                                 
3274                                 old_number_lines = 1;
3275                                 
3276                                 Text = String.Empty;
3277                                 
3278                                 Size = DefaultSize;
3279                         }
3280
3281                         static object EditingCancelledEvent = new object ();
3282                         public event EventHandler EditingCancelled {
3283                                 add { Events.AddHandler (EditingCancelledEvent, value); }
3284                                 remove { Events.RemoveHandler (EditingCancelledEvent, value); }
3285                         }
3286
3287                         static object EditingFinishedEvent = new object ();
3288                         public event EventHandler EditingFinished {
3289                                 add { Events.AddHandler (EditingFinishedEvent, value); }
3290                                 remove { Events.RemoveHandler (EditingFinishedEvent, value); }
3291                         }
3292                 }
3293
3294                 internal override void OnPaintInternal (PaintEventArgs pe)
3295                 {
3296                         if (updating)
3297                                 return;
3298                                 
3299                         CalculateScrollBars ();
3300                 }
3301
3302                 void FocusChanged (object o, EventArgs args)
3303                 {
3304                         if (Items.Count == 0)
3305                                 return;
3306
3307                         if (FocusedItem == null)
3308                                 SetFocusedItem (0);
3309
3310                         ListViewItem focused_item = FocusedItem;
3311
3312                         if (focused_item.ListView != null) {
3313                                 focused_item.Invalidate ();
3314                                 focused_item.Layout ();
3315                                 focused_item.Invalidate ();
3316                         }
3317                 }
3318
3319                 private void ListView_Invalidated (object sender, InvalidateEventArgs e)
3320                 {
3321                         // When the ListView is invalidated, we need to invalidate
3322                         // the child controls.
3323                         header_control.Invalidate ();
3324                         item_control.Invalidate ();
3325                 }
3326
3327                 private void ListView_MouseEnter (object sender, EventArgs args)
3328                 {
3329                         hover_pending = true; // Need a hover event for every Enter/Leave cycle
3330                 }
3331
3332                 private void ListView_MouseWheel (object sender, MouseEventArgs me)
3333                 {
3334                         if (Items.Count == 0)
3335                                 return;
3336
3337                         int lines = me.Delta / 120;
3338
3339                         if (lines == 0)
3340                                 return;
3341
3342                         switch (View) {
3343                         case View.Details:
3344                         case View.SmallIcon:
3345                                 Scroll (v_scroll, -ItemSize.Height * SystemInformation.MouseWheelScrollLines * lines);
3346                                 break;
3347                         case View.LargeIcon:
3348                                 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing)  * lines);
3349                                 break;
3350                         case View.List:
3351                                 Scroll (h_scroll, -ItemSize.Width * lines);
3352                                 break;
3353 #if NET_2_0
3354                         case View.Tile:
3355                                 if (!Application.VisualStylesEnabled)
3356                                         goto case View.LargeIcon;
3357
3358                                 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * 2 * lines);
3359                                 break;
3360 #endif
3361                         }
3362                 }
3363
3364                 private void ListView_SizeChanged (object sender, EventArgs e)
3365                 {
3366                         Redraw (true);
3367                 }
3368                 
3369                 private void SetFocusedItem (int display_index)
3370                 {
3371                         if (display_index != -1)
3372                                 GetItemAtDisplayIndex (display_index).Focused = true;
3373                         else if (focused_item_index != -1 && focused_item_index < items.Count) // Previous focused item
3374                                 GetItemAtDisplayIndex (focused_item_index).Focused = false;
3375                         focused_item_index = display_index;
3376 #if NET_2_0
3377                         if (display_index == -1)
3378                                 OnUIAFocusedItemChanged ();
3379                                 // otherwise the event will have been fired
3380                                 // when the ListViewItem's Focused was set
3381 #endif
3382                 }
3383
3384                 private void HorizontalScroller (object sender, EventArgs e)
3385                 {
3386                         item_control.EndEdit (item_control.edit_item);
3387                         
3388                         // Avoid unnecessary flickering, when button is
3389                         // kept pressed at the end
3390                         if (h_marker != h_scroll.Value) {
3391                                 
3392                                 int pixels = h_marker - h_scroll.Value;
3393                                 
3394                                 h_marker = h_scroll.Value;
3395                                 if (header_control.Visible)
3396                                         XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
3397
3398                                 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
3399                         }
3400                 }
3401
3402                 private void VerticalScroller (object sender, EventArgs e)
3403                 {
3404                         item_control.EndEdit (item_control.edit_item);
3405                         
3406                         // Avoid unnecessary flickering, when button is
3407                         // kept pressed at the end
3408                         if (v_marker != v_scroll.Value) {
3409                                 int pixels = v_marker - v_scroll.Value;
3410                                 Rectangle area = item_control.ClientRectangle;
3411                                 if (header_control.Visible) {
3412                                         area.Y += header_control.Height;
3413                                         area.Height -= header_control.Height;
3414                                 }
3415
3416                                 v_marker = v_scroll.Value;
3417                                 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
3418                         }
3419                 }
3420
3421                 internal override bool IsInputCharInternal (char charCode)
3422                 {
3423                         return true;
3424                 }
3425                 #endregion      // Internal Methods Properties
3426
3427                 #region Protected Methods
3428                 protected override void CreateHandle ()
3429                 {
3430                         base.CreateHandle ();
3431                         for (int i = 0; i < SelectedItems.Count; i++)
3432                                 OnSelectedIndexChanged (EventArgs.Empty);
3433                 }
3434
3435                 protected override void Dispose (bool disposing)
3436                 {
3437                         if (disposing) {
3438                                 h_scroll.Dispose ();
3439                                 v_scroll.Dispose ();
3440                                 
3441                                 large_image_list = null;
3442                                 small_image_list = null;
3443                                 state_image_list = null;
3444
3445                                 foreach (ColumnHeader col in columns)
3446                                         col.SetListView (null);
3447
3448 #if NET_2_0
3449                                 if (!virtual_mode) // In virtual mode we don't save the items
3450 #endif
3451                                         foreach (ListViewItem item in items)
3452                                                 item.Owner = null;
3453                         }
3454                         
3455                         base.Dispose (disposing);
3456                 }
3457
3458                 protected override bool IsInputKey (Keys keyData)
3459                 {
3460                         switch (keyData) {
3461                         case Keys.Up:
3462                         case Keys.Down:
3463                         case Keys.PageUp:
3464                         case Keys.PageDown:
3465                         case Keys.Right:
3466                         case Keys.Left:
3467                         case Keys.End:
3468                         case Keys.Home:
3469                                 return true;
3470
3471                         default:
3472                                 break;
3473                         }
3474                         
3475                         return base.IsInputKey (keyData);
3476                 }
3477
3478                 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
3479                 {
3480                         LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
3481                         if (eh != null)
3482                                 eh (this, e);
3483                 }
3484
3485 #if NET_2_0
3486                 protected override void OnBackgroundImageChanged (EventArgs e)
3487                 {
3488                         item_control.BackgroundImage = BackgroundImage;
3489                         base.OnBackgroundImageChanged (e);
3490                 }
3491 #endif
3492
3493                 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
3494                 {
3495                         LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
3496                         if (eh != null)
3497                                 eh (this, e);
3498                 }
3499
3500                 protected internal virtual void OnColumnClick (ColumnClickEventArgs e)
3501                 {
3502                         ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
3503                         if (eh != null)
3504                                 eh (this, e);
3505                 }
3506
3507 #if NET_2_0
3508                 protected internal virtual void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
3509                 {
3510                         DrawListViewColumnHeaderEventHandler eh = (DrawListViewColumnHeaderEventHandler)(Events[DrawColumnHeaderEvent]);
3511                         if (eh != null)
3512                                 eh(this, e);
3513                 }
3514
3515                 protected internal virtual void OnDrawItem(DrawListViewItemEventArgs e)
3516                 {
3517                         DrawListViewItemEventHandler eh = (DrawListViewItemEventHandler)(Events[DrawItemEvent]);
3518                         if (eh != null)
3519                                 eh(this, e);
3520                 }
3521
3522                 protected internal virtual void OnDrawSubItem(DrawListViewSubItemEventArgs e)
3523                 {
3524                         DrawListViewSubItemEventHandler eh = (DrawListViewSubItemEventHandler)(Events[DrawSubItemEvent]);
3525                         if (eh != null)
3526                                 eh(this, e);
3527                 }
3528
3529 #else
3530                 protected override void OnEnabledChanged (EventArgs e)
3531                 {
3532                         base.OnEnabledChanged (e);
3533                 }
3534 #endif
3535
3536                 protected override void OnFontChanged (EventArgs e)
3537                 {
3538                         base.OnFontChanged (e);
3539                         Redraw (true);
3540                 }
3541
3542                 protected override void OnHandleCreated (EventArgs e)
3543                 {
3544                         base.OnHandleCreated (e);
3545                         CalculateListView (alignment);
3546 #if NET_2_0
3547                         if (!virtual_mode) // Sorting is not allowed in virtual mode
3548 #endif
3549                                 Sort ();
3550                 }
3551
3552                 protected override void OnHandleDestroyed (EventArgs e)
3553                 {
3554                         base.OnHandleDestroyed (e);
3555                 }
3556
3557                 protected virtual void OnItemActivate (EventArgs e)
3558                 {
3559                         EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
3560                         if (eh != null)
3561                                 eh (this, e);
3562                 }
3563
3564                 protected internal virtual void OnItemCheck (ItemCheckEventArgs ice)
3565                 {
3566                         ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
3567                         if (eh != null)
3568                                 eh (this, ice);
3569                 }
3570
3571 #if NET_2_0
3572                 protected internal virtual void OnItemChecked (ItemCheckedEventArgs e)
3573                 {
3574                         ItemCheckedEventHandler eh = (ItemCheckedEventHandler)(Events [ItemCheckedEvent]);
3575                         if (eh != null)
3576                                 eh (this, e);
3577                 }
3578 #endif
3579
3580                 protected virtual void OnItemDrag (ItemDragEventArgs e)
3581                 {
3582                         ItemDragEventHandler eh = (ItemDragEventHandler)(Events [ItemDragEvent]);
3583                         if (eh != null)
3584                                 eh (this, e);
3585                 }
3586
3587 #if NET_2_0
3588                 protected virtual void OnItemMouseHover (ListViewItemMouseHoverEventArgs e)
3589                 {
3590                         ListViewItemMouseHoverEventHandler eh = (ListViewItemMouseHoverEventHandler)(Events [ItemMouseHoverEvent]);
3591                         if (eh != null)
3592                                 eh (this, e);
3593                 }
3594
3595                 protected internal virtual void OnItemSelectionChanged (ListViewItemSelectionChangedEventArgs e)
3596                 {
3597                         ListViewItemSelectionChangedEventHandler eh = 
3598                                 (ListViewItemSelectionChangedEventHandler) Events [ItemSelectionChangedEvent];
3599                         if (eh != null)
3600                                 eh (this, e);
3601                 }
3602
3603                 protected override void OnMouseHover (EventArgs e)
3604                 {
3605                         base.OnMouseHover (e);
3606                 }
3607
3608                 protected override void OnParentChanged (EventArgs e)
3609                 {
3610                         base.OnParentChanged (e);
3611                 }
3612 #endif
3613
3614                 protected virtual void OnSelectedIndexChanged (EventArgs e)
3615                 {
3616                         EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
3617                         if (eh != null)
3618                                 eh (this, e);
3619                 }
3620
3621                 protected override void OnSystemColorsChanged (EventArgs e)
3622                 {
3623                         base.OnSystemColorsChanged (e);
3624                 }
3625
3626 #if NET_2_0
3627                 protected internal virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs e)
3628                 {
3629                         CacheVirtualItemsEventHandler eh = (CacheVirtualItemsEventHandler)Events [CacheVirtualItemsEvent];
3630                         if (eh != null)
3631                                 eh (this, e);
3632                 }
3633
3634                 protected virtual void OnRetrieveVirtualItem (RetrieveVirtualItemEventArgs e)
3635                 {
3636                         RetrieveVirtualItemEventHandler eh = (RetrieveVirtualItemEventHandler)Events [RetrieveVirtualItemEvent];
3637                         if (eh != null)
3638                                 eh (this, e);
3639                 }
3640
3641                 [EditorBrowsable (EditorBrowsableState.Advanced)]
3642                 protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
3643                 {
3644                         EventHandler eh = (EventHandler)Events[RightToLeftLayoutChangedEvent];
3645                         if (eh != null)
3646                                 eh (this, e);
3647                 }
3648
3649                 protected virtual void OnSearchForVirtualItem (SearchForVirtualItemEventArgs e)
3650                 {
3651                         SearchForVirtualItemEventHandler eh = (SearchForVirtualItemEventHandler) Events [SearchForVirtualItemEvent];
3652                         if (eh != null)
3653                                 eh (this, e);
3654                 }
3655                 
3656                 protected virtual void OnVirtualItemsSelectionRangeChanged (ListViewVirtualItemsSelectionRangeChangedEventArgs e)
3657                 {
3658                         ListViewVirtualItemsSelectionRangeChangedEventHandler eh = 
3659                                 (ListViewVirtualItemsSelectionRangeChangedEventHandler) Events [VirtualItemsSelectionRangeChangedEvent];
3660                         if (eh != null)
3661                                 eh (this, e);
3662                 }
3663 #endif
3664
3665                 protected void RealizeProperties ()
3666                 {
3667                         // FIXME: TODO
3668                 }
3669
3670                 protected void UpdateExtendedStyles ()
3671                 {
3672                         // FIXME: TODO
3673                 }
3674
3675                 bool refocusing = false;
3676
3677                 protected override void WndProc (ref Message m)
3678                 {
3679                         switch ((Msg)m.Msg) {
3680                         case Msg.WM_KILLFOCUS:
3681                                 Control receiver = Control.FromHandle (m.WParam);
3682                                 if (receiver == item_control) {
3683                                         has_focus = false;
3684                                         refocusing = true;
3685                                         return;
3686                                 }
3687                                 break;
3688                         case Msg.WM_SETFOCUS:
3689                                 if (refocusing) {
3690                                         has_focus = true;
3691                                         refocusing = false;
3692                                         return;
3693                                 }
3694                                 break;
3695                         default:
3696                                 break;
3697                         }
3698                         base.WndProc (ref m);
3699                 }
3700                 #endregion // Protected Methods
3701
3702                 #region Public Instance Methods
3703                 public void ArrangeIcons ()
3704                 {
3705                         ArrangeIcons (this.alignment);
3706                 }
3707
3708                 public void ArrangeIcons (ListViewAlignment value)
3709                 {
3710                         // Icons are arranged only if view is set to LargeIcon or SmallIcon
3711                         if (view == View.LargeIcon || view == View.SmallIcon)
3712                                 Redraw (true);
3713                 }
3714
3715 #if NET_2_0
3716                 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
3717                 {
3718                         if (columnIndex < 0 || columnIndex >= columns.Count)
3719                                 throw new ArgumentOutOfRangeException ("columnIndex");
3720
3721                         columns [columnIndex].AutoResize (headerAutoResize);
3722                 }
3723
3724                 public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
3725                 {
3726                         BeginUpdate ();
3727                         foreach (ColumnHeader col in columns) 
3728                                 col.AutoResize (headerAutoResize);
3729                         EndUpdate ();
3730                 }
3731 #endif
3732
3733                 public void BeginUpdate ()
3734                 {
3735                         // flag to avoid painting
3736                         updating = true;
3737                 }
3738
3739                 public void Clear ()
3740                 {
3741                         columns.Clear ();
3742                         items.Clear (); // Redraw (true) called here
3743                 }
3744
3745                 public void EndUpdate ()
3746                 {
3747                         // flag to avoid painting
3748                         updating = false;
3749
3750                         // probably, now we need a redraw with recalculations
3751                         this.Redraw (true);
3752                 }
3753
3754                 public void EnsureVisible (int index)
3755                 {
3756                         if (index < 0 || index >= items.Count || scrollable == false || updating)
3757                                 return;
3758
3759                         Rectangle view_rect = item_control.ClientRectangle;
3760 #if NET_2_0
3761                         // Avoid direct access to items in virtual mode, and use item bounds otherwise, since we could have reordered items
3762                         Rectangle bounds = virtual_mode ? new Rectangle (GetItemLocation (index), ItemSize) : items [index].Bounds;
3763 #else
3764                         Rectangle bounds = items [index].Bounds;
3765 #endif
3766
3767                         if (view == View.Details && header_style != ColumnHeaderStyle.None) {
3768                                 view_rect.Y += header_control.Height;
3769                                 view_rect.Height -= header_control.Height;
3770                         }
3771
3772                         if (view_rect.Contains (bounds))
3773                                 return;
3774
3775                         if (View != View.Details) {
3776                                 if (bounds.Left < 0)
3777                                         h_scroll.Value += bounds.Left;
3778                                 else if (bounds.Right > view_rect.Right)
3779                                         h_scroll.Value += (bounds.Right - view_rect.Right);
3780                         }
3781
3782                         if (bounds.Top < view_rect.Y)
3783                                 v_scroll.Value += bounds.Top - view_rect.Y;
3784                         else if (bounds.Bottom > view_rect.Bottom)
3785                                 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
3786                 }
3787
3788 #if NET_2_0
3789                 public ListViewItem FindItemWithText (string text)
3790                 {
3791                         if (items.Count == 0)
3792                                 return null;
3793
3794                         return FindItemWithText (text, true, 0, true);
3795                 }
3796
3797                 public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex)
3798                 {
3799                         return FindItemWithText (text, includeSubItemsInSearch, startIndex, true, false);
3800                 }
3801
3802                 public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch)
3803                 {
3804                         return FindItemWithText (text, includeSubItemsInSearch, startIndex, isPrefixSearch, false);
3805                 }
3806 #endif
3807                 
3808                 internal ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch, bool roundtrip)
3809                 {
3810                         if (startIndex < 0 || startIndex >= items.Count)
3811                                 throw new ArgumentOutOfRangeException ("startIndex");
3812
3813                         if (text == null)
3814                                 throw new ArgumentNullException ("text");
3815
3816 #if NET_2_0
3817                         if (virtual_mode) {
3818                                 SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (true,
3819                                                 isPrefixSearch, includeSubItemsInSearch, text, Point.Empty, 
3820                                                 SearchDirectionHint.Down, startIndex);
3821
3822                                 OnSearchForVirtualItem (args);
3823                                 int idx = args.Index;
3824                                 if (idx >= 0 && idx < virtual_list_size)
3825                                         return items [idx];
3826
3827                                 return null;
3828                         }
3829 #endif
3830
3831                         int i = startIndex;
3832                         while (true) {
3833                                 ListViewItem lvi = items [i];
3834
3835                                 if (isPrefixSearch) { // prefix search
3836                                         if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (lvi.Text, text, CompareOptions.IgnoreCase))
3837                                                 return lvi;
3838                                 } else if (String.Compare (lvi.Text, text, true) == 0) // match
3839                                         return lvi;
3840
3841                                 if (i + 1 >= items.Count) {
3842                                         if (!roundtrip)
3843                                                 break;
3844
3845                                         i = 0;
3846                                 } else 
3847                                         i++;
3848
3849                                 if (i == startIndex)
3850                                         break;
3851                         }
3852
3853                         // Subitems have a minor priority, so we have to do a second linear search
3854                         // Also, we don't need to to a roundtrip search for them by now
3855                         if (includeSubItemsInSearch) {
3856                                 for (i = startIndex; i < items.Count; i++) {
3857                                         ListViewItem lvi = items [i];
3858                                         foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
3859                                                 if (isPrefixSearch) {
3860                                                         if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (sub_item.Text, 
3861                                                                 text, CompareOptions.IgnoreCase))
3862                                                                 return lvi;
3863                                                 } else if (String.Compare (sub_item.Text, text, true) == 0)
3864                                                         return lvi;
3865                                 }
3866                         }
3867
3868                         return null;
3869                 }
3870
3871 #if NET_2_0
3872                 public ListViewItem FindNearestItem (SearchDirectionHint searchDirection, int x, int y)
3873                 {
3874                         return FindNearestItem (searchDirection, new Point (x, y));
3875                 }
3876
3877                 public ListViewItem FindNearestItem (SearchDirectionHint dir, Point point)
3878                 {
3879                         if (dir < SearchDirectionHint.Left || dir > SearchDirectionHint.Down)
3880                                 throw new ArgumentOutOfRangeException ("searchDirection");
3881
3882                         if (view != View.LargeIcon && view != View.SmallIcon)
3883                                 throw new InvalidOperationException ();
3884
3885                         if (virtual_mode) {
3886                                 SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (false,
3887                                                 false, false, String.Empty, point, 
3888                                                 dir, 0);
3889
3890                                 OnSearchForVirtualItem (args);
3891                                 int idx = args.Index;
3892                                 if (idx >= 0 && idx < virtual_list_size)
3893                                         return items [idx];
3894
3895                                 return null;
3896                         }
3897
3898                         ListViewItem item = null;
3899                         int min_dist = Int32.MaxValue;
3900
3901                         //
3902                         // It looks like .Net does a previous adjustment
3903                         //
3904                         switch (dir) {
3905                                 case SearchDirectionHint.Up:
3906                                         point.Y -= item_size.Height;
3907                                         break;
3908                                 case SearchDirectionHint.Down:
3909                                         point.Y += item_size.Height;
3910                                         break;
3911                                 case SearchDirectionHint.Left:
3912                                         point.X -= item_size.Width;
3913                                         break;
3914                                 case SearchDirectionHint.Right:
3915                                         point.X += item_size.Width;
3916                                         break;
3917                         }
3918
3919                         for (int i = 0; i < items.Count; i++) {
3920                                 Point item_loc = GetItemLocation (i);
3921
3922                                 if (dir == SearchDirectionHint.Up) {
3923                                         if (point.Y < item_loc.Y)
3924                                                 continue;
3925                                 } else if (dir == SearchDirectionHint.Down) {
3926                                         if (point.Y > item_loc.Y)
3927                                                 continue;
3928                                 } else if (dir == SearchDirectionHint.Left) {
3929                                         if (point.X < item_loc.X)
3930                                                 continue;
3931                                 } else if (dir == SearchDirectionHint.Right) {
3932                                         if (point.X > item_loc.X)
3933                                                 continue;
3934                                 }
3935
3936                                 int x_dist = point.X - item_loc.X;
3937                                 int y_dist = point.Y - item_loc.Y;
3938
3939                                 int dist = x_dist * x_dist  + y_dist * y_dist;
3940                                 if (dist < min_dist) {
3941                                         item = items [i];
3942                                         min_dist = dist;
3943                                 }
3944                         }
3945
3946                         return item;
3947                 }
3948 #endif
3949                 
3950                 public ListViewItem GetItemAt (int x, int y)
3951                 {
3952                         Size item_size = ItemSize;
3953                         for (int i = 0; i < items.Count; i++) {
3954                                 Point item_location = GetItemLocation (i);
3955                                 Rectangle item_rect = new Rectangle (item_location, item_size);
3956                                 if (item_rect.Contains (x, y))
3957                                         return items [i];
3958                         }
3959
3960                         return null;
3961                 }
3962
3963                 public Rectangle GetItemRect (int index)
3964                 {
3965                         return GetItemRect (index, ItemBoundsPortion.Entire);
3966                 }
3967
3968                 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
3969                 {
3970                         if (index < 0 || index >= items.Count)
3971                                 throw new IndexOutOfRangeException ("index");
3972
3973                         return items [index].GetBounds (portion);
3974                 }
3975
3976 #if NET_2_0
3977                 public ListViewHitTestInfo HitTest (Point point)
3978                 {
3979                         return HitTest (point.X, point.Y);
3980                 }
3981
3982                 public ListViewHitTestInfo HitTest (int x, int y)
3983                 {
3984                         if (x < 0)
3985                                 throw new ArgumentOutOfRangeException ("x");
3986                         if (y < 0)
3987                                 throw new ArgumentOutOfRangeException ("y");
3988
3989                         ListViewItem item = GetItemAt (x, y);
3990                         if (item == null)
3991                                 return new ListViewHitTestInfo (null, null, ListViewHitTestLocations.None);
3992
3993                         ListViewHitTestLocations locations = 0;
3994                         if (item.GetBounds (ItemBoundsPortion.Label).Contains (x, y))
3995                                 locations |= ListViewHitTestLocations.Label;
3996                         else if (item.GetBounds (ItemBoundsPortion.Icon).Contains (x, y))
3997                                 locations |= ListViewHitTestLocations.Image;
3998                         else if (item.CheckRectReal.Contains (x, y))
3999                                 locations |= ListViewHitTestLocations.StateImage;
4000
4001                         ListViewItem.ListViewSubItem subitem = null;
4002                         if (view == View.Details)
4003                                 foreach (ListViewItem.ListViewSubItem si in item.SubItems)
4004                                         if (si.Bounds.Contains (x, y)) {
4005                                                 subitem = si;
4006                                                 break;
4007                                         }
4008
4009                         return new ListViewHitTestInfo (item, subitem, locations);
4010                 }
4011
4012                 [EditorBrowsable (EditorBrowsableState.Advanced)]
4013                 public void RedrawItems (int startIndex, int endIndex, bool invalidateOnly)
4014                 {
4015                         if (startIndex < 0 || startIndex >= items.Count)
4016                                 throw new ArgumentOutOfRangeException ("startIndex");
4017                         if (endIndex < 0 || endIndex >= items.Count)
4018                                 throw new ArgumentOutOfRangeException ("endIndex");
4019                         if (startIndex > endIndex)
4020                                 throw new ArgumentException ("startIndex");
4021
4022                         if (updating)
4023                                 return;
4024
4025                         for (int i = startIndex; i <= endIndex; i++)
4026                                 items [i].Invalidate ();
4027
4028                         if (!invalidateOnly)
4029                                 Update ();
4030                 }
4031 #endif
4032
4033                 public void Sort ()
4034                 {
4035 #if NET_2_0
4036                         if (virtual_mode)
4037                                 throw new InvalidOperationException ();
4038 #endif
4039
4040                         Sort (true);
4041                 }
4042
4043                 // we need this overload to reuse the logic for sorting, while allowing
4044                 // redrawing to be done by caller or have it done by this method when
4045                 // sorting is really performed
4046                 //
4047                 // ListViewItemCollection's Add and AddRange methods call this overload
4048                 // with redraw set to false, as they take care of redrawing themselves
4049                 // (they even want to redraw the listview if no sort is performed, as 
4050                 // an item was added), while ListView.Sort () only wants to redraw if 
4051                 // sorting was actually performed
4052                 private void Sort (bool redraw)
4053                 {
4054                         if (!IsHandleCreated || item_sorter == null) {
4055                                 return;
4056                         }
4057                         
4058                         items.Sort (item_sorter);
4059                         if (redraw)
4060                                 this.Redraw (true);
4061                 }
4062
4063                 public override string ToString ()
4064                 {
4065                         int count = this.Items.Count;
4066
4067                         if (count == 0)
4068                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
4069                         else
4070                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
4071                 }
4072                 #endregion      // Public Instance Methods
4073
4074
4075                 #region Subclasses
4076
4077                 internal class HeaderControl : Control {
4078
4079                         ListView owner;
4080                         bool column_resize_active = false;
4081                         ColumnHeader resize_column;
4082                         ColumnHeader clicked_column;
4083                         ColumnHeader drag_column;
4084                         int drag_x;
4085                         int drag_to_index = -1;
4086                         ColumnHeader entered_column_header;
4087
4088                         public HeaderControl (ListView owner)
4089                         {
4090                                 this.owner = owner;
4091                                 this.SetStyle (ControlStyles.DoubleBuffer, true);
4092                                 MouseDown += new MouseEventHandler (HeaderMouseDown);
4093                                 MouseMove += new MouseEventHandler (HeaderMouseMove);
4094                                 MouseUp += new MouseEventHandler (HeaderMouseUp);
4095                                 MouseLeave += new EventHandler (OnMouseLeave);
4096                         }
4097
4098                         internal ColumnHeader EnteredColumnHeader {
4099                                 get { return entered_column_header; }
4100                                 private set {
4101                                         if (entered_column_header == value)
4102                                                 return;
4103                                         if (ThemeEngine.Current.ListViewHasHotHeaderStyle) {
4104                                                 Region region_to_invalidate = new Region ();
4105                                                 region_to_invalidate.MakeEmpty ();
4106                                                 if (entered_column_header != null)
4107                                                         region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header));
4108                                                 entered_column_header = value;
4109                                                 if (entered_column_header != null)
4110                                                         region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header));
4111                                                 Invalidate (region_to_invalidate);
4112                                                 region_to_invalidate.Dispose ();
4113                                         } else
4114                                                 entered_column_header = value;
4115                                 }
4116                         }
4117
4118                         void OnMouseLeave (object sender, EventArgs e)
4119                         {
4120                                 EnteredColumnHeader = null;
4121                         }
4122
4123                         private ColumnHeader ColumnAtX (int x)
4124                         {
4125                                 Point pt = new Point (x, 0);
4126                                 ColumnHeader result = null;
4127                                 foreach (ColumnHeader col in owner.Columns) {
4128                                         if (col.Rect.Contains (pt)) {
4129                                                 result = col;
4130                                                 break;
4131                                         }
4132                                 }
4133                                 return result;
4134                         }
4135
4136                         private int GetReorderedIndex (ColumnHeader col)
4137                         {
4138                                 if (owner.reordered_column_indices == null)
4139                                         return col.Index;
4140                                 else
4141                                         for (int i = 0; i < owner.Columns.Count; i++)
4142                                                 if (owner.reordered_column_indices [i] == col.Index)
4143                                                         return i;
4144                                 throw new Exception ("Column index missing from reordered array");
4145                         }
4146
4147                         private void HeaderMouseDown (object sender, MouseEventArgs me)
4148                         {
4149                                 if (resize_column != null) {
4150                                         column_resize_active = true;
4151                                         Capture = true;
4152                                         return;
4153                                 }
4154
4155                                 clicked_column = ColumnAtX (me.X + owner.h_marker);
4156
4157                                 if (clicked_column != null) {
4158                                         Capture = true;
4159                                         if (owner.AllowColumnReorder) {
4160                                                 drag_x = me.X;
4161                                                 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
4162                                                 drag_column.Rect = clicked_column.Rect;
4163                                                 drag_to_index = GetReorderedIndex (clicked_column);
4164                                         }
4165                                         clicked_column.Pressed = true;
4166                                         Invalidate (clicked_column);
4167                                         return;
4168                                 }
4169                         }
4170
4171                         void Invalidate (ColumnHeader columnHeader)
4172                         {
4173                                 Invalidate (GetColumnHeaderInvalidateArea (columnHeader));
4174                         }
4175
4176                         Rectangle GetColumnHeaderInvalidateArea (ColumnHeader columnHeader)
4177                         {
4178                                 Rectangle bounds = columnHeader.Rect;
4179                                 bounds.X -= owner.h_marker;
4180                                 return bounds;
4181                         }
4182
4183                         void StopResize ()
4184                         {
4185                                 column_resize_active = false;
4186                                 resize_column = null;
4187                                 Capture = false;
4188                                 Cursor = Cursors.Default;
4189                         }
4190                         
4191                         private void HeaderMouseMove (object sender, MouseEventArgs me)
4192                         {
4193                                 Point pt = new Point (me.X + owner.h_marker, me.Y);
4194
4195                                 if (column_resize_active) {
4196                                         int width = pt.X - resize_column.X;
4197                                         if (width < 0)
4198                                                 width = 0;
4199
4200                                         if (!owner.CanProceedWithResize (resize_column, width)){
4201                                                 StopResize ();
4202                                                 return;
4203                                         }
4204                                         resize_column.Width = width;
4205                                         return;
4206                                 }
4207
4208                                 resize_column = null;
4209
4210                                 if (clicked_column != null) {
4211                                         if (owner.AllowColumnReorder) {
4212                                                 Rectangle r;
4213
4214                                                 r = drag_column.Rect;
4215                                                 r.X = clicked_column.Rect.X + me.X - drag_x;
4216                                                 drag_column.Rect = r;
4217
4218                                                 int x = me.X + owner.h_marker;
4219                                                 ColumnHeader over = ColumnAtX (x);
4220                                                 if (over == null)
4221                                                         drag_to_index = owner.Columns.Count;
4222                                                 else if (x < over.X + over.Width / 2)
4223                                                         drag_to_index = GetReorderedIndex (over);
4224                                                 else
4225                                                         drag_to_index = GetReorderedIndex (over) + 1;
4226                                                 Invalidate ();
4227                                         } else {
4228                                                 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
4229                                                 bool pressed = clicked_column.Pressed;
4230                                                 clicked_column.Pressed = over == clicked_column;
4231                                                 if (clicked_column.Pressed ^ pressed)
4232                                                         Invalidate (clicked_column);
4233                                         }
4234                                         return;
4235                                 }
4236
4237                                 for (int i = 0; i < owner.Columns.Count; i++) {
4238                                         Rectangle zone = owner.Columns [i].Rect;
4239                                         if (zone.Contains (pt))
4240                                                 EnteredColumnHeader = owner.Columns [i];
4241                                         zone.X = zone.Right - 5;
4242                                         zone.Width = 10;
4243                                         if (zone.Contains (pt)) {
4244                                                 if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
4245                                                         i++;
4246                                                 resize_column = owner.Columns [i];
4247                                                 break;
4248                                         }
4249                                 }
4250
4251                                 if (resize_column == null)
4252                                         Cursor = Cursors.Default;
4253                                 else
4254                                         Cursor = Cursors.VSplit;
4255                         }
4256
4257                         void HeaderMouseUp (object sender, MouseEventArgs me)
4258                         {
4259                                 Capture = false;
4260
4261                                 if (column_resize_active) {
4262                                         int column_idx = resize_column.Index;
4263                                         StopResize ();
4264                                         owner.RaiseColumnWidthChanged (column_idx);
4265                                         return;
4266                                 }
4267
4268                                 if (clicked_column != null && clicked_column.Pressed) {
4269                                         clicked_column.Pressed = false;
4270                                         Invalidate (clicked_column);
4271                                         owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
4272                                 }
4273
4274                                 if (drag_column != null && owner.AllowColumnReorder) {
4275                                         drag_column = null;
4276                                         if (drag_to_index > GetReorderedIndex (clicked_column))
4277                                                 drag_to_index--;
4278                                         if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
4279                                                 owner.ReorderColumn (clicked_column, drag_to_index, true);
4280                                         drag_to_index = -1;
4281                                         Invalidate ();
4282                                 }
4283
4284                                 clicked_column = null;
4285                         }
4286
4287                         internal override void OnPaintInternal (PaintEventArgs pe)
4288                         {
4289                                 if (owner.updating)
4290                                         return;
4291                                 
4292                                 Theme theme = ThemeEngine.Current;
4293                                 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
4294
4295                                 if (drag_column == null)
4296                                         return;
4297
4298                                 int target_x;
4299                                 if (drag_to_index == owner.Columns.Count)
4300                                         target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
4301                                 else
4302                                         target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
4303                                 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
4304                         }
4305
4306                         protected override void WndProc (ref Message m)
4307                         {
4308                                 switch ((Msg)m.Msg) {
4309                                 case Msg.WM_SETFOCUS:
4310                                         owner.Focus ();
4311                                         break;
4312                                 default:
4313                                         base.WndProc (ref m);
4314                                         break;
4315                                 }
4316                         }
4317                 }
4318
4319                 private class ItemComparer : IComparer {
4320                         readonly SortOrder sort_order;
4321
4322                         public ItemComparer (SortOrder sortOrder)
4323                         {
4324                                 sort_order = sortOrder;
4325                         }
4326
4327                         public int Compare (object x, object y)
4328                         {
4329                                 ListViewItem item_x = x as ListViewItem;
4330                                 ListViewItem item_y = y as ListViewItem;
4331                                 if (sort_order == SortOrder.Ascending)
4332                                         return String.Compare (item_x.Text, item_y.Text);
4333                                 else
4334                                         return String.Compare (item_y.Text, item_x.Text);
4335                         }
4336                 }
4337
4338 #if NET_2_0
4339                 [ListBindable (false)]
4340 #endif
4341                 public class CheckedIndexCollection : IList, ICollection, IEnumerable
4342                 {
4343                         private readonly ListView owner;
4344
4345                         #region Public Constructor
4346                         public CheckedIndexCollection (ListView owner)
4347                         {
4348                                 this.owner = owner;
4349                         }
4350                         #endregion      // Public Constructor
4351
4352                         #region Public Properties
4353                         [Browsable (false)]
4354                         public int Count {
4355                                 get { return owner.CheckedItems.Count; }
4356                         }
4357
4358                         public bool IsReadOnly {
4359                                 get { return true; }
4360                         }
4361
4362                         public int this [int index] {
4363                                 get {
4364                                         int [] indices = GetIndices ();
4365                                         if (index < 0 || index >= indices.Length)
4366                                                 throw new ArgumentOutOfRangeException ("index");
4367                                         return indices [index];
4368                                 }
4369                         }
4370
4371                         bool ICollection.IsSynchronized {
4372                                 get { return false; }
4373                         }
4374
4375                         object ICollection.SyncRoot {
4376                                 get { return this; }
4377                         }
4378
4379                         bool IList.IsFixedSize {
4380                                 get { return true; }
4381                         }
4382
4383                         object IList.this [int index] {
4384                                 get { return this [index]; }
4385                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4386                         }
4387                         #endregion      // Public Properties
4388
4389                         #region Public Methods
4390                         public bool Contains (int checkedIndex)
4391                         {
4392                                 int [] indices = GetIndices ();
4393                                 for (int i = 0; i < indices.Length; i++) {
4394                                         if (indices [i] == checkedIndex)
4395                                                 return true;
4396                                 }
4397                                 return false;
4398                         }
4399
4400                         public IEnumerator GetEnumerator ()
4401                         {
4402                                 int [] indices = GetIndices ();
4403                                 return indices.GetEnumerator ();
4404                         }
4405
4406                         void ICollection.CopyTo (Array dest, int index)
4407                         {
4408                                 int [] indices = GetIndices ();
4409                                 Array.Copy (indices, 0, dest, index, indices.Length);
4410                         }
4411
4412                         int IList.Add (object value)
4413                         {
4414                                 throw new NotSupportedException ("Add operation is not supported.");
4415                         }
4416
4417                         void IList.Clear ()
4418                         {
4419                                 throw new NotSupportedException ("Clear operation is not supported.");
4420                         }
4421
4422                         bool IList.Contains (object checkedIndex)
4423                         {
4424                                 if (!(checkedIndex is int))
4425                                         return false;
4426                                 return Contains ((int) checkedIndex);
4427                         }
4428
4429                         int IList.IndexOf (object checkedIndex)
4430                         {
4431                                 if (!(checkedIndex is int))
4432                                         return -1;
4433                                 return IndexOf ((int) checkedIndex);
4434                         }
4435
4436                         void IList.Insert (int index, object value)
4437                         {
4438                                 throw new NotSupportedException ("Insert operation is not supported.");
4439                         }
4440
4441                         void IList.Remove (object value)
4442                         {
4443                                 throw new NotSupportedException ("Remove operation is not supported.");
4444                         }
4445
4446                         void IList.RemoveAt (int index)
4447                         {
4448                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
4449                         }
4450
4451                         public int IndexOf (int checkedIndex)
4452                         {
4453                                 int [] indices = GetIndices ();
4454                                 for (int i = 0; i < indices.Length; i++) {
4455                                         if (indices [i] == checkedIndex)
4456                                                 return i;
4457                                 }
4458                                 return -1;
4459                         }
4460                         #endregion      // Public Methods
4461
4462                         private int [] GetIndices ()
4463                         {
4464                                 ArrayList checked_items = owner.CheckedItems.List;
4465                                 int [] indices = new int [checked_items.Count];
4466                                 for (int i = 0; i < checked_items.Count; i++) {
4467                                         ListViewItem item = (ListViewItem) checked_items [i];
4468                                         indices [i] = item.Index;
4469                                 }
4470                                 return indices;
4471                         }
4472                 }       // CheckedIndexCollection
4473
4474 #if NET_2_0
4475                 [ListBindable (false)]
4476 #endif
4477                 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
4478                 {
4479                         private readonly ListView owner;
4480                         private ArrayList list;
4481
4482                         #region Public Constructor
4483                         public CheckedListViewItemCollection (ListView owner)
4484                         {
4485                                 this.owner = owner;
4486                                 this.owner.Items.Changed += new CollectionChangedHandler (
4487                                         ItemsCollection_Changed);
4488                         }
4489                         #endregion      // Public Constructor
4490
4491                         #region Public Properties
4492                         [Browsable (false)]
4493                         public int Count {
4494                                 get {
4495                                         if (!owner.CheckBoxes)
4496                                                 return 0;
4497                                         return List.Count;
4498                                 }
4499                         }
4500
4501                         public bool IsReadOnly {
4502                                 get { return true; }
4503                         }
4504
4505                         public ListViewItem this [int index] {
4506                                 get {
4507 #if NET_2_0
4508                                         if (owner.VirtualMode)
4509                                                 throw new InvalidOperationException ();
4510 #endif
4511                                         ArrayList checked_items = List;
4512                                         if (index < 0 || index >= checked_items.Count)
4513                                                 throw new ArgumentOutOfRangeException ("index");
4514                                         return (ListViewItem) checked_items [index];
4515                                 }
4516                         }
4517
4518 #if NET_2_0
4519                         public virtual ListViewItem this [string key] {
4520                                 get {
4521                                         int idx = IndexOfKey (key);
4522                                         return idx == -1 ? null : (ListViewItem) List [idx];
4523                                 }
4524                         }
4525 #endif
4526
4527                         bool ICollection.IsSynchronized {
4528                                 get { return false; }
4529                         }
4530
4531                         object ICollection.SyncRoot {
4532                                 get { return this; }
4533                         }
4534
4535                         bool IList.IsFixedSize {
4536                                 get { return true; }
4537                         }
4538
4539                         object IList.this [int index] {
4540                                 get { return this [index]; }
4541                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4542                         }
4543                         #endregion      // Public Properties
4544
4545                         #region Public Methods
4546                         public bool Contains (ListViewItem item)
4547                         {
4548                                 if (!owner.CheckBoxes)
4549                                         return false;
4550                                 return List.Contains (item);
4551                         }
4552
4553 #if NET_2_0
4554                         public virtual bool ContainsKey (string key)
4555                         {
4556                                 return IndexOfKey (key) != -1;
4557                         }
4558 #endif
4559
4560                         public void CopyTo (Array dest, int index)
4561                         {
4562 #if NET_2_0
4563                                 if (owner.VirtualMode)
4564                                         throw new InvalidOperationException ();
4565 #endif
4566                                 if (!owner.CheckBoxes)
4567                                         return;
4568                                 List.CopyTo (dest, index);
4569                         }
4570
4571                         public IEnumerator GetEnumerator ()
4572                         {
4573 #if NET_2_0
4574                                 if (owner.VirtualMode)
4575                                         throw new InvalidOperationException ();
4576 #endif
4577                                 if (!owner.CheckBoxes)
4578                                         return (new ListViewItem [0]).GetEnumerator ();
4579                                 return List.GetEnumerator ();
4580                         }
4581
4582                         int IList.Add (object value)
4583                         {
4584                                 throw new NotSupportedException ("Add operation is not supported.");
4585                         }
4586
4587                         void IList.Clear ()
4588                         {
4589                                 throw new NotSupportedException ("Clear operation is not supported.");
4590                         }
4591
4592                         bool IList.Contains (object item)
4593                         {
4594                                 if (!(item is ListViewItem))
4595                                         return false;
4596                                 return Contains ((ListViewItem) item);
4597                         }
4598
4599                         int IList.IndexOf (object item)
4600                         {
4601                                 if (!(item is ListViewItem))
4602                                         return -1;
4603                                 return IndexOf ((ListViewItem) item);
4604                         }
4605
4606                         void IList.Insert (int index, object value)
4607                         {
4608                                 throw new NotSupportedException ("Insert operation is not supported.");
4609                         }
4610
4611                         void IList.Remove (object value)
4612                         {
4613                                 throw new NotSupportedException ("Remove operation is not supported.");
4614                         }
4615
4616                         void IList.RemoveAt (int index)
4617                         {
4618                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
4619                         }
4620
4621                         public int IndexOf (ListViewItem item)
4622                         {
4623 #if NET_2_0
4624                                 if (owner.VirtualMode)
4625                                         throw new InvalidOperationException ();
4626 #endif
4627                                 if (!owner.CheckBoxes)
4628                                         return -1;
4629                                 return List.IndexOf (item);
4630                         }
4631
4632 #if NET_2_0
4633                         public virtual int IndexOfKey (string key)
4634                         {
4635 #if NET_2_0
4636                                 if (owner.VirtualMode)
4637                                         throw new InvalidOperationException ();
4638 #endif
4639                                 if (key == null || key.Length == 0)
4640                                         return -1;
4641
4642                                 ArrayList checked_items = List;
4643                                 for (int i = 0; i < checked_items.Count; i++) {
4644                                         ListViewItem item = (ListViewItem) checked_items [i];
4645                                         if (String.Compare (key, item.Name, true) == 0)
4646                                                 return i;
4647                                 }
4648
4649                                 return -1;
4650                         }
4651 #endif
4652                         #endregion      // Public Methods
4653
4654                         internal ArrayList List {
4655                                 get {
4656                                         if (list == null) {
4657                                                 list = new ArrayList ();
4658                                                 foreach (ListViewItem item in owner.Items) {
4659                                                         if (item.Checked)
4660                                                                 list.Add (item);
4661                                                 }
4662                                         }
4663                                         return list;
4664                                 }
4665                         }
4666
4667                         internal void Reset ()
4668                         {
4669                                 // force re-population of list
4670                                 list = null;
4671                         }
4672
4673                         private void ItemsCollection_Changed ()
4674                         {
4675                                 Reset ();
4676                         }
4677                 }       // CheckedListViewItemCollection
4678
4679 #if NET_2_0
4680                 [ListBindable (false)]
4681 #endif
4682                 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
4683                 {
4684                         internal ArrayList list;
4685                         private ListView owner;
4686
4687                         #region UIA Framework Events 
4688 #if NET_2_0
4689                         //NOTE:
4690                         //      We are using Reflection to add/remove internal events.
4691                         //      Class ListViewProvider uses the events when View is Details.
4692                         //
4693                         //Event used to generate UIA StructureChangedEvent
4694                         static object UIACollectionChangedEvent = new object ();
4695
4696                         internal event CollectionChangeEventHandler UIACollectionChanged {
4697                                 add { 
4698                                         if (owner != null)
4699                                                 owner.Events.AddHandler (UIACollectionChangedEvent, value); 
4700                                 }
4701                                 remove { 
4702                                         if (owner != null)
4703                                                 owner.Events.RemoveHandler (UIACollectionChangedEvent, value); 
4704                                 }
4705                         }
4706
4707                         internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
4708                         {
4709                                 if (owner == null)
4710                                         return;
4711
4712                                 CollectionChangeEventHandler eh
4713                                         = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
4714                                 if (eh != null)
4715                                         eh (owner, args);
4716                         }
4717
4718 #endif
4719                         #endregion UIA Framework Events 
4720
4721                         #region Public Constructor
4722                         public ColumnHeaderCollection (ListView owner)
4723                         {
4724                                 list = new ArrayList ();
4725                                 this.owner = owner;
4726                         }
4727                         #endregion      // Public Constructor
4728
4729                         #region Public Properties
4730                         [Browsable (false)]
4731                         public int Count {
4732                                 get { return list.Count; }
4733                         }
4734
4735                         public bool IsReadOnly {
4736                                 get { return false; }
4737                         }
4738
4739                         public virtual ColumnHeader this [int index] {
4740                                 get {
4741                                         if (index < 0 || index >= list.Count)
4742                                                 throw new ArgumentOutOfRangeException ("index");
4743                                         return (ColumnHeader) list [index];
4744                                 }
4745                         }
4746
4747 #if NET_2_0
4748                         public virtual ColumnHeader this [string key] {
4749                                 get {
4750                                         int idx = IndexOfKey (key);
4751                                         if (idx == -1)
4752                                                 return null;
4753
4754                                         return (ColumnHeader) list [idx];
4755                                 }
4756                         }
4757 #endif
4758
4759                         bool ICollection.IsSynchronized {
4760                                 get { return true; }
4761                         }
4762
4763                         object ICollection.SyncRoot {
4764                                 get { return this; }
4765                         }
4766
4767                         bool IList.IsFixedSize {
4768                                 get { return list.IsFixedSize; }
4769                         }
4770
4771                         object IList.this [int index] {
4772                                 get { return this [index]; }
4773                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4774                         }
4775                         #endregion      // Public Properties
4776
4777                         #region Public Methods
4778                         public virtual int Add (ColumnHeader value)
4779                         {
4780                                 int idx = list.Add (value);
4781                                 owner.AddColumn (value, idx, true);
4782
4783 #if NET_2_0
4784                                 //UIA Framework event: Item Added
4785                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
4786 #endif
4787
4788                                 return idx;
4789                         }
4790
4791 #if NET_2_0
4792                         public virtual ColumnHeader Add (string text, int width, HorizontalAlignment textAlign)
4793                         {
4794                                 string str = text;
4795 #else
4796                         public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
4797                         {
4798 #endif
4799                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
4800                                 this.Add (colHeader);
4801                                 return colHeader;
4802                         }
4803
4804 #if NET_2_0
4805                         public virtual ColumnHeader Add (string text)
4806                         {
4807                                 return Add (String.Empty, text);
4808                         }
4809
4810                         public virtual ColumnHeader Add (string text, int width)
4811                         {
4812                                 return Add (String.Empty, text, width);
4813                         }
4814
4815                         public virtual ColumnHeader Add (string key, string text)
4816                         {
4817                                 ColumnHeader colHeader = new ColumnHeader ();
4818                                 colHeader.Name = key;
4819                                 colHeader.Text = text;
4820                                 Add (colHeader);
4821                                 return colHeader;
4822                         }
4823
4824                         public virtual ColumnHeader Add (string key, string text, int width)
4825                         {
4826                                 return Add (key, text, width, HorizontalAlignment.Left, -1);
4827                         }
4828
4829                         public virtual ColumnHeader Add (string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
4830                         {
4831                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4832                                 colHeader.ImageIndex = imageIndex;
4833                                 Add (colHeader);
4834                                 return colHeader;
4835                         }
4836
4837                         public virtual ColumnHeader Add (string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
4838                         {
4839                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4840                                 colHeader.ImageKey = imageKey;
4841                                 Add (colHeader);
4842                                 return colHeader;
4843                         }
4844 #endif
4845
4846                         public virtual void AddRange (ColumnHeader [] values)
4847                         {
4848                                 foreach (ColumnHeader colHeader in values) {
4849                                         int idx = list.Add (colHeader);
4850                                         owner.AddColumn (colHeader, idx, false);
4851                                 }
4852                                 
4853                                 owner.Redraw (true);
4854                         }
4855
4856                         public virtual void Clear ()
4857                         {
4858                                 foreach (ColumnHeader col in list)
4859                                         col.SetListView (null);
4860                                 list.Clear ();
4861                                 owner.ReorderColumns (new int [0], true);
4862
4863 #if NET_2_0
4864                                 //UIA Framework event: Items cleared
4865                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
4866 #endif
4867
4868                         }
4869
4870                         public bool Contains (ColumnHeader value)
4871                         {
4872                                 return list.Contains (value);
4873                         }
4874
4875 #if NET_2_0
4876                         public virtual bool ContainsKey (string key)
4877                         {
4878                                 return IndexOfKey (key) != -1;
4879                         }
4880 #endif
4881
4882                         public IEnumerator GetEnumerator ()
4883                         {
4884                                 return list.GetEnumerator ();
4885                         }
4886
4887                         void ICollection.CopyTo (Array dest, int index)
4888                         {
4889                                 list.CopyTo (dest, index);
4890                         }
4891
4892                         int IList.Add (object value)
4893                         {
4894                                 if (! (value is ColumnHeader)) {
4895                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
4896                                 }
4897
4898                                 return this.Add ((ColumnHeader) value);
4899                         }
4900
4901                         bool IList.Contains (object value)
4902                         {
4903                                 if (! (value is ColumnHeader)) {
4904                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
4905                                 }
4906
4907                                 return this.Contains ((ColumnHeader) value);
4908                         }
4909
4910                         int IList.IndexOf (object value)
4911                         {
4912                                 if (! (value is ColumnHeader)) {
4913                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
4914                                 }
4915
4916                                 return this.IndexOf ((ColumnHeader) value);
4917                         }
4918
4919                         void IList.Insert (int index, object value)
4920                         {
4921                                 if (! (value is ColumnHeader)) {
4922                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
4923                                 }
4924
4925                                 this.Insert (index, (ColumnHeader) value);
4926                         }
4927
4928                         void IList.Remove (object value)
4929                         {
4930                                 if (! (value is ColumnHeader)) {
4931                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
4932                                 }
4933
4934                                 this.Remove ((ColumnHeader) value);
4935                         }
4936
4937                         public int IndexOf (ColumnHeader value)
4938                         {
4939                                 return list.IndexOf (value);
4940                         }
4941
4942 #if NET_2_0
4943                         public virtual int IndexOfKey (string key)
4944                         {
4945                                 if (key == null || key.Length == 0)
4946                                         return -1;
4947
4948                                 for (int i = 0; i < list.Count; i++) {
4949                                         ColumnHeader col = (ColumnHeader) list [i];
4950                                         if (String.Compare (key, col.Name, true) == 0)
4951                                                 return i;
4952                                 }
4953
4954                                 return -1;
4955                         }
4956 #endif
4957
4958                         public void Insert (int index, ColumnHeader value)
4959                         {
4960                                 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
4961                                 // but it's really only greater.
4962                                 if (index < 0 || index > list.Count)
4963                                         throw new ArgumentOutOfRangeException ("index");
4964
4965                                 list.Insert (index, value);
4966                                 owner.AddColumn (value, index, true);
4967
4968 #if NET_2_0
4969                                 //UIA Framework event: Item added
4970                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
4971 #endif
4972                         }
4973
4974 #if NET_2_0
4975                         public void Insert (int index, string text)
4976                         {
4977                                 Insert (index, String.Empty, text);
4978                         }
4979
4980                         public void Insert (int index, string text, int width)
4981                         {
4982                                 Insert (index, String.Empty, text, width);
4983                         }
4984
4985                         public void Insert (int index, string key, string text)
4986                         {
4987                                 ColumnHeader colHeader = new ColumnHeader ();
4988                                 colHeader.Name = key;
4989                                 colHeader.Text = text;
4990                                 Insert (index, colHeader);
4991                         }
4992
4993                         public void Insert (int index, string key, string text, int width)
4994                         {
4995                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
4996                                 Insert (index, colHeader);
4997                         }
4998
4999                         public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
5000                         {
5001                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
5002                                 colHeader.ImageIndex = imageIndex;
5003                                 Insert (index, colHeader);
5004                         }
5005
5006                         public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
5007                         {
5008                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
5009                                 colHeader.ImageKey = imageKey;
5010                                 Insert (index, colHeader);
5011                         }
5012 #endif
5013
5014 #if NET_2_0
5015                         public void Insert (int index, string text, int width, HorizontalAlignment textAlign)
5016                         {
5017                                 string str = text;
5018 #else
5019                         public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
5020                         {
5021 #endif
5022                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
5023                                 this.Insert (index, colHeader);
5024                         }
5025
5026                         public virtual void Remove (ColumnHeader column)
5027                         {
5028                                 if (!Contains (column))
5029                                         return;
5030
5031                                 list.Remove (column);
5032                                 column.SetListView (null);
5033
5034                                 int rem_display_index = column.InternalDisplayIndex;
5035                                 int [] display_indices = new int [list.Count];
5036                                 for (int i = 0; i < display_indices.Length; i++) {
5037                                         ColumnHeader col = (ColumnHeader) list [i];
5038                                         int display_index = col.InternalDisplayIndex;
5039                                         if (display_index < rem_display_index) {
5040                                                 display_indices [i] = display_index;
5041                                         } else {
5042                                                 display_indices [i] = (display_index - 1);
5043                                         }
5044                                 }
5045
5046                                 column.InternalDisplayIndex = -1;
5047                                 owner.ReorderColumns (display_indices, true);
5048
5049 #if NET_2_0
5050                                 //UIA Framework event: Item Removed
5051                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, column));
5052 #endif
5053                         }
5054
5055 #if NET_2_0
5056                         public virtual void RemoveByKey (string key)
5057                         {
5058                                 int idx = IndexOfKey (key);
5059                                 if (idx != -1)
5060                                         RemoveAt (idx);
5061                         }
5062 #endif
5063
5064                         public virtual void RemoveAt (int index)
5065                         {
5066                                 if (index < 0 || index >= list.Count)
5067                                         throw new ArgumentOutOfRangeException ("index");
5068
5069                                 ColumnHeader col = (ColumnHeader) list [index];
5070                                 Remove (col);
5071                         }
5072                         #endregion      // Public Methods
5073                         
5074
5075                 }       // ColumnHeaderCollection
5076
5077 #if NET_2_0
5078                 [ListBindable (false)]
5079 #endif
5080                 public class ListViewItemCollection : IList, ICollection, IEnumerable
5081                 {
5082                         private readonly ArrayList list;
5083                         private ListView owner;
5084 #if NET_2_0
5085                         private ListViewGroup group;
5086 #endif
5087
5088                         #region UIA Framework Events 
5089 #if NET_2_0
5090                         //NOTE:
5091                         //      We are using Reflection to add/remove internal events.
5092                         //      Class ListViewProvider uses the events.
5093                         //
5094                         //Event used to generate UIA StructureChangedEvent
5095                         static object UIACollectionChangedEvent = new object ();
5096
5097                         internal event CollectionChangeEventHandler UIACollectionChanged {
5098                                 add { 
5099                                         if (owner != null)
5100                                                 owner.Events.AddHandler (UIACollectionChangedEvent, value); 
5101                                 }
5102                                 remove { 
5103                                         if (owner != null)
5104                                                 owner.Events.RemoveHandler (UIACollectionChangedEvent, value); 
5105                                 }
5106                         }
5107
5108                         internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
5109                         {
5110                                 if (owner == null)
5111                                         return;
5112
5113                                 CollectionChangeEventHandler eh
5114                                         = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
5115                                 if (eh != null)
5116                                         eh (owner, args);
5117                         }
5118
5119 #endif
5120                         #endregion UIA Framework Events 
5121
5122                         // The collection can belong to a ListView (main) or to a ListViewGroup (sub-collection)
5123                         // In the later case ListViewItem.ListView never gets modified
5124                         private bool is_main_collection = true;
5125
5126                         #region Public Constructor
5127                         public ListViewItemCollection (ListView owner)
5128                         {
5129                                 list = new ArrayList (0);
5130                                 this.owner = owner;
5131                         }
5132                         #endregion      // Public Constructor
5133
5134 #if NET_2_0
5135                         internal ListViewItemCollection (ListView owner, ListViewGroup group) : this (owner)
5136                         {
5137                                 this.group = group;
5138                                 is_main_collection = false;
5139                         }
5140 #endif
5141
5142                         #region Public Properties
5143                         [Browsable (false)]
5144                         public int Count {
5145                                 get {
5146 #if NET_2_0
5147                                         if (owner != null && owner.VirtualMode)
5148                                                 return owner.VirtualListSize;
5149 #endif
5150
5151                                         return list.Count; 
5152                                 }
5153                         }
5154
5155                         public bool IsReadOnly {
5156                                 get { return false; }
5157                         }
5158
5159 #if NET_2_0
5160                         public virtual ListViewItem this [int index] {
5161 #else
5162                         public virtual ListViewItem this [int displayIndex] {
5163 #endif
5164                                 get {
5165 #if !NET_2_0
5166                                         int index = displayIndex;
5167 #endif
5168
5169                                         if (index < 0 || index >= Count)
5170                                                 throw new ArgumentOutOfRangeException ("index");
5171
5172 #if NET_2_0
5173                                         if (owner != null && owner.VirtualMode)
5174                                                 return RetrieveVirtualItemFromOwner (index);
5175 #endif
5176                                         return (ListViewItem) list [index];
5177                                 }
5178
5179                                 set {
5180 #if !NET_2_0
5181                                         int index = displayIndex;
5182 #endif
5183
5184                                         if (index < 0 || index >= Count)
5185                                                 throw new ArgumentOutOfRangeException ("index");
5186
5187 #if NET_2_0
5188                                         if (owner != null && owner.VirtualMode)
5189                                                 throw new InvalidOperationException ();
5190 #endif
5191
5192                                         if (list.Contains (value))
5193                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
5194
5195                                         if (value.ListView != null && value.ListView != owner)
5196                                                 throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
5197
5198                                         if (is_main_collection)
5199                                                 value.Owner = owner;
5200 #if NET_2_0
5201                                         else {
5202                                                 if (value.Group != null)
5203                                                         value.Group.Items.Remove (value);
5204
5205                                                 value.SetGroup (group);
5206                                         }
5207 #endif
5208
5209 #if NET_2_0
5210                                         //UIA Framework event: Item Replaced
5211                                         OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, list [index]));
5212 #endif
5213
5214                                         list [index] = value;
5215
5216                                         CollectionChanged (true);
5217
5218 #if NET_2_0
5219                                         //UIA Framework event: Item Replaced
5220                                         OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5221 #endif
5222
5223                                 }
5224                         }
5225
5226 #if NET_2_0
5227                         public virtual ListViewItem this [string key] {
5228                                 get {
5229                                         int idx = IndexOfKey (key);
5230                                         if (idx == -1)
5231                                                 return null;
5232
5233                                         return this [idx];
5234                                 }
5235                         }
5236 #endif
5237
5238                         bool ICollection.IsSynchronized {
5239                                 get { return true; }
5240                         }
5241
5242                         object ICollection.SyncRoot {
5243                                 get { return this; }
5244                         }
5245
5246                         bool IList.IsFixedSize {
5247                                 get { return list.IsFixedSize; }
5248                         }
5249
5250                         object IList.this [int index] {
5251                                 get { return this [index]; }
5252                                 set {
5253 #if NET_2_0
5254                                         //UIA Framework event: Item Replaced
5255                                         OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, this [index]));
5256 #endif
5257
5258                                         if (value is ListViewItem)
5259                                                 this [index] = (ListViewItem) value;
5260                                         else
5261                                                 this [index] = new ListViewItem (value.ToString ());
5262
5263                                         OnChange ();
5264 #if NET_2_0
5265                                         //UIA Framework event: Item Replaced
5266                                         OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5267 #endif
5268                                 }
5269                         }
5270                         #endregion      // Public Properties
5271
5272                         #region Public Methods
5273                         public virtual ListViewItem Add (ListViewItem value)
5274                         {
5275 #if NET_2_0
5276                                 if (owner != null && owner.VirtualMode)
5277                                         throw new InvalidOperationException ();
5278 #endif
5279
5280                                 AddItem (value);
5281
5282                                 // Item is ignored until it has been added to the ListView
5283                                 if (is_main_collection || value.ListView != null)
5284                                         CollectionChanged (true);
5285
5286 #if NET_2_0
5287                                 //UIA Framework event: Item Added
5288                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5289 #endif
5290
5291                                 return value;
5292                         }
5293
5294                         public virtual ListViewItem Add (string text)
5295                         {
5296                                 ListViewItem item = new ListViewItem (text);
5297                                 return this.Add (item);
5298                         }
5299
5300                         public virtual ListViewItem Add (string text, int imageIndex)
5301                         {
5302                                 ListViewItem item = new ListViewItem (text, imageIndex);
5303                                 return this.Add (item);
5304                         }
5305
5306 #if NET_2_0
5307                         public virtual ListViewItem Add (string text, string imageKey)
5308                         {
5309                                 ListViewItem item = new ListViewItem (text, imageKey);
5310                                 return this.Add (item);
5311                         }
5312
5313                         public virtual ListViewItem Add (string key, string text, int imageIndex)
5314                         {
5315                                 ListViewItem item = new ListViewItem (text, imageIndex);
5316                                 item.Name = key;
5317                                 return this.Add (item);
5318                         }
5319
5320                         public virtual ListViewItem Add (string key, string text, string imageKey)
5321                         {
5322                                 ListViewItem item = new ListViewItem (text, imageKey);
5323                                 item.Name = key;
5324                                 return this.Add (item);
5325                         }
5326 #endif
5327
5328 #if NET_2_0
5329                         public void AddRange (ListViewItem [] items)
5330                         {
5331 #else
5332                         public void AddRange (ListViewItem [] values)
5333                         {
5334                                 ListViewItem [] items = values;
5335 #endif
5336                                 if (items == null)
5337                                         throw new ArgumentNullException ("Argument cannot be null!", "items");
5338 #if NET_2_0
5339                                 if (owner != null && owner.VirtualMode)
5340                                         throw new InvalidOperationException ();
5341 #endif
5342
5343                                 owner.BeginUpdate ();
5344                                 
5345                                 foreach (ListViewItem item in items) {
5346                                         AddItem (item);
5347
5348 #if NET_2_0
5349                                         //UIA Framework event: Item Added
5350                                         OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
5351 #endif
5352                                 }
5353
5354                                 owner.EndUpdate ();
5355                                 
5356                                 CollectionChanged (true);
5357                         }
5358
5359 #if NET_2_0
5360                         public void AddRange (ListViewItemCollection items)
5361                         {
5362                                 if (items == null)
5363                                         throw new ArgumentNullException ("Argument cannot be null!", "items");
5364
5365                                 ListViewItem[] itemArray = new ListViewItem[items.Count];
5366                                 items.CopyTo (itemArray,0);
5367                                 this.AddRange (itemArray);
5368                         }
5369 #endif
5370
5371                         public virtual void Clear ()
5372                         {
5373 #if NET_2_0
5374                                 if (owner != null && owner.VirtualMode)
5375                                         throw new InvalidOperationException ();
5376 #endif
5377                                 if (is_main_collection && owner != null) {
5378                                         owner.SetFocusedItem (-1);
5379                                         owner.h_scroll.Value = owner.v_scroll.Value = 0;
5380
5381 #if NET_2_0
5382                                         // first remove any item in the groups that *are* part of this LV too
5383                                         foreach (ListViewGroup group in owner.groups)
5384                                                 group.Items.ClearItemsWithSameListView ();
5385 #endif
5386                                 
5387                                         foreach (ListViewItem item in list) {
5388                                                 owner.item_control.CancelEdit (item);
5389                                                 item.Owner = null;
5390                                         }
5391                                 }
5392 #if NET_2_0
5393                                 else
5394                                         foreach (ListViewItem item in list)
5395                                                 item.SetGroup (null);
5396 #endif
5397
5398                                 list.Clear ();
5399                                 CollectionChanged (false);
5400
5401 #if NET_2_0
5402                                 //UIA Framework event: Items Removed
5403                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
5404 #endif
5405
5406                         }
5407
5408 #if NET_2_0
5409                         // This method is intended to be used from ListViewGroup.Items, not from ListView.Items,
5410                         // added for performance reasons (avoid calling manually Remove for every item on ListViewGroup.Items)
5411                         void ClearItemsWithSameListView ()
5412                         {
5413                                 if (is_main_collection)
5414                                         return;
5415
5416                                 int counter = list.Count - 1;
5417                                 while (counter >= 0) {
5418                                         ListViewItem item = list [counter] as ListViewItem;
5419
5420                                         // remove only if the items in group have being added to the ListView too
5421                                         if (item.ListView == group.ListView) {
5422                                                 list.RemoveAt (counter);
5423                                                 item.SetGroup (null);
5424                                         }
5425                                                 
5426                                         counter--;
5427                                 }
5428                         }
5429 #endif
5430
5431                         public bool Contains (ListViewItem item)
5432                         {
5433                                 return IndexOf (item) != -1;
5434                         }
5435
5436 #if NET_2_0
5437                         public virtual bool ContainsKey (string key)
5438                         {
5439                                 return IndexOfKey (key) != -1;
5440                         }
5441 #endif
5442
5443                         public void CopyTo (Array dest, int index)
5444                         {
5445                                 list.CopyTo (dest, index);
5446                         }
5447
5448 #if NET_2_0
5449                         public ListViewItem [] Find (string key, bool searchAllSubItems)
5450                         {
5451                                 if (key == null)
5452                                         return new ListViewItem [0];
5453
5454                                 List<ListViewItem> temp_list = new List<ListViewItem> ();
5455                                 
5456                                 for (int i = 0; i < list.Count; i++) {
5457                                         ListViewItem lvi = (ListViewItem) list [i];
5458                                         if (String.Compare (key, lvi.Name, true) == 0)
5459                                                 temp_list.Add (lvi);
5460                                 }
5461
5462                                 ListViewItem [] retval = new ListViewItem [temp_list.Count];
5463                                 temp_list.CopyTo (retval);
5464
5465                                 return retval;
5466                         }
5467 #endif
5468
5469                         public IEnumerator GetEnumerator ()
5470                         {
5471 #if NET_2_0
5472                                 if (owner != null && owner.VirtualMode)
5473                                         throw new InvalidOperationException ();
5474 #endif
5475
5476                                 // This enumerator makes a copy of the collection so
5477                                 // it can be deleted from in a foreach
5478                                 return new Control.ControlCollection.ControlCollectionEnumerator (list);
5479                         }
5480
5481                         int IList.Add (object item)
5482                         {
5483                                 int result;
5484                                 ListViewItem li;
5485
5486 #if NET_2_0
5487                                 if (owner != null && owner.VirtualMode)
5488                                         throw new InvalidOperationException ();
5489 #endif
5490
5491                                 if (item is ListViewItem) {
5492                                         li = (ListViewItem) item;
5493                                         if (list.Contains (li))
5494                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
5495
5496                                         if (li.ListView != null && li.ListView != owner)
5497                                                 throw new ArgumentException ("Cannot add or insert the item '" + li.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
5498                                 }
5499                                 else
5500                                         li = new ListViewItem (item.ToString ());
5501
5502                                 li.Owner = owner;
5503                                 
5504                                 
5505                                 result = list.Add (li);
5506                                 CollectionChanged (true);
5507
5508 #if NET_2_0
5509                                 //UIA Framework event: Item Added
5510                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, li));
5511 #endif
5512
5513                                 return result;
5514                         }
5515
5516                         bool IList.Contains (object item)
5517                         {
5518                                 return Contains ((ListViewItem) item);
5519                         }
5520
5521                         int IList.IndexOf (object item)
5522                         {
5523                                 return IndexOf ((ListViewItem) item);
5524                         }
5525
5526                         void IList.Insert (int index, object item)
5527                         {
5528                                 if (item is ListViewItem)
5529                                         this.Insert (index, (ListViewItem) item);
5530                                 else
5531                                         this.Insert (index, item.ToString ());
5532
5533 #if NET_2_0
5534                                 //UIA Framework event: Item Added
5535                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, this [index]));
5536 #endif
5537                         }
5538
5539                         void IList.Remove (object item)
5540                         {
5541                                 Remove ((ListViewItem) item);
5542                         }
5543
5544                         public int IndexOf (ListViewItem item)
5545                         {
5546 #if NET_2_0
5547                                 if (owner != null && owner.VirtualMode) {
5548                                         for (int i = 0; i < Count; i++)
5549                                                 if (RetrieveVirtualItemFromOwner (i) == item)
5550                                                         return i;
5551
5552                                         return -1;
5553                                 }
5554 #endif
5555                                 
5556                                 return list.IndexOf (item);
5557                         }
5558
5559 #if NET_2_0
5560                         public virtual int IndexOfKey (string key)
5561                         {
5562                                 if (key == null || key.Length == 0)
5563                                         return -1;
5564
5565                                 for (int i = 0; i < Count; i++) {
5566                                         ListViewItem lvi = this [i];
5567                                         if (String.Compare (key, lvi.Name, true) == 0)
5568                                                 return i;
5569                                 }
5570
5571                                 return -1;
5572                         }
5573 #endif
5574
5575                         public ListViewItem Insert (int index, ListViewItem item)
5576                         {
5577                                 if (index < 0 || index > list.Count)
5578                                         throw new ArgumentOutOfRangeException ("index");
5579
5580 #if NET_2_0
5581                                 if (owner != null && owner.VirtualMode)
5582                                         throw new InvalidOperationException ();
5583 #endif
5584
5585                                 if (list.Contains (item))
5586                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
5587
5588                                 if (item.ListView != null && item.ListView != owner)
5589                                         throw new ArgumentException ("Cannot add or insert the item '" + item.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
5590
5591                                 if (is_main_collection)
5592                                         item.Owner = owner;
5593 #if NET_2_0
5594                                 else {
5595                                         if (item.Group != null)
5596                                                 item.Group.Items.Remove (item);
5597
5598                                         item.SetGroup (group);
5599                                 }
5600 #endif
5601
5602                                 list.Insert (index, item);
5603
5604                                 if (is_main_collection || item.ListView != null)
5605                                         CollectionChanged (true);
5606
5607 #if NET_2_0
5608                                 //UIA Framework event: Item Added
5609                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
5610 #endif
5611
5612                                 return item;
5613                         }
5614
5615                         public ListViewItem Insert (int index, string text)
5616                         {
5617                                 return this.Insert (index, new ListViewItem (text));
5618                         }
5619
5620                         public ListViewItem Insert (int index, string text, int imageIndex)
5621                         {
5622                                 return this.Insert (index, new ListViewItem (text, imageIndex));
5623                         }
5624
5625 #if NET_2_0
5626                         public ListViewItem Insert (int index, string text, string imageKey)
5627                         {
5628                                 ListViewItem lvi = new ListViewItem (text, imageKey);
5629                                 return Insert (index, lvi);
5630                         }
5631
5632                         public virtual ListViewItem Insert (int index, string key, string text, int imageIndex)
5633                         {
5634                                 ListViewItem lvi = new ListViewItem (text, imageIndex);
5635                                 lvi.Name = key;
5636                                 return Insert (index, lvi);
5637                         }
5638
5639                         public virtual ListViewItem Insert (int index, string key, string text, string imageKey)
5640                         {
5641                                 ListViewItem lvi = new ListViewItem (text, imageKey);
5642                                 lvi.Name = key;
5643                                 return Insert (index, lvi);
5644                         }
5645 #endif
5646
5647                         public virtual void Remove (ListViewItem item)
5648                         {
5649 #if NET_2_0
5650                                 if (owner != null && owner.VirtualMode)
5651                                         throw new InvalidOperationException ();
5652 #endif
5653
5654                                 int idx = list.IndexOf (item);
5655                                 if (idx != -1)
5656                                         RemoveAt (idx);
5657                         }
5658
5659                         public virtual void RemoveAt (int index)
5660                         {
5661                                 if (index < 0 || index >= Count)
5662                                         throw new ArgumentOutOfRangeException ("index");
5663
5664 #if NET_2_0
5665                                 if (owner != null && owner.VirtualMode)
5666                                         throw new InvalidOperationException ();
5667 #endif
5668
5669                                 ListViewItem item = (ListViewItem) list [index];
5670
5671                                 bool selection_changed = false;
5672                                 if (is_main_collection && owner != null) {
5673
5674                                         int display_index = item.DisplayIndex;
5675                                         if (item.Focused && display_index + 1 == Count) // Last item
5676                                                 owner.SetFocusedItem (display_index == 0 ? -1 : display_index - 1);
5677
5678                                         selection_changed = owner.SelectedIndices.Contains (index);
5679                                         owner.item_control.CancelEdit (item);
5680                                 }
5681
5682                                 list.RemoveAt (index);
5683
5684 #if NET_2_0
5685                                 if (is_main_collection) {
5686                                         item.Owner = null;
5687                                         if (item.Group != null)
5688                                                 item.Group.Items.Remove (item);
5689                                 } else
5690                                         item.SetGroup (null);
5691 #else
5692                                 item.Owner = null;
5693 #endif
5694
5695                                 CollectionChanged (false);
5696                                 if (selection_changed && owner != null)
5697                                         owner.OnSelectedIndexChanged (EventArgs.Empty);
5698
5699
5700 #if NET_2_0
5701                                 //UIA Framework event: Item Removed 
5702                                 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, item));
5703 #endif
5704                         }
5705
5706 #if NET_2_0
5707                         public virtual void RemoveByKey (string key)
5708                         {
5709                                 int idx = IndexOfKey (key);
5710                                 if (idx != -1)
5711                                         RemoveAt (idx);
5712                         }
5713 #endif
5714
5715                         #endregion      // Public Methods
5716
5717                         internal ListView Owner {
5718                                 get {
5719                                         return owner;
5720                                 }
5721                                 set {
5722                                         owner = value;
5723                                 }
5724                         }
5725
5726 #if NET_2_0
5727                         internal ListViewGroup Group {
5728                                 get {
5729                                         return group;
5730                                 }
5731                                 set {
5732                                         group = value;
5733                                 }
5734                         }
5735 #endif
5736
5737                         void AddItem (ListViewItem value)
5738                         {
5739                                 if (list.Contains (value))
5740                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
5741
5742                                 if (value.ListView != null && value.ListView != owner)
5743                                         throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
5744                                 if (is_main_collection)
5745                                         value.Owner = owner;
5746 #if NET_2_0
5747                                 else {
5748                                         if (value.Group != null)
5749                                                 value.Group.Items.Remove (value);
5750
5751                                         value.SetGroup (group);
5752                                 }
5753 #endif
5754
5755                                 list.Add (value);
5756
5757                         }
5758
5759                         void CollectionChanged (bool sort)
5760                         {
5761                                 if (owner != null) {
5762                                         if (sort)
5763                                                 owner.Sort (false);
5764
5765                                         OnChange ();
5766                                         owner.Redraw (true);
5767                                 }
5768                         }
5769
5770 #if NET_2_0
5771                         ListViewItem RetrieveVirtualItemFromOwner (int displayIndex)
5772                         {
5773                                 RetrieveVirtualItemEventArgs args = new RetrieveVirtualItemEventArgs (displayIndex);
5774
5775                                 owner.OnRetrieveVirtualItem (args);
5776                                 ListViewItem retval = args.Item;
5777                                 retval.Owner = owner;
5778                                 retval.DisplayIndex = displayIndex;
5779
5780                                 return retval;
5781                         }
5782 #endif
5783
5784                         internal event CollectionChangedHandler Changed;
5785
5786                         internal void Sort (IComparer comparer)
5787                         {
5788                                 list.Sort (comparer);
5789                                 OnChange ();
5790                         }
5791
5792                         internal void OnChange ()
5793                         {
5794                                 if (Changed != null)
5795                                         Changed ();
5796                         }
5797                 }       // ListViewItemCollection
5798
5799                         
5800                 // In normal mode, the selection information resides in the Items,
5801                 // making SelectedIndexCollection.List read-only
5802                 //
5803                 // In virtual mode, SelectedIndexCollection directly saves the selection
5804                 // information, instead of getting it from Items, making List read-and-write
5805 #if NET_2_0
5806                 [ListBindable (false)]
5807 #endif
5808                 public class SelectedIndexCollection : IList, ICollection, IEnumerable
5809                 {
5810                         private readonly ListView owner;
5811                         private ArrayList list;
5812
5813                         #region Public Constructor
5814                         public SelectedIndexCollection (ListView owner)
5815                         {
5816                                 this.owner = owner;
5817                                 owner.Items.Changed += new CollectionChangedHandler (ItemsCollection_Changed);
5818                         }
5819                         #endregion      // Public Constructor
5820
5821                         #region Public Properties
5822                         [Browsable (false)]
5823                         public int Count {
5824                                 get {
5825                                         if (!owner.IsHandleCreated)
5826                                                 return 0;
5827
5828                                         return List.Count;
5829                                 }
5830                         }
5831
5832                         public bool IsReadOnly {
5833                                 get { 
5834 #if NET_2_0
5835                                         return false;
5836 #else
5837                                         return true; 
5838 #endif
5839                                 }
5840                         }
5841
5842                         public int this [int index] {
5843                                 get {
5844                                         if (!owner.IsHandleCreated || index < 0 || index >= List.Count)
5845                                                 throw new ArgumentOutOfRangeException ("index");
5846
5847                                         return (int) List [index];
5848                                 }
5849                         }
5850
5851                         bool ICollection.IsSynchronized {
5852                                 get { return false; }
5853                         }
5854
5855                         object ICollection.SyncRoot {
5856                                 get { return this; }
5857                         }
5858
5859                         bool IList.IsFixedSize {
5860                                 get { 
5861 #if NET_2_0
5862                                         return false;
5863 #else
5864                                         return true;
5865 #endif
5866                                 }
5867                         }
5868
5869                         object IList.this [int index] {
5870                                 get { return this [index]; }
5871                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
5872                         }
5873                         #endregion      // Public Properties
5874
5875                         #region Public Methods
5876 #if NET_2_0
5877                         public int Add (int itemIndex)
5878                         {
5879                                 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5880                                         throw new ArgumentOutOfRangeException ("index");
5881
5882                                 if (owner.virtual_mode && !owner.IsHandleCreated)
5883                                         return -1;
5884
5885                                 owner.Items [itemIndex].Selected = true;
5886
5887                                 if (!owner.IsHandleCreated)
5888                                         return 0;
5889
5890                                 return List.Count;
5891                         }
5892 #endif
5893
5894 #if NET_2_0
5895                         public 
5896 #else
5897                         internal
5898 #endif  
5899                         void Clear ()
5900                         {
5901                                 if (!owner.IsHandleCreated)
5902                                         return;
5903
5904                                 int [] indexes = (int []) List.ToArray (typeof (int));
5905                                 foreach (int index in indexes)
5906                                         owner.Items [index].Selected = false;
5907                         }
5908
5909                         public bool Contains (int selectedIndex)
5910                         {
5911                                 return IndexOf (selectedIndex) != -1;
5912                         }
5913
5914                         public void CopyTo (Array dest, int index)
5915                         {
5916                                 List.CopyTo (dest, index);
5917                         }
5918
5919                         public IEnumerator GetEnumerator ()
5920                         {
5921                                 return List.GetEnumerator ();
5922                         }
5923
5924                         int IList.Add (object value)
5925                         {
5926                                 throw new NotSupportedException ("Add operation is not supported.");
5927                         }
5928
5929                         void IList.Clear ()
5930                         {
5931                                 Clear ();
5932                         }
5933
5934                         bool IList.Contains (object selectedIndex)
5935                         {
5936                                 if (!(selectedIndex is int))
5937                                         return false;
5938                                 return Contains ((int) selectedIndex);
5939                         }
5940
5941                         int IList.IndexOf (object selectedIndex)
5942                         {
5943                                 if (!(selectedIndex is int))
5944                                         return -1;
5945                                 return IndexOf ((int) selectedIndex);
5946                         }
5947
5948                         void IList.Insert (int index, object value)
5949                         {
5950                                 throw new NotSupportedException ("Insert operation is not supported.");
5951                         }
5952
5953                         void IList.Remove (object value)
5954                         {
5955                                 throw new NotSupportedException ("Remove operation is not supported.");
5956                         }
5957
5958                         void IList.RemoveAt (int index)
5959                         {
5960                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
5961                         }
5962
5963                         public int IndexOf (int selectedIndex)
5964                         {
5965                                 if (!owner.IsHandleCreated)
5966                                         return -1;
5967
5968                                 return List.IndexOf (selectedIndex);
5969                         }
5970
5971 #if NET_2_0
5972                         public void Remove (int itemIndex)
5973                         {
5974                                 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5975                                         throw new ArgumentOutOfRangeException ("itemIndex");
5976
5977                                 owner.Items [itemIndex].Selected = false;
5978                         }
5979 #endif
5980                         #endregion      // Public Methods
5981
5982                         internal ArrayList List {
5983                                 get {
5984                                         if (list == null) {
5985                                                 list = new ArrayList ();
5986 #if NET_2_0
5987                                                 if (!owner.VirtualMode)
5988 #endif
5989                                                 for (int i = 0; i < owner.Items.Count; i++) {
5990                                                         if (owner.Items [i].Selected)
5991                                                                 list.Add (i);
5992                                                 }
5993                                         }
5994                                         return list;
5995                                 }
5996                         }
5997
5998                         internal void Reset ()
5999                         {
6000                                 // force re-population of list
6001                                 list = null;
6002                         }
6003
6004                         private void ItemsCollection_Changed ()
6005                         {
6006                                 Reset ();
6007                         }
6008
6009 #if NET_2_0
6010                         internal void RemoveIndex (int index)
6011                         {
6012                                 int idx = List.BinarySearch (index);
6013                                 if (idx != -1)
6014                                         List.RemoveAt (idx);
6015                         }
6016
6017                         // actually store index in the collection
6018                         // also, keep the collection sorted, as .Net does
6019                         internal void InsertIndex (int index)
6020                         {
6021                                 int iMin = 0;
6022                                 int iMax = List.Count - 1;
6023                                 while (iMin <= iMax) {
6024                                         int iMid = (iMin + iMax) / 2;
6025                                         int current_index = (int) List [iMid];
6026
6027                                         if (current_index == index)
6028                                                 return; // Already added
6029                                         if (current_index > index)
6030                                                 iMax = iMid - 1;
6031                                         else
6032                                                 iMin = iMid + 1;
6033                                 }
6034
6035                                 List.Insert (iMin, index);
6036                         }
6037 #endif
6038
6039                 }       // SelectedIndexCollection
6040
6041 #if NET_2_0
6042                 [ListBindable (false)]
6043 #endif
6044                 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
6045                 {
6046                         private readonly ListView owner;
6047
6048                         #region Public Constructor
6049                         public SelectedListViewItemCollection (ListView owner)
6050                         {
6051                                 this.owner = owner;
6052                         }
6053                         #endregion      // Public Constructor
6054
6055                         #region Public Properties
6056                         [Browsable (false)]
6057                         public int Count {
6058                                 get {
6059                                         return owner.SelectedIndices.Count;
6060                                 }
6061                         }
6062
6063                         public bool IsReadOnly {
6064                                 get { return true; }
6065                         }
6066
6067                         public ListViewItem this [int index] {
6068                                 get {
6069                                         if (!owner.IsHandleCreated || index < 0 || index >= Count)
6070                                                 throw new ArgumentOutOfRangeException ("index");
6071
6072                                         int item_index = owner.SelectedIndices [index];
6073                                         return owner.Items [item_index];
6074                                 }
6075                         }
6076
6077 #if NET_2_0
6078                         public virtual ListViewItem this [string key] {
6079                                 get {
6080                                         int idx = IndexOfKey (key);
6081                                         if (idx == -1)
6082                                                 return null;
6083
6084                                         return this [idx];
6085                                 }
6086                         }
6087 #endif
6088
6089                         bool ICollection.IsSynchronized {
6090                                 get { return false; }
6091                         }
6092
6093                         object ICollection.SyncRoot {
6094                                 get { return this; }
6095                         }
6096
6097                         bool IList.IsFixedSize {
6098                                 get { return true; }
6099                         }
6100
6101                         object IList.this [int index] {
6102                                 get { return this [index]; }
6103                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
6104                         }
6105                         #endregion      // Public Properties
6106
6107                         #region Public Methods
6108                         public void Clear ()
6109                         {
6110                                 owner.SelectedIndices.Clear ();
6111                         }
6112
6113                         public bool Contains (ListViewItem item)
6114                         {
6115                                 return IndexOf (item) != -1;
6116                         }
6117
6118 #if NET_2_0
6119                         public virtual bool ContainsKey (string key)
6120                         {
6121                                 return IndexOfKey (key) != -1;
6122                         }
6123 #endif
6124
6125                         public void CopyTo (Array dest, int index)
6126                         {
6127                                 if (!owner.IsHandleCreated)
6128                                         return;
6129                                 if (index > Count) // Throws ArgumentException instead of IOOR exception
6130                                         throw new ArgumentException ("index");
6131
6132                                 for (int i = 0; i < Count; i++)
6133                                         dest.SetValue (this [i], index++);
6134                         }
6135
6136                         public IEnumerator GetEnumerator ()
6137                         {
6138                                 if (!owner.IsHandleCreated)
6139                                         return (new ListViewItem [0]).GetEnumerator ();
6140
6141                                 ListViewItem [] items = new ListViewItem [Count];
6142                                 for (int i = 0; i < Count; i++)
6143                                         items [i] = this [i];
6144
6145                                 return items.GetEnumerator ();
6146                         }
6147
6148                         int IList.Add (object value)
6149                         {
6150                                 throw new NotSupportedException ("Add operation is not supported.");
6151                         }
6152
6153                         bool IList.Contains (object item)
6154                         {
6155                                 if (!(item is ListViewItem))
6156                                         return false;
6157                                 return Contains ((ListViewItem) item);
6158                         }
6159
6160                         int IList.IndexOf (object item)
6161                         {
6162                                 if (!(item is ListViewItem))
6163                                         return -1;
6164                                 return IndexOf ((ListViewItem) item);
6165                         }
6166
6167                         void IList.Insert (int index, object value)
6168                         {
6169                                 throw new NotSupportedException ("Insert operation is not supported.");
6170                         }
6171
6172                         void IList.Remove (object value)
6173                         {
6174                                 throw new NotSupportedException ("Remove operation is not supported.");
6175                         }
6176
6177                         void IList.RemoveAt (int index)
6178                         {
6179                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
6180                         }
6181
6182                         public int IndexOf (ListViewItem item)
6183                         {
6184                                 if (!owner.IsHandleCreated)
6185                                         return -1;
6186
6187                                 for (int i = 0; i < Count; i++)
6188                                         if (this [i] == item)
6189                                                 return i;
6190
6191                                 return -1;
6192                         }
6193
6194 #if NET_2_0
6195                         public virtual int IndexOfKey (string key)
6196                         {
6197                                 if (!owner.IsHandleCreated || key == null || key.Length == 0)
6198                                         return -1;
6199
6200                                 for (int i = 0; i < Count; i++) {
6201                                         ListViewItem item = this [i];
6202                                         if (String.Compare (item.Name, key, true) == 0)
6203                                                 return i;
6204                                 }
6205
6206                                 return -1;
6207                         }
6208 #endif
6209                         #endregion      // Public Methods
6210
6211                 }       // SelectedListViewItemCollection
6212
6213                 internal delegate void CollectionChangedHandler ();
6214
6215                 struct ItemMatrixLocation
6216                 {
6217                         int row;
6218                         int col;
6219
6220                         public ItemMatrixLocation (int row, int col)
6221                         {
6222                                 this.row = row;
6223                                 this.col = col;
6224                 
6225                         }
6226                 
6227                         public int Col {
6228                                 get {
6229                                         return col;
6230                                 }
6231                                 set {
6232                                         col = value;
6233                                 }
6234                         }
6235
6236                         public int Row {
6237                                 get {
6238                                         return row;
6239                                 }
6240                                 set {
6241                                         row = value;
6242                                 }
6243                         }
6244         
6245                 }
6246
6247                 #endregion // Subclasses
6248 #if NET_2_0
6249                 protected override void OnResize (EventArgs e)
6250                 {
6251                         base.OnResize (e);
6252                 }
6253
6254                 protected override void OnMouseLeave (EventArgs e)
6255                 {
6256                         base.OnMouseLeave (e);
6257                 }
6258
6259                 //
6260                 // ColumnReorder event
6261                 //
6262                 static object ColumnReorderedEvent = new object ();
6263                 public event ColumnReorderedEventHandler ColumnReordered {
6264                         add { Events.AddHandler (ColumnReorderedEvent, value); }
6265                         remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
6266                 }
6267
6268                 protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
6269                 {
6270                         ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
6271
6272                         if (creh != null)
6273                                 creh (this, e);
6274                 }
6275
6276                 //
6277                 // ColumnWidthChanged
6278                 //
6279                 static object ColumnWidthChangedEvent = new object ();
6280                 public event ColumnWidthChangedEventHandler ColumnWidthChanged {
6281                         add { Events.AddHandler (ColumnWidthChangedEvent, value); }
6282                         remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
6283                 }
6284
6285                 protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
6286                 {
6287                         ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
6288                         if (eh != null)
6289                                 eh (this, e);
6290                 }
6291                 
6292                 void RaiseColumnWidthChanged (int resize_column)
6293                 {
6294                         ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
6295
6296                         OnColumnWidthChanged (n);
6297                 }
6298                 
6299                 //
6300                 // ColumnWidthChanging
6301                 //
6302                 static object ColumnWidthChangingEvent = new object ();
6303                 public event ColumnWidthChangingEventHandler ColumnWidthChanging {
6304                         add { Events.AddHandler (ColumnWidthChangingEvent, value); }
6305                         remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
6306                 }
6307
6308                 protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
6309                 {
6310                         ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
6311                         if (cwceh != null)
6312                                 cwceh (this, e);
6313                 }
6314                 
6315                 //
6316                 // 2.0 profile based implementation
6317                 //
6318                 bool CanProceedWithResize (ColumnHeader col, int width)
6319                 {
6320                         ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
6321                         if (cwceh == null)
6322                                 return true;
6323                         
6324                         ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
6325                         cwceh (this, changing);
6326                         return !changing.Cancel;
6327                 }
6328 #else
6329                 //
6330                 // 1.0 profile based implementation
6331                 //
6332                 bool CanProceedWithResize (ColumnHeader col, int width)
6333                 {
6334                         return true;
6335                 }
6336
6337                 void RaiseColumnWidthChanged (int resize_column)
6338                 {
6339                 }
6340 #endif
6341
6342                 internal void RaiseColumnWidthChanged (ColumnHeader column)
6343                 {
6344                         int index = Columns.IndexOf (column);
6345                         RaiseColumnWidthChanged (index);
6346                 }
6347
6348 #if NET_2_0
6349                 
6350                 #region UIA Framework: Methods, Properties and Events
6351                 
6352                 static object UIALabelEditChangedEvent = new object ();
6353                 static object UIAShowGroupsChangedEvent = new object ();
6354                 static object UIAMultiSelectChangedEvent = new object ();
6355                 static object UIAViewChangedEvent = new object ();
6356                 static object UIACheckBoxesChangedEvent = new object ();
6357                 static object UIAFocusedItemChangedEvent = new object ();
6358
6359                 internal Rectangle UIAHeaderControl {
6360                         get { return header_control.Bounds; }
6361                 }
6362
6363                 internal int UIAColumns {
6364                         get { return cols; }
6365                 }
6366
6367                 internal int UIARows {
6368                         get { return rows; }
6369                 }
6370
6371                 internal ListViewGroup UIADefaultListViewGroup 
6372                 {
6373                         get { return groups.DefaultGroup; }
6374                 }
6375
6376                 internal ScrollBar UIAHScrollBar {
6377                         get { return h_scroll; }
6378                 }
6379
6380                 internal ScrollBar UIAVScrollBar {
6381                         get { return v_scroll; }
6382                 }
6383
6384                 internal event EventHandler UIAShowGroupsChanged {
6385                         add { Events.AddHandler (UIAShowGroupsChangedEvent, value); }
6386                         remove { Events.RemoveHandler (UIAShowGroupsChangedEvent, value); }
6387                 }
6388
6389                 internal event EventHandler UIACheckBoxesChanged {
6390                         add { Events.AddHandler (UIACheckBoxesChangedEvent, value); }
6391                         remove { Events.RemoveHandler (UIACheckBoxesChangedEvent, value); }
6392                 }
6393
6394                 internal event EventHandler UIAMultiSelectChanged {
6395                         add { Events.AddHandler (UIAMultiSelectChangedEvent, value); }
6396                         remove { Events.RemoveHandler (UIAMultiSelectChangedEvent, value); }
6397                 }
6398
6399                 internal event EventHandler UIALabelEditChanged {
6400                         add { Events.AddHandler (UIALabelEditChangedEvent, value); }
6401                         remove { Events.RemoveHandler (UIALabelEditChangedEvent, value); }
6402                 }
6403
6404                 internal event EventHandler UIAViewChanged {
6405                         add { Events.AddHandler (UIAViewChangedEvent, value); }
6406                         remove { Events.RemoveHandler (UIAViewChangedEvent, value); }
6407                 }
6408
6409                 internal event EventHandler UIAFocusedItemChanged {
6410                         add { Events.AddHandler (UIAFocusedItemChangedEvent, value); }
6411                         remove { Events.RemoveHandler (UIAFocusedItemChangedEvent, value); }
6412                 }
6413
6414                 internal Rectangle UIAGetHeaderBounds (ListViewGroup group)
6415                 {
6416                         return group.HeaderBounds;
6417                 }
6418
6419                 internal int UIAItemsLocationLength
6420                 {
6421                         get { return items_location.Length; }
6422                 }
6423
6424                 private void OnUIACheckBoxesChanged ()
6425                 {
6426                         EventHandler eh = (EventHandler) Events [UIACheckBoxesChangedEvent];
6427                         if (eh != null)
6428                                 eh (this, EventArgs.Empty);
6429                 }
6430
6431                 private void OnUIAShowGroupsChanged ()
6432                 {
6433                         EventHandler eh = (EventHandler) Events [UIAShowGroupsChangedEvent];
6434                         if (eh != null)
6435                                 eh (this, EventArgs.Empty);
6436                 }
6437
6438                 private void OnUIAMultiSelectChanged ()
6439                 {
6440                         EventHandler eh = (EventHandler) Events [UIAMultiSelectChangedEvent];
6441                         if (eh != null)
6442                                 eh (this, EventArgs.Empty);
6443                 }
6444
6445                 private void OnUIALabelEditChanged ()
6446                 {
6447                         EventHandler eh = (EventHandler) Events [UIALabelEditChangedEvent];
6448                         if (eh != null)
6449                                 eh (this, EventArgs.Empty);
6450                 }
6451                 
6452                 private void OnUIAViewChanged ()
6453                 {
6454                         EventHandler eh = (EventHandler) Events [UIAViewChangedEvent];
6455                         if (eh != null)
6456                                 eh (this, EventArgs.Empty);
6457                 }
6458
6459                 internal void OnUIAFocusedItemChanged ()
6460                 {
6461                         EventHandler eh = (EventHandler) Events [UIAFocusedItemChangedEvent];
6462                         if (eh != null)
6463                                 eh (this, EventArgs.Empty);
6464                 }
6465
6466                 #endregion // UIA Framework: Methods, Properties and Events
6467
6468 #endif
6469         }
6470 }