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