Moved ProviderCollectionTest.cs from System assembly to System.Configuration.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / TextBox.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2006 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //     Daniel Nauck    (dna(at)mono-project(dot)de)
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.Collections;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
33 using System.Drawing;
34 #if NET_2_0
35 using System.Collections.Generic;
36 using System.Runtime.InteropServices;
37 #endif
38
39 namespace System.Windows.Forms {
40
41 #if NET_2_0
42         [ComVisible(true)]
43         [ClassInterface (ClassInterfaceType.AutoDispatch)]
44         [Designer ("System.Windows.Forms.Design.TextBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 #endif
46         public class TextBox : TextBoxBase {
47                 #region Variables
48                 private ContextMenu     menu;
49                 private MenuItem        undo;
50                 private MenuItem        cut;
51                 private MenuItem        copy;
52                 private MenuItem        paste;
53                 private MenuItem        delete;
54                 private MenuItem        select_all;
55
56 #if NET_2_0
57                 private bool use_system_password_char;
58                 private AutoCompleteStringCollection auto_complete_custom_source;
59                 private AutoCompleteMode auto_complete_mode = AutoCompleteMode.None;
60                 private AutoCompleteSource auto_complete_source = AutoCompleteSource.None;
61                 private AutoCompleteListBox auto_complete_listbox;
62                 private string auto_complete_original_text;
63                 private ComboBox auto_complete_cb_source;
64 #endif
65                 #endregion      // Variables
66
67                 #region Public Constructors
68                 public TextBox() {
69
70                         scrollbars = RichTextBoxScrollBars.None;
71                         alignment = HorizontalAlignment.Left;
72                         this.LostFocus +=new EventHandler(TextBox_LostFocus);
73                         this.RightToLeftChanged += new EventHandler (TextBox_RightToLeftChanged);
74 #if NET_2_0
75                         MouseWheel += new MouseEventHandler (TextBox_MouseWheel);
76 #endif
77
78                         BackColor = SystemColors.Window;
79                         ForeColor = SystemColors.WindowText;
80                         backcolor_set = false;
81
82                         SetStyle (ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, false);
83                         SetStyle (ControlStyles.FixedHeight, true);
84
85                         undo = new MenuItem(Locale.GetText("&Undo"));
86                         cut = new MenuItem(Locale.GetText("Cu&t"));
87                         copy = new MenuItem(Locale.GetText("&Copy"));
88                         paste = new MenuItem(Locale.GetText("&Paste"));
89                         delete = new MenuItem(Locale.GetText("&Delete"));
90                         select_all = new MenuItem(Locale.GetText("Select &All"));
91
92                         menu = new ContextMenu(new MenuItem[] { undo, new MenuItem("-"), cut, copy, paste, delete, new MenuItem("-"), select_all});
93                         ContextMenu = menu;
94
95                         menu.Popup += new EventHandler(menu_Popup);
96                         undo.Click += new EventHandler(undo_Click);
97                         cut.Click += new EventHandler(cut_Click);
98                         copy.Click += new EventHandler(copy_Click);
99                         paste.Click += new EventHandler(paste_Click);
100                         delete.Click += new EventHandler(delete_Click);
101                         select_all.Click += new EventHandler(select_all_Click);
102
103                         document.multiline = false;
104                 }
105
106                 #endregion      // Public Constructors
107
108                 #region Private & Internal Methods
109
110                 void TextBox_RightToLeftChanged (object sender, EventArgs e)
111                 {
112                         UpdateAlignment ();
113                 }
114
115                 private void TextBox_LostFocus (object sender, EventArgs e) {
116                         if (hide_selection)
117                                 document.InvalidateSelectionArea ();
118 #if NET_2_0
119                         if (auto_complete_listbox != null && auto_complete_listbox.Visible)
120                                 auto_complete_listbox.HideListBox (false);
121 #endif
122                 }
123
124 #if NET_2_0
125                 private void TextBox_MouseWheel (object o, MouseEventArgs args)
126                 {
127                         if (auto_complete_listbox == null || !auto_complete_listbox.Visible)
128                                 return;
129
130                         int lines = args.Delta / 120;
131                         auto_complete_listbox.Scroll (-lines);
132                 }
133
134                 private void ShowAutoCompleteListBox ()
135                 {
136                         if (auto_complete_mode == AutoCompleteMode.None || auto_complete_source == AutoCompleteSource.None)
137                                 return;
138
139                         // 
140                         // We only support CustomSource *and* Suggest mode by now
141                         //
142
143                         if (auto_complete_mode != AutoCompleteMode.Suggest)
144                                 return;
145
146                         IList source;
147                         if (auto_complete_cb_source == null)
148                                 source = auto_complete_custom_source;
149                         else
150                                 source = auto_complete_cb_source.Items;
151
152                         if (auto_complete_source != AutoCompleteSource.CustomSource ||
153                                 source == null || source.Count == 0)
154                                 return;
155
156                         if (Text.Length == 0) {
157                                 if (auto_complete_listbox != null)
158                                         auto_complete_listbox.HideListBox (false);
159                                 return;
160                         }
161
162                         if (auto_complete_listbox == null)
163                                 auto_complete_listbox = new AutoCompleteListBox (this);
164
165                         string text = Text;
166                         auto_complete_listbox.Items.Clear ();
167
168                         for (int i = 0; i < source.Count; i++) {
169                                 string item_text = auto_complete_cb_source == null ? auto_complete_custom_source [i] :
170                                         auto_complete_cb_source.GetItemText (auto_complete_cb_source.Items [i]);
171                                 if (item_text.StartsWith (text, StringComparison.CurrentCultureIgnoreCase))
172                                         auto_complete_listbox.Items.Add (item_text);
173                         }
174
175                         IList<string> matches = auto_complete_listbox.Items;
176                         if ((matches.Count == 0) ||
177                                 (matches.Count == 1 && matches [0].Equals (text, StringComparison.CurrentCultureIgnoreCase))) { // Exact single match
178
179                                 if (auto_complete_listbox.Visible)
180                                         auto_complete_listbox.HideListBox (false);
181                                 return;
182                         }
183
184                         // Show or update auto complete listbox contents
185                         auto_complete_listbox.Location = PointToScreen (new Point (0, Height));
186                         auto_complete_listbox.ShowListBox ();
187                 }
188
189                 internal ComboBox AutoCompleteInternalSource {
190                         get {
191                                 return auto_complete_cb_source;
192                         }
193                         set {
194                                 auto_complete_cb_source = value;
195                         }
196                 }
197
198                 void NavigateAutoCompleteList (Keys key)
199                 {
200                         int index = auto_complete_listbox.HighlightedIndex;
201                         if (index == -1)
202                                 auto_complete_original_text = Text;
203
204                         switch (key) {
205                                 case Keys.Up:
206                                         index -= 1;
207                                         if (index < -1)
208                                                 index = auto_complete_listbox.Items.Count - 1;
209                                         break;
210                                 case Keys.Down:
211                                         index += 1;
212                                         if (index >= auto_complete_listbox.Items.Count)
213                                                 index = -1;
214                                         break;
215                                 case Keys.PageUp:
216                                         if (index == -1)
217                                                 index = auto_complete_listbox.Items.Count - 1;
218                                         else if (index == 0)
219                                                 index = -1;
220                                         else {
221                                                 index -= auto_complete_listbox.page_size - 1;
222                                                 if (index < 0)
223                                                         index = 0;
224                                         }
225                                         break;
226                                 case Keys.PageDown:
227                                         if (index == -1)
228                                                 index = 0;
229                                         else if (index == auto_complete_listbox.Items.Count - 1)
230                                                 index = -1;
231                                         else {
232                                                 index += auto_complete_listbox.page_size - 1;
233                                                 if (index >= auto_complete_listbox.Items.Count)
234                                                         index = auto_complete_listbox.Items.Count - 1;
235                                         }
236                                         break;
237                                 default:
238                                         break;
239                         }
240
241                         auto_complete_listbox.HighlightedIndex = index;
242                         Text = index == -1 ? auto_complete_original_text : auto_complete_listbox.Items [index];
243                 }
244 #endif
245
246                 private void UpdateAlignment ()
247                 {
248                         HorizontalAlignment new_alignment = alignment;
249                         RightToLeft rtol = GetInheritedRtoL ();
250
251                         if (rtol == RightToLeft.Yes) {
252                                 if (new_alignment == HorizontalAlignment.Left)
253                                         new_alignment = HorizontalAlignment.Right;
254                                 else if (new_alignment == HorizontalAlignment.Right)
255                                         new_alignment = HorizontalAlignment.Left;
256                         }
257
258                         document.alignment = new_alignment;
259
260                         // MS word-wraps if alignment isn't left
261                         if (Multiline) {
262                                 if (alignment != HorizontalAlignment.Left) {
263                                         document.Wrap = true;
264                                 } else {
265                                         document.Wrap = word_wrap;
266                                 }
267                         }
268
269                         for (int i = 1; i <= document.Lines; i++) {
270                                 document.GetLine (i).Alignment = new_alignment;
271                         }
272
273                         document.RecalculateDocument (CreateGraphicsInternal ());
274
275                         Invalidate ();  // Make sure we refresh
276                 }
277
278                 internal override Color ChangeBackColor (Color backColor)
279                 {
280                         if (backColor == Color.Empty) {
281 #if NET_2_0
282                                 if (!ReadOnly)
283                                         backColor = SystemColors.Window;
284 #else
285                                 backColor = SystemColors.Window;
286 #endif
287                                 backcolor_set = false;
288                         }
289                         return backColor;
290                 }
291
292 #if NET_2_0
293                 void OnAutoCompleteCustomSourceChanged(object sender, CollectionChangeEventArgs e) {
294                         if(auto_complete_source == AutoCompleteSource.CustomSource) {
295                                 //FIXME: handle add, remove and refresh events in AutoComplete algorithm.
296                         }
297                 }
298 #endif
299                 #endregion      // Private & Internal Methods
300
301                 #region Public Instance Properties
302 #if NET_2_0
303                 [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
304                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
305                 [Browsable (true)]
306                 [EditorBrowsable (EditorBrowsableState.Always)]
307                 [Localizable (true)]
308                 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design,
309                  "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
310                 public AutoCompleteStringCollection AutoCompleteCustomSource { 
311                         get {
312                                 if(auto_complete_custom_source == null) {
313                                         auto_complete_custom_source = new AutoCompleteStringCollection ();
314                                         auto_complete_custom_source.CollectionChanged += new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
315                                 }
316                                 return auto_complete_custom_source;
317                         }
318                         set {
319                                 if(auto_complete_custom_source == value)
320                                         return;
321
322                                 if(auto_complete_custom_source != null) //remove eventhandler from old collection
323                                         auto_complete_custom_source.CollectionChanged -= new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
324
325                                 auto_complete_custom_source = value;
326
327                                 if(auto_complete_custom_source != null)
328                                         auto_complete_custom_source.CollectionChanged += new CollectionChangeEventHandler (OnAutoCompleteCustomSourceChanged);
329                         }
330                 }
331
332                 [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
333                 [Browsable (true)]
334                 [EditorBrowsable (EditorBrowsableState.Always)]
335                 [DefaultValue (AutoCompleteMode.None)]
336                 public AutoCompleteMode AutoCompleteMode {
337                         get { return auto_complete_mode; }
338                         set {
339                                 if(auto_complete_mode == value)
340                                         return;
341
342                                 if((value < AutoCompleteMode.None) || (value > AutoCompleteMode.SuggestAppend))
343                                         throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for AutoCompleteMode", value));
344
345                                 auto_complete_mode = value;
346                         }
347                 }
348
349                 [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
350                 [Browsable (true)]
351                 [EditorBrowsable (EditorBrowsableState.Always)]
352                 [DefaultValue (AutoCompleteSource.None)]
353                 [TypeConverter (typeof (TextBoxAutoCompleteSourceConverter))]
354                 public AutoCompleteSource AutoCompleteSource {
355                         get { return auto_complete_source; }
356                         set {
357                                 if(auto_complete_source == value)
358                                         return;
359
360                                 if(!Enum.IsDefined (typeof (AutoCompleteSource), value))
361                                         throw new InvalidEnumArgumentException (Locale.GetText ("Enum argument value '{0}' is not valid for AutoCompleteSource", value));
362
363                                 auto_complete_source = value;
364                         }
365                 }
366
367                 [DefaultValue(false)]
368                 [RefreshProperties (RefreshProperties.Repaint)]
369                 public bool UseSystemPasswordChar {
370                         get {
371                                 return use_system_password_char;
372                         }
373
374                         set {
375                                 if (use_system_password_char != value) {
376                                         use_system_password_char = value;
377                                         
378                                         if (!Multiline)
379                                                 document.PasswordChar = PasswordChar.ToString ();
380                                         else
381                                                 document.PasswordChar = string.Empty;
382                                         Invalidate ();
383                                 }
384                         }
385                 }
386 #endif
387
388                 [DefaultValue(false)]
389                 [MWFCategory("Behavior")]
390                 public bool AcceptsReturn {
391                         get {
392                                 return accepts_return;
393                         }
394
395                         set {
396                                 if (value != accepts_return) {
397                                         accepts_return = value;
398                                 }
399                         }
400                 }
401
402                 [DefaultValue(CharacterCasing.Normal)]
403                 [MWFCategory("Behavior")]
404                 public CharacterCasing CharacterCasing {
405                         get {
406                                 return character_casing;
407                         }
408
409                         set {
410                                 if (value != character_casing) {
411                                         character_casing = value;
412                                 }
413                         }
414                 }
415
416                 [Localizable(true)]
417                 [DefaultValue('\0')]
418                 [MWFCategory("Behavior")]
419 #if NET_2_0
420                 [RefreshProperties (RefreshProperties.Repaint)]
421 #endif
422                 public char PasswordChar {
423                         get {
424 #if NET_2_0
425                                 if (use_system_password_char) {
426                                         return '*';
427                                 }
428 #endif
429                                 return password_char;
430                         }
431
432                         set {
433                                 if (value != password_char) {
434                                         password_char = value;
435                                         if (!Multiline) {
436                                                 document.PasswordChar = PasswordChar.ToString ();
437                                         } else {
438                                                 document.PasswordChar = string.Empty;
439                                         }
440                                         this.CalculateDocument();
441                                 }
442                         }
443                 }
444
445                 [DefaultValue(ScrollBars.None)]
446                 [Localizable(true)]
447                 [MWFCategory("Appearance")]
448                 public ScrollBars ScrollBars {
449                         get {
450                                 return (ScrollBars)scrollbars;
451                         }
452
453                         set {
454                                 if (!Enum.IsDefined (typeof (ScrollBars), value))
455                                         throw new InvalidEnumArgumentException ("value", (int) value,
456                                                 typeof (ScrollBars));
457
458                                 if (value != (ScrollBars)scrollbars) {
459                                         scrollbars = (RichTextBoxScrollBars)value;
460                                         base.CalculateScrollBars();
461                                 }
462                         }
463                 }
464
465 #if ONLY_1_1
466                 [Browsable(false)]
467                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
468                 public override int SelectionLength {
469                         get {
470                                 return base.SelectionLength;
471                         }
472                         set {
473                                 base.SelectionLength = value;
474                         }
475                 }
476 #endif
477
478                 public override string Text {
479                         get {
480                                 return base.Text;
481                         }
482
483                         set {
484                                 base.Text = value;
485                         }
486                 }
487
488                 [DefaultValue(HorizontalAlignment.Left)]
489                 [Localizable(true)]
490                 [MWFCategory("Appearance")]
491                 public HorizontalAlignment TextAlign {
492                         get {
493                                 return alignment;
494                         }
495
496                         set {
497                                 if (value != alignment) {
498                                         alignment = value;
499
500                                         UpdateAlignment ();
501
502                                         OnTextAlignChanged(EventArgs.Empty);
503                                 }
504                         }
505                 }
506                 #endregion      // Public Instance Properties
507
508 #if NET_2_0
509                 public void Paste (string text)
510                 {
511                         document.ReplaceSelection (CaseAdjust (text), false);
512
513                         ScrollToCaret();
514                         OnTextChanged(EventArgs.Empty);
515                 }
516 #endif
517                 #region Protected Instance Methods
518                 protected override CreateParams CreateParams {
519                         get {
520                                 return base.CreateParams;
521                         }
522                 }
523
524 #if ONLY_1_1
525                 protected override ImeMode DefaultImeMode {
526                         get {
527                                 return base.DefaultImeMode;
528                         }
529                 }
530 #endif
531 #if NET_2_0
532                 protected override void Dispose (bool disposing)
533                 {
534                         base.Dispose (disposing);
535                 }
536 #endif
537
538                 protected override bool IsInputKey (Keys keyData)
539                 {
540                         return base.IsInputKey (keyData);
541                 }
542
543                 protected override void OnGotFocus (EventArgs e)
544                 {
545                         base.OnGotFocus (e);
546                         if (selection_length == -1 && !has_been_focused)
547                                 SelectAllNoScroll ();
548                         has_been_focused = true;
549                 }
550
551                 protected override void OnHandleCreated (EventArgs e)
552                 {
553                         base.OnHandleCreated (e);
554                 }
555
556 #if ONLY_1_1
557                 protected override void OnMouseUp(MouseEventArgs mevent)
558                 {
559                         base.OnMouseUp (mevent);
560                 }
561 #endif
562
563                 protected virtual void OnTextAlignChanged (EventArgs e)
564                 {
565                         EventHandler eh = (EventHandler)(Events [TextAlignChangedEvent]);
566                         if (eh != null)
567                                 eh (this, e);
568                 }
569
570                 protected override void WndProc (ref Message m)
571                 {
572                         switch ((Msg)m.Msg) {
573 #if NET_2_0
574                                 case Msg.WM_KEYDOWN:
575                                         if (auto_complete_listbox == null || !auto_complete_listbox.Visible)
576                                                 break;
577
578                                         Keys key_data = (Keys)m.WParam.ToInt32 ();
579                                         switch (key_data) {
580                                                 case Keys.Down:
581                                                 case Keys.Up:
582                                                 case Keys.PageDown:
583                                                 case Keys.PageUp:
584                                                         NavigateAutoCompleteList (key_data);
585                                                         m.Result = IntPtr.Zero;
586                                                         return;
587                                                 default:
588                                                         break;
589                                         }
590                                         break;
591                                 case Msg.WM_CHAR:
592                                         // Need to call base.WndProc before to have access to
593                                         // the updated Text property value
594                                         base.WndProc (ref m);
595                                         ShowAutoCompleteListBox ();
596                                         return;
597 #endif
598                                 case Msg.WM_LBUTTONDOWN:
599                                         // When the textbox gets focus by LBUTTON (but not by middle or right)
600                                         // it does not do the select all / scroll thing.
601                                         has_been_focused = true;
602                                         FocusInternal (true);
603                                         break;
604                         }
605
606                         base.WndProc(ref m);
607                 }
608                 #endregion      // Protected Instance Methods
609
610                 #region Events
611                 static object TextAlignChangedEvent = new object ();
612
613                 public event EventHandler TextAlignChanged {
614                         add { Events.AddHandler (TextAlignChangedEvent, value); }
615                         remove { Events.RemoveHandler (TextAlignChangedEvent, value); }
616                 }
617                 #endregion      // Events
618
619                 #region Private Methods
620
621                 internal override ContextMenu ContextMenuInternal {
622                         get {
623                                 ContextMenu res = base.ContextMenuInternal;
624                                 if (res == menu)
625                                         return null;
626                                 return res;
627                         }
628                         set {
629                                 base.ContextMenuInternal = value;
630                         }
631                 }
632
633                 internal void RestoreContextMenu ()
634                 {
635                         ContextMenuInternal = menu;
636                 }
637
638                 private void menu_Popup(object sender, EventArgs e) {
639                         if (SelectionLength == 0) {
640                                 cut.Enabled = false;
641                                 copy.Enabled = false;
642                         } else {
643                                 cut.Enabled = true;
644                                 copy.Enabled = true;
645                         }
646
647                         if (SelectionLength == TextLength) {
648                                 select_all.Enabled = false;
649                         } else {
650                                 select_all.Enabled = true;
651                         }
652
653                         if (!CanUndo) {
654                                 undo.Enabled = false;
655                         } else {
656                                 undo.Enabled = true;
657                         }
658
659                         if (ReadOnly) {
660                                 undo.Enabled = cut.Enabled = paste.Enabled = delete.Enabled = false;
661                         }
662                 }
663
664                 private void undo_Click(object sender, EventArgs e) {
665                         Undo();
666                 }
667
668                 private void cut_Click(object sender, EventArgs e) {
669                         Cut();
670                 }
671
672                 private void copy_Click(object sender, EventArgs e) {
673                         Copy();
674                 }
675
676                 private void paste_Click(object sender, EventArgs e) {
677                         Paste();
678                 }
679
680                 private void delete_Click(object sender, EventArgs e) {
681                         SelectedText = string.Empty;
682                 }
683
684                 private void select_all_Click(object sender, EventArgs e) {
685                         SelectAll();
686                 }
687                 #endregion      // Private Methods
688
689 #if NET_2_0
690                 public override bool Multiline {
691                         get {
692                                 return base.Multiline;
693                         }
694
695                         set {
696                                 base.Multiline = value;
697                         }
698                 }
699
700                 protected override void OnBackColorChanged (EventArgs e)
701                 {
702                         base.OnBackColorChanged (e);
703                 }
704                 
705                 protected override void OnFontChanged (EventArgs e)
706                 {
707                         base.OnFontChanged (e);
708                 }
709
710                 protected override void OnHandleDestroyed (EventArgs e)
711                 {
712                         base.OnHandleDestroyed (e);
713                 }
714
715                 class AutoCompleteListBox : Control
716                 {
717                         TextBox owner;
718                         VScrollBar vscroll;
719                         List<string> items;
720                         int top_item;
721                         int last_item;
722                         internal int page_size;
723                         int item_height;
724                         int highlighted_index = -1;
725                         bool user_defined_size;
726                         bool resizing;
727                         Rectangle resizer_bounds;
728
729                         const int DefaultDropDownItems = 7;
730
731                         public AutoCompleteListBox (TextBox tb)
732                         {
733                                 owner = tb;
734                                 items = new List<string> ();
735                                 item_height = FontHeight + 2;
736
737                                 vscroll = new VScrollBar ();
738                                 vscroll.ValueChanged += VScrollValueChanged;
739                                 Controls.Add (vscroll);
740
741                                 is_visible = false;
742                                 InternalBorderStyle = BorderStyle.FixedSingle;
743                         }
744
745                         protected override CreateParams CreateParams {
746                                 get {
747                                         CreateParams cp = base.CreateParams;
748
749                                         cp.Style ^= (int)WindowStyles.WS_CHILD;
750                                         cp.Style ^= (int)WindowStyles.WS_VISIBLE;
751                                         cp.Style |= (int)WindowStyles.WS_POPUP;
752                                         cp.ExStyle |= (int)WindowExStyles.WS_EX_TOPMOST | (int)WindowExStyles.WS_EX_TOOLWINDOW;
753                                         return cp;
754                                 }
755                         }
756
757                         public IList<string> Items {
758                                 get {
759                                         return items;
760                                 }
761                         }
762
763                         public int HighlightedIndex {
764                                 get {
765                                         return highlighted_index;
766                                 }
767                                 set {
768                                         if (value == highlighted_index)
769                                                 return;
770
771                                         if (highlighted_index != -1)
772                                                 Invalidate (GetItemBounds (highlighted_index));
773                                         highlighted_index = value;
774                                         if (highlighted_index != -1)
775                                                 Invalidate (GetItemBounds (highlighted_index));
776
777                                         if (highlighted_index != -1)
778                                                 EnsureVisible (highlighted_index);
779                                 }
780                         }
781
782                         public void Scroll (int lines)
783                         {
784                                 int max = vscroll.Maximum - page_size + 1;
785                                 int val = vscroll.Value + lines;
786                                 if (val > max)
787                                         val = max;
788                                 else if (val < vscroll.Minimum)
789                                         val = vscroll.Minimum;
790
791                                 vscroll.Value = val;
792                         }
793
794                         public void EnsureVisible (int index)
795                         {
796                                 if (index < top_item) {
797                                         vscroll.Value = index;
798                                 } else {
799                                         int max = vscroll.Maximum - page_size + 1;
800                                         int rows = Height / item_height;
801                                         if (index > top_item + rows - 1) {
802                                                 index = index - rows + 1;
803                                                 vscroll.Value = index > max ? max : index;
804                                         }
805                                 }
806                         }
807
808                         internal override bool ActivateOnShow {
809                                 get {
810                                         return false;
811                                 }
812                         }
813
814                         void VScrollValueChanged (object o, EventArgs args)
815                         {
816                                 if (top_item == vscroll.Value)
817                                         return;
818
819                                 top_item = vscroll.Value;
820                                 last_item = GetLastVisibleItem ();
821                                 Invalidate ();
822                         }
823
824                         int GetLastVisibleItem ()
825                         {
826                                 int top_y = Height;
827
828                                 for (int i = top_item; i < items.Count; i++) {
829                                         int pos = i - top_item; // relative to visible area
830                                         if ((pos * item_height) + item_height >= top_y)
831                                                 return i;
832                                 }
833
834                                 return items.Count - 1;
835                         }
836
837                         Rectangle GetItemBounds (int index)
838                         {
839                                 int pos = index - top_item;
840                                 Rectangle bounds = new Rectangle (0, pos * item_height, Width, item_height);
841                                 if (vscroll.Visible)
842                                         bounds.Width -= vscroll.Width;
843
844                                 return bounds;
845                         }
846
847                         int GetItemAt (Point loc)
848                         {
849                                 if (loc.Y > (last_item - top_item) * item_height + item_height)
850                                         return -1;
851
852                                 int retval = loc.Y / item_height;
853                                 retval += top_item;
854
855                                 return retval;
856                         }
857
858                         void LayoutListBox ()
859                         {
860                                 int total_height = items.Count * item_height;
861                                 page_size = Math.Max (Height / item_height, 1);
862                                 last_item = GetLastVisibleItem ();
863
864                                 if (Height < total_height) {
865                                         vscroll.Visible = true;
866                                         vscroll.Maximum = items.Count - 1;
867                                         vscroll.LargeChange = page_size;
868                                         vscroll.Location = new Point (Width - vscroll.Width, 0);
869                                         vscroll.Height = Height - item_height;
870                                 } else
871                                         vscroll.Visible = false;
872
873                                 resizer_bounds = new Rectangle (Width - item_height, Height - item_height,
874                                                 item_height, item_height);
875                         }
876
877                         public void HideListBox (bool set_text)
878                         {
879                                 if (set_text) {
880                                         owner.Text = items [HighlightedIndex];
881                                         owner.SelectAll ();
882                                 }
883
884                                 Capture = false;
885                                 Hide ();
886                         }
887
888                         public void ShowListBox ()
889                         {
890                                 if (!user_defined_size) {
891                                         // This should call the Layout routine for us
892                                         int height = items.Count > DefaultDropDownItems ? DefaultDropDownItems * item_height : 
893                                                 (items.Count + 1) * item_height;
894                                         Size = new Size (owner.Width, height);
895                                 } else
896                                         LayoutListBox ();
897
898                                 vscroll.Value = 0;
899                                 HighlightedIndex = -1;
900
901                                 Show ();
902                                 Invalidate ();
903                         }
904
905                         protected override void OnResize (EventArgs args)
906                         {
907                                 base.OnResize (args);
908
909                                 LayoutListBox ();
910                                 Refresh ();
911                         }
912
913                         protected override void OnMouseDown (MouseEventArgs args)
914                         {
915                                 base.OnMouseDown (args);
916
917                                 if (!resizer_bounds.Contains (args.Location))
918                                         return;
919
920                                 user_defined_size = true;
921                                 resizing = true;
922                                 Capture = true;
923                         }
924
925                         protected override void OnMouseMove (MouseEventArgs args)
926                         {
927                                 base.OnMouseMove (args);
928
929                                 if (resizing) {
930                                         Point mouse_loc = Control.MousePosition;
931                                         Point ctrl_loc = PointToScreen (Point.Empty);
932
933                                         Size new_size = new Size (mouse_loc.X - ctrl_loc.X, mouse_loc.Y - ctrl_loc.Y);
934                                         if (new_size.Height < item_height)
935                                                 new_size.Height = item_height;
936                                         if (new_size.Width < item_height)
937                                                 new_size.Width = item_height;
938
939                                         Size = new_size;
940                                         return;
941                                 }
942
943                                 Cursor = resizer_bounds.Contains (args.Location) ? Cursors.SizeNWSE : Cursors.Default;
944
945                                 int item_idx = GetItemAt (args.Location);
946                                 if (item_idx != -1)
947                                         HighlightedIndex = item_idx;
948                         }
949
950                         protected override void OnMouseUp (MouseEventArgs args)
951                         {
952                                 base.OnMouseUp (args);
953
954                                 int item_idx = GetItemAt (args.Location);
955                                 if (item_idx != -1 && !resizing)
956                                         HideListBox (true);
957
958                                 resizing = false;
959                                 Capture = false;
960                         }
961
962                         internal override void OnPaintInternal (PaintEventArgs args)
963                         {
964                                 Graphics g = args.Graphics;
965                                 Brush brush = ThemeEngine.Current.ResPool.GetSolidBrush (ForeColor);
966
967                                 int highlighted_idx = HighlightedIndex;
968
969                                 int y = 0;
970                                 int last = GetLastVisibleItem ();
971                                 for (int i = top_item; i <= last; i++) {
972                                         Rectangle item_bounds = GetItemBounds (i);
973                                         if (!item_bounds.IntersectsWith (args.ClipRectangle))
974                                                 continue;
975
976                                         if (i == highlighted_idx) {
977                                                 g.FillRectangle (SystemBrushes.Highlight, item_bounds);
978                                                 g.DrawString (items [i], Font, SystemBrushes.HighlightText, item_bounds);
979                                         } else 
980                                                 g.DrawString (items [i], Font, brush, item_bounds);
981
982                                         y += item_height;
983                                 }
984
985                                 ThemeEngine.Current.CPDrawSizeGrip (g, SystemColors.Control, resizer_bounds);
986                         }
987                 }
988 #endif
989         }
990         
991 #if NET_2_0
992         internal class TextBoxAutoCompleteSourceConverter : EnumConverter
993         {
994                 public TextBoxAutoCompleteSourceConverter(Type type)
995                         : base(type)
996                 { }
997
998                 public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
999                 {
1000                         StandardValuesCollection stdv = base.GetStandardValues(context);
1001                         AutoCompleteSource[] arr = new AutoCompleteSource[stdv.Count];
1002                         stdv.CopyTo(arr, 0);
1003                         AutoCompleteSource[] arr2 = Array.FindAll(arr, delegate (AutoCompleteSource value) {
1004                                 // No "ListItems" in a TextBox.
1005                                 return value != AutoCompleteSource.ListItems;
1006                         });
1007                         return new StandardValuesCollection(arr2);
1008                 }
1009         }
1010 #endif
1011 }