mirror of
https://github.com/Kopano-dev/kopano-ol-extension.git
synced 2023-10-10 13:37:40 +02:00
Implemented basic filtering for combo box items
This commit is contained in:
parent
acfc47f018
commit
27f1eb7b8a
@ -229,6 +229,7 @@
|
|||||||
<Compile Include="Controls\KCopyLabel.cs">
|
<Compile Include="Controls\KCopyLabel.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\KDataSource.cs" />
|
||||||
<Compile Include="Controls\KDialogButtons.cs">
|
<Compile Include="Controls\KDialogButtons.cs">
|
||||||
<SubType>UserControl</SubType>
|
<SubType>UserControl</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -175,10 +175,12 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
public Control Control
|
public Control Control
|
||||||
{
|
{
|
||||||
get
|
get { return ControlHost.Control; }
|
||||||
{
|
}
|
||||||
return ((ToolStripControlHost)Items[0]).Control;
|
|
||||||
}
|
public ToolStripControlHost ControlHost
|
||||||
|
{
|
||||||
|
get { return (ToolStripControlHost)Items[0]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public DropDown(KAbstractComboBox owner, Control control)
|
public DropDown(KAbstractComboBox owner, Control control)
|
||||||
@ -303,6 +305,17 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
private void ShowDropDown()
|
private void ShowDropDown()
|
||||||
{
|
{
|
||||||
|
UpdateDropDownLayout();
|
||||||
|
|
||||||
|
// Show the drop down below the current control
|
||||||
|
_dropDown.Show(this.PointToScreen(new Point(0, Height - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateDropDownLayout()
|
||||||
|
{
|
||||||
|
if (_dropDown == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Calculate the dimensions of the drop-down
|
// Calculate the dimensions of the drop-down
|
||||||
int maxHeight = GetDropDownHeightMax();
|
int maxHeight = GetDropDownHeightMax();
|
||||||
int minHeight = GetDropDownHeightMin();
|
int minHeight = GetDropDownHeightMin();
|
||||||
@ -313,8 +326,13 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
DropControl.MaximumSize = DropControl.MinimumSize = new Size(width, height);
|
DropControl.MaximumSize = DropControl.MinimumSize = new Size(width, height);
|
||||||
|
|
||||||
// Show the drop down below the current control
|
_dropDown.Control.Bounds = _dropDown.ControlHost.Bounds;
|
||||||
_dropDown.Show(this.PointToScreen(new Point(0, Height - 1)));
|
System.Diagnostics.Trace.WriteLine(string.Format(
|
||||||
|
"Layout: {0}, host: {1}, control: {2}",
|
||||||
|
height,
|
||||||
|
_dropDown.ControlHost.Bounds,
|
||||||
|
_dropDown.Control.Bounds
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract int GetDropDownHeightMax();
|
protected abstract int GetDropDownHeightMax();
|
||||||
|
@ -45,13 +45,17 @@ namespace Acacia.Controls
|
|||||||
protected override void OnMouseLeave(EventArgs e)
|
protected override void OnMouseLeave(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnMouseLeave(e);
|
base.OnMouseLeave(e);
|
||||||
SelectedIndex = _committedIndex;
|
ResetSelectedIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnVisibleChanged(EventArgs e)
|
protected override void OnVisibleChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnVisibleChanged(e);
|
base.OnVisibleChanged(e);
|
||||||
SelectedIndex = _committedIndex;
|
}
|
||||||
|
|
||||||
|
private void ResetSelectedIndex()
|
||||||
|
{
|
||||||
|
SelectedIndex = _committedIndex >= Items.Count ? -1 : _committedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseDown(MouseEventArgs e)
|
protected override void OnMouseDown(MouseEventArgs e)
|
||||||
@ -90,12 +94,18 @@ namespace Acacia.Controls
|
|||||||
{
|
{
|
||||||
// Don't notify until committed
|
// Don't notify until committed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ItemsChanged(int selectIndex)
|
||||||
|
{
|
||||||
|
_committedIndex = SelectedIndex = selectIndex;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private readonly DropList _list;
|
private readonly DropList _list;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Items properties
|
#region Items properties
|
||||||
|
|
||||||
[DefaultValue(true)]
|
[DefaultValue(true)]
|
||||||
@ -108,13 +118,6 @@ namespace Acacia.Controls
|
|||||||
[Category("Behavior")]
|
[Category("Behavior")]
|
||||||
public int ItemHeight { get { return _list.ItemHeight; } set { _list.ItemHeight = value; } }
|
public int ItemHeight { get { return _list.ItemHeight; } set { _list.ItemHeight = value; } }
|
||||||
|
|
||||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
||||||
[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
|
|
||||||
[Localizable(true)]
|
|
||||||
[MergableProperty(false)]
|
|
||||||
[Category("Behavior")]
|
|
||||||
public ListBox.ObjectCollection Items { get { return _list.Items; } }
|
|
||||||
|
|
||||||
[DefaultValue(8)]
|
[DefaultValue(8)]
|
||||||
[Localizable(true)]
|
[Localizable(true)]
|
||||||
[Category("Behavior")]
|
[Category("Behavior")]
|
||||||
@ -122,6 +125,8 @@ namespace Acacia.Controls
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private DisplayItem _selectedItem;
|
||||||
|
|
||||||
public KComboBox()
|
public KComboBox()
|
||||||
{
|
{
|
||||||
MaxDropDownItems = 8;
|
MaxDropDownItems = 8;
|
||||||
@ -136,11 +141,13 @@ namespace Acacia.Controls
|
|||||||
{
|
{
|
||||||
if (_list.SelectedIndex >= 0)
|
if (_list.SelectedIndex >= 0)
|
||||||
{
|
{
|
||||||
Text = _list.SelectedItem.ToString();
|
_selectedItem = (DisplayItem)_list.SelectedItem;
|
||||||
|
Text = _selectedItem.ToString();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Text = "";
|
Text = "";
|
||||||
|
_selectedItem = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,24 +161,96 @@ namespace Acacia.Controls
|
|||||||
_list.EndUpdate();
|
_list.EndUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public object DataSource
|
/// <summary>
|
||||||
|
/// Wrapper for list items to use custom string formatting
|
||||||
|
/// </summary>
|
||||||
|
private class DisplayItem
|
||||||
{
|
{
|
||||||
get
|
private readonly KComboBox _owner;
|
||||||
|
private readonly object _item;
|
||||||
|
|
||||||
|
public DisplayItem(KComboBox owner, object item)
|
||||||
{
|
{
|
||||||
return _list.DataSource;
|
this._owner = owner;
|
||||||
|
this._item = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return _owner.DataSource.GetItemText(_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
bool result = obj is DisplayItem && ((DisplayItem)obj)._item == _item;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ToString().GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private KDataSourceRaw _dataSource;
|
||||||
|
public KDataSourceRaw DataSource
|
||||||
|
{
|
||||||
|
get { return _dataSource; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_list.BindingContext = new BindingContext();
|
if (_dataSource != value)
|
||||||
_list.DataSource = value;
|
{
|
||||||
_list.SelectedIndex = -1;
|
_dataSource = value;
|
||||||
|
UpdateItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateItems()
|
||||||
|
{
|
||||||
|
int oldCount = _list.Items.Count;
|
||||||
|
_list.BeginUpdate();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_list.Items.Clear();
|
||||||
|
int selected = -1;
|
||||||
|
foreach (object item in _dataSource.FilteredItems)
|
||||||
|
{
|
||||||
|
DisplayItem displayItem = new DisplayItem(this, item);
|
||||||
|
if (displayItem.Equals(_selectedItem))
|
||||||
|
selected = _list.Items.Count;
|
||||||
|
_list.Items.Add(displayItem);
|
||||||
|
}
|
||||||
|
System.Diagnostics.Trace.WriteLine(string.Format("FILTER: {0}", _list.Items.Count, selected));
|
||||||
|
|
||||||
|
// Select the current item only if new number of items is smaller. This means we don't keep selection
|
||||||
|
// when the user is removing text, only when they are typing more.
|
||||||
|
_list.ItemsChanged(_list.Items.Count < oldCount ? selected : -1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_list.EndUpdate();
|
||||||
|
}
|
||||||
|
UpdateDropDownLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnTextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnTextChanged(e);
|
||||||
|
|
||||||
|
// Update the filter
|
||||||
|
if (DataSource != null)
|
||||||
|
{
|
||||||
|
DataSource.Filter = new KDataFilter(Text);
|
||||||
|
UpdateItems();
|
||||||
|
|
||||||
|
DroppedDown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override int GetDropDownHeightMax()
|
protected override int GetDropDownHeightMax()
|
||||||
{
|
{
|
||||||
return Util.Bound(Items.Count, 1, MaxDropDownItems) * ItemHeight + _list.Margin.Vertical;
|
return Util.Bound(_list.Items.Count, 1, MaxDropDownItems) * ItemHeight + _list.Margin.Vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override int GetDropDownHeightMin()
|
protected override int GetDropDownHeightMin()
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Acacia.Controls
|
||||||
|
{
|
||||||
|
public class KDataFilter
|
||||||
|
{
|
||||||
|
public readonly string FilterText;
|
||||||
|
|
||||||
|
public KDataFilter(string filterText)
|
||||||
|
{
|
||||||
|
this.FilterText = filterText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface KDataSourceRaw
|
||||||
|
{
|
||||||
|
System.Collections.IEnumerable Items { get; }
|
||||||
|
System.Collections.IEnumerable FilteredItems { get; }
|
||||||
|
KDataFilter Filter { get; set; }
|
||||||
|
string GetItemText(object item);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public class KDataSource<T> : KDataSourceRaw
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all the items
|
||||||
|
/// </summary>
|
||||||
|
abstract public IEnumerable<T> Items
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<T> FilteredItems
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Filter?.FilterText))
|
||||||
|
return Items;
|
||||||
|
|
||||||
|
return ApplyFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<T> ApplyFilter()
|
||||||
|
{
|
||||||
|
foreach (T item in Items)
|
||||||
|
{
|
||||||
|
if (MatchesFilter(item))
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual protected bool MatchesFilter(T item)
|
||||||
|
{
|
||||||
|
return GetItemText(item).StartsWith(Filter.FilterText);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected string GetItemText(T item);
|
||||||
|
|
||||||
|
public string GetItemText(object item)
|
||||||
|
{
|
||||||
|
return GetItemText((T)item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KDataFilter Filter
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable KDataSourceRaw.Items { get{return Items;}}
|
||||||
|
IEnumerable KDataSourceRaw.FilteredItems { get { return FilteredItems; } }
|
||||||
|
}
|
||||||
|
}
|
@ -216,7 +216,7 @@ namespace Acacia.UI
|
|||||||
|
|
||||||
// Setting the datasource will trigger a select if there is a match
|
// Setting the datasource will trigger a select if there is a match
|
||||||
BeginUpdate();
|
BeginUpdate();
|
||||||
DataSource = users;
|
//DataSource = users;
|
||||||
//SetItemsCore(users);
|
//SetItemsCore(users);
|
||||||
if (dropDown && text.Length != 0)
|
if (dropDown && text.Length != 0)
|
||||||
DroppedDown = true;
|
DroppedDown = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user