remove unused vars
[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 max_length;
44                 private int preferred_height;
45                 private int selected_index;
46                 private object selected_item;
47                 internal ObjectCollection items;
48                 private bool suspend_ctrlupdate;
49                 private int maxdrop_items;
50                 private bool integral_height;
51                 private bool sorted;
52                 internal ComboBoxInfo combobox_info;
53                 private readonly int def_button_width = 16;
54                 private bool clicked;
55                 private ListBoxPopUp listbox_popup;
56                 private StringFormat string_format;
57
58                 internal class ComboBoxInfo
59                 {
60                         internal int item_height;               /* Item's height */
61                         internal Rectangle textarea_rect;       /* Rectangle of the editable text area - decorations */
62                         internal Rectangle button_rect;
63                         internal bool show_button;              /* Is the DropDown button shown? */
64                         internal Rectangle client_rect;         /* Client Rectangle. Usually = ClientRectangle except when IntegralHeight has been applied*/
65                         internal ButtonState button_status;     /* Drop button status */
66                         internal Size listbox_size;
67
68                         public ComboBoxInfo ()
69                         {
70                                 button_status = ButtonState.Normal;
71                                 show_button = false;
72                                 item_height = 0;
73                         }
74                 }
75
76                 internal class ComboBoxItem
77                 {
78                         internal int Index;
79
80                         public ComboBoxItem (int index)
81                         {
82                                 Index = index;
83
84                         }
85                 }
86
87                 public ComboBox ()
88                 {
89                         BackColor = ThemeEngine.Current.ColorWindow;
90                         draw_mode = DrawMode.Normal;
91                         selected_index = -1;\r
92                         selected_item = null;
93                         maxdrop_items = 8;
94                         combobox_info = new ComboBoxInfo ();
95                         combobox_info.item_height = FontHeight;
96                         suspend_ctrlupdate = false;
97                         clicked = false;
98
99                         items = new ObjectCollection (this);
100                         string_format = new StringFormat ();
101                         CBoxInfo.show_button = true;
102                         listbox_popup = null;
103
104                         /* Events */
105                         MouseDown += new MouseEventHandler (OnMouseDownCB);
106                         MouseUp += new MouseEventHandler (OnMouseUpCB);
107                         
108                         Console.WriteLine ("ComboBox is still an on going effort. Only ComboBoxStyle.DropDownList is implemented");
109                 }
110
111                 #region Events
112                 public new event EventHandler BackgroundImageChanged;
113                 public event DrawItemEventHandler DrawItem;
114                 public event EventHandler DropDown;
115                 public event EventHandler DropDownStyleChanged;
116                 public event MeasureItemEventHandler MeasureItem;
117                 public new event PaintEventHandler Paint;
118                 public event EventHandler SelectedIndexChanged;
119                 public event EventHandler SelectionChangeCommitted;
120                 #endregion Events
121
122                 #region Public Properties
123                 public override Color BackColor {
124                         get { return base.BackColor; }
125                         set {
126                                 if (base.BackColor == value)
127                                         return;
128
129                                 base.BackColor = value;
130                                 Refresh ();
131                         }
132                 }
133
134                 public override Image BackgroundImage {
135                         get { return base.BackgroundImage; }
136                         set {
137                                 if (base.BackgroundImage == value)
138                                         return;
139
140                                 base.BackgroundImage = value;
141
142                                 if (BackgroundImageChanged != null)
143                                         BackgroundImageChanged (this, EventArgs.Empty);
144
145                                 Refresh ();
146                         }
147                 }
148
149                 protected override CreateParams CreateParams {
150                         get { return base.CreateParams;}
151                 }
152
153                 protected override Size DefaultSize {
154                         get { return new Size (121, PreferredHeight); }
155                 }
156
157                 public DrawMode DrawMode {
158                         get { return draw_mode; }
159
160                         set {
161                                 if (!Enum.IsDefined (typeof (DrawMode), value))
162                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
163
164                                 if (draw_mode == value)
165                                         return;
166
167                                 draw_mode = value;
168                                 Refresh ();
169                         }
170                 }
171
172                 public ComboBoxStyle DropDownStyle {
173                         get { return dropdown_style; }
174
175                         set {
176                                 if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
177                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
178
179                                 if (dropdown_style == value)
180                                         return;
181
182                                 dropdown_style = value;
183                                 Refresh ();
184                         }
185                 }
186
187                 public int DropDownWidth {
188                         get { return dropdown_width; }
189                         set {
190
191                                 if (dropdown_width == value)
192                                         return;
193
194                                 dropdown_width = value;
195                                 Refresh ();
196                         }
197                 }
198
199                 public override bool Focused {
200                         get { return base.Focused; }
201                 }
202
203                 public override Color ForeColor {
204                         get { return base.ForeColor; }
205                         set {
206
207                                 if (base.ForeColor == value)
208                                         return;
209
210                                 base.ForeColor = value;
211                                 Refresh ();
212                         }
213                 }
214
215                 public bool IntegralHeight {
216                         get { return integral_height; }
217                         set {
218                                 if (integral_height == value)
219                                         return;
220
221                                 integral_height = value;
222                         }
223                 }
224
225                 public virtual int ItemHeight {
226                         get { return combobox_info.item_height; }
227                         set {
228                                 if (value < 0)
229                                         throw new ArgumentOutOfRangeException ("The item height value is less than zero");
230
231                                 combobox_info.item_height = value;
232                                 Refresh ();
233                         }
234                 }
235
236
237                 public ComboBox.ObjectCollection Items {
238                         get { return items; }
239                 }
240
241                 public int MaxDropDownItems {
242                         get { return maxdrop_items; }
243                         set {
244                                 if (maxdrop_items == value)
245                                         return;
246
247                                 maxdrop_items = value;
248                         }
249                 }
250
251                 public int MaxLength {
252                         get { return max_length; }
253                         set {
254                                 if (max_length == value)
255                                         return;
256
257                                 max_length = value;
258                         }
259                 }
260
261                 public int PreferredHeight {
262                         get { return preferred_height; }
263                 }
264
265                 public override int SelectedIndex {
266                         get { return selected_index; }
267                         set {
268                                 if (value < -2 || value >= Items.Count)
269                                         throw new ArgumentOutOfRangeException ("Index of out range");
270
271                                 if (selected_index == value)
272                                         return;
273
274                                 selected_index = value;
275                                 OnSelectedIndexChanged  (new EventArgs ());
276                                 Refresh ();
277                         }
278                 }
279
280                 public object SelectedItem {
281                         get {
282                                 if (selected_index !=-1 && Items.Count > 0)
283                                         return Items[selected_index];
284                                 else
285                                         return null;
286                                 }
287                         set {
288                                 if (selected_item == value)
289                                         return;
290
291                                 int index = Items.IndexOf (value);
292
293                                 if (index == -1)
294                                         return;
295
296                                 selected_index = index;
297                                 OnSelectedItemChanged  (new EventArgs ());
298                                 Refresh ();
299                         }
300                 }
301                 \r
302                 public string SelectedText {
303                         get {throw new NotImplementedException ();}
304                         set {}
305                 }
306
307                 public int SelectionLength {
308                         get {throw new NotImplementedException ();}
309                         set {}
310                 }
311
312                 public int SelectionStart {
313                         get {throw new NotImplementedException (); }
314                         set {}
315                 }
316
317                 public bool Sorted {
318                                 get { return sorted; }
319
320                         set {
321                                 if (sorted == value)
322                                         return;
323
324                                 sorted = value;
325                         }
326                 }
327
328                 public override string Text {
329                         get { return ""; /*throw new NotImplementedException ();*/ }
330                         set {}
331                 }
332
333                 #endregion Public Properties
334
335                 #region Private Properties
336                 internal ComboBoxInfo CBoxInfo {
337                         get { return combobox_info; }
338                 }
339
340                 #endregion Private Properties
341
342                 #region Public Methods
343                 protected virtual void AddItemsCore (object[] value)
344                 {
345
346                 }
347
348                 public void BeginUpdate ()
349                 {
350                         suspend_ctrlupdate = true;
351                 }
352
353                 protected virtual void Dispose (bool disposing)
354                 {
355
356                 }
357
358                 public void EndUpdate ()
359                 {
360                         suspend_ctrlupdate = false;
361                         Refresh ();
362                 }
363
364                 public int FindString (string s)
365                 {
366                         return FindString (s, 0);
367                 }
368
369                 public int FindString (string s, int startIndex)
370                 {
371                         for (int i = startIndex; i < Items.Count; i++) {
372                                 if ((Items[i].ToString ()).StartsWith (s))
373                                         return i;
374                         }
375
376                         return -1;
377                 }
378
379                 public int FindStringExact (string s)
380                 {
381                         return FindStringExact (s, 0);
382                 }
383
384                 public int FindStringExact (string s, int startIndex)
385                 {
386                         for (int i = startIndex; i < Items.Count; i++) {
387                                 if ((Items[i].ToString ()).Equals (s))
388                                         return i;
389                         }
390
391                         return -1;
392                 }
393
394                 public int GetItemHeight (int index)
395                 {
396                         throw new NotImplementedException ();
397                 }
398
399                 protected override bool IsInputKey (Keys keyData)
400                 {
401                         return false;
402                 }
403
404                 protected override void OnBackColorChanged (EventArgs e)
405                 {
406                         base.OnBackColorChanged (e);
407                 }
408
409                 protected override void OnDataSourceChanged (EventArgs e)
410                 {
411                         base.OnDataSourceChanged (e);
412                 }
413
414                 protected override void OnDisplayMemberChanged (EventArgs e)
415                 {
416                         base.OnDisplayMemberChanged (e);
417                 }
418
419                 protected virtual void OnDrawItem (DrawItemEventArgs e)
420                 {
421                         if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable))
422                                 DrawItem (this, e);
423
424                         if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
425
426                                 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
427                                         (ThemeEngine.Current.ColorHilight), e.Bounds);
428
429                                 e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
430                                         ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHilightText),
431                                         e.Bounds, string_format);
432
433                                 // It seems to be a bug in CPDrawFocusRectangle
434                                 //ThemeEngine.Current.CPDrawFocusRectangle (e.Graphics, e.Bounds,
435                                 //      ThemeEngine.Current.ColorHilightText, BackColor);
436                         }
437                         else {
438                                 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
439                                         (e.BackColor), e.Bounds);
440
441                                 e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
442                                         ThemeEngine.Current.ResPool.GetSolidBrush (e.ForeColor),
443                                         e.Bounds, string_format);
444                         }
445                 }
446
447                 protected virtual void OnDropDownStyleChanged (EventArgs e)
448                 {
449
450                 }
451
452                 protected override void OnFontChanged (EventArgs e)
453                 {
454                         base.OnFontChanged (e);
455                 }
456
457                 protected override void OnForeColorChanged (EventArgs e)
458                 {
459                         base.OnForeColorChanged (e);
460                 }
461
462                 protected override void OnHandleCreated (EventArgs e)
463                 {
464                         base.OnHandleCreated (e);
465                         CalcTextArea ();
466                 }
467
468                 protected override void OnHandleDestroyed (EventArgs e)
469                 {
470                         base.OnHandleDestroyed (e);
471                 }
472
473                 protected override void OnKeyPress (KeyPressEventArgs e)
474                 {
475
476                 }
477
478                 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
479                 {
480
481                 }
482
483                 protected override void OnParentBackColorChanged (EventArgs e)
484                 {
485                         base.OnParentBackColorChanged (e);
486                 }
487
488                 protected override void OnResize (EventArgs e)
489                 {
490                         base.OnResize (e);
491                         CalcTextArea ();
492                 }
493
494                 protected override void OnSelectedIndexChanged (EventArgs e)
495                 {
496                         base.OnSelectedIndexChanged (e);
497
498                         if (SelectedIndexChanged != null)
499                                 SelectedIndexChanged (this, e);
500                 }
501
502                 protected virtual void OnSelectedItemChanged (EventArgs e)
503                 {
504
505                 }
506
507                 protected override void OnSelectedValueChanged (EventArgs e)
508                 {
509                         base.OnSelectedValueChanged (e);
510                 }
511
512                 protected virtual void OnSelectionChangeCommitted (EventArgs e)
513                 {
514
515                 }
516
517                 protected override void RefreshItem (int index)
518                 {
519
520                 }
521
522
523                 protected virtual void Select (int start, int lenght)
524                 {
525
526                 }
527
528                 public void SelectAll ()
529                 {
530
531                 }
532
533                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
534                 {
535                         base.SetBoundsCore (x, y, width, height, specified);
536                 }
537
538                 protected override void SetItemCore (int index, object value)
539                 {
540                         if (index < 0 || index >= Items.Count)
541                                 return;
542
543                         Items[index] = value;
544                 }
545
546                 protected override void SetItemsCore (IList value)
547                 {
548
549                 }
550
551                 public override string ToString ()
552                 {
553                         throw new NotImplementedException ();
554                 }
555
556                 protected override void WndProc (ref Message m)
557                 {
558
559                         switch ((Msg) m.Msg) {
560
561                         case Msg.WM_PAINT: {
562                                 PaintEventArgs  paint_event;
563                                 paint_event = XplatUI.PaintEventStart (Handle);
564                                 OnPaintCB (paint_event);
565                                 XplatUI.PaintEventEnd (Handle);
566                                 return;
567                         }
568
569                         case Msg.WM_ERASEBKGND:
570                                 m.Result = (IntPtr) 1;
571                                 return;
572
573                         default:
574                                 break;
575                         }
576
577                         base.WndProc (ref m);
578
579                 }
580
581                 #endregion Public Methods
582
583                 #region Private Methods
584
585                 internal void ButtonReleased ()
586                 {
587                         combobox_info.button_status = ButtonState.Normal;
588                         Invalidate (combobox_info.button_rect);
589                 }
590
591                 // Calcs the text area size
592                 internal void CalcTextArea ()
593                 {
594                         combobox_info.textarea_rect = ClientRectangle;
595                         combobox_info.textarea_rect.Y += ThemeEngine.Current.DrawComboBoxDecorationTop ();
596                         combobox_info.textarea_rect.X += ThemeEngine.Current.DrawComboBoxDecorationLeft ();
597                         combobox_info.textarea_rect.Height -= ThemeEngine.Current.DrawComboBoxDecorationBottom ();
598                         combobox_info.textarea_rect.Width -= ThemeEngine.Current.DrawComboBoxDecorationRight ();
599
600                         if (CBoxInfo.show_button) {
601                                 combobox_info.textarea_rect.Width -= def_button_width;
602
603                                 combobox_info.button_rect = new Rectangle (combobox_info.textarea_rect.X + combobox_info.textarea_rect.Width,
604                                         combobox_info.textarea_rect.Y,  def_button_width, combobox_info.textarea_rect.Height);
605                         }
606                 }
607
608                 private void CreateListBoxPopUp ()
609                 {
610                         listbox_popup = new ListBoxPopUp (this);
611                         listbox_popup.Location = PointToScreen (new Point (ClientRectangle.X, ClientRectangle.Y + ClientRectangle.Height));
612                         listbox_popup.Size = combobox_info.listbox_size;
613                 }
614
615                 internal void Draw (Rectangle clip)
616                 {
617                         
618                         // No edit control, we paint the edit are ourselfs
619                         if (dropdown_style == ComboBoxStyle.DropDownList) {
620
621                                 if (selected_index != -1) {
622                                         
623                                         OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, combobox_info.textarea_rect,
624                                                                 selected_index, DrawItemState.Selected,
625                                                                 ForeColor, BackColor));                         
626                                 }
627                                 else
628                                         DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), 
629                                                 ClientRectangle);
630                         }
631
632                         if (CBoxInfo.show_button) {
633                                 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorButtonFace),
634                                         combobox_info.button_rect);
635
636                                 ThemeEngine.Current.CPDrawComboButton (DeviceContext,
637                                         combobox_info.button_rect, combobox_info.button_status);
638                         }
639
640                         ThemeEngine.Current.DrawComboBoxDecorations (DeviceContext, this);
641                 }
642
643                 internal virtual void OnMouseDownCB (object sender, MouseEventArgs e)
644                 {
645                         /* Click On button*/
646                         if (clicked == false && combobox_info.button_rect.Contains (e.X, e.Y)) {
647
648                                 clicked = true;
649
650                                 if (combobox_info.button_status == ButtonState.Normal) {
651                                                 combobox_info.button_status = ButtonState.Pushed;
652                                 }
653                                         else {
654                                         if (combobox_info.button_status == ButtonState.Pushed) {
655                                                 combobox_info.button_status = ButtonState.Normal;
656                                         }
657                                 }
658
659                                 if (combobox_info.button_status == ButtonState.Pushed) {
660                                         if (listbox_popup == null)
661                                                 CreateListBoxPopUp ();
662
663                                         listbox_popup.ShowWindow ();
664                                 }
665
666                                 Invalidate (combobox_info.button_rect);
667                         }
668                 }
669
670                 internal virtual void OnMouseUpCB (object sender, MouseEventArgs e)
671                 {
672                         /* Click on button*/
673                         if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) {
674
675                                 clicked = false;
676                         }
677
678                 }
679
680                 private void OnPaintCB (PaintEventArgs pevent)
681                 {
682                         if (Width <= 0 || Height <=  0 || Visible == false || suspend_ctrlupdate == true)
683                                 return;
684
685                         /* Copies memory drawing buffer to screen*/
686                         Draw (ClientRectangle);
687                         pevent.Graphics.DrawImage (ImageBuffer, ClientRectangle, ClientRectangle, GraphicsUnit.Pixel);
688
689                         if (Paint != null)
690                                 Paint (this, pevent);
691                 }
692
693                 #endregion Private Methods
694
695
696                 /*
697                         ComboBox.ObjectCollection
698                 */
699                 public class ObjectCollection : IList, ICollection, IEnumerable
700                 {
701
702                         private ComboBox owner;
703                         internal ArrayList object_items = new ArrayList ();
704                         internal ArrayList listbox_items = new ArrayList ();
705
706                         public ObjectCollection (ComboBox owner)
707                         {
708                                 this.owner = owner;
709                         }
710
711
712                         #region Public Properties
713                         public virtual int Count {
714                                 get { return object_items.Count; }
715                         }
716
717                         public virtual bool IsReadOnly {
718                                 get { return false; }
719                         }
720
721                         public virtual object this [int index] {
722                                 get {
723                                         if (index < 0 || index >= Count)
724                                                 throw new ArgumentOutOfRangeException ("Index of out range");
725
726                                         return object_items[index];
727                                 }
728                                 set {
729                                         if (index < 0 || index >= Count)
730                                                 throw new ArgumentOutOfRangeException ("Index of out range");
731
732                                         object_items[index] = value;
733                                 }
734                         }
735
736                         bool ICollection.IsSynchronized {
737                                 get { return false; }
738                         }
739
740                         object ICollection.SyncRoot {
741                                 get { return this; }
742                         }
743
744                         bool IList.IsFixedSize {
745                                 get { return false; }
746                         }
747
748                         #endregion Public Properties
749
750                         #region Public Methods
751                         public int Add (object item)
752                         {
753                                 int idx;
754
755                                 idx = AddItem (item);
756                                 return idx;
757                         }
758
759                         public void AddRange (object[] items)
760                         {
761                                 foreach (object mi in items)
762                                         AddItem (mi);
763                         }
764
765
766                         public virtual void Clear ()
767                         {
768                                 object_items.Clear ();
769                                 listbox_items.Clear ();
770
771                         }
772                         public virtual bool Contains (object obj)
773                         {
774                                 return object_items.Contains (obj);
775                         }
776
777                         public void CopyTo (object[] dest, int arrayIndex)
778                         {
779                                 object_items.CopyTo (dest, arrayIndex);
780                         }
781
782                         void ICollection.CopyTo (Array dest, int index)
783                         {
784                                 object_items.CopyTo (dest, index);
785                         }
786
787                         public virtual IEnumerator GetEnumerator ()
788                         {
789                                 return object_items.GetEnumerator ();
790                         }
791
792                         int IList.Add (object item)
793                         {
794                                 return Add (item);
795                         }
796
797                         public virtual int IndexOf (object value)
798                         {
799                                 return object_items.IndexOf (value);
800                         }
801
802                         public virtual void Insert (int index,  object item)
803                         {
804                                 throw new NotImplementedException ();
805                         }
806
807                         public virtual void Remove (object value)
808                         {
809                                 RemoveAt (IndexOf (value));
810
811                         }
812
813                         public virtual void RemoveAt (int index)
814                         {
815                                 if (index < 0 || index >= Count)
816                                         throw new ArgumentOutOfRangeException ("Index of out range");
817
818                                 object_items.RemoveAt (index);
819                                 listbox_items.RemoveAt (index);
820                                 //owner.UpdateItemInfo (false, -1, -1);
821                         }
822                         #endregion Public Methods
823
824                         #region Private Methods
825                         private int AddItem (object item)
826                         {
827                                 int cnt = object_items.Count;
828                                 object_items.Add (item);
829                                 listbox_items.Add (new ComboBox.ComboBoxItem (cnt));
830                                 return cnt;
831                         }
832
833                         internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
834                         {
835                                 if (index < 0 || index >= Count)
836                                         throw new ArgumentOutOfRangeException ("Index of out range");
837
838                                 return (ComboBox.ComboBoxItem) listbox_items[index];
839                         }
840
841                         internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
842                         {
843                                 if (index < 0 || index >= Count)
844                                         throw new ArgumentOutOfRangeException ("Index of out range");
845
846                                 listbox_items[index] = item;
847                         }
848
849                         #endregion Private Methods
850                 }
851
852                 /*
853                         class ListBoxPopUp
854                 */
855                 internal class ListBoxPopUp : Control
856                 {
857                         private ComboBox owner;
858                         private bool need_vscrollbar;
859                         private VScrollBar vscrollbar_ctrl;
860                         private int top_item;                   /* First item that we show the in the current page */
861                         private int last_item;                  /* Last visible item */
862                         private int highlighted_item;           /* Item that is currently selected */
863                         private Rectangle textarea_rect;        /* Rectangle of the drawable text area */
864
865
866                         public ListBoxPopUp (ComboBox owner): base ()
867                         {
868                                 this.owner = owner;
869                                 need_vscrollbar = false;
870                                 top_item = 0;
871                                 last_item = 0;
872                                 highlighted_item = -1;
873
874                                 MouseDown += new MouseEventHandler (OnMouseDownPUW);
875                                 MouseMove += new MouseEventHandler (OnMouseMovePUW);
876                                 MouseUp += new MouseEventHandler (OnMouseUpPUW);
877                                 Paint += new PaintEventHandler (OnPaintPUW);
878                                 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
879                                 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
880
881                                 /* Vertical scrollbar */
882                                 vscrollbar_ctrl = new VScrollBar ();
883                                 vscrollbar_ctrl.Minimum = 0;
884                                 vscrollbar_ctrl.SmallChange = 1;
885                                 vscrollbar_ctrl.LargeChange = 1;
886                                 vscrollbar_ctrl.Maximum = 0;
887                                 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
888                                 vscrollbar_ctrl.Visible = false;
889                         }
890
891                         protected override CreateParams CreateParams
892                         {
893                                 get {
894                                         CreateParams cp = base.CreateParams;
895                                         cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
896                                         cp.ExStyle |= (int)WindowStyles.WS_EX_TOOLWINDOW;
897                                         return cp;
898                                 }
899                         }
900
901
902                         #region Private Methods
903
904                         protected override void CreateHandle ()
905                         {
906                                 base.CreateHandle ();
907                                 Controls.Add (vscrollbar_ctrl);
908                         }
909
910                         // Calcs the listbox area
911                         internal void CalcListBoxArea ()
912                         {
913                                 int width, height;
914
915                                 width = owner.ClientRectangle.Width;
916
917                                 if (owner.Items.Count <= owner.MaxDropDownItems) {
918                                         height = owner.ItemHeight * owner.Items.Count;
919                                         need_vscrollbar = false;
920                                 }
921                                 else {
922                                         height = owner.ItemHeight * owner.MaxDropDownItems;
923                                         need_vscrollbar = true;
924
925                                         vscrollbar_ctrl.Height = height - 1;
926                                         vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - 1, 1);
927
928                                         vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems;
929                                 }
930
931                                 if (vscrollbar_ctrl.Visible != need_vscrollbar)
932                                         vscrollbar_ctrl.Visible = need_vscrollbar;
933
934                                 Size = new Size (width, height);
935                                 textarea_rect = ClientRectangle;
936
937                                 // Exclude decorations
938                                 textarea_rect.X += 1;
939                                 textarea_rect.Y += 1;
940                                 textarea_rect.Width -= 1;
941                                 textarea_rect.Height -= 1;
942
943                                 if (need_vscrollbar)
944                                         textarea_rect.Width -= vscrollbar_ctrl.Width;
945
946                                 last_item = LastVisibleItem ();
947                         }
948
949                         private void Draw (Rectangle clip)
950                         {
951                                 Rectangle cl = ClientRectangle;
952
953                                 if (owner.Items.Count > 0) {
954                                         Rectangle item_rect;
955                                         DrawItemState state = DrawItemState.None;
956
957                                         for (int i = top_item; i < last_item; i++) {
958                                                 item_rect = GetItemDisplayRectangle (i, top_item);
959
960                                                 if (clip.IntersectsWith (item_rect) == false)
961                                                         continue;
962
963                                                 /* Draw item */
964                                                 state = DrawItemState.None;
965
966                                                 if (i  == highlighted_item)
967                                                         state |= DrawItemState.Selected;
968
969                                                 owner.OnDrawItem (new DrawItemEventArgs (DeviceContext, owner.Font, item_rect,
970                                                         i, state, owner.ForeColor, owner.BackColor));
971                                         }
972                                 }
973
974                                 //DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
975                                 //      (owner.BackColor), ClientRectangle);
976
977                                 DeviceContext.DrawRectangle (ThemeEngine.Current.ResPool.GetPen (ThemeEngine.Current.ColorWindowFrame),
978                                         cl.X, cl.Y, cl.Width - 1, cl.Height - 1);
979                         }
980
981                         private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
982                         {
983                                 if (index < 0 || index >= owner.Items.Count)
984                                         throw new  ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
985
986                                 Rectangle item_rect = new Rectangle ();
987
988                                 item_rect.X = 0;
989                                 item_rect.Y = owner.ItemHeight * (index - first_displayble);
990                                 item_rect.Height = owner.ItemHeight;
991                                 item_rect.Width = textarea_rect.Width;
992
993                                 return item_rect;
994                         }
995
996                         public void HideWindow ()
997                         {
998                                 owner.ButtonReleased ();
999                                 Hide ();
1000                         }
1001
1002                         private int IndexFromPointDisplayRectangle (int x, int y)
1003                         {
1004                                 for (int i = top_item; i < last_item; i++) {
1005                                         if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
1006                                                 return i;
1007                                 }
1008
1009                                 return -1;
1010                         }
1011
1012                         private int LastVisibleItem ()
1013                         {
1014                                 Rectangle item_rect;
1015                                 int top_y = textarea_rect.Y + textarea_rect.Height;
1016                                 int i = 0;
1017
1018                                 for (i = top_item; i < owner.Items.Count; i++) {
1019                                         item_rect = GetItemDisplayRectangle (i, top_item);
1020                                         if (item_rect.Y > top_y)
1021                                                 return i;
1022                                 }
1023                                 return i;
1024                         }
1025
1026                         private void OnMouseDownPUW (object sender, MouseEventArgs e)
1027                         {
1028                                 /* Click outside the client area destroys the popup */
1029                                 if (ClientRectangle.Contains (e.X, e.Y) == false) {
1030                                         HideWindow ();
1031                                         return;
1032                                 }
1033
1034                                 /* Click on an element */
1035                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1036                                 if (index == -1) return;
1037
1038                                 owner.SelectedIndex = index;
1039                                 HideWindow ();
1040                         }
1041
1042                         private void OnMouseUpPUW (object sender, MouseEventArgs e)
1043                         {
1044
1045                         }
1046
1047                         private void OnMouseMovePUW (object sender, MouseEventArgs e)
1048                         {
1049                                 Rectangle invalidate;
1050                                 int index = IndexFromPointDisplayRectangle (e.X, e.Y);
1051
1052                                 if (index == -1) return;
1053
1054                                 /* Previous item */
1055                                 if (highlighted_item != -1) {
1056                                         invalidate = GetItemDisplayRectangle (highlighted_item, top_item);
1057                                         if (ClientRectangle.Contains (invalidate))
1058                                                 Invalidate (invalidate);
1059                                 }
1060
1061                                 highlighted_item = index;
1062
1063                                  /* Current item */
1064                                 invalidate = GetItemDisplayRectangle (highlighted_item, top_item);
1065                                 if (ClientRectangle.Contains (invalidate))
1066                                         Invalidate (invalidate);
1067                         }
1068
1069                         private void OnPaintPUW (Object o, PaintEventArgs pevent)
1070                         {
1071                                 if (Width <= 0 || Height <=  0 || Visible == false)
1072                                         return;
1073
1074                                 Draw (pevent.ClipRectangle);
1075                                 pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
1076                         }
1077
1078                         public void ShowWindow ()
1079                         {
1080                                 CalcListBoxArea ();
1081                                 Show ();
1082                                 Refresh ();
1083                         }
1084
1085                         // Value Changed
1086                         private void VerticalScrollEvent (object sender, EventArgs e)
1087                         {
1088                                 top_item =  vscrollbar_ctrl.Value;
1089                                 last_item = LastVisibleItem ();
1090                                 Refresh ();
1091                         }
1092
1093                         #endregion Private Methods
1094                 }
1095         }
1096
1097 }
1098