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">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KDataSource.cs" />
|
||||
<Compile Include="Controls\KDialogButtons.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
|
@ -175,10 +175,12 @@ namespace Acacia.Controls
|
||||
|
||||
public Control Control
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((ToolStripControlHost)Items[0]).Control;
|
||||
}
|
||||
get { return ControlHost.Control; }
|
||||
}
|
||||
|
||||
public ToolStripControlHost ControlHost
|
||||
{
|
||||
get { return (ToolStripControlHost)Items[0]; }
|
||||
}
|
||||
|
||||
public DropDown(KAbstractComboBox owner, Control control)
|
||||
@ -303,6 +305,17 @@ namespace Acacia.Controls
|
||||
|
||||
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
|
||||
int maxHeight = GetDropDownHeightMax();
|
||||
int minHeight = GetDropDownHeightMin();
|
||||
@ -313,8 +326,13 @@ namespace Acacia.Controls
|
||||
|
||||
DropControl.MaximumSize = DropControl.MinimumSize = new Size(width, height);
|
||||
|
||||
// Show the drop down below the current control
|
||||
_dropDown.Show(this.PointToScreen(new Point(0, Height - 1)));
|
||||
_dropDown.Control.Bounds = _dropDown.ControlHost.Bounds;
|
||||
System.Diagnostics.Trace.WriteLine(string.Format(
|
||||
"Layout: {0}, host: {1}, control: {2}",
|
||||
height,
|
||||
_dropDown.ControlHost.Bounds,
|
||||
_dropDown.Control.Bounds
|
||||
));
|
||||
}
|
||||
|
||||
protected abstract int GetDropDownHeightMax();
|
||||
|
@ -45,13 +45,17 @@ namespace Acacia.Controls
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
SelectedIndex = _committedIndex;
|
||||
ResetSelectedIndex();
|
||||
}
|
||||
|
||||
protected override void OnVisibleChanged(EventArgs e)
|
||||
{
|
||||
base.OnVisibleChanged(e);
|
||||
SelectedIndex = _committedIndex;
|
||||
}
|
||||
|
||||
private void ResetSelectedIndex()
|
||||
{
|
||||
SelectedIndex = _committedIndex >= Items.Count ? -1 : _committedIndex;
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
@ -90,12 +94,18 @@ namespace Acacia.Controls
|
||||
{
|
||||
// Don't notify until committed
|
||||
}
|
||||
|
||||
public void ItemsChanged(int selectIndex)
|
||||
{
|
||||
_committedIndex = SelectedIndex = selectIndex;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly DropList _list;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Items properties
|
||||
|
||||
[DefaultValue(true)]
|
||||
@ -108,13 +118,6 @@ namespace Acacia.Controls
|
||||
[Category("Behavior")]
|
||||
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)]
|
||||
[Localizable(true)]
|
||||
[Category("Behavior")]
|
||||
@ -122,6 +125,8 @@ namespace Acacia.Controls
|
||||
|
||||
#endregion
|
||||
|
||||
private DisplayItem _selectedItem;
|
||||
|
||||
public KComboBox()
|
||||
{
|
||||
MaxDropDownItems = 8;
|
||||
@ -136,11 +141,13 @@ namespace Acacia.Controls
|
||||
{
|
||||
if (_list.SelectedIndex >= 0)
|
||||
{
|
||||
Text = _list.SelectedItem.ToString();
|
||||
_selectedItem = (DisplayItem)_list.SelectedItem;
|
||||
Text = _selectedItem.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = "";
|
||||
_selectedItem = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,24 +161,96 @@ namespace Acacia.Controls
|
||||
_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
|
||||
{
|
||||
_list.BindingContext = new BindingContext();
|
||||
_list.DataSource = value;
|
||||
_list.SelectedIndex = -1;
|
||||
if (_dataSource != value)
|
||||
{
|
||||
_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()
|
||||
{
|
||||
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()
|
||||
|
@ -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
|
||||
BeginUpdate();
|
||||
DataSource = users;
|
||||
//DataSource = users;
|
||||
//SetItemsCore(users);
|
||||
if (dropDown && text.Length != 0)
|
||||
DroppedDown = true;
|
||||
|
Loading…
Reference in New Issue
Block a user