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