listbox, comboxes keyboard fixes, focus item, Selection.Multiextended, etc
[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 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
35 namespace System.Windows.Forms
36 {
37
38         public class ComboBox : ListControl
39         {
40                 private DrawMode draw_mode;
41                 private ComboBoxStyle dropdown_style;
42                 private int dropdown_width;             
43                 private int preferred_height;
44                 private int selected_index;
45                 private object selected_item;
46                 internal ObjectCollection items = null;
47                 private bool suspend_ctrlupdate;
48                 private int maxdrop_items;
49                 private bool integral_height;
50                 private bool sorted;
51                 internal ComboBoxInfo combobox_info;
52                 private readonly int def_button_width = 16;
53                 private bool clicked;
54                 private int max_length;
55                 private ComboListBox listbox_ctrl;
56                 private StringFormat string_format;
57                 private TextBox textbox_ctrl;
58                 private bool process_textchanged_event;
59
60                 internal class ComboBoxInfo
61                 {
62                         internal int item_height;               /* Item's height */
63                         internal Rectangle textarea;            /* Rectangle of the editable text area  */
64                         internal Rectangle textarea_drawable;   /* Rectangle of the editable text area - decorations - button if present*/
65                         internal Rectangle button_rect;
66                         internal bool show_button;              /* Is the DropDown button shown? */
67                         internal ButtonState button_status;     /* Drop button status */
68                         internal Size listbox_size;
69                         internal Rectangle listbox_area;        /* ListBox area in Simple combox, not used in the rest */
70                         internal bool droppeddown;              /* Is the associated ListBox dropped down? */
71
72                         public ComboBoxInfo ()
73                         {
74                                 button_status = ButtonState.Normal;
75                                 show_button = false;
76                                 item_height = 0;
77                                 droppeddown = false;
78                         }
79                 }
80
81                 internal class ComboBoxItem
82                 {
83                         internal int Index;
84
85                         public ComboBoxItem (int index)
86                         {
87                                 Index = index;
88                         }
89                 }
90
91                 public ComboBox ()
92                 {
93                         items = new ObjectCollection (this);
94                         listbox_ctrl = null;
95                         textbox_ctrl = null;
96                         combobox_info = new ComboBoxInfo ();                    
97                         DropDownStyle = ComboBoxStyle.DropDown;
98                         BackColor = ThemeEngine.Current.ColorWindow;
99                         draw_mode = DrawMode.Normal;
100                         selected_index = -1;
101                         selected_item = null;
102                         maxdrop_items = 8;                      
103                         combobox_info.item_height = FontHeight + 2;
104                         suspend_ctrlupdate = false;
105                         clicked = false;
106                         dropdown_width = -1;
107                         max_length = 0;
108                         integral_height = true;
109                         process_textchanged_event = true;
110                         
111                         string_format = new StringFormat ();
112                         
113
114                         /* Events */
115                         MouseDown += new MouseEventHandler (OnMouseDownCB);
116                         MouseUp += new MouseEventHandler (OnMouseUpCB);                 
117                 }
118
119                 #region Events
120                 public new event EventHandler BackgroundImageChanged;
121                 public event DrawItemEventHandler DrawItem;
122                 public event EventHandler DropDown;
123                 public event EventHandler DropDownStyleChanged;
124                 public event MeasureItemEventHandler MeasureItem;
125                 public new event PaintEventHandler Paint;
126                 public event EventHandler SelectedIndexChanged;
127                 public event EventHandler SelectionChangeCommitted;
128                 #endregion Events
129
130                 #region Public Properties
131                 public override Color BackColor {
132                         get { return base.BackColor; }
133                         set {
134                                 if (base.BackColor == value)
135                                         return;
136
137                                 base.BackColor = value;
138                                 Refresh ();
139                         }
140                 }
141
142                 public override Image BackgroundImage {
143                         get { return base.BackgroundImage; }
144                         set {
145                                 if (base.BackgroundImage == value)
146                                         return;
147
148                                 base.BackgroundImage = value;
149
150                                 if (BackgroundImageChanged != null)
151                                         BackgroundImageChanged (this, EventArgs.Empty);
152
153                                 Refresh ();
154                         }
155                 }
156
157                 protected override CreateParams CreateParams {
158                         get { return base.CreateParams;}
159                 }
160
161                 protected override Size DefaultSize {
162                         get { return new Size (121, PreferredHeight); }
163                 }
164
165                 public DrawMode DrawMode {
166                         get { return draw_mode; }
167
168                         set {
169                                 if (!Enum.IsDefined (typeof (DrawMode), value))
170                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
171
172                                 if (draw_mode == value)
173                                         return;
174
175                                 draw_mode = value;
176                                 Refresh ();
177                         }
178                 }
179
180                 public ComboBoxStyle DropDownStyle {
181                         get { return dropdown_style; }
182
183                         set {
184                                 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
185                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
186
187                                 if (dropdown_style == value)
188                                         return;                                 
189                                                                         
190                                 if (dropdown_style == ComboBoxStyle.Simple) {
191                                         if (listbox_ctrl != null) {
192                                                 listbox_ctrl.Dispose ();
193                                                 Controls.Remove (listbox_ctrl);
194                                                 listbox_ctrl = null;
195                                         }
196                                 }
197
198                                 if (dropdown_style != ComboBoxStyle.DropDownList && value == ComboBoxStyle.DropDownList) {
199                                         if (textbox_ctrl != null) {
200                                                 Controls.Remove (textbox_ctrl);
201                                                 textbox_ctrl.Dispose ();
202                                                 textbox_ctrl = null;
203                                         }
204                                 }
205                                 
206                                 
207                                 dropdown_style = value;                                 
208                                 
209                                 if (dropdown_style == ComboBoxStyle.Simple) {
210                                         CBoxInfo.show_button = false;                                   
211                                         CreateComboListBox ();
212                                         Controls.Add (listbox_ctrl);
213                                 }
214                                 else {
215                                         CBoxInfo.show_button = true;
216                                         CBoxInfo.button_status = ButtonState.Normal;
217                                 }                               
218                                 
219                                 if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
220                                         textbox_ctrl = new TextBox ();
221                                         textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
222                                         Controls.Add (textbox_ctrl);                                                                            
223                                 }
224                                 
225                                 if (DropDownStyleChanged  != null)
226                                         DropDownStyleChanged (this, EventArgs.Empty);
227                                 
228                                 CalcTextArea ();
229                                 Refresh ();
230                         }
231                 }
232
233                 public int DropDownWidth {
234                         get { 
235                                 if (dropdown_width == -1)
236                                         return Width;
237                                         
238                                 return dropdown_width; 
239                         }
240                         set {
241                                 if (dropdown_width == value)
242                                         return;
243                                         
244                                 if (value < 1)
245                                         throw new ArgumentException ("The DropDownWidth value is less than one");
246
247                                 dropdown_width = value;                         
248                         }
249                 }
250                 
251                 public bool DroppedDown {
252                         get { 
253                                 if (dropdown_style == ComboBoxStyle.Simple)                             
254                                         return true;
255                                 
256                                 return CBoxInfo.droppeddown;
257                         }
258                         set {
259                                 if (dropdown_style == ComboBoxStyle.Simple)                             
260                                         return;
261                                         
262                                         
263                                 if (value == true) {
264                                         DropDownListBox ();
265                                 }
266                                 else {
267                                         listbox_ctrl.Hide ();
268                                 }
269                                 
270                                 if (DropDown != null)
271                                         DropDown (this, EventArgs.Empty);
272                         }
273                 }               
274
275                 public override bool Focused {
276                         get { return base.Focused; }
277                 }
278
279                 public override Color ForeColor {
280                         get { return base.ForeColor; }
281                         set {
282                                 if (base.ForeColor == value)
283                                         return;
284
285                                 base.ForeColor = value;
286                                 Refresh ();
287                         }
288                 }
289
290                 public bool IntegralHeight {
291                         get { return integral_height; }
292                         set {
293                                 if (integral_height == value)
294                                         return;
295
296                                 integral_height = value;
297                                 Refresh ();
298                         }
299                 }
300
301                 public virtual int ItemHeight {
302                         get { return combobox_info.item_height; }
303                         set {
304                                 if (value < 0)
305                                         throw new ArgumentOutOfRangeException ("The item height value is less than zero");
306
307                                 combobox_info.item_height = value;
308                                 Refresh ();
309                         }
310                 }
311
312
313                 public ComboBox.ObjectCollection Items {
314                         get { return items; }
315                 }
316
317                 public int MaxDropDownItems {
318                         get { return maxdrop_items; }
319                         set {
320                                 if (maxdrop_items == value)
321                                         return;
322
323                                 maxdrop_items = value;
324                         }
325                 }
326
327                 public int MaxLength {
328                         get { return max_length; }
329                         set {
330                                 if (max_length == value)
331                                         return;
332
333                                 max_length = value;
334                                 
335                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
336                                         
337                                         if (value < 0) {
338                                                 value = 0;
339                                         }
340                                         
341                                         textbox_ctrl.MaxLength = value;
342                                 }                       
343                         }
344                 }
345
346                 public int PreferredHeight {
347                         get { return preferred_height; }
348                 }
349
350                 public override int SelectedIndex {
351                         get { return selected_index; }
352                         set {
353                                 if (value < -2 || value >= Items.Count)
354                                         throw new ArgumentOutOfRangeException ("Index of out range");
355
356                                 if (selected_index == value)
357                                         return;
358
359                                 selected_index = value;
360                                 
361                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
362                                         SetControlText (Items[selected_index].ToString ());
363                                 }
364                                 
365                                 OnSelectedIndexChanged  (new EventArgs ());
366                                 Refresh ();
367                         }
368                 }
369
370                 public object SelectedItem {
371                         get {
372                                 if (selected_index !=-1 && Items !=null && Items.Count > 0)
373                                         return Items[selected_index];
374                                 else
375                                         return null;
376                                 }                               
377                         set {
378                                 if (selected_item == value)
379                                         return;
380
381                                 int index = Items.IndexOf (value);
382
383                                 if (index == -1)
384                                         return;
385
386                                 selected_index = index;
387                                 
388                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
389                                         SetControlText (Items[selected_index].ToString ());
390                                 }
391                                 
392                                 OnSelectedItemChanged  (new EventArgs ());
393                                 Refresh ();
394                         }
395                 }
396                 
397                 public string SelectedText {
398                         get {
399                                 if (dropdown_style == ComboBoxStyle.DropDownList)
400                                         return "";
401                                         
402                                 return textbox_ctrl.Text;
403                         }
404                         set {
405                                 if (dropdown_style == ComboBoxStyle.DropDownList)
406                                         return;
407                                 
408                                 if (textbox_ctrl.Text == value)
409                                         return;
410                                         
411                                 textbox_ctrl.SelectedText = value;
412                         }
413                 }
414
415                 public int SelectionLength {
416                         get {
417                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
418                                         return 0;
419                                 
420                                 return textbox_ctrl.SelectionLength;
421                         }
422                         set {
423                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
424                                         return;
425                                         
426                                 if (textbox_ctrl.SelectionLength == value)
427                                         return;
428                                         
429                                 textbox_ctrl.SelectionLength = value;
430                         }
431                 }
432
433                 public int SelectionStart {
434                         get { 
435                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
436                                         return 0;                                       
437                                 
438                                 return textbox_ctrl.SelectionStart;                             
439                         }
440                         set {
441                                 if (dropdown_style == ComboBoxStyle.DropDownList) 
442                                         return;
443                                 
444                                 if (textbox_ctrl.SelectionStart == value)
445                                         return;                                 
446                                 
447                                 textbox_ctrl.SelectionStart = value;
448                         }
449                 }
450
451                 public bool Sorted {
452                         get { return sorted; }
453
454                         set {
455                                 if (sorted == value)
456                                         return;
457
458                                 sorted = value;
459                         }
460                 }
461
462                 public override string Text {
463                         get { 
464                                 if (SelectedItem != null) 
465                                         return SelectedItem.ToString ();
466                                                                 
467                                 return base.Text;                               
468                         }
469                         set {                           
470                                 if (value == null) {
471                                         SelectedIndex = -1;
472                                         return;
473                                 }
474                                 
475                                 int index = FindString (value);
476                                 
477                                 if (index != -1) {
478                                         SelectedIndex = -1;
479                                         return;                                 
480                                 }
481                                 
482                                 if (dropdown_style != ComboBoxStyle.DropDownList) {
483                                         textbox_ctrl.Text = value.ToString ();
484                                 }                               
485                         }
486                 }
487
488                 #endregion Public Properties
489
490                 #region Private Properties
491                 internal ComboBoxInfo CBoxInfo {
492                         get { return combobox_info; }
493                 }
494
495                 #endregion Private Properties
496
497                 #region Public Methods
498                 protected virtual void AddItemsCore (object[] value)
499                 {
500                         
501                 }
502
503                 public void BeginUpdate ()
504                 {
505                         suspend_ctrlupdate = true;
506                 }
507
508                 protected override void Dispose (bool disposing)
509                 {                                               
510                         if (disposing == true) {
511                                 if (listbox_ctrl != null) {
512                                         listbox_ctrl.Dispose ();
513                                         Controls.Remove (listbox_ctrl);
514                                         listbox_ctrl = null;
515                                 }                       
516                         
517                                 if (textbox_ctrl != null) {
518                                         Controls.Remove (textbox_ctrl);
519                                         textbox_ctrl.Dispose ();
520                                         textbox_ctrl = null;
521                                 }                       
522                         }
523                         
524                         base.Dispose (disposing);
525                 }
526
527                 public void EndUpdate ()
528                 {
529                         suspend_ctrlupdate = false;
530                         Refresh ();
531                 }
532
533                 public int FindString (string s)
534                 {
535                         return FindString (s, 0);
536                 }
537
538                 public int FindString (string s, int startIndex)
539                 {
540                         for (int i = startIndex; i < Items.Count; i++) {
541                                 if ((Items[i].ToString ()).StartsWith (s))
542                                         return i;
543                         }
544
545                         return -1;
546                 }
547
548                 public int FindStringExact (string s)
549                 {
550                         return FindStringExact (s, 0);
551                 }
552
553                 public int FindStringExact (string s, int startIndex)
554                 {
555                         for (int i = startIndex; i < Items.Count; i++) {
556                                 if ((Items[i].ToString ()).Equals (s))
557                                         return i;
558                         }
559
560                         return -1;
561                 }
562
563                 public int GetItemHeight (int index)
564                 {
565                         if (index < 0 || index >= Items.Count )
566                                 throw new ArgumentOutOfRangeException ("The item height value is less than zero");
567
568                         if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {                                
569                                 MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
570                                                                 
571                                 OnMeasureItem (args);                                           
572                                 return args.ItemHeight;
573                                 
574                         } else {
575                                 return ItemHeight;
576                         }                       
577                 }
578
579                 protected override bool IsInputKey (Keys keyData)
580                 {
581                         switch (keyData) {
582                         case Keys.Up:
583                         case Keys.Down:
584                         case Keys.PageUp:
585                         case Keys.PageDown:                     
586                                 return true;
587                         
588                         default:                                        
589                                 return false;
590                         }
591                 }
592
593                 protected override void OnBackColorChanged (EventArgs e)
594                 {
595                         base.OnBackColorChanged (e);
596                 }
597
598                 protected override void OnDataSourceChanged (EventArgs e)
599                 {
600                         base.OnDataSourceChanged (e);
601                 }
602
603                 protected override void OnDisplayMemberChanged (EventArgs e)
604                 {
605                         base.OnDisplayMemberChanged (e);
606                 }
607
608                 protected virtual void OnDrawItem (DrawItemEventArgs e)
609                 {
610                         if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) {
611                                 DrawItem (this, e);
612                                 return;
613                         }
614                         
615                         Rectangle text_draw = e.Bounds;
616                         
617                         if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
618
619                                 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
620                                         (ThemeEngine.Current.ColorHilight), text_draw);
621
622                                 if (e.Index != -1) {
623                                         e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
624                                                 ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHilightText),
625                                                 text_draw, string_format);
626                                 }
627
628                                 // It seems to be a bug in CPDrawFocusRectangle
629                                 //ThemeEngine.Current.CPDrawFocusRectangle (e.Graphics, e.Bounds,
630                                 //      ThemeEngine.Current.ColorHilightText, BackColor);
631                         }
632                         else {                          
633                                 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
634                                         (e.BackColor), e.Bounds);
635
636                                 if (e.Index != -1) {
637                                         e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
638                                                 ThemeEngine.Current.ResPool.GetSolidBrush (e.ForeColor),
639                                                 text_draw, string_format);
640                                 }
641                         }
642                 }               
643 \r
644                 protected virtual void OnDropDown (EventArgs e)
645                 {
646                         if (DropDown != null)
647                                 DropDown (this, e);
648                 }
649
650                 protected virtual void OnDropDownStyleChanged (EventArgs e)
651                 {
652                         if (DropDownStyleChanged != null)
653                                 DropDownStyleChanged (this, e);
654                 }
655
656                 protected override void OnFontChanged (EventArgs e)
657                 {
658                         base.OnFontChanged (e);
659                         
660                         if (textbox_ctrl != null) {
661                                 textbox_ctrl.Font = Font;
662                         }
663                         
664                         combobox_info.item_height = FontHeight + 2;
665                         CalcTextArea ();
666                 }
667
668                 protected override void OnForeColorChanged (EventArgs e)
669                 {
670                         base.OnForeColorChanged (e);
671                 }
672
673                 protected override void OnHandleCreated (EventArgs e)
674                 {
675                         base.OnHandleCreated (e);
676                         CalcTextArea ();
677                 }
678
679                 protected override void OnHandleDestroyed (EventArgs e)
680                 {
681                         base.OnHandleDestroyed (e);
682                 }
683
684                 protected override void OnKeyPress (KeyPressEventArgs e)
685                 {
686                         base.OnKeyPress (e);
687                 }
688
689                 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
690                 {
691                         if (MeasureItem != null)
692                                 MeasureItem (this, e);
693                 }
694
695                 protected override void OnParentBackColorChanged (EventArgs e)
696                 {
697                         base.OnParentBackColorChanged (e);
698                 }
699
700                 protected override void OnResize (EventArgs e)
701                 {
702                         base.OnResize (e);                      
703                         CalcTextArea ();                        
704                 }
705
706                 protected override void OnSelectedIndexChanged (EventArgs e)
707                 {
708                         base.OnSelectedIndexChanged (e);
709
710                         if (SelectedIndexChanged != null)
711                                 SelectedIndexChanged (this, e);
712                 }
713
714                 protected virtual void OnSelectedItemChanged (EventArgs e)
715                 {
716
717                 }
718
719                 protected override void OnSelectedValueChanged (EventArgs e)
720                 {
721                         base.OnSelectedValueChanged (e);
722                 }
723
724                 protected virtual void OnSelectionChangeCommitted (EventArgs e)
725                 {
726
727                 }
728
729                 protected override void RefreshItem (int index)
730                 {
731                         
732                 }
733
734                 public void Select (int start, int lenght)
735                 {
736                         if (start < 0)
737                                 throw new ArgumentException ("Start cannot be less than zero");
738                                 
739                         if (lenght < 0)
740                                 throw new ArgumentException ("Start cannot be less than zero");
741                                 
742                         if (dropdown_style == ComboBoxStyle.DropDownList)
743                                 return;
744                                 
745                         textbox_ctrl.Select (start, lenght);
746                 }
747
748                 public void SelectAll ()
749                 {
750                         if (dropdown_style == ComboBoxStyle.DropDownList)
751                                 return;
752                                 
753                         textbox_ctrl.SelectAll ();
754                 }               
755
756                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
757                 {
758                         base.SetBoundsCore (x, y, width, height, specified);
759                 }
760
761                 protected override void SetItemCore (int index, object value)
762                 {
763                         if (index < 0 || index >= Items.Count)
764                                 return;
765
766                         Items[index] = value;
767                 }
768
769                 protected override void SetItemsCore (IList value)
770                 {
771
772                 }
773
774                 public override string ToString ()
775                 {
776                         return base.ToString () + ", Items.Count:" + Items.Count;
777                 }
778
779                 protected override void WndProc (ref Message m)
780                 {
781
782                         switch ((Msg) m.Msg) {
783
784                         case Msg.WM_PAINT: {
785                                 PaintEventArgs  paint_event;
786                                 paint_event = XplatUI.PaintEventStart (Handle);
787                                 OnPaintCB (paint_event);
788                                 XplatUI.PaintEventEnd (Handle);
789                                 return;
790                         }
791
792                         case Msg.WM_ERASEBKGND:
793                                 m.Result = (IntPtr) 1;
794                                 return;
795
796                         default:
797                                 break;
798                         }
799
800                         base.WndProc (ref m);
801
802                 }
803
804                 #endregion Public Methods
805
806                 #region Private Methods
807                 
808                 // Calcs the text area size
809                 internal void CalcTextArea ()
810                 {                       
811                         combobox_info.textarea = ClientRectangle;
812                                         
813                         /* Edit area */
814                         combobox_info.textarea.Height = ItemHeight + ThemeEngine.Current.DrawComboBoxEditDecorationTop () +
815                                         ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2;
816                                         // TODO: Does the +2 change at different font resolutions?
817                         
818                         /* Edit area - minus decorations (text drawable area) */
819                         combobox_info.textarea_drawable = combobox_info.textarea;
820                         combobox_info.textarea_drawable.Y += ThemeEngine.Current.DrawComboBoxEditDecorationTop ();
821                         combobox_info.textarea_drawable.X += ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
822                         combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationBottom ();
823                         combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationTop();
824                         combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationRight ();
825                         combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
826                         
827                         /* Non-drawable area */
828                         Region area = new Region (ClientRectangle);
829                         area.Exclude (combobox_info.textarea);
830                         RectangleF bounds = area.GetBounds (DeviceContext);
831                         combobox_info.listbox_area = new Rectangle ((int)bounds.X, (int)bounds.Y, 
832                                 (int)bounds.Width, (int)bounds.Height);                         
833                         
834                         if (CBoxInfo.show_button) {
835                                 combobox_info.textarea_drawable.Width -= def_button_width;
836
837                                 combobox_info.button_rect = new Rectangle (combobox_info.textarea_drawable.X + combobox_info.textarea_drawable.Width,
838                                         combobox_info.textarea_drawable.Y, def_button_width, combobox_info.textarea_drawable.Height);                           
839                                         
840                         }
841                         
842                         if (dropdown_style != ComboBoxStyle.DropDownList) { /* There is an edit control*/
843                                 if (textbox_ctrl != null) {
844                                         textbox_ctrl.Location = new Point (combobox_info.textarea_drawable.X, combobox_info.textarea_drawable.Y);
845                                         textbox_ctrl.Size = new Size (combobox_info.textarea_drawable.Width, combobox_info.textarea_drawable.Height);                                   
846                                 }
847                         }
848                         
849                         if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
850                                 listbox_ctrl.Location = new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
851                                         combobox_info.textarea.Height);
852                                 listbox_ctrl.CalcListBoxArea ();
853                         }
854                 }
855
856                 private void CreateComboListBox ()
857                 {                       
858                         listbox_ctrl = new ComboListBox (this);                 
859                 }
860                 
861                 internal void Draw (Rectangle clip)
862                 {                                       
863                         // No edit control, we paint the edit ourselfs
864                         if (dropdown_style == ComboBoxStyle.DropDownList) {
865
866                                 Rectangle item_rect = combobox_info.textarea;
867                                 
868                                 OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, item_rect,
869                                                         selected_index, DrawItemState.Selected,
870                                                         ForeColor, BackColor));
871                         }                                               
872                         
873                         if (clip.IntersectsWith (combobox_info.listbox_area) == true) {
874                                 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor), 
875                                                 combobox_info.listbox_area);
876                         }
877                         
878                         if (CBoxInfo.show_button) {
879                                 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorButtonFace),
880                                         combobox_info.button_rect);
881
882                                 ThemeEngine.Current.CPDrawComboButton (DeviceContext,
883                                         combobox_info.button_rect, combobox_info.button_status);
884                         }                       
885                         
886                         ThemeEngine.Current.DrawComboBoxEditDecorations (DeviceContext, this, combobox_info.textarea);
887                 }
888
889                 internal void DropDownListBox ()
890                 {
891                         combobox_info.button_status = ButtonState.Pushed;
892                         
893                         if (combobox_info.button_status == ButtonState.Pushed) {
894                                 if (listbox_ctrl == null) {
895                                         CreateComboListBox ();
896                                 }
897
898                                 listbox_ctrl.Location = PointToScreen (new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
899                                         combobox_info.textarea.Height));
900                                                 
901                                 listbox_ctrl.ShowWindow ();
902                         }
903                         
904                         CBoxInfo.droppeddown = true;
905                 }
906                 
907                 internal void DropDownListBoxFinished ()
908                 {
909                         combobox_info.button_status = ButtonState.Normal;
910                         Invalidate (combobox_info.button_rect);
911                         CBoxInfo.droppeddown = false;
912                 }
913                 
914                 private int FindStringCaseInsensitive (string search)
915                 {                       
916                         for (int i = 0; i < Items.Count; i++) \r
917                         {
918                                 
919                                 if (String.Compare (Items[i].ToString (), 0, search, 0, search.Length, true) == 0)
920                                         return i;
921                         }
922
923                         return -1;
924                 }
925
926
927                 internal virtual void OnMouseDownCB (object sender, MouseEventArgs e)
928                 {
929                         /* Click On button*/
930                         if (clicked == false && combobox_info.button_rect.Contains (e.X, e.Y)) {
931
932                                 clicked = true;
933
934                                 if (combobox_info.button_status == ButtonState.Normal) {
935                                         DropDownListBox ();
936                                 }
937                                 
938                                 Invalidate (combobox_info.button_rect);
939                         }
940                 }
941
942                 internal virtual void OnMouseUpCB (object sender, MouseEventArgs e)
943                 {
944                         /* Click on button*/
945                         if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) {
946                                 clicked = false;
947                         }
948
949                 }
950
951                 private void OnPaintCB (PaintEventArgs pevent)
952                 {
953                         if (Width <= 0 || Height <=  0 || Visible == false || suspend_ctrlupdate == true)
954                                 return;
955                                 
956                         /* Copies memory drawing buffer to screen*/
957                         Draw (ClientRectangle);                 
958                         pevent.Graphics.DrawImage (ImageBuffer, ClientRectangle, ClientRectangle, GraphicsUnit.Pixel);
959
960                         if (Paint != null)
961                                 Paint (this, pevent);
962                 }
963                 
964                 private void OnTextChangedEdit (object sender, EventArgs e)
965                 {
966                         if (process_textchanged_event == false)
967                                 return; 
968                                 
969                         int item = FindStringCaseInsensitive (textbox_ctrl.Text);
970                         
971                         if (item == -1)
972                                 return;
973                         
974                         listbox_ctrl.SetTopItem (item);
975                         listbox_ctrl.SetHighLightedItem (item);
976                         
977                 }
978                 
979                 internal void SetControlText (string s)
980                 {               
981                         process_textchanged_event = false; 
982                         textbox_ctrl.Text = s;
983                         process_textchanged_event = true;
984                 }
985                 
986                 private void UpdatedItems ()
987                 {
988                         if (dropdown_style != ComboBoxStyle.Simple)
989                                 return;
990                                 
991                         listbox_ctrl.UpdateLastVisibleItem ();
992                         listbox_ctrl.Refresh ();                        
993                 }
994
995                 #endregion Private Methods
996
997
998                 /*
999                         ComboBox.ObjectCollection
1000                 */
1001                 public class ObjectCollection : IList, ICollection, IEnumerable
1002                 {
1003
1004                         private ComboBox owner;
1005                         internal ArrayList object_items = new ArrayList ();
1006                         internal ArrayList listbox_items = new ArrayList ();
1007
1008                         public ObjectCollection (ComboBox owner)
1009                         {
1010                                 this.owner = owner;
1011                         }
1012
1013
1014                         #region Public Properties
1015                         public virtual int Count {
1016                                 get { return object_items.Count; }
1017                         }
1018
1019                         public virtual bool IsReadOnly {
1020                                 get { return false; }
1021                         }
1022
1023                         public virtual object this [int index] {
1024                                 get {
1025                                         if (index < 0 || index >= Count)
1026                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1027
1028                                         return object_items[index];
1029                                 }
1030                                 set {
1031                                         if (index < 0 || index >= Count)
1032                                                 throw new ArgumentOutOfRangeException ("Index of out range");
1033
1034                                         object_items[index] = value;
1035                                 }
1036                         }
1037
1038                         bool ICollection.IsSynchronized {
1039                                 get { return false; }
1040                         }
1041
1042                         object ICollection.SyncRoot {
1043                                 get { return this; }
1044                         }
1045
1046                         bool IList.IsFixedSize {
1047                                 get { return false; }
1048                         }
1049
1050                         #endregion Public Properties
1051
1052                         #region Public Methods
1053                         public int Add (object item)
1054                         {
1055                                 int idx;
1056
1057                                 idx = AddItem (item);
1058                                 owner.UpdatedItems ();
1059                                 return idx;
1060                         }
1061
1062                         public void AddRange (object[] items)
1063                         {
1064                                 foreach (object mi in items)
1065                                         AddItem (mi);
1066                                         
1067                                 owner.UpdatedItems ();
1068                         }
1069
1070                         public virtual void Clear ()
1071                         {
1072                                 object_items.Clear ();
1073                                 listbox_items.Clear ();
1074                                 owner.UpdatedItems ();
1075
1076                         }
1077                         public virtual bool Contains (object obj)
1078                         {
1079                                 return object_items.Contains (obj);
1080                         }
1081
1082                         public void CopyTo (object[] dest, int arrayIndex)
1083                         {
1084                                 object_items.CopyTo (dest, arrayIndex);
1085                         }
1086
1087                         void ICollection.CopyTo (Array dest, int index)
1088                         {
1089                                 object_items.CopyTo (dest, index);
1090                         }
1091
1092                         public virtual IEnumerator GetEnumerator ()
1093                         {
1094                                 return object_items.GetEnumerator ();
1095                         }
1096
1097                         int IList.Add (object item)
1098                         {
1099                                 return Add (item);
1100                         }
1101
1102                         public virtual int IndexOf (object value)
1103                         {
1104                                 return object_items.IndexOf (value);
1105                         }
1106
1107                         public virtual void Insert (int index,  object item)
1108                         {
1109                                 throw new NotImplementedException ();
1110                         }
1111
1112                         public virtual void Remove (object value)
1113                         {
1114                                 RemoveAt (IndexOf (value));                             
1115                         }
1116
1117                         public virtual void RemoveAt (int index)
1118                         {
1119                                 if (index < 0 || index >= Count)
1120                                         throw new ArgumentOutOfRangeException ("Index of out range");
1121
1122                                 object_items.RemoveAt (index);
1123                                 listbox_items.RemoveAt (index);
1124                                 owner.UpdatedItems ();
1125                         }
1126                         #endregion Public Methods
1127
1128                         #region Private Methods
1129                         private int AddItem (object item)
1130                         {
1131                                 int cnt = object_items.Count;
1132                                 object_items.Add (item);
1133                                 listbox_items.Add (new ComboBox.ComboBoxItem (cnt));                            
1134                                 return cnt;
1135                         }
1136
1137                         internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
1138                         {
1139                                 if (index < 0 || index >= Count)
1140                                         throw new ArgumentOutOfRangeException ("Index of out range");
1141
1142                                 return (ComboBox.ComboBoxItem) listbox_items[index];
1143                         }
1144
1145                         internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
1146                         {
1147                                 if (index < 0 || index >= Count)
1148                                         throw new ArgumentOutOfRangeException ("Index of out range");
1149
1150                                 listbox_items[index] = item;
1151                         }
1152
1153                         #endregion Private Methods
1154                 }
1155
1156                 /*
1157                         class ComboListBox
1158                 */
1159                 internal class ComboListBox : Control
1160                 {
1161                         private ComboBox owner;
1162                         private bool need_vscrollbar;
1163                         private VScrollBar vscrollbar_ctrl;
1164                         private int top_item;                   /* First item that we show the in the current page */
1165                         private int last_item;                  /* Last visible item */
1166                         private int highlighted_item;           /* Item that is currently selected */
1167                         internal int page_size;                 /* Number of listbox items per page */
1168                         private Rectangle textarea_drawable;    /* Rectangle of the drawable text area */
1169                         
1170                         internal enum ItemNavigation
1171                         {
1172                                 First,
1173                                 Last,
1174                                 Next,
1175                                 Previous,
1176                                 NextPage,
1177                                 PreviousPage,
1178                         }
1179
1180                         public ComboListBox (ComboBox owner) : base ()
1181                         {       
1182                                 this.owner = owner;                             
1183                                 need_vscrollbar = false;
1184                                 top_item = 0;
1185                                 last_item = 0;
1186                                 page_size = 0;
1187                                 highlighted_item = -1;
1188
1189                                 MouseDown += new MouseEventHandler (OnMouseDownPUW);
1190                                 MouseMove += new MouseEventHandler (OnMouseMovePUW);                            
1191                                 KeyDown += new KeyEventHandler (OnKeyDownPUW);
1192                                 Paint += new PaintEventHandler (OnPaintPUW);
1193                                 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
1194                                 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
1195
1196                                 /* Vertical scrollbar */
1197                                 vscrollbar_ctrl = new VScrollBar ();
1198                                 vscrollbar_ctrl.Minimum = 0;
1199                                 vscrollbar_ctrl.SmallChange = 1;
1200                                 vscrollbar_ctrl.LargeChange = 1;
1201                                 vscrollbar_ctrl.Maximum = 0;
1202                                 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
1203                                 vscrollbar_ctrl.Visible = false;                                
1204                         }
1205
1206                         protected override CreateParams CreateParams
1207                         {
1208                                 get {
1209                                         CreateParams cp = base.CreateParams;                                    
1210                                         if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) {
1211                                                 cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
1212                                                 cp.ExStyle |= (int)WindowStyles.WS_EX_TOOLWINDOW;
1213                                         }                                       
1214                                         return cp;
1215                                 }
1216                         }
1217
1218                         #region Private Methods
1219
1220                         protected override void CreateHandle ()
1221                         {                       
1222                                 base.CreateHandle ();
1223                                 Controls.Add (vscrollbar_ctrl);
1224                         }
1225
1226                         // Calcs the listbox area
1227                         internal void CalcListBoxArea ()
1228                         {                               
1229                                 int width, height;
1230                                 int item_height = owner.ItemHeight;
1231                                 
1232                                 if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1233                                         width = owner.CBoxInfo.listbox_area.Width;
1234                                         height = owner.CBoxInfo.listbox_area.Height;
1235
1236                                         if (owner.IntegralHeight == true) {
1237                                                 int remaining = (height -
1238                                                         ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1239                                                         ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)) %
1240                                                         (item_height - 2);                                                      
1241                 
1242                                                 if (remaining > 0) {
1243                                                         height -= remaining;                                                    
1244                                                 }
1245                                         }
1246                                 }
1247                                 else { // DropDown or DropDownList
1248                                         
1249                                         width = owner.DropDownWidth;
1250                                         int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;                         
1251                                         
1252                                         if (owner.DrawMode == DrawMode.OwnerDrawVariable) {                                             
1253                                                 height = 0;
1254                                                 for (int i = 0; i < count; i++) {
1255                                                         height += owner.GetItemHeight (i);
1256                                                 }
1257                                                 
1258                                         } else  {
1259                                                 height = (item_height - 2) * count;
1260                                         }
1261                                         
1262                                         
1263                                         height += ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);                           
1264                                         height += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1265
1266                                 }
1267                                 
1268                                 if (owner.Items.Count <= owner.MaxDropDownItems) {
1269                                         need_vscrollbar = false;
1270                                 }
1271                                 else {
1272                                         need_vscrollbar = true;
1273                                         vscrollbar_ctrl.Height = height - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
1274                                                 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1275                                                 
1276                                         vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle), 
1277                                                 ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle));                                       
1278                                                 
1279                                         vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems;
1280                                 }
1281
1282                                 if (vscrollbar_ctrl.Visible != need_vscrollbar)
1283                                         vscrollbar_ctrl.Visible = need_vscrollbar;
1284
1285                                 Size = new Size (width, height);
1286                                 textarea_drawable = ClientRectangle;
1287                                 textarea_drawable.Width = width;
1288                                 textarea_drawable.Height = height;                              
1289
1290                                 // Exclude decorations
1291                                 textarea_drawable.X += ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1292                                 textarea_drawable.Y += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1293                                 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1294                                 textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
1295                                 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);                         
1296                                 textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
1297                                 
1298                                 if (need_vscrollbar)
1299                                         textarea_drawable.Width -= vscrollbar_ctrl.Width;
1300
1301                                 last_item = LastVisibleItem ();                         
1302                                 page_size = textarea_drawable.Height / (item_height - 2);
1303                                 
1304                                 Console.WriteLine ("ComboListBox.CalcListBoxArea {0} page_size {1}, dh: {2}, itemh {3}", textarea_drawable,
1305                                         page_size, textarea_drawable.Height, (item_height - 2));
1306                                         
1307                                 Console.WriteLine ("CalcTextArea  Items:{0}", owner.Items.Count);
1308                         }                       
1309
1310                         private void Draw (Rectangle clip)
1311                         {       
1312                                 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
1313                                         (owner.BackColor), ClientRectangle);
1314
1315                                 if (owner.Items.Count > 0) {
1316                                         Rectangle item_rect;
1317                                         DrawItemState state = DrawItemState.None;
1318                                         
1319                                         for (int i = top_item; i <= last_item; i++) {
1320                                                 item_rect = GetItemDisplayRectangle (i, top_item);
1321
1322                                                 if (clip.IntersectsWith (item_rect) == false)
1323                                                         continue;
1324
1325                                                 /* Draw item */
1326                                                 state = DrawItemState.None;
1327
1328                                                 if (i == highlighted_item)
1329                                                         state |= DrawItemState.Selected;
1330                                                         
1331                                                 owner.OnDrawItem (new DrawItemEventArgs (DeviceContext, owner.Font, item_rect,
1332                                                         i, state, owner.ForeColor, owner.BackColor));
1333                                         }
1334                                 }                       
1335                                 
1336                                 ThemeEngine.Current.DrawComboListBoxDecorations (DeviceContext, owner, ClientRectangle);
1337                         }
1338
1339                         private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
1340                         {
1341                                 if (index < 0 || index >= owner.Items.Count)
1342                                         throw new  ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
1343
1344                                 Rectangle item_rect = new Rectangle ();
1345                                 int height = owner.GetItemHeight (index);
1346
1347                                 item_rect.X = ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
1348                                 item_rect.Width = textarea_drawable.Width;
1349                                 item_rect.Y = 2 + ((height - 2) * (index - first_displayble));
1350                                 item_rect.Height = height;
1351                                 return item_rect;
1352                         }
1353
1354                         public void HideWindow ()
1355                         {
1356                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1357                                         return;
1358                                         
1359                                 owner.DropDownListBoxFinished ();
1360                                 Hide ();
1361                         }
1362
1363                         private int IndexFromPointDisplayRectangle (int x, int y)
1364                         {
1365                                 for (int i = top_item; i <= last_item; i++) {
1366                                         if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1367                                                 return i;
1368                                 }
1369
1370                                 return -1;
1371                         }
1372                         
1373                         protected override bool IsInputKey (Keys keyData)
1374                         {
1375                                 return owner.IsInputKey (keyData);
1376                         }
1377
1378                         private int LastVisibleItem ()
1379                         {
1380                                 Rectangle item_rect;
1381                                 int top_y = textarea_drawable.Y + textarea_drawable.Height;
1382                                 int i = 0;                              
1383                                 
1384                                 for (i = top_item; i < owner.Items.Count; i++) {
1385                                         item_rect = GetItemDisplayRectangle (i, top_item);                              
1386                                         if (item_rect.Y + item_rect.Height > top_y) {
1387                                                 return i;
1388                                         }
1389                                 }
1390                                 return i - 1;
1391                         }
1392                         
1393                         private void NavigateItemVisually (ItemNavigation navigation)
1394                         {
1395                                 int item = -1;
1396                                 
1397                                 switch (navigation) {
1398                                 case ItemNavigation.Next: {
1399                                         if (highlighted_item + 1 < owner.Items.Count) {
1400                                                 
1401                                                 if (highlighted_item + 1 > last_item) {
1402                                                         top_item++;
1403                                                         vscrollbar_ctrl.Value = top_item;
1404                                                 }
1405                                                 item = highlighted_item + 1;
1406                                         }
1407                                         break;
1408                                 }
1409                                 
1410                                 case ItemNavigation.Previous: {
1411                                         if (highlighted_item > 0) {                                             
1412                                                 
1413                                                 if (highlighted_item - 1 < top_item) {                                                  
1414                                                         top_item--;
1415                                                         vscrollbar_ctrl.Value = top_item;                                                       
1416                                                 }
1417                                                 item = highlighted_item - 1;
1418                                         }                                       
1419                                         break;
1420                                 }
1421                                 
1422                                 case ItemNavigation.NextPage: {
1423                                         if (highlighted_item + page_size - 1 > owner.Items.Count) {
1424                                                 top_item = owner.Items.Count - page_size;
1425                                                 vscrollbar_ctrl.Value = top_item;                                               
1426                                                 item = owner.Items.Count - 1;
1427                                         }
1428                                         else {
1429                                                 if (highlighted_item + page_size - 1  > last_item) {
1430                                                         top_item = highlighted_item;
1431                                                         vscrollbar_ctrl.Value = highlighted_item;
1432                                                 }
1433                                         
1434                                                 item = highlighted_item + page_size - 1;
1435                                         }                                       
1436                                         break;
1437                                 }
1438                                 
1439                                 case ItemNavigation.PreviousPage: {                                     
1440                                         
1441                                         /* Go to the first item*/
1442                                         if (highlighted_item - (page_size - 1) <= 0) {
1443                                                                                                                                                 
1444                                                 top_item = 0;
1445                                                 vscrollbar_ctrl.Value = top_item;
1446                                                 item = 0;                       
1447                                         }
1448                                         else { /* One page back */
1449                                                 if (highlighted_item - (page_size - 1)  < top_item) {
1450                                                         top_item = highlighted_item - (page_size - 1);
1451                                                         vscrollbar_ctrl.Value = top_item;
1452                                                 }
1453                                         
1454                                                 item = highlighted_item - (page_size - 1);
1455                                         }
1456                                         
1457                                         break;
1458                                 }                               
1459                                         
1460                                 default:
1461                                         break;
1462                                 }       
1463                                 
1464                                 if (item != -1) {
1465                                         SetHighLightedItem (item);
1466                                         
1467                                         if (owner.DropDownStyle == ComboBoxStyle.Simple) {
1468                                                 owner.SetControlText (owner.Items[item].ToString ());
1469                                         }
1470                                 }
1471                         }
1472                         
1473                         private void OnKeyDownPUW (object sender, KeyEventArgs e)                       
1474                         {                               
1475                                 switch (e.KeyCode) {                    
1476                                 case Keys.Up:
1477                                         NavigateItemVisually (ItemNavigation.Previous);
1478                                         break;                          
1479         
1480                                 case Keys.Down:                         
1481                                         NavigateItemVisually (ItemNavigation.Next);
1482                                         break;
1483                                 
1484                                 case Keys.PageUp:
1485                                         NavigateItemVisually (ItemNavigation.PreviousPage);
1486                                         break;                          
1487         
1488                                 case Keys.PageDown:                             
1489                                         NavigateItemVisually (ItemNavigation.NextPage);
1490                                         break;
1491                                 
1492                                 default:
1493                                         break;
1494                                 }
1495                         }
1496                         
1497                         public void SetHighLightedItem (int index)
1498                         {
1499                                 Rectangle invalidate;
1500                                 
1501                                 if (highlighted_item == index)
1502                                         return;
1503                                 
1504                                 /* Previous item */
1505                                 if (highlighted_item != -1) {
1506                                         invalidate = GetItemDisplayRectangle (highlighted_item, top_item);
1507                                         if (ClientRectangle.Contains (invalidate))
1508                                                 Invalidate (invalidate);
1509                                 }
1510                                 
1511                                 highlighted_item = index;
1512
1513                                  /* Current item */
1514                                 invalidate = GetItemDisplayRectangle (highlighted_item, top_item);
1515                                 if (ClientRectangle.Contains (invalidate))
1516                                         Invalidate (invalidate);
1517                                 
1518                         }                       
1519
1520                         public void SetTopItem (int item)
1521                         {
1522                                 top_item = item;
1523                                 UpdateLastVisibleItem ();
1524                                 Refresh ();
1525                         }
1526                         
1527                         private void OnMouseDownPUW (object sender, MouseEventArgs e)
1528                         {
1529                                 /* Click outside the client area destroys the popup */
1530                                 if (ClientRectangle.Contains (e.X, e.Y) == false) {
1531                                         HideWindow ();
1532                                         return;
1533                                 }
1534
1535                                 /* Click on an element */
1536                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1537                                 if (index == -1) return;
1538
1539                                 owner.SelectedIndex = index;
1540                                 SetHighLightedItem (index);
1541                                 HideWindow ();
1542                         }
1543
1544                         private void OnMouseMovePUW (object sender, MouseEventArgs e)
1545                         {                       
1546                                 if (owner.DropDownStyle == ComboBoxStyle.Simple)
1547                                         return;
1548                                                 
1549                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1550
1551                                 if (index != -1)
1552                                         SetHighLightedItem (index);
1553                         }
1554
1555                         private void OnPaintPUW (Object o, PaintEventArgs pevent)
1556                         {
1557                                 if (Width <= 0 || Height <=  0 || Visible == false)
1558                                         return;
1559
1560                                 Draw (pevent.ClipRectangle);
1561                                 pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
1562                         }
1563
1564                         public void ShowWindow ()
1565                         {
1566                                 CalcListBoxArea ();
1567                                 Show ();
1568                                 Refresh ();
1569                                 
1570                                 if (owner.DropDown != null)
1571                                         owner.DropDown (owner, EventArgs.Empty);
1572                         }
1573                         
1574                         public void UpdateLastVisibleItem ()
1575                         {
1576                                 last_item = LastVisibleItem ();
1577                         }
1578
1579                         // Value Changed
1580                         private void VerticalScrollEvent (object sender, EventArgs e)
1581                         {                               
1582                                 top_item =  vscrollbar_ctrl.Value;
1583                                 UpdateLastVisibleItem ();
1584                                 Refresh ();
1585                         }                       
1586
1587                         #endregion Private Methods
1588                 }
1589         }
1590 }
1591