fixed tests
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListBox.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-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //      Mike Kestner  <mkestner@novell.com>
25 //
26
27 // COMPLETE
28
29 using System;
30 using System.Drawing;
31 using System.Collections;
32 using System.ComponentModel;
33 using System.ComponentModel.Design;
34 using System.ComponentModel.Design.Serialization;
35 using System.Reflection;
36 using System.Runtime.InteropServices;
37
38 namespace System.Windows.Forms
39 {
40         [DefaultProperty("Items")]
41         [DefaultEvent("SelectedIndexChanged")]
42         [Designer ("System.Windows.Forms.Design.ListBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43 #if NET_2_0
44         [DefaultBindingProperty ("SelectedValue")]
45         [ClassInterface (ClassInterfaceType.AutoDispatch)]
46         [ComVisible (true)]
47 #endif
48         public class ListBox : ListControl
49         {
50                 public const int DefaultItemHeight = 13;
51                 public const int NoMatches = -1;
52                 
53                 internal enum ItemNavigation
54                 {
55                         First,
56                         Last,
57                         Next,
58                         Previous,
59                         NextPage,
60                         PreviousPage,
61                         PreviousColumn,
62                         NextColumn
63                 }
64                 
65                 Hashtable item_heights;
66                 private int item_height = -1;
67                 private int column_width = 0;
68                 private int requested_height = -1;
69                 private DrawMode draw_mode = DrawMode.Normal;
70                 private int horizontal_extent = 0;
71                 private bool horizontal_scrollbar = false;
72                 private bool integral_height = true;
73                 private bool multicolumn = false;
74                 private bool scroll_always_visible = false;
75                 private int selected_index = -1;                
76                 private SelectedIndexCollection selected_indices;               
77                 private SelectedObjectCollection selected_items;
78                 private ArrayList selection = new ArrayList ();
79                 private SelectionMode selection_mode = SelectionMode.One;
80                 private bool sorted = false;
81                 private bool use_tabstops = true;
82                 private int column_width_internal = 120;
83                 private ImplicitVScrollBar vscrollbar;
84                 private ImplicitHScrollBar hscrollbar;
85                 private int hbar_offset;
86                 private bool suspend_layout;
87                 private bool ctrl_pressed = false;
88                 private bool shift_pressed = false;
89                 private bool explicit_item_height = false;
90                 private int top_index = 0;
91                 private int last_visible_index = 0;
92                 private Rectangle items_area;
93                 private int focused_item = -1;          
94                 private ObjectCollection items;
95
96                 public ListBox ()
97                 {
98                         border_style = BorderStyle.Fixed3D;                     
99                         BackColor = ThemeEngine.Current.ColorWindow;
100
101                         items = CreateItemCollection ();
102                         selected_indices = new SelectedIndexCollection (this);
103                         selected_items = new SelectedObjectCollection (this);
104
105                         /* Vertical scrollbar */
106                         vscrollbar = new ImplicitVScrollBar ();
107                         vscrollbar.Minimum = 0;
108                         vscrollbar.SmallChange = 1;
109                         vscrollbar.LargeChange = 1;
110                         vscrollbar.Maximum = 0;
111                         vscrollbar.ValueChanged += new EventHandler (VerticalScrollEvent);
112                         vscrollbar.Visible = false;
113
114                         /* Horizontal scrollbar */
115                         hscrollbar = new ImplicitHScrollBar ();
116                         hscrollbar.Minimum = 0;
117                         hscrollbar.SmallChange = 1;
118                         hscrollbar.LargeChange = 1;
119                         hscrollbar.Maximum = 0;
120                         hscrollbar.Visible = false;
121                         hscrollbar.ValueChanged += new EventHandler (HorizontalScrollEvent);
122
123                         /* Events */
124                         MouseDown += new MouseEventHandler (OnMouseDownLB);
125                         MouseMove += new MouseEventHandler (OnMouseMoveLB);
126                         MouseUp += new MouseEventHandler (OnMouseUpLB);
127                         MouseWheel += new MouseEventHandler (OnMouseWheelLB);
128                         KeyDown += new KeyEventHandler (OnKeyDownLB);
129                         KeyUp += new KeyEventHandler (OnKeyUpLB);
130                         GotFocus += new EventHandler (OnGotFocus);
131                         LostFocus += new EventHandler (OnLostFocus);
132                         
133                         SetStyle (ControlStyles.UserPaint, false);
134                 }
135
136                 #region Events
137                 static object DrawItemEvent = new object ();
138                 static object MeasureItemEvent = new object ();
139                 static object SelectedIndexChangedEvent = new object ();
140
141                 [Browsable (false)]
142                 [EditorBrowsable (EditorBrowsableState.Never)]
143                 public new event EventHandler BackgroundImageChanged {
144                         add { base.BackgroundImageChanged += value; }
145                         remove { base.BackgroundImageChanged -= value; }
146                 }
147
148 #if NET_2_0
149                 [Browsable (true)]
150                 [EditorBrowsable (EditorBrowsableState.Always)]
151 #else
152                 [Browsable (false)]
153                 [EditorBrowsable (EditorBrowsableState.Advanced)]
154 #endif
155                 public new event EventHandler Click {
156                         add { base.Click += value; }
157                         remove { base.Click -= value; }
158                 }
159
160                 public event DrawItemEventHandler DrawItem {
161                         add { Events.AddHandler (DrawItemEvent, value); }
162                         remove { Events.RemoveHandler (DrawItemEvent, value); }
163                 }
164
165                 public event MeasureItemEventHandler MeasureItem {
166                         add { Events.AddHandler (MeasureItemEvent, value); }
167                         remove { Events.RemoveHandler (MeasureItemEvent, value); }
168                 }
169
170                 [Browsable (false)]
171                 [EditorBrowsable (EditorBrowsableState.Never)]
172                 public new event PaintEventHandler Paint {
173                         add { base.Paint += value; }
174                         remove { base.Paint -= value; }
175                 }
176
177                 public event EventHandler SelectedIndexChanged {
178                         add { Events.AddHandler (SelectedIndexChangedEvent, value); }
179                         remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
180                 }
181
182                 [Browsable (false)]
183                 [EditorBrowsable (EditorBrowsableState.Advanced)]
184                 public new event EventHandler TextChanged {
185                         add { base.TextChanged += value; }
186                         remove { base.TextChanged -= value; }
187                 }
188                 #endregion // Events
189
190                 #region Public Properties
191                 public override Color BackColor {
192                         get { return base.BackColor; }
193                         set {
194                                 if (base.BackColor == value)
195                                         return;
196
197                                 base.BackColor = value;
198                                 base.Refresh ();        // Careful. Calling the base method is not the same that calling 
199                         }                               // the overriden one that refresh also all the items
200                 }
201
202                 [Browsable (false)]
203                 [EditorBrowsable (EditorBrowsableState.Never)]
204                 public override Image BackgroundImage {
205                         get { return base.BackgroundImage; }
206                         set { 
207                                 base.BackgroundImage = value;
208                                 base.Refresh ();
209                         }
210                 }
211
212                 [DefaultValue (BorderStyle.Fixed3D)]
213                 [DispId(-504)]
214                 public BorderStyle BorderStyle {
215                         get { return InternalBorderStyle; }
216                         set { 
217                                 InternalBorderStyle = value; 
218                                 UpdateListBoxBounds ();
219                         }
220                 }
221
222                 [DefaultValue (0)]
223                 [Localizable (true)]
224                 public int ColumnWidth {
225                         get { return column_width; }
226                         set {
227                                 if (value < 0)
228                                         throw new ArgumentException ("A value less than zero is assigned to the property.");
229
230                                 column_width = value;
231
232                                 if (value == 0)
233                                         ColumnWidthInternal = 120;
234                                 else
235                                         ColumnWidthInternal = value;
236
237                                 base.Refresh ();
238                         }
239                 }
240
241                 protected override CreateParams CreateParams {
242                         get { return base.CreateParams;}
243                 }
244
245                 protected override Size DefaultSize {
246                         get { return new Size (120, 96); }
247                 }
248
249                 [RefreshProperties(RefreshProperties.Repaint)]
250                 [DefaultValue (DrawMode.Normal)]
251                 public virtual DrawMode DrawMode {
252                         get { return draw_mode; }
253
254                         set {
255                                 if (!Enum.IsDefined (typeof (DrawMode), value))
256                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
257                                         
258                                 if (value == DrawMode.OwnerDrawVariable && multicolumn == true)
259                                         throw new ArgumentException ("Cannot have variable height and multicolumn");
260
261                                 if (draw_mode == value)
262                                         return;
263
264                                 draw_mode = value;
265
266                                 if (draw_mode == DrawMode.OwnerDrawVariable)
267                                         item_heights = new Hashtable ();
268                                 else
269                                         item_heights = null;
270
271                                 base.Refresh ();
272                         }
273                 }
274
275                 public override Color ForeColor {
276                         get { return base.ForeColor; }
277                         set {
278
279                                 if (base.ForeColor == value)
280                                         return;
281
282                                 base.ForeColor = value;
283                                 base.Refresh ();
284                         }
285                 }
286
287                 [DefaultValue (0)]
288                 [Localizable (true)]
289                 public int HorizontalExtent {
290                         get { return horizontal_extent; }
291                         set {
292                                 if (horizontal_extent == value)
293                                         return;
294
295                                 horizontal_extent = value;
296                                 base.Refresh ();
297                         }
298                 }
299
300                 [DefaultValue (false)]
301                 [Localizable (true)]
302                 public bool HorizontalScrollbar {
303                         get { return horizontal_scrollbar; }
304                         set {
305                                 if (horizontal_scrollbar == value)
306                                         return;
307
308                                 horizontal_scrollbar = value;
309                                 UpdateScrollBars ();
310                                 base.Refresh ();
311                         }
312                 }
313
314                 [DefaultValue (true)]
315                 [Localizable (true)]
316                 [RefreshProperties(RefreshProperties.Repaint)]
317                 public bool IntegralHeight {
318                         get { return integral_height; }
319                         set {
320                                 if (integral_height == value)
321                                         return;
322
323                                 integral_height = value;
324                                 UpdateListBoxBounds ();
325                         }
326                 }
327
328                 [DefaultValue (13)]
329                 [Localizable (true)]
330                 [RefreshProperties(RefreshProperties.Repaint)]
331                 public virtual int ItemHeight {
332                         get {
333                                 if (item_height == -1) {
334                                         SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
335                                         item_height = (int) sz.Height;
336                                 }
337                                 return item_height;
338                         }
339                         set {
340                                 if (value > 255)
341                                         throw new ArgumentOutOfRangeException ("The ItemHeight property was set beyond 255 pixels");
342
343                                 explicit_item_height = true;
344                                 if (item_height == value)
345                                         return;
346
347                                 item_height = value;
348                                 if (IntegralHeight)
349                                         UpdateListBoxBounds ();
350                                 LayoutListBox ();
351                         }
352                 }
353
354                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
355                 [Localizable (true)]
356                 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
357 #if NET_2_0
358                 [MergableProperty (false)]
359 #endif
360                 public ObjectCollection Items {
361                         get { return items; }
362                 }
363
364                 [DefaultValue (false)]
365                 public bool MultiColumn {
366                         get { return multicolumn; }
367                         set {
368                                 if (multicolumn == value)
369                                         return;
370
371                                 if (value == true && DrawMode == DrawMode.OwnerDrawVariable)
372                                         throw new ArgumentException ("A multicolumn ListBox cannot have a variable-sized height.");
373                                         
374                                 multicolumn = value;
375                                 LayoutListBox ();
376                         }
377                 }
378
379                 [Browsable (false)]
380                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
381                 [EditorBrowsable (EditorBrowsableState.Advanced)]
382                 public int PreferredHeight {
383                         get {
384                                 int itemsHeight = 0;
385                                 if (draw_mode == DrawMode.Normal)
386                                         itemsHeight = FontHeight * items.Count;
387                                 else if (draw_mode == DrawMode.OwnerDrawFixed)
388                                         itemsHeight = ItemHeight * items.Count;
389                                 else if (draw_mode == DrawMode.OwnerDrawVariable) {
390                                         for (int i = 0; i < items.Count; i++)
391                                                 itemsHeight += (int) item_heights [Items [i]];
392                                 }
393                                 
394                                 return itemsHeight;
395                         }
396                 }
397
398                 public override RightToLeft RightToLeft {
399                         get { return base.RightToLeft; }
400                         set {
401                                 base.RightToLeft = value;                               
402                                 if (base.RightToLeft == RightToLeft.Yes)
403                                         StringFormat.Alignment = StringAlignment.Far;                           
404                                 else
405                                         StringFormat.Alignment = StringAlignment.Near;                          
406                                 base.Refresh ();
407                         }
408                 }
409
410                 // Only affects the Vertical ScrollBar
411                 [DefaultValue (false)]
412                 [Localizable (true)]
413                 public bool ScrollAlwaysVisible {
414                         get { return scroll_always_visible; }
415                         set {
416                                 if (scroll_always_visible == value)
417                                         return;
418
419                                 scroll_always_visible = value;
420                                 UpdateScrollBars ();
421                         }
422                 }
423
424                 [Bindable(true)]
425                 [Browsable (false)]
426                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
427                 public override int SelectedIndex {
428                         get { return selected_index;}
429                         set {
430                                 if (value < -1 || value >= Items.Count)
431                                         throw new ArgumentOutOfRangeException ("Index of out range");
432
433                                 if (SelectionMode == SelectionMode.None)
434                                         throw new ArgumentException ("cannot call this method if SelectionMode is SelectionMode.None");
435
436                                 if (selected_index == value)
437                                         return;
438
439                                 if (value == -1)
440                                         ClearSelected ();
441                                 else if (SelectionMode == SelectionMode.One)
442                                         UnSelectItem (selected_index, true);
443
444                                 if (value < top_index)
445                                 {
446                                         top_index = value;
447                                         UpdateTopItem ();
448                                 } else {
449                                         int rows = items_area.Height / ItemHeight;
450                                         if (value >= (top_index + rows))
451                                         {
452                                                 top_index = value - rows + 1;
453                                                 UpdateTopItem ();
454                                         }
455                                 }
456                                 SelectItem (value);
457                                 selected_index = value;
458                                 FocusedItem = value;
459                                 OnSelectedIndexChanged  (new EventArgs ());
460                                 OnSelectedValueChanged (new EventArgs ());
461                         }
462                 }
463
464                 [Browsable (false)]
465                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
466                 public SelectedIndexCollection SelectedIndices {
467                         get { return selected_indices; }
468                 }
469
470                 [Bindable(true)]
471                 [Browsable (false)]
472                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
473                 public object SelectedItem {
474                         get {
475                                 if (SelectedItems.Count > 0)
476                                         return SelectedItems[0];
477                                 else
478                                         return null;
479                         }
480                         set {
481                                 if (value != null && !Items.Contains (value))
482                                         return; // FIXME: this is probably an exception
483                                         
484                                 SelectedIndex = value == null ? - 1 : Items.IndexOf (value);
485                         }
486                 }
487
488                 [Browsable (false)]
489                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
490                 public SelectedObjectCollection SelectedItems {
491                         get {return selected_items;}
492                 }
493
494                 [DefaultValue (SelectionMode.One)]
495                 public virtual SelectionMode SelectionMode {
496                         get { return selection_mode; }
497                         set {
498                                 if (!Enum.IsDefined (typeof (SelectionMode), value))
499                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for SelectionMode", value));
500
501                                 if (selection_mode == value)
502                                         return;
503                                         
504                                 selection_mode = value;
505                                         
506                                 switch (selection_mode) {
507                                 case SelectionMode.None: 
508                                         ClearSelected ();
509                                         break;                                          
510
511                                 case SelectionMode.One:
512                                         while (SelectedIndices.Count > 1)
513                                                 UnSelectItem (SelectedIndices [SelectedIndices.Count - 1], true);
514                                         break;
515
516                                 default:
517                                         break;                                          
518                                 }
519                         }
520                 }
521
522                 [DefaultValue (false)]
523                 public bool Sorted {
524                         get { return sorted; }
525
526                         set {
527                                 if (sorted == value)
528                                         return;
529
530                                 sorted = value;
531                                 if (sorted)
532                                         Sort ();
533                         }
534                 }
535
536                 [Bindable (false)]
537                 [Browsable (false)]
538                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
539                 [EditorBrowsable (EditorBrowsableState.Advanced)]
540                 public override string Text {
541                         get {
542                                 if (SelectionMode != SelectionMode.None && SelectedIndex != -1)
543                                         return GetItemText (SelectedItem);
544
545                                 return base.Text;
546                         }
547                         set {
548
549                                 base.Text = value;
550
551                                 if (SelectionMode == SelectionMode.None)
552                                         return;
553
554                                 int index;
555
556                                 index = FindStringExact (value);
557
558                                 if (index == -1)
559                                         return;
560
561                                 SelectedIndex = index;
562                         }
563                 }
564
565                 [Browsable (false)]
566                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
567                 public int TopIndex {
568                         get { return top_index; }
569                         set {
570                                 if (value == top_index)
571                                         return;
572
573                                 if (value < 0 || value >= Items.Count)
574                                         return;
575
576                                 top_index = value;
577                                 UpdateTopItem ();
578                                 base.Refresh ();
579                         }
580                 }
581
582                 [DefaultValue (true)]
583                 public bool UseTabStops {
584                         get { return use_tabstops; }
585
586                         set {
587                                 if (use_tabstops == value)
588                                         return;
589
590                                 use_tabstops = value;                                   
591                                 if (use_tabstops)
592                                         StringFormat.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)});
593                                 else
594                                         StringFormat.SetTabStops (0, new float [0]);
595                                 base.Refresh ();
596                         }
597                 }
598
599 #if NET_2_0
600                 protected override bool AllowSelection {
601                         get {
602                                 return SelectionMode != SelectionMode.None;
603                         }
604                 }
605 #endif
606
607                 #endregion Public Properties
608
609                 #region Private Properties
610
611                 private int ColumnWidthInternal {
612                         get { return column_width_internal; }
613                         set { column_width_internal = value; }
614                 }
615
616                 private int row_count = 1;
617                 private int RowCount {
618                         get {
619                                 return MultiColumn ? row_count : Items.Count;
620                         }
621                 }
622
623                 #endregion Private Properties
624
625                 #region Public Methods
626 #if NET_2_0
627                 [Obsolete ("this method has been deprecated")]
628 #endif
629                 protected virtual void AddItemsCore (object[] value)
630                 {
631                         Items.AddRange (value);
632                 }
633
634                 public void BeginUpdate ()
635                 {
636                         suspend_layout = true;
637                 }
638
639                 public void ClearSelected ()
640                 {
641                         foreach (int i in selected_indices) {
642                                 UnSelectItem (i, false);
643                         }
644
645                         selection.Clear ();
646                 }
647
648                 protected virtual ObjectCollection CreateItemCollection ()
649                 {
650                         return new ObjectCollection (this);
651                 }
652
653                 public void EndUpdate ()
654                 {
655                         suspend_layout = false;
656                         LayoutListBox ();
657                         base.Refresh ();
658                 }
659
660                 public int FindString (String s)
661                 {
662                         return FindString (s, -1);
663                 }
664
665                 public int FindString (string s,  int startIndex)
666                 {
667                         if (Items.Count == 0)
668                                 return -1; // No exception throwing if empty
669
670                         if (startIndex < -1 || startIndex >= Items.Count - 1)
671                                 throw new ArgumentOutOfRangeException ("Index of out range");
672
673                         startIndex++;
674                         for (int i = startIndex; i < Items.Count; i++) {
675                                 if ((GetItemText (Items[i])).StartsWith (s))
676                                         return i;
677                         }
678
679                         return NoMatches;
680                 }
681
682                 public int FindStringExact (string s)
683                 {
684                         return FindStringExact (s, -1);
685                 }
686
687                 public int FindStringExact (string s,  int startIndex)
688                 {
689                         if (Items.Count == 0)
690                                 return -1; // No exception throwing if empty
691
692                         if (startIndex < -1 || startIndex >= Items.Count - 1)
693                                 throw new ArgumentOutOfRangeException ("Index of out range");
694
695                         startIndex++;
696                         for (int i = startIndex; i < Items.Count; i++) {
697                                 if ((GetItemText (Items[i])).Equals (s))
698                                         return i;
699                         }
700
701                         return NoMatches;
702                 }
703
704                 public int GetItemHeight (int index)
705                 {
706                         if (index < 0 || index >= Items.Count)
707                                 throw new ArgumentOutOfRangeException ("Index of out range");
708                                 
709                         if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {
710                                 
711                                 object o = Items [index];
712                                 if (item_heights.Contains (o))
713                                         return (int) item_heights [o];
714                                 
715                                 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
716                                 OnMeasureItem (args);
717                                 item_heights [o] = args.ItemHeight;
718                                 return args.ItemHeight;
719                         }
720
721                         return ItemHeight;
722                 }
723
724                 public Rectangle GetItemRectangle (int index)
725                 {
726                         if (index < 0 || index >= Items.Count)
727                                 throw new  ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
728
729                         Rectangle rect = new Rectangle ();
730
731                         if (MultiColumn) {
732                                 int col = index / RowCount;
733                                 rect.Y = ((index - top_index) % RowCount) * ItemHeight;
734                                 rect.X = col * ColumnWidthInternal;
735                                 rect.Height = ItemHeight;
736                                 rect.Width = ColumnWidthInternal;
737                         } else {
738                                 rect.X = 0;                             
739                                 rect.Height = GetItemHeight (index);
740                                 rect.Width = items_area.Width;
741                                 
742                                 if (DrawMode == DrawMode.OwnerDrawVariable) {
743                                         rect.Y = 0;
744                                         if (index >= top_index) {
745                                                 for (int i = top_index; i < index; i++) {
746                                                         rect.Y += GetItemHeight (i);
747                                                 }
748                                         } else {
749                                                 for (int i = index; i < top_index; i++) {
750                                                         rect.Y -= GetItemHeight (i);
751                                                 }
752                                         }
753                                 } else {
754                                         rect.Y = ItemHeight * (index - top_index);      
755                                 }                               
756                         }
757
758                         return rect;
759                 }
760
761                 public bool GetSelected (int index)
762                 {
763                         if (index < 0 || index >= Items.Count)
764                                 throw new ArgumentOutOfRangeException ("Index of out range");
765
766                         return SelectedIndices.Contains (index);
767                 }
768
769                 public int IndexFromPoint (Point p)
770                 {
771                         return IndexFromPoint (p.X, p.Y);
772                 }
773
774                 // Only returns visible points
775                 public int IndexFromPoint (int x, int y)
776                 {
777
778                         if (Items.Count == 0) {
779                                 return -1;
780                         }
781
782                         for (int i = top_index; i <= last_visible_index; i++) {
783                                 if (GetItemRectangle (i).Contains (x,y) == true)
784                                         return i;
785                         }
786
787                         return -1;
788                 }
789
790                 protected override void OnChangeUICues (UICuesEventArgs e)
791                 {
792                         base.OnChangeUICues (e);
793                 }
794
795                 protected override void OnDataSourceChanged (EventArgs e)
796                 {
797                         base.OnDataSourceChanged (e);
798                         BindDataItems ();
799                         
800                         if (DataSource == null || DataManager == null) {
801                                 SelectedIndex = -1;
802                         } 
803                         else {
804                                 SelectedIndex = DataManager.Position;
805                         }
806                 }
807
808                 protected override void OnDisplayMemberChanged (EventArgs e)
809                 {
810                         base.OnDisplayMemberChanged (e);
811
812                         if (DataManager == null || !IsHandleCreated)
813                                 return;
814
815                         BindDataItems ();
816                         base.Refresh ();
817                 }
818
819                 protected virtual void OnDrawItem (DrawItemEventArgs e)
820                 {                       
821                         switch (DrawMode) {
822                         case DrawMode.OwnerDrawFixed:
823                         case DrawMode.OwnerDrawVariable:
824                                 DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
825                                 if (eh != null)
826                                         eh (this, e);
827
828                                 break;
829
830                         default:
831                                 ThemeEngine.Current.DrawListBoxItem (this, e);
832                                 break;
833                         }
834                 }
835
836                 protected override void OnFontChanged (EventArgs e)
837                 {
838                         base.OnFontChanged (e);
839
840                         if (use_tabstops)
841                                 StringFormat.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)});
842
843                         if (explicit_item_height) {
844                                 base.Refresh ();
845                         } else {
846                                 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
847                                 item_height = (int) sz.Height;
848                                 if (IntegralHeight)
849                                         UpdateListBoxBounds ();
850                                 LayoutListBox ();
851                         }
852                 }
853
854                 protected override void OnHandleCreated (EventArgs e)
855                 {
856                         base.OnHandleCreated (e);
857
858                         SuspendLayout ();
859                         Controls.AddImplicit (vscrollbar);
860                         Controls.AddImplicit (hscrollbar);
861                         ResumeLayout ();
862                         LayoutListBox ();
863                 }
864
865                 protected override void OnHandleDestroyed (EventArgs e)
866                 {
867                         base.OnHandleDestroyed (e);
868                 }
869
870                 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
871                 {
872                         if (draw_mode != DrawMode.OwnerDrawVariable)
873                                 return;
874
875                         MeasureItemEventHandler eh = (MeasureItemEventHandler)(Events [MeasureItemEvent]);
876                         if (eh != null)
877                                 eh (this, e);
878                 }
879
880                 protected override void OnParentChanged (EventArgs e)
881                 {
882                         base.OnParentChanged (e);
883                 }
884
885                 protected override void OnResize (EventArgs e)
886                 {
887                         base.OnResize (e);
888                         if (canvas_size.IsEmpty || MultiColumn)
889                                 LayoutListBox ();
890                 }
891
892                 protected override void OnSelectedIndexChanged (EventArgs e)
893                 {
894                         base.OnSelectedIndexChanged (e);
895
896                         EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
897                         if (eh != null)
898                                 eh (this, e);
899                 }
900
901                 protected override void OnSelectedValueChanged (EventArgs e)
902                 {
903                         base.OnSelectedValueChanged (e);
904                 }
905
906                 public override void Refresh ()
907                 {
908                         if (draw_mode == DrawMode.OwnerDrawVariable)
909                                 item_heights.Clear ();
910                         
911                         base.Refresh ();
912                 }
913
914                 protected override void RefreshItem (int index)
915                 {
916                         if (index < 0 || index >= Items.Count)
917                                 throw new ArgumentOutOfRangeException ("Index of out range");
918                                 
919                         if (draw_mode == DrawMode.OwnerDrawVariable)
920                                 item_heights.Remove (Items [index]);
921                 }
922
923                 protected override void SetBoundsCore (int x,  int y, int width, int height, BoundsSpecified specified)
924                 {
925                         if ((specified & BoundsSpecified.Height) == BoundsSpecified.Height)
926                                 requested_height = height;
927
928                         if (IntegralHeight) {
929                                 int border;
930                                 switch (border_style) {
931                                 case BorderStyle.Fixed3D:
932                                         border = ThemeEngine.Current.Border3DSize.Height;
933                                         break;
934                                 case BorderStyle.FixedSingle:
935                                         border = ThemeEngine.Current.BorderSize.Height;
936                                         break;
937                                 case BorderStyle.None:
938                                 default:
939                                         border = 0;
940                                         break;
941                                 }
942                                 height -= (2 * border);
943                                 height -= height % ItemHeight;
944                                 height += (2 * border);
945                         }
946
947                         base.SetBoundsCore (x, y, width, height, specified);
948                         UpdateScrollBars ();
949                 }
950
951                 protected override void SetItemCore (int index,  object value)
952                 {
953                         if (index < 0 || index >= Items.Count)
954                                 return;
955
956                         Items[index] = value;
957                 }
958
959                 protected override void SetItemsCore (IList value)
960                 {
961                         BeginUpdate ();
962                         try {
963                                 Items.Clear ();
964                                 Items.AddRange (value);
965                         } finally {
966                                 EndUpdate ();
967                         }
968                 }
969
970                 public void SetSelected (int index, bool value)
971                 {
972                         if (index < 0 || index >= Items.Count)
973                                 throw new ArgumentOutOfRangeException ("Index of out range");
974
975                         if (SelectionMode == SelectionMode.None)
976                                 throw new InvalidOperationException ();
977
978                         if (value)
979                                 SelectItem (index);
980                         else
981                                 UnSelectItem (index, true);
982                 }
983
984                 protected virtual void Sort ()
985                 {
986                         if (Items.Count == 0)
987                                 return;
988
989                         Items.Sort ();
990                         base.Refresh ();
991                 }
992
993                 public override string ToString ()
994                 {
995                         return base.ToString ();
996                 }
997
998                 protected virtual void WmReflectCommand (ref Message m)
999                 {
1000                 }
1001
1002                 protected override void WndProc (ref Message m)
1003                 {
1004                         base.WndProc (ref m);
1005                 }
1006
1007                 #endregion Public Methods
1008
1009                 #region Private Methods
1010
1011                 private Size canvas_size;
1012
1013                 private void LayoutListBox ()
1014                 {
1015                         if (!IsHandleCreated || suspend_layout)
1016                                 return;
1017
1018                         if (MultiColumn)
1019                                 LayoutMultiColumn ();
1020                         else
1021                                 LayoutSingleColumn ();
1022
1023                         UpdateScrollBars ();
1024                         last_visible_index = LastVisibleItem ();
1025                 }
1026
1027                 private void LayoutSingleColumn ()
1028                 {
1029                         int height, width;
1030
1031                         switch (DrawMode) {
1032                         case DrawMode.OwnerDrawVariable:
1033                                 height = 0;
1034                                 width = HorizontalExtent;
1035                                 for (int i = 0; i < Items.Count; i++) {
1036                                         height += GetItemHeight (i);
1037                                 }
1038                                 break;
1039
1040                         case DrawMode.OwnerDrawFixed:
1041                                 height = Items.Count * ItemHeight;
1042                                 width = HorizontalExtent;
1043                                 break;
1044
1045                         case DrawMode.Normal:
1046                         default:
1047                                 height = Items.Count * ItemHeight;
1048                                 width = 0;
1049                                 for (int i = 0; i < Items.Count; i++) {
1050                                         SizeF sz = DeviceContext.MeasureString (GetItemText (Items[i]), Font);
1051                                         if ((int) sz.Width > width)
1052                                                 width = (int) sz.Width;
1053                                 }
1054                                 break;
1055                         }
1056
1057                         canvas_size = new Size (width, height);
1058                 }
1059
1060                 private void LayoutMultiColumn ()
1061                 {
1062                         int usable_height = ClientRectangle.Height - (ScrollAlwaysVisible ? hscrollbar.Height : 0);
1063                         row_count = usable_height / ItemHeight;
1064                         if (row_count == 0)
1065                                 row_count = 1;
1066                         int cols = (int) Math.Ceiling ((float)Items.Count / (float) row_count);
1067                         Size sz = new Size (cols * ColumnWidthInternal, row_count * ItemHeight);
1068                         if (!ScrollAlwaysVisible && sz.Width > ClientRectangle.Width && row_count > 1) {
1069                                 usable_height = ClientRectangle.Height - hscrollbar.Height;
1070                                 row_count = usable_height / ItemHeight;
1071                                 cols = (int) Math.Ceiling ((float)Items.Count / (float) row_count);
1072                                 sz = new Size (cols * ColumnWidthInternal, row_count * ItemHeight);
1073                         }
1074                         canvas_size = sz;
1075                 }
1076
1077                 internal void Draw (Rectangle clip, Graphics dc)
1078                 {                               
1079                         Theme theme = ThemeEngine.Current;
1080
1081                         if (hscrollbar.Visible && vscrollbar.Visible) {
1082                                 // Paint the dead space in the bottom right corner
1083                                 Rectangle rect = new Rectangle (hscrollbar.Right, vscrollbar.Bottom, vscrollbar.Width, hscrollbar.Height);
1084                                 if (rect.IntersectsWith (clip))
1085                                         dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), rect);
1086                         }
1087
1088                         dc.FillRectangle (theme.ResPool.GetSolidBrush (BackColor), items_area);
1089
1090                         if (Items.Count == 0)
1091                                 return;
1092
1093                         for (int i = top_index; i <= last_visible_index; i++) {
1094                                 Rectangle rect = GetItemDisplayRectangle (i, top_index);
1095
1096                                 if (!clip.IntersectsWith (rect))
1097                                         continue;
1098
1099                                 DrawItemState state = DrawItemState.None;
1100
1101                                 if (SelectedIndices.Contains (i))
1102                                         state |= DrawItemState.Selected;
1103                                         
1104                                 if (has_focus && FocusedItem == i)
1105                                         state |= DrawItemState.Focus;
1106                                         
1107                                 if (MultiColumn == false && hscrollbar != null && hscrollbar.Visible) {
1108                                         rect.X -= hscrollbar.Value;
1109                                         rect.Width += hscrollbar.Value;
1110                                 }
1111
1112                                 OnDrawItem (new DrawItemEventArgs (dc, Font, rect, i, state, ForeColor, BackColor));
1113                         }
1114                 }
1115
1116                 // Converts a GetItemRectangle to a one that we can display
1117                 internal Rectangle GetItemDisplayRectangle (int index, int first_displayble)
1118                 {
1119                         Rectangle item_rect;
1120                         Rectangle first_item_rect = GetItemRectangle (first_displayble);
1121                         item_rect = GetItemRectangle (index);
1122                         item_rect.X -= first_item_rect.X;
1123                         item_rect.Y -= first_item_rect.Y;
1124                         
1125                         return item_rect;
1126                 }
1127
1128                 // Value Changed
1129                 private void HorizontalScrollEvent (object sender, EventArgs e)
1130                 {
1131                         if (multicolumn) {
1132                                 int top_item = top_index;
1133                                 int last_item = last_visible_index;
1134
1135                                 top_index = RowCount * hscrollbar.Value;
1136                                 last_visible_index = LastVisibleItem ();
1137
1138                                 if (top_item != top_index || last_item != last_visible_index)
1139                                         Invalidate (items_area);
1140                         }
1141                         else {
1142                                 int old_offset = hbar_offset;
1143                                 hbar_offset = hscrollbar.Value;
1144
1145                                 if (hbar_offset < 0)
1146                                         hbar_offset = 0;
1147
1148                                 XplatUI.ScrollWindow (Handle, items_area, old_offset - hbar_offset, 0, false);
1149                         }
1150                 }
1151
1152                 // Only returns visible points. The diference of with IndexFromPoint is that the rectangle
1153                 // has screen coordinates
1154                 private int IndexAtClientPoint (int x, int y)
1155                 {       
1156                         if (Items.Count == 0)
1157                                 return -1;
1158                         
1159                         if (x < 0)
1160                                 x = 0;
1161                         else if (x > ClientRectangle.Right)
1162                                 x = ClientRectangle.Right;
1163
1164                         if (y < 0)
1165                                 y = 0;
1166                         else if (y > ClientRectangle.Bottom)
1167                                 y = ClientRectangle.Bottom;
1168
1169                         for (int i = top_index; i <= last_visible_index; i++)
1170                                 if (GetItemDisplayRectangle (i, top_index).Contains (x, y))
1171                                         return i;
1172
1173                         return -1;
1174                 }
1175
1176                 private int LastVisibleItem ()
1177                 {
1178                         Rectangle item_rect;
1179                         int top_y = items_area.Y + items_area.Height;
1180                         int i = 0;
1181
1182                         if (top_index >= Items.Count)
1183                                 return top_index;
1184
1185                         for (i = top_index; i < Items.Count; i++) {
1186
1187                                 item_rect = GetItemDisplayRectangle (i, top_index);
1188                                 if (MultiColumn) {
1189
1190                                         if (item_rect.X > items_area.Width)
1191                                                 return i - 1;
1192                                 }
1193                                 else {                                  
1194                                         if (item_rect.Y + item_rect.Height > top_y) {
1195                                                 return i;
1196                                         }
1197                                 }
1198                         }
1199                         return i - 1;
1200                 }
1201
1202                 private void UpdateTopItem ()
1203                 {
1204                         if (MultiColumn) {                              
1205                                 int col = top_index / RowCount;
1206                                 
1207                                 if (col > hscrollbar.Maximum)
1208                                         hscrollbar.Value = hscrollbar.Maximum;
1209                                 else
1210                                         hscrollbar.Value = col;
1211                         } else {
1212                                 int val = vscrollbar.Value;
1213                                 if (top_index > vscrollbar.Maximum)
1214                                         vscrollbar.Value = vscrollbar.Maximum;
1215                                 else
1216                                         vscrollbar.Value = top_index;
1217                                 Scroll (vscrollbar, vscrollbar.Value - top_index);
1218                                 XplatUI.ScrollWindow (Handle, items_area, 0, ItemHeight * (val - vscrollbar.Value), false);
1219                         }
1220                 }
1221                 
1222                 // Navigates to the indicated item and returns the new item
1223                 private int NavigateItemVisually (ItemNavigation navigation)
1224                 {                       
1225                         int page_size, columns, selected_index = -1;
1226
1227                         if (multicolumn) {
1228                                 columns = items_area.Width / ColumnWidthInternal; 
1229                                 page_size = columns * RowCount;
1230                                 if (page_size == 0) {
1231                                         page_size = RowCount;
1232                                 }
1233                         } else {
1234                                 page_size = items_area.Height / ItemHeight;     
1235                         }
1236
1237                         switch (navigation) {
1238
1239                         case ItemNavigation.PreviousColumn: {
1240                                 if (FocusedItem - RowCount < 0) {
1241                                         return -1;
1242                                 }
1243
1244                                 if (FocusedItem - RowCount < top_index) {
1245                                         top_index = FocusedItem - RowCount;
1246                                         UpdateTopItem ();
1247                                 }
1248                                         
1249                                 selected_index = FocusedItem - RowCount;
1250                                 break;
1251                         }
1252                         
1253                         case ItemNavigation.NextColumn: {
1254                                 if (FocusedItem + RowCount >= Items.Count) {
1255                                         break;
1256                                 }
1257
1258                                 if (FocusedItem + RowCount > last_visible_index) {
1259                                         top_index = FocusedItem;
1260                                         UpdateTopItem ();
1261                                 }
1262                                         
1263                                 selected_index = FocusedItem + RowCount;                                        
1264                                 break;
1265                         }
1266
1267                         case ItemNavigation.First: {
1268                                 top_index = 0;
1269                                 selected_index  = 0;
1270                                 UpdateTopItem ();
1271                                 break;
1272                         }
1273
1274                         case ItemNavigation.Last: {
1275
1276                                 int rows = items_area.Height / ItemHeight;
1277                                 if (Items.Count < rows) {
1278                                         top_index = 0;
1279                                         selected_index  = Items.Count - 1;
1280                                         UpdateTopItem ();
1281                                 } else {
1282                                         top_index = Items.Count - rows;
1283                                         selected_index  = Items.Count - 1;
1284                                         UpdateTopItem ();
1285                                 }
1286                                 break;
1287                         }
1288
1289                         case ItemNavigation.Next: {
1290                                 if (FocusedItem == Items.Count - 1)
1291                                         return -1;
1292
1293                                 int bottom = 0;
1294                                 ArrayList heights = new ArrayList ();
1295                                 if (draw_mode == DrawMode.OwnerDrawVariable) {
1296                                         for (int i = top_index; i <= FocusedItem + 1; i++) {
1297                                                 int h = GetItemHeight (i);
1298                                                 bottom += h;
1299                                                 heights.Add (h);
1300                                         }
1301                                 } else {
1302                                         bottom = ((FocusedItem + 1) - top_index + 1) * ItemHeight;
1303                                 }
1304
1305                                 if (bottom >= items_area.Height) {
1306                                         int overhang = bottom - items_area.Height;
1307
1308                                         int offset = 0;
1309                                         if (draw_mode == DrawMode.OwnerDrawVariable)
1310                                                 while (overhang > 0)
1311                                                         overhang -= (int) heights [offset];
1312                                         else
1313                                                 offset = (int) Math.Ceiling ((float)overhang / (float) ItemHeight);
1314                                         top_index += offset;
1315                                         UpdateTopItem ();                                               
1316                                 }
1317                                 selected_index = FocusedItem + 1;
1318                                 break;
1319                         }
1320
1321                         case ItemNavigation.Previous: {
1322                                 if (FocusedItem > 0) {
1323                                         if (FocusedItem - 1 < top_index) {
1324                                                 top_index--;
1325                                                 UpdateTopItem ();
1326                                         }
1327                                         selected_index = FocusedItem - 1;
1328                                 }                                       
1329                                 break;
1330                         }
1331
1332                         case ItemNavigation.NextPage: {
1333                                 if (Items.Count < page_size) {
1334                                         NavigateItemVisually (ItemNavigation.Last);
1335                                         break;
1336                                 }
1337
1338                                 if (FocusedItem + page_size - 1 >= Items.Count) {
1339                                         top_index = Items.Count - page_size;
1340                                         UpdateTopItem ();
1341                                         selected_index = Items.Count - 1;                                               
1342                                 }
1343                                 else {
1344                                         if (FocusedItem + page_size - 1  > last_visible_index) {
1345                                                 top_index = FocusedItem;
1346                                                 UpdateTopItem ();
1347                                         }
1348                                         
1349                                         selected_index = FocusedItem + page_size - 1;                                           
1350                                 }
1351                                         
1352                                 break;
1353                         }                       
1354
1355                         case ItemNavigation.PreviousPage: {
1356                                         
1357                                 int rows = items_area.Height / ItemHeight;
1358                                 if (FocusedItem - (rows - 1) <= 0) {
1359                                                                                                                                                 
1360                                         top_index = 0;                                  
1361                                         UpdateTopItem ();                                       
1362                                         SelectedIndex = 0;                                      
1363                                 }
1364                                 else { 
1365                                         if (FocusedItem - (rows - 1)  < top_index) {
1366                                                 top_index = FocusedItem - (rows - 1);
1367                                                 UpdateTopItem ();                                               
1368                                         }
1369                                         
1370                                         selected_index = FocusedItem - (rows - 1);
1371                                 }
1372                                         
1373                                 break;
1374                         }               
1375                         default:
1376                                 break;                          
1377                         }
1378                         
1379                         return selected_index;
1380                 }
1381                 
1382                 
1383                 private void OnGotFocus (object sender, EventArgs e)                    
1384                 {                       
1385                         if (FocusedItem != -1)
1386                                 InvalidateItem (FocusedItem);
1387                 }               
1388                 
1389                 private void OnLostFocus (object sender, EventArgs e)                   
1390                 {                       
1391                         if (FocusedItem != -1)
1392                                 InvalidateItem (FocusedItem);
1393                 }               
1394
1395                 private void OnKeyDownLB (object sender, KeyEventArgs e)
1396                 {                                       
1397                         int new_item = -1;
1398                         
1399                         if (Items.Count == 0)
1400                                 return;
1401
1402                         switch (e.KeyCode) {
1403                                 
1404                                 case Keys.ControlKey:
1405                                         ctrl_pressed = true;
1406                                         break;
1407                                         
1408                                 case Keys.ShiftKey:
1409                                         shift_pressed = true;
1410                                         break;
1411                                         
1412                                 case Keys.Home:
1413                                         new_item = NavigateItemVisually (ItemNavigation.First);
1414                                         break;  
1415
1416                                 case Keys.End:
1417                                         new_item = NavigateItemVisually (ItemNavigation.Last);
1418                                         break;  
1419
1420                                 case Keys.Up:
1421                                         new_item = NavigateItemVisually (ItemNavigation.Previous);
1422                                         break;                          
1423         
1424                                 case Keys.Down:                         
1425                                         new_item = NavigateItemVisually (ItemNavigation.Next);
1426                                         break;
1427                                 
1428                                 case Keys.PageUp:
1429                                         new_item = NavigateItemVisually (ItemNavigation.PreviousPage);
1430                                         break;                          
1431         
1432                                 case Keys.PageDown:                             
1433                                         new_item = NavigateItemVisually (ItemNavigation.NextPage);
1434                                         break;
1435
1436                                 case Keys.Right:
1437                                         if (multicolumn == true) {
1438                                                 new_item = NavigateItemVisually (ItemNavigation.NextColumn);
1439                                         }
1440                                         break;                          
1441         
1442                                 case Keys.Left:                 
1443                                         if (multicolumn == true) {      
1444                                                 new_item = NavigateItemVisually (ItemNavigation.PreviousColumn);
1445                                         }
1446                                         break;
1447                                         
1448                                 case Keys.Space:
1449                                         if (selection_mode == SelectionMode.MultiSimple) {
1450                                                 SelectedItemFromNavigation (FocusedItem);
1451                                         }
1452                                         break;
1453                                 
1454
1455                                 default:
1456                                         break;
1457                                 }
1458                                 
1459                                 if (new_item != -1) {
1460                                         FocusedItem = new_item;
1461                                         if (selection_mode != SelectionMode.MultiSimple && selection_mode != SelectionMode.None) {
1462                                                 SelectedItemFromNavigation (new_item);
1463                                         }
1464                                 }
1465                 }
1466                 
1467                 private void OnKeyUpLB (object sender, KeyEventArgs e)                  
1468                 {
1469                         switch (e.KeyCode) {
1470                                 case Keys.ControlKey:
1471                                         ctrl_pressed = false;
1472                                         break;
1473                                 case Keys.ShiftKey:
1474                                         shift_pressed = false;
1475                                         break;
1476                                 default: 
1477                                         break;
1478                         }
1479                 }               
1480
1481                 internal void InvalidateItem (int index)
1482                 {
1483                         Rectangle bounds = GetItemDisplayRectangle (index, top_index);
1484                         if (ClientRectangle.IntersectsWith (bounds))
1485                                 Invalidate (bounds);
1486                 }
1487
1488                 internal virtual void OnItemClick (int index)
1489                 {
1490                         OnSelectedIndexChanged  (EventArgs.Empty);
1491                         OnSelectedValueChanged (EventArgs.Empty);
1492                 }
1493
1494                 int anchor = -1;
1495                 int[] prev_selection;
1496                 bool button_pressed = false;
1497
1498                 private void SelectExtended (int index)
1499                 {
1500                         SuspendLayout ();
1501
1502                         ArrayList new_selection = new ArrayList ();
1503                         int start = anchor < index ? anchor : index;
1504                         int end = anchor > index ? anchor : index;
1505                         for (int i = start; i <= end; i++)
1506                                 new_selection.Add (i);
1507
1508                         if (ctrl_pressed)
1509                                 foreach (int i in prev_selection)
1510                                         if (!selection.Contains (i))
1511                                                 new_selection.Add (i);
1512
1513                         foreach (int i in SelectedIndices)
1514                                 if (!new_selection.Contains (i))
1515                                         UnSelectItem (i, true);
1516
1517                         foreach (int i in new_selection)
1518                                 if (!SelectedIndices.Contains (i))
1519                                         SelectItem (i);
1520                         ResumeLayout ();
1521                 }
1522
1523                 private void OnMouseDownLB (object sender, MouseEventArgs e)
1524                 {
1525                         int index = IndexAtClientPoint (e.X, e.Y);
1526                                                         
1527                         if (index == -1)
1528                                 return;                 
1529
1530                         switch (SelectionMode) {
1531                         case SelectionMode.One:
1532                                 if (SelectedIndex != index) {
1533                                         UnSelectItem (SelectedIndex, true);
1534                                         SelectItem (index);
1535                                 }
1536                                 selected_index = index;
1537                                 break;
1538
1539                         case SelectionMode.MultiSimple:
1540                                 if (SelectedIndices.Contains (index))
1541                                         UnSelectItem (index, true);
1542                                 else
1543                                         SelectItem (index);
1544                                 break;
1545
1546                         case SelectionMode.MultiExtended:
1547                                 shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1548                                 ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1549
1550                                 if (ctrl_pressed) {
1551                                         prev_selection = new int [selection.Count];
1552                                         SelectedIndices.CopyTo (prev_selection, 0);
1553                                 } else
1554                                         ClearSelected ();
1555
1556                                 if (!shift_pressed)
1557                                         anchor = index;
1558
1559                                 SelectExtended (index);
1560                                 break;
1561
1562                         case SelectionMode.None:
1563                         default:
1564                                 return;
1565                         }
1566                                 
1567                         button_pressed = true;
1568                         FocusedItem = index;
1569                 }
1570
1571                 private void OnMouseMoveLB (object sender, MouseEventArgs e)
1572                 {
1573                         if (!button_pressed)
1574                                 return;
1575
1576                         int index = IndexAtClientPoint (e.X, e.Y);
1577
1578                         switch (SelectionMode) {
1579                         case SelectionMode.One:
1580                                 if (index == selected_index)
1581                                         return;
1582
1583                                 UnSelectItem (SelectedIndex, true);
1584                                 SelectItem (index);
1585                                 selected_index = index;
1586                                 break;
1587
1588                         case SelectionMode.MultiSimple:
1589                                 break;
1590
1591                         case SelectionMode.MultiExtended:
1592                                 SelectExtended (index);
1593                                 break;
1594
1595                         case SelectionMode.None:
1596                         default:
1597                                 return;
1598                         }
1599
1600                         FocusedItem = index;
1601                 }
1602
1603                 private void OnMouseUpLB (object sender, MouseEventArgs e)
1604                 {
1605                         if (e.Clicks > 1)
1606                                 OnDoubleClick (EventArgs.Empty);
1607                         else if (e.Clicks == 1)
1608                                 OnClick (EventArgs.Empty);
1609                         
1610                         if (!button_pressed)
1611                                 return;
1612
1613                         int index = IndexAtClientPoint (e.X, e.Y);
1614                         OnItemClick (index);
1615                         button_pressed = ctrl_pressed = shift_pressed = false;
1616                 }
1617
1618                 private void Scroll (ScrollBar scrollbar, int delta)
1619                 {
1620                         if (delta == 0 || !scrollbar.Visible || !scrollbar.Enabled)
1621                                 return;
1622
1623                         int max;
1624                         if (scrollbar == hscrollbar)
1625                                 max = hscrollbar.Maximum - (items_area.Width / ColumnWidthInternal) + 1;
1626                         else
1627                                 max = vscrollbar.Maximum - (items_area.Height / ItemHeight) + 1;
1628
1629                         int val = scrollbar.Value + delta;
1630                         if (val > max)
1631                                 val = max;
1632                         else if (val < scrollbar.Minimum)
1633                                 val = scrollbar.Minimum;
1634                         scrollbar.Value = val;
1635                 }
1636
1637                 private void OnMouseWheelLB (object sender, MouseEventArgs me)
1638                 {
1639                         if (Items.Count == 0)
1640                                 return;
1641
1642                         int lines = me.Delta / 120;
1643
1644                         if (MultiColumn)
1645                                 Scroll (hscrollbar, -SystemInformation.MouseWheelScrollLines * lines);
1646                         else
1647                                 Scroll (vscrollbar, -lines);
1648                 }
1649
1650                 internal override void OnPaintInternal (PaintEventArgs pevent)
1651                 {
1652                         if (suspend_layout)
1653                                 return;
1654
1655                         Draw (pevent.ClipRectangle, pevent.Graphics);
1656                 }
1657
1658                 internal void RepositionScrollBars ()
1659                 {
1660                         if (vscrollbar.is_visible) {
1661                                 vscrollbar.Size = new Size (vscrollbar.Width, items_area.Height);
1662                                 vscrollbar.Location = new Point (items_area.Width, 0);
1663                         }
1664
1665                         if (hscrollbar.is_visible) {
1666                                 hscrollbar.Size = new Size (items_area.Width, hscrollbar.Height);
1667                                 hscrollbar.Location = new Point (0, items_area.Height);
1668                         }
1669                 }
1670
1671                 // Add an item in the Selection array and marks it visually as selected
1672                 private void SelectItem (int index)
1673                 {
1674                         if (index == -1 || SelectedIndices.Contains (index))
1675                                 return;
1676
1677                         selection.Add (Items[index]);
1678                         InvalidateItem (index);
1679                 }               
1680                 
1681                 // An item navigation operation (mouse or keyboard) has caused to select a new item
1682                 internal void SelectedItemFromNavigation (int index)
1683                 {
1684                         switch (SelectionMode) {
1685                                 case SelectionMode.None: // Do nothing
1686                                         break;
1687                                 case SelectionMode.One: {
1688                                         SelectedIndex = index;
1689                                         break;
1690                                 }
1691                                 case SelectionMode.MultiSimple: {
1692                                         if (SelectedIndex == -1) {
1693                                                 SelectedIndex = index;
1694                                         } else {
1695
1696                                                 if (SelectedIndices.Contains (index))
1697                                                         UnSelectItem (index, true);
1698                                                 else {
1699                                                         SelectItem (index);
1700                                                         OnSelectedIndexChanged  (new EventArgs ());
1701                                                         OnSelectedValueChanged (new EventArgs ());
1702                                                 }
1703                                         }
1704                                         break;
1705                                 }
1706                                 
1707                                 case SelectionMode.MultiExtended: {
1708                                         if (SelectedIndex == -1) {
1709                                                 SelectedIndex = index;
1710                                         } else {
1711
1712                                                 if (ctrl_pressed == false && shift_pressed == false) {
1713                                                         ClearSelected ();
1714                                                 }
1715                                                 
1716                                                 if (shift_pressed == true) {
1717                                                         ShiftSelection (index);
1718                                                 } else { // ctrl_pressed or single item
1719                                                         SelectItem (index);
1720                                                 }
1721                                                 
1722                                                 OnSelectedIndexChanged  (new EventArgs ());
1723                                                 OnSelectedValueChanged (new EventArgs ());
1724                                         }
1725                                         break;
1726                                 }                               
1727                                 
1728                                 default:
1729                                         break;
1730                         }                       
1731                 }
1732                 
1733                 private void ShiftSelection (int index)
1734                 {
1735                         int shorter_item = -1, dist = Items.Count + 1, cur_dist;
1736                         
1737                         foreach (int idx in selected_indices) {
1738                                 if (idx > index) {
1739                                         cur_dist = idx - index;
1740                                 }
1741                                 else {
1742                                         cur_dist = index - idx;                                 
1743                                 }
1744                                                 
1745                                 if (cur_dist < dist) {
1746                                         dist = cur_dist;
1747                                         shorter_item = idx;
1748                                 }
1749                         }
1750                         
1751                         if (shorter_item != -1) {
1752                                 int start, end;
1753                                 
1754                                 if (shorter_item > index) {
1755                                         start = index;
1756                                         end = shorter_item;
1757                                 } else {
1758                                         start = shorter_item;
1759                                         end = index;
1760                                 }
1761                                 
1762                                 ClearSelected ();
1763                                 for (int idx = start; idx <= end; idx++) {
1764                                         SelectItem (idx);       
1765                                 }
1766                         }
1767                 }
1768                 
1769                 internal int FocusedItem {
1770                         get { return focused_item; }
1771                         set {                   
1772                                 if (focused_item == value)
1773                                         return;
1774
1775                                 int prev = focused_item;                        
1776                         
1777                                 focused_item = value;
1778                         
1779                                 if (has_focus == false)
1780                                         return;
1781
1782                                 if (prev != -1)
1783                                         InvalidateItem (prev);
1784                         
1785                                 if (value != -1)
1786                                         InvalidateItem (value);
1787                         }
1788                 }
1789
1790                 // Removes an item in the Selection array and marks it visually as unselected
1791                 private void UnSelectItem (int index, bool remove)
1792                 {
1793                         if (index == -1)
1794                                 return;
1795
1796                         if (remove)
1797                                 selection.Remove (Items[index]);
1798
1799                         InvalidateItem (index);
1800                 }
1801
1802                 StringFormat string_format;
1803                 internal StringFormat StringFormat {
1804                         get {
1805                                 if (string_format == null) {
1806                                         string_format = new StringFormat ();
1807                                         if (RightToLeft == RightToLeft.Yes)
1808                                                 string_format.Alignment = StringAlignment.Far;
1809                                         else
1810                                                 string_format.Alignment = StringAlignment.Near;
1811                                         if (use_tabstops)
1812                                                 string_format.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)});
1813                                 }
1814                                 return string_format;
1815                         }
1816
1817                 }
1818
1819                 internal virtual void CollectionChanged ()
1820                 {
1821                         if (sorted) 
1822                                 Sort ();
1823                         
1824                         if (Items.Count == 0) {
1825                                 selected_index = -1;
1826                                 focused_item = -1;
1827                                 top_index = 0;
1828                         }
1829                         
1830                         if (!IsHandleCreated || suspend_layout)
1831                                 return;
1832
1833                         LayoutListBox ();
1834
1835                         base.Refresh ();
1836                 }
1837
1838                 private void UpdateListBoxBounds ()
1839                 {
1840                         if (requested_height == -1)
1841                                 return;
1842
1843                         SetBounds(0, 0, 0, requested_height, BoundsSpecified.Height);
1844                 }
1845
1846                 private void UpdateScrollBars ()
1847                 {
1848                         items_area = ClientRectangle;
1849                         if (UpdateHorizontalScrollBar ()) {
1850                                 items_area.Height -= hscrollbar.Height;
1851                                 if (UpdateVerticalScrollBar ()) {
1852                                         items_area.Width -= vscrollbar.Width;
1853                                         UpdateHorizontalScrollBar ();
1854                                 }
1855                         } else if (UpdateVerticalScrollBar ()) {
1856                                 items_area.Width -= vscrollbar.Width;
1857                                 if (UpdateHorizontalScrollBar ()) {
1858                                         items_area.Height -= hscrollbar.Height;
1859                                         UpdateVerticalScrollBar ();
1860                                 }
1861                         }
1862
1863                         RepositionScrollBars ();
1864                 }
1865
1866                 /* Determines if the horizontal scrollbar has to be displyed */
1867                 private bool UpdateHorizontalScrollBar ()
1868                 {
1869                         bool show = false;
1870                         bool enabled = true;
1871
1872                         if (MultiColumn) {
1873                                 if (canvas_size.Width > items_area.Width) {
1874                                         show = true;
1875                                         hscrollbar.Maximum  = canvas_size.Width / ColumnWidthInternal - 1;
1876                                 } else if (ScrollAlwaysVisible == true) {
1877                                         enabled = false;
1878                                         show = true;
1879                                         hscrollbar.Maximum  = 0;
1880                                 }
1881                         } else if (canvas_size.Width > ClientRectangle.Width && HorizontalScrollbar) {
1882                                 show = true;                                    
1883                                 hscrollbar.Maximum = canvas_size.Width;
1884                                 hscrollbar.LargeChange = items_area.Width;
1885                         }
1886
1887                         hbar_offset = hscrollbar.Value;
1888                         hscrollbar.Enabled = enabled;
1889                         hscrollbar.Visible = show;
1890
1891                         return show;
1892                 }
1893
1894                 /* Determines if the vertical scrollbar has to be displyed */
1895                 private bool UpdateVerticalScrollBar ()
1896                 {
1897                         if (MultiColumn || Items.Count == 0) {
1898                                 vscrollbar.Visible = false;
1899                                 return false;
1900                         }
1901
1902                         bool show = false;
1903                         bool enabled = true;
1904                         if (canvas_size.Height > items_area.Height) {
1905                                 show = true;
1906                                 vscrollbar.Maximum = Items.Count - 1;
1907                                 vscrollbar.LargeChange = items_area.Height / ItemHeight;
1908                         } else if (ScrollAlwaysVisible) {
1909                                 show = true;
1910                                 enabled = false;
1911                                 vscrollbar.Maximum = 0;
1912                         }
1913
1914                         vscrollbar.Enabled = enabled;
1915                         vscrollbar.Visible = show;
1916
1917                         return show;
1918                 }
1919
1920                 // Value Changed
1921                 private void VerticalScrollEvent (object sender, EventArgs e)
1922                 {
1923                         int top_item = top_index;
1924
1925                         top_index = /*row_count + */ vscrollbar.Value;
1926                         last_visible_index = LastVisibleItem ();
1927
1928                         int diff = top_item - top_index;
1929
1930                         XplatUI.ScrollWindow (Handle, items_area, 0, ItemHeight * diff, false);
1931                 }
1932
1933                 #endregion Private Methods
1934
1935                 [ListBindable (false)]
1936                 public class ObjectCollection : IList, ICollection, IEnumerable
1937                 {
1938                         internal class ListObjectComparer : IComparer
1939                         {
1940                                 public int Compare (object a, object b)
1941                                 {
1942                                         string str1 = a.ToString ();
1943                                         string str2 = b.ToString ();                                    
1944                                         return str1.CompareTo (str2);
1945                                 }
1946                         }
1947
1948                         private ListBox owner;
1949                         internal ArrayList object_items = new ArrayList ();
1950
1951                         public ObjectCollection (ListBox owner)
1952                         {
1953                                 this.owner = owner;
1954                         }
1955
1956                         public ObjectCollection (ListBox owner, object[] obj)
1957                         {
1958                                 this.owner = owner;
1959                                 AddRange (obj);
1960                         }
1961
1962                         public ObjectCollection (ListBox owner,  ObjectCollection obj)
1963                         {
1964                                 this.owner = owner;
1965                                 AddRange (obj);
1966                         }
1967
1968                         #region Public Properties
1969                         public int Count {
1970                                 get { return object_items.Count; }
1971                         }
1972
1973                         public bool IsReadOnly {
1974                                 get { return false; }
1975                         }
1976
1977                         [Browsable(false)]
1978                         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1979                         public virtual object this [int index] {
1980                                 get {
1981                                         if (index < 0 || index >= Count)
1982                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1983
1984                                         return object_items[index];
1985                                 }
1986                                 set {
1987                                         if (index < 0 || index >= Count)
1988                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1989                                         if (value == null)
1990                                                 throw new ArgumentNullException ("value");
1991
1992                                         object_items[index] = value;
1993                                         owner.CollectionChanged ();
1994                                 }
1995                         }
1996
1997                         bool ICollection.IsSynchronized {
1998                                 get { return false; }
1999                         }
2000
2001                         object ICollection.SyncRoot {
2002                                 get { return this; }
2003                         }
2004
2005                         bool IList.IsFixedSize {
2006                                 get { return false; }
2007                         }
2008
2009                         #endregion Public Properties
2010                         
2011                         #region Public Methods
2012                         public int Add (object item)
2013                         {
2014                                 int idx;
2015
2016                                 idx = AddItem (item);
2017                                 owner.CollectionChanged ();
2018                                 return idx;
2019                         }
2020
2021                         public void AddRange (object[] items)
2022                         {
2023                                 foreach (object mi in items)
2024                                         AddItem (mi);
2025
2026                                 owner.CollectionChanged ();
2027                         }
2028
2029                         public void AddRange (ObjectCollection col)
2030                         {
2031                                 foreach (object mi in col)
2032                                         AddItem (mi);
2033
2034                                 owner.CollectionChanged ();
2035                         }
2036
2037                         internal void AddRange (IList list)
2038                         {
2039                                 foreach (object mi in list)
2040                                         AddItem (mi);
2041
2042                                 owner.CollectionChanged ();
2043                         }
2044
2045                         public virtual void Clear ()
2046                         {
2047                                 owner.selection.Clear ();
2048                                 object_items.Clear ();
2049                                 owner.CollectionChanged ();
2050                         }
2051                         public bool Contains (object obj)
2052                         {
2053                                 return object_items.Contains (obj);
2054                         }
2055
2056                         public void CopyTo (object[] dest, int arrayIndex)
2057                         {
2058                                 object_items.CopyTo (dest, arrayIndex);
2059                         }
2060
2061                         void ICollection.CopyTo (Array dest, int index)
2062                         {
2063                                 object_items.CopyTo (dest, index);
2064                         }
2065
2066                         public IEnumerator GetEnumerator ()
2067                         {
2068                                 return object_items.GetEnumerator ();
2069                         }
2070
2071                         int IList.Add (object item)
2072                         {
2073                                 return Add (item);
2074                         }
2075
2076                         public int IndexOf (object value)
2077                         {
2078                                 return object_items.IndexOf (value);
2079                         }
2080
2081                         public void Insert (int index,  object item)
2082                         {
2083                                 if (index < 0 || index > Count)
2084                                         throw new ArgumentOutOfRangeException ("Index of out range");
2085                                         
2086                                 owner.BeginUpdate ();
2087                                 object_items.Insert (index, item);
2088                                 owner.CollectionChanged ();
2089                                 owner.EndUpdate ();
2090                         }
2091
2092                         public void Remove (object value)
2093                         {                               
2094                                 RemoveAt (IndexOf (value));                             
2095                         }
2096
2097                         public void RemoveAt (int index)
2098                         {
2099                                 if (index < 0 || index >= Count)
2100                                         throw new ArgumentOutOfRangeException ("Index of out range");
2101
2102                                 owner.selection.Remove (object_items [index]);
2103                                 object_items.RemoveAt (index);
2104                                 owner.CollectionChanged ();
2105                         }
2106                         #endregion Public Methods
2107
2108                         #region Private Methods
2109                         internal int AddItem (object item)
2110                         {
2111                                 if (item == null)
2112                                         throw new ArgumentNullException ("item");
2113
2114                                 int cnt = object_items.Count;
2115                                 object_items.Add (item);
2116                                 return cnt;
2117                         }
2118
2119                         internal void Sort ()
2120                         {
2121                                 object_items.Sort (new ListObjectComparer ());
2122                         }
2123
2124                         #endregion Private Methods
2125                 }
2126
2127                 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2128                 {
2129                         private ListBox owner;
2130
2131                         public SelectedIndexCollection (ListBox owner)
2132                         {
2133                                 this.owner = owner;
2134                         }
2135
2136                         #region Public Properties
2137                         [Browsable (false)]
2138                         public int Count {
2139                                 get { return owner.selection.Count; }
2140                         }
2141
2142                         public bool IsReadOnly {
2143                                 get { return true; }
2144                         }
2145
2146                         public int this [int index] {
2147                                 get {
2148                                         if (index < 0 || index >= Count)
2149                                                 throw new ArgumentOutOfRangeException ("Index of out range");
2150
2151                                         return owner.Items.IndexOf (owner.selection [index]);
2152                                 }
2153                         }
2154
2155                         bool ICollection.IsSynchronized {
2156                                 get { return true; }
2157                         }
2158
2159                         bool IList.IsFixedSize{
2160                                 get { return true; }
2161                         }
2162
2163                         object ICollection.SyncRoot {
2164                                 get { return this; }
2165                         }
2166
2167                         #endregion Public Properties
2168
2169                         #region Public Methods
2170                         public bool Contains (int selectedIndex)
2171                         {
2172                                 foreach (object o in owner.selection)
2173                                         if (owner.Items.IndexOf (o) == selectedIndex)
2174                                                 return true;
2175                                 return false;
2176                         }
2177
2178                         public void CopyTo (Array dest, int index)
2179                         {
2180                                 foreach (object o in owner.selection)
2181                                         dest.SetValue(owner.Items.IndexOf (o), index++);
2182                         }
2183
2184                         public IEnumerator GetEnumerator ()
2185                         {
2186                                 //FIXME: write an enumerator that uses owner.selection.GetEnumerator
2187                                 //  so that invalidation is write on selection changes
2188                                 ArrayList indices = new ArrayList ();
2189                                 foreach (object o in owner.selection)
2190                                         indices.Add (owner.Items.IndexOf (o));
2191                                 return indices.GetEnumerator ();
2192                         }
2193
2194                         int IList.Add (object obj)
2195                         {
2196                                 throw new NotSupportedException ();
2197                         }
2198
2199                         void IList.Clear ()
2200                         {
2201                                 throw new NotSupportedException ();
2202                         }
2203
2204                         bool IList.Contains (object selectedIndex)
2205                         {
2206                                 return Contains ((int)selectedIndex);
2207                         }
2208
2209                         int IList.IndexOf (object selectedIndex)
2210                         {
2211                                 return IndexOf ((int) selectedIndex);
2212                         }
2213
2214                         void IList.Insert (int index, object value)
2215                         {
2216                                 throw new NotSupportedException ();
2217                         }
2218
2219                         void IList.Remove (object value)
2220                         {
2221                                 throw new NotSupportedException ();
2222                         }
2223
2224                         void IList.RemoveAt (int index)
2225                         {
2226                                 throw new NotSupportedException ();
2227                         }
2228
2229                         object IList.this[int index]{
2230                                 get {return owner.Items.IndexOf (owner.selection [index]); }
2231                                 set {throw new NotImplementedException (); }
2232                         }
2233
2234                         public int IndexOf (int selectedIndex)
2235                         {
2236                                 for (int i = 0; i < owner.selection.Count; i++)
2237                                         if (owner.Items.IndexOf (owner.selection [i]) == selectedIndex)
2238                                                 return i;
2239                                 return -1;
2240                         }
2241                         #endregion Public Methods
2242                 }
2243
2244                 public class SelectedObjectCollection : IList, ICollection, IEnumerable
2245                 {
2246                         private ListBox owner;
2247
2248                         public SelectedObjectCollection (ListBox owner)
2249                         {
2250                                 this.owner = owner;
2251                         }
2252
2253                         #region Public Properties
2254                         public int Count {
2255                                 get { return owner.selection.Count; }
2256                         }
2257
2258                         public bool IsReadOnly {
2259                                 get { return true; }
2260                         }
2261
2262                         [Browsable(false)]
2263                         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
2264                         public object this [int index] {
2265                                 get {
2266                                         if (index < 0 || index >= Count)
2267                                                 throw new ArgumentOutOfRangeException ("Index of out range");
2268
2269                                         return owner.selection [index];
2270                                 }
2271                                 set {throw new NotSupportedException ();}
2272                         }
2273
2274                         bool ICollection.IsSynchronized {
2275                                 get { return true; }
2276                         }
2277
2278                         object ICollection.SyncRoot {
2279                                 get { return this; }
2280                         }
2281
2282                         bool IList.IsFixedSize {
2283                                 get { return true; }
2284                         }
2285
2286                         #endregion Public Properties
2287
2288                         #region Public Methods
2289                         public bool Contains (object selectedObject)
2290                         {
2291                                 return owner.selection.Contains (selectedObject);
2292                         }
2293
2294                         public void CopyTo (Array dest, int index)
2295                         {
2296                                 owner.selection.CopyTo (dest, index);
2297                         }
2298
2299                         int IList.Add (object value)
2300                         {
2301                                 throw new NotSupportedException ();
2302                         }
2303
2304                         void IList.Clear ()
2305                         {
2306                                 throw new NotSupportedException ();
2307                         }
2308
2309                         void IList.Insert (int index, object value)
2310                         {
2311                                 throw new NotSupportedException ();
2312                         }
2313
2314                         void IList.Remove (object value)
2315                         {
2316                                 throw new NotSupportedException ();
2317                         }
2318
2319                         void IList.RemoveAt (int index)
2320                         {
2321                                 throw new NotSupportedException ();
2322                         }
2323         
2324                         public int IndexOf (object item)
2325                         {
2326                                 return owner.selection.IndexOf (item);
2327                         }
2328
2329                         public IEnumerator GetEnumerator ()
2330                         {
2331                                 return owner.selection.GetEnumerator ();
2332                         }
2333
2334                         #endregion Public Methods
2335                 }
2336
2337         }
2338 }
2339