* X11Keyboard.cs: Detect and use the num lock mask.
[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 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //
25 // TODO:
26 //      - Keyboard navigation
27 //      - Horizontal item scroll
28 //      - Performance testing
29 //      
30 //
31
32 // NOT COMPLETE
33
34 using System;
35 using System.Drawing;
36 using System.Collections;
37 using System.ComponentModel;
38 using System.Reflection;
39
40 namespace System.Windows.Forms
41 {
42
43         public class ListBox : ListControl
44         {
45                 internal class ListBoxInfo
46                 {
47                         internal int item_height;               /* Item's height */
48                         internal int top_item;                  /* First item that we show the in the current page */
49                         internal int last_item;                 /* Last visible item */
50                         internal int page_size;                 /* Number of listbox items per page. In MultiColumn listbox indicates items per column */
51                         internal Rectangle textdrawing_rect;    /* Displayable Client Rectangle minus the scrollbars and with IntegralHeight calculated*/
52                         internal bool show_verticalsb;          /* Is Vertical scrollbar show it? */
53                         internal bool show_horizontalsb;        /* Is Horizontal scrollbar show it? */
54                         internal Rectangle client_rect;         /* Client Rectangle. Usually = ClientRectangle except when IntegralHeight has been applied*/
55                         internal int max_itemwidth;             /* Maxium item width within the listbox */
56
57                         public ListBoxInfo ()
58                         {
59                                 last_item = 0;
60                                 item_height = 0;
61                                 top_item = 0;
62                                 page_size = 0;
63                                 max_itemwidth = 0;
64                                 show_verticalsb = false;
65                                 show_horizontalsb = false;
66                         }
67                 }
68
69                 internal class ListBoxItem
70                 {
71                         internal int Index;
72                         internal bool Selected;
73
74                         public ListBoxItem (int index)
75                         {
76                                 Index = index;
77                                 Selected = false;
78                         }
79                 }
80
81                 private BorderStyle border_style;
82                 private int column_width;
83                 private DrawMode draw_mode;
84                 private int horizontal_extent;
85                 private bool horizontal_scrollbar;
86                 private bool integral_height;
87                 private ObjectCollection items;
88                 private bool multicolumn;
89                 private bool scroll_always_visible;
90                 private int selected_index;
91                 private SelectedIndexCollection selected_indices;
92                 private object selected_item;
93                 private SelectedObjectCollection selected_items;
94                 private SelectionMode selection_mode;
95                 private bool sorted;
96                 private bool use_tabstops;
97                 private int preferred_height;
98                 private int top_index;
99                 private StringFormat string_format;
100                 private int column_width_internal;
101                 private ListBoxInfo listbox_info;
102                 private VScrollBar vscrollbar_ctrl;
103                 private HScrollBar hscrollbar_ctrl;
104                 private bool suspend_ctrlupdate;
105
106                 public ListBox ()
107                 {
108                         border_style = BorderStyle.Fixed3D;                     \r
109                         draw_mode = DrawMode.Normal;\r
110                         horizontal_extent = 0;\r
111                         horizontal_scrollbar = false;\r
112                         integral_height = true;\r
113                         multicolumn = false;\r
114                         preferred_height = 7;\r
115                         scroll_always_visible = false;\r
116                         selected_index = -1;\r
117                         selected_item = null;\r
118                         selection_mode = SelectionMode.One;\r
119                         sorted = false;\r
120                         top_index = 0;\r
121                         use_tabstops = true;
122                         BackColor = ThemeEngine.Current.ColorWindow;
123                         ColumnWidth = 0;
124                         suspend_ctrlupdate = false;
125
126                         items = new ObjectCollection (this);
127                         selected_indices = new SelectedIndexCollection (this);
128                         selected_items = new SelectedObjectCollection (this);
129                         listbox_info = new ListBoxInfo ();
130                         string_format = new StringFormat ();
131                         listbox_info.item_height = FontHeight;
132
133                         /* Vertical scrollbar */
134                         vscrollbar_ctrl = new VScrollBar ();
135                         vscrollbar_ctrl.Minimum = 0;
136                         vscrollbar_ctrl.SmallChange = 1;
137                         vscrollbar_ctrl.LargeChange = 1;
138                         vscrollbar_ctrl.Maximum = 0;
139                         vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
140                         vscrollbar_ctrl.Visible = false;
141
142                         /* Horizontal scrollbar */
143                         hscrollbar_ctrl = new HScrollBar ();
144                         hscrollbar_ctrl.Minimum = 0;
145                         hscrollbar_ctrl.SmallChange = 1;
146                         hscrollbar_ctrl.LargeChange = 1;
147                         hscrollbar_ctrl.Maximum = 0;
148                         hscrollbar_ctrl.Visible = false;
149                         hscrollbar_ctrl.ValueChanged += new EventHandler (HorizontalScrollEvent);
150
151                         /* Events */
152                         MouseDown += new MouseEventHandler (OnMouseDownLB);
153
154                         UpdateFormatString ();
155                 }
156
157                 #region Events
158                 public new event EventHandler BackgroundImageChanged;
159                 public new event EventHandler Click;
160                 public event DrawItemEventHandler DrawItem;
161                 public event MeasureItemEventHandler MeasureItem;
162                 public new event PaintEventHandler Paint;
163                 public event EventHandler SelectedIndexChanged;
164                 public new event EventHandler TextChanged;
165                 #endregion // Events
166
167                 #region Public Properties
168                 public override Color BackColor {
169                         get { return base.BackColor; }
170                         set {
171                                 if (base.BackColor == value)
172                                         return;
173
174                                 base.BackColor = value;
175                                 Refresh ();
176                         }
177                 }
178
179                 public override Image BackgroundImage {
180                         get { return base.BackgroundImage; }
181                         set {
182                                 if (base.BackgroundImage == value)
183                                         return;
184
185                                 base.BackgroundImage = value;
186
187                                 if (BackgroundImageChanged != null)
188                                         BackgroundImageChanged (this, EventArgs.Empty);
189
190                                 Refresh ();
191                         }
192                 }
193
194                 public BorderStyle BorderStyle {
195                         get { return border_style; }
196
197                         set {
198                                 if (!Enum.IsDefined (typeof (BorderStyle), value))
199                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for BorderStyle", value));
200
201                                 if (border_style == value)
202                                         return;
203
204                                 border_style = value;
205                                 Refresh ();
206                         }
207                 }
208
209                 public int ColumnWidth {
210                         get { return column_width; }
211                         set {
212                                 if (column_width < 0)
213                                         throw new ArgumentException ("A value less than zero is assigned to the property.");
214
215                                 column_width = value;
216
217                                 if (value == 0)
218                                         ColumnWidthInternal = 120;
219                                 else
220                                         ColumnWidthInternal = value;
221
222                                 Refresh ();
223                         }
224                 }
225
226                 protected override CreateParams CreateParams {
227                         get { return base.CreateParams;}
228                 }
229
230                 protected override Size DefaultSize {
231                         get { return new Size (120, 96); }
232                 }
233
234                 public virtual DrawMode DrawMode {
235                         get { return draw_mode; }
236
237                         set {
238                                 if (!Enum.IsDefined (typeof (DrawMode), value))
239                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
240
241                                 if (draw_mode == value)
242                                         return;
243
244                                 draw_mode = value;
245                                 Refresh ();
246                         }
247                 }
248
249                 public override Color ForeColor {
250                         get { return base.ForeColor; }
251                         set {
252
253                                 if (base.ForeColor == value)
254                                         return;
255
256                                 base.ForeColor = value;
257                                 Refresh ();
258                         }
259                 }
260
261                 public int HorizontalExtent {
262                         get { return horizontal_extent; }
263                         set {
264                                 if (horizontal_extent == value)
265                                         return;
266
267                                 horizontal_extent = value;
268                                 Refresh ();
269                         }
270                 }
271
272                 public bool HorizontalScrollbar {
273                         get { return horizontal_scrollbar; }
274                         set {
275                                 if (horizontal_scrollbar == value)
276                                         return;
277
278                                 horizontal_scrollbar = value;
279                                 UpdateShowHorizontalScrollBar ();
280                                 Refresh ();
281                         }
282                 }
283
284                 public bool IntegralHeight {
285                         get { return integral_height; }
286                         set {
287                                 if (integral_height == value)
288                                         return;
289
290                                 integral_height = value;
291                                 CalcClientArea ();
292                         }
293                 }
294
295                 public virtual int ItemHeight {
296                         get { return listbox_info.item_height; }
297                         set {
298                                 if (value > 255)
299                                         throw new ArgumentOutOfRangeException ("The ItemHeight property was set beyond 255 pixels");
300
301                                 listbox_info.item_height = value;
302                                 CalcClientArea ();
303                         }
304                 }
305
306                 public ObjectCollection Items {
307                         get { return items; }
308                 }
309
310                 public bool MultiColumn {
311                         get { return multicolumn; }
312                         set {
313                                 if (multicolumn == value)
314                                         return;
315
316                                 if (value == true && DrawMode == DrawMode.OwnerDrawVariable)
317                                         throw new ArgumentException ("A multicolumn ListBox cannot have a variable-sized height.");
318
319                                 multicolumn = value;
320                                 UpdateShowVerticalScrollBar (); /* the needs for scrollbars may change */
321                                 UpdateShowHorizontalScrollBar ();
322                                 Refresh ();
323                         }
324                 }
325
326                 public int PreferredHeight {
327                         get { return preferred_height;}
328                 }
329
330                 public override RightToLeft RightToLeft {
331                         get { return base.RightToLeft; }
332                         set {
333                                 if (base.RightToLeft == value)
334                                         return;
335
336                                 base.RightToLeft = value;
337                                 UpdateFormatString ();
338                                 Refresh ();
339                         }
340                 }
341
342                 // Only afects the Vertical ScrollBar
343                 public bool ScrollAlwaysVisible {
344                         get { return scroll_always_visible; }
345                         set {
346                                 if (scroll_always_visible == value)
347                                         return;
348
349                                 scroll_always_visible = value;
350                                 UpdateShowVerticalScrollBar ();
351                                 UpdateShowHorizontalScrollBar ();
352                         }
353                 }
354
355                 public override int SelectedIndex {
356                         get { return selected_index;}
357                         set {
358                                 if (value < -1 || value >= Items.Count)
359                                         throw new ArgumentOutOfRangeException ("Index of out range");
360
361                                 if (SelectionMode == SelectionMode.None)
362                                         throw new ArgumentException ("cannot call this method if SelectionMode is SelectionMode.None");
363
364                                 if (selected_index == value)
365                                         return;
366
367                                 if (SelectionMode == SelectionMode.One)
368                                         UnSelectItem (selected_index, true);
369
370                                 SelectItem (value);
371                                 selected_index = value;
372                                 OnSelectedIndexChanged  (new EventArgs ());
373                         }
374                 }
375
376                 public SelectedIndexCollection SelectedIndices {
377                         get { return selected_indices; }
378                 }
379
380                 public object SelectedItem {
381                         get {
382                                 if (SelectedItems.Count > 0)
383                                         return SelectedItems[0];
384                                 else
385                                         return null;
386                         }
387                         set {
388                                 if (selected_item == value)
389                                         return;
390
391                                 int index = Items.IndexOf (value);
392
393                                 if (index == -1)
394                                         return;
395
396                                 SelectedIndex = index;
397                         }
398                 }
399
400                 public SelectedObjectCollection SelectedItems {
401                         get {return selected_items;}
402                 }
403
404                 public virtual SelectionMode SelectionMode {
405                         get { return selection_mode; }
406                         set {
407                                 if (!Enum.IsDefined (typeof (SelectionMode), value))
408                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for SelectionMode", value));
409
410                                 if (selection_mode == value)
411                                         return;
412
413                                 selection_mode = value;
414                                 Refresh ();
415                         }
416                 }
417
418                 public bool Sorted {
419                         get { return sorted; }
420
421                         set {
422                                 if (sorted == value)
423                                         return;
424
425                                 sorted = value;
426                                 Sort ();
427                         }
428                 }
429
430                 public override string Text {
431                         get {
432                                 if (SelectionMode != SelectionMode.None && SelectedIndex != -1)
433                                         return Items[SelectedIndex].ToString ();
434
435                                 return base.Text;
436                         }
437                         set {
438
439                                 base.Text = value;
440
441                                 if (SelectionMode == SelectionMode.None)
442                                         return;
443
444                                 int index;
445
446                                 index = FindStringExact (value);
447
448                                 if (index == -1)
449                                         return;
450
451                                 SelectedIndex = index;
452                         }
453                 }
454
455                 public int TopIndex {
456                         get { return top_index;}
457                         set {                           
458                                 if (value == top_index)
459                                         return;
460                                         
461                                 if (value < 0 || value >= Items.Count)
462                                         return;                         
463
464                                 value = top_index;
465                                 Refresh ();
466                         }
467                 }
468
469                 public bool UseTabStops {
470                         get { return use_tabstops; }
471
472                         set {
473                                 if (use_tabstops == value)
474                                         return;
475
476                                 use_tabstops = value;
477                                 UpdateFormatString ();
478                                 Refresh ();
479                         }
480                 }
481
482                 #endregion Public Properties
483
484                 #region Private Properties
485
486                 internal ListBoxInfo LBoxInfo {
487                         get { return listbox_info; }
488                 }
489
490                 private int ColumnWidthInternal {
491                         get { return column_width_internal; }
492                         set { column_width_internal = value; }
493                 }
494
495                 #endregion Private Properties
496
497                 #region Public Methods
498                 protected virtual void AddItemsCore (object[] value)
499                 {
500                         items.AddRange (value);
501                 }
502
503                 public void BeginUpdate ()
504                 {
505                         suspend_ctrlupdate = true;
506                 }
507
508                 public void ClearSelected ()
509                 {
510                         foreach (int i in selected_indices) {
511                                 UnSelectItem (i, false);
512                         }
513
514                         selected_indices.ClearIndices ();
515                         selected_items.ClearObjects ();
516                 }
517
518                 protected virtual ObjectCollection CreateItemCollection ()
519                 {
520                         return new ObjectCollection (this);
521                 }
522
523                 public void EndUpdate ()
524                 {
525                         suspend_ctrlupdate = false;
526                         UpdateItemInfo (false, -1, -1);
527                         Refresh ();
528                 }
529
530                 public int FindString (String s)
531                 {
532                         return FindString (s, 0);
533                 }
534
535                 public int FindString (string s,  int startIndex)
536                 {
537                         for (int i = startIndex; i < Items.Count; i++) {
538                                 if ((Items[i].ToString ()).StartsWith (s))
539                                         return i;
540                         }
541
542                         return -1;
543                 }
544
545                 public int FindStringExact (string s)
546                 {
547                         return FindStringExact (s, 0);
548                 }
549
550                 public int FindStringExact (string s,  int startIndex)
551                 {
552                         for (int i = startIndex; i < Items.Count; i++) {
553                                 if ((Items[i].ToString ()).Equals (s))
554                                         return i;
555                         }
556
557                         return -1;
558                 }
559
560                 public int GetItemHeight (int index)
561                 {
562                         if (index < 0 || index >= Items.Count)
563                                 throw new ArgumentOutOfRangeException ("Index of out range");
564
565                         return ItemHeight;
566                 }
567
568                 public Rectangle GetItemRectangle (int index)
569                 {
570                         if (index < 0 || index >= Items.Count)
571                                 throw new  ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
572
573                         Rectangle rect = new Rectangle ();
574
575                         if (MultiColumn == false) {
576
577                                 rect.X = 0;
578                                 rect.Y = ItemHeight * index;
579                                 rect.Height = ItemHeight;
580                                 rect.Width = listbox_info.textdrawing_rect.Width;
581                         }
582                         else {
583                                 int which_page = index / listbox_info.page_size;
584
585                                 rect.X = which_page * ColumnWidthInternal;
586                                 rect.Y = (index % listbox_info.page_size) * ItemHeight;
587                                 rect.Height = ItemHeight;
588                                 rect.Width = ColumnWidthInternal;
589                         }
590
591                         return rect;
592                 }
593
594                 public bool GetSelected (int index)
595                 {
596                         if (index < 0 || index >= Items.Count)
597                                 throw new ArgumentOutOfRangeException ("Index of out range");
598
599                         return (Items.GetListBoxItem (index)).Selected;
600                 }
601
602                 public int IndexFromPoint (Point p)
603                 {
604                         return IndexFromPoint (p.X, p.Y);
605                 }
606
607                 // Only returns visible points
608                 public int IndexFromPoint (int x, int y)
609                 {
610                         for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
611                                 if (GetItemRectangle (i).Contains (x,y) == true)
612                                         return i;
613                         }
614
615                         return -1;
616                 }
617
618                 protected override void OnChangeUICues (UICuesEventArgs e)
619                 {
620                         base.OnChangeUICues (e);
621                 }
622
623                 protected override void OnDataSourceChanged (EventArgs e)
624                 {
625                         base.OnDataSourceChanged (e);
626                 }
627
628                 protected override void OnDisplayMemberChanged (EventArgs e)
629                 {
630                         base.OnDisplayMemberChanged (e);
631                 }
632
633                 protected virtual void OnDrawItem (DrawItemEventArgs e)
634                 {
635                         if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable))
636                                 DrawItem (this, e);
637
638                         if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
639                                 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
640                                         (ThemeEngine.Current.ColorHilight), e.Bounds);
641
642                                 e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
643                                         ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHilightText),
644                                         e.Bounds, string_format);
645                         }
646                         else {
647                                 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
648                                         (e.BackColor), e.Bounds);
649
650                                 e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
651                                         ThemeEngine.Current.ResPool.GetSolidBrush (e.ForeColor),
652                                         e.Bounds, string_format);
653                         }
654                 }
655
656                 protected override void OnFontChanged (EventArgs e)
657                 {
658                         base.OnFontChanged (e);
659
660                         UpdateShowHorizontalScrollBar ();
661                         UpdateShowVerticalScrollBar ();
662                         RellocateScrollBars ();
663                         CalcClientArea ();
664                         UpdateItemInfo (false, -1, -1);
665                 }
666
667                 protected override void OnHandleCreated (EventArgs e)
668                 {
669                         base.OnHandleCreated (e);
670
671                         UpdateInternalClientRect (ClientRectangle);
672                         Controls.Add (vscrollbar_ctrl);
673                         Controls.Add (hscrollbar_ctrl);
674                         Sort ();
675                 }
676
677                 protected override void OnHandleDestroyed (EventArgs e)
678                 {
679                         base.OnHandleDestroyed (e);
680                 }
681
682                 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
683                 {
684
685                 }
686
687                 protected override void OnParentChanged (EventArgs e)
688                 {
689                         base.OnParentChanged (e);
690                 }
691
692                 protected override void OnResize (EventArgs e)
693                 {
694                         base.OnResize (e);
695                         UpdateInternalClientRect (ClientRectangle);
696                 }
697
698                 protected override void OnSelectedIndexChanged (EventArgs e)
699                 {
700                         base.OnSelectedIndexChanged (e);
701
702                         if (SelectedIndexChanged != null)
703                                 SelectedIndexChanged (this, e);
704                 }
705
706                 protected override void OnSelectedValueChanged (EventArgs e)
707                 {
708                         base.OnSelectedValueChanged (e);
709                 }
710
711                 public override void Refresh ()
712                 {
713                         base.Refresh ();
714                 }
715
716                 protected override void RefreshItem (int index)
717                 {
718                                                 
719                 }
720
721                 protected override void SetBoundsCore (int x,  int y, int width, int height, BoundsSpecified specified)
722                 {
723                         base.SetBoundsCore (x, y, width, height, specified);
724                 }
725
726                 protected override void SetItemCore (int index,  object value)
727                 {
728                         if (index < 0 || index >= Items.Count) 
729                                 return;
730                                 
731                         Items[index] = value;
732                 }
733
734                 protected override void SetItemsCore (IList value)
735                 {                       
736                         
737                 }
738
739                 public void SetSelected (int index, bool value)
740                 {
741                         if (index < 0 || index >= Items.Count)
742                                 throw new ArgumentOutOfRangeException ("Index of out range");
743
744                         if (SelectionMode == SelectionMode.None)
745                                 throw new InvalidOperationException ();
746
747                         if (value)
748                                 SelectItem (index);
749                         else
750                                 UnSelectItem (index, true);
751                 }
752
753                 protected virtual void Sort ()
754                 {
755                         if (Items.Count == 0)
756                                 return;
757
758                         Items.Sort ();
759                         Refresh ();
760                 }
761
762                 public override string ToString ()
763                 {
764                         return base.ToString () + ", Items Count: " + Items.Count;
765                 }
766
767                 protected virtual void WmReflectCommand (ref Message m)
768                 {
769
770                 }
771
772                 protected override void WndProc (ref Message m)
773                 {
774                         switch ((Msg) m.Msg) {
775
776                         case Msg.WM_PAINT: {
777                                 PaintEventArgs  paint_event;
778                                 paint_event = XplatUI.PaintEventStart (Handle);
779                                 OnPaintLB (paint_event);
780                                 XplatUI.PaintEventEnd (Handle);
781                                 return;
782                         }
783
784                         case Msg.WM_ERASEBKGND:
785                                 m.Result = (IntPtr) 1;
786                                 return;
787
788                         default:
789                                 break;
790                         }
791
792                         base.WndProc (ref m);
793                 }
794
795                 #endregion Public Methods
796
797                 #region Private Methods
798
799                 internal void CalcClientArea ()
800                 {
801                         listbox_info.textdrawing_rect = listbox_info.client_rect;
802                         listbox_info.textdrawing_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
803                         listbox_info.textdrawing_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
804                         listbox_info.textdrawing_rect.Height -= ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle);
805                         listbox_info.textdrawing_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
806
807                         if (listbox_info.show_verticalsb)
808                                 listbox_info.textdrawing_rect.Width -= vscrollbar_ctrl.Width;
809
810                         if (listbox_info.show_horizontalsb)
811                                 listbox_info.textdrawing_rect.Height -= hscrollbar_ctrl.Height;
812
813                         //listbox_info.page_size = listbox_info.client_rect.Height / listbox_info.item_height;
814                         listbox_info.page_size = listbox_info.textdrawing_rect.Height / listbox_info.item_height;
815
816                         /* Adjust size to visible the maxim number of displayable items */
817                         if (IntegralHeight == true) {
818
819                                 // From MS Docs: The integral height is based on the height of the ListBox, rather than
820                                 // the client area height. As a result, when the IntegralHeight property is set true,
821                                 // items can still be partially shown if scroll bars are displayed.
822
823                                 int remaining =  (listbox_info.client_rect.Height -
824                                         ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle) -
825                                         ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle)) %
826                                         listbox_info.item_height;
827
828                                 if (remaining > 0) {
829                                         listbox_info.client_rect.Height -= remaining;
830                                         CalcClientArea ();
831                                         RellocateScrollBars ();
832                                         Refresh ();
833                                 }
834                         }
835
836                         LBoxInfo.last_item = LastVisibleItem ();
837                 }
838
839                 internal void Draw (Rectangle clip)
840                 {
841                         if (LBoxInfo.textdrawing_rect.Contains (clip) == false) {
842                                 // IntegralHeight has effect, we also have to paint the unused area
843                                 if (ClientRectangle.Height > listbox_info.client_rect.Height) {
844                                         Region area = new Region (ClientRectangle);
845                                         area.Exclude (listbox_info.client_rect);
846
847                                         DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
848                                                 area.GetBounds (DeviceContext));
849                                 }
850
851                                 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), LBoxInfo.textdrawing_rect);
852                                 ThemeEngine.Current.DrawListBoxDecorations (DeviceContext, this);
853                         }
854
855                         if (Items.Count > 0) {
856                                 Rectangle item_rect;
857                                 DrawItemState state = DrawItemState.None;
858
859                                 for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
860                                         item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
861
862                                         if (clip.IntersectsWith (item_rect) == false)
863                                                 continue;
864
865                                         /* Draw item */
866                                         state = DrawItemState.None;
867
868                                         if ((Items.GetListBoxItem (i)).Selected) {
869                                                 state |= DrawItemState.Selected;
870                                         }
871
872                                         OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, item_rect,
873                                                 i, state, ForeColor, BackColor));
874                                 }
875                         }
876                 }
877
878                 // Converts a GetItemRectangle to a one that we can display
879                 private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
880                 {
881                         Rectangle item_rect;
882                         Rectangle first_item_rect = GetItemRectangle (first_displayble);
883                         item_rect = GetItemRectangle (index);
884                         item_rect.X -= first_item_rect.X;
885                         item_rect.Y -= first_item_rect.Y;
886
887                         item_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
888                         item_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
889                         item_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
890
891                         return item_rect;
892                 }
893
894                 // Value Changed
895                 private void HorizontalScrollEvent (object sender, EventArgs e)
896                 {
897                         LBoxInfo.top_item = listbox_info.page_size * hscrollbar_ctrl.Value;
898                         LBoxInfo.last_item = LastVisibleItem ();
899                         Refresh ();
900                 }
901
902                 private int LastVisibleItem ()
903                 {
904                         Rectangle item_rect;
905                         int top_y = LBoxInfo.textdrawing_rect.Y + LBoxInfo.textdrawing_rect.Height;
906                         int i = 0;
907
908                         for (i = LBoxInfo.top_item; i < Items.Count; i++) {
909
910                                 item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
911
912                                 if (MultiColumn) {
913
914                                         if (item_rect.X > LBoxInfo.textdrawing_rect.Width)
915                                                 return i - 1;
916                                 }
917                                 else {
918                                         if (IntegralHeight) {
919                                                 if (item_rect.Y + item_rect.Height > top_y)
920                                                         return i - 1;
921                                         }
922                                         else {
923                                                 if (item_rect.Y > top_y)
924                                                         return i - 1;
925                                         }
926                                 }
927                         }
928
929                         return i;
930                 }
931
932                 private void OnMouseDownLB (object sender, MouseEventArgs e)
933                 {
934                         int index = -1;
935
936                         for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
937                                 if (GetItemDisplayRectangle (i, LBoxInfo.top_item).Contains (e.X, e.Y) == true) {
938                                         index = i;
939                                         break;
940                                 }
941                         }
942
943                         if (index == -1) return;
944
945                         switch (SelectionMode) {
946                                 case SelectionMode.None: // Do nothing
947                                         break;
948                                 case SelectionMode.One: {
949                                         SelectedIndex = index;
950                                         break;
951                                 }
952
953                                 case SelectionMode.MultiSimple: {
954                                         if (selected_index == -1) {
955                                                 SelectedIndex = index;
956                                         } else {
957
958                                                 if ((Items.GetListBoxItem (index)).Selected)
959                                                         UnSelectItem (index, true);
960                                                 else {
961                                                         SelectItem (index);
962                                                         OnSelectedIndexChanged  (new EventArgs ());
963                                                 }
964                                         }
965                                         break;
966                                 }
967                                 default:
968                                         break;
969                         }
970                 }
971
972                 private void OnPaintLB (PaintEventArgs pevent)
973                 {
974                         if (Width <= 0 || Height <=  0 || Visible == false || suspend_ctrlupdate == true)
975                                 return;
976
977                         /* Copies memory drawing buffer to screen*/
978                         Draw (pevent.ClipRectangle);
979                         pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
980
981                         if (Paint != null)
982                                 Paint (this, pevent);
983                 }
984
985                 internal void RellocateScrollBars ()
986                 {
987                         if (listbox_info.show_verticalsb) {
988
989                                 vscrollbar_ctrl.Size = new Size (vscrollbar_ctrl.Width,
990                                         listbox_info.client_rect.Height - ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle) -
991                                         ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle));
992
993                                 vscrollbar_ctrl.Location = new Point (listbox_info.client_rect.Width - vscrollbar_ctrl.Width
994                                         - ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle),
995                                         ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle));
996
997                         }
998
999                         if (listbox_info.show_horizontalsb) {
1000
1001                                 int width;
1002
1003                                 width = listbox_info.client_rect.Width - (ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle) + ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle));
1004
1005                                 if (listbox_info.show_verticalsb)
1006                                         width -= vscrollbar_ctrl.Width;
1007
1008                                 hscrollbar_ctrl.Size = new Size (width, hscrollbar_ctrl.Height);
1009
1010                                 hscrollbar_ctrl.Location = new Point (ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle),
1011                                         listbox_info.client_rect.Height - hscrollbar_ctrl.Height
1012                                         - ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle));
1013                         }
1014
1015                         CalcClientArea ();
1016                 }
1017
1018                 // Add an item in the Selection array and marks it visually as selected
1019                 private void SelectItem (int index)
1020                 {
1021                         if (index == -1)
1022                                 return;
1023
1024                         Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
1025                         (Items.GetListBoxItem (index)).Selected = true;
1026                         selected_indices.AddIndex (index);
1027                         selected_items.AddObject (Items[index]);
1028
1029                         if (ClientRectangle.Contains (invalidate))
1030                                 Invalidate (invalidate);
1031
1032                 }
1033
1034                 // Removes an item in the Selection array and marks it visually as unselected
1035                 private void UnSelectItem (int index, bool remove)
1036                 {
1037                         if (index == -1)
1038                                 return;
1039
1040                         Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
1041                         (Items.GetListBoxItem (index)).Selected = false;
1042
1043                         if (remove) {
1044                                 selected_indices.RemoveIndex (index);
1045                                 selected_items.RemoveObject (Items[index]);
1046                         }
1047
1048
1049                         if (ClientRectangle.Contains (invalidate))
1050                                 Invalidate (invalidate);
1051                 }
1052
1053                 private void UpdateFormatString ()
1054                 {
1055                         if (RightToLeft == RightToLeft.No)
1056                                 string_format.Alignment = StringAlignment.Near;
1057                         else
1058                                 string_format.Alignment = StringAlignment.Far;
1059
1060                         if (UseTabStops)
1061                                 string_format.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)});
1062                 }
1063
1064                 // Updates the scrollbar's position with the new items and inside area
1065                 internal void UpdateItemInfo (bool adding, int first, int last)
1066                 {
1067                         if (!IsHandleCreated || suspend_ctrlupdate == true)
1068                                 return;
1069
1070                         UpdateShowVerticalScrollBar ();
1071
1072                         if (listbox_info.show_verticalsb && Items.Count > listbox_info.page_size)
1073                                 if (vscrollbar_ctrl.Enabled)
1074                                         vscrollbar_ctrl.Maximum = Items.Count - listbox_info.page_size;
1075
1076                         if (listbox_info.show_horizontalsb) {
1077                                 if (MultiColumn) {
1078                                         int fullpage = (listbox_info.page_size * (listbox_info.client_rect.Width / ColumnWidthInternal));
1079
1080                                         if (hscrollbar_ctrl.Enabled && listbox_info.page_size > 0)
1081                                                 hscrollbar_ctrl.Maximum  = 1 + ((Items.Count - fullpage) / listbox_info.page_size);
1082                                 }
1083                         }
1084
1085                         if (MultiColumn == false) {
1086                                 /* Calc the longest items for non multicolumn listboxes */
1087                                 if ((first == -1 && last == -1) || (adding == false)) {
1088
1089                                         SizeF size;
1090                                         for (int i = 0; i < Items.Count; i++) {
1091                                                 size = DeviceContext.MeasureString (Items[i].ToString(), Font);
1092
1093                                                 if ((int) size.Width > listbox_info.max_itemwidth)
1094                                                         listbox_info.max_itemwidth = (int) size.Width;
1095                                         }
1096                                 }
1097                                 else {
1098                                         if (adding) {
1099
1100                                                 SizeF size;
1101                                                 for (int i = first; i < last + 1; i++) {
1102                                                         size = DeviceContext.MeasureString (Items[i].ToString(), Font);
1103
1104                                                         if ((int) size.Width > listbox_info.max_itemwidth)
1105                                                                 listbox_info.max_itemwidth = (int) size.Width;
1106                                                 }
1107                                         }
1108                                 }
1109                         }
1110
1111                         if (sorted)
1112                                 Sort ();
1113
1114                         SelectedItems.ReCreate ();
1115                         SelectedIndices.ReCreate ();
1116
1117                         UpdateShowHorizontalScrollBar ();
1118                         Refresh ();
1119                 }
1120
1121                 private void UpdateInternalClientRect (Rectangle client_rectangle)
1122                 {
1123                         listbox_info.client_rect = client_rectangle;
1124                         UpdateShowHorizontalScrollBar ();
1125                         UpdateShowVerticalScrollBar ();
1126                         RellocateScrollBars ();
1127                         UpdateItemInfo (false, -1, -1);
1128                 }
1129
1130                 /* Determines if the horizontal scrollbar has to be displyed */
1131                 private void UpdateShowHorizontalScrollBar ()
1132                 {
1133                         bool show = false;
1134                         bool enabled = true;
1135
1136                         if (MultiColumn) {  /* Horizontal scrollbar is always shown in Multicolum mode */
1137
1138                                 /* Is it really need it */
1139                                 int page_size = listbox_info.client_rect.Height / listbox_info.item_height;
1140                                 int fullpage = (page_size * (listbox_info.client_rect.Width / ColumnWidthInternal));
1141
1142                                 if (Items.Count > fullpage) {
1143                                         show = true;
1144                                 }
1145                                 else { /* Acording to MS Documentation ScrollAlwaysVisible only affects Horizontal scrollbars but
1146                                           this is not true for MultiColumn listboxes */
1147                                         if (ScrollAlwaysVisible == true) {
1148                                                 enabled = false;
1149                                                 show = true;
1150                                         }
1151                                 }
1152
1153                         } else { /* If large item*/
1154
1155                                 if (listbox_info.max_itemwidth > listbox_info.client_rect.Width && HorizontalScrollbar) {
1156                                         show = true;
1157                                         hscrollbar_ctrl.Maximum = listbox_info.max_itemwidth;
1158                                 }
1159                         }
1160
1161                         if (hscrollbar_ctrl.Enabled != enabled)
1162                                 hscrollbar_ctrl.Enabled = enabled;
1163
1164                         if (listbox_info.show_horizontalsb == show)
1165                                 return;
1166
1167                         listbox_info.show_horizontalsb = show;
1168                         hscrollbar_ctrl.Visible = show;
1169
1170                         if (show == true) {
1171                                 RellocateScrollBars ();
1172                         }
1173
1174                         CalcClientArea ();
1175                 }
1176
1177                 /* Determines if the vertical scrollbar has to be displyed */
1178                 private void UpdateShowVerticalScrollBar ()
1179                 {
1180                         bool show = false;
1181                         bool enabled = true;
1182
1183                         if (!MultiColumn) {  /* Vertical scrollbar is never shown in Multicolum mode */
1184                                 if (Items.Count > listbox_info.page_size) {
1185                                         show = true;
1186                                 }
1187                                 else
1188                                         if (ScrollAlwaysVisible) {
1189                                                 show = true;
1190                                                 enabled = false;
1191                                         }
1192                         }
1193
1194                         if (vscrollbar_ctrl.Enabled != enabled)
1195                                 vscrollbar_ctrl.Enabled = enabled;
1196
1197                         if (listbox_info.show_verticalsb == show)
1198                                 return;
1199
1200                         listbox_info.show_verticalsb = show;
1201                         vscrollbar_ctrl.Visible = show;
1202
1203                         if (show == true) {
1204                                 if (vscrollbar_ctrl.Enabled)
1205                                         vscrollbar_ctrl.Maximum = Items.Count - listbox_info.page_size;
1206
1207                                 RellocateScrollBars ();
1208                         }
1209
1210                         CalcClientArea ();
1211                 }
1212
1213                 // Value Changed
1214                 private void VerticalScrollEvent (object sender, EventArgs e)
1215                 {
1216                         LBoxInfo.top_item = /*listbox_info.page_size + */ vscrollbar_ctrl.Value;
1217                         LBoxInfo.last_item = LastVisibleItem ();
1218
1219                         Refresh ();
1220                 }
1221
1222                 #endregion Private Methods
1223
1224                 /*
1225                         ListBox.ObjectCollection
1226                 */
1227                 public class ObjectCollection : IList, ICollection, IEnumerable
1228                 {
1229                         // Compare objects
1230                         internal class ListObjectComparer : IComparer\r
1231                         {\r
1232                                 private ListBox owner;\r
1233                         \r
1234                                 public ListObjectComparer (ListBox owner)\r
1235                                 {\r
1236                                         this.owner = owner;\r
1237                                 }\r
1238                                 \r
1239                                 public int Compare (object a, object b)\r
1240                                 {\r
1241                                         string str1 = a.ToString ();
1242                                         string str2 = b.ToString ();                                    \r
1243                                         return str1.CompareTo (str2);\r
1244                                 }\r
1245                         }
1246
1247                         // Compare ListItem
1248                         internal class ListItemComparer : IComparer\r
1249                         {\r
1250                                 private ListBox owner;\r
1251                         \r
1252                                 public ListItemComparer (ListBox owner)\r
1253                                 {\r
1254                                         this.owner = owner;\r
1255                                 }\r
1256                                 \r
1257                                 public int Compare (object a, object b)\r
1258                                 {\r
1259                                         int index1 = ((ListBox.ListBoxItem) (a)).Index;
1260                                         int index2 = ((ListBox.ListBoxItem) (b)).Index;
1261                                         string str1 = owner.Items[index1].ToString ();
1262                                         string str2 = owner.Items[index2].ToString ();                                  \r
1263                                         return str1.CompareTo (str2);                                   \r
1264                                 }\r
1265                         }
1266
1267                         private ListBox owner;
1268                         private ArrayList object_items = new ArrayList ();
1269                         private ArrayList listbox_items = new ArrayList ();
1270
1271                         public ObjectCollection (ListBox owner)
1272                         {
1273                                 this.owner = owner;
1274                         }
1275
1276                         public ObjectCollection (ListBox owner, object[] obj)
1277                         {
1278                                 this.owner = owner;
1279                                 AddRange (obj);
1280                         }
1281
1282                         public ObjectCollection (ListBox owner,  ObjectCollection obj)
1283                         {
1284                                 this.owner = owner;
1285                                 AddRange (obj);
1286                         }
1287
1288                         #region Public Properties
1289                         public virtual int Count {
1290                                 get { return object_items.Count; }
1291                         }
1292
1293                         public virtual bool IsReadOnly {
1294                                 get { return false; }
1295                         }
1296
1297                         public virtual object this [int index] {
1298                                 get {
1299                                         if (index < 0 || index >= Count)
1300                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1301
1302                                         return object_items[index];
1303                                 }
1304                                 set {
1305                                         if (index < 0 || index >= Count)
1306                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1307
1308                                         object_items[index] = value;
1309                                 }
1310                         }
1311
1312                         bool ICollection.IsSynchronized {
1313                                 get { return false; }
1314                         }
1315
1316                         object ICollection.SyncRoot {
1317                                 get { return this; }
1318                         }
1319
1320                         bool IList.IsFixedSize {
1321                                 get { return false; }
1322                         }
1323
1324                         #endregion Public Properties
1325
1326                         #region Public Methods
1327                         public int Add (object item)
1328                         {
1329                                 int idx;
1330
1331                                 idx = AddItem (item);
1332                                 owner.UpdateItemInfo (true, idx, idx);
1333                                 return idx;
1334                         }
1335
1336                         public void AddRange (object[] items)
1337                         {
1338                                 int cnt = Count;
1339
1340                                 foreach (object mi in items)
1341                                         AddItem (mi);
1342
1343                                 owner.UpdateItemInfo (true, cnt, Count);
1344                         }
1345
1346                         public void AddRange (ObjectCollection col)
1347                         {
1348                                 int cnt = Count;
1349
1350                                 foreach (object mi in col)
1351                                         AddItem (mi);
1352
1353                                 owner.UpdateItemInfo (true, cnt, Count);
1354                         }
1355
1356                         public virtual void Clear ()
1357                         {
1358                                 object_items.Clear ();
1359                                 listbox_items.Clear ();
1360                                 owner.UpdateItemInfo (false, -1, -1);
1361                         }
1362                         public virtual bool Contains (object obj)
1363                         {
1364                                 return object_items.Contains (obj);
1365                         }
1366
1367                         public void CopyTo (object[] dest, int arrayIndex)
1368                         {
1369                                 object_items.CopyTo (dest, arrayIndex);
1370                         }
1371
1372                         void ICollection.CopyTo (Array dest, int index)
1373                         {
1374                                 object_items.CopyTo (dest, index);
1375                         }
1376
1377                         public virtual IEnumerator GetEnumerator ()
1378                         {
1379                                 return object_items.GetEnumerator ();
1380                         }
1381
1382                         int IList.Add (object item)
1383                         {
1384                                 return Add (item);
1385                         }
1386
1387                         public virtual int IndexOf (object value)
1388                         {
1389                                 return object_items.IndexOf (value);
1390                         }
1391
1392                         public virtual void Insert (int index,  object item)
1393                         {
1394                                 throw new NotImplementedException ();
1395                         }
1396
1397                         public virtual void Remove (object value)
1398                         {
1399                                 RemoveAt (IndexOf (value));
1400                                 owner.UpdateItemInfo (false, -1, -1);
1401                         }
1402
1403                         public virtual void RemoveAt (int index)
1404                         {
1405                                 if (index < 0 || index >= Count)
1406                                         throw new ArgumentOutOfRangeException ("Index of out range");
1407
1408                                 object_items.RemoveAt (index);
1409                                 listbox_items.RemoveAt (index);
1410                                 owner.UpdateItemInfo (false, -1, -1);
1411                         }
1412                         #endregion Public Methods
1413
1414                         #region Private Methods
1415                         private int AddItem (object item)
1416                         {
1417                                 int cnt = object_items.Count;
1418                                 object_items.Add (item);
1419                                 listbox_items.Add (new ListBox.ListBoxItem (cnt));
1420                                 return cnt;
1421                         }
1422
1423                         // TODO: object_items have to be sorted, look at ListBoxItem. Are we using object theere?
1424                         internal ListBox.ListBoxItem GetListBoxItem (int index)
1425                         {
1426                                 if (index < 0 || index >= Count)
1427                                         throw new ArgumentOutOfRangeException ("Index of out range");
1428
1429                                 return (ListBox.ListBoxItem) listbox_items[index];
1430                         }
1431
1432                         internal void SetListBoxItem (ListBox.ListBoxItem item, int index)
1433                         {
1434                                 if (index < 0 || index >= Count)
1435                                         throw new ArgumentOutOfRangeException ("Index of out range");
1436
1437                                 listbox_items[index] = item;
1438                         }
1439
1440                         internal void Sort ()
1441                         {
1442                                 /* Keep this order */
1443                                 listbox_items.Sort (new ListItemComparer (owner));
1444                                 object_items.Sort (new ListObjectComparer (owner));
1445
1446                                 for (int i = 0; i < listbox_items.Count; i++) {
1447                                         ListBox.ListBoxItem item = GetListBoxItem (i);
1448                                         item.Index = i;
1449                                 }
1450                         }
1451
1452                         #endregion Private Methods
1453                 }
1454
1455                 /*
1456                         ListBox.SelectedIndexCollection
1457                 */
1458                 public class SelectedIndexCollection : IList, ICollection, IEnumerable
1459                 {
1460                         private ListBox owner;
1461                         private ArrayList indices = new ArrayList ();
1462
1463                         public SelectedIndexCollection (ListBox owner)
1464                         {
1465                                 this.owner = owner;
1466                         }
1467
1468                         #region Public Properties
1469                         public virtual int Count {
1470                                 get { return indices.Count; }
1471                         }
1472
1473                         public virtual bool IsReadOnly {
1474                                 get { return true; }
1475                         }
1476
1477                         public int this [int index] {
1478                                 get {
1479                                         if (index < 0 || index >= Count)
1480                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1481
1482                                         return (int) indices[index];
1483                                 }
1484                         }
1485
1486                         bool ICollection.IsSynchronized {
1487                                 get { return true; }
1488                         }
1489
1490                         bool IList.IsFixedSize{
1491                                 get { return true; }
1492                         }
1493
1494                         object ICollection.SyncRoot {
1495                                 get { return this; }
1496                         }
1497
1498                         #endregion Public Properties
1499
1500                         #region Public Methods
1501                         public bool Contains (int selectedIndex)
1502                         {
1503                                 return indices.Contains (selectedIndex);
1504                         }
1505
1506                         public virtual void CopyTo (Array dest, int index)
1507                         {
1508                                 indices.CopyTo (dest, index);
1509                         }
1510
1511                         public virtual IEnumerator GetEnumerator ()
1512                         {
1513                                 return indices.GetEnumerator ();
1514                         }
1515
1516                         int IList.Add (object obj)
1517                         {
1518                                 throw new NotSupportedException ();
1519                         }
1520
1521                         void IList.Clear ()
1522                         {
1523                                 throw new NotSupportedException ();
1524                         }
1525
1526                         bool IList.Contains (object selectedIndex)
1527                         {
1528                                 return Contains ((int)selectedIndex);
1529                         }
1530
1531                         int IList.IndexOf (object selectedIndex)
1532                         {
1533                                 return IndexOf ((int) selectedIndex);
1534                         }
1535
1536                         void IList.Insert (int index, object value)
1537                         {
1538                                 throw new NotSupportedException ();
1539                         }
1540
1541                         void IList.Remove (object value)
1542                         {
1543                                 throw new NotSupportedException ();
1544                         }
1545
1546                         void IList.RemoveAt (int index)
1547                         {
1548                                 throw new NotSupportedException ();
1549                         }
1550
1551                         object IList.this[int index]{
1552                                 get {return indices[index]; }
1553                                 set {throw new NotImplementedException (); }
1554                         }
1555
1556                         public int IndexOf (int selectedIndex)
1557                         {
1558                                 return indices.IndexOf (selectedIndex);
1559                         }
1560                         #endregion Public Methods
1561
1562                         #region Private Methods
1563
1564                         internal void AddIndex (int index)
1565                         {
1566                                 indices.Add (index);
1567                         }
1568
1569                         internal void ClearIndices ()
1570                         {
1571                                 indices.Clear ();
1572                         }
1573
1574                         internal void RemoveIndex (int index)
1575                         {
1576                                 indices.Remove (index);
1577                         }
1578
1579                         internal void ReCreate ()
1580                         {
1581                                 indices.Clear ();
1582
1583                                 for (int i = 0; i < owner.Items.Count; i++) {
1584                                         ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
1585
1586                                         if (item.Selected)
1587                                                 indices.Add (item.Index);
1588                                 }
1589                         }
1590
1591                         #endregion Private Methods
1592                 }
1593
1594                 /*
1595                         SelectedObjectCollection
1596                 */
1597                 public class SelectedObjectCollection : IList, ICollection, IEnumerable
1598                 {
1599                         private ListBox owner;
1600                         private ArrayList object_items = new ArrayList ();
1601
1602                         public SelectedObjectCollection (ListBox owner)
1603                         {
1604                                 this.owner = owner;
1605                         }
1606
1607                         #region Public Properties
1608                         public virtual int Count {
1609                                 get { return object_items.Count; }
1610                         }
1611
1612                         public virtual bool IsReadOnly {
1613                                 get { return true; }
1614                         }
1615
1616                         public virtual object this [int index] {
1617                                 get {
1618                                         if (index < 0 || index >= Count)
1619                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1620
1621                                         return object_items[index];
1622                                 }
1623                                 set {throw new NotSupportedException ();}
1624                         }
1625
1626                         bool ICollection.IsSynchronized {
1627                                 get { return true; }
1628                         }
1629
1630                         object ICollection.SyncRoot {
1631                                 get { return this; }
1632                         }
1633
1634                         bool IList.IsFixedSize {
1635                                 get { return true; }
1636                         }
1637
1638                         object IList.this[int index] {
1639                                 get { return object_items[index]; }
1640                                 set { throw new NotSupportedException (); }
1641                         }
1642
1643                         #endregion Public Properties
1644
1645                         #region Public Methods
1646                         public virtual bool Contains (object selectedObject)
1647                         {
1648                                 return object_items.Contains (selectedObject);
1649                         }
1650
1651                         public virtual void CopyTo (Array dest, int index)
1652                         {
1653                                 object_items.CopyTo (dest, index);
1654                         }
1655
1656                         int IList.Add (object value)
1657                         {
1658                                 throw new NotSupportedException ();
1659                         }
1660
1661                         void IList.Clear ()
1662                         {
1663                                 throw new NotSupportedException ();
1664                         }
1665
1666                         bool IList.Contains (object selectedIndex)
1667                         {
1668                                 throw new NotImplementedException ();
1669                         }
1670
1671                         int IList.IndexOf (object selectedIndex)
1672                         {
1673                                 return IndexOf ((int) selectedIndex);
1674                         }
1675         \r
1676                         void IList.Insert (int index, object value)
1677                         {
1678                                 throw new NotSupportedException ();
1679                         }
1680
1681                         void IList.Remove (object value)
1682                         {
1683                                 throw new NotSupportedException ();
1684                         }
1685
1686                         void IList.RemoveAt (int index)
1687                         {
1688                                 throw new NotSupportedException ();
1689                         }
1690         \r
1691                         public int IndexOf (int selectedIndex)
1692                         {
1693                                 return object_items.IndexOf (selectedIndex);
1694                         }
1695
1696                         public virtual IEnumerator GetEnumerator ()
1697                         {
1698                                 return object_items.GetEnumerator ();
1699                         }
1700
1701                         #endregion Public Methods
1702
1703                         #region Private Methods
1704                         internal void AddObject (object obj)
1705                         {
1706                                 object_items.Add (obj);
1707                         }
1708
1709                         internal void ClearObjects ()
1710                         {
1711                                 object_items.Clear ();
1712                         }
1713
1714                         internal void ReCreate ()
1715                         {
1716                                 object_items.Clear ();
1717
1718                                 for (int i = 0; i < owner.Items.Count; i++) {
1719                                         ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
1720
1721                                         if (item.Selected)
1722                                                 object_items.Add (owner.Items[item.Index]);
1723                                 }
1724                         }
1725
1726                         internal void RemoveObject (object obj)
1727                         {
1728                                 object_items.Remove (obj);
1729                         }
1730
1731
1732
1733                         #endregion Private Methods
1734
1735                 }
1736
1737         }
1738 }
1739