diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs index 895a3db..38146fe 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs @@ -16,87 +16,49 @@ namespace Acacia.Controls { #region Drop-down list + /// + /// Custom list for the drop-down. Performs a few functions: + /// - Prevents grabbing the focus away from the edit when clicked + /// - Adds hover highlighting + /// - Only commits selection when clicked or externally (through enter in the edit). + /// This prevents updating the text and associated filters when scrolling through the combo. + /// private class DropList : ListBox { private readonly KComboBox _owner; - private int _highlightIndex = -1; + private int _committedIndex = -1; public DropList(KComboBox owner) { this._owner = owner; SetStyle(ControlStyles.OptimizedDoubleBuffer, true); - DrawMode = DrawMode.OwnerDrawFixed; SetStyle(ControlStyles.Selectable, false); BorderStyle = BorderStyle.None; } protected override void OnMouseMove(MouseEventArgs e) { - // Use the mouse to highlight the current item - int newIndex = IndexFromPoint(PointToClient(Cursor.Position)); - if (newIndex != _highlightIndex) - { - int oldIndex = _highlightIndex; - _highlightIndex = newIndex; - - // Invalidate the affected items, which may include a previously selected one - InvalidateItem(oldIndex); - InvalidateItem(_highlightIndex); - if (SelectedIndex != oldIndex && SelectedIndex != _highlightIndex) - InvalidateItem(SelectedIndex); - } + // Perform the select to highlight + SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position)); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); - _highlightIndex = -1; - } - - protected override void OnMouseDown(MouseEventArgs e) - { - base.OnMouseDown(e); - - // Perform the select when the mouse is clicked - SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position)); + SelectedIndex = _committedIndex; } protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); - _highlightIndex = -1; + SelectedIndex = _committedIndex; } - private void InvalidateItem(int index) + protected override void OnMouseDown(MouseEventArgs e) { - if (index < 0 || index >= Items.Count) - return; - Invalidate(GetItemRectangle(index)); - } - - protected override void OnDrawItem(DrawItemEventArgs e) - { - // Create a custom event instance to be able to set the selected state for mouse hover - DrawItemState state = e.State; - if (_highlightIndex >= 0) - { - state = _highlightIndex == e.Index ? DrawItemState.Selected : DrawItemState.None; - } - DrawItemEventArgs draw = new DrawItemEventArgs(e.Graphics, e.Font, e.Bounds, e.Index, state); - draw.DrawBackground(); - - string text = Items[draw.Index].ToString(); - using (StringFormat format = new StringFormat()) - { - format.LineAlignment = StringAlignment.Center; - using (Brush brush = new SolidBrush(draw.ForeColor)) - { - draw.Graphics.DrawString(text, - draw.Font, brush, - draw.Bounds, - format); - } - } + // Select the item under the mouse and commit + SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position)); + CommitSelection(); } protected override void DefWndProc(ref Message m) @@ -117,12 +79,22 @@ namespace Acacia.Controls Size prefSize = base.GetPreferredSize(proposedSize); return new Size(prefSize.Width, ItemHeight * Math.Min(Items.Count, _owner.MaxDropDownItems)); } + + public void CommitSelection() + { + _committedIndex = SelectedIndex; + base.OnSelectedIndexChanged(new EventArgs()); + } + + protected override void OnSelectedIndexChanged(EventArgs e) + { + // Don't notify until committed + } } #endregion private readonly DropList _list; - private int _ignoreListEvents; #region Items properties @@ -162,10 +134,14 @@ namespace Acacia.Controls private void _list_SelectedIndexChanged(object sender, EventArgs e) { - if (_list.SelectedIndex >= 0 && _ignoreListEvents == 0) + if (_list.SelectedIndex >= 0) { Text = _list.SelectedItem.ToString(); } + else + { + Text = ""; + } } public void BeginUpdate() @@ -188,16 +164,8 @@ namespace Acacia.Controls set { _list.BindingContext = new BindingContext(); - ++_ignoreListEvents; - try - { - _list.DataSource = value; - _list.SelectedIndex = -1; - } - finally - { - --_ignoreListEvents; - } + _list.DataSource = value; + _list.SelectedIndex = -1; } } @@ -219,7 +187,15 @@ namespace Acacia.Controls case Keys.Down: case Keys.Up: User32.SendMessage(_list.Handle, (int)WM.KEYDOWN, new IntPtr((int)e.KeyCode), IntPtr.Zero); - e.IsInputKey = false; + e.IsInputKey = true; + break; + + // Enter commits the selected index and closes the drop down + case Keys.Enter: + case Keys.Tab: + _list.CommitSelection(); + DroppedDown = false; + e.IsInputKey = e.KeyCode == Keys.Enter; break; default: base.OnPreviewKeyDown(e);