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