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