* Control.cs: Double buffering is handled differently now. As per
[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, Graphics dc)
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 (dc, Font, item_rect,
947                                                         selected_index, state, ForeColor, BackColor));
948                         }                                               
949                         
950                         if (clip.IntersectsWith (combobox_info.listbox_area) == true) {
951                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor), 
952                                                 combobox_info.listbox_area);
953                         }
954                         
955                         if (CBoxInfo.show_button) {
956                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorButtonFace),
957                                         combobox_info.button_rect);
958
959                                 ThemeEngine.Current.CPDrawComboButton (dc,
960                                         combobox_info.button_rect, combobox_info.button_status);
961                         }                       
962                         
963                         ThemeEngine.Current.DrawComboBoxEditDecorations (dc, 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, pevent.Graphics);                        
1070
1071                         if (Paint != null)
1072                                 Paint (this, pevent);
1073                 }
1074                 
1075                 private void OnTextChangedEdit (object sender, EventArgs e)
1076                 {
1077                         if (process_textchanged_event == false)
1078                                 return; 
1079                                 
1080                         int item = FindStringCaseInsensitive (textbox_ctrl.Text);
1081                         
1082                         if (item == -1)
1083                                 return;
1084                         
1085                         listbox_ctrl.SetTopItem (item);
1086                         listbox_ctrl.SetHighLightedItem (Items[item]);
1087                 }
1088                 
1089                 internal void SetControlText (string s)
1090                 {               
1091                         process_textchanged_event = false; 
1092                         textbox_ctrl.Text = s;
1093                         process_textchanged_event = true;
1094                 }
1095                 
1096                 private void UpdatedItems ()
1097                 {
1098                         if (dropdown_style != ComboBoxStyle.Simple)
1099                                 return;                         
1100                                                         
1101                         listbox_ctrl.UpdateLastVisibleItem ();
1102                         listbox_ctrl.CalcListBoxArea ();
1103                         listbox_ctrl.Refresh ();
1104                 }
1105
1106                 #endregion Private Methods
1107
1108
1109                 /*
1110                         ComboBox.ObjectCollection
1111                 */
1112                 [ListBindableAttribute (false)]
1113                 public class ObjectCollection : IList, ICollection, IEnumerable
1114                 {
1115
1116                         private ComboBox owner;
1117                         internal ArrayList object_items = new ArrayList ();
1118                         internal ArrayList combobox_items = new ArrayList ();
1119
1120                         public ObjectCollection (ComboBox owner)
1121                         {
1122                                 this.owner = owner;
1123                         }
1124
1125                         #region Public Properties
1126                         public virtual int Count {
1127                                 get { return object_items.Count; }
1128                         }
1129
1130                         public virtual bool IsReadOnly {
1131                                 get { return false; }
1132                         }
1133
1134                         [Browsable (false)]
1135                         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1136                         public virtual object this [int index] {
1137                                 get {
1138                                         if (index < 0 || index >= Count)
1139                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1140
1141                                         return object_items[index];
1142                                 }
1143                                 set {
1144                                         if (index < 0 || index >= Count)
1145                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1146
1147                                         object_items[index] = value;
1148                                 }
1149                         }
1150
1151                         bool ICollection.IsSynchronized {
1152                                 get { return false; }
1153                         }
1154
1155                         object ICollection.SyncRoot {
1156                                 get { return this; }
1157                         }
1158
1159                         bool IList.IsFixedSize {
1160                                 get { return false; }
1161                         }
1162
1163                         #endregion Public Properties
1164                         
1165                         #region Private Properties                      
1166                         internal ArrayList ObjectItems {
1167                                 get { return object_items;}
1168                                 set {
1169                                         object_items = value;
1170                                 }
1171                         }
1172                         
1173                         internal ArrayList ListBoxItems {
1174                                 get { return combobox_items;}
1175                                 set {
1176                                         combobox_items = value;
1177                                 }
1178                         }                       
1179                         #endregion Private Properties
1180
1181                         #region Public Methods
1182                         public int Add (object item)
1183                         {
1184                                 int idx;
1185
1186                                 idx = AddItem (item);
1187                                 owner.UpdatedItems ();
1188                                 return idx;
1189                         }
1190
1191                         public void AddRange (object[] items)
1192                         {
1193                                 foreach (object mi in items)
1194                                         AddItem (mi);
1195                                         
1196                                 owner.UpdatedItems ();
1197                         }
1198
1199                         public virtual void Clear ()
1200                         {
1201                                 owner.selected_index = -1;
1202                                 object_items.Clear ();
1203                                 combobox_items.Clear ();
1204                                 owner.UpdatedItems ();
1205                                 owner.Refresh ();
1206                         }
1207                         
1208                         public virtual bool Contains (object obj)
1209                         {
1210                                 return object_items.Contains (obj);
1211                         }
1212
1213                         public void CopyTo (object[] dest, int arrayIndex)
1214                         {
1215                                 object_items.CopyTo (dest, arrayIndex);
1216                         }
1217
1218                         void ICollection.CopyTo (Array dest, int index)
1219                         {
1220                                 object_items.CopyTo (dest, index);
1221                         }
1222
1223                         public virtual IEnumerator GetEnumerator ()
1224                         {
1225                                 return object_items.GetEnumerator ();
1226                         }
1227
1228                         int IList.Add (object item)
1229                         {
1230                                 return Add (item);
1231                         }
1232
1233                         public virtual int IndexOf (object value)
1234                         {
1235                                 return object_items.IndexOf (value);
1236                         }
1237
1238                         public virtual void Insert (int index,  object item)
1239                         {
1240                                 if (index < 0 || index >= Count)
1241                                         throw new ArgumentOutOfRangeException ("Index of out range");                                   
1242                                 
1243                                 ObjectCollection new_items = new ObjectCollection (owner);                              
1244                                 object sel_item = owner.SelectedItem;
1245                                                                                                 
1246                                 owner.BeginUpdate ();
1247                                 
1248                                 for (int i = 0; i < index; i++) {
1249                                         new_items.AddItem (ObjectItems[i]);
1250                                 }
1251
1252                                 new_items.AddItem (item);
1253
1254                                 for (int i = index; i < Count; i++){
1255                                         new_items.AddItem (ObjectItems[i]);
1256                                 }                               
1257
1258                                 ObjectItems = new_items.ObjectItems;
1259                                 ListBoxItems = new_items.ListBoxItems;
1260                                 
1261                                 if (sel_item != null) {
1262                                         int idx = IndexOf (sel_item);
1263                                         owner.selected_index = idx;
1264                                         owner.listbox_ctrl.SetHighLightedItem (owner.Items[idx]);
1265                                 }
1266                                                                                                 
1267                                 owner.EndUpdate ();     // Calls UpdatedItems
1268                         }
1269
1270                         public virtual void Remove (object value)
1271                         {                               
1272                                 if (IndexOf (value) == owner.SelectedIndex)
1273                                         owner.SelectedItem = null;
1274                                 
1275                                 RemoveAt (IndexOf (value));                             
1276                                 
1277                         }
1278
1279                         public virtual void RemoveAt (int index)
1280                         {
1281                                 if (index < 0 || index >= Count)
1282                                         throw new ArgumentOutOfRangeException ("Index of out range");
1283                                         
1284                                 if (index == owner.SelectedIndex)
1285                                         owner.SelectedItem = null;
1286
1287                                 object_items.RemoveAt (index);
1288                                 combobox_items.RemoveAt (index);
1289                                 owner.UpdatedItems ();
1290                         }
1291                         #endregion Public Methods
1292
1293                         #region Private Methods
1294                         private int AddItem (object item)
1295                         {
1296                                 int cnt = object_items.Count;
1297                                 object_items.Add (item);
1298                                 combobox_items.Add (new ComboBox.ComboBoxItem (cnt));                           
1299                                 return cnt;
1300                         }
1301                         
1302                         internal void AddRange (IList items)
1303                         {
1304                                 foreach (object mi in items)
1305                                         AddItem (mi);
1306                                                                                 
1307                                 owner.UpdatedItems ();
1308                         }
1309
1310                         internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
1311                         {
1312                                 if (index < 0 || index >= Count)
1313                                         throw new ArgumentOutOfRangeException ("Index of out range");
1314
1315                                 return (ComboBox.ComboBoxItem) combobox_items[index];
1316                         }
1317
1318                         internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
1319                         {
1320                                 if (index < 0 || index >= Count)
1321                                         throw new ArgumentOutOfRangeException ("Index of out range");
1322
1323                                 combobox_items[index] = item;
1324                         }
1325
1326                         #endregion Private Methods
1327                 }
1328
1329                 /*
1330                         class ComboListBox
1331                 */
1332                 internal class ComboListBox : Control
1333                 {
1334                         private ComboBox owner;                 
1335                         private VScrollBarLB vscrollbar_ctrl;
1336                         private int top_item;                   /* First item that we show the in the current page */
1337                         private int last_item;                  /* Last visible item */
1338                         public object highlighted_item; /* Item that is currently selected */
1339                         internal int page_size;                 /* Number of listbox items per page */
1340                         private Rectangle textarea_drawable;    /* Rectangle of the drawable text area */
1341                         
1342                         internal enum ItemNavigation
1343                         {
1344                                 First,
1345                                 Last,
1346                                 Next,
1347                                 Previous,
1348                                 NextPage,
1349                                 PreviousPage,
1350                         }
1351                         
1352                         class VScrollBarLB : VScrollBar
1353                         {
1354                                 public VScrollBarLB ()
1355                                 {                                       
1356                                 }
1357                                 
1358                                 public void FireMouseDown (MouseEventArgs e) 
1359                                 {
1360                                         OnMouseDown (e);
1361                                 }       
1362                                 
1363                                 public void FireMouseUp (MouseEventArgs e) 
1364                                 {
1365                                         OnMouseUp (e);
1366                                 }
1367                                 
1368                                 public void FireMouseMove (MouseEventArgs e) 
1369                                 {
1370                                         OnMouseMove (e);
1371                                 }                       
1372                                 
1373                         }
1374
1375                         public ComboListBox (ComboBox owner) : base ()
1376                         {       
1377                                 this.owner = owner;                                                             
1378                                 top_item = 0;
1379                                 last_item = 0;
1380                                 page_size = 0;
1381                                 highlighted_item = null;
1382
1383                                 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1384                                 MouseUp += new MouseEventHandler (OnMouseUpPUW);
1385                                 MouseMove += new MouseEventHandler (OnMouseMovePUW);                            
1386                                 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1387                                 Paint += new PaintEventHandler (OnPaintPUW);                            
1388                                 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1389                                 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);                             
1390                         }
1391
1392                         protected override CreateParams CreateParams
1393                         {
1394                                 get {
1395                                         CreateParams cp = base.CreateParams;                                    
1396                                         if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) {
1397                                                 cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
1398                                                 cp.ExStyle |= (int)(WindowStyles.WS_EX_TOOLWINDOW | WindowStyles.WS_EX_TOPMOST);
1399                                         }                                       
1400                                         return cp;
1401                                 }
1402                         }
1403
1404                         #region Private Methods
1405
1406                         protected override void CreateHandle ()
1407                         {                       
1408                                 base.CreateHandle ();                           
1409                         }
1410
1411                         // Calcs the listbox area
1412                         internal void CalcListBoxArea ()
1413                         {                               
1414                                 int width, height;
1415                                 int item_height = owner.ItemHeight;
1416                                 bool show_scrollbar = false;
1417                                 
1418                                 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1419                                         width = owner.CBoxInfo.listbox_area.Width;
1420                                         height = owner.CBoxInfo.listbox_area.Height;
1421
1422                                         if (owner.IntegralHeight == true) {
1423                                                 int remaining = (height -
1424                                                         ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1425                                                         ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)) %
1426                                                         (item_height - 2);                                                      
1427                 
1428                                                 if (remaining > 0) {
1429                                                         height -= remaining;                                                    
1430                                                 }
1431                                         }
1432                                 }
1433                                 else { // DropDown or DropDownList
1434                                         
1435                                         width = owner.DropDownWidth;
1436                                         int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;                         
1437                                         
1438                                         if (owner.DrawMode == DrawMode.OwnerDrawVariable) {                                             
1439                                                 height = 0;
1440                                                 for (int i = 0; i < count; i++) {
1441                                                         height += owner.GetItemHeight (i);
1442                                                 }
1443                                                 
1444                                         } else  {
1445                                                 height = (item_height - 2) * count;
1446                                         }
1447                                         
1448                                         
1449                                         height += ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);                           
1450                                         height += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1451                                 }
1452                                 
1453                                 if (owner.Items.Count <= owner.MaxDropDownItems) {                                      
1454                                         
1455                                         /* Does not need vertical scrollbar*/
1456                                         if (vscrollbar_ctrl != null) {                                          
1457                                                 vscrollbar_ctrl.Visible = false;                                                
1458                                         }                                       
1459                                 }
1460                                 else {
1461                                         /* Need vertical scrollbar */
1462                                         if (vscrollbar_ctrl == null) {
1463                                                 vscrollbar_ctrl = new VScrollBarLB ();
1464                                                 vscrollbar_ctrl.Minimum = 0;
1465                                                 vscrollbar_ctrl.SmallChange = 1;
1466                                                 vscrollbar_ctrl.LargeChange = 1;
1467                                                 vscrollbar_ctrl.Maximum = 0;
1468                                                 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1469                                                 
1470                                                 Controls.Add (vscrollbar_ctrl);
1471                                         }
1472                                         
1473                                         vscrollbar_ctrl.Height = height - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1474                                                         ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1475                                                         
1476                                         vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle), 
1477                                                         ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle));
1478                                                 
1479                                         vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems;
1480                                         show_scrollbar = vscrollbar_ctrl.Visible = true;
1481                                         
1482                                 }
1483                                 
1484                                 Size = new Size (width, height);
1485                                 textarea_drawable = ClientRectangle;
1486                                 textarea_drawable.Width = width;
1487                                 textarea_drawable.Height = height;                              
1488
1489                                 // Exclude decorations
1490                                 textarea_drawable.X += ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1491                                 textarea_drawable.Y += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1492                                 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1493                                 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1494                                 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);                         
1495                                 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1496                                 
1497                                 if (vscrollbar_ctrl != null && show_scrollbar)
1498                                         textarea_drawable.Width -= vscrollbar_ctrl.Width;
1499
1500                                 last_item = LastVisibleItem ();                         
1501                                 page_size = textarea_drawable.Height / (item_height - 2);                               
1502                         }                       
1503
1504                         private void Draw (Rectangle clip, Graphics dc)
1505                         {       
1506                                 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
1507                                         (owner.BackColor), ClientRectangle);                            
1508
1509                                 if (owner.Items.Count > 0) {
1510                                         Rectangle item_rect;
1511                                         DrawItemState state = DrawItemState.None;
1512                                         
1513                                         for (int i = top_item; i <= last_item; i++) {
1514                                                 item_rect = GetItemDisplayRectangle (i, top_item);                                              
1515
1516                                                 if (clip.IntersectsWith (item_rect) == false)
1517                                                         continue;
1518
1519                                                 /* Draw item */
1520                                                 state = DrawItemState.None;
1521
1522                                                 if (i == GetHighLightedIndex () ) {
1523                                                         state |= DrawItemState.Selected;
1524                                                         
1525                                                         if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
1526                                                                 state |= DrawItemState.Focus;
1527                                                         }                                                       
1528                                                 }
1529                                                         
1530                                                 owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
1531                                                         i, state, owner.ForeColor, owner.BackColor));
1532                                         }
1533                                 }                       
1534                                 
1535                                 ThemeEngine.Current.DrawComboListBoxDecorations (dc, owner, ClientRectangle);
1536                         }
1537                         
1538                         public int GetHighLightedIndex ()
1539                         {                                       
1540                                 return owner.Items.IndexOf (highlighted_item);
1541                         }
1542                         
1543                         public object GetHighLightedItem ()
1544                         {                               
1545                                 return highlighted_item;
1546                         }
1547
1548                         private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
1549                         {
1550                                 if (index < 0 || index >= owner.Items.Count)
1551                                         throw new  ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1552
1553                                 Rectangle item_rect = new Rectangle ();
1554                                 int height = owner.GetItemHeight (index);
1555
1556                                 item_rect.X = ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1557                                 item_rect.Width = textarea_drawable.Width;
1558                                 item_rect.Y = 2 + ((height - 2) * (index - first_displayble));
1559                                 item_rect.Height = height;
1560                                 return item_rect;
1561                         }
1562
1563                         public void HideWindow ()
1564                         {
1565                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1566                                         return;
1567                                         
1568                                 Capture = false;
1569                                 Hide ();
1570                                 highlighted_item = -1;
1571                                 owner.DropDownListBoxFinished ();
1572                         }
1573
1574                         private int IndexFromPointDisplayRectangle (int x, int y)
1575                         {
1576                                 for (int i = top_item; i <= last_item; i++) {
1577                                         if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1578                                                 return i;
1579                                 }
1580
1581                                 return -1;
1582                         }
1583                         
1584                         protected override bool IsInputKey (Keys keyData)
1585                         {
1586                                 return owner.IsInputKey (keyData);
1587                         }
1588
1589                         private int LastVisibleItem ()
1590                         {
1591                                 Rectangle item_rect;
1592                                 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1593                                 int i = 0;                              
1594                                 
1595                                 for (i = top_item; i < owner.Items.Count; i++) {
1596                                         item_rect = GetItemDisplayRectangle (i, top_item);                              
1597                                         if (item_rect.Y + item_rect.Height > top_y) {
1598                                                 return i;
1599                                         }
1600                                 }
1601                                 return i - 1;
1602                         }
1603                         
1604                         private void NavigateItemVisually (ItemNavigation navigation)
1605                         {
1606                                 int item = -1;
1607                                 
1608                                 switch (navigation) {
1609                                 case ItemNavigation.Next: {
1610                                         if (GetHighLightedIndex () + 1 < owner.Items.Count) {
1611                                                 
1612                                                 if (GetHighLightedIndex () + 1 > last_item) {
1613                                                         top_item++;
1614                                                         vscrollbar_ctrl.Value = top_item;
1615                                                 }
1616                                                 item = GetHighLightedIndex () + 1;
1617                                         }
1618                                         break;
1619                                 }
1620                                 
1621                                 case ItemNavigation.Previous: {
1622                                         if (GetHighLightedIndex () > 0) {                                               
1623                                                 
1624                                                 if (GetHighLightedIndex () - 1 < top_item) {                                                    
1625                                                         top_item--;
1626                                                         vscrollbar_ctrl.Value = top_item;                                                       
1627                                                 }
1628                                                 item = GetHighLightedIndex () - 1;
1629                                         }                                       
1630                                         break;
1631                                 }
1632                                 
1633                                 case ItemNavigation.NextPage: {
1634                                         if (GetHighLightedIndex () + page_size - 1 >= owner.Items.Count) {
1635                                                 top_item = owner.Items.Count - page_size;
1636                                                 vscrollbar_ctrl.Value = top_item;                                               
1637                                                 item = owner.Items.Count - 1;
1638                                         }
1639                                         else {
1640                                                 if (GetHighLightedIndex () + page_size - 1  > last_item) {
1641                                                         top_item = GetHighLightedIndex ();
1642                                                         vscrollbar_ctrl.Value = GetHighLightedIndex ();
1643                                                 }
1644                                         
1645                                                 item = GetHighLightedIndex () + page_size - 1;
1646                                         }                                       
1647                                         break;
1648                                 }
1649                                 
1650                                 case ItemNavigation.PreviousPage: {                                     
1651                                         
1652                                         /* Go to the first item*/
1653                                         if (GetHighLightedIndex () - (page_size - 1) <= 0) {
1654                                                                                                                                                 
1655                                                 top_item = 0;
1656                                                 vscrollbar_ctrl.Value = top_item;
1657                                                 item = 0;                       
1658                                         }
1659                                         else { /* One page back */
1660                                                 if (GetHighLightedIndex () - (page_size - 1)  < top_item) {
1661                                                         top_item = GetHighLightedIndex () - (page_size - 1);
1662                                                         vscrollbar_ctrl.Value = top_item;
1663                                                 }
1664                                         
1665                                                 item = GetHighLightedIndex () - (page_size - 1);
1666                                         }
1667                                         
1668                                         break;
1669                                 }                               
1670                                         
1671                                 default:
1672                                         break;
1673                                 }       
1674                                 
1675                                 if (item != -1) {
1676                                         SetHighLightedItem (owner.Items[item]);
1677                                         
1678                                         owner.OnSelectionChangeCommitted (new EventArgs ());
1679                                         
1680                                         if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1681                                                 owner.SetControlText (owner.Items[item].ToString ());
1682                                         }
1683                                 }
1684                         }
1685                         
1686                         private void OnKeyDownPUW (object sender, KeyEventArgs e)                       
1687                         {                               
1688                                 switch (e.KeyCode) {                    
1689                                 case Keys.Up:
1690                                         NavigateItemVisually (ItemNavigation.Previous);
1691                                         break;                          
1692         
1693                                 case Keys.Down:                         
1694                                         NavigateItemVisually (ItemNavigation.Next);
1695                                         break;
1696                                 
1697                                 case Keys.PageUp:
1698                                         NavigateItemVisually (ItemNavigation.PreviousPage);
1699                                         break;                          
1700         
1701                                 case Keys.PageDown:                             
1702                                         NavigateItemVisually (ItemNavigation.NextPage);
1703                                         break;
1704                                 
1705                                 default:
1706                                         break;
1707                                 }
1708                         }
1709                         
1710                         public void SetHighLightedItem (object item)
1711                         {
1712                                 Rectangle invalidate;
1713                                 
1714                                 if (GetHighLightedItem () == item)
1715                                         return;
1716                                 
1717                                 /* Previous item */
1718                                 if (GetHighLightedIndex () != -1) {                                     
1719                                         invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item);
1720                                         if (ClientRectangle.Contains (invalidate))
1721                                                 Invalidate (invalidate);
1722                                 }
1723                                 
1724                                 highlighted_item = item;
1725                                 
1726                                 if (highlighted_item != null) {
1727                                          /* Current item */
1728                                         invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item);
1729                                         if (ClientRectangle.Contains (invalidate))
1730                                                 Invalidate (invalidate);
1731                                 }
1732                                 
1733                         }                       
1734
1735                         public void SetTopItem (int item)
1736                         {
1737                                 top_item = item;
1738                                 UpdateLastVisibleItem ();
1739                                 Refresh ();
1740                         }                       
1741                         
1742                         private void OnMouseDownPUW (object sender, MouseEventArgs e)
1743                         {       
1744                                 Rectangle scrollbar_screenrect;
1745                                 Point mouse_screen, scrollbar_screen;
1746                                 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1747                                         
1748                                 /* Click on an element ? */                             
1749                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1750                                 if (index != -1) {                                      
1751                                         owner.SelectedIndex = index;
1752                                         SetHighLightedItem (owner.Items[index]);
1753                                         owner.OnSelectionChangeCommitted (new EventArgs ());
1754                                         HideWindow ();
1755                                         return;
1756                                 }
1757                                 
1758                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1759                                         return;                                 
1760                                                                 
1761                                 /* Reroute event to scrollbar */                                
1762                                 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {
1763                                         scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1764                                         scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1765                                         scrollbar_screenrect.X = scrollbar_screen.X;
1766                                         scrollbar_screenrect.Y = scrollbar_screen.Y;
1767                                         
1768                                         if (scrollbar_screenrect.Contains (mouse_screen)){                                      
1769                                                 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);                                        
1770                                                 vscrollbar_ctrl.FireMouseDown (new MouseEventArgs (e.Button, e.Clicks,
1771                                                         pnt_client.X, pnt_client.Y, e.Delta));                                          
1772                                         } else  { /* Click in a non-client area*/
1773                                                 HideWindow ();                          
1774                                         }                               
1775                                 } else  { /* Click in a non-client area*/
1776                                         HideWindow ();
1777                                 }
1778                         }
1779
1780                         private void OnMouseMovePUW (object sender, MouseEventArgs e)
1781                         {                       
1782                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1783                                         return;
1784                                                 
1785                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1786
1787                                 if (index != -1) {
1788                                         SetHighLightedItem (owner.Items[index]);
1789                                         return;
1790                                 }
1791                                 
1792                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1793                                         return;         
1794                                 
1795                                 /* Reroute event to scrollbar */
1796                                 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {       
1797                                         Rectangle scrollbar_screenrect;
1798                                         Point mouse_screen, scrollbar_screen;
1799                                         mouse_screen = PointToScreen (new Point (e.X, e.Y));
1800                                         
1801                                         scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1802                                         scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1803                                         scrollbar_screenrect.X = scrollbar_screen.X;
1804                                         scrollbar_screenrect.Y = scrollbar_screen.Y;
1805                                         
1806                                         if (scrollbar_screenrect.Contains (mouse_screen)){                                      
1807                                                 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
1808                                                 
1809                                                 vscrollbar_ctrl.FireMouseMove (new MouseEventArgs (e.Button, e.Clicks,
1810                                                         pnt_client.X, pnt_client.Y, e.Delta));
1811                                         }
1812                                 }                               
1813                         }
1814                         
1815                         private void OnMouseUpPUW (object sender, MouseEventArgs e)
1816                         {
1817                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1818                                         return;                                 
1819                                         
1820                                 /* Reroute event to scrollbar */        
1821                                 Rectangle scrollbar_screenrect;
1822                                 Point mouse_screen, scrollbar_screen;
1823                                 mouse_screen = PointToScreen (new Point (e.X, e.Y));
1824                                 
1825                                 if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) {       
1826                                         scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
1827                                         scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
1828                                         scrollbar_screenrect.X = scrollbar_screen.X;
1829                                         scrollbar_screenrect.Y = scrollbar_screen.Y;
1830                                         
1831                                         if (scrollbar_screenrect.Contains (mouse_screen)){                                      
1832                                                 Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);                                        
1833                                                 
1834                                                 vscrollbar_ctrl.FireMouseUp (new MouseEventArgs (e.Button, e.Clicks,
1835                                                         pnt_client.X, pnt_client.Y, e.Delta));
1836                                         }
1837                                 }
1838                         }
1839
1840                         private void OnPaintPUW (Object o, PaintEventArgs pevent)
1841                         {
1842                                 Draw (pevent.ClipRectangle,pevent.Graphics);
1843                         }
1844
1845                         public bool ShowWindow ()
1846                         {
1847                                 if (owner.DropDownStyle != ComboBoxStyle.Simple && owner.Items.Count == 0)
1848                                         return false;
1849                                         
1850                                 SetTopItem (0);
1851                                 SetHighLightedItem (owner.SelectedItem);
1852                                 
1853                                 CalcListBoxArea ();                             
1854                                 Show ();
1855                                 
1856                                 if (owner.DropDownStyle != ComboBoxStyle.Simple) {
1857                                         Capture = true;
1858                                 }
1859                                 
1860                                 Refresh ();
1861                                 
1862                                 if (owner.DropDown != null) {
1863                                         owner.DropDown (owner, EventArgs.Empty);
1864                                 }
1865                                 
1866                                 return true;
1867                         }
1868                         
1869                         public void UpdateLastVisibleItem ()
1870                         {
1871                                 last_item = LastVisibleItem ();
1872                         }
1873
1874                         // Value Changed
1875                         private void VerticalScrollEvent (object sender, EventArgs e)
1876                         {                               
1877                                 top_item =  vscrollbar_ctrl.Value;
1878                                 UpdateLastVisibleItem ();
1879                                 Refresh ();
1880                         }                       
1881
1882                         #endregion Private Methods
1883                 }\r
1884         }
1885 }
1886