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