fixed tests
[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 //
28 // TODO:
29 //   - Feedback for item activation, change in cursor types as mouse moves.
30 //   - Drag and drop
31
32
33 // NOT COMPLETE
34
35
36 using System.Collections;
37 using System.ComponentModel;
38 using System.ComponentModel.Design;
39 using System.Drawing;
40 using System.Runtime.InteropServices;
41 using System.Globalization;
42 #if NET_2_0
43 using System.Collections.Generic;
44 #endif
45
46 namespace System.Windows.Forms
47 {
48         [DefaultEvent ("SelectedIndexChanged")]
49         [DefaultProperty ("Items")]
50         [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
51 #if NET_2_0
52         [ClassInterface (ClassInterfaceType.AutoDispatch)]
53         [ComVisible (true)]
54         [Docking (DockingBehavior.Ask)]
55 #endif
56         public class ListView : Control
57         {
58                 private ItemActivation activation = ItemActivation.Standard;
59                 private ListViewAlignment alignment = ListViewAlignment.Top;
60                 private bool allow_column_reorder;
61                 private bool auto_arrange = true;
62                 private bool check_boxes;
63                 private readonly CheckedIndexCollection checked_indices;
64                 private readonly CheckedListViewItemCollection checked_items;
65                 private readonly ColumnHeaderCollection columns;
66                 internal ListViewItem focused_item;
67                 private bool full_row_select;
68                 private bool grid_lines;
69                 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
70                 private bool hide_selection = true;
71                 private bool hover_selection;
72                 private IComparer item_sorter;
73                 private readonly ListViewItemCollection items;
74 #if NET_2_0
75                 private readonly ListViewGroupCollection groups;
76                 private bool show_groups = true;
77 #endif
78                 private bool label_edit;
79                 private bool label_wrap = true;
80                 private bool multiselect = true;
81                 private bool scrollable = true;
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                 private 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                 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 Point [] items_location;
101                 private ItemMatrixLocation [] items_matrix_location;
102                 private Size item_size; // used for caching item size
103 #if NET_2_0
104                 private Size tile_size;
105 #endif
106
107                 // internal variables
108                 internal ImageList large_image_list;
109                 internal ImageList small_image_list;
110                 internal Size text_size = Size.Empty;
111
112                 #region Events
113                 static object AfterLabelEditEvent = new object ();
114                 static object BeforeLabelEditEvent = new object ();
115                 static object ColumnClickEvent = new object ();
116                 static object ItemActivateEvent = new object ();
117                 static object ItemCheckEvent = new object ();
118                 static object ItemDragEvent = new object ();
119                 static object SelectedIndexChangedEvent = new object ();
120
121                 public event LabelEditEventHandler AfterLabelEdit {
122                         add { Events.AddHandler (AfterLabelEditEvent, value); }
123                         remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
124                 }
125
126                 [Browsable (false)]
127                 [EditorBrowsable (EditorBrowsableState.Never)]
128                 public new event EventHandler BackgroundImageChanged {
129                         add { base.BackgroundImageChanged += value; }
130                         remove { base.BackgroundImageChanged -= value; }
131                 }
132
133                 public event LabelEditEventHandler BeforeLabelEdit {
134                         add { Events.AddHandler (BeforeLabelEditEvent, value); }
135                         remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
136                 }
137
138                 public event ColumnClickEventHandler ColumnClick {
139                         add { Events.AddHandler (ColumnClickEvent, value); }
140                         remove { Events.RemoveHandler (ColumnClickEvent, value); }
141                 }
142
143                 public event EventHandler ItemActivate {
144                         add { Events.AddHandler (ItemActivateEvent, value); }
145                         remove { Events.RemoveHandler (ItemActivateEvent, value); }
146                 }
147
148                 public event ItemCheckEventHandler ItemCheck {
149                         add { Events.AddHandler (ItemCheckEvent, value); }
150                         remove { Events.RemoveHandler (ItemCheckEvent, value); }
151                 }
152
153                 public event ItemDragEventHandler ItemDrag {
154                         add { Events.AddHandler (ItemDragEvent, value); }
155                         remove { Events.RemoveHandler (ItemDragEvent, value); }
156                 }
157
158                 [Browsable (false)]
159                 [EditorBrowsable (EditorBrowsableState.Never)]
160                 public new event PaintEventHandler Paint {
161                         add { base.Paint += value; }
162                         remove { base.Paint -= value; }
163                 }
164
165                 public event EventHandler SelectedIndexChanged {
166                         add { Events.AddHandler (SelectedIndexChangedEvent, value); }
167                         remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
168                 }
169
170                 [Browsable (false)]
171                 [EditorBrowsable (EditorBrowsableState.Never)]
172                 public new event EventHandler TextChanged {
173                         add { base.TextChanged += value; }
174                         remove { base.TextChanged -= value; }
175                 }
176
177                 #endregion // Events
178
179                 #region Public Constructors
180                 public ListView ()
181                 {
182                         background_color = ThemeEngine.Current.ColorWindow;
183                         items = new ListViewItemCollection (this);
184 #if NET_2_0
185                         groups = new ListViewGroupCollection (this);
186 #endif
187                         checked_indices = new CheckedIndexCollection (this);
188                         checked_items = new CheckedListViewItemCollection (this);
189                         columns = new ColumnHeaderCollection (this);
190                         foreground_color = SystemColors.WindowText;
191                         selected_indices = new SelectedIndexCollection (this);
192                         selected_items = new SelectedListViewItemCollection (this);
193                         items_location = new Point [16];
194                         items_matrix_location = new ItemMatrixLocation [16];
195
196                         border_style = BorderStyle.Fixed3D;
197
198                         header_control = new HeaderControl (this);
199                         header_control.Visible = false;
200                         Controls.AddImplicit (header_control);
201
202                         item_control = new ItemControl (this);
203                         Controls.AddImplicit (item_control);
204
205                         h_scroll = new ImplicitHScrollBar ();
206                         Controls.AddImplicit (this.h_scroll);
207
208                         v_scroll = new ImplicitVScrollBar ();
209                         Controls.AddImplicit (this.v_scroll);
210
211                         h_marker = v_marker = 0;
212                         keysearch_tickcnt = 0;
213
214                         // scroll bars are disabled initially
215                         h_scroll.Visible = false;
216                         h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
217                         v_scroll.Visible = false;
218                         v_scroll.ValueChanged += new EventHandler(VerticalScroller);
219
220                         // event handlers
221                         base.KeyDown += new KeyEventHandler(ListView_KeyDown);
222                         SizeChanged += new EventHandler (ListView_SizeChanged);
223                         GotFocus += new EventHandler (FocusChanged);
224                         LostFocus += new EventHandler (FocusChanged);
225                         MouseWheel += new MouseEventHandler(ListView_MouseWheel);
226
227                         this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
228 #if NET_2_0
229                                 | ControlStyles.UseTextForAccessibility
230 #endif
231                                 , false);
232                 }
233                 #endregion      // Public Constructors
234
235                 #region Private Internal Properties
236                 internal Size CheckBoxSize {
237                         get {
238                                 if (this.check_boxes) {
239                                         if (this.state_image_list != null)
240                                                 return this.state_image_list.ImageSize;
241                                         else
242                                                 return ThemeEngine.Current.ListViewCheckBoxSize;
243                                 }
244                                 return Size.Empty;
245                         }
246                 }
247
248                 internal Size ItemSize {
249                         get {
250                                 if (view != View.Details)
251                                         return item_size;
252
253                                 Size size = new Size ();
254                                 size.Height = item_size.Height;
255                                 for (int i = 0; i < columns.Count; i++)
256                                         size.Width += columns [i].Wd;
257
258                                 return size;
259                         }
260                         set {
261                                 item_size = value;
262                         }
263                 }
264
265                 #endregion      // Private Internal Properties
266
267                 #region  Protected Properties
268                 protected override CreateParams CreateParams {
269                         get { return base.CreateParams; }
270                 }
271
272                 protected override Size DefaultSize {
273                         get { return ThemeEngine.Current.ListViewDefaultSize; }
274                 }
275                 #endregion      // Protected Properties
276
277                 #region Public Instance Properties
278                 [DefaultValue (ItemActivation.Standard)]
279                 public ItemActivation Activation {
280                         get { return activation; }
281                         set { 
282                                 if (value != ItemActivation.Standard && value != ItemActivation.OneClick && 
283                                         value != ItemActivation.TwoClick) {
284                                         throw new InvalidEnumArgumentException (string.Format
285                                                 ("Enum argument value '{0}' is not valid for Activation", value));
286                                 }
287                                 
288                                 activation = value;
289                         }
290                 }
291
292                 [DefaultValue (ListViewAlignment.Top)]
293                 [Localizable (true)]
294                 public ListViewAlignment Alignment {
295                         get { return alignment; }
296                         set {
297                                 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left && 
298                                         value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
299                                         throw new InvalidEnumArgumentException (string.Format 
300                                                 ("Enum argument value '{0}' is not valid for Alignment", value));
301                                 }
302                                 
303                                 if (this.alignment != value) {
304                                         alignment = value;
305                                         // alignment does not matter in Details/List views
306                                         if (this.view == View.LargeIcon || this.View == View.SmallIcon)
307                                                 this.Redraw (true);
308                                 }
309                         }
310                 }
311
312                 [DefaultValue (false)]
313                 public bool AllowColumnReorder {
314                         get { return allow_column_reorder; }
315                         set { allow_column_reorder = value; }
316                 }
317
318                 [DefaultValue (true)]
319                 public bool AutoArrange {
320                         get { return auto_arrange; }
321                         set {
322                                 if (auto_arrange != value) {
323                                         auto_arrange = value;
324                                         // autoarrange does not matter in Details/List views
325                                         if (this.view == View.LargeIcon || this.View == View.SmallIcon)
326                                                 this.Redraw (true);
327                                 }
328                         }
329                 }
330
331                 public override Color BackColor {
332                         get {
333                                 if (background_color.IsEmpty)
334                                         return ThemeEngine.Current.ColorWindow;
335                                 else
336                                         return background_color;
337                         }
338                         set { background_color = value; }
339                 }
340
341                 [Browsable (false)]
342                 [EditorBrowsable (EditorBrowsableState.Never)]
343                 public override Image BackgroundImage {
344                         get { return base.BackgroundImage; }
345                         set { base.BackgroundImage = value; }
346                 }
347
348                 [DefaultValue (BorderStyle.Fixed3D)]
349                 [DispId (-504)]
350                 public BorderStyle BorderStyle {
351                         get { return InternalBorderStyle; }
352                         set { InternalBorderStyle = value; }
353                 }
354
355                 [DefaultValue (false)]
356                 public bool CheckBoxes {
357                         get { return check_boxes; }
358                         set {
359                                 if (check_boxes != value) {
360 #if NET_2_0
361                                         if (value && View == View.Tile)
362                                                 throw new NotSupportedException ("CheckBoxes are not"
363                                                         + " supported in Tile view. Choose a different"
364                                                         + " view or set CheckBoxes to false.");
365 #endif
366
367                                         check_boxes = value;
368                                         this.Redraw (true);
369                                 }
370                         }
371                 }
372
373                 [Browsable (false)]
374                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
375                 public CheckedIndexCollection CheckedIndices {
376                         get { return checked_indices; }
377                 }
378
379                 [Browsable (false)]
380                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
381                 public CheckedListViewItemCollection CheckedItems {
382                         get { return checked_items; }
383                 }
384
385                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
386                 [Localizable (true)]
387                 [MergableProperty (false)]
388                 public ColumnHeaderCollection Columns {
389                         get { return columns; }
390                 }
391
392                 [Browsable (false)]
393                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394                 public ListViewItem FocusedItem {
395                         get {
396                                 return focused_item;
397                         }
398 #if NET_2_0
399                         set {
400                                 throw new NotImplementedException ();
401                         }
402 #endif
403                 }
404
405                 public override Color ForeColor {
406                         get {
407                                 if (foreground_color.IsEmpty)
408                                         return ThemeEngine.Current.ColorWindowText;
409                                 else
410                                         return foreground_color;
411                         }
412                         set { foreground_color = value; }
413                 }
414
415                 [DefaultValue (false)]
416                 public bool FullRowSelect {
417                         get { return full_row_select; }
418                         set { full_row_select = value; }
419                 }
420
421                 [DefaultValue (false)]
422                 public bool GridLines {
423                         get { return grid_lines; }
424                         set {
425                                 if (grid_lines != value) {
426                                         grid_lines = value;
427                                         this.Redraw (false);
428                                 }
429                         }
430                 }
431
432                 [DefaultValue (ColumnHeaderStyle.Clickable)]
433                 public ColumnHeaderStyle HeaderStyle {
434                         get { return header_style; }
435                         set {
436                                 if (header_style == value)
437                                         return;
438
439                                 switch (value) {
440                                 case ColumnHeaderStyle.Clickable:
441                                 case ColumnHeaderStyle.Nonclickable:
442                                 case ColumnHeaderStyle.None:
443                                         break;
444                                 default:
445                                         throw new InvalidEnumArgumentException (string.Format 
446                                                 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
447                                 }
448                                 
449                                 header_style = value;
450                                 if (view == View.Details)
451                                         Redraw (true);
452                         }
453                 }
454
455                 [DefaultValue (true)]
456                 public bool HideSelection {
457                         get { return hide_selection; }
458                         set {
459                                 if (hide_selection != value) {
460                                         hide_selection = value;
461                                         this.Redraw (false);
462                                 }
463                         }
464                 }
465
466                 [DefaultValue (false)]
467                 public bool HoverSelection {
468                         get { return hover_selection; }
469                         set { hover_selection = value; }
470                 }
471
472                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
473                 [Localizable (true)]
474                 [MergableProperty (false)]
475                 public ListViewItemCollection Items {
476                         get { return items; }
477                 }
478
479                 [DefaultValue (false)]
480                 public bool LabelEdit {
481                         get { return label_edit; }
482                         set { label_edit = value; }
483                 }
484
485                 [DefaultValue (true)]
486                 [Localizable (true)]
487                 public bool LabelWrap {
488                         get { return label_wrap; }
489                         set {
490                                 if (label_wrap != value) {
491                                         label_wrap = value;
492                                         this.Redraw (true);
493                                 }
494                         }
495                 }
496
497                 [DefaultValue (null)]
498                 public ImageList LargeImageList {
499                         get { return large_image_list; }
500                         set {
501                                 large_image_list = value;
502                                 this.Redraw (true);
503                         }
504                 }
505
506                 [Browsable (false)]
507                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
508                 public IComparer ListViewItemSorter {
509                         get {
510                                 if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
511                                         return null;
512                                 return item_sorter;
513                         }
514                         set {
515                                 if (item_sorter != value) {
516                                         item_sorter = value;
517                                         Sort ();
518                                 }
519                         }
520                 }
521
522                 [DefaultValue (true)]
523                 public bool MultiSelect {
524                         get { return multiselect; }
525                         set { multiselect = value; }
526                 }
527
528                 [DefaultValue (true)]
529                 public bool Scrollable {
530                         get { return scrollable; }
531                         set {
532                                 if (scrollable != value) {
533                                         scrollable = value;
534                                         this.Redraw (true);
535                                 }
536                         }
537                 }
538
539                 [Browsable (false)]
540                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
541                 public SelectedIndexCollection SelectedIndices {
542                         get { return selected_indices; }
543                 }
544
545                 [Browsable (false)]
546                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
547                 public SelectedListViewItemCollection SelectedItems {
548                         get { return selected_items; }
549                 }
550
551 #if NET_2_0
552                 [DefaultValue(true)]
553                 public bool ShowGroups {
554                         get { return show_groups; }
555                         set {
556                                 if (show_groups != value) {
557                                         show_groups = value;
558                                         Redraw(true);
559                                 }
560                         }
561                 }
562
563                 [LocalizableAttribute (true)]
564                 [MergableProperty (false)]
565                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
566                 public ListViewGroupCollection Groups {
567                         get { return groups; }
568                 }
569 #endif
570
571                 [DefaultValue (null)]
572                 public ImageList SmallImageList {
573                         get { return small_image_list; }
574                         set {
575                                 small_image_list = value;
576                                 this.Redraw (true);
577                         }
578                 }
579
580                 [DefaultValue (SortOrder.None)]
581                 public SortOrder Sorting {
582                         get { return sort_order; }
583                         set { 
584                                 if (!Enum.IsDefined (typeof (SortOrder), value)) {
585                                         throw new InvalidEnumArgumentException ("value", (int) value,
586                                                 typeof (SortOrder));
587                                 }
588                                 
589                                 if (sort_order == value)
590                                         return;
591
592                                 sort_order = value;
593
594                                 if (value == SortOrder.None) {
595                                         if (item_sorter != null) {
596                                                 // ListViewItemSorter should never be reset for SmallIcon
597                                                 // and LargeIcon view
598                                                 if (View != View.SmallIcon && View != View.LargeIcon)
599 #if NET_2_0
600                                                         item_sorter = null;
601 #else
602                                                         // in .NET 1.1, only internal IComparer would be
603                                                         // set to null
604                                                         if (item_sorter is ItemComparer)
605                                                                 item_sorter = null;
606 #endif
607                                         }
608                                         this.Redraw (false);
609                                 } else {
610                                         if (item_sorter == null)
611                                                 item_sorter = new ItemComparer (value);
612                                         if (item_sorter is ItemComparer) {
613 #if NET_2_0
614                                                 item_sorter = new ItemComparer (value);
615 #else
616                                                 // in .NET 1.1, the sort order is not updated for
617                                                 // SmallIcon and LargeIcon views if no custom IComparer
618                                                 // is set
619                                                 if (View != View.SmallIcon && View != View.LargeIcon)
620                                                         item_sorter = new ItemComparer (value);
621 #endif
622                                         }
623                                         Sort ();
624                                 }
625                         }
626                 }
627
628                 [DefaultValue (null)]
629                 public ImageList StateImageList {
630                         get { return state_image_list; }
631                         set {
632                                 state_image_list = value;
633                                 this.Redraw (true);
634                         }
635                 }
636
637                 [Bindable (false)]
638                 [Browsable (false)]
639                 [EditorBrowsable (EditorBrowsableState.Never)]
640                 public override string Text {
641                         get { return base.Text; } 
642                         set {
643                                 if (value == base.Text)
644                                         return;
645
646                                 base.Text = value;
647                                 this.Redraw (true);
648                         }
649                 }
650
651 #if NET_2_0
652                 [Browsable (true)]
653                 public Size TileSize {
654                         get {
655                                 return tile_size;
656                         }
657                         set {
658                                 if (value.Width <= 0 || value.Height <= 0)
659                                         throw new ArgumentOutOfRangeException ("value");
660
661                                 tile_size = value;
662                                 Redraw (true);
663                         }
664                 }
665 #endif
666
667                 [Browsable (false)]
668                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
669                 public ListViewItem TopItem {
670                         get {
671                                 // there is no item
672                                 if (this.items.Count == 0)
673                                         return null;
674                                 // if contents are not scrolled
675                                 // it is the first item
676                                 else if (h_marker == 0 && v_marker == 0)
677                                         return this.items [0];
678                                 // do a hit test for the scrolled position
679                                 else {
680                                         for (int i = 0; i < items.Count; i++) {
681                                                 Point item_loc = GetItemLocation (i);
682                                                 if (item_loc.X >= 0 && item_loc.Y >= 0)
683                                                         return items [i];
684                                         }
685                                         return null;
686                                 }
687                         }
688 #if NET_2_0
689                         set {
690                                 throw new NotImplementedException ();
691                         }
692 #endif
693                 }
694
695 #if NET_2_0
696                 [EditorBrowsable (EditorBrowsableState.Advanced)]
697                 [DefaultValue (true)]
698                 [Browsable (false)]
699                 [MonoInternalNote ("Stub, not implemented")]
700                 public bool UseCompatibleStateImageBehavior {
701                         get {
702                                 return false;
703                         }
704                         set {
705                         }
706                 }
707 #endif
708
709                 [DefaultValue (View.LargeIcon)]
710                 public View View {
711                         get { return view; }
712                         set { 
713                                 if (!Enum.IsDefined (typeof (View), value))
714                                         throw new InvalidEnumArgumentException ("value", (int) value,
715                                                 typeof (View));
716
717                                 if (view != value) {
718 #if NET_2_0
719                                         if (CheckBoxes && value == View.Tile)
720                                                 throw new NotSupportedException ("CheckBoxes are not"
721                                                         + " supported in Tile view. Choose a different"
722                                                         + " view or set CheckBoxes to false.");
723 #endif
724
725                                         h_scroll.Value = v_scroll.Value = 0;
726                                         view = value; 
727                                         Redraw (true);
728                                 }
729                         }
730                 }
731                 #endregion      // Public Instance Properties
732
733                 #region Internal Methods Properties
734                 
735                 internal int FirstVisibleIndex {
736                         get {
737                                 // there is no item
738                                 if (this.items.Count == 0)
739                                         return 0;
740                                 
741                                 if (h_marker == 0 && v_marker == 0)
742                                         return 0;
743                                 
744                                 Size item_size = ItemSize;
745                                 for (int i = 0; i < items.Count; i++) {
746                                         Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
747                                         if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
748                                                 return i;
749                                 }
750
751                                 return 0;
752                         }
753                 }
754
755                 
756                 internal int LastVisibleIndex {
757                         get {
758                                 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
759                                         if (View == View.List || Alignment == ListViewAlignment.Left) {
760                                                 if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
761                                                         return i - 1;
762                                         } else {
763                                                 if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
764                                                         return i - 1;
765                                         }
766                                 }
767                                 
768                                 return Items.Count - 1;
769                         }
770                 }
771                 
772                 internal void OnSelectedIndexChanged ()
773                 {
774                         if (IsHandleCreated)
775                                 OnSelectedIndexChanged (EventArgs.Empty);
776                 }
777
778                 internal int TotalWidth {
779                         get { return Math.Max (this.Width, this.layout_wd); }
780                 }
781
782                 internal int TotalHeight {
783                         get { return Math.Max (this.Height, this.layout_ht); }
784                 }
785
786                 internal void Redraw (bool recalculate)
787                 {
788                         // Avoid calculations when control is being updated
789                         if (updating)
790                                 return;
791
792                         if (recalculate)
793                                 CalculateListView (this.alignment);
794
795                         Refresh ();
796                 }
797
798                 const int text_padding = 15;
799
800                 internal Size GetChildColumnSize (int index)
801                 {
802                         Size ret_size = Size.Empty;
803                         ColumnHeader col = this.columns [index];
804
805                         if (col.Width == -2) { // autosize = max(items, columnheader)
806                                 Size size = Size.Ceiling (this.DeviceContext.MeasureString
807                                         (col.Text, this.Font));
808                                 size.Width += text_padding;
809                                 ret_size = BiggestItem (index);
810                                 if (size.Width > ret_size.Width)
811                                         ret_size = size;
812                         }
813                         else { // -1 and all the values < -2 are put under one category
814                                 ret_size = BiggestItem (index);
815                                 // fall back to empty columns' width if no subitem is available for a column
816                                 if (ret_size.IsEmpty) {
817                                         ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
818                                         if (col.Text.Length > 0)
819                                                 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
820                                                                                 (col.Text, this.Font)).Height;
821                                         else
822                                                 ret_size.Height = this.Font.Height;
823                                 }
824                         }
825
826                         ret_size.Height += text_padding;
827
828                         // adjust the size for icon and checkbox for 0th column
829                         if (index == 0) {
830                                 ret_size.Width += (this.CheckBoxSize.Width + 4);
831                                 if (this.small_image_list != null)
832                                         ret_size.Width += this.small_image_list.ImageSize.Width;
833                         }
834                         return ret_size;
835                 }
836
837                 // Returns the size of biggest item text in a column.
838                 private Size BiggestItem (int col)
839                 {
840                         Size temp = Size.Empty;
841                         Size ret_size = Size.Empty;
842
843                         // 0th column holds the item text, we check the size of
844                         // the various subitems falling in that column and get
845                         // the biggest one's size.
846                         foreach (ListViewItem item in items) {
847                                 if (col >= item.SubItems.Count)
848                                         continue;
849
850                                 temp = Size.Ceiling (this.DeviceContext.MeasureString
851                                                         (item.SubItems [col].Text, this.Font));
852                                 if (temp.Width > ret_size.Width)
853                                         ret_size = temp;
854                         }
855
856                         // adjustment for space
857                         if (!ret_size.IsEmpty)
858                                 ret_size.Width += 4;
859
860                         return ret_size;
861                 }
862
863                 const int max_wrap_padding = 38;
864
865                 // Sets the size of the biggest item text as per the view
866                 private void CalcTextSize ()
867                 {
868                         // clear the old value
869                         text_size = Size.Empty;
870
871                         if (items.Count == 0)
872                                 return;
873
874                         text_size = BiggestItem (0);
875
876                         if (view == View.LargeIcon && this.label_wrap) {
877                                 Size temp = Size.Empty;
878                                 if (this.check_boxes)
879                                         temp.Width += 2 * this.CheckBoxSize.Width;
880                                 int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
881                                 temp.Width += icon_w + max_wrap_padding;
882                                 // wrapping is done for two lines only
883                                 if (text_size.Width > temp.Width) {
884                                         text_size.Width = temp.Width;
885                                         text_size.Height *= 2;
886                                 }
887                         }
888                         else if (view == View.List) {
889                                 // in list view max text shown in determined by the
890                                 // control width, even if scolling is enabled.
891                                 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
892                                 if (this.small_image_list != null)
893                                         max_wd -= this.small_image_list.ImageSize.Width;
894
895                                 if (text_size.Width > max_wd)
896                                         text_size.Width = max_wd;
897                         }
898
899                         // we do the default settings, if we have got 0's
900                         if (text_size.Height <= 0)
901                                 text_size.Height = this.Font.Height;
902                         if (text_size.Width <= 0)
903                                 text_size.Width = this.Width;
904
905                         // little adjustment
906                         text_size.Width += 4;
907                         text_size.Height += 2;
908                 }
909
910                 private void Scroll (ScrollBar scrollbar, int delta)
911                 {
912                         if (delta == 0 || !scrollbar.Visible)
913                                 return;
914
915                         int max;
916                         if (scrollbar == h_scroll)
917                                 max = h_scroll.Maximum - item_control.Width;
918                         else
919                                 max = v_scroll.Maximum - item_control.Height;
920
921                         int val = scrollbar.Value + delta;
922                         if (val > max)
923                                 val = max;
924                         else if (val < scrollbar.Minimum)
925                                 val = scrollbar.Minimum;
926                         scrollbar.Value = val;
927                 }
928
929                 private void CalculateScrollBars ()
930                 {
931                         Rectangle client_area = ClientRectangle;
932                         
933                         if (!this.scrollable || this.items.Count <= 0) {
934                                 h_scroll.Visible = false;
935                                 v_scroll.Visible = false;
936                                 item_control.Location = new Point (0, header_control.Height);
937                                 item_control.Height = ClientRectangle.Width - header_control.Height;
938                                 item_control.Width = ClientRectangle.Width;
939                                 header_control.Width = ClientRectangle.Width;
940                                 return;
941                         }
942
943                         // Don't calculate if the view is not displayable
944                         if (client_area.Height < 0 || client_area.Width < 0)
945                                 return;
946
947                         // making a scroll bar visible might make
948                         // other scroll bar visible
949                         if (layout_wd > client_area.Right) {
950                                 h_scroll.Visible = true;
951                                 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
952                                         v_scroll.Visible = true;
953                                 else
954                                         v_scroll.Visible = false;
955                         } else if (layout_ht > client_area.Bottom) {
956                                 v_scroll.Visible = true;
957                                 if ((layout_wd + v_scroll.Width) > client_area.Right)
958                                         h_scroll.Visible = true;
959                                 else
960                                         h_scroll.Visible = false;
961                         } else {
962                                 h_scroll.Visible = false;
963                                 v_scroll.Visible = false;
964                         }
965
966                         item_control.Height = ClientRectangle.Height - header_control.Height;
967
968                         if (h_scroll.is_visible) {
969                                 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
970                                 h_scroll.Minimum = 0;
971
972                                 // if v_scroll is visible, adjust the maximum of the
973                                 // h_scroll to account for the width of v_scroll
974                                 if (v_scroll.Visible) {
975                                         h_scroll.Maximum = layout_wd + v_scroll.Width;
976                                         h_scroll.Width = client_area.Width - v_scroll.Width;
977                                 }
978                                 else {
979                                         h_scroll.Maximum = layout_wd;
980                                         h_scroll.Width = client_area.Width;
981                                 }
982
983                                 h_scroll.LargeChange = client_area.Width;
984                                 h_scroll.SmallChange = Font.Height;
985                                 item_control.Height -= h_scroll.Height;
986                         }
987
988                         if (header_control.is_visible)
989                                 header_control.Width = ClientRectangle.Width;
990                         item_control.Width = ClientRectangle.Width;
991
992                         if (v_scroll.is_visible) {
993                                 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
994                                 v_scroll.Minimum = 0;
995
996                                 // if h_scroll is visible, adjust the maximum of the
997                                 // v_scroll to account for the height of h_scroll
998                                 if (h_scroll.Visible) {
999                                         v_scroll.Maximum = layout_ht + h_scroll.Height;
1000                                         v_scroll.Height = client_area.Height; // - h_scroll.Height already done 
1001                                 } else {
1002                                         v_scroll.Maximum = layout_ht;
1003                                         v_scroll.Height = client_area.Height;
1004                                 }
1005
1006                                 v_scroll.LargeChange = client_area.Height;
1007                                 v_scroll.SmallChange = Font.Height;
1008                                 if (header_control.Visible)
1009                                         header_control.Width -= v_scroll.Width;
1010                                 item_control.Width -= v_scroll.Width;
1011                         }
1012                 }
1013
1014 #if NET_2_0
1015                 internal int GetReorderedColumnIndex (ColumnHeader column)
1016                 {
1017                         if (reordered_column_indices == null)
1018                                 return column.Index;
1019
1020                         for (int i = 0; i < Columns.Count; i++)
1021                                 if (reordered_column_indices [i] == column.Index)
1022                                         return i;
1023
1024                         return -1;
1025                 }
1026 #endif
1027                 
1028                 internal ColumnHeader GetReorderedColumn (int index)
1029                 {
1030                         if (reordered_column_indices == null)
1031                                 return Columns [index];
1032                         else
1033                                 return Columns [reordered_column_indices [index]];
1034                 }
1035
1036                 internal void ReorderColumn (ColumnHeader col, int index)
1037                 {
1038 #if NET_2_0
1039                         ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
1040                         if (eh != null){
1041                                 ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
1042
1043                                 eh (this, args);
1044                                 if (args.Cancel){
1045                                         header_control.Invalidate ();
1046                                         item_control.Invalidate ();
1047                                         return;
1048                                 }
1049                         }
1050 #endif
1051                         if (reordered_column_indices == null) {
1052                                 reordered_column_indices = new int [Columns.Count];
1053                                 for (int i = 0; i < Columns.Count; i++)
1054                                         reordered_column_indices [i] = i;
1055                         }
1056
1057                         if (reordered_column_indices [index] == col.Index)
1058                                 return;
1059
1060                         int[] curr = reordered_column_indices;
1061                         int[] result = new int [Columns.Count];
1062                         int curr_idx = 0;
1063                         for (int i = 0; i < Columns.Count; i++) {
1064                                 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
1065                                         curr_idx++;
1066
1067                                 if (i == index)
1068                                         result [i] = col.Index;
1069                                 else
1070                                         result [i] = curr [curr_idx++];
1071                         }
1072
1073                         reordered_column_indices = result;
1074                         LayoutDetails ();
1075                         header_control.Invalidate ();
1076                         item_control.Invalidate ();
1077                 }
1078
1079                 Size LargeIconItemSize {
1080                         get {
1081                                 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1082                                 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
1083                                 int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
1084                                 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
1085                                 return new Size (w, h);
1086                         }
1087                 }
1088
1089                 Size SmallIconItemSize {
1090                         get {
1091                                 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
1092                                 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1093                                 int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
1094                                 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
1095                                 return new Size (w, h);
1096                         }
1097                 }
1098
1099 #if NET_2_0
1100                 Size TileItemSize {
1101                         get {
1102                                 // Calculate tile size if needed
1103                                 // It appears that using Font.Size instead of a SizeF value can give us
1104                                 // a slightly better approach to the proportions defined in .Net
1105                                 if (tile_size == Size.Empty) {
1106                                         int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
1107                                         int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
1108                                         int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
1109                                         int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
1110                                 
1111                                         tile_size = new Size (w, h);
1112                                 }
1113                         
1114                                 return tile_size;
1115                         }
1116                 }
1117 #endif
1118
1119                 int GetDetailsItemHeight ()
1120                 {
1121                         int item_height;
1122                         int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
1123                         int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1124                         item_height = Math.Max (checkbox_height, text_size.Height);
1125                         item_height = Math.Max (item_height, small_image_height);
1126                         return item_height;
1127                 }
1128
1129
1130                 void SetItemLocation (int index, int x, int y, int row, int col)
1131                 {
1132                         Point old_location = items_location [index];
1133                         if (old_location.X == x && old_location.Y == y)
1134                                 return;
1135
1136                         Size item_size = ItemSize;
1137                         Rectangle old_rect = new Rectangle (GetItemLocation (index), item_size);
1138
1139                         items_location [index] = new Point (x, y);
1140                         items_matrix_location [index] = new ItemMatrixLocation (row, col);
1141
1142                         // Invalidate both previous and new bounds
1143                         item_control.Invalidate (old_rect);
1144                         item_control.Invalidate (new Rectangle (GetItemLocation (index), item_size));
1145                 }
1146
1147                 int rows;
1148                 int cols;
1149                 int[,] item_index_matrix;
1150
1151                 void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1152                 {
1153                         header_control.Visible = false;
1154                         header_control.Size = Size.Empty;
1155                         item_control.Visible = true;
1156                         item_control.Location = Point.Empty;
1157                         ItemSize = item_size; // Cache item size
1158
1159                         if (items.Count == 0)
1160                                 return;
1161
1162                         Size sz = item_size;
1163                         Rectangle area = ClientRectangle;
1164
1165                         if (left_aligned) {
1166                                 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
1167                                 if (rows <= 0)
1168                                         rows = 1;
1169                                 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
1170                         } else {
1171                                 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
1172                                 if (cols <= 0)
1173                                         cols = 1;
1174                                 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
1175                         }
1176
1177                         layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
1178                         layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
1179                         item_index_matrix = new int [rows, cols];
1180                         int row = 0;
1181                         int col = 0;
1182                         for (int i = 0; i < items.Count; i++) {
1183                                 int x = col * (sz.Width + x_spacing);
1184                                 int y = row * (sz.Height + y_spacing);
1185                                 SetItemLocation (i, x, y, row, col);
1186                                 item_index_matrix [row, col] = i;
1187                                 items [i].Layout ();
1188                                 if (left_aligned) {
1189                                         if (++row == rows) {
1190                                                 row = 0;
1191                                                 col++;
1192                                         }
1193                                 } else {
1194                                         if (++col == cols) {
1195                                                 col = 0;
1196                                                 row++;
1197                                         }
1198                                 }
1199                         }
1200
1201                         item_control.Size = new Size (layout_wd, layout_ht);
1202                 }
1203
1204                 void LayoutHeader ()
1205                 {
1206                         int x = 0;
1207                         for (int i = 0; i < Columns.Count; i++) {
1208                                 ColumnHeader col = GetReorderedColumn (i);
1209                                 col.X = x;
1210                                 col.Y = 0;
1211                                 col.CalcColumnHeader ();
1212                                 x += col.Wd;
1213                         }
1214
1215                         if (x < ClientRectangle.Width)
1216                                 x = ClientRectangle.Width;
1217
1218                         if (header_style == ColumnHeaderStyle.None) {
1219                                 header_control.Visible = false;
1220                                 header_control.Size = Size.Empty;
1221                         } else {
1222                                 header_control.Width = x;
1223                                 header_control.Height = columns [0].Ht;
1224                                 header_control.Visible = true;
1225                         }
1226                 }
1227
1228                 void LayoutDetails ()
1229                 {
1230                         if (columns.Count == 0) {
1231                                 header_control.Visible = false;
1232                                 item_control.Visible = false;
1233                                 return;
1234                         }
1235
1236                         LayoutHeader ();
1237
1238                         item_control.Visible = true;
1239                         item_control.Location = new Point (0, header_control.Height);
1240
1241                         int item_height = GetDetailsItemHeight ();
1242                         ItemSize = new Size (0, item_height); // We only cache Height for details view
1243
1244                         int y = 0; 
1245                         if (items.Count > 0) {
1246                                 for (int i = 0; i < items.Count; i++) {
1247                                         SetItemLocation (i, 0, y, 0, 0);
1248                                         items [i].Layout ();
1249                                         y += item_height + 2;
1250                                 }
1251
1252                                 // some space for bottom gridline
1253                                 if (grid_lines)
1254                                         y += 2;
1255                         }
1256
1257                         layout_wd = Math.Max (header_control.Width, item_control.Width);
1258                         layout_ht = y + header_control.Height;
1259                 }
1260
1261                 private void AdjustItemsPositionArray (int count)
1262                 {
1263                         if (items_location.Length >= count)
1264                                 return;
1265
1266                         // items_location and items_matrix_location must keep the same length
1267                         count = Math.Max (count, items_location.Length * 2);
1268                         items_location = new Point [count];
1269                         items_matrix_location = new ItemMatrixLocation [count];
1270                 }
1271
1272                 private void CalculateListView (ListViewAlignment align)
1273                 {
1274                         CalcTextSize ();
1275
1276                         AdjustItemsPositionArray (items.Count);
1277
1278                         switch (view) {
1279                         case View.Details:
1280                                 LayoutDetails ();
1281                                 break;
1282
1283                         case View.SmallIcon:
1284                                 LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left, 4, 2);
1285                                 break;
1286
1287                         case View.LargeIcon:
1288                                 LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
1289                                         ThemeEngine.Current.ListViewHorizontalSpacing,
1290                                         ThemeEngine.Current.ListViewVerticalSpacing);
1291                                 break;
1292
1293                         case View.List:
1294                                 LayoutIcons (SmallIconItemSize, true, 4, 2);
1295                                 break;
1296 #if NET_2_0
1297                         case View.Tile:
1298                                 LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left, 
1299                                                 ThemeEngine.Current.ListViewHorizontalSpacing,
1300                                                 ThemeEngine.Current.ListViewVerticalSpacing);
1301                                 break;
1302 #endif
1303                         }
1304
1305                         CalculateScrollBars ();
1306                 }
1307
1308                 internal Point GetItemLocation (int index)
1309                 {
1310                         Point loc = items_location [index];
1311                         loc.X -= h_marker; // Adjust to scroll
1312                         loc.Y -= v_marker;
1313
1314                         return loc;
1315                 }
1316
1317                 private bool KeySearchString (KeyEventArgs ke)
1318                 {
1319                         int current_tickcnt = Environment.TickCount;
1320                         if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1321                                 keysearch_text = string.Empty;
1322                         }
1323                         
1324                         keysearch_text += (char) ke.KeyData;
1325                         keysearch_tickcnt = current_tickcnt;
1326
1327                         int start = FocusedItem == null ? 0 : FocusedItem.Index;
1328                         int i = start;
1329                         while (true) {
1330                                 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1331                                         CompareOptions.IgnoreCase)) {
1332                                         SetFocusedItem (Items [i]);
1333                                         items [i].Selected = true;
1334                                         EnsureVisible (i);
1335                                         break;
1336                                 }
1337                                 i = (i + 1 < Items.Count) ? i+1 : 0;
1338
1339                                 if (i == start)
1340                                         break;
1341                         }
1342                         return true;
1343                 }
1344
1345                 int GetAdjustedIndex (Keys key)
1346                 {
1347                         int result = -1;
1348
1349                         if (View == View.Details) {
1350                                 switch (key) {
1351                                 case Keys.Up:
1352                                         result = FocusedItem.Index - 1;
1353                                         break;
1354                                 case Keys.Down:
1355                                         result = FocusedItem.Index + 1;
1356                                         if (result == items.Count)
1357                                                 result = -1;
1358                                         break;
1359                                 case Keys.PageDown:
1360                                         int last_index = LastVisibleIndex;
1361                                         Rectangle item_rect = new Rectangle (GetItemLocation (last_index), ItemSize);
1362                                         if (item_rect.Bottom > item_control.ClientRectangle.Bottom)
1363                                                 last_index--;
1364                                         if (FocusedItem.Index == last_index) {
1365                                                 if (FocusedItem.Index < Items.Count - 1) {
1366                                                         int page_size = item_control.Height / ItemSize.Height - 1;
1367                                                         result = FocusedItem.Index + page_size - 1;
1368                                                         if (result >= Items.Count)
1369                                                                 result = Items.Count - 1;
1370                                                 }
1371                                         } else
1372                                                 result = last_index;
1373                                         break;
1374                                 case Keys.PageUp:
1375                                         int first_index = FirstVisibleIndex;
1376                                         if (GetItemLocation (first_index).Y < 0)
1377                                                 first_index++;
1378                                         if (FocusedItem.Index == first_index) {
1379                                                 if (first_index > 0) {
1380                                                         int page_size = item_control.Height / ItemSize.Height - 1;
1381                                                         result = first_index - page_size + 1;
1382                                                         if (result < 0)
1383                                                                 result = 0;
1384                                                 }
1385                                         } else
1386                                                 result = first_index;
1387                                         break;
1388                                 }
1389                                 return result;
1390                         }
1391
1392                         ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.Index];
1393                         int row = item_matrix_location.Row;
1394                         int col = item_matrix_location.Col;
1395
1396                         switch (key) {
1397                         case Keys.Left:
1398                                 if (col == 0)
1399                                         return -1;
1400                                 return item_index_matrix [row, col - 1];
1401
1402                         case Keys.Right:
1403                                 if (col == (cols - 1))
1404                                         return -1;
1405                                 while (item_index_matrix [row, col + 1] == 0) {
1406                                         row--;
1407                                         if (row < 0)
1408                                                 return -1;
1409                                 }
1410                                 return item_index_matrix [row, col + 1];
1411
1412                         case Keys.Up:
1413                                 if (row == 0)
1414                                         return -1;
1415                                 return item_index_matrix [row - 1, col];
1416
1417                         case Keys.Down:
1418                                 if (row == (rows - 1) || row == Items.Count - 1)
1419                                         return -1;
1420                                 while (item_index_matrix [row + 1, col] == 0) {
1421                                         col--;
1422                                         if (col < 0)
1423                                                 return -1;
1424                                 }
1425                                 return item_index_matrix [row + 1, col];
1426
1427                         default:
1428                                 return -1;
1429                         }
1430                 }
1431
1432                 ListViewItem selection_start;
1433
1434                 private bool SelectItems (ArrayList sel_items)
1435                 {
1436                         bool changed = false;
1437                         ArrayList curr_items = SelectedItems.List;
1438                         foreach (ListViewItem item in curr_items)
1439                                 if (!sel_items.Contains (item)) {
1440                                         item.Selected = false;
1441                                         changed = true;
1442                                 }
1443                         foreach (ListViewItem item in sel_items)
1444                                 if (!item.Selected) {
1445                                         item.Selected = true;
1446                                         changed = true;
1447                                 }
1448                         return changed;
1449                 }
1450
1451                 private void UpdateMultiSelection (int index, bool reselect)
1452                 {
1453                         bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1454                         bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1455                         ListViewItem item = items [index];
1456
1457                         if (shift_pressed && selection_start != null) {
1458                                 ArrayList list = new ArrayList ();
1459                                 int start_index = selection_start.Index;
1460                                 int start = Math.Min (start_index, index);
1461                                 int end = Math.Max (start_index, index);
1462                                 if (View == View.Details) {
1463                                         for (int i = start; i <= end; i++)
1464                                                 list.Add (items [i]);
1465                                 } else {
1466                                         ItemMatrixLocation start_item_matrix_location = items_matrix_location [start];
1467                                         ItemMatrixLocation end_item_matrix_location = items_matrix_location [end];
1468                                         int left = Math.Min (start_item_matrix_location.Col, end_item_matrix_location.Col);
1469                                         int right = Math.Max (start_item_matrix_location.Col, end_item_matrix_location.Col);
1470                                         int top = Math.Min (start_item_matrix_location.Row, end_item_matrix_location.Row);
1471                                         int bottom = Math.Max (start_item_matrix_location.Row, end_item_matrix_location.Row);
1472
1473                                         for (int i = 0; i < items.Count; i++) {
1474                                                 ItemMatrixLocation item_matrix_loc = items_matrix_location [i];
1475
1476                                                 if (item_matrix_loc.Row >= top && item_matrix_loc.Row <= bottom &&
1477                                                                 item_matrix_loc.Col >= left && item_matrix_loc.Col <= right)
1478                                                         list.Add (items [i]);
1479                                         }
1480                                 }
1481                                 SelectItems (list);
1482                         } else if (ctrl_pressed) {
1483                                 item.Selected = !item.Selected;
1484                                 selection_start = item;
1485                         } else {
1486                                 if (!reselect) {
1487                                         // do not unselect, and reselect the item
1488                                         foreach (int itemIndex in SelectedIndices) {
1489                                                 if (index == itemIndex)
1490                                                         continue;
1491                                                 items [itemIndex].Selected = false;
1492                                         }
1493                                 } else {
1494                                         SelectedItems.Clear ();
1495                                         item.Selected = true;
1496                                 }
1497                                 selection_start = item;
1498                         }
1499                 }
1500
1501                 internal override bool InternalPreProcessMessage (ref Message msg)
1502                 {
1503                         if (msg.Msg == (int)Msg.WM_KEYDOWN) {
1504                                 Keys key_data = (Keys)msg.WParam.ToInt32();
1505                                 if (HandleNavKeys (key_data))
1506                                         return true;
1507                         } 
1508                         return base.InternalPreProcessMessage (ref msg);
1509                 }
1510
1511                 bool HandleNavKeys (Keys key_data)
1512                 {
1513                         if (Items.Count == 0 || !item_control.Visible)
1514                                 return false;
1515
1516                         if (FocusedItem == null)
1517                                 SetFocusedItem (Items [0]);
1518
1519                         switch (key_data) {
1520                         case Keys.End:
1521                                 SelectIndex (Items.Count - 1);
1522                                 break;
1523
1524                         case Keys.Home:
1525                                 SelectIndex (0);
1526                                 break;
1527
1528                         case Keys.Left:
1529                         case Keys.Right:
1530                         case Keys.Up:
1531                         case Keys.Down:
1532                         case Keys.PageUp:
1533                         case Keys.PageDown:
1534                                 SelectIndex (GetAdjustedIndex (key_data));
1535                                 break;
1536
1537                         default:
1538                                 return false;
1539                         }
1540
1541                         return true;
1542                 }
1543
1544                 void SelectIndex (int index)
1545                 {
1546                         if (index == -1)
1547                                 return;
1548
1549                         if (MultiSelect)
1550                                 UpdateMultiSelection (index, true);
1551                         else if (!items [index].Selected)
1552                                 items [index].Selected = true;
1553
1554                         SetFocusedItem (items [index]);
1555                         EnsureVisible (index);
1556                 }
1557
1558                 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1559                 {
1560                         if (ke.Handled || Items.Count == 0 || !item_control.Visible)
1561                                 return;
1562
1563                         ke.Handled = KeySearchString (ke);
1564                 }
1565
1566                 private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
1567                 {
1568                         Point loc = PointToClient (Control.MousePosition);
1569                         return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
1570                 }
1571
1572                 internal class ItemControl : Control {
1573
1574                         ListView owner;
1575                         ListViewItem clicked_item;
1576                         ListViewItem last_clicked_item;
1577                         bool hover_processed = false;
1578                         bool checking = false;
1579                         
1580                         ListViewLabelEditTextBox edit_text_box;
1581                         internal ListViewItem edit_item;
1582                         LabelEditEventArgs edit_args;
1583
1584                         public ItemControl (ListView owner)
1585                         {
1586                                 this.owner = owner;
1587                                 DoubleClick += new EventHandler(ItemsDoubleClick);
1588                                 MouseDown += new MouseEventHandler(ItemsMouseDown);
1589                                 MouseMove += new MouseEventHandler(ItemsMouseMove);
1590                                 MouseHover += new EventHandler(ItemsMouseHover);
1591                                 MouseUp += new MouseEventHandler(ItemsMouseUp);
1592                         }
1593
1594                         void ItemsDoubleClick (object sender, EventArgs e)
1595                         {
1596                                 if (owner.activation == ItemActivation.Standard)
1597                                         owner.OnItemActivate (EventArgs.Empty);
1598                         }
1599
1600                         enum BoxSelect {
1601                                 None,
1602                                 Normal,
1603                                 Shift,
1604                                 Control
1605                         }
1606
1607                         BoxSelect box_select_mode = BoxSelect.None;
1608                         ArrayList prev_selection;
1609                         Point box_select_start;
1610
1611                         Rectangle box_select_rect;
1612                         internal Rectangle BoxSelectRectangle {
1613                                 get { return box_select_rect; }
1614                                 set {
1615                                         if (box_select_rect == value)
1616                                                 return;
1617
1618                                         InvalidateBoxSelectRect ();
1619                                         box_select_rect = value;
1620                                         InvalidateBoxSelectRect ();
1621                                 }
1622                         }
1623
1624                         void InvalidateBoxSelectRect ()
1625                         {
1626                                 if (BoxSelectRectangle.Size.IsEmpty)
1627                                         return;
1628
1629                                 Rectangle edge = BoxSelectRectangle;
1630                                 edge.X -= 1;
1631                                 edge.Y -= 1;
1632                                 edge.Width += 2;
1633                                 edge.Height = 2;
1634                                 Invalidate (edge);
1635                                 edge.Y = BoxSelectRectangle.Bottom - 1;
1636                                 Invalidate (edge);
1637                                 edge.Y = BoxSelectRectangle.Y - 1;
1638                                 edge.Width = 2;
1639                                 edge.Height = BoxSelectRectangle.Height + 2;
1640                                 Invalidate (edge);
1641                                 edge.X = BoxSelectRectangle.Right - 1;
1642                                 Invalidate (edge);
1643                         }
1644
1645                         private Rectangle CalculateBoxSelectRectangle (Point pt)
1646                         {
1647                                 int left = Math.Min (box_select_start.X, pt.X);
1648                                 int right = Math.Max (box_select_start.X, pt.X);
1649                                 int top = Math.Min (box_select_start.Y, pt.Y);
1650                                 int bottom = Math.Max (box_select_start.Y, pt.Y);
1651                                 return Rectangle.FromLTRB (left, top, right, bottom);
1652                         }
1653
1654                         ArrayList BoxSelectedItems {
1655                                 get {
1656                                         ArrayList result = new ArrayList ();
1657                                         Size item_size = owner.ItemSize;
1658                                         for (int i = 0; i < owner.Items.Count; i++) {
1659                                                 Rectangle r = new Rectangle (owner.GetItemLocation (i), item_size);
1660                                                 r.X += r.Width / 4;
1661                                                 r.Y += r.Height / 4;
1662                                                 r.Width /= 2;
1663                                                 r.Height /= 2;
1664                                                 if (BoxSelectRectangle.IntersectsWith (r))
1665                                                         result.Add (owner.Items [i]);
1666                                         }
1667                                         return result;
1668                                 }
1669                         }
1670
1671                         private bool PerformBoxSelection (Point pt)
1672                         {
1673                                 if (box_select_mode == BoxSelect.None)
1674                                         return false;
1675
1676                                 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
1677                                 
1678                                 ArrayList box_items = BoxSelectedItems;
1679
1680                                 ArrayList items;
1681
1682                                 switch (box_select_mode) {
1683
1684                                 case BoxSelect.Normal:
1685                                         items = box_items;
1686                                         break;
1687
1688                                 case BoxSelect.Control:
1689                                         items = new ArrayList ();
1690                                         foreach (ListViewItem item in prev_selection)
1691                                                 if (!box_items.Contains (item))
1692                                                         items.Add (item);
1693                                         foreach (ListViewItem item in box_items)
1694                                                 if (!prev_selection.Contains (item))
1695                                                         items.Add (item);
1696                                         break;
1697
1698                                 case BoxSelect.Shift:
1699                                         items = box_items;
1700                                         foreach (ListViewItem item in box_items)
1701                                                 prev_selection.Remove (item);
1702                                         foreach (ListViewItem item in prev_selection)
1703                                                 items.Add (item);
1704                                         break;
1705
1706                                 default:
1707                                         throw new Exception ("Unexpected Selection mode: " + box_select_mode);
1708                                 }
1709
1710                                 SuspendLayout ();
1711                                 owner.SelectItems (items);
1712                                 ResumeLayout ();
1713
1714                                 return true;
1715                         }
1716
1717                         private void ToggleCheckState (ListViewItem item)
1718                         {
1719                                 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1720                                 item.Checked = !item.Checked;
1721                                 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1722
1723                                 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1724                                 owner.OnItemCheck (ice);
1725                         }
1726
1727                         private void ItemsMouseDown (object sender, MouseEventArgs me)
1728                         {
1729                                 if (owner.items.Count == 0) {
1730                                         owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
1731                                         return;
1732                                 }
1733
1734                                 Size item_size = owner.ItemSize;
1735                                 Point pt = new Point (me.X, me.Y);
1736                                 for (int i = 0; i < owner.items.Count; i++) {
1737                                         Rectangle item_rect = new Rectangle (owner.GetItemLocation (i), item_size);
1738                                         if (!item_rect.Contains (pt))
1739                                                 continue;
1740
1741                                         if (me.Clicks == 1 && owner.items [i].CheckRectReal.Contains (pt)) {
1742                                                 checking = true;
1743                                                 ToggleCheckState (owner.items [i]);
1744                                                 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
1745                                                 return;
1746                                         }
1747
1748                                         if (owner.View == View.Details && !owner.FullRowSelect) {
1749                                                 if (owner.items [i].GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1750                                                         clicked_item = owner.items [i];
1751                                                         break;
1752                                                 }
1753                                         } else
1754                                                 clicked_item = owner.items [i];
1755                                 }
1756
1757
1758                                 if (clicked_item != null) {
1759                                         owner.SetFocusedItem (clicked_item);
1760                                         bool changed = !clicked_item.Selected;
1761
1762                                         if (owner.MultiSelect) {
1763                                                 bool reselect = (!owner.LabelEdit || changed);
1764                                                 owner.UpdateMultiSelection (clicked_item.Index, reselect);
1765                                         } else {
1766                                                 clicked_item.Selected = true;
1767                                         }
1768
1769                                         // Raise double click if the item was clicked. On MS the
1770                                         // double click is only raised if you double click an item
1771                                         if (me.Clicks > 1) {
1772                                                 owner.OnDoubleClick (EventArgs.Empty);
1773                                                 if (owner.CheckBoxes)
1774                                                         ToggleCheckState (clicked_item);
1775                                         } else if (me.Clicks == 1) {
1776                                                 owner.OnClick (EventArgs.Empty);
1777                                                 if (owner.LabelEdit && !changed)
1778                                                         BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
1779                                         }
1780                                 } else {
1781                                         if (owner.MultiSelect) {
1782                                                 Keys mods = XplatUI.State.ModifierKeys;
1783                                                 if ((mods & Keys.Shift) != 0)
1784                                                         box_select_mode = BoxSelect.Shift;
1785                                                 else if ((mods & Keys.Control) != 0)
1786                                                         box_select_mode = BoxSelect.Control;
1787                                                 else
1788                                                         box_select_mode = BoxSelect.Normal;
1789                                                 box_select_start = pt; 
1790                                                 prev_selection = owner.SelectedItems.List;
1791                                         } else if (owner.SelectedItems.Count > 0) {
1792                                                 owner.SelectedItems.Clear ();
1793                                         }
1794                                 }
1795
1796                                 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
1797                         }
1798
1799                         private void ItemsMouseMove (object sender, MouseEventArgs me)
1800                         {
1801                                 bool done = PerformBoxSelection (new Point (me.X, me.Y));
1802
1803                                 if (!done && owner.HoverSelection && hover_processed) {
1804
1805                                         Point pt = PointToClient (Control.MousePosition);
1806                                         ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1807                                         if (item != null && !item.Selected) {
1808                                                 hover_processed = false;
1809                                                 XplatUI.ResetMouseHover (Handle);
1810                                         }
1811                                 }
1812
1813                                 owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
1814                         }
1815
1816
1817                         private void ItemsMouseHover (object sender, EventArgs e)
1818                         {
1819                                 owner.OnMouseHover(e);
1820
1821                                 if (Capture || !owner.HoverSelection)
1822                                         return;
1823
1824                                 hover_processed = true;
1825                                 Point pt = PointToClient (Control.MousePosition);
1826                                 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1827
1828                                 if (item == null)
1829                                         return;
1830
1831                                 item.Selected = true;
1832                         }
1833
1834                         private void ItemsMouseUp (object sender, MouseEventArgs me)
1835                         {
1836                                 Capture = false;
1837                                 if (owner.Items.Count == 0) {
1838                                         owner.OnMouseUp (owner.TranslateMouseEventArgs (me));
1839                                         return;
1840                                 }
1841
1842                                 Point pt = new Point (me.X, me.Y);
1843
1844                                 Rectangle rect = Rectangle.Empty;
1845                                 if (clicked_item != null) {
1846                                         if (owner.view == View.Details && !owner.full_row_select)
1847                                                 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1848                                         else
1849                                                 rect = clicked_item.Bounds;
1850
1851                                         if (rect.Contains (pt)) {
1852                                                 switch (owner.activation) {
1853                                                 case ItemActivation.OneClick:
1854                                                         owner.OnItemActivate (EventArgs.Empty);
1855                                                         break;
1856
1857                                                 case ItemActivation.TwoClick:
1858                                                         if (last_clicked_item == clicked_item) {
1859                                                                 owner.OnItemActivate (EventArgs.Empty);
1860                                                                 last_clicked_item = null;
1861                                                         } else
1862                                                                 last_clicked_item = clicked_item;
1863                                                         break;
1864                                                 default:
1865                                                         // DoubleClick activation is handled in another handler
1866                                                         break;
1867                                                 }
1868                                         }
1869                                 } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
1870                                         // Need this to clean up background clicks
1871                                         owner.SelectedItems.Clear ();
1872                                 }
1873
1874                                 clicked_item = null;
1875                                 box_select_start = Point.Empty;
1876                                 BoxSelectRectangle = Rectangle.Empty;
1877                                 prev_selection = null;
1878                                 box_select_mode = BoxSelect.None;
1879                                 checking = false;
1880                                 owner.OnMouseUp (owner.TranslateMouseEventArgs (me));
1881                         }
1882                         
1883                         private void LabelEditFinished (object sender, EventArgs e)
1884                         {
1885                                 EndEdit (edit_item);
1886                         }
1887
1888                         private void LabelEditCancelled (object sender, EventArgs e)
1889                         {
1890                                 edit_args.SetLabel (null);
1891                                 EndEdit (edit_item);
1892                         }
1893
1894                         private void LabelTextChanged (object sender, EventArgs e)
1895                         {
1896                                 if (edit_args != null)
1897                                         edit_args.SetLabel (edit_text_box.Text);
1898                         }
1899
1900                         internal void BeginEdit (ListViewItem item)
1901                         {
1902                                 if (edit_item != null)
1903                                         EndEdit (edit_item);
1904                                 
1905                                 if (edit_text_box == null) {
1906                                         edit_text_box = new ListViewLabelEditTextBox ();
1907                                         edit_text_box.BorderStyle = BorderStyle.FixedSingle;
1908                                         edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
1909                                         edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
1910                                         edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
1911                                         edit_text_box.Visible = false;
1912                                         Controls.Add (edit_text_box);
1913                                 }
1914                                 
1915                                 item.EnsureVisible();
1916                                 
1917                                 edit_text_box.Reset ();
1918                                 
1919                                 switch (owner.view) {
1920                                         case View.List:
1921                                         case View.SmallIcon:
1922                                         case View.Details:
1923                                                 edit_text_box.TextAlign = HorizontalAlignment.Left;
1924                                                 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
1925                                                 SizeF sizef = DeviceContext.MeasureString (item.Text, item.Font);
1926                                                 edit_text_box.Width = (int)sizef.Width + 4;
1927                                                 edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
1928                                                 edit_text_box.WordWrap = false;
1929                                                 edit_text_box.Multiline = false;
1930                                                 break;
1931                                         case View.LargeIcon:
1932                                                 edit_text_box.TextAlign = HorizontalAlignment.Center;
1933                                                 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
1934                                                 sizef = DeviceContext.MeasureString (item.Text, item.Font);
1935                                                 edit_text_box.Width = (int)sizef.Width + 4;
1936                                                 edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
1937                                                 edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
1938                                                 edit_text_box.WordWrap = true;
1939                                                 edit_text_box.Multiline = true;
1940                                                 break;
1941                                 }
1942
1943                                 edit_item = item;
1944
1945                                 edit_text_box.Text = item.Text;
1946                                 edit_text_box.Font = item.Font;
1947                                 edit_text_box.Visible = true;
1948                                 edit_text_box.Focus ();
1949                                 edit_text_box.SelectAll ();
1950
1951                                 edit_args = new LabelEditEventArgs (owner.Items.IndexOf (edit_item));
1952                                 owner.OnBeforeLabelEdit (edit_args);
1953
1954                                 if (edit_args.CancelEdit)
1955                                         EndEdit (item);
1956                         }
1957
1958                         internal void CancelEdit (ListViewItem item)
1959                         {
1960                                 // do nothing if there's no item being edited, or if the
1961                                 // item being edited is not the one passed in
1962                                 if (edit_item == null || edit_item != item)
1963                                         return;
1964
1965                                 edit_args.SetLabel (null);
1966                                 EndEdit (item);
1967                         }
1968
1969                         internal void EndEdit (ListViewItem item)
1970                         {
1971                                 // do nothing if there's no item being edited, or if the
1972                                 // item being edited is not the one passed in
1973                                 if (edit_item == null || edit_item != item)
1974                                         return;
1975
1976                                 owner.OnAfterLabelEdit (edit_args);
1977                                 if (!edit_args.CancelEdit && edit_args.Label != null)
1978                                         edit_item.Text = edit_text_box.Text;
1979
1980                                 if (edit_text_box != null) {
1981                                         if (edit_text_box.Visible)
1982                                                 edit_text_box.Visible = false;
1983                                         // ensure listview gets focus
1984                                         owner.Focus ();
1985                                 }
1986
1987                                 edit_item = null;
1988                         }
1989
1990                         internal override void OnPaintInternal (PaintEventArgs pe)
1991                         {
1992                                 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1993                         }
1994
1995                         protected override void WndProc (ref Message m)
1996                         {
1997                                 switch ((Msg)m.Msg) {
1998                                 case Msg.WM_KILLFOCUS:
1999                                         owner.Select (false, true);
2000                                         break;
2001                                 case Msg.WM_SETFOCUS:
2002                                         owner.Select (false, true);
2003                                         break;
2004                                 case Msg.WM_RBUTTONDOWN:
2005                                         owner.Select (false, true);
2006                                         break;
2007                                 default:
2008                                         break;
2009                                 }
2010                                 base.WndProc (ref m);
2011                         }
2012                 }
2013                 
2014                 internal class ListViewLabelEditTextBox : TextBox
2015                 {
2016                         int max_width = -1;
2017                         int min_width = -1;
2018                         
2019                         int max_height = -1;
2020                         int min_height = -1;
2021                         
2022                         int old_number_lines = 1;
2023                         
2024                         SizeF text_size_one_char;
2025                         
2026                         public ListViewLabelEditTextBox ()
2027                         {
2028                                 min_height = DefaultSize.Height;
2029                                 text_size_one_char = DeviceContext.MeasureString ("B", Font);
2030                         }
2031                         
2032                         public int MaxWidth {
2033                                 set {
2034                                         if (value < min_width)
2035                                                 max_width = min_width;
2036                                         else
2037                                                 max_width = value;
2038                                 }
2039                         }
2040                         
2041                         public int MaxHeight {
2042                                 set {
2043                                         if (value < min_height)
2044                                                 max_height = min_height;
2045                                         else
2046                                                 max_height = value;
2047                                 }
2048                         }
2049                         
2050                         public new int Width {
2051                                 get {
2052                                         return base.Width;
2053                                 }
2054                                 set {
2055                                         min_width = value;
2056                                         base.Width = value;
2057                                 }
2058                         }
2059                         
2060                         public override Font Font {
2061                                 get {
2062                                         return base.Font;
2063                                 }
2064                                 set {
2065                                         base.Font = value;
2066                                         text_size_one_char = DeviceContext.MeasureString ("B", Font);
2067                                 }
2068                         }
2069                         
2070                         protected override void OnTextChanged (EventArgs e)
2071                         {
2072                                 SizeF text_size = DeviceContext.MeasureString (Text, Font);
2073                                 
2074                                 int new_width = (int)text_size.Width + 8;
2075                                 
2076                                 if (!Multiline)
2077                                         ResizeTextBoxWidth (new_width);
2078                                 else {
2079                                         if (Width != max_width)
2080                                                 ResizeTextBoxWidth (new_width);
2081                                         
2082                                         int number_lines = Lines.Length;
2083                                         
2084                                         if (number_lines != old_number_lines) {
2085                                                 int new_height = number_lines * (int)text_size_one_char.Height + 4;
2086                                                 old_number_lines = number_lines;
2087                                                 
2088                                                 ResizeTextBoxHeight (new_height);
2089                                         }
2090                                 }
2091                                 
2092                                 base.OnTextChanged (e);
2093                         }
2094                         
2095                         protected override bool IsInputKey (Keys key_data)
2096                         {
2097                                 if ((key_data & Keys.Alt) == 0) {
2098                                         switch (key_data & Keys.KeyCode) {
2099                                                 case Keys.Enter:
2100                                                         return true;
2101                                                 case Keys.Escape:
2102                                                         return true;
2103                                         }
2104                                 }
2105                                 return base.IsInputKey (key_data);
2106                         }
2107                         
2108                         protected override void OnKeyDown (KeyEventArgs e)
2109                         {
2110                                 if (!Visible)
2111                                         return;
2112
2113                                 switch (e.KeyCode) {
2114                                 case Keys.Return:
2115                                         Visible = false;
2116                                         e.Handled = true;
2117                                         OnEditingFinished (e);
2118                                         break;
2119                                 case Keys.Escape:
2120                                         Visible = false;
2121                                         e.Handled = true;
2122                                         OnEditingCancelled (e);
2123                                         break;
2124                                 }
2125                         }
2126                         
2127                         protected override void OnLostFocus (EventArgs e)
2128                         {
2129                                 if (Visible) {
2130                                         OnEditingFinished (e);
2131                                 }
2132                         }
2133
2134                         protected void OnEditingCancelled (EventArgs e)
2135                         {
2136                                 EventHandler eh = (EventHandler)(Events [EditingCancelledEvent]);
2137                                 if (eh != null)
2138                                         eh (this, e);
2139                         }
2140                         
2141                         protected void OnEditingFinished (EventArgs e)
2142                         {
2143                                 EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
2144                                 if (eh != null)
2145                                         eh (this, e);
2146                         }
2147                         
2148                         private void ResizeTextBoxWidth (int new_width)
2149                         {
2150                                 if (new_width > max_width)
2151                                         base.Width = max_width;
2152                                 else 
2153                                 if (new_width >= min_width)
2154                                         base.Width = new_width;
2155                                 else
2156                                         base.Width = min_width;
2157                         }
2158                         
2159                         private void ResizeTextBoxHeight (int new_height)
2160                         {
2161                                 if (new_height > max_height)
2162                                         base.Height = max_height;
2163                                 else 
2164                                 if (new_height >= min_height)
2165                                         base.Height = new_height;
2166                                 else
2167                                         base.Height = min_height;
2168                         }
2169                         
2170                         public void Reset ()
2171                         {
2172                                 max_width = -1;
2173                                 min_width = -1;
2174                                 
2175                                 max_height = -1;
2176                                 
2177                                 old_number_lines = 1;
2178                                 
2179                                 Text = String.Empty;
2180                                 
2181                                 Size = DefaultSize;
2182                         }
2183
2184                         static object EditingCancelledEvent = new object ();
2185                         public event EventHandler EditingCancelled {
2186                                 add { Events.AddHandler (EditingCancelledEvent, value); }
2187                                 remove { Events.RemoveHandler (EditingCancelledEvent, value); }
2188                         }
2189
2190                         static object EditingFinishedEvent = new object ();
2191                         public event EventHandler EditingFinished {
2192                                 add { Events.AddHandler (EditingFinishedEvent, value); }
2193                                 remove { Events.RemoveHandler (EditingFinishedEvent, value); }
2194                         }
2195                 }
2196
2197                 internal override void OnPaintInternal (PaintEventArgs pe)
2198                 {
2199                         if (updating)
2200                                 return;
2201                                 
2202                         CalculateScrollBars ();
2203                 }
2204
2205                 void FocusChanged (object o, EventArgs args)
2206                 {
2207                         if (Items.Count == 0)
2208                                 return;
2209
2210                         if (FocusedItem == null)
2211                                 SetFocusedItem (Items [0]);
2212
2213                         item_control.Invalidate (FocusedItem.Bounds);
2214                 }
2215
2216                 private void ListView_MouseWheel (object sender, MouseEventArgs me)
2217                 {
2218                         if (Items.Count == 0)
2219                                 return;
2220
2221                         int lines = me.Delta / 120;
2222
2223                         if (lines == 0)
2224                                 return;
2225
2226                         switch (View) {
2227                         case View.Details:
2228                         case View.SmallIcon:
2229                                 Scroll (v_scroll, -ItemSize.Height * SystemInformation.MouseWheelScrollLines * lines);
2230                                 break;
2231                         case View.LargeIcon:
2232                                 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing)  * lines);
2233                                 break;
2234                         case View.List:
2235                                 Scroll (h_scroll, -ItemSize.Width * lines);
2236                                 break;
2237                         }
2238                 }
2239
2240                 private void ListView_SizeChanged (object sender, EventArgs e)
2241                 {
2242                         CalculateListView (alignment);
2243                 }
2244                 
2245                 private void SetFocusedItem (ListViewItem item)
2246                 {
2247                         if (focused_item != null)
2248                                 focused_item.Focused = false;
2249                         
2250                         if (item != null)
2251                                 item.Focused = true;
2252                                 
2253                         focused_item = item;
2254                 }
2255
2256                 private void HorizontalScroller (object sender, EventArgs e)
2257                 {
2258                         item_control.EndEdit (item_control.edit_item);
2259                         
2260                         // Avoid unnecessary flickering, when button is
2261                         // kept pressed at the end
2262                         if (h_marker != h_scroll.Value) {
2263                                 
2264                                 int pixels = h_marker - h_scroll.Value;
2265                                 
2266                                 h_marker = h_scroll.Value;
2267                                 if (header_control.Visible)
2268                                         XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
2269
2270                                 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
2271                         }
2272                 }
2273
2274                 private void VerticalScroller (object sender, EventArgs e)
2275                 {
2276                         item_control.EndEdit (item_control.edit_item);
2277                         
2278                         // Avoid unnecessary flickering, when button is
2279                         // kept pressed at the end
2280                         if (v_marker != v_scroll.Value) {
2281                                 int pixels = v_marker - v_scroll.Value;
2282                                 Rectangle area = item_control.ClientRectangle;
2283                                 v_marker = v_scroll.Value;
2284                                 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
2285                         }
2286                 }
2287                 #endregion      // Internal Methods Properties
2288
2289                 #region Protected Methods
2290                 protected override void CreateHandle ()
2291                 {
2292                         base.CreateHandle ();
2293                         for (int i = 0; i < SelectedItems.Count; i++)
2294                                 OnSelectedIndexChanged (EventArgs.Empty);
2295                 }
2296
2297                 protected override void Dispose (bool disposing)
2298                 {
2299                         if (disposing) {
2300                                 h_scroll.Dispose ();
2301                                 v_scroll.Dispose ();
2302                                 
2303                                 large_image_list = null;
2304                                 small_image_list = null;
2305                                 state_image_list = null;
2306
2307                                 foreach (ColumnHeader col in columns)
2308                                         col.SetListView (null);
2309
2310                                 foreach (ListViewItem item in items)
2311                                         item.Owner = null;
2312                         }
2313                         
2314                         base.Dispose (disposing);
2315                 }
2316
2317                 protected override bool IsInputKey (Keys keyData)
2318                 {
2319                         switch (keyData) {
2320                         case Keys.Up:
2321                         case Keys.Down:
2322                         case Keys.PageUp:
2323                         case Keys.PageDown:
2324                         case Keys.Right:
2325                         case Keys.Left:
2326                         case Keys.End:
2327                         case Keys.Home:
2328                                 return true;
2329
2330                         default:
2331                                 break;
2332                         }
2333                         
2334                         return base.IsInputKey (keyData);
2335                 }
2336
2337                 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
2338                 {
2339                         LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
2340                         if (eh != null)
2341                                 eh (this, e);
2342                 }
2343
2344                 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
2345                 {
2346                         LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
2347                         if (eh != null)
2348                                 eh (this, e);
2349                 }
2350
2351                 protected virtual void OnColumnClick (ColumnClickEventArgs e)
2352                 {
2353                         ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
2354                         if (eh != null)
2355                                 eh (this, e);
2356                 }
2357
2358                 protected override void OnEnabledChanged (EventArgs e)
2359                 {
2360                         base.OnEnabledChanged (e);
2361                 }
2362
2363                 protected override void OnFontChanged (EventArgs e)
2364                 {
2365                         base.OnFontChanged (e);
2366                         Redraw (true);
2367                 }
2368
2369                 protected override void OnHandleCreated (EventArgs e)
2370                 {
2371                         base.OnHandleCreated (e);
2372                         Sort ();
2373                 }
2374
2375                 protected override void OnHandleDestroyed (EventArgs e)
2376                 {
2377                         base.OnHandleDestroyed (e);
2378                 }
2379
2380                 protected virtual void OnItemActivate (EventArgs e)
2381                 {
2382                         EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
2383                         if (eh != null)
2384                                 eh (this, e);
2385                 }
2386
2387                 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
2388                 {
2389                         EventHandler eh = (EventHandler)(Events [ItemCheckEvent]);
2390                         if (eh != null)
2391                                 eh (this, ice);
2392                 }
2393
2394                 protected virtual void OnItemDrag (ItemDragEventArgs e)
2395                 {
2396                         EventHandler eh = (EventHandler)(Events [ItemDragEvent]);
2397                         if (eh != null)
2398                                 eh (this, e);
2399                 }
2400
2401                 protected virtual void OnSelectedIndexChanged (EventArgs e)
2402                 {
2403                         EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
2404                         if (eh != null)
2405                                 eh (this, e);
2406                 }
2407
2408                 protected override void OnSystemColorsChanged (EventArgs e)
2409                 {
2410                         base.OnSystemColorsChanged (e);
2411                 }
2412
2413                 protected void RealizeProperties ()
2414                 {
2415                         // FIXME: TODO
2416                 }
2417
2418                 protected void UpdateExtendedStyles ()
2419                 {
2420                         // FIXME: TODO
2421                 }
2422
2423                 bool refocusing = false;
2424
2425                 protected override void WndProc (ref Message m)
2426                 {
2427                         switch ((Msg)m.Msg) {
2428                         case Msg.WM_KILLFOCUS:
2429                                 Control receiver = Control.FromHandle (m.WParam);
2430                                 if (receiver == item_control) {
2431                                         has_focus = false;
2432                                         refocusing = true;
2433                                         return;
2434                                 }
2435                                 break;
2436                         case Msg.WM_SETFOCUS:
2437                                 if (refocusing) {
2438                                         has_focus = true;
2439                                         refocusing = false;
2440                                         return;
2441                                 }
2442                                 break;
2443                         default:
2444                                 break;
2445                         }
2446                         base.WndProc (ref m);
2447                 }
2448                 #endregion // Protected Methods
2449
2450                 #region Public Instance Methods
2451                 public void ArrangeIcons ()
2452                 {
2453                         ArrangeIcons (this.alignment);
2454                 }
2455
2456                 public void ArrangeIcons (ListViewAlignment alignment)
2457                 {
2458                         // Icons are arranged only if view is set to LargeIcon or SmallIcon
2459                         if (view == View.LargeIcon || view == View.SmallIcon) {
2460                                 this.CalculateListView (alignment);
2461                                 // we have done the calculations already
2462                                 this.Redraw (false);
2463                         }
2464                 }
2465
2466 #if NET_2_0
2467                 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
2468                 {
2469                         if (columnIndex < 0 || columnIndex >= columns.Count)
2470                                 throw new ArgumentOutOfRangeException ("columnIndex");
2471
2472                         columns [columnIndex].AutoResize (headerAutoResize);
2473                 }
2474
2475                 public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
2476                 {
2477                         BeginUpdate ();
2478                         foreach (ColumnHeader col in columns) 
2479                                 col.AutoResize (headerAutoResize);
2480                         EndUpdate ();
2481                 }
2482 #endif
2483
2484                 public void BeginUpdate ()
2485                 {
2486                         // flag to avoid painting
2487                         updating = true;
2488                 }
2489
2490                 public void Clear ()
2491                 {
2492                         columns.Clear ();
2493                         items.Clear (); // Redraw (true) called here
2494                 }
2495
2496                 public void EndUpdate ()
2497                 {
2498                         // flag to avoid painting
2499                         updating = false;
2500
2501                         // probably, now we need a redraw with recalculations
2502                         this.Redraw (true);
2503                 }
2504
2505                 public void EnsureVisible (int index)
2506                 {
2507                         if (index < 0 || index >= items.Count || scrollable == false)
2508                                 return;
2509
2510                         Rectangle view_rect = item_control.ClientRectangle;
2511                         Rectangle bounds = new Rectangle (GetItemLocation (index), ItemSize);
2512
2513                         if (view_rect.Contains (bounds))
2514                                 return;
2515
2516                         if (View != View.Details) {
2517                                 if (bounds.Left < 0)
2518                                         h_scroll.Value += bounds.Left;
2519                                 else if (bounds.Right > view_rect.Right)
2520                                         h_scroll.Value += (bounds.Right - view_rect.Right);
2521                         }
2522
2523                         if (bounds.Top < 0)
2524                                 v_scroll.Value += bounds.Top;
2525                         else if (bounds.Bottom > view_rect.Bottom)
2526                                 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
2527                 }
2528
2529 #if NET_2_0
2530                 public ListViewItem FindItemWithText (string text)
2531                 {
2532                         if (items.Count == 0)
2533                                 return null;
2534
2535                         return FindItemWithText (text, true, 0, true);
2536                 }
2537
2538                 public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex)
2539                 {
2540                         return FindItemWithText (text, includeSubItems, startIndex, true);
2541                 }
2542
2543                 public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex, bool prefixSearch)
2544                 {
2545                         if (startIndex < 0 || startIndex >= items.Count)
2546                                 throw new ArgumentOutOfRangeException ("startIndex");
2547
2548                         if (text == null)
2549                                 throw new ArgumentNullException ("text");
2550
2551                         for (int i = startIndex; i < items.Count; i++) {
2552                                 ListViewItem lvi = items [i];
2553
2554                                 if ((prefixSearch && lvi.Text.StartsWith (text, true, CultureInfo.CurrentCulture)) // prefix search
2555                                                 || String.Compare (lvi.Text, text, true) == 0) // match
2556                                         return lvi;
2557                         }
2558
2559                         if (includeSubItems) {
2560                                 for (int i = startIndex; i < items.Count; i++) {
2561                                         ListViewItem lvi = items [i];
2562                                         foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
2563                                                 if ((prefixSearch && sub_item.Text.StartsWith (text, true, CultureInfo.CurrentCulture))
2564                                                                 || String.Compare (sub_item.Text, text, true) == 0)
2565                                                         return lvi;
2566                                 }
2567                         }
2568
2569                         return null;
2570                 }
2571 #endif
2572                 
2573                 public ListViewItem GetItemAt (int x, int y)
2574                 {
2575                         Size item_size = ItemSize;
2576                         for (int i = 0; i < items.Count; i++) {
2577                                 Point item_location = GetItemLocation (i);
2578                                 Rectangle item_rect = new Rectangle (item_location, item_size);
2579                                 if (item_rect.Contains (x, y))
2580                                         return items [i];
2581                         }
2582
2583                         return null;
2584                 }
2585
2586                 public Rectangle GetItemRect (int index)
2587                 {
2588                         return GetItemRect (index, ItemBoundsPortion.Entire);
2589                 }
2590
2591                 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
2592                 {
2593                         if (index < 0 || index >= items.Count)
2594                                 throw new IndexOutOfRangeException ("index");
2595
2596                         return items [index].GetBounds (portion);
2597                 }
2598
2599                 public void Sort ()
2600                 {
2601                         Sort (true);
2602                 }
2603
2604                 // we need this overload to reuse the logic for sorting, while allowing
2605                 // redrawing to be done by caller or have it done by this method when
2606                 // sorting is really performed
2607                 //
2608                 // ListViewItemCollection's Add and AddRange methods call this overload
2609                 // with redraw set to false, as they take care of redrawing themselves
2610                 // (they even want to redraw the listview if no sort is performed, as 
2611                 // an item was added), while ListView.Sort () only wants to redraw if 
2612                 // sorting was actually performed
2613                 private void Sort (bool redraw)
2614                 {
2615                         if (!IsHandleCreated || item_sorter == null) {
2616                                 return;
2617                         }
2618                         
2619                         items.Sort (item_sorter);
2620                         if (redraw)
2621                                 this.Redraw (true);
2622                 }
2623
2624                 public override string ToString ()
2625                 {
2626                         int count = this.Items.Count;
2627
2628                         if (count == 0)
2629                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
2630                         else
2631                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
2632                 }
2633                 #endregion      // Public Instance Methods
2634
2635
2636                 #region Subclasses
2637
2638                 class HeaderControl : Control {
2639
2640                         ListView owner;
2641                         bool column_resize_active = false;
2642                         ColumnHeader resize_column;
2643                         ColumnHeader clicked_column;
2644                         ColumnHeader drag_column;
2645                         int drag_x;
2646                         int drag_to_index = -1;
2647
2648                         public HeaderControl (ListView owner)
2649                         {
2650                                 this.owner = owner;
2651                                 MouseDown += new MouseEventHandler (HeaderMouseDown);
2652                                 MouseMove += new MouseEventHandler (HeaderMouseMove);
2653                                 MouseUp += new MouseEventHandler (HeaderMouseUp);
2654                         }
2655
2656                         private ColumnHeader ColumnAtX (int x)
2657                         {
2658                                 Point pt = new Point (x, 0);
2659                                 ColumnHeader result = null;
2660                                 foreach (ColumnHeader col in owner.Columns) {
2661                                         if (col.Rect.Contains (pt)) {
2662                                                 result = col;
2663                                                 break;
2664                                         }
2665                                 }
2666                                 return result;
2667                         }
2668
2669                         private int GetReorderedIndex (ColumnHeader col)
2670                         {
2671                                 if (owner.reordered_column_indices == null)
2672                                         return col.Index;
2673                                 else
2674                                         for (int i = 0; i < owner.Columns.Count; i++)
2675                                                 if (owner.reordered_column_indices [i] == col.Index)
2676                                                         return i;
2677                                 throw new Exception ("Column index missing from reordered array");
2678                         }
2679
2680                         private void HeaderMouseDown (object sender, MouseEventArgs me)
2681                         {
2682                                 if (resize_column != null) {
2683                                         column_resize_active = true;
2684                                         Capture = true;
2685                                         return;
2686                                 }
2687
2688                                 clicked_column = ColumnAtX (me.X + owner.h_marker);
2689
2690                                 if (clicked_column != null) {
2691                                         Capture = true;
2692                                         if (owner.AllowColumnReorder) {
2693                                                 drag_x = me.X;
2694                                                 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
2695                                                 drag_column.Rect = clicked_column.Rect;
2696                                                 drag_to_index = GetReorderedIndex (clicked_column);
2697                                         }
2698                                         clicked_column.Pressed = true;
2699                                         Rectangle bounds = clicked_column.Rect;
2700                                         bounds.X -= owner.h_marker;
2701                                         Invalidate (bounds);
2702                                         return;
2703                                 }
2704                         }
2705
2706                         void StopResize ()
2707                         {
2708                                 column_resize_active = false;
2709                                 resize_column = null;
2710                                 Capture = false;
2711                                 Cursor = Cursors.Default;
2712                         }
2713                         
2714                         private void HeaderMouseMove (object sender, MouseEventArgs me)
2715                         {
2716                                 Point pt = new Point (me.X + owner.h_marker, me.Y);
2717
2718                                 if (column_resize_active) {
2719                                         int width = pt.X - resize_column.X;
2720                                         if (width < 0)
2721                                                 width = 0;
2722
2723                                         if (!owner.CanProceedWithResize (resize_column, width)){
2724                                                 StopResize ();
2725                                                 return;
2726                                         }
2727                                         resize_column.Width = width;
2728                                         return;
2729                                 }
2730
2731                                 resize_column = null;
2732
2733                                 if (clicked_column != null) {
2734                                         if (owner.AllowColumnReorder) {
2735                                                 Rectangle r;
2736
2737                                                 r = drag_column.Rect;
2738                                                 r.X = clicked_column.Rect.X + me.X - drag_x;
2739                                                 drag_column.Rect = r;
2740
2741                                                 int x = me.X + owner.h_marker;
2742                                                 ColumnHeader over = ColumnAtX (x);
2743                                                 if (over == null)
2744                                                         drag_to_index = owner.Columns.Count;
2745                                                 else if (x < over.X + over.Width / 2)
2746                                                         drag_to_index = GetReorderedIndex (over);
2747                                                 else
2748                                                         drag_to_index = GetReorderedIndex (over) + 1;
2749                                                 Invalidate ();
2750                                         } else {
2751                                                 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
2752                                                 bool pressed = clicked_column.Pressed;
2753                                                 clicked_column.Pressed = over == clicked_column;
2754                                                 if (clicked_column.Pressed ^ pressed) {
2755                                                         Rectangle bounds = clicked_column.Rect;
2756                                                         bounds.X -= owner.h_marker;
2757                                                         Invalidate (bounds);
2758                                                 }
2759                                         }
2760                                         return;
2761                                 }
2762
2763                                 for (int i = 0; i < owner.Columns.Count; i++) {
2764                                         Rectangle zone = owner.Columns [i].Rect;
2765                                         zone.X = zone.Right - 5;
2766                                         zone.Width = 10;
2767                                         if (zone.Contains (pt)) {
2768                                                 if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
2769                                                         i++;
2770                                                 resize_column = owner.Columns [i];
2771                                                 break;
2772                                         }
2773                                 }
2774
2775                                 if (resize_column == null)
2776                                         Cursor = Cursors.Default;
2777                                 else
2778                                         Cursor = Cursors.VSplit;
2779                         }
2780
2781                         void HeaderMouseUp (object sender, MouseEventArgs me)
2782                         {
2783                                 Capture = false;
2784
2785                                 if (column_resize_active) {
2786                                         int column_idx = resize_column.Index;
2787                                         StopResize ();
2788                                         owner.RaiseColumnWidthChanged (column_idx);
2789                                         return;
2790                                 }
2791
2792                                 if (clicked_column != null && clicked_column.Pressed) {
2793                                         clicked_column.Pressed = false;
2794                                         Rectangle bounds = clicked_column.Rect;
2795                                         bounds.X -= owner.h_marker;
2796                                         Invalidate (bounds);
2797                                         owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
2798                                 }
2799
2800                                 if (drag_column != null && owner.AllowColumnReorder) {
2801                                         drag_column = null;
2802                                         if (drag_to_index > GetReorderedIndex (clicked_column))
2803                                                 drag_to_index--;
2804                                         if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
2805                                                 owner.ReorderColumn (clicked_column, drag_to_index);
2806                                         drag_to_index = -1;
2807                                         Invalidate ();
2808                                 }
2809
2810                                 clicked_column = null;
2811                         }
2812
2813                         internal override void OnPaintInternal (PaintEventArgs pe)
2814                         {
2815                                 if (owner.updating)
2816                                         return;
2817                                 
2818                                 Theme theme = ThemeEngine.Current;
2819                                 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
2820
2821                                 if (drag_column == null)
2822                                         return;
2823
2824                                 int target_x;
2825                                 if (drag_to_index == owner.Columns.Count)
2826                                         target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
2827                                 else
2828                                         target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
2829                                 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
2830                         }
2831
2832                         protected override void WndProc (ref Message m)
2833                         {
2834                                 switch ((Msg)m.Msg) {
2835                                 case Msg.WM_SETFOCUS:
2836                                         owner.Focus ();
2837                                         break;
2838                                 default:
2839                                         base.WndProc (ref m);
2840                                         break;
2841                                 }
2842                         }
2843                 }
2844
2845                 private class ItemComparer : IComparer {
2846                         readonly SortOrder sort_order;
2847
2848                         public ItemComparer (SortOrder sortOrder)
2849                         {
2850                                 sort_order = sortOrder;
2851                         }
2852
2853                         public int Compare (object x, object y)
2854                         {
2855                                 ListViewItem item_x = x as ListViewItem;
2856                                 ListViewItem item_y = y as ListViewItem;
2857                                 if (sort_order == SortOrder.Ascending)
2858                                         return String.Compare (item_x.Text, item_y.Text);
2859                                 else
2860                                         return String.Compare (item_y.Text, item_x.Text);
2861                         }
2862                 }
2863
2864                 public class CheckedIndexCollection : IList, ICollection, IEnumerable
2865                 {
2866                         private readonly ListView owner;
2867
2868                         #region Public Constructor
2869                         public CheckedIndexCollection (ListView owner)
2870                         {
2871                                 this.owner = owner;
2872                         }
2873                         #endregion      // Public Constructor
2874
2875                         #region Public Properties
2876                         [Browsable (false)]
2877                         public int Count {
2878                                 get { return owner.CheckedItems.Count; }
2879                         }
2880
2881                         public bool IsReadOnly {
2882                                 get { return true; }
2883                         }
2884
2885                         public int this [int index] {
2886                                 get {
2887                                         int [] indices = GetIndices ();
2888                                         if (index < 0 || index >= indices.Length)
2889                                                 throw new ArgumentOutOfRangeException ("index");
2890                                         return indices [index];
2891                                 }
2892                         }
2893
2894                         bool ICollection.IsSynchronized {
2895                                 get { return false; }
2896                         }
2897
2898                         object ICollection.SyncRoot {
2899                                 get { return this; }
2900                         }
2901
2902                         bool IList.IsFixedSize {
2903                                 get { return true; }
2904                         }
2905
2906                         object IList.this [int index] {
2907                                 get { return this [index]; }
2908                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2909                         }
2910                         #endregion      // Public Properties
2911
2912                         #region Public Methods
2913                         public bool Contains (int checkedIndex)
2914                         {
2915                                 int [] indices = GetIndices ();
2916                                 for (int i = 0; i < indices.Length; i++) {
2917                                         if (indices [i] == checkedIndex)
2918                                                 return true;
2919                                 }
2920                                 return false;
2921                         }
2922
2923                         public IEnumerator GetEnumerator ()
2924                         {
2925                                 int [] indices = GetIndices ();
2926                                 return indices.GetEnumerator ();
2927                         }
2928
2929                         void ICollection.CopyTo (Array dest, int index)
2930                         {
2931                                 int [] indices = GetIndices ();
2932                                 Array.Copy (indices, 0, dest, index, indices.Length);
2933                         }
2934
2935                         int IList.Add (object value)
2936                         {
2937                                 throw new NotSupportedException ("Add operation is not supported.");
2938                         }
2939
2940                         void IList.Clear ()
2941                         {
2942                                 throw new NotSupportedException ("Clear operation is not supported.");
2943                         }
2944
2945                         bool IList.Contains (object checkedIndex)
2946                         {
2947                                 if (!(checkedIndex is int))
2948                                         return false;
2949                                 return Contains ((int) checkedIndex);
2950                         }
2951
2952                         int IList.IndexOf (object checkedIndex)
2953                         {
2954                                 if (!(checkedIndex is int))
2955                                         return -1;
2956                                 return IndexOf ((int) checkedIndex);
2957                         }
2958
2959                         void IList.Insert (int index, object value)
2960                         {
2961                                 throw new NotSupportedException ("Insert operation is not supported.");
2962                         }
2963
2964                         void IList.Remove (object value)
2965                         {
2966                                 throw new NotSupportedException ("Remove operation is not supported.");
2967                         }
2968
2969                         void IList.RemoveAt (int index)
2970                         {
2971                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
2972                         }
2973
2974                         public int IndexOf (int checkedIndex)
2975                         {
2976                                 int [] indices = GetIndices ();
2977                                 for (int i = 0; i < indices.Length; i++) {
2978                                         if (indices [i] == checkedIndex)
2979                                                 return i;
2980                                 }
2981                                 return -1;
2982                         }
2983                         #endregion      // Public Methods
2984
2985                         private int [] GetIndices ()
2986                         {
2987                                 ArrayList checked_items = owner.CheckedItems.List;
2988                                 int [] indices = new int [checked_items.Count];
2989                                 for (int i = 0; i < checked_items.Count; i++) {
2990                                         ListViewItem item = (ListViewItem) checked_items [i];
2991                                         indices [i] = item.Index;
2992                                 }
2993                                 return indices;
2994                         }
2995                 }       // CheckedIndexCollection
2996
2997                 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
2998                 {
2999                         private readonly ListView owner;
3000                         private ArrayList list;
3001
3002                         #region Public Constructor
3003                         public CheckedListViewItemCollection (ListView owner)
3004                         {
3005                                 this.owner = owner;
3006                                 this.owner.Items.Changed += new CollectionChangedHandler (
3007                                         ItemsCollection_Changed);
3008                         }
3009                         #endregion      // Public Constructor
3010
3011                         #region Public Properties
3012                         [Browsable (false)]
3013                         public int Count {
3014                                 get {
3015                                         if (!owner.CheckBoxes)
3016                                                 return 0;
3017                                         return List.Count;
3018                                 }
3019                         }
3020
3021                         public bool IsReadOnly {
3022                                 get { return true; }
3023                         }
3024
3025                         public ListViewItem this [int index] {
3026                                 get {
3027                                         ArrayList checked_items = List;
3028                                         if (index < 0 || index >= checked_items.Count)
3029                                                 throw new ArgumentOutOfRangeException ("index");
3030                                         return (ListViewItem) checked_items [index];
3031                                 }
3032                         }
3033
3034 #if NET_2_0
3035                         public virtual ListViewItem this [string key] {
3036                                 get {
3037                                         int idx = IndexOfKey (key);
3038                                         return idx == -1 ? null : (ListViewItem) List [idx];
3039                                 }
3040                         }
3041 #endif
3042
3043                         bool ICollection.IsSynchronized {
3044                                 get { return false; }
3045                         }
3046
3047                         object ICollection.SyncRoot {
3048                                 get { return this; }
3049                         }
3050
3051                         bool IList.IsFixedSize {
3052                                 get { return true; }
3053                         }
3054
3055                         object IList.this [int index] {
3056                                 get { return this [index]; }
3057                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3058                         }
3059                         #endregion      // Public Properties
3060
3061                         #region Public Methods
3062                         public bool Contains (ListViewItem item)
3063                         {
3064                                 if (!owner.CheckBoxes)
3065                                         return false;
3066                                 return List.Contains (item);
3067                         }
3068
3069 #if NET_2_0
3070                         public virtual bool ContainsKey (string key)
3071                         {
3072                                 return IndexOfKey (key) != -1;
3073                         }
3074 #endif
3075
3076                         public void CopyTo (Array dest, int index)
3077                         {
3078                                 if (!owner.CheckBoxes)
3079                                         return;
3080                                 List.CopyTo (dest, index);
3081                         }
3082
3083                         public IEnumerator GetEnumerator ()
3084                         {
3085                                 if (!owner.CheckBoxes)
3086                                         return (new ListViewItem [0]).GetEnumerator ();
3087                                 return List.GetEnumerator ();
3088                         }
3089
3090                         int IList.Add (object value)
3091                         {
3092                                 throw new NotSupportedException ("Add operation is not supported.");
3093                         }
3094
3095                         void IList.Clear ()
3096                         {
3097                                 throw new NotSupportedException ("Clear operation is not supported.");
3098                         }
3099
3100                         bool IList.Contains (object item)
3101                         {
3102                                 if (!(item is ListViewItem))
3103                                         return false;
3104                                 return Contains ((ListViewItem) item);
3105                         }
3106
3107                         int IList.IndexOf (object item)
3108                         {
3109                                 if (!(item is ListViewItem))
3110                                         return -1;
3111                                 return IndexOf ((ListViewItem) item);
3112                         }
3113
3114                         void IList.Insert (int index, object value)
3115                         {
3116                                 throw new NotSupportedException ("Insert operation is not supported.");
3117                         }
3118
3119                         void IList.Remove (object value)
3120                         {
3121                                 throw new NotSupportedException ("Remove operation is not supported.");
3122                         }
3123
3124                         void IList.RemoveAt (int index)
3125                         {
3126                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
3127                         }
3128
3129                         public int IndexOf (ListViewItem item)
3130                         {
3131                                 if (!owner.CheckBoxes)
3132                                         return -1;
3133                                 return List.IndexOf (item);
3134                         }
3135
3136 #if NET_2_0
3137                         public virtual int IndexOfKey (string key)
3138                         {
3139                                 if (key == null || key.Length == 0)
3140                                         return -1;
3141
3142                                 ArrayList checked_items = List;
3143                                 for (int i = 0; i < checked_items.Count; i++) {
3144                                         ListViewItem item = (ListViewItem) checked_items [i];
3145                                         if (String.Compare (key, item.Name, true) == 0)
3146                                                 return i;
3147                                 }
3148
3149                                 return -1;
3150                         }
3151 #endif
3152                         #endregion      // Public Methods
3153
3154                         internal ArrayList List {
3155                                 get {
3156                                         if (list == null) {
3157                                                 list = new ArrayList ();
3158                                                 foreach (ListViewItem item in owner.Items) {
3159                                                         if (item.Checked)
3160                                                                 list.Add (item);
3161                                                 }
3162                                         }
3163                                         return list;
3164                                 }
3165                         }
3166
3167                         internal void Reset ()
3168                         {
3169                                 // force re-population of list
3170                                 list = null;
3171                         }
3172
3173                         private void ItemsCollection_Changed ()
3174                         {
3175                                 Reset ();
3176                         }
3177                 }       // CheckedListViewItemCollection
3178
3179                 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
3180                 {
3181                         internal ArrayList list;
3182                         private ListView owner;
3183
3184                         #region Public Constructor
3185                         public ColumnHeaderCollection (ListView owner)
3186                         {
3187                                 list = new ArrayList ();
3188                                 this.owner = owner;
3189                         }
3190                         #endregion      // Public Constructor
3191
3192                         #region Public Properties
3193                         [Browsable (false)]
3194                         public int Count {
3195                                 get { return list.Count; }
3196                         }
3197
3198                         public bool IsReadOnly {
3199                                 get { return false; }
3200                         }
3201
3202                         public virtual ColumnHeader this [int index] {
3203                                 get {
3204                                         if (index < 0 || index >= list.Count)
3205                                                 throw new ArgumentOutOfRangeException ("index");
3206                                         return (ColumnHeader) list [index];
3207                                 }
3208                         }
3209
3210 #if NET_2_0
3211                         public virtual ColumnHeader this [string key] {
3212                                 get {
3213                                         int idx = IndexOfKey (key);
3214                                         if (idx == -1)
3215                                                 return null;
3216
3217                                         return (ColumnHeader) list [idx];
3218                                 }
3219                         }
3220 #endif
3221
3222                         bool ICollection.IsSynchronized {
3223                                 get { return true; }
3224                         }
3225
3226                         object ICollection.SyncRoot {
3227                                 get { return this; }
3228                         }
3229
3230                         bool IList.IsFixedSize {
3231                                 get { return list.IsFixedSize; }
3232                         }
3233
3234                         object IList.this [int index] {
3235                                 get { return this [index]; }
3236                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3237                         }
3238                         #endregion      // Public Properties
3239
3240                         #region Public Methods
3241                         public virtual int Add (ColumnHeader value)
3242                         {
3243                                 int idx;
3244                                 value.SetListView (this.owner);
3245                                 idx = list.Add (value);
3246                                 if (owner.IsHandleCreated) {
3247                                         owner.Redraw (true); 
3248                                 }
3249                                 return idx;
3250                         }
3251
3252                         public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
3253                         {
3254                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
3255                                 this.Add (colHeader);
3256                                 return colHeader;
3257                         }
3258
3259 #if NET_2_0
3260                         public virtual ColumnHeader Add (string text)
3261                         {
3262                                 return Add (String.Empty, text);
3263                         }
3264
3265                         public virtual ColumnHeader Add (string text, int iwidth)
3266                         {
3267                                 return Add (String.Empty, text, iwidth);
3268                         }
3269
3270                         public virtual ColumnHeader Add (string key, string text)
3271                         {
3272                                 ColumnHeader colHeader = new ColumnHeader ();
3273                                 colHeader.Name = key;
3274                                 colHeader.Text = text;
3275                                 Add (colHeader);
3276                                 return colHeader;
3277                         }
3278
3279                         public virtual ColumnHeader Add (string key, string text, int iwidth)
3280                         {
3281                                 return Add (key, text, iwidth, HorizontalAlignment.Left, -1);
3282                         }
3283
3284                         public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, int imageIndex)
3285                         {
3286                                 ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
3287                                 colHeader.ImageIndex = imageIndex;
3288                                 Add (colHeader);
3289                                 return colHeader;
3290                         }
3291
3292                         public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, string imageKey)
3293                         {
3294                                 ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
3295                                 colHeader.ImageKey = imageKey;
3296                                 Add (colHeader);
3297                                 return colHeader;
3298                         }
3299 #endif
3300
3301                         public virtual void AddRange (ColumnHeader [] values)
3302                         {
3303                                 foreach (ColumnHeader colHeader in values) {
3304                                         colHeader.SetListView (this.owner);
3305                                         Add (colHeader);
3306                                 }
3307                                 
3308                                 owner.Redraw (true); 
3309                         }
3310
3311                         public virtual void Clear ()
3312                         {
3313                                 foreach (ColumnHeader col in list)
3314                                         col.SetListView (null);
3315                                 list.Clear ();
3316                                 owner.Redraw (true);
3317                         }
3318
3319                         public bool Contains (ColumnHeader value)
3320                         {
3321                                 return list.Contains (value);
3322                         }
3323
3324 #if NET_2_0
3325                         public virtual bool ContainsKey (string key)
3326                         {
3327                                 return IndexOfKey (key) != -1;
3328                         }
3329 #endif
3330
3331                         public IEnumerator GetEnumerator ()
3332                         {
3333                                 return list.GetEnumerator ();
3334                         }
3335
3336                         void ICollection.CopyTo (Array dest, int index)
3337                         {
3338                                 list.CopyTo (dest, index);
3339                         }
3340
3341                         int IList.Add (object value)
3342                         {
3343                                 if (! (value is ColumnHeader)) {
3344                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
3345                                 }
3346
3347                                 return this.Add ((ColumnHeader) value);
3348                         }
3349
3350                         bool IList.Contains (object value)
3351                         {
3352                                 if (! (value is ColumnHeader)) {
3353                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
3354                                 }
3355
3356                                 return this.Contains ((ColumnHeader) value);
3357                         }
3358
3359                         int IList.IndexOf (object value)
3360                         {
3361                                 if (! (value is ColumnHeader)) {
3362                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
3363                                 }
3364
3365                                 return this.IndexOf ((ColumnHeader) value);
3366                         }
3367
3368                         void IList.Insert (int index, object value)
3369                         {
3370                                 if (! (value is ColumnHeader)) {
3371                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
3372                                 }
3373
3374                                 this.Insert (index, (ColumnHeader) value);
3375                         }
3376
3377                         void IList.Remove (object value)
3378                         {
3379                                 if (! (value is ColumnHeader)) {
3380                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
3381                                 }
3382
3383                                 this.Remove ((ColumnHeader) value);
3384                         }
3385
3386                         public int IndexOf (ColumnHeader value)
3387                         {
3388                                 return list.IndexOf (value);
3389                         }
3390
3391 #if NET_2_0
3392                         public virtual int IndexOfKey (string key)
3393                         {
3394                                 if (key == null || key.Length == 0)
3395                                         return -1;
3396
3397                                 for (int i = 0; i < list.Count; i++) {
3398                                         ColumnHeader col = (ColumnHeader) list [i];
3399                                         if (String.Compare (key, col.Name, true) == 0)
3400                                                 return i;
3401                                 }
3402
3403                                 return -1;
3404                         }
3405 #endif
3406
3407                         public void Insert (int index, ColumnHeader value)
3408                         {
3409                                 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
3410                                 // but it's really only greater.
3411                                 if (index < 0 || index > list.Count)
3412                                         throw new ArgumentOutOfRangeException ("index");
3413
3414                                 value.SetListView (owner);
3415                                 list.Insert (index, value);
3416                                 owner.Redraw (true);
3417                         }
3418
3419 #if NET_2_0
3420                         public void Insert (int index, string text)
3421                         {
3422                                 Insert (index, String.Empty, text);
3423                         }
3424
3425                         public void Insert (int index, string text, int width)
3426                         {
3427                                 Insert (index, String.Empty, text, width);
3428                         }
3429
3430                         public void Insert (int index, string key, string text)
3431                         {
3432                                 ColumnHeader colHeader = new ColumnHeader ();
3433                                 colHeader.Name = key;
3434                                 colHeader.Text = text;
3435                                 Insert (index, colHeader);
3436                         }
3437
3438                         public void Insert (int index, string key, string text, int width)
3439                         {
3440                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
3441                                 Insert (index, colHeader);
3442                         }
3443
3444                         public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
3445                         {
3446                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
3447                                 colHeader.ImageIndex = imageIndex;
3448                                 Insert (index, colHeader);
3449                         }
3450
3451                         public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
3452                         {
3453                                 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
3454                                 colHeader.ImageKey = imageKey;
3455                                 Insert (index, colHeader);
3456                         }
3457 #endif
3458
3459                         public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
3460                         {
3461                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
3462                                 this.Insert (index, colHeader);
3463                         }
3464
3465                         public virtual void Remove (ColumnHeader column)
3466                         {
3467                                 // TODO: Update Column internal index ?
3468                                 list.Remove (column);
3469                                 column.SetListView (null);
3470                                 owner.Redraw (true);
3471                         }
3472
3473 #if NET_2_0
3474                         public virtual void RemoveByKey (string key)
3475                         {
3476                                 int idx = IndexOfKey (key);
3477                                 if (idx != -1)
3478                                         RemoveAt (idx);
3479                         }
3480 #endif
3481
3482                         public virtual void RemoveAt (int index)
3483                         {
3484                                 if (index < 0 || index >= list.Count)
3485                                         throw new ArgumentOutOfRangeException ("index");
3486
3487                                 ColumnHeader col = (ColumnHeader) list [index];
3488                                 Remove (col);
3489                         }
3490                         #endregion      // Public Methods
3491                         
3492
3493                 }       // ColumnHeaderCollection
3494
3495                 public class ListViewItemCollection : IList, ICollection, IEnumerable
3496                 {
3497                         private readonly ArrayList list;
3498                         private readonly ListView owner;
3499
3500                         #region Public Constructor
3501                         public ListViewItemCollection (ListView owner)
3502                         {
3503                                 list = new ArrayList ();
3504                                 this.owner = owner;
3505                         }
3506                         #endregion      // Public Constructor
3507
3508                         #region Public Properties
3509                         [Browsable (false)]
3510                         public int Count {
3511                                 get { return list.Count; }
3512                         }
3513
3514                         public bool IsReadOnly {
3515                                 get { return false; }
3516                         }
3517
3518                         public virtual ListViewItem this [int displayIndex] {
3519                                 get {
3520                                         if (displayIndex < 0 || displayIndex >= list.Count)
3521                                                 throw new ArgumentOutOfRangeException ("displayIndex");
3522                                         return (ListViewItem) list [displayIndex];
3523                                 }
3524
3525                                 set {
3526                                         if (displayIndex < 0 || displayIndex >= list.Count)
3527                                                 throw new ArgumentOutOfRangeException ("displayIndex");
3528
3529                                         if (list.Contains (value))
3530                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
3531
3532                                         if (value.ListView != null && value.ListView != owner)
3533                                                 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");
3534
3535                                         value.Owner = owner;
3536                                         list [displayIndex] = value;
3537                                         OnChange ();
3538
3539                                         owner.Redraw (true);
3540                                 }
3541                         }
3542
3543 #if NET_2_0
3544                         public virtual ListViewItem this [string key] {
3545                                 get {
3546                                         int idx = IndexOfKey (key);
3547                                         if (idx == -1)
3548                                                 return null;
3549
3550                                         return (ListViewItem) list [idx];
3551                                 }
3552                         }
3553 #endif
3554
3555                         bool ICollection.IsSynchronized {
3556                                 get { return true; }
3557                         }
3558
3559                         object ICollection.SyncRoot {
3560                                 get { return this; }
3561                         }
3562
3563                         bool IList.IsFixedSize {
3564                                 get { return list.IsFixedSize; }
3565                         }
3566
3567                         object IList.this [int index] {
3568                                 get { return this [index]; }
3569                                 set {
3570                                         if (value is ListViewItem)
3571                                                 this [index] = (ListViewItem) value;
3572                                         else
3573                                                 this [index] = new ListViewItem (value.ToString ());
3574                                         OnChange ();
3575                                 }
3576                         }
3577                         #endregion      // Public Properties
3578
3579                         #region Public Methods
3580                         public virtual ListViewItem Add (ListViewItem value)
3581                         {
3582                                 AddItem (value);
3583                                 CollectionChanged (true);
3584
3585                                 return value;
3586                         }
3587
3588                         public virtual ListViewItem Add (string text)
3589                         {
3590                                 ListViewItem item = new ListViewItem (text);
3591                                 return this.Add (item);
3592                         }
3593
3594                         public virtual ListViewItem Add (string text, int imageIndex)
3595                         {
3596                                 ListViewItem item = new ListViewItem (text, imageIndex);
3597                                 return this.Add (item);
3598                         }
3599
3600 #if NET_2_0
3601                         public virtual ListViewItem Add (string text, string imageKey)
3602                         {
3603                                 ListViewItem item = new ListViewItem (text, imageKey);
3604                                 return this.Add (item);
3605                         }
3606
3607                         public virtual ListViewItem Add (string key, string text, int imageIndex)
3608                         {
3609                                 ListViewItem item = new ListViewItem (text, imageIndex);
3610                                 item.Name = key;
3611                                 return this.Add (item);
3612                         }
3613
3614                         public virtual ListViewItem Add (string key, string text, string imageKey)
3615                         {
3616                                 ListViewItem item = new ListViewItem (text, imageKey);
3617                                 item.Name = key;
3618                                 return this.Add (item);
3619                         }
3620 #endif
3621
3622                         public void AddRange (ListViewItem [] values)
3623                         {
3624                                 if (values == null)
3625                                         throw new ArgumentNullException ("Argument cannot be null!", "values");
3626
3627                                 foreach (ListViewItem item in values)
3628                                         AddItem (item);
3629
3630                                 CollectionChanged (true);
3631                         }
3632
3633 #if NET_2_0
3634                         public void AddRange (ListViewItemCollection items)
3635                         {
3636                                 if (items == null)
3637                                         throw new ArgumentNullException ("Argument cannot be null!", "items");
3638
3639                                 ListViewItem[] itemArray = new ListViewItem[items.Count];
3640                                 items.CopyTo (itemArray,0);
3641                                 this.AddRange (itemArray);
3642                         }
3643 #endif
3644
3645                         public virtual void Clear ()
3646                         {
3647                                 owner.SetFocusedItem (null);
3648                                 owner.h_scroll.Value = owner.v_scroll.Value = 0;
3649                                 foreach (ListViewItem item in list) {
3650                                         owner.item_control.CancelEdit (item);
3651                                         item.Owner = null;
3652                                 }
3653                                 list.Clear ();
3654                                 CollectionChanged (false);
3655                         }
3656
3657                         public bool Contains (ListViewItem item)
3658                         {
3659                                 return list.Contains (item);
3660                         }
3661
3662 #if NET_2_0
3663                         public virtual bool ContainsKey (string key)
3664                         {
3665                                 return IndexOfKey (key) != -1;
3666                         }
3667 #endif
3668
3669                         public void CopyTo (Array dest, int index)
3670                         {
3671                                 list.CopyTo (dest, index);
3672                         }
3673
3674 #if NET_2_0
3675                         public ListViewItem [] Find (string key, bool searchAllSubitems)
3676                         {
3677                                 if (key == null)
3678                                         return new ListViewItem [0];
3679
3680                                 List<ListViewItem> temp_list = new List<ListViewItem> ();
3681                                 
3682                                 for (int i = 0; i < list.Count; i++) {
3683                                         ListViewItem lvi = (ListViewItem) list [i];
3684                                         if (String.Compare (key, lvi.Name, true) == 0)
3685                                                 temp_list.Add (lvi);
3686                                 }
3687
3688                                 ListViewItem [] retval = new ListViewItem [temp_list.Count];
3689                                 temp_list.CopyTo (retval);
3690
3691                                 return retval;
3692                         }
3693 #endif
3694
3695                         public IEnumerator GetEnumerator ()
3696                         {
3697                                 return list.GetEnumerator ();
3698                         }
3699
3700                         int IList.Add (object item)
3701                         {
3702                                 int result;
3703                                 ListViewItem li;
3704
3705                                 if (item is ListViewItem) {
3706                                         li = (ListViewItem) item;
3707                                         if (list.Contains (li))
3708                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
3709
3710                                         if (li.ListView != null && li.ListView != owner)
3711                                                 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");
3712                                 }
3713                                 else
3714                                         li = new ListViewItem (item.ToString ());
3715
3716                                 li.Owner = owner;
3717                                 result = list.Add (li);
3718                                 CollectionChanged (true);
3719
3720                                 return result;
3721                         }
3722
3723                         bool IList.Contains (object item)
3724                         {
3725                                 return list.Contains (item);
3726                         }
3727
3728                         int IList.IndexOf (object item)
3729                         {
3730                                 return list.IndexOf (item);
3731                         }
3732
3733                         void IList.Insert (int index, object item)
3734                         {
3735                                 if (item is ListViewItem)
3736                                         this.Insert (index, (ListViewItem) item);
3737                                 else
3738                                         this.Insert (index, item.ToString ());
3739                         }
3740
3741                         void IList.Remove (object item)
3742                         {
3743                                 Remove ((ListViewItem) item);
3744                         }
3745
3746                         public int IndexOf (ListViewItem item)
3747                         {
3748                                 return list.IndexOf (item);
3749                         }
3750
3751 #if NET_2_0
3752                         public virtual int IndexOfKey (string key)
3753                         {
3754                                 if (key == null || key.Length == 0)
3755                                         return -1;
3756
3757                                 for (int i = 0; i < list.Count; i++) {
3758                                         ListViewItem lvi = (ListViewItem) list [i];
3759                                         if (String.Compare (key, lvi.Name, true) == 0)
3760                                                 return i;
3761                                 }
3762
3763                                 return -1;
3764                         }
3765 #endif
3766
3767                         public ListViewItem Insert (int index, ListViewItem item)
3768                         {
3769                                 if (index < 0 || index > list.Count)
3770                                         throw new ArgumentOutOfRangeException ("index");
3771
3772                                 if (list.Contains (item))
3773                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
3774
3775                                 if (item.ListView != null && item.ListView != owner)
3776                                         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");
3777
3778                                 item.Owner = owner;
3779                                 list.Insert (index, item);
3780                                 CollectionChanged (true);
3781                                 return item;
3782                         }
3783
3784                         public ListViewItem Insert (int index, string text)
3785                         {
3786                                 return this.Insert (index, new ListViewItem (text));
3787                         }
3788
3789                         public ListViewItem Insert (int index, string text, int imageIndex)
3790                         {
3791                                 return this.Insert (index, new ListViewItem (text, imageIndex));
3792                         }
3793
3794 #if NET_2_0
3795                         public ListViewItem Insert (int index, string key, string text, int imageIndex)
3796                         {
3797                                 ListViewItem lvi = new ListViewItem (text, imageIndex);
3798                                 lvi.Name = key;
3799                                 return Insert (index, lvi);
3800                         }
3801 #endif
3802
3803                         public virtual void Remove (ListViewItem item)
3804                         {
3805                                 if (!list.Contains (item))
3806                                         return;
3807                                         
3808                                 bool selection_changed = owner.SelectedItems.Contains (item);
3809                                 owner.item_control.CancelEdit (item);
3810                                 list.Remove (item);
3811                                 item.Owner = null;
3812                                 CollectionChanged (false);
3813                                 if (selection_changed)
3814                                         owner.OnSelectedIndexChanged (EventArgs.Empty);
3815                         }
3816
3817                         public virtual void RemoveAt (int index)
3818                         {
3819                                 if (index < 0 || index >= Count)
3820                                         throw new ArgumentOutOfRangeException ("index");
3821                                 ListViewItem item = (ListViewItem) list [index];
3822                                 Remove (item);
3823                         }
3824
3825 #if NET_2_0
3826                         public virtual void RemoveByKey (string key)
3827                         {
3828                                 int idx = IndexOfKey (key);
3829                                 if (idx != -1)
3830                                         RemoveAt (idx);
3831                         }
3832 #endif
3833
3834                         #endregion      // Public Methods
3835
3836                         void AddItem (ListViewItem value)
3837                         {
3838                                 if (list.Contains (value))
3839                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
3840
3841                                 if (value.ListView != null && value.ListView != owner)
3842                                         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");
3843                                 value.Owner = owner;
3844                                 list.Add (value);
3845                         }
3846
3847                         void CollectionChanged (bool sort)
3848                         {
3849                                 if (owner != null) {
3850                                         if (sort)
3851                                                 owner.Sort (false);
3852
3853                                         OnChange ();
3854                                         owner.Redraw (true);
3855                                 }
3856                         }
3857
3858                         internal event CollectionChangedHandler Changed;
3859
3860                         internal void Sort (IComparer comparer)
3861                         {
3862                                 list.Sort (comparer);
3863                                 OnChange ();
3864                         }
3865
3866                         internal void OnChange ()
3867                         {
3868                                 if (Changed != null)
3869                                         Changed ();
3870                         }
3871                 }       // ListViewItemCollection
3872
3873                 public class SelectedIndexCollection : IList, ICollection, IEnumerable
3874                 {
3875                         private readonly ListView owner;
3876
3877                         #region Public Constructor
3878                         public SelectedIndexCollection (ListView owner)
3879                         {
3880                                 this.owner = owner;
3881                         }
3882                         #endregion      // Public Constructor
3883
3884                         #region Public Properties
3885                         [Browsable (false)]
3886                         public int Count {
3887                                 get {
3888                                         return owner.SelectedItems.Count;
3889                                 }
3890                         }
3891
3892                         public bool IsReadOnly {
3893                                 get { 
3894 #if NET_2_0
3895                                         return false;
3896 #else
3897                                         return true; 
3898 #endif
3899                                 }
3900                         }
3901
3902                         public int this [int index] {
3903                                 get {
3904                                         int [] indices = GetIndices ();
3905                                         if (index < 0 || index >= indices.Length)
3906                                                 throw new ArgumentOutOfRangeException ("index");
3907                                         return indices [index];
3908                                 }
3909                         }
3910
3911                         bool ICollection.IsSynchronized {
3912                                 get { return false; }
3913                         }
3914
3915                         object ICollection.SyncRoot {
3916                                 get { return this; }
3917                         }
3918
3919                         bool IList.IsFixedSize {
3920                                 get { 
3921 #if NET_2_0
3922                                         return false;
3923 #else
3924                                         return true;
3925 #endif
3926                                 }
3927                         }
3928
3929                         object IList.this [int index] {
3930                                 get { return this [index]; }
3931                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3932                         }
3933                         #endregion      // Public Properties
3934
3935                         #region Public Methods
3936 #if NET_2_0
3937                         public int Add (int itemIndex)
3938                         {
3939                                 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
3940                                         throw new ArgumentOutOfRangeException ("index");
3941
3942                                 owner.Items [itemIndex].Selected = true;
3943                                 if (!owner.IsHandleCreated)
3944                                         return 0;
3945
3946                                 return owner.SelectedItems.Count;
3947                         }
3948
3949                         public void Clear ()
3950                         {
3951                                 owner.SelectedItems.Clear ();
3952                         }
3953 #endif
3954                         public bool Contains (int selectedIndex)
3955                         {
3956                                 int [] indices = GetIndices ();
3957                                 for (int i = 0; i < indices.Length; i++) {
3958                                         if (indices [i] == selectedIndex)
3959                                                 return true;
3960                                 }
3961                                 return false;
3962                         }
3963
3964                         public void CopyTo (Array dest, int index)
3965                         {
3966                                 int [] indices = GetIndices ();
3967                                 Array.Copy (indices, 0, dest, index, indices.Length);
3968                         }
3969
3970                         public IEnumerator GetEnumerator ()
3971                         {
3972                                 int [] indices = GetIndices ();
3973                                 return indices.GetEnumerator ();
3974                         }
3975
3976                         int IList.Add (object value)
3977                         {
3978                                 throw new NotSupportedException ("Add operation is not supported.");
3979                         }
3980
3981                         void IList.Clear ()
3982                         {
3983                                 throw new NotSupportedException ("Clear operation is not supported.");
3984                         }
3985
3986                         bool IList.Contains (object selectedIndex)
3987                         {
3988                                 if (!(selectedIndex is int))
3989                                         return false;
3990                                 return Contains ((int) selectedIndex);
3991                         }
3992
3993                         int IList.IndexOf (object selectedIndex)
3994                         {
3995                                 if (!(selectedIndex is int))
3996                                         return -1;
3997                                 return IndexOf ((int) selectedIndex);
3998                         }
3999
4000                         void IList.Insert (int index, object value)
4001                         {
4002                                 throw new NotSupportedException ("Insert operation is not supported.");
4003                         }
4004
4005                         void IList.Remove (object value)
4006                         {
4007                                 throw new NotSupportedException ("Remove operation is not supported.");
4008                         }
4009
4010                         void IList.RemoveAt (int index)
4011                         {
4012                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
4013                         }
4014
4015                         public int IndexOf (int selectedIndex)
4016                         {
4017                                 int [] indices = GetIndices ();
4018                                 for (int i = 0; i < indices.Length; i++) {
4019                                         if (indices [i] == selectedIndex)
4020                                                 return i;
4021                                 }
4022                                 return -1;
4023                         }
4024
4025 #if NET_2_0
4026                         public void Remove (int itemIndex)
4027                         {
4028                                 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
4029                                         throw new ArgumentOutOfRangeException ("itemIndex");
4030
4031                                 owner.Items [itemIndex].Selected = false;
4032                         }
4033 #endif
4034                         #endregion      // Public Methods
4035
4036                         private int [] GetIndices ()
4037                         {
4038                                 ArrayList selected_items = owner.SelectedItems.List;
4039                                 int [] indices = new int [selected_items.Count];
4040                                 for (int i = 0; i < selected_items.Count; i++) {
4041                                         ListViewItem item = (ListViewItem) selected_items [i];
4042                                         indices [i] = item.Index;
4043                                 }
4044                                 return indices;
4045                         }
4046                 }       // SelectedIndexCollection
4047
4048                 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
4049                 {
4050                         private readonly ListView owner;
4051                         private ArrayList list;
4052
4053                         #region Public Constructor
4054                         public SelectedListViewItemCollection (ListView owner)
4055                         {
4056                                 this.owner = owner;
4057                                 this.owner.Items.Changed += new CollectionChangedHandler (
4058                                         ItemsCollection_Changed);
4059                         }
4060                         #endregion      // Public Constructor
4061
4062                         #region Public Properties
4063                         [Browsable (false)]
4064                         public int Count {
4065                                 get {
4066                                         if (!owner.IsHandleCreated)
4067                                                 return 0;
4068                                         return List.Count;
4069                                 }
4070                         }
4071
4072                         public bool IsReadOnly {
4073                                 get { return true; }
4074                         }
4075
4076                         public ListViewItem this [int index] {
4077                                 get {
4078                                         ArrayList selected_items = List;
4079                                         if (!owner.IsHandleCreated || index < 0 || index >= selected_items.Count)
4080                                                 throw new ArgumentOutOfRangeException ("index");
4081                                         return (ListViewItem) selected_items [index];
4082                                 }
4083                         }
4084
4085 #if NET_2_0
4086                         public virtual ListViewItem this [string key] {
4087                                 get {
4088                                         int idx = IndexOfKey (key);
4089                                         if (idx == -1)
4090                                                 return null;
4091
4092                                         return (ListViewItem) List [idx];
4093                                 }
4094                         }
4095 #endif
4096
4097                         bool ICollection.IsSynchronized {
4098                                 get { return false; }
4099                         }
4100
4101                         object ICollection.SyncRoot {
4102                                 get { return this; }
4103                         }
4104
4105                         bool IList.IsFixedSize {
4106                                 get { return true; }
4107                         }
4108
4109                         object IList.this [int index] {
4110                                 get { return this [index]; }
4111                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4112                         }
4113                         #endregion      // Public Properties
4114
4115                         #region Public Methods
4116                         public void Clear ()
4117                         {
4118                                 if (!owner.IsHandleCreated)
4119                                         return;
4120
4121                                 foreach (ListViewItem item in List)
4122                                         item.Selected = false;
4123                         }
4124
4125                         public bool Contains (ListViewItem item)
4126                         {
4127                                 if (!owner.IsHandleCreated)
4128                                         return false;
4129                                 return List.Contains (item);
4130                         }
4131
4132 #if NET_2_0
4133                         public virtual bool ContainsKey (string key)
4134                         {
4135                                 return IndexOfKey (key) != -1;
4136                         }
4137 #endif
4138
4139                         public void CopyTo (Array dest, int index)
4140                         {
4141                                 if (!owner.IsHandleCreated)
4142                                         return;
4143                                 List.CopyTo (dest, index);
4144                         }
4145
4146                         public IEnumerator GetEnumerator ()
4147                         {
4148                                 if (!owner.IsHandleCreated)
4149                                         return (new ListViewItem [0]).GetEnumerator ();
4150                                 return List.GetEnumerator ();
4151                         }
4152
4153                         int IList.Add (object value)
4154                         {
4155                                 throw new NotSupportedException ("Add operation is not supported.");
4156                         }
4157
4158                         bool IList.Contains (object item)
4159                         {
4160                                 if (!(item is ListViewItem))
4161                                         return false;
4162                                 return Contains ((ListViewItem) item);
4163                         }
4164
4165                         int IList.IndexOf (object item)
4166                         {
4167                                 if (!(item is ListViewItem))
4168                                         return -1;
4169                                 return IndexOf ((ListViewItem) item);
4170                         }
4171
4172                         void IList.Insert (int index, object value)
4173                         {
4174                                 throw new NotSupportedException ("Insert operation is not supported.");
4175                         }
4176
4177                         void IList.Remove (object value)
4178                         {
4179                                 throw new NotSupportedException ("Remove operation is not supported.");
4180                         }
4181
4182                         void IList.RemoveAt (int index)
4183                         {
4184                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
4185                         }
4186
4187                         public int IndexOf (ListViewItem item)
4188                         {
4189                                 if (!owner.IsHandleCreated)
4190                                         return -1;
4191                                 return List.IndexOf (item);
4192                         }
4193
4194 #if NET_2_0
4195                         public virtual int IndexOfKey (string key)
4196                         {
4197                                 if (!owner.IsHandleCreated || key == null || key.Length == 0)
4198                                         return -1;
4199
4200                                 ArrayList selected_items = List;
4201                                 for (int i = 0; i < selected_items.Count; i++) {
4202                                         ListViewItem item = (ListViewItem) selected_items [i];
4203                                         if (String.Compare (item.Name, key, true) == 0)
4204                                                 return i;
4205                                 }
4206
4207                                 return -1;
4208                         }
4209 #endif
4210                         #endregion      // Public Methods
4211
4212                         internal ArrayList List {
4213                                 get {
4214                                         if (list == null) {
4215                                                 list = new ArrayList ();
4216                                                 foreach (ListViewItem item in owner.Items) {
4217                                                         if (item.Selected)
4218                                                                 list.Add (item);
4219                                                 }
4220                                         }
4221                                         return list;
4222                                 }
4223                         }
4224
4225                         internal void Reset ()
4226                         {
4227                                 // force re-population of list
4228                                 list = null;
4229                         }
4230
4231                         private void ItemsCollection_Changed ()
4232                         {
4233                                 Reset ();
4234                         }
4235                 }       // SelectedListViewItemCollection
4236
4237                 internal delegate void CollectionChangedHandler ();
4238
4239                 struct ItemMatrixLocation
4240                 {
4241                         int row;
4242                         int col;
4243
4244                         public ItemMatrixLocation (int row, int col)
4245                         {
4246                                 this.row = row;
4247                                 this.col = col;
4248                 
4249                         }
4250                 
4251                         public int Col {
4252                                 get {
4253                                         return col;
4254                                 }
4255                                 set {
4256                                         col = value;
4257                                 }
4258                         }
4259
4260                         public int Row {
4261                                 get {
4262                                         return row;
4263                                 }
4264                                 set {
4265                                         row = value;
4266                                 }
4267                         }
4268         
4269                 }
4270
4271                 #endregion // Subclasses
4272 #if NET_2_0
4273                 protected override void OnResize (EventArgs e)
4274                 {
4275                         base.OnResize (e);
4276                 }
4277
4278                 protected override void OnMouseLeave (EventArgs e)
4279                 {
4280                         base.OnMouseLeave (e);
4281                 }
4282
4283                 //
4284                 // ColumnReorder event
4285                 //
4286                 static object ColumnReorderedEvent = new object ();
4287                 public event ColumnReorderedEventHandler ColumnReordered {
4288                         add { Events.AddHandler (ColumnReorderedEvent, value); }
4289                         remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
4290                 }
4291
4292                 protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
4293                 {
4294                         ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
4295
4296                         if (creh != null)
4297                                 creh (this, e);
4298                 }
4299
4300                 //
4301                 // ColumnWidthChanged
4302                 //
4303                 static object ColumnWidthChangedEvent = new object ();
4304                 public event ColumnWidthChangedEventHandler ColumnWidthChanged {
4305                         add { Events.AddHandler (ColumnWidthChangedEvent, value); }
4306                         remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
4307                 }
4308
4309                 protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
4310                 {
4311                         ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
4312                         if (eh != null)
4313                                 eh (this, e);
4314                 }
4315                 
4316                 void RaiseColumnWidthChanged (int resize_column)
4317                 {
4318                         ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
4319
4320                         OnColumnWidthChanged (n);
4321                 }
4322                 
4323                 //
4324                 // ColumnWidthChanging
4325                 //
4326                 static object ColumnWidthChangingEvent = new object ();
4327                 public event ColumnWidthChangingEventHandler ColumnWidthChanging {
4328                         add { Events.AddHandler (ColumnWidthChangingEvent, value); }
4329                         remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
4330                 }
4331
4332                 protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
4333                 {
4334                         ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
4335                         if (cwceh != null)
4336                                 cwceh (this, e);
4337                 }
4338                 
4339                 //
4340                 // 2.0 profile based implementation
4341                 //
4342                 bool CanProceedWithResize (ColumnHeader col, int width)
4343                 {
4344                         ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
4345                         if (cwceh == null)
4346                                 return true;
4347                         
4348                         ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
4349                         cwceh (this, changing);
4350                         return !changing.Cancel;
4351                 }
4352 #else
4353                 //
4354                 // 1.0 profile based implementation
4355                 //
4356                 bool CanProceedWithResize (ColumnHeader col, int width)
4357                 {
4358                         return true;
4359                 }
4360
4361                 void RaiseColumnWidthChanged (int resize_column)
4362                 {
4363                 }
4364 #endif
4365         }
4366 }