- When the textboxes text is updated update our base Control
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ComboBox.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //      Mike Kestner  <mkestner@novell.com>
25 //
26 // NOT COMPLETE
27
28 using System;
29 using System.Drawing;
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Reflection;
33 using System.ComponentModel.Design;
34 using System.ComponentModel.Design.Serialization;
35 using System.Runtime.InteropServices;
36
37
38 namespace System.Windows.Forms
39 {
40
41         [DefaultProperty("Items")]
42         [DefaultEvent("SelectedIndexChanged")]
43         [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44         public class ComboBox : ListControl
45         {
46                 private DrawMode draw_mode = DrawMode.Normal;
47                 private ComboBoxStyle dropdown_style = (ComboBoxStyle)(-1);
48                 private int dropdown_width = -1;                
49                 private int selected_index = -1;
50                 internal ObjectCollection items = null;
51                 private bool suspend_ctrlupdate;
52                 private int maxdrop_items = 8;                  
53                 private bool integral_height = true;
54                 private bool sorted;
55                 private int max_length;
56                 private ComboListBox listbox_ctrl;              
57                 private TextBox textbox_ctrl;
58                 private bool item_height_specified = false;
59                 private int item_height;
60                 private int requested_height = -1;
61                 private Hashtable item_heights;
62                 private bool show_dropdown_button = false;
63                 private ButtonState button_state = ButtonState.Normal;
64                 private bool dropped_down;
65                 private Rectangle text_area;
66                 private Rectangle button_area;
67                 private Rectangle listbox_area;
68                 private const int button_width = 16;
69
70                 [ComVisible(true)]
71                 public class ChildAccessibleObject : AccessibleObject {
72                         private ComboBox        owner;
73                         private IntPtr          handle;
74
75                         public ChildAccessibleObject (ComboBox owner, IntPtr handle) {
76                                 this.owner = owner;
77                                 this.handle = handle;
78                         }
79
80                         public override string Name {
81                                 get {
82                                         return base.Name;
83                                 }
84                         }
85                 }
86
87                 public ComboBox ()
88                 {
89                         items = new ObjectCollection (this);
90                         DropDownStyle = ComboBoxStyle.DropDown;
91                         item_height = FontHeight + 2;
92                         BackColor = ThemeEngine.Current.ColorWindow;
93                         border_style = BorderStyle.None;
94
95                         /* Events */
96                         MouseDown += new MouseEventHandler (OnMouseDownCB);
97                         MouseUp += new MouseEventHandler (OnMouseUpCB);
98                         MouseMove += new MouseEventHandler (OnMouseMoveCB);
99                         KeyDown +=new KeyEventHandler(OnKeyDownCB);
100                 }
101
102                 #region events
103                 
104                 [Browsable (false)]
105                 [EditorBrowsable (EditorBrowsableState.Never)]
106                 public new event EventHandler BackgroundImageChanged {
107                         add { base.BackgroundImageChanged += value; }
108                         remove { base.BackgroundImageChanged -= value; }
109                 }
110                 
111                 public event DrawItemEventHandler DrawItem;             
112                 public event EventHandler DropDown;             
113                 public event EventHandler DropDownStyleChanged;         
114                 public event MeasureItemEventHandler MeasureItem;
115                 
116                 [Browsable (false)]
117                 [EditorBrowsable (EditorBrowsableState.Never)]
118                 public new event PaintEventHandler Paint {
119                         add { base.Paint += value; }
120                         remove { base.Paint -= value; }
121                 }
122                 
123                 public event EventHandler SelectedIndexChanged;         
124                 public event EventHandler SelectionChangeCommitted;
125                 #endregion Events
126
127                 #region Public Properties
128                 public override Color BackColor {
129                         get { return base.BackColor; }
130                         set {
131                                 if (base.BackColor == value)
132                                         return;
133
134                                 base.BackColor = value;
135                                 Refresh ();
136                         }
137                 }
138
139                 [Browsable (false)]
140                 [EditorBrowsable (EditorBrowsableState.Never)]
141                 public override Image BackgroundImage {
142                         get { return base.BackgroundImage; }
143                         set {
144                                 if (base.BackgroundImage == value)
145                                         return;
146
147                                 base.BackgroundImage = value;
148                                 Refresh ();
149                         }
150                 }
151
152                 protected override CreateParams CreateParams {
153                         get { return base.CreateParams;}
154                 }
155
156                 protected override Size DefaultSize {
157                         get { return new Size (121, 21); }
158                 }
159
160                 [RefreshProperties(RefreshProperties.Repaint)]
161                 [DefaultValue (DrawMode.Normal)]
162                 public DrawMode DrawMode {
163                         get { return draw_mode; }
164
165                         set {
166                                 if (!Enum.IsDefined (typeof (DrawMode), value))
167                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
168
169                                 if (draw_mode == value)
170                                         return;
171
172                                 if (draw_mode == DrawMode.OwnerDrawVariable)
173                                         item_heights = null;
174                                 draw_mode = value;
175                                 if (draw_mode == DrawMode.OwnerDrawVariable)
176                                         item_heights = new Hashtable ();
177                                 Refresh ();
178                         }
179                 }
180
181                 [DefaultValue (ComboBoxStyle.DropDown)]
182                 [RefreshProperties(RefreshProperties.Repaint)]
183                 public ComboBoxStyle DropDownStyle {
184                         get { return dropdown_style; }
185
186                         set {
187                 
188                                 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
189                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
190
191                                 if (dropdown_style == value)
192                                         return;                                 
193                                                                         
194                                 if (dropdown_style == ComboBoxStyle.Simple) {
195                                         if (listbox_ctrl != null) {                                             
196                                                 Controls.RemoveImplicit (listbox_ctrl);
197                                                 listbox_ctrl.Dispose ();                                                
198                                                 listbox_ctrl = null;
199                                         }
200                                 }
201
202                                 dropdown_style = value;                                 
203                                 
204                                 if (dropdown_style == ComboBoxStyle.DropDownList && textbox_ctrl != null) {
205                                         Controls.RemoveImplicit (textbox_ctrl);
206                                         textbox_ctrl.Dispose ();                                                
207                                         textbox_ctrl = null;                                            
208                                 }                               
209
210                                 if (dropdown_style == ComboBoxStyle.Simple) {
211                                         show_dropdown_button = false;                                   
212                                         
213                                         CreateComboListBox ();
214
215                                         if (IsHandleCreated)
216                                                 Controls.AddImplicit (listbox_ctrl);
217                                 } else {
218                                         show_dropdown_button = true;
219                                         button_state = ButtonState.Normal;
220                                 }                               
221         
222                                 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
223                                         textbox_ctrl = new FixedSizeTextBox ();
224                                         if (SelectedItem != null)
225                                                 textbox_ctrl.Text = GetItemText (SelectedItem);
226                                         textbox_ctrl.BorderStyle = BorderStyle.None;
227                                         textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
228                                         textbox_ctrl.KeyPress += new KeyPressEventHandler(textbox_ctrl_KeyPress);
229                                         textbox_ctrl.KeyDown += new KeyEventHandler (OnKeyDownCB);
230                                         textbox_ctrl.GotFocus += new EventHandler(textbox_ctrl_GotFocus);
231                                         textbox_ctrl.LostFocus += new EventHandler(textbox_ctrl_LostFocus);
232                                         textbox_ctrl.MouseDown += new MouseEventHandler(textbox_ctrl_MouseDown);
233                                         textbox_ctrl.MouseMove += new MouseEventHandler(textbox_ctrl_MouseMove);
234                                         textbox_ctrl.MouseUp += new MouseEventHandler(textbox_ctrl_MouseUp);
235
236                                         if (IsHandleCreated == true) {
237                                                 Controls.AddImplicit (textbox_ctrl);
238                                         }
239                                 }
240                                 
241                                 OnDropDownStyleChanged (EventArgs.Empty);
242                                 
243                                 Layout ();
244                                 UpdateBounds ();
245                                 Refresh ();
246                         }
247                 }
248
249                 public int DropDownWidth {
250                         get { 
251                                 if (dropdown_width == -1)
252                                         return Width;
253                                         
254                                 return dropdown_width; 
255                         }
256                         set {
257                                 if (dropdown_width == value)
258                                         return;
259                                         
260                                 if (value < 1)
261                                         throw new ArgumentException ("The DropDownWidth value is less than one");
262
263                                 dropdown_width = value;                         
264                         }
265                 }
266                 
267                 [Browsable (false)]
268                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]              
269                 public bool DroppedDown {
270                         get { 
271                                 if (dropdown_style == ComboBoxStyle.Simple)                             
272                                         return true;
273                                 
274                                 return dropped_down;
275                         }
276                         set {
277                                 if (dropdown_style == ComboBoxStyle.Simple || dropped_down == value)
278                                         return;
279                                         
280                                 if (value) 
281                                         DropDownListBox ();
282                                 else
283                                         listbox_ctrl.Hide ();
284                         }
285                 }               
286
287                 public override bool Focused {
288                         get { return base.Focused; }
289                 }
290
291                 public override Color ForeColor {
292                         get { return base.ForeColor; }
293                         set {
294                                 if (base.ForeColor == value)
295                                         return;
296
297                                 base.ForeColor = value;
298                                 Refresh ();
299                         }
300                 }
301
302                 [DefaultValue (true)]
303                 [Localizable (true)]            
304                 public bool IntegralHeight {
305                         get { return integral_height; }
306                         set {
307                                 if (integral_height == value)
308                                         return;
309
310                                 integral_height = value;
311                                 UpdateBounds ();
312                                 Refresh ();
313                         }
314                 }
315
316                 [Localizable (true)]
317                 public int ItemHeight {
318                         get {
319                                 if (item_height == -1) {
320                                         SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
321                                         item_height = (int) sz.Height;
322                                 }
323                                 return item_height;
324                         }
325                         set {
326                                 if (value < 0)
327                                         throw new ArgumentException ("The item height value is less than zero");
328
329                                 item_height_specified = true;
330                                 item_height = value;
331                                 if (IntegralHeight)
332                                         UpdateBounds ();
333                                 Layout ();
334                                 Refresh ();
335                         }
336                 }
337
338                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
339                 [Localizable (true)]
340                 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]                
341                 public ComboBox.ObjectCollection Items {
342                         get { return items; }
343                 }
344
345                 [DefaultValue (8)]
346                 [Localizable (true)]
347                 public int MaxDropDownItems {
348                         get { return maxdrop_items; }
349                         set {
350                                 if (maxdrop_items == value)
351                                         return;
352
353                                 maxdrop_items = value;
354                         }
355                 }
356
357                 [DefaultValue (0)]
358                 [Localizable (true)]
359                 public int MaxLength {
360                         get { return max_length; }
361                         set {
362                                 if (max_length == value)
363                                         return;
364
365                                 max_length = value;
366                                 
367                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
368                                         
369                                         if (value < 0) {
370                                                 value = 0;
371                                         }
372                                         
373                                         textbox_ctrl.MaxLength = value;
374                                 }                       
375                         }
376                 }
377
378                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
379                 [Browsable (false)]             
380                 public int PreferredHeight {
381                         get {
382                                 return ItemHeight + 5;
383                         }
384                 }
385
386                 [Browsable (false)]
387                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
388                 public override int SelectedIndex {
389                         get { return selected_index; }
390                         set {
391                                 if (value <= -2 || value >= Items.Count)
392                                         throw new ArgumentOutOfRangeException ("Index of out range");
393
394                                 selected_index = value;
395                                 
396                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
397                                         if (selected_index == -1)
398                                                 SetControlText (String.Empty);
399                                         else {
400                                                 SetControlText (GetItemText (items [value]));
401                                                 SelectAll ();
402                                         }
403                                 }
404
405                                 OnSelectedValueChanged (new EventArgs ());
406                                 OnSelectedIndexChanged  (new EventArgs ());
407                                 OnSelectedItemChanged (new EventArgs ());
408
409                                 if (DropDownStyle == ComboBoxStyle.DropDownList)
410                                         Refresh ();
411
412                                 if (listbox_ctrl != null)
413                                         listbox_ctrl.HighlightedIndex = value;
414                         }
415                 }
416
417                 [Browsable (false)]
418                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
419                 [Bindable(true)]
420                 public object SelectedItem {
421                         get {
422                                 if (selected_index == -1)
423                                         return null;
424                                 return items [selected_index];
425                         }
426                         set {                           
427                                 if (items [selected_index] == value)
428                                         return;
429
430                                 if (value == null)
431                                         SelectedIndex = -1;
432                                 else
433                                         SelectedIndex = items.IndexOf (value);
434                         }
435                 }
436                 
437                 [Browsable (false)]
438                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
439                 public string SelectedText {
440                         get {
441                                 if (dropdown_style == ComboBoxStyle.DropDownList)
442                                         return "";
443                                         
444                                 return textbox_ctrl.SelectedText;
445                         }
446                         set {
447                                 if (dropdown_style == ComboBoxStyle.DropDownList)
448                                         return;
449                                 
450                                 textbox_ctrl.SelectedText = value;
451                         }
452                 }
453
454                 [Browsable (false)]
455                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
456                 public int SelectionLength {
457                         get {
458                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
459                                         return 0;
460                                 
461                                 return textbox_ctrl.SelectionLength;
462                         }
463                         set {
464                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
465                                         return;
466                                         
467                                 if (textbox_ctrl.SelectionLength == value)
468                                         return;
469                                         
470                                 textbox_ctrl.SelectionLength = value;
471                         }
472                 }
473
474                 [Browsable (false)]
475                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
476                 public int SelectionStart {
477                         get { 
478                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
479                                         return 0;                                       
480                                 
481                                 return textbox_ctrl.SelectionStart;                             
482                         }
483                         set {
484                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
485                                         return;
486                                 
487                                 if (textbox_ctrl.SelectionStart == value)
488                                         return;                                 
489                                 
490                                 textbox_ctrl.SelectionStart = value;
491                         }
492                 }
493
494                 [DefaultValue (false)]
495                 public bool Sorted {
496                         get { return sorted; }
497
498                         set {
499                                 if (sorted == value)
500                                         return;
501
502                                 sorted = value;
503                         }
504                 }
505
506                 [Bindable (true)]
507                 [Localizable (true)]
508                 public override string Text {
509                         get {
510                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
511                                         if (textbox_ctrl != null) {
512                                                 return textbox_ctrl.Text;
513                                         }
514                                 }
515
516                                 if (SelectedItem != null)
517                                         return GetItemText (SelectedItem);
518                                                                 
519                                 return base.Text;                               
520                         }
521                         set {                           
522                                 if (value == null) {
523                                         SelectedIndex = -1;
524                                         return;
525                                 }
526                                 
527                                 int index = FindString (value);
528                                 
529                                 if (index != -1) {
530                                         SelectedIndex = index;
531                                 }
532                                 
533                                 if (dropdown_style != ComboBoxStyle.DropDownList)
534                                         textbox_ctrl.Text = GetItemText (value);
535                         }
536                 }
537
538                 #endregion Public Properties
539
540                 #region Public Methods
541                 protected virtual void AddItemsCore (object[] value)
542                 {
543                         
544                 }
545
546                 public void BeginUpdate ()
547                 {
548                         suspend_ctrlupdate = true;
549                 }
550
551                 protected override void Dispose (bool disposing)
552                 {                                               
553                         if (disposing) {
554                                 if (listbox_ctrl != null) {
555                                         listbox_ctrl.Dispose ();
556                                         Controls.RemoveImplicit (listbox_ctrl);
557                                         listbox_ctrl = null;
558                                 }                       
559                         
560                                 if (textbox_ctrl != null) {
561                                         Controls.RemoveImplicit (textbox_ctrl);
562                                         textbox_ctrl.Dispose ();
563                                         textbox_ctrl = null;
564                                 }                       
565                         }
566                         
567                         base.Dispose (disposing);
568                 }
569
570                 public void EndUpdate ()
571                 {
572                         suspend_ctrlupdate = false;
573                         UpdatedItems ();
574                         Refresh ();
575                 }
576
577                 public int FindString (string s)
578                 {
579                         return FindString (s, -1);
580                 }
581
582                 public int FindString (string s, int startIndex)
583                 {
584                         if (Items.Count == 0) 
585                                 return -1; // No exception throwing if empty
586
587                         if (startIndex < -1 || startIndex >= Items.Count - 1)
588                                 throw new  ArgumentOutOfRangeException ("Index of out range");
589
590                         startIndex++;
591                         for (int i = startIndex; i < Items.Count; i++) {
592                                 if ((GetItemText (Items[i])).StartsWith (s))
593                                         return i;
594                         }
595
596                         return -1;
597                 }
598
599                 public int FindStringExact (string s)
600                 {
601                         return FindStringExact (s, -1);
602                 }
603
604                 public int FindStringExact (string s, int startIndex)
605                 {
606                         if (Items.Count == 0) 
607                                 return -1; // No exception throwing if empty
608
609                         if (startIndex < -1 || startIndex >= Items.Count - 1)
610                                 throw new ArgumentOutOfRangeException ("Index of out range");
611
612                         startIndex++;
613                         for (int i = startIndex; i < Items.Count; i++) {
614                                 if ((GetItemText (Items[i])).Equals (s))
615                                         return i;
616                         }
617
618                         return -1;
619                 }
620
621                 public int GetItemHeight (int index)
622                 {       
623                         if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated) {
624
625                                 if (index < 0 || index >= Items.Count )
626                                         throw new ArgumentOutOfRangeException ("The item height value is less than zero");
627                                 
628                                 object item = Items [index];
629                                 if (item_heights.Contains (item))
630                                         return (int) item_heights [item];
631                                 
632                                 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
633                                 OnMeasureItem (args);
634                                 item_heights [item] = args.ItemHeight;
635                                 return args.ItemHeight;
636                         }
637
638                         return ItemHeight;
639                 }
640
641                 protected override bool IsInputKey (Keys keyData)
642                 {
643                         switch (keyData) {
644                         case Keys.Up:
645                         case Keys.Down:
646                         case Keys.PageUp:
647                         case Keys.PageDown:                     
648                                 return true;
649                         
650                         default:                                        
651                                 return false;
652                         }
653                 }
654
655                 protected override void OnBackColorChanged (EventArgs e)
656                 {
657                         base.OnBackColorChanged (e);
658                 }
659
660                 protected override void OnDataSourceChanged (EventArgs e)
661                 {
662                         base.OnDataSourceChanged (e);
663                         BindDataItems (items);
664                         
665                         if (DataSource == null || DataManager == null) {
666                                 SelectedIndex = -1;
667                         } 
668                         else {
669                                 SelectedIndex = DataManager.Position;
670                         }
671                 }
672
673                 protected override void OnDisplayMemberChanged (EventArgs e)
674                 {
675                         base.OnDisplayMemberChanged (e);
676
677                         if (DataManager == null || !IsHandleCreated)
678                                return;
679
680                         BindDataItems (items);
681                         SelectedIndex = DataManager.Position;
682                 }
683
684                 protected virtual void OnDrawItem (DrawItemEventArgs e)
685                 {
686                         switch (DrawMode) {
687                         case DrawMode.OwnerDrawFixed:
688                         case DrawMode.OwnerDrawVariable:
689                                 if (DrawItem != null)
690                                         DrawItem (this, e);
691                                 break;
692                         default:
693                                 ThemeEngine.Current.DrawComboBoxItem (this, e);
694                                 break;
695                         }
696                 }               
697
698                 protected virtual void OnDropDown (EventArgs e)
699                 {
700                         if (DropDown != null)
701                                 DropDown (this, e);
702                 }
703
704                 protected virtual void OnDropDownStyleChanged (EventArgs e)
705                 {
706                         if (DropDownStyleChanged != null)
707                                 DropDownStyleChanged (this, e);
708                 }
709
710                 protected override void OnFontChanged (EventArgs e)
711                 {
712                         base.OnFontChanged (e);
713
714                         if (textbox_ctrl != null)
715                                 textbox_ctrl.Font = Font;
716                         
717                         if (!item_height_specified) {
718                                 SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font);
719                                 item_height = (int) sz.Height;
720                         }
721
722                         if (IntegralHeight)
723                                 UpdateBounds ();
724
725                         Layout ();
726                 }
727
728                 protected override void OnForeColorChanged (EventArgs e)
729                 {
730                         base.OnForeColorChanged (e);
731                 }
732
733                 [EditorBrowsable(EditorBrowsableState.Advanced)]                
734                 protected override void OnGotFocus (EventArgs e) {                      
735                         Invalidate ();
736
737                         if (dropdown_style == ComboBoxStyle.Simple)
738                                 listbox_ctrl.Focus ();
739                         else if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl != null)
740                                 textbox_ctrl.Focus ();
741                         base.OnGotFocus (e);
742                 }
743
744                 [EditorBrowsable(EditorBrowsableState.Advanced)]                
745                 protected override void OnLostFocus (EventArgs e) {                     
746                         base.OnLostFocus (e);
747                 }               
748
749                 protected override void OnHandleCreated (EventArgs e)
750                 {
751                         base.OnHandleCreated (e);
752
753                         if (listbox_ctrl != null)
754                                 Controls.AddImplicit (listbox_ctrl);
755                         
756                         if (textbox_ctrl != null)
757                                 Controls.AddImplicit (textbox_ctrl);
758
759                         Layout ();
760                 }
761
762                 protected override void OnHandleDestroyed (EventArgs e)
763                 {
764                         base.OnHandleDestroyed (e);
765                 }
766
767                 protected override void OnKeyPress (KeyPressEventArgs e)
768                 {
769                         int index= FindStringCaseInsensitive (e.KeyChar.ToString (), SelectedIndex + 1);
770                         if (index == -1)
771                                 return;
772                         SelectedIndex = index;
773
774                         base.OnKeyPress (e);
775                 }
776
777                 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
778                 {
779                         if (MeasureItem != null)
780                                 MeasureItem (this, e);
781                 }
782
783                 protected override void OnParentBackColorChanged (EventArgs e)
784                 {
785                         base.OnParentBackColorChanged (e);
786                 }
787
788                 protected override void OnResize (EventArgs e)
789                 {                       
790                         Layout ();
791                         if (listbox_ctrl != null)
792                                 listbox_ctrl.CalcListBoxArea ();
793                 }
794
795                 protected override void OnSelectedIndexChanged (EventArgs e)
796                 {
797                         base.OnSelectedIndexChanged (e);
798
799                         if (SelectedIndexChanged != null)
800                                 SelectedIndexChanged (this, e);
801                 }
802
803                 protected virtual void OnSelectedItemChanged (EventArgs e)
804                 {
805                         
806                 }
807
808                 protected override void OnSelectedValueChanged (EventArgs e)
809                 {
810                         base.OnSelectedValueChanged (e);
811                 }
812
813                 protected virtual void OnSelectionChangeCommitted (EventArgs e)
814                 {
815                         if (SelectionChangeCommitted != null)
816                                 SelectionChangeCommitted (this, e);
817                 }
818
819                 protected override void RefreshItem (int index)
820                 {
821                         if (index < 0 || index >= Items.Count)
822                                 throw new ArgumentOutOfRangeException ("Index of out range");
823                                 
824                         if (draw_mode == DrawMode.OwnerDrawVariable)
825                                 item_heights.Remove (Items [index]);
826                 }
827
828                 public void Select (int start, int length)
829                 {
830                         if (start < 0)
831                                 throw new ArgumentException ("Start cannot be less than zero");
832                                 
833                         if (length < 0)
834                                 throw new ArgumentException ("length cannot be less than zero");
835                                 
836                         if (dropdown_style == ComboBoxStyle.DropDownList)
837                                 return;
838                                 
839                         textbox_ctrl.Select (start, length);
840                 }
841
842                 public void SelectAll ()
843                 {
844                         if (dropdown_style == ComboBoxStyle.DropDownList)
845                                 return;
846                                 
847                         textbox_ctrl.SelectAll ();
848                 }               
849
850                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
851                 {                       
852                         if ((specified & BoundsSpecified.Height) != 0) {
853                                 requested_height = height;
854
855                                 if (DropDownStyle == ComboBoxStyle.Simple && height > PreferredHeight) {
856                                         if (IntegralHeight) {
857                                                 int border = ThemeEngine.Current.Border3DSize.Height;
858                                                 int lb_height = height - PreferredHeight - 2;
859                                                 if (lb_height - 2 * border > ItemHeight) {
860                                                         int partial = (lb_height - 2 * border) % ItemHeight;
861                                                         height -= partial;
862                                                 } else
863                                                         height = PreferredHeight;
864                                         }
865                                 } else
866                                         height = PreferredHeight;
867                         }
868
869                         base.SetBoundsCore (x, y, width, height, specified);
870                 }
871
872                 protected override void SetItemCore (int index, object value)
873                 {
874                         if (index < 0 || index >= Items.Count)
875                                 return;
876
877                         Items[index] = value;
878                 }
879
880                 protected override void SetItemsCore (IList value)
881                 {
882                         BeginUpdate ();
883                         try {
884                                 Items.Clear ();
885                                 Items.AddRange (value);
886                         } finally {
887                                 EndUpdate ();
888                         }
889                 }
890
891                 public override string ToString ()
892                 {
893                         return base.ToString () + ", Items.Count:" + Items.Count;
894                 }
895
896                 protected override void WndProc (ref Message m)
897                 {
898                         switch ((Msg) m.Msg) {
899                         case Msg.WM_MOUSE_LEAVE:
900                                 Point location = PointToClient (Control.MousePosition);
901                                 if (ClientRectangle.Contains (location))
902                                         return;
903                                 break;
904                         default:
905                                 break;
906                         }
907                         base.WndProc (ref m);
908                 }
909
910                 #endregion Public Methods
911
912                 #region Private Methods
913
914                 internal override bool InternalCapture {
915                         get { return Capture; }
916                         set {}
917                 }
918
919                 private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e) 
920                 {
921                         OnKeyPress (e);
922                 }
923                 
924                 private void textbox_ctrl_GotFocus(object sender, EventArgs e )
925                 {
926                         OnGotFocus(e);
927                 }
928                 
929                 private void textbox_ctrl_LostFocus(object sender, EventArgs e )
930                 {
931                         OnLostFocus(e);
932                 }
933                 
934                 private void textbox_ctrl_MouseDown(object sender, MouseEventArgs e )
935                 {
936                         OnMouseDown(e);
937                 }
938                 
939                 private void textbox_ctrl_MouseMove(object sender, MouseEventArgs e )
940                 {
941                         OnMouseMove(e);
942                 }
943                 
944                 private void textbox_ctrl_MouseUp(object sender, MouseEventArgs e )
945                 {
946                         OnMouseUp(e);
947                 }
948                 
949                 void Layout ()
950                 {                       
951                         int border = ThemeEngine.Current.Border3DSize.Width;
952
953                         text_area = ClientRectangle;
954                         text_area.Height = PreferredHeight;
955                         
956                         listbox_area = ClientRectangle;
957                         listbox_area.Y = text_area.Bottom + 3;
958                         listbox_area.Height -= (text_area.Height + 2);
959
960                         Rectangle prev_button_area = button_area;
961
962                         if (DropDownStyle == ComboBoxStyle.Simple)
963                                 button_area = Rectangle.Empty;
964                         else {
965                                 button_area = text_area;
966                                 button_area.X = text_area.Right - button_width - border;
967                                 button_area.Y = text_area.Y + border;
968                                 button_area.Width = button_width;
969                                 button_area.Height = text_area.Height - 2 * border;
970                         }
971
972                         if (button_area != prev_button_area) {
973                                 prev_button_area.Y -= border;
974                                 prev_button_area.Width += border;
975                                 prev_button_area.Height += 2 * border;
976                                 Invalidate (prev_button_area);
977                                 Invalidate (button_area);
978                         }
979
980                         if (textbox_ctrl != null) {
981                                 textbox_ctrl.Location = new Point (text_area.X + border, text_area.Y + border);
982                                 textbox_ctrl.Width = text_area.Width - button_area.Width - border * 2;
983                                 textbox_ctrl.Height = text_area.Height - border * 2;
984                         }
985
986                         if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
987                                 listbox_ctrl.Location = listbox_area.Location;
988                                 listbox_ctrl.CalcListBoxArea ();
989                         }
990                 }
991
992                 private void CreateComboListBox ()
993                 {                       
994                         listbox_ctrl = new ComboListBox (this);                 
995                         if (selected_index != -1)
996                                 listbox_ctrl.HighlightedIndex = selected_index;
997                 }
998                 
999                 internal void Draw (Rectangle clip, Graphics dc)
1000                 {                               
1001                         Theme theme = ThemeEngine.Current;
1002
1003                         if (DropDownStyle == ComboBoxStyle.Simple)
1004                                 dc.FillRectangle (theme.ResPool.GetSolidBrush (Parent.BackColor), ClientRectangle);
1005
1006                         if (clip.IntersectsWith (text_area))
1007                                 ControlPaint.DrawBorder3D (dc, text_area, Border3DStyle.Sunken);
1008
1009                         int border = theme.Border3DSize.Width;
1010
1011                         // No edit control, we paint the edit ourselves
1012                         if (dropdown_style == ComboBoxStyle.DropDownList) {
1013                                 DrawItemState state = DrawItemState.None;
1014                                 Rectangle item_rect = text_area;
1015                                 item_rect.X += border;
1016                                 item_rect.Y += border;
1017                                 item_rect.Width -= (button_area.Width + 2 * border);                            
1018                                 item_rect.Height -= 2 * border;                         
1019                                                                 
1020                                 if (has_focus) {
1021                                         state = DrawItemState.Selected;
1022                                         state |= DrawItemState.Focus;
1023                                 }
1024                                 
1025                                 state |= DrawItemState.ComboBoxEdit;                            
1026                                 OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, ForeColor, BackColor));
1027                         }                                               
1028                         
1029                         if (show_dropdown_button) {
1030                                 dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area);
1031
1032                                 if (!is_enabled)
1033                                         button_state = ButtonState.Inactive;
1034                                 
1035                                 theme.CPDrawComboButton (dc, button_area, button_state);
1036                         }                       
1037                 }
1038
1039                 internal void DropDownListBox ()
1040                 {
1041                         if (DropDownStyle == ComboBoxStyle.Simple)
1042                                 return;                 
1043                         
1044                         if (listbox_ctrl == null)
1045                                 CreateComboListBox ();
1046
1047                         listbox_ctrl.Location = PointToScreen (new Point (text_area.X, text_area.Y + text_area.Height));
1048                                                 
1049                         if (listbox_ctrl.ShowWindow ())                                 
1050                                 dropped_down = true;                                    
1051                         
1052                         button_state = ButtonState.Pushed;                              
1053                         if (dropdown_style == ComboBoxStyle.DropDownList)
1054                                 Invalidate (text_area);
1055
1056                         OnDropDown (EventArgs.Empty);
1057                 }
1058                 
1059                 internal void DropDownListBoxFinished ()
1060                 {
1061                         if (DropDownStyle == ComboBoxStyle.Simple)
1062                                 return;                 
1063                                 
1064                         button_state = ButtonState.Normal;
1065                         Invalidate (button_area);
1066                         dropped_down = false;
1067                 }
1068                 
1069                 private int FindStringCaseInsensitive (string search)
1070                 {                       
1071                         if (search.Length == 0) {
1072                                 return -1;
1073                         }
1074                         
1075                         for (int i = 0; i < Items.Count; i++) 
1076                         {                               
1077                                 if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0)
1078                                         return i;
1079                         }
1080
1081                         return -1;
1082                 }
1083
1084                 internal int FindStringCaseInsensitive (string search, int start_index)
1085                 {                       
1086                         if (search.Length == 0) {
1087                                 return -1;
1088                         }
1089                         
1090                         for (int i = 0; i < Items.Count; i++) {
1091                                 int index = (i + start_index) % Items.Count;
1092                                 if (String.Compare (GetItemText (Items [index]), 0, search, 0, search.Length, true) == 0)
1093                                         return index;
1094                         }
1095
1096                         return -1;
1097                 }
1098
1099                 private void OnKeyDownCB(object sender, KeyEventArgs e)
1100                 {
1101                         if (Items.Count == 0)
1102                                 return;
1103
1104                         switch (e.KeyCode) 
1105                         {                       
1106                                 case Keys.Up:
1107                                         SelectedIndex = Math.Max(SelectedIndex-1, 0);
1108                                         break;                          
1109         
1110                                 case Keys.Down:                 
1111                                         SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1);
1112                                         break;
1113                                 
1114                                 case Keys.PageUp:
1115                                         if (listbox_ctrl != null)
1116                                                 SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0);
1117                                         break;                          
1118         
1119                                 case Keys.PageDown:             
1120                                         if (listbox_ctrl != null)               
1121                                                 SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1);
1122                                         break;
1123                                 
1124                                 default:
1125                                         break;
1126                         }
1127                 }
1128                 
1129                 void OnMouseDownCB (object sender, MouseEventArgs e)
1130                 {                       
1131                         Rectangle area;
1132                         if (DropDownStyle == ComboBoxStyle.DropDownList)
1133                                 area = ClientRectangle;
1134                         else
1135                                 area = button_area;
1136
1137                         if (area.Contains (e.X, e.Y)) {
1138                                 DropDownListBox ();                                     
1139                                 Invalidate (button_area);
1140                                 Update ();
1141                         }
1142                         Capture = true;
1143                 }
1144
1145                 void OnMouseMoveCB (object sender, MouseEventArgs e)
1146                 {                       
1147                         if (DropDownStyle == ComboBoxStyle.Simple)
1148                                 return;
1149
1150                         if (listbox_ctrl != null && listbox_ctrl.Visible) {
1151                                 Point location = listbox_ctrl.PointToClient (Control.MousePosition);
1152                                 if (listbox_ctrl.ClientRectangle.Contains (location))
1153                                         listbox_ctrl.Capture = true;
1154                         }
1155                 }
1156
1157                 void OnMouseUpCB (object sender, MouseEventArgs e)
1158                 {
1159                         Capture = false;
1160                         OnClick (EventArgs.Empty);
1161
1162                         if (dropped_down)
1163                                 listbox_ctrl.Capture = true;
1164                 }
1165
1166                 internal override void OnPaintInternal (PaintEventArgs pevent)
1167                 {
1168                         if (suspend_ctrlupdate)
1169                                 return;
1170                                 
1171                         Draw (ClientRectangle, pevent.Graphics);                        
1172                 }
1173                 
1174                 private void OnTextChangedEdit (object sender, EventArgs e)
1175                 {
1176                         int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1177                         
1178                         if (item == -1 && listbox_ctrl != null) {
1179                                 listbox_ctrl.SetTopItem (item);
1180                                 listbox_ctrl.HighlightedIndex = item;
1181                         }
1182
1183                         base.Text = textbox_ctrl.Text;
1184                 }
1185                 
1186                 internal void SetControlText (string s)
1187                 {               
1188                         textbox_ctrl.Text = s;
1189                 }
1190                 
1191                 void UpdateBounds ()
1192                 {
1193                         if (requested_height != -1)
1194                                 SetBoundsCore (0, 0, 0, requested_height, BoundsSpecified.Height);
1195                 }
1196
1197                 private void UpdatedItems ()
1198                 {
1199                         if (listbox_ctrl != null) {
1200                                 listbox_ctrl.UpdateLastVisibleItem ();
1201                                 listbox_ctrl.CalcListBoxArea ();
1202                                 listbox_ctrl.Refresh ();
1203                         }
1204                 }
1205
1206                 #endregion Private Methods
1207
1208                 [ListBindableAttribute (false)]
1209                 public class ObjectCollection : IList, ICollection, IEnumerable
1210                 {
1211
1212                         private ComboBox owner;
1213                         internal ArrayList object_items = new ArrayList ();
1214
1215                         public ObjectCollection (ComboBox owner)
1216                         {
1217                                 this.owner = owner;
1218                         }
1219
1220                         #region Public Properties
1221                         public int Count {
1222                                 get { return object_items.Count; }
1223                         }
1224
1225                         public bool IsReadOnly {
1226                                 get { return false; }
1227                         }
1228
1229                         [Browsable (false)]
1230                         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1231                         public virtual object this [int index] {
1232                                 get {
1233                                         if (index < 0 || index >= Count)
1234                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1235
1236                                         return object_items[index];
1237                                 }
1238                                 set {
1239                                         if (index < 0 || index >= Count)
1240                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1241
1242                                         object_items[index] = value;
1243                                 }
1244                         }
1245
1246                         bool ICollection.IsSynchronized {
1247                                 get { return false; }
1248                         }
1249
1250                         object ICollection.SyncRoot {
1251                                 get { return this; }
1252                         }
1253
1254                         bool IList.IsFixedSize {
1255                                 get { return false; }
1256                         }
1257
1258                         #endregion Public Properties
1259                         
1260                         #region Private Properties                      
1261                         internal ArrayList ObjectItems {
1262                                 get { return object_items;}
1263                                 set {
1264                                         object_items = value;
1265                                 }
1266                         }
1267                         
1268                         #endregion Private Properties
1269
1270                         #region Public Methods
1271                         public int Add (object item)
1272                         {
1273                                 int idx;
1274
1275                                 idx = AddItem (item);
1276                                 owner.UpdatedItems ();
1277                                 return idx;
1278                         }
1279
1280                         public void AddRange (object[] items)
1281                         {
1282                                 foreach (object mi in items)
1283                                         AddItem (mi);
1284                                         
1285                                 owner.UpdatedItems ();
1286                         }
1287
1288                         public void Clear ()
1289                         {
1290                                 owner.selected_index = -1;
1291                                 object_items.Clear ();
1292                                 owner.UpdatedItems ();
1293                                 owner.Refresh ();
1294                         }
1295                         
1296                         public bool Contains (object obj)
1297                         {
1298                                 return object_items.Contains (obj);
1299                         }
1300
1301                         public void CopyTo (object[] dest, int arrayIndex)
1302                         {
1303                                 object_items.CopyTo (dest, arrayIndex);
1304                         }
1305
1306                         void ICollection.CopyTo (Array dest, int index)
1307                         {
1308                                 object_items.CopyTo (dest, index);
1309                         }
1310
1311                         public IEnumerator GetEnumerator ()
1312                         {
1313                                 return object_items.GetEnumerator ();
1314                         }
1315
1316                         int IList.Add (object item)
1317                         {
1318                                 return Add (item);
1319                         }
1320
1321                         public int IndexOf (object value)
1322                         {
1323                                 return object_items.IndexOf (value);
1324                         }
1325
1326                         public void Insert (int index,  object item)
1327                         {
1328                                 if (index < 0 || index > Count)
1329                                         throw new ArgumentOutOfRangeException ("Index of out range");                                   
1330                                 
1331                                 owner.BeginUpdate ();
1332                                 
1333                                 object_items.Insert (index, item);
1334                                                                                                 
1335                                 owner.EndUpdate ();     // Calls UpdatedItems
1336                         }
1337
1338                         public void Remove (object value)
1339                         {                               
1340                                 if (IndexOf (value) == owner.SelectedIndex)
1341                                         owner.SelectedItem = null;
1342                                 
1343                                 RemoveAt (IndexOf (value));                             
1344                                 
1345                         }
1346
1347                         public void RemoveAt (int index)
1348                         {
1349                                 if (index < 0 || index >= Count)
1350                                         throw new ArgumentOutOfRangeException ("Index of out range");
1351                                         
1352                                 if (index == owner.SelectedIndex)
1353                                         owner.SelectedItem = null;
1354
1355                                 object_items.RemoveAt (index);
1356                                 owner.UpdatedItems ();
1357                         }
1358                         #endregion Public Methods
1359
1360                         #region Private Methods
1361                         private int AddItem (object item)
1362                         {
1363                                 int cnt = object_items.Count;
1364                                 object_items.Add (item);
1365                                 return cnt;
1366                         }
1367                         
1368                         internal void AddRange (IList items)
1369                         {
1370                                 foreach (object mi in items)
1371                                         AddItem (mi);
1372                                                                                 
1373                                 owner.UpdatedItems ();
1374                         }
1375
1376                         #endregion Private Methods
1377                 }
1378
1379                 internal class ComboListBox : Control
1380                 {
1381                         private ComboBox owner;                 
1382                         private VScrollBarLB vscrollbar_ctrl;
1383                         private int top_item;                   /* First item that we show the in the current page */
1384                         private int last_item;                  /* Last visible item */
1385                         internal int page_size;                 /* Number of listbox items per page */
1386                         private Rectangle textarea_drawable;    /* Rectangle of the drawable text area */
1387                         
1388                         internal enum ItemNavigation
1389                         {
1390                                 First,
1391                                 Last,
1392                                 Next,
1393                                 Previous,
1394                                 NextPage,
1395                                 PreviousPage,
1396                         }
1397                         
1398                         class VScrollBarLB : VScrollBar
1399                         {
1400                                 public VScrollBarLB ()
1401                                 {                                       
1402                                 }
1403                                 
1404                                 internal override bool InternalCapture {
1405                                         get { return Capture; }
1406                                         set { }
1407                                 }
1408
1409                                 public bool FireMouseDown (MouseEventArgs e) 
1410                                 {
1411                                         if (Visible) {
1412                                                 e = TranslateEvent (e);
1413                                                 if (ClientRectangle.Contains (e.X, e.Y)) {
1414                                                         OnMouseDown (e);
1415                                                         return true;
1416                                                 }
1417                                         }
1418                                         return false;
1419                                 }       
1420                                 
1421                                 public void FireMouseUp (MouseEventArgs e) 
1422                                 {
1423                                         if (Visible) {
1424                                                 e = TranslateEvent (e);
1425                                                 if (ClientRectangle.Contains (e.X, e.Y))
1426                                                         OnMouseUp (e);
1427                                         }
1428                                 }
1429                                 
1430                                 public void FireMouseMove (MouseEventArgs e) 
1431                                 {
1432                                         if (Visible) {
1433                                                 e = TranslateEvent (e);
1434                                                 if (ClientRectangle.Contains (e.X, e.Y))
1435                                                         OnMouseMove (e);
1436                                         }
1437                                 }                       
1438                                 
1439                                 MouseEventArgs TranslateEvent (MouseEventArgs e)
1440                                 {
1441                                         Point loc = PointToClient (Control.MousePosition);
1442                                         return new MouseEventArgs (e.Button, e.Clicks, loc.X, loc.Y, e.Delta);
1443                                 }
1444                         }
1445
1446                         public ComboListBox (ComboBox owner)
1447                         {                                       
1448                                 this.owner = owner;                                                             
1449                                 top_item = 0;
1450                                 last_item = 0;
1451                                 page_size = 0;
1452
1453                                 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1454                                 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1455                                 MouseMove += new MouseEventHandler (OnMouseMovePUW);                            
1456                                 MouseWheel += new MouseEventHandler (OnMouseWheelCLB);                          
1457                                 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1458                                 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1459                                 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1460
1461                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1462                                         InternalBorderStyle = BorderStyle.Fixed3D;
1463                                 else
1464                                         InternalBorderStyle = BorderStyle.FixedSingle;
1465                         }
1466
1467                         protected override CreateParams CreateParams
1468                         {
1469                                 get {
1470                                         CreateParams cp = base.CreateParams;                                    
1471                                         if (owner == null || owner.DropDownStyle == ComboBoxStyle.Simple)
1472                                                 return cp;
1473
1474                                         cp.Style ^= (int) WindowStyles.WS_CHILD;
1475                                         cp.Style |= (int) WindowStyles.WS_POPUP;
1476                                         cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST;
1477                                         return cp;
1478                                 }
1479                         }
1480
1481                         internal override bool InternalCapture {
1482                                 get {
1483                                         return Capture;
1484                                 }
1485
1486                                 set {
1487                                 }
1488                         }
1489
1490                         protected override void OnLostFocus(EventArgs e) {
1491                                 if (Capture) {
1492                                         HideWindow();
1493                                 }
1494                                 base.OnLostFocus (e);
1495                         }
1496
1497
1498                         int BorderWidth {
1499                                 get {
1500                                         switch (border_style) {
1501                                         case BorderStyle.Fixed3D:
1502                                                 return ThemeEngine.Current.Border3DSize.Width;
1503                                         default:
1504                                                 return ThemeEngine.Current.BorderSize.Width;
1505                                         }
1506                                 }
1507                         }
1508
1509                         #region Private Methods                 
1510                         // Calcs the listbox area
1511                         internal void CalcListBoxArea ()
1512                         {                               
1513                                 int width, height;
1514                                 bool show_scrollbar = false;
1515                                 
1516                                 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1517                                         Rectangle area = owner.listbox_area;
1518                                         width = area.Width;
1519                                         height = area.Height;
1520                                 }
1521                                 else { // DropDown or DropDownList
1522                                         
1523                                         width = owner.DropDownWidth;
1524                                         int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;                         
1525                                         
1526                                         if (owner.DrawMode == DrawMode.OwnerDrawVariable) {                                             
1527                                                 height = 0;
1528                                                 for (int i = 0; i < count; i++) {
1529                                                         height += owner.GetItemHeight (i);
1530                                                 }
1531                                                 
1532                                         } else  {
1533                                                 height = owner.ItemHeight * count;
1534                                         }
1535                                 }
1536                                 
1537                                 if (owner.Items.Count <= owner.MaxDropDownItems) {                                      
1538                                         if (vscrollbar_ctrl != null)
1539                                                 vscrollbar_ctrl.Visible = false;
1540                                 } else {                                        
1541                                         /* Need vertical scrollbar */
1542                                         if (vscrollbar_ctrl == null) {
1543                                                 vscrollbar_ctrl = new VScrollBarLB ();
1544                                                 vscrollbar_ctrl.Minimum = 0;
1545                                                 vscrollbar_ctrl.SmallChange = 1;
1546                                                 vscrollbar_ctrl.LargeChange = 1;
1547                                                 vscrollbar_ctrl.Maximum = 0;
1548                                                 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1549                                                 Controls.AddImplicit (vscrollbar_ctrl);
1550                                         }
1551                                         
1552                                         vscrollbar_ctrl.Height = height - 2 * BorderWidth;
1553                                                         
1554                                         vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - BorderWidth - 1, 0);
1555
1556                                         vscrollbar_ctrl.Maximum = owner.Items.Count - (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items);
1557                                         show_scrollbar = vscrollbar_ctrl.Visible = true;
1558
1559                                         int hli = HighlightedIndex;
1560                                         if (hli > 0) {
1561                                                 hli = Math.Min (hli, vscrollbar_ctrl.Maximum);
1562                                                 vscrollbar_ctrl.Value = hli;
1563                                         }
1564                                 }
1565                                 
1566                                 Size = new Size (width, height);
1567                                 textarea_drawable = ClientRectangle;
1568                                 textarea_drawable.Width = width;
1569                                 textarea_drawable.Height = height;                              
1570                                 
1571                                 if (vscrollbar_ctrl != null && show_scrollbar)
1572                                         textarea_drawable.Width -= vscrollbar_ctrl.Width;
1573
1574                                 last_item = LastVisibleItem ();
1575                                 page_size = textarea_drawable.Height / owner.ItemHeight;
1576                         }                       
1577
1578                         private void Draw (Rectangle clip, Graphics dc)
1579                         {       
1580                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (owner.BackColor), clip);
1581
1582                                 if (owner.Items.Count > 0) {
1583                                         
1584                                         for (int i = top_item; i <= last_item; i++) {
1585                                                 Rectangle item_rect = GetItemDisplayRectangle (i, top_item);
1586
1587                                                 if (!clip.IntersectsWith (item_rect))
1588                                                         continue;
1589
1590                                                 DrawItemState state = DrawItemState.None;
1591
1592                                                 if (i == HighlightedIndex) {
1593                                                         state |= DrawItemState.Selected;
1594                                                         
1595                                                         if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1596                                                                 state |= DrawItemState.Focus;
1597                                                         }                                                       
1598                                                 }
1599                                                         
1600                                                 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1601                                                         i, state, owner.ForeColor, owner.BackColor));
1602                                         }
1603                                 }
1604                         }
1605
1606                         private int highlighted_index = -1;
1607                         public int HighlightedIndex {
1608                                 get { return highlighted_index; }
1609                                 set {
1610                                         if (highlighted_index != -1)
1611                                                 Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
1612                                         highlighted_index = value;
1613                                         if (value != -1)
1614                                                 Invalidate (GetItemDisplayRectangle (highlighted_index, top_item));
1615
1616                                         // Scroll if we need to
1617                                         if (vscrollbar_ctrl != null) {
1618                                                 int max = (owner.Items.Count <= owner.MaxDropDownItems) ?
1619                                                        owner.Items.Count : owner.MaxDropDownItems;
1620
1621                                                 if (value > max + vscrollbar_ctrl.Value - 1) {
1622                                                         vscrollbar_ctrl.Value += (value - (max + vscrollbar_ctrl.Value - 1));
1623                                                 } else if (value < vscrollbar_ctrl.Value) {
1624                                                         vscrollbar_ctrl.Value = value;
1625                                                 }
1626                                         }
1627                                 }
1628                         }
1629                         
1630                         private Rectangle GetItemDisplayRectangle (int index, int top_index)
1631                         {
1632                                 if (index < 0 || index >= owner.Items.Count)
1633                                         throw new  ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1634
1635                                 Rectangle item_rect = new Rectangle ();
1636                                 int height = owner.GetItemHeight (index);
1637
1638                                 item_rect.X = 0;
1639                                 item_rect.Width = textarea_drawable.Width;
1640                                 if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
1641                                         item_rect.Y = 0;
1642                                         for (int i = top_index; i < index; i++)
1643                                                 item_rect.Y += owner.GetItemHeight (i);
1644                                 } else
1645                                         item_rect.Y = height * (index - top_index);
1646
1647                                 item_rect.Height = height;
1648                                 return item_rect;
1649                         }
1650
1651                         public void HideWindow ()
1652                         {
1653                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1654                                         return;
1655                                         
1656                                 Capture = false;
1657                                 Hide ();
1658                                 owner.DropDownListBoxFinished ();
1659                         }
1660
1661                         private int IndexFromPointDisplayRectangle (int x, int y)
1662                         {
1663                                 for (int i = top_item; i <= last_item; i++) {
1664                                         if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1665                                                 return i;
1666                                 }
1667
1668                                 return -1;
1669                         }
1670                         
1671                         protected override bool IsInputKey (Keys keyData)
1672                         {
1673                                 return owner.IsInputKey (keyData);
1674                         }
1675
1676                         private int LastVisibleItem ()
1677                         {
1678                                 Rectangle item_rect;
1679                                 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1680                                 int i = 0;                              
1681                                 
1682                                 for (i = top_item; i < owner.Items.Count; i++) {
1683                                         item_rect = GetItemDisplayRectangle (i, top_item);                              
1684                                         if (item_rect.Y + item_rect.Height > top_y) {
1685                                                 return i;
1686                                         }
1687                                 }
1688                                 return i - 1;
1689                         }
1690                         
1691                         private void NavigateItemVisually (ItemNavigation navigation)
1692                         {
1693                                 int item = -1;
1694                                 
1695                                 switch (navigation) {
1696                                 case ItemNavigation.Next:
1697                                         if (HighlightedIndex + 1 < owner.Items.Count) {
1698                                                 if (HighlightedIndex + 1 > last_item) {
1699                                                         top_item++;
1700                                                         vscrollbar_ctrl.Value = top_item;
1701                                                 }
1702                                                 item = HighlightedIndex + 1;
1703                                         }
1704                                         break;
1705                                 
1706                                 case ItemNavigation.Previous:
1707                                         if (HighlightedIndex > 0) {                                             
1708                                                 if (HighlightedIndex - 1 < top_item) {                                                  
1709                                                         top_item--;
1710                                                         vscrollbar_ctrl.Value = top_item;                                                       
1711                                                 }
1712                                                 item = HighlightedIndex - 1;
1713                                         }                                       
1714                                         break;
1715                                 
1716                                 case ItemNavigation.NextPage:
1717                                         if (HighlightedIndex + page_size - 1 >= owner.Items.Count) {
1718                                                 top_item = owner.Items.Count - page_size;
1719                                                 vscrollbar_ctrl.Value = top_item;
1720                                                 item = owner.Items.Count - 1;
1721                                         } else {
1722                                                 if (HighlightedIndex + page_size - 1  > last_item) {
1723                                                         top_item = HighlightedIndex;
1724                                                         vscrollbar_ctrl.Value = HighlightedIndex;
1725                                                 }
1726                                                 item = HighlightedIndex + page_size - 1;
1727                                         }                                       
1728                                         break;
1729                                 
1730                                 case ItemNavigation.PreviousPage:
1731                                         if (HighlightedIndex - page_size - 1 <= 0) {
1732                                                 top_item = 0;
1733                                                 vscrollbar_ctrl.Value = top_item;
1734                                                 item = 0;                       
1735                                         } else {
1736                                                 if (HighlightedIndex - page_size - 1  < top_item) {
1737                                                         top_item = HighlightedIndex - page_size - 1;
1738                                                         vscrollbar_ctrl.Value = top_item;
1739                                                 }
1740                                                 item = HighlightedIndex - page_size - 1;
1741                                         }
1742                                         break;
1743                                         
1744                                 default:
1745                                         break;
1746                                 }       
1747                                 
1748                                 if (item != -1) {
1749                                         HighlightedIndex = item;
1750                                         owner.OnSelectionChangeCommitted (new EventArgs ());
1751                                         if (owner.DropDownStyle == ComboBoxStyle.Simple)
1752                                                 owner.SetControlText (owner.GetItemText (owner.Items[item]));
1753                                 }
1754                         }
1755
1756                         private void OnKeyDownPUW (object sender, KeyEventArgs e)                       
1757                         {                               
1758                                 switch (e.KeyCode) {                    
1759                                 case Keys.Up:
1760                                         NavigateItemVisually (ItemNavigation.Previous);
1761                                         break;                          
1762         
1763                                 case Keys.Down:                         
1764                                         NavigateItemVisually (ItemNavigation.Next);
1765                                         break;
1766                                 
1767                                 case Keys.PageUp:
1768                                         NavigateItemVisually (ItemNavigation.PreviousPage);
1769                                         break;                          
1770         
1771                                 case Keys.PageDown:                             
1772                                         NavigateItemVisually (ItemNavigation.NextPage);
1773                                         break;
1774                                 }
1775                         }
1776
1777                         protected override void OnKeyPress (KeyPressEventArgs e)
1778                         {
1779                                 int index = owner.FindStringCaseInsensitive (e.KeyChar.ToString (),
1780                                                 owner.SelectedIndex + 1);
1781                                 if (index == -1)
1782                                         return;
1783                                 owner.SelectedIndex = index;
1784                         }
1785
1786                         public void SetTopItem (int item)
1787                         {
1788                                 if (top_item == item)
1789                                         return;
1790                                 top_item = item;
1791                                 UpdateLastVisibleItem ();
1792                                 Refresh ();
1793                         }                       
1794                         
1795                         private void OnMouseDownPUW (object sender, MouseEventArgs e)
1796                         {
1797                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1798
1799                                 if (index == -1) {                                      
1800                                         if (vscrollbar_ctrl == null || !vscrollbar_ctrl.FireMouseDown (e))
1801                                                 HideWindow ();
1802                                 } else {
1803                                         owner.OnSelectionChangeCommitted (new EventArgs ());
1804                                         owner.SelectedIndex = index;
1805                                         HighlightedIndex = index;
1806                                         HideWindow ();
1807                                 }
1808                                 
1809                                 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1810                                         owner.OnMouseDown (e);
1811                                         owner.textbox_ctrl.Focus ();
1812                                 }
1813                         }
1814
1815                         private void OnMouseMovePUW (object sender, MouseEventArgs e)
1816                         {
1817                                 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1818                                         owner.OnMouseMove (e);
1819                                         return;
1820                                 }
1821                                                 
1822                                 Point pt = PointToClient (Control.MousePosition);
1823                                 int index = IndexFromPointDisplayRectangle (pt.X, pt.Y);
1824
1825                                 if (index != -1) {
1826                                         HighlightedIndex = index;
1827                                         return;
1828                                 }
1829                                 
1830                                 if (vscrollbar_ctrl != null)
1831                                         vscrollbar_ctrl.FireMouseMove (e);
1832                         }
1833                         
1834                         private void OnMouseUpPUW (object sender, MouseEventArgs e)
1835                         {
1836                                 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1837                                         owner.OnMouseUp (e);
1838                                         return;                                 
1839                                 }
1840
1841                                 if (vscrollbar_ctrl != null)
1842                                         vscrollbar_ctrl.FireMouseUp (e);
1843                         }
1844
1845                         internal override void OnPaintInternal (PaintEventArgs pevent)
1846                         {                               
1847                                 Draw (pevent.ClipRectangle,pevent.Graphics);
1848                         }
1849
1850                         public bool ShowWindow ()
1851                         {
1852                                 if (owner.DropDownStyle == ComboBoxStyle.Simple && owner.Items.Count == 0)
1853                                         return false;
1854                                         
1855                                 HighlightedIndex = owner.SelectedIndex;
1856
1857                                 CalcListBoxArea ();                             
1858                                 Show ();
1859
1860                                 Refresh ();
1861                                 owner.OnDropDown (EventArgs.Empty);
1862                                 return true;
1863                         }
1864                         
1865                         public void UpdateLastVisibleItem ()
1866                         {
1867                                 last_item = LastVisibleItem ();
1868                         }
1869
1870                         private void Scroll (int delta)
1871                         {
1872                                 if (delta == 0 || !vscrollbar_ctrl.Visible)
1873                                         return;
1874
1875                                 int max = vscrollbar_ctrl.Maximum;//- (page_size) + 1;
1876
1877                                 int val = vscrollbar_ctrl.Value + delta;
1878                                 if (val > max)
1879                                         val = max;
1880                                 else if (val < vscrollbar_ctrl.Minimum)
1881                                         val = vscrollbar_ctrl.Minimum;
1882                                 vscrollbar_ctrl.Value = val;
1883                         }
1884
1885                         private void OnMouseWheelCLB (object sender, MouseEventArgs me)
1886                         {
1887                                 if (owner.Items.Count == 0)
1888                                         return;
1889
1890                                 int lines = me.Delta / 120 * SystemInformation.MouseWheelScrollLines;
1891                                 Scroll (-lines);
1892                         }
1893
1894                         // Value Changed
1895                         private void VerticalScrollEvent (object sender, EventArgs e)
1896                         {                               
1897                                 if (top_item == vscrollbar_ctrl.Value)
1898                                         return;
1899
1900                                 top_item =  vscrollbar_ctrl.Value;
1901                                 UpdateLastVisibleItem ();
1902                                 Refresh ();
1903                         }                       
1904                         
1905                         #endregion Private Methods
1906                 }
1907         }
1908 }
1909