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