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