X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FManaged.Windows.Forms%2FSystem.Windows.Forms%2FComboBox.cs;h=497504705de6852fa7990120ea79f39879dbca18;hb=f5c9af07ca3c7de8bbdb62a7d7ba8f19d4974b85;hp=8b79c773348c7bff51373e5008fe29cb1ea250f8;hpb=cf1296f0be585d7c2c288908c2b6c64269df4502;p=mono.git diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs index 8b79c773348..497504705de 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ComboBox.cs @@ -17,13 +17,12 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -// Copyright (c) 2004-2005 Novell, Inc. +// Copyright (c) 2004-2006 Novell, Inc. // // Authors: // Jordi Mas i Hernandez, jordi@ximian.com +// Mike Kestner // -// - // NOT COMPLETE using System; @@ -33,6 +32,7 @@ using System.ComponentModel; using System.Reflection; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; +using System.Runtime.InteropServices; namespace System.Windows.Forms @@ -40,97 +40,74 @@ namespace System.Windows.Forms [DefaultProperty("Items")] [DefaultEvent("SelectedIndexChanged")] - [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, (string)null)] + [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] public class ComboBox : ListControl { - private DrawMode draw_mode; - private ComboBoxStyle dropdown_style; - private int dropdown_width; - private const int preferred_height = 20; - private int selected_index; - private object selected_item; + private DrawMode draw_mode = DrawMode.Normal; + private ComboBoxStyle dropdown_style = (ComboBoxStyle)(-1); + private int dropdown_width = -1; + private object selected_item = null; internal ObjectCollection items = null; private bool suspend_ctrlupdate; - private int maxdrop_items; - private bool integral_height; + private int maxdrop_items = 8; + private bool integral_height = true; private bool sorted; - internal ComboBoxInfo combobox_info; - private readonly int def_button_width = 16; - private bool clicked; private int max_length; private ComboListBox listbox_ctrl; - private TextBox textbox_ctrl; - private bool process_textchanged_event; - private bool has_focus; - - internal class ComboBoxInfo - { - internal int item_height; /* Item's height */ - internal Rectangle textarea; /* Rectangle of the editable text area */ - internal Rectangle textarea_drawable; /* Rectangle of the editable text area - decorations - button if present*/ - internal Rectangle button_rect; - internal bool show_button; /* Is the DropDown button shown? */ - internal ButtonState button_status; /* Drop button status */ - internal Size listbox_size; - internal Rectangle listbox_area; /* ListBox area in Simple combox, not used in the rest */ - internal bool droppeddown; /* Is the associated ListBox dropped down? */ - - public ComboBoxInfo () - { - button_status = ButtonState.Normal; - show_button = false; - item_height = 0; - droppeddown = false; + private ComboTextBox textbox_ctrl; + private bool process_textchanged_event = true; + private bool item_height_specified = false; + private int item_height; + private int requested_height = -1; + private Hashtable item_heights; + private bool show_dropdown_button = false; + private ButtonState button_state = ButtonState.Normal; + private bool dropped_down; + private Rectangle text_area; + private Rectangle button_area; + private Rectangle listbox_area; + private const int button_width = 16; + + [ComVisible(true)] + public class ChildAccessibleObject : AccessibleObject { + private ComboBox owner; + private IntPtr handle; + + public ChildAccessibleObject (ComboBox owner, IntPtr handle) { + this.owner = owner; + this.handle = handle; } - } - internal class ComboBoxItem - { - internal int Index; - internal int ItemHeight; /* Only used for OwnerDrawVariable */ - - public ComboBoxItem (int index) - { - Index = index; - ItemHeight = -1; - } + public override string Name { + get { + return base.Name; + } + } } public ComboBox () { items = new ObjectCollection (this); - listbox_ctrl = null; - textbox_ctrl = null; - combobox_info = new ComboBoxInfo (); - combobox_info.item_height = FontHeight + 2; - dropdown_style = (ComboBoxStyle)(-1); DropDownStyle = ComboBoxStyle.DropDown; + item_height = FontHeight + 2; BackColor = ThemeEngine.Current.ColorWindow; - draw_mode = DrawMode.Normal; - selected_index = -1; - selected_item = null; - maxdrop_items = 8; - suspend_ctrlupdate = false; - clicked = false; - dropdown_width = -1; - max_length = 0; - integral_height = true; - process_textchanged_event = true; - has_focus = false; + border_style = BorderStyle.None; /* Events */ MouseDown += new MouseEventHandler (OnMouseDownCB); MouseUp += new MouseEventHandler (OnMouseUpCB); MouseMove += new MouseEventHandler (OnMouseMoveCB); - GotFocus += new EventHandler (OnGotFocus); - LostFocus += new EventHandler (OnLostFocus); + KeyDown +=new KeyEventHandler(OnKeyDownCB); } #region events [Browsable (false)] [EditorBrowsable (EditorBrowsableState.Never)] - public new event EventHandler BackgroundImageChanged; + public new event EventHandler BackgroundImageChanged { + add { base.BackgroundImageChanged += value; } + remove { base.BackgroundImageChanged -= value; } + } public event DrawItemEventHandler DrawItem; public event EventHandler DropDown; @@ -139,7 +116,10 @@ namespace System.Windows.Forms [Browsable (false)] [EditorBrowsable (EditorBrowsableState.Never)] - public new event PaintEventHandler Paint; + public new event PaintEventHandler Paint { + add { base.Paint += value; } + remove { base.Paint -= value; } + } public event EventHandler SelectedIndexChanged; public event EventHandler SelectionChangeCommitted; @@ -166,10 +146,6 @@ namespace System.Windows.Forms return; base.BackgroundImage = value; - - if (BackgroundImageChanged != null) - BackgroundImageChanged (this, EventArgs.Empty); - Refresh (); } } @@ -179,7 +155,7 @@ namespace System.Windows.Forms } protected override Size DefaultSize { - get { return new Size (121, PreferredHeight); } + get { return new Size (121, 21); } } [RefreshProperties(RefreshProperties.Repaint)] @@ -194,7 +170,11 @@ namespace System.Windows.Forms if (draw_mode == value) return; + if (draw_mode == DrawMode.OwnerDrawVariable) + item_heights = null; draw_mode = value; + if (draw_mode == DrawMode.OwnerDrawVariable) + item_heights = new Hashtable (); Refresh (); } } @@ -214,49 +194,48 @@ namespace System.Windows.Forms if (dropdown_style == ComboBoxStyle.Simple) { if (listbox_ctrl != null) { - Controls.Remove (listbox_ctrl); + Controls.RemoveImplicit (listbox_ctrl); listbox_ctrl.Dispose (); listbox_ctrl = null; } } - if (dropdown_style != ComboBoxStyle.DropDownList && value == ComboBoxStyle.DropDownList) { - if (textbox_ctrl != null) { - Controls.Remove (textbox_ctrl); - textbox_ctrl.Dispose (); - textbox_ctrl = null; - } - } - dropdown_style = value; + if (dropdown_style == ComboBoxStyle.DropDownList && textbox_ctrl != null) { + Controls.RemoveImplicit (textbox_ctrl); + textbox_ctrl.Dispose (); + textbox_ctrl = null; + } + if (dropdown_style == ComboBoxStyle.Simple) { - CBoxInfo.show_button = false; + show_dropdown_button = false; + CreateComboListBox (); - if (IsHandleCreated == true) { - Controls.Add (listbox_ctrl); - } - } - else { - CBoxInfo.show_button = true; - CBoxInfo.button_status = ButtonState.Normal; + if (IsHandleCreated) + Controls.AddImplicit (listbox_ctrl); + } else { + show_dropdown_button = true; + button_state = ButtonState.Normal; } if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) { - textbox_ctrl = new TextBox (); + textbox_ctrl = new ComboTextBox (this); + if (selected_item != null) + textbox_ctrl.Text = GetItemText (selected_item); + textbox_ctrl.BorderStyle = BorderStyle.None; textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit); - textbox_ctrl.KeyPress += new KeyPressEventHandler(textbox_ctrl_KeyPress); if (IsHandleCreated == true) { - Controls.Add (textbox_ctrl); + Controls.AddImplicit (textbox_ctrl); } } - if (DropDownStyleChanged != null) - DropDownStyleChanged (this, EventArgs.Empty); + OnDropDownStyleChanged (EventArgs.Empty); - CalcTextArea (); + Layout (); + UpdateBounds (); Refresh (); } } @@ -286,22 +265,16 @@ namespace System.Windows.Forms if (dropdown_style == ComboBoxStyle.Simple) return true; - return CBoxInfo.droppeddown; + return dropped_down; } set { - if (dropdown_style == ComboBoxStyle.Simple) + if (dropdown_style == ComboBoxStyle.Simple || dropped_down == value) return; - - if (value == true) { + if (value) DropDownListBox (); - } - else { + else listbox_ctrl.Hide (); - } - - if (DropDown != null) - DropDown (this, EventArgs.Empty); } } @@ -329,19 +302,29 @@ namespace System.Windows.Forms return; integral_height = value; + UpdateBounds (); Refresh (); } } [Localizable (true)] - public virtual int ItemHeight { - get { return combobox_info.item_height; } + public int ItemHeight { + get { + if (item_height == -1) { + SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font); + item_height = (int) sz.Height; + } + return item_height; + } set { if (value < 0) - throw new ArgumentOutOfRangeException ("The item height value is less than zero"); + throw new ArgumentException ("The item height value is less than zero"); - combobox_info.item_height = value; - CalcTextArea (); + item_height_specified = true; + item_height = value; + if (IntegralHeight) + UpdateBounds (); + Layout (); Refresh (); } } @@ -389,28 +372,24 @@ namespace System.Windows.Forms [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public int PreferredHeight { - get { return preferred_height; } + get { + return ItemHeight + 5; + } } - + [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public override int SelectedIndex { - get { return selected_index; } + get { return Items.IndexOf (selected_item); } set { - if (value < -2 || value >= Items.Count) + if (value <= -2 || value >= Items.Count) throw new ArgumentOutOfRangeException ("Index of out range"); - if (selected_index == value) - return; + object item = null; + if (value != -1) + item = Items [value]; - selected_index = value; - - if (dropdown_style != ComboBoxStyle.DropDownList) { - SetControlText (Items[selected_index].ToString ()); - } - - OnSelectedIndexChanged (new EventArgs ()); - Refresh (); + SelectedItem = item; } } @@ -418,29 +397,28 @@ namespace System.Windows.Forms [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Bindable(true)] public object SelectedItem { - get { - if (selected_index !=-1 && Items !=null && Items.Count > 0) - return Items[selected_index]; - else - return null; - } + get { return selected_item; } set { - int index = Items.IndexOf (value); - - if (index == -1) - return; - - if (selected_index == index) + if (selected_item == value) return; - selected_index = index; - - if (dropdown_style != ComboBoxStyle.DropDownList) { - SetControlText (Items[selected_index].ToString ()); + selected_item = value; + + if (dropdown_style != ComboBoxStyle.DropDownList) { + if (selected_item == null) + SetControlText(""); + else + SetControlText (GetItemText (selected_item)); } - - OnSelectedItemChanged (new EventArgs ()); - Refresh (); + + OnSelectedValueChanged (new EventArgs ()); + OnSelectedIndexChanged (new EventArgs ()); + OnSelectedItemChanged (new EventArgs ()); + if (DropDownStyle == ComboBoxStyle.DropDownList) + Invalidate (); + + if (listbox_ctrl != null) + listbox_ctrl.HighlightedItem = value; } } @@ -454,9 +432,8 @@ namespace System.Windows.Forms return textbox_ctrl.SelectedText; } set { - if (dropdown_style == ComboBoxStyle.DropDownList) { + if (dropdown_style == ComboBoxStyle.DropDownList) return; - } textbox_ctrl.SelectedText = value; } @@ -524,9 +501,8 @@ namespace System.Windows.Forms } } - if (SelectedItem != null) { - return SelectedItem.ToString (); - } + if (SelectedItem != null) + return GetItemText (SelectedItem); return base.Text; } @@ -543,21 +519,13 @@ namespace System.Windows.Forms return; } - if (dropdown_style != ComboBoxStyle.DropDownList) { - textbox_ctrl.Text = value.ToString (); - } + if (dropdown_style != ComboBoxStyle.DropDownList) + textbox_ctrl.Text = GetItemText (value); } } #endregion Public Properties - #region Private Properties - internal ComboBoxInfo CBoxInfo { - get { return combobox_info; } - } - - #endregion Private Properties - #region Public Methods protected virtual void AddItemsCore (object[] value) { @@ -571,15 +539,15 @@ namespace System.Windows.Forms protected override void Dispose (bool disposing) { - if (disposing == true) { + if (disposing) { if (listbox_ctrl != null) { listbox_ctrl.Dispose (); - Controls.Remove (listbox_ctrl); + Controls.RemoveImplicit (listbox_ctrl); listbox_ctrl = null; } if (textbox_ctrl != null) { - Controls.Remove (textbox_ctrl); + Controls.RemoveImplicit (textbox_ctrl); textbox_ctrl.Dispose (); textbox_ctrl = null; } @@ -592,17 +560,25 @@ namespace System.Windows.Forms { suspend_ctrlupdate = false; UpdatedItems (); + Refresh (); } public int FindString (string s) { - return FindString (s, 0); + return FindString (s, -1); } public int FindString (string s, int startIndex) { + if (Items.Count == 0) + return -1; // No exception throwing if empty + + if (startIndex < -1 || startIndex >= Items.Count - 1) + throw new ArgumentOutOfRangeException ("Index of out range"); + + startIndex++; for (int i = startIndex; i < Items.Count; i++) { - if ((Items[i].ToString ()).StartsWith (s)) + if ((GetItemText (Items[i])).StartsWith (s)) return i; } @@ -611,13 +587,20 @@ namespace System.Windows.Forms public int FindStringExact (string s) { - return FindStringExact (s, 0); + return FindStringExact (s, -1); } public int FindStringExact (string s, int startIndex) { + if (Items.Count == 0) + return -1; // No exception throwing if empty + + if (startIndex < -1 || startIndex >= Items.Count - 1) + throw new ArgumentOutOfRangeException ("Index of out range"); + + startIndex++; for (int i = startIndex; i < Items.Count; i++) { - if ((Items[i].ToString ()).Equals (s)) + if ((GetItemText (Items[i])).Equals (s)) return i; } @@ -625,19 +608,19 @@ namespace System.Windows.Forms } public int GetItemHeight (int index) - { - if (index < 0 || index >= Items.Count ) - throw new ArgumentOutOfRangeException ("The item height value is less than zero"); - - if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) { + { + if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated) { + + if (index < 0 || index >= Items.Count ) + throw new ArgumentOutOfRangeException ("The item height value is less than zero"); - if ((Items.GetComboBoxItem (index)).ItemHeight != -1) { - return (Items.GetComboBoxItem (index)).ItemHeight; - } + object item = Items [index]; + if (item_heights.Contains (item)) + return (int) item_heights [item]; MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight); OnMeasureItem (args); - (Items.GetComboBoxItem (index)).ItemHeight = args.ItemHeight; + item_heights [item] = args.ItemHeight; return args.ItemHeight; } @@ -649,6 +632,8 @@ namespace System.Windows.Forms switch (keyData) { case Keys.Up: case Keys.Down: + case Keys.Left: + case Keys.Right: case Keys.PageUp: case Keys.PageDown: return true; @@ -666,11 +651,14 @@ namespace System.Windows.Forms protected override void OnDataSourceChanged (EventArgs e) { base.OnDataSourceChanged (e); - - if (DataSource != null) + BindDataItems (); + + if (DataSource == null || DataManager == null) { SelectedIndex = -1; - - BindDataItems (items); + } + else { + SelectedIndex = DataManager.Position; + } } protected override void OnDisplayMemberChanged (EventArgs e) @@ -680,18 +668,22 @@ namespace System.Windows.Forms if (DataManager == null || !IsHandleCreated) return; - BindDataItems (items); + BindDataItems (); SelectedIndex = DataManager.Position; } protected virtual void OnDrawItem (DrawItemEventArgs e) { - if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) { - DrawItem (this, e); - return; + switch (DrawMode) { + case DrawMode.OwnerDrawFixed: + case DrawMode.OwnerDrawVariable: + if (DrawItem != null) + DrawItem (this, e); + break; + default: + ThemeEngine.Current.DrawComboBoxItem (this, e); + break; } - - ThemeEngine.Current.DrawComboBoxItem (this, e); } protected virtual void OnDropDown (EventArgs e) @@ -709,13 +701,19 @@ namespace System.Windows.Forms protected override void OnFontChanged (EventArgs e) { base.OnFontChanged (e); - - if (textbox_ctrl != null) { + + if (textbox_ctrl != null) textbox_ctrl.Font = Font; - } - combobox_info.item_height = FontHeight + 2; - CalcTextArea (); + if (!item_height_specified) { + SizeF sz = DeviceContext.MeasureString ("The quick brown Fox", Font); + item_height = (int) sz.Height; + } + + if (IntegralHeight) + UpdateBounds (); + + Layout (); } protected override void OnForeColorChanged (EventArgs e) @@ -723,19 +721,58 @@ namespace System.Windows.Forms base.OnForeColorChanged (e); } - protected override void OnHandleCreated (EventArgs e) + [EditorBrowsable(EditorBrowsableState.Advanced)] + protected override void OnGotFocus (EventArgs e) { - base.OnHandleCreated (e); - - if (listbox_ctrl != null) { - Controls.Add (listbox_ctrl); + if (dropdown_style == ComboBoxStyle.DropDownList) { + // We draw DDL styles manually, so they require a + // refresh to have their selection drawn + Invalidate (); } if (textbox_ctrl != null) { - Controls.Add (textbox_ctrl); + textbox_ctrl.SetSelectable (false); + textbox_ctrl.ActivateCaret (true); + textbox_ctrl.ShowSelection = true; + textbox_ctrl.SelectAll (); } - CalcTextArea (); + base.OnGotFocus (e); + } + + [EditorBrowsable(EditorBrowsableState.Advanced)] + protected override void OnLostFocus (EventArgs e) + { + if (dropdown_style == ComboBoxStyle.DropDownList) { + // We draw DDL styles manually, so they require a + // refresh to have their selection drawn + Invalidate (); + } + + if (listbox_ctrl != null && dropped_down) { + listbox_ctrl.HideWindow (); + } + + if (textbox_ctrl != null) { + textbox_ctrl.SetSelectable (true); + textbox_ctrl.ActivateCaret (false); + textbox_ctrl.ShowSelection = false; + } + + base.OnLostFocus (e); + } + + protected override void OnHandleCreated (EventArgs e) + { + base.OnHandleCreated (e); + + if (listbox_ctrl != null) + Controls.AddImplicit (listbox_ctrl); + + if (textbox_ctrl != null) + Controls.AddImplicit (textbox_ctrl); + + Layout (); } protected override void OnHandleDestroyed (EventArgs e) @@ -745,6 +782,10 @@ namespace System.Windows.Forms protected override void OnKeyPress (KeyPressEventArgs e) { + // int index = FindStringCaseInsensitive (e.KeyChar.ToString (), SelectedIndex); + //if (index != -1) + // SelectedIndex = index; + base.OnKeyPress (e); } @@ -760,9 +801,10 @@ namespace System.Windows.Forms } protected override void OnResize (EventArgs e) - { - base.OnResize (e); - CalcTextArea (); + { + Layout (); + if (listbox_ctrl != null) + listbox_ctrl.CalcListBoxArea (); } protected override void OnSelectedIndexChanged (EventArgs e) @@ -775,8 +817,7 @@ namespace System.Windows.Forms protected virtual void OnSelectedItemChanged (EventArgs e) { - if (SelectedIndexChanged != null) - SelectedIndexChanged (this, e); + } protected override void OnSelectedValueChanged (EventArgs e) @@ -795,35 +836,54 @@ namespace System.Windows.Forms if (index < 0 || index >= Items.Count) throw new ArgumentOutOfRangeException ("Index of out range"); - if (draw_mode == DrawMode.OwnerDrawVariable) { - (Items.GetComboBoxItem (index)).ItemHeight = -1; - } + if (draw_mode == DrawMode.OwnerDrawVariable) + item_heights.Remove (Items [index]); } - public void Select (int start, int lenght) + public void Select (int start, int length) { if (start < 0) throw new ArgumentException ("Start cannot be less than zero"); - if (lenght < 0) - throw new ArgumentException ("Start cannot be less than zero"); + if (length < 0) + throw new ArgumentException ("length cannot be less than zero"); if (dropdown_style == ComboBoxStyle.DropDownList) return; - - textbox_ctrl.Select (start, lenght); + + textbox_ctrl.Select (start, length); } public void SelectAll () { if (dropdown_style == ComboBoxStyle.DropDownList) return; - - textbox_ctrl.SelectAll (); + + if (textbox_ctrl != null) { + textbox_ctrl.ShowSelection = true; + textbox_ctrl.SelectAll (); + } } protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified) - { + { + if ((specified & BoundsSpecified.Height) != 0) { + requested_height = height; + + if (DropDownStyle == ComboBoxStyle.Simple && height > PreferredHeight) { + if (IntegralHeight) { + int border = ThemeEngine.Current.Border3DSize.Height; + int lb_height = height - PreferredHeight - 2; + if (lb_height - 2 * border > ItemHeight) { + int partial = (lb_height - 2 * border) % ItemHeight; + height -= partial; + } else + height = PreferredHeight; + } + } else + height = PreferredHeight; + } + base.SetBoundsCore (x, y, width, height, specified); } @@ -837,7 +897,13 @@ namespace System.Windows.Forms protected override void SetItemsCore (IList value) { - Items.AddRange (value); + BeginUpdate (); + try { + Items.Clear (); + Items.AddRange (value); + } finally { + EndUpdate (); + } } public override string ToString () @@ -847,80 +913,76 @@ namespace System.Windows.Forms protected override void WndProc (ref Message m) { - switch ((Msg) m.Msg) { - - case Msg.WM_PAINT: { - PaintEventArgs paint_event; - paint_event = XplatUI.PaintEventStart (Handle); - OnPaintCB (paint_event); - XplatUI.PaintEventEnd (Handle); - return; - } - - case Msg.WM_ERASEBKGND: - m.Result = (IntPtr) 1; - return; - + case Msg.WM_KEYUP: + case Msg.WM_KEYDOWN: + Keys keys = (Keys) m.WParam.ToInt32 (); + if (keys == Keys.Up || keys == Keys.Down) + break; + goto case Msg.WM_CHAR; + case Msg.WM_CHAR: + if (textbox_ctrl != null) + XplatUI.SendMessage (textbox_ctrl.Handle, (Msg) m.Msg, m.WParam, m.LParam); + break; + case Msg.WM_MOUSE_LEAVE: + Point location = PointToClient (Control.MousePosition); + if (ClientRectangle.Contains (location)) + return; + break; default: break; } - base.WndProc (ref m); - } #endregion Public Methods #region Private Methods - private void textbox_ctrl_KeyPress(object sender, KeyPressEventArgs e) { - OnKeyPress(e); - } + + internal override bool InternalCapture { + get { return Capture; } + set {} + } - // Calcs the text area size - internal void CalcTextArea () + void Layout () { - combobox_info.textarea = ClientRectangle; - - /* Edit area */ - combobox_info.textarea.Height = ItemHeight + ThemeEngine.Current.DrawComboBoxEditDecorationTop () + - ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2; - // TODO: Does the +2 change at different font resolutions? - - /* Edit area - minus decorations (text drawable area) */ - combobox_info.textarea_drawable = combobox_info.textarea; - combobox_info.textarea_drawable.Y += ThemeEngine.Current.DrawComboBoxEditDecorationTop (); - combobox_info.textarea_drawable.X += ThemeEngine.Current.DrawComboBoxEditDecorationLeft (); - combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationBottom (); - combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationTop(); - combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationRight (); - combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationLeft (); - - /* Non-drawable area */ - Region area = new Region (ClientRectangle); - area.Exclude (combobox_info.textarea); - RectangleF bounds = area.GetBounds (DeviceContext); - combobox_info.listbox_area = new Rectangle ((int)bounds.X, (int)bounds.Y, - (int)bounds.Width, (int)bounds.Height); + int border = ThemeEngine.Current.Border3DSize.Width; + + text_area = ClientRectangle; + text_area.Height = PreferredHeight; - if (CBoxInfo.show_button) { - combobox_info.textarea_drawable.Width -= def_button_width; + listbox_area = ClientRectangle; + listbox_area.Y = text_area.Bottom + 3; + listbox_area.Height -= (text_area.Height + 2); - combobox_info.button_rect = new Rectangle (combobox_info.textarea_drawable.X + combobox_info.textarea_drawable.Width, - combobox_info.textarea_drawable.Y, def_button_width, combobox_info.textarea_drawable.Height); - + Rectangle prev_button_area = button_area; + + if (DropDownStyle == ComboBoxStyle.Simple) + button_area = Rectangle.Empty; + else { + button_area = text_area; + button_area.X = text_area.Right - button_width - border; + button_area.Y = text_area.Y + border; + button_area.Width = button_width; + button_area.Height = text_area.Height - 2 * border; } - - if (dropdown_style != ComboBoxStyle.DropDownList) { /* There is an edit control*/ - if (textbox_ctrl != null) { - textbox_ctrl.Location = new Point (combobox_info.textarea_drawable.X, combobox_info.textarea_drawable.Y); - textbox_ctrl.Size = new Size (combobox_info.textarea_drawable.Width, combobox_info.textarea_drawable.Height); - } + + if (button_area != prev_button_area) { + prev_button_area.Y -= border; + prev_button_area.Width += border; + prev_button_area.Height += 2 * border; + Invalidate (prev_button_area); + Invalidate (button_area); } - + + if (textbox_ctrl != null) { + textbox_ctrl.Location = new Point (text_area.X + border, text_area.Y + border); + textbox_ctrl.Width = text_area.Width - button_area.Width - border * 2; + textbox_ctrl.Height = text_area.Height - border * 2; + } + if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) { - listbox_ctrl.Location = new Point (combobox_info.textarea.X, combobox_info.textarea.Y + - combobox_info.textarea.Height); + listbox_ctrl.Location = listbox_area.Location; listbox_ctrl.CalcListBoxArea (); } } @@ -928,39 +990,48 @@ namespace System.Windows.Forms private void CreateComboListBox () { listbox_ctrl = new ComboListBox (this); + if (selected_item != null) + listbox_ctrl.HighlightedItem = selected_item; } internal void Draw (Rectangle clip, Graphics dc) { - // No edit control, we paint the edit ourselfs + Theme theme = ThemeEngine.Current; + + if (DropDownStyle == ComboBoxStyle.Simple) + dc.FillRectangle (theme.ResPool.GetSolidBrush (Parent.BackColor), ClientRectangle); + + if (clip.IntersectsWith (text_area)) + ControlPaint.DrawBorder3D (dc, text_area, Border3DStyle.Sunken); + + int border = theme.Border3DSize.Width; + + // No edit control, we paint the edit ourselves if (dropdown_style == ComboBoxStyle.DropDownList) { DrawItemState state = DrawItemState.None; - Rectangle item_rect = combobox_info.textarea_drawable; - item_rect.Height = ItemHeight + 2; + Rectangle item_rect = text_area; + item_rect.X += border; + item_rect.Y += border; + item_rect.Width -= (button_area.Width + 2 * border); + item_rect.Height -= 2 * border; - if (has_focus == true) { + if (Focused) { state = DrawItemState.Selected; state |= DrawItemState.Focus; } - OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, - selected_index, state, ForeColor, BackColor)); + state |= DrawItemState.ComboBoxEdit; + OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, ForeColor, BackColor)); } - if (clip.IntersectsWith (combobox_info.listbox_area) == true) { - dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor), - combobox_info.listbox_area); - } - - if (CBoxInfo.show_button) { - dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorButtonFace), - combobox_info.button_rect); + if (show_dropdown_button) { + dc.FillRectangle (theme.ResPool.GetSolidBrush (theme.ColorControl), button_area); - ThemeEngine.Current.CPDrawComboButton (dc, - combobox_info.button_rect, combobox_info.button_status); + if (!is_enabled) + button_state = ButtonState.Inactive; + + theme.CPDrawComboButton (dc, button_area, button_state); } - - ThemeEngine.Current.DrawComboBoxEditDecorations (dc, this, combobox_info.textarea); } internal void DropDownListBox () @@ -968,21 +1039,19 @@ namespace System.Windows.Forms if (DropDownStyle == ComboBoxStyle.Simple) return; - if (listbox_ctrl == null) { + if (listbox_ctrl == null) CreateComboListBox (); - } - listbox_ctrl.Location = PointToScreen (new Point (combobox_info.textarea.X, combobox_info.textarea.Y + - combobox_info.textarea.Height)); + listbox_ctrl.Location = PointToScreen (new Point (text_area.X, text_area.Y + text_area.Height)); - if (listbox_ctrl.ShowWindow () == true) { - CBoxInfo.droppeddown = true; - } + if (listbox_ctrl.ShowWindow ()) + dropped_down = true; - combobox_info.button_status = ButtonState.Pushed; - if (dropdown_style == ComboBoxStyle.DropDownList) { - Invalidate (combobox_info.textarea_drawable); - } + button_state = ButtonState.Pushed; + if (dropdown_style == ComboBoxStyle.DropDownList) + Invalidate (text_area); + + OnDropDown (EventArgs.Empty); } internal void DropDownListBoxFinished () @@ -990,86 +1059,114 @@ namespace System.Windows.Forms if (DropDownStyle == ComboBoxStyle.Simple) return; - combobox_info.button_status = ButtonState.Normal; - Invalidate (combobox_info.button_rect); - CBoxInfo.droppeddown = false; - clicked = false; + button_state = ButtonState.Normal; + Invalidate (button_area); + dropped_down = false; } private int FindStringCaseInsensitive (string search) { + if (search.Length == 0) { + return -1; + } + for (int i = 0; i < Items.Count; i++) { - if (String.Compare (Items[i].ToString (), 0, search, 0, search.Length, true) == 0) + if (String.Compare (GetItemText (Items[i]), 0, search, 0, search.Length, true) == 0) return i; } return -1; } - - private void OnGotFocus (object sender, EventArgs e) - { - has_focus = true; - Invalidate (); + + internal int FindStringCaseInsensitive (string search, int start_index) + { + if (search.Length == 0) { + return -1; + } + + for (int i = 0; i < Items.Count; i++) { + int index = (i + start_index) % Items.Count; + if (String.Compare (GetItemText (Items [index]), 0, search, 0, search.Length, true) == 0) + return index; + } + + return -1; } - - private void OnLostFocus (object sender, EventArgs e) - { - has_focus = false; - Invalidate (); - } - internal virtual void OnMouseDownCB (object sender, MouseEventArgs e) - { - /* Click On button*/ - Rectangle hit_rect; - - if (dropdown_style == ComboBoxStyle.DropDownList) { - hit_rect = combobox_info.textarea; - } else { - hit_rect = combobox_info.button_rect; - } - - if (hit_rect.Contains (e.X, e.Y)) { - if (clicked == false) { - clicked = true; - DropDownListBox (); - } else { - listbox_ctrl.Hide (); - DropDownListBoxFinished (); - } - - Invalidate (combobox_info.button_rect); + private void OnKeyDownCB(object sender, KeyEventArgs e) + { + if (Items.Count == 0) + return; + + switch (e.KeyCode) + { + case Keys.Up: + SelectedIndex = Math.Max(SelectedIndex-1, 0); + break; + + case Keys.Down: + SelectedIndex = Math.Min(SelectedIndex+1, Items.Count-1); + break; + + case Keys.PageUp: + if (listbox_ctrl != null) + SelectedIndex = Math.Max(SelectedIndex- (listbox_ctrl.page_size-1), 0); + break; + + case Keys.PageDown: + if (listbox_ctrl != null) + SelectedIndex = Math.Min(SelectedIndex+(listbox_ctrl.page_size-1), Items.Count-1); + break; + + default: + break; + } + } + + void OnMouseDownCB (object sender, MouseEventArgs e) + { + Rectangle area; + if (DropDownStyle == ComboBoxStyle.DropDownList) + area = ClientRectangle; + else + area = button_area; + + if (area.Contains (e.X, e.Y)) { + DropDownListBox (); + Invalidate (button_area); + Update (); } + Capture = true; } - - internal virtual void OnMouseMoveCB (object sender, MouseEventArgs e) + + void OnMouseMoveCB (object sender, MouseEventArgs e) { - /* When there are no items, act as a regular button */ - if (clicked == true && Items.Count == 0 && - combobox_info.button_rect.Contains (e.X, e.Y) == false) { - DropDownListBoxFinished (); - } + if (DropDownStyle == ComboBoxStyle.Simple) + return; + + if (listbox_ctrl != null && listbox_ctrl.Visible) { + Point location = listbox_ctrl.PointToClient (Control.MousePosition); + if (listbox_ctrl.ClientRectangle.Contains (location)) + listbox_ctrl.Capture = true; + } } - internal virtual void OnMouseUpCB (object sender, MouseEventArgs e) + void OnMouseUpCB (object sender, MouseEventArgs e) { - /* Click on button*/ - if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) { - DropDownListBoxFinished (); - } + Capture = false; + OnClick (EventArgs.Empty); + + if (dropped_down) + listbox_ctrl.Capture = true; } - private void OnPaintCB (PaintEventArgs pevent) + internal override void OnPaintInternal (PaintEventArgs pevent) { - if (Width <= 0 || Height <= 0 || Visible == false || suspend_ctrlupdate == true) + if (suspend_ctrlupdate) return; - /* Copies memory drawing buffer to screen*/ Draw (ClientRectangle, pevent.Graphics); - - if (Paint != null) - Paint (this, pevent); } private void OnTextChangedEdit (object sender, EventArgs e) @@ -1081,41 +1178,49 @@ namespace System.Windows.Forms if (item == -1) return; + + // TODO: THIS IS BROKEN-ISH + // I don't think we should hilight, and setting the top item does weirdness + // when there is no scrollbar - listbox_ctrl.SetTopItem (item); - listbox_ctrl.SetHighLightedItem (Items[item]); + if (listbox_ctrl != null) { + listbox_ctrl.SetTopItem (item); + listbox_ctrl.HighlightedItem = Items [item]; + } + + base.Text = textbox_ctrl.Text; } internal void SetControlText (string s) { - process_textchanged_event = false; + process_textchanged_event = false; textbox_ctrl.Text = s; process_textchanged_event = true; } + void UpdateBounds () + { + if (requested_height != -1) + SetBoundsCore (0, 0, 0, requested_height, BoundsSpecified.Height); + } + private void UpdatedItems () { - if (dropdown_style != ComboBoxStyle.Simple) - return; - - listbox_ctrl.UpdateLastVisibleItem (); - listbox_ctrl.CalcListBoxArea (); - listbox_ctrl.Refresh (); + if (listbox_ctrl != null) { + listbox_ctrl.UpdateLastVisibleItem (); + listbox_ctrl.CalcListBoxArea (); + listbox_ctrl.Refresh (); + } } #endregion Private Methods - - /* - ComboBox.ObjectCollection - */ [ListBindableAttribute (false)] public class ObjectCollection : IList, ICollection, IEnumerable { private ComboBox owner; internal ArrayList object_items = new ArrayList (); - internal ArrayList combobox_items = new ArrayList (); public ObjectCollection (ComboBox owner) { @@ -1123,11 +1228,11 @@ namespace System.Windows.Forms } #region Public Properties - public virtual int Count { + public int Count { get { return object_items.Count; } } - public virtual bool IsReadOnly { + public bool IsReadOnly { get { return false; } } @@ -1170,12 +1275,6 @@ namespace System.Windows.Forms } } - internal ArrayList ListBoxItems { - get { return combobox_items;} - set { - combobox_items = value; - } - } #endregion Private Properties #region Public Methods @@ -1196,16 +1295,15 @@ namespace System.Windows.Forms owner.UpdatedItems (); } - public virtual void Clear () + public void Clear () { - owner.selected_index = -1; + owner.selected_item = null; object_items.Clear (); - combobox_items.Clear (); owner.UpdatedItems (); owner.Refresh (); } - public virtual bool Contains (object obj) + public bool Contains (object obj) { return object_items.Contains (obj); } @@ -1220,7 +1318,7 @@ namespace System.Windows.Forms object_items.CopyTo (dest, index); } - public virtual IEnumerator GetEnumerator () + public IEnumerator GetEnumerator () { return object_items.GetEnumerator (); } @@ -1230,44 +1328,24 @@ namespace System.Windows.Forms return Add (item); } - public virtual int IndexOf (object value) + public int IndexOf (object value) { return object_items.IndexOf (value); } - public virtual void Insert (int index, object item) + public void Insert (int index, object item) { - if (index < 0 || index >= Count) + if (index < 0 || index > Count) throw new ArgumentOutOfRangeException ("Index of out range"); - ObjectCollection new_items = new ObjectCollection (owner); - object sel_item = owner.SelectedItem; - owner.BeginUpdate (); - for (int i = 0; i < index; i++) { - new_items.AddItem (ObjectItems[i]); - } - - new_items.AddItem (item); - - for (int i = index; i < Count; i++){ - new_items.AddItem (ObjectItems[i]); - } - - ObjectItems = new_items.ObjectItems; - ListBoxItems = new_items.ListBoxItems; - - if (sel_item != null) { - int idx = IndexOf (sel_item); - owner.selected_index = idx; - owner.listbox_ctrl.SetHighLightedItem (owner.Items[idx]); - } + object_items.Insert (index, item); owner.EndUpdate (); // Calls UpdatedItems } - public virtual void Remove (object value) + public void Remove (object value) { if (IndexOf (value) == owner.SelectedIndex) owner.SelectedItem = null; @@ -1276,7 +1354,7 @@ namespace System.Windows.Forms } - public virtual void RemoveAt (int index) + public void RemoveAt (int index) { if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("Index of out range"); @@ -1285,7 +1363,6 @@ namespace System.Windows.Forms owner.SelectedItem = null; object_items.RemoveAt (index); - combobox_items.RemoveAt (index); owner.UpdatedItems (); } #endregion Public Methods @@ -1295,7 +1372,6 @@ namespace System.Windows.Forms { int cnt = object_items.Count; object_items.Add (item); - combobox_items.Add (new ComboBox.ComboBoxItem (cnt)); return cnt; } @@ -1307,35 +1383,49 @@ namespace System.Windows.Forms owner.UpdatedItems (); } - internal ComboBox.ComboBoxItem GetComboBoxItem (int index) + #endregion Private Methods + } + + internal class ComboTextBox : TextBox { + + private ComboBox owner; + + public ComboTextBox (ComboBox owner) { - if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException ("Index of out range"); + this.owner = owner; + ShowSelection = false; + } - return (ComboBox.ComboBoxItem) combobox_items[index]; + internal void SetSelectable (bool selectable) + { + SetStyle (ControlStyles.Selectable, selectable); } - internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index) + internal void ActivateCaret (bool active) { - if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException ("Index of out range"); + if (active) + document.CaretHasFocus (); + else + document.CaretLostFocus (); + } - combobox_items[index] = item; + internal override void OnGotFocusInternal (EventArgs e) + { + owner.Select (false, true); } - #endregion Private Methods + internal override void OnLostFocusInternal (EventArgs e) + { + owner.Select (false, true); + } } - /* - class ComboListBox - */ internal class ComboListBox : Control { private ComboBox owner; private VScrollBarLB vscrollbar_ctrl; private int top_item; /* First item that we show the in the current page */ private int last_item; /* Last visible item */ - public object highlighted_item; /* Item that is currently selected */ internal int page_size; /* Number of listbox items per page */ private Rectangle textarea_drawable; /* Rectangle of the drawable text area */ @@ -1355,80 +1445,116 @@ namespace System.Windows.Forms { } - public void FireMouseDown (MouseEventArgs e) + internal override bool InternalCapture { + get { return Capture; } + set { } + } + + public bool FireMouseDown (MouseEventArgs e) { - OnMouseDown (e); + if (Visible) { + e = TranslateEvent (e); + if (ClientRectangle.Contains (e.X, e.Y)) { + OnMouseDown (e); + return true; + } + } + return false; } public void FireMouseUp (MouseEventArgs e) { - OnMouseUp (e); + if (Visible) { + e = TranslateEvent (e); + if (ClientRectangle.Contains (e.X, e.Y)) + OnMouseUp (e); + } } public void FireMouseMove (MouseEventArgs e) { - OnMouseMove (e); + if (Visible) { + e = TranslateEvent (e); + if (ClientRectangle.Contains (e.X, e.Y)) + OnMouseMove (e); + } } + MouseEventArgs TranslateEvent (MouseEventArgs e) + { + Point loc = PointToClient (Control.MousePosition); + return new MouseEventArgs (e.Button, e.Clicks, loc.X, loc.Y, e.Delta); + } } - public ComboListBox (ComboBox owner) : base () - { + public ComboListBox (ComboBox owner) + { this.owner = owner; top_item = 0; last_item = 0; page_size = 0; - highlighted_item = null; - MouseDown += new MouseEventHandler (OnMouseDownPUW); - MouseUp += new MouseEventHandler (OnMouseUpPUW); - MouseMove += new MouseEventHandler (OnMouseMovePUW); - KeyDown += new KeyEventHandler (OnKeyDownPUW); - Paint += new PaintEventHandler (OnPaintPUW); + MouseWheel += new MouseEventHandler (OnMouseWheelCLB); + SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); - SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true); + SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true); + + if (owner.DropDownStyle == ComboBoxStyle.Simple) + InternalBorderStyle = BorderStyle.Fixed3D; + else + InternalBorderStyle = BorderStyle.FixedSingle; } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; - if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) { - cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN)); - cp.ExStyle |= (int)(WindowStyles.WS_EX_TOOLWINDOW | WindowStyles.WS_EX_TOPMOST); - } + if (owner == null || owner.DropDownStyle == ComboBoxStyle.Simple) + return cp; + + cp.Style ^= (int) WindowStyles.WS_CHILD; + cp.Style |= (int) WindowStyles.WS_POPUP; + cp.ExStyle |= (int) WindowExStyles.WS_EX_TOOLWINDOW | (int) WindowExStyles.WS_EX_TOPMOST; return cp; } } - #region Private Methods + protected override void Select (bool directed, bool forward) + { + // Do nothing, we never want to be selected + } - protected override void CreateHandle () - { - base.CreateHandle (); + internal override bool InternalCapture { + get { + return Capture; + } + + set { + } } + int BorderWidth { + get { + switch (border_style) { + case BorderStyle.Fixed3D: + return ThemeEngine.Current.Border3DSize.Width; + default: + return ThemeEngine.Current.BorderSize.Width; + } + } + } + + #region Private Methods // Calcs the listbox area internal void CalcListBoxArea () { int width, height; - int item_height = owner.ItemHeight; bool show_scrollbar = false; if (owner.DropDownStyle == ComboBoxStyle.Simple) { - width = owner.CBoxInfo.listbox_area.Width; - height = owner.CBoxInfo.listbox_area.Height; - - if (owner.IntegralHeight == true) { - int remaining = (height - - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) - - ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)) % - (item_height - 2); - - if (remaining > 0) { - height -= remaining; - } - } + Rectangle area = owner.listbox_area; + width = area.Width; + height = area.Height; } else { // DropDown or DropDownList @@ -1442,22 +1568,14 @@ namespace System.Windows.Forms } } else { - height = (item_height - 2) * count; + height = owner.ItemHeight * count; } - - - height += ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle); - height += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle); } if (owner.Items.Count <= owner.MaxDropDownItems) { - - /* Does not need vertical scrollbar*/ - if (vscrollbar_ctrl != null) { - vscrollbar_ctrl.Visible = false; - } - } - else { + if (vscrollbar_ctrl != null) + vscrollbar_ctrl.Visible = false; + } else { /* Need vertical scrollbar */ if (vscrollbar_ctrl == null) { vscrollbar_ctrl = new VScrollBarLB (); @@ -1466,60 +1584,50 @@ namespace System.Windows.Forms vscrollbar_ctrl.LargeChange = 1; vscrollbar_ctrl.Maximum = 0; vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent); - - Controls.Add (vscrollbar_ctrl); + Controls.AddImplicit (vscrollbar_ctrl); } - vscrollbar_ctrl.Height = height - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) - - ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle); + vscrollbar_ctrl.Height = height - 2 * BorderWidth; - vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle), - ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)); - - vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems; + vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - BorderWidth - 1, 0); + + vscrollbar_ctrl.Maximum = owner.Items.Count - (owner.DropDownStyle == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items); show_scrollbar = vscrollbar_ctrl.Visible = true; - + + int hli = HighlightedIndex; + if (hli > 0) { + hli = Math.Min (hli, vscrollbar_ctrl.Maximum); + vscrollbar_ctrl.Value = hli; + } } Size = new Size (width, height); textarea_drawable = ClientRectangle; textarea_drawable.Width = width; textarea_drawable.Height = height; - - // Exclude decorations - textarea_drawable.X += ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle); - textarea_drawable.Y += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle); - textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle); - textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle); - textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle); - textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle); if (vscrollbar_ctrl != null && show_scrollbar) textarea_drawable.Width -= vscrollbar_ctrl.Width; - last_item = LastVisibleItem (); - page_size = textarea_drawable.Height / (item_height - 2); + last_item = LastVisibleItem (); + page_size = textarea_drawable.Height / owner.ItemHeight; } private void Draw (Rectangle clip, Graphics dc) { - dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush - (owner.BackColor), ClientRectangle); + dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (owner.BackColor), clip); if (owner.Items.Count > 0) { - Rectangle item_rect; - DrawItemState state = DrawItemState.None; for (int i = top_item; i <= last_item; i++) { - item_rect = GetItemDisplayRectangle (i, top_item); + Rectangle item_rect = GetItemDisplayRectangle (i, top_item); - if (clip.IntersectsWith (item_rect) == false) + if (!clip.IntersectsWith (item_rect)) continue; - /* Draw item */ - state = DrawItemState.None; + DrawItemState state = DrawItemState.None; - if (i == GetHighLightedIndex () ) { + if (i == HighlightedIndex) { state |= DrawItemState.Selected; if (owner.DropDownStyle == ComboBoxStyle.DropDownList) { @@ -1530,22 +1638,38 @@ namespace System.Windows.Forms owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect, i, state, owner.ForeColor, owner.BackColor)); } - } - - ThemeEngine.Current.DrawComboListBoxDecorations (dc, owner, ClientRectangle); - } - - public int GetHighLightedIndex () - { - return owner.Items.IndexOf (highlighted_item); + } } - - public object GetHighLightedItem () - { - return highlighted_item; + + public int HighlightedIndex { + get { return owner.Items.IndexOf (highlighted_item); } + set { + object item = null; + if (value != -1) + item = owner.Items [value]; + HighlightedItem = item; + } } - private Rectangle GetItemDisplayRectangle (int index, int first_displayble) + object highlighted_item = null; + + public object HighlightedItem { + get { return highlighted_item; } + set { + if (highlighted_item == value) + return; + + int index = owner.Items.IndexOf (highlighted_item); + if (index != -1) + Invalidate (GetItemDisplayRectangle (index, top_item)); + highlighted_item = value; + index = owner.Items.IndexOf (highlighted_item); + if (index != -1) + Invalidate (GetItemDisplayRectangle (index, top_item)); + } + } + + private Rectangle GetItemDisplayRectangle (int index, int top_index) { if (index < 0 || index >= owner.Items.Count) throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range."); @@ -1553,9 +1677,15 @@ namespace System.Windows.Forms Rectangle item_rect = new Rectangle (); int height = owner.GetItemHeight (index); - item_rect.X = ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle); + item_rect.X = 0; item_rect.Width = textarea_drawable.Width; - item_rect.Y = 2 + ((height - 2) * (index - first_displayble)); + if (owner.DrawMode == DrawMode.OwnerDrawVariable) { + item_rect.Y = 0; + for (int i = top_index; i < index; i++) + item_rect.Y += owner.GetItemHeight (i); + } else + item_rect.Y = height * (index - top_index); + item_rect.Height = height; return item_rect; } @@ -1567,7 +1697,6 @@ namespace System.Windows.Forms Capture = false; Hide (); - highlighted_item = -1; owner.DropDownListBoxFinished (); } @@ -1580,11 +1709,6 @@ namespace System.Windows.Forms return -1; } - - protected override bool IsInputKey (Keys keyData) - { - return owner.IsInputKey (keyData); - } private int LastVisibleItem () { @@ -1600,269 +1724,71 @@ namespace System.Windows.Forms } return i - 1; } - - private void NavigateItemVisually (ItemNavigation navigation) - { - int item = -1; - - switch (navigation) { - case ItemNavigation.Next: { - if (GetHighLightedIndex () + 1 < owner.Items.Count) { - - if (GetHighLightedIndex () + 1 > last_item) { - top_item++; - vscrollbar_ctrl.Value = top_item; - } - item = GetHighLightedIndex () + 1; - } - break; - } - - case ItemNavigation.Previous: { - if (GetHighLightedIndex () > 0) { - - if (GetHighLightedIndex () - 1 < top_item) { - top_item--; - vscrollbar_ctrl.Value = top_item; - } - item = GetHighLightedIndex () - 1; - } - break; - } - - case ItemNavigation.NextPage: { - if (GetHighLightedIndex () + page_size - 1 >= owner.Items.Count) { - top_item = owner.Items.Count - page_size; - vscrollbar_ctrl.Value = top_item; - item = owner.Items.Count - 1; - } - else { - if (GetHighLightedIndex () + page_size - 1 > last_item) { - top_item = GetHighLightedIndex (); - vscrollbar_ctrl.Value = GetHighLightedIndex (); - } - - item = GetHighLightedIndex () + page_size - 1; - } - break; - } - - case ItemNavigation.PreviousPage: { - - /* Go to the first item*/ - if (GetHighLightedIndex () - (page_size - 1) <= 0) { - - top_item = 0; - vscrollbar_ctrl.Value = top_item; - item = 0; - } - else { /* One page back */ - if (GetHighLightedIndex () - (page_size - 1) < top_item) { - top_item = GetHighLightedIndex () - (page_size - 1); - vscrollbar_ctrl.Value = top_item; - } - - item = GetHighLightedIndex () - (page_size - 1); - } - - break; - } - - default: - break; - } - - if (item != -1) { - SetHighLightedItem (owner.Items[item]); - - owner.OnSelectionChangeCommitted (new EventArgs ()); - - if (owner.DropDownStyle == ComboBoxStyle.Simple) { - owner.SetControlText (owner.Items[item].ToString ()); - } - } - } - - private void OnKeyDownPUW (object sender, KeyEventArgs e) - { - switch (e.KeyCode) { - case Keys.Up: - NavigateItemVisually (ItemNavigation.Previous); - break; - - case Keys.Down: - NavigateItemVisually (ItemNavigation.Next); - break; - - case Keys.PageUp: - NavigateItemVisually (ItemNavigation.PreviousPage); - break; - - case Keys.PageDown: - NavigateItemVisually (ItemNavigation.NextPage); - break; - - default: - break; - } - } - - public void SetHighLightedItem (object item) - { - Rectangle invalidate; - - if (GetHighLightedItem () == item) - return; - - /* Previous item */ - if (GetHighLightedIndex () != -1) { - invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item); - if (ClientRectangle.Contains (invalidate)) - Invalidate (invalidate); - } - - highlighted_item = item; - - if (highlighted_item != null) { - /* Current item */ - invalidate = GetItemDisplayRectangle (GetHighLightedIndex (), top_item); - if (ClientRectangle.Contains (invalidate)) - Invalidate (invalidate); - } - - } public void SetTopItem (int item) { + if (top_item == item) + return; top_item = item; UpdateLastVisibleItem (); Refresh (); } - - private void OnMouseDownPUW (object sender, MouseEventArgs e) - { - Rectangle scrollbar_screenrect; - Point mouse_screen, scrollbar_screen; - mouse_screen = PointToScreen (new Point (e.X, e.Y)); - - /* Click on an element ? */ - int index = IndexFromPointDisplayRectangle (e.X, e.Y); - if (index != -1) { - owner.SelectedIndex = index; - SetHighLightedItem (owner.Items[index]); - owner.OnSelectionChangeCommitted (new EventArgs ()); - HideWindow (); - return; - } - - if (owner.DropDownStyle == ComboBoxStyle.Simple) - return; - - /* Reroute event to scrollbar */ - if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) { - scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle; - scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location); - scrollbar_screenrect.X = scrollbar_screen.X; - scrollbar_screenrect.Y = scrollbar_screen.Y; - - if (scrollbar_screenrect.Contains (mouse_screen)){ - Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen); - vscrollbar_ctrl.FireMouseDown (new MouseEventArgs (e.Button, e.Clicks, - pnt_client.X, pnt_client.Y, e.Delta)); - } else { /* Click in a non-client area*/ - HideWindow (); - } - } else { /* Click in a non-client area*/ - HideWindow (); - } - } - - private void OnMouseMovePUW (object sender, MouseEventArgs e) - { - if (owner.DropDownStyle == ComboBoxStyle.Simple) - return; - - int index = IndexFromPointDisplayRectangle (e.X, e.Y); + + protected override void OnMouseDown (MouseEventArgs e) + { + if (vscrollbar_ctrl != null) + vscrollbar_ctrl.FireMouseDown (e); + } + + protected override void OnMouseMove (MouseEventArgs e) + { + Point pt = PointToClient (Control.MousePosition); + int index = IndexFromPointDisplayRectangle (pt.X, pt.Y); if (index != -1) { - SetHighLightedItem (owner.Items[index]); + HighlightedIndex = index; return; } - if (owner.DropDownStyle == ComboBoxStyle.Simple) - return; - - /* Reroute event to scrollbar */ - if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) { - Rectangle scrollbar_screenrect; - Point mouse_screen, scrollbar_screen; - mouse_screen = PointToScreen (new Point (e.X, e.Y)); - - scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle; - scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location); - scrollbar_screenrect.X = scrollbar_screen.X; - scrollbar_screenrect.Y = scrollbar_screen.Y; - - if (scrollbar_screenrect.Contains (mouse_screen)){ - Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen); - - vscrollbar_ctrl.FireMouseMove (new MouseEventArgs (e.Button, e.Clicks, - pnt_client.X, pnt_client.Y, e.Delta)); - } - } + if (vscrollbar_ctrl != null) + vscrollbar_ctrl.FireMouseMove (e); } - private void OnMouseUpPUW (object sender, MouseEventArgs e) - { - if (owner.DropDownStyle == ComboBoxStyle.Simple) - return; - - /* Reroute event to scrollbar */ - Rectangle scrollbar_screenrect; - Point mouse_screen, scrollbar_screen; - mouse_screen = PointToScreen (new Point (e.X, e.Y)); - - if (vscrollbar_ctrl != null && vscrollbar_ctrl.Visible == true) { - scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle; - scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location); - scrollbar_screenrect.X = scrollbar_screen.X; - scrollbar_screenrect.Y = scrollbar_screen.Y; - - if (scrollbar_screenrect.Contains (mouse_screen)){ - Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen); - - vscrollbar_ctrl.FireMouseUp (new MouseEventArgs (e.Button, e.Clicks, - pnt_client.X, pnt_client.Y, e.Delta)); - } - } - } - - private void OnPaintPUW (Object o, PaintEventArgs pevent) + protected override void OnMouseUp (MouseEventArgs e) { + int index = IndexFromPointDisplayRectangle (e.X, e.Y); + + if (index == -1) { + if (vscrollbar_ctrl == null || !vscrollbar_ctrl.FireMouseDown (e)) + HideWindow (); + } else { + owner.OnSelectionChangeCommitted (new EventArgs ()); + owner.SelectedIndex = index; + HighlightedIndex = index; + HideWindow (); + } + + if (vscrollbar_ctrl != null) + vscrollbar_ctrl.FireMouseUp (e); + } + + internal override void OnPaintInternal (PaintEventArgs pevent) + { Draw (pevent.ClipRectangle,pevent.Graphics); } public bool ShowWindow () { - if (owner.DropDownStyle != ComboBoxStyle.Simple && owner.Items.Count == 0) + if (owner.DropDownStyle == ComboBoxStyle.Simple && owner.Items.Count == 0) return false; - - SetTopItem (0); - SetHighLightedItem (owner.SelectedItem); - + + HighlightedIndex = owner.SelectedIndex; + CalcListBoxArea (); Show (); - - if (owner.DropDownStyle != ComboBoxStyle.Simple) { - Capture = true; - } - + Refresh (); - - if (owner.DropDown != null) { - owner.DropDown (owner, EventArgs.Empty); - } - + owner.OnDropDown (EventArgs.Empty); return true; } @@ -1871,16 +1797,52 @@ namespace System.Windows.Forms last_item = LastVisibleItem (); } + private void Scroll (int delta) + { + if (delta == 0 || !vscrollbar_ctrl.Visible) + return; + + int max = vscrollbar_ctrl.Maximum;//- (page_size) + 1; + + int val = vscrollbar_ctrl.Value + delta; + if (val > max) + val = max; + else if (val < vscrollbar_ctrl.Minimum) + val = vscrollbar_ctrl.Minimum; + vscrollbar_ctrl.Value = val; + } + + private void OnMouseWheelCLB (object sender, MouseEventArgs me) + { + if (owner.Items.Count == 0) + return; + + int lines = me.Delta / 120 * SystemInformation.MouseWheelScrollLines; + Scroll (-lines); + } + // Value Changed private void VerticalScrollEvent (object sender, EventArgs e) { + if (top_item == vscrollbar_ctrl.Value) + return; + top_item = vscrollbar_ctrl.Value; UpdateLastVisibleItem (); Refresh (); } + + protected override void WndProc(ref Message m) { + if (m.Msg == (int)Msg.WM_SETFOCUS) { + if (m.WParam != IntPtr.Zero) { + XplatUI.SetFocus(m.WParam); + } + } + base.WndProc (ref m); + } #endregion Private Methods - } + } } }