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