1
0
mirror of https://github.com/Kopano-dev/kopano-ol-extension.git synced 2023-10-10 13:37:40 +02:00
Conflicts:
	translations/hu.po
This commit is contained in:
Weblate 2017-06-30 08:44:36 +02:00
commit 2ca9f0e715
23 changed files with 1232 additions and 520 deletions

View File

@ -226,9 +226,13 @@
<Compile Include="Controls\KComboBox.cs"> <Compile Include="Controls\KComboBox.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Controls\KComboBoxCustomDraw.cs">
<SubType>Component</SubType>
</Compile>
<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>

View File

@ -1,4 +1,5 @@
using Acacia.Native; using Acacia.Native;
using Acacia.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@ -11,10 +12,13 @@ using System.Windows.Forms;
namespace Acacia.Controls namespace Acacia.Controls
{ {
public abstract class KAbstractComboBox : ContainerControl, IMessageFilter public abstract class KAbstractComboBox : ContainerControl
{ {
#region Properties #region Properties
/// <summary>
/// Hide the AutoSize property, it is always enabled
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
override public bool AutoSize { get { return base.AutoSize; } set { base.AutoSize = value; } } override public bool AutoSize { get { return base.AutoSize; } set { base.AutoSize = value; } }
@ -40,12 +44,41 @@ namespace Acacia.Controls
set { _edit.PlaceholderFont = value; } set { _edit.PlaceholderFont = value; }
} }
/// <summary>
/// The control to set in the drop-down
/// </summary>
protected Control DropControl
{
get
{
return _dropDown?.Control;
}
set
{
_dropDown = new DropDown(this, value);
}
}
#endregion protected int _settingText = 0;
#region Components override public string Text
{
private KTextBox _edit; get { return _edit.Text; }
set
{
++_settingText;
try
{
_edit.Text = value;
// Set the cursor after the text
_edit.Select(_edit.Text.Length, 0);
}
finally
{
--_settingText;
}
}
}
#endregion #endregion
@ -55,28 +88,24 @@ namespace Acacia.Controls
{ {
AutoSize = true; AutoSize = true;
SetupRenderer(); SetupRenderer();
SetupEdit();
_edit = new KTextBox();
_edit.BorderStyle = BorderStyle.None;
Controls.Add(_edit);
_state.AddControl(_edit);
_edit.TextChanged += _edit_TextChanged;
} }
#endregion #endregion
#region Text edit #region Text edit
private void _edit_TextChanged(object sender, EventArgs e) private KTextBox _edit;
{
OnTextChanged(new EventArgs());
}
override public string Text private void SetupEdit()
{ {
get { return _edit.Text; } _edit = new KTextBox();
set { _edit.Text = value; } _edit.BorderStyle = BorderStyle.None;
Controls.Add(_edit);
_state.AddControl(_edit);
_edit.TextChanged += _edit_TextChanged;
_edit.LostFocus += _edit_LostFocus;
_edit.PreviewKeyDown += _edit_PreviewKeyDown;
} }
public void FocusEdit() public void FocusEdit()
@ -84,138 +113,177 @@ namespace Acacia.Controls
_edit.Select(); _edit.Select();
} }
private void _edit_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Escape:
// Escape closes the drop-down
if (DroppedDown)
{
DroppedDown = false;
// Grab the keypress to prevent closing a dialog
e.IsInputKey = true;
return;
}
break;
case Keys.Down:
// Down opens the drop down
if (!DroppedDown)
{
DroppedDown = true;
e.IsInputKey = true;
return;
}
break;
}
OnPreviewKeyDown(e);
}
private void _edit_LostFocus(object sender, EventArgs e)
{
// Close the drop down when losing focus. This also handles the case when another window is selected,
// as that causes the focus to be taken away
DroppedDown = false;
}
private void _edit_TextChanged(object sender, EventArgs e)
{
OnTextChanged(new EventArgs());
}
#endregion #endregion
#region Drop down #region Drop down
public Control DropControl /// <summary>
/// Custom drop down. Registers a message filter when shown to close on clicks outside the drop-down.
/// This is required as the default AutoClose behaviour consumes all keyboard events.
/// </summary>
private class DropDown : ToolStripDropDown, IMessageFilter
{ {
get /// <summary>
/// Custom renderer that renders the border using the combo focus style.
/// </summary>
private class DropDownRenderer : ToolStripRenderer
{ {
return _dropControl; private readonly KVisualStyle<COMBOBOXPARTS, State>.Part _style;
public DropDownRenderer(KVisualStyle<COMBOBOXPARTS, State>.Part style)
{
this._style = style;
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
_style.DrawBackground(e.Graphics, State.Pressed, e.AffectedBounds);
}
} }
set
private readonly KAbstractComboBox _owner;
public Control Control
{ {
_dropControl = value; get { return ControlHost.Control; }
SetupDropDown();
} }
}
private ToolStripDropDown _dropDown; public ToolStripControlHost ControlHost
private Control _dropControl;
private ToolStripControlHost _dropListHost;
private void SetupDropDown()
{
_dropListHost = new ToolStripControlHost(_dropControl);
_dropListHost.Padding = new Padding(0);
_dropListHost.Margin = new Padding(0);
_dropListHost.AutoSize = false;
_dropDown = new ToolStripDropDown();
_dropDown.Padding = new Padding(0);
_dropDown.Margin = new Padding(0);
_dropDown.AutoSize = true;
_dropDown.DropShadowEnabled = false;
_dropDown.Items.Add(_dropListHost);
_dropDown.Closed += _dropDown_Closed;
_dropDown.AutoClose = false;
Application.AddMessageFilter(this);
}
protected override void OnHandleDestroyed(EventArgs e)
{
Application.RemoveMessageFilter(this);
base.OnHandleDestroyed(e);
}
public bool PreFilterMessage(ref Message m)
{
switch ((WM)m.Msg)
{ {
case WM.KEYDOWN: get { return (ToolStripControlHost)Items[0]; }
System.Diagnostics.Trace.WriteLine("KEYMESSAGE: " + m); }
switch((VirtualKeys)m.WParam.ToInt32())
{
case VirtualKeys.Escape:
// Escape closes the popup
if (DroppedDown)
{
DroppedDown = false;
return true;
}
break;
case VirtualKeys.Down:
// Down opens the drop down
if (!DroppedDown)
{
DroppedDown = true;
return true;
}
break;
}
break;
case WM.CHAR:
case WM.KEYUP:
System.Diagnostics.Trace.WriteLine("KEYMESSAGE: " + m);
break;
case WM.LBUTTONDOWN:
case WM.RBUTTONDOWN:
case WM.MBUTTONDOWN:
case WM.NCLBUTTONDOWN:
case WM.NCRBUTTONDOWN:
case WM.NCMBUTTONDOWN:
if (_dropDown.Visible)
{
//
// When a mouse button is pressed, we should determine if it is within the client coordinates
// of the active dropdown. If not, we should dismiss it.
//
int i = unchecked((int)(long)m.LParam);
short x = (short)(i & 0xFFFF);
short y = (short)((i >> 16) & 0xffff);
Point pt = new Point(x, y);
// Map to global coordinates public DropDown(KAbstractComboBox owner, Control control)
User32.MapWindowPoints(m.HWnd, IntPtr.Zero, ref pt, 1); {
System.Diagnostics.Trace.WriteLine(string.Format("MOUSE: {0} - {1}", pt, _dropDown.Bounds)); this._owner = owner;
if (!_dropDown.Bounds.Contains(pt))
KVisualStyle<COMBOBOXPARTS, State>.Part style = owner._style[COMBOBOXPARTS.CP_BORDER];
Renderer = new DropDownRenderer(style);
using (Graphics graphics = CreateGraphics())
{
Padding = style?.GetMargins(graphics, State.Pressed) ?? new Padding();
}
Margin = new Padding(0);
AutoSize = true;
DropShadowEnabled = false;
AutoClose = false;
// Add a host for the control
ToolStripControlHost host = new ToolStripControlHost(control);
host.Padding = new Padding(0);
host.Margin = new Padding(0);
host.AutoSize = true;
Items.Add(host);
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
// Only register the message filter when it can do something useful
if (Visible)
Application.AddMessageFilter(this);
else
Application.RemoveMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
// Handle mouse clicks to close the popup
switch ((WM)m.Msg)
{
case WM.LBUTTONDOWN:
case WM.RBUTTONDOWN:
case WM.MBUTTONDOWN:
return CheckMouseDown(m, false);
case WM.NCLBUTTONDOWN:
case WM.NCRBUTTONDOWN:
case WM.NCMBUTTONDOWN:
return CheckMouseDown(m, true);
}
return false;
}
private bool CheckMouseDown(Message m, bool nonClient)
{
Point pt = User32.GetPointLParam(m.LParam);
Point ptOrig = pt;
if (!nonClient)
{
// Map to global coordinates, non-client ones already are
User32.MapWindowPoints(m.HWnd, IntPtr.Zero, ref pt, 1);
}
// Check if the click was inside the drop-down
if (!Bounds.Contains(pt))
{
// Outside the drop-down, check if it was inside the combo box
// Map to the combo box coordinates
User32.MapWindowPoints(IntPtr.Zero, _owner.Handle, ref pt, 1);
if (_owner.ClientRectangle.Contains(pt))
{
// Clicked inside the combo box. If the click was on the button, return true to prevent opening
// the popup again.
if (_owner._stateButton.Rectangle.Contains(pt))
{ {
// the user has clicked outside the dropdown return true;
User32.MapWindowPoints(m.HWnd, Handle, ref pt, 1);
if (!ClientRectangle.Contains(pt))
{
// the user has clicked outside the combo
DroppedDown = false;
}
} }
} }
break; else
{
// Outside the drop-down, close it
Close();
}
}
return false;
} }
return false;
} }
// Cannot use visibility of _dropDown to keep the open state, as clicking on the button already private DropDown _dropDown;
// hides the popup before the event handler is shown.
private bool _isDroppedDown;
private bool _clickedButton;
private void _dropDown_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
/*if (_stateButton.IsMouseOver)
{
_clickedButton = true;
}*/
_isDroppedDown = false;
}
private void Button_Clicked() private void Button_Clicked()
{ {
/*if (_clickedButton)
_clickedButton = false;
else
DroppedDown = true;*/
DroppedDown = !DroppedDown; DroppedDown = !DroppedDown;
this._edit.Focus(); this._edit.Focus();
} }
@ -225,30 +293,54 @@ namespace Acacia.Controls
{ {
get get
{ {
return _isDroppedDown; return _dropDown?.Visible == true;
} }
set set
{ {
if (value != _isDroppedDown) if (value != DroppedDown)
{ {
if (value) if (value)
{ {
_dropListHost.Control.Width = this.Width; ShowDropDown();
_dropListHost.Control.Height = 200;
_dropListHost.Control.Refresh();
_dropDown.Show(this.PointToScreen(new Point(0, Height)));
_dropDown.Capture = true;
} }
else else
{ {
_dropDown.Close(); _dropDown.Close();
} }
_isDroppedDown = value;
} }
} }
} }
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();
Size prefSize = DropControl.GetPreferredSize(new Size(Width - _dropDown.Padding.Horizontal, maxHeight - _dropDown.Padding.Vertical));
int width = Util.Bound(prefSize.Width, Width - _dropDown.Padding.Horizontal, Width * 2);
int height = Util.Bound(prefSize.Height, minHeight, maxHeight);
DropControl.MaximumSize = DropControl.MinimumSize = new Size(width, height);
_dropDown.Control.Bounds = _dropDown.ControlHost.Bounds;
}
protected abstract int GetDropDownHeightMax();
protected abstract int GetDropDownHeightMin();
#endregion #endregion
#region Rendering #region Rendering
@ -306,7 +398,6 @@ namespace Acacia.Controls
protected override void OnPaint(PaintEventArgs e) protected override void OnPaint(PaintEventArgs e)
{ {
_style[COMBOBOXPARTS.CP_BORDER]?.DrawBackground(e.Graphics, _state.Root.State, ClientRectangle); _style[COMBOBOXPARTS.CP_BORDER]?.DrawBackground(e.Graphics, _state.Root.State, ClientRectangle);
System.Diagnostics.Trace.WriteLine(string.Format("BUTTON: {0}", _stateButton.State));
_style[COMBOBOXPARTS.CP_DROPDOWNBUTTON]?.DrawBackground(e.Graphics, _stateButton.State, _stateButton.Rectangle); _style[COMBOBOXPARTS.CP_DROPDOWNBUTTON]?.DrawBackground(e.Graphics, _stateButton.State, _stateButton.Rectangle);
} }

View File

@ -1,4 +1,6 @@
using System; using Acacia.Native;
using Acacia.Utils;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing; using System.Drawing;
@ -12,7 +14,108 @@ namespace Acacia.Controls
{ {
public class KComboBox : KAbstractComboBox public class KComboBox : KAbstractComboBox
{ {
private readonly ListBox _list; #region Drop-down list
/// <summary>
/// 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.
/// </summary>
private class DropList : ListBox
{
private readonly KComboBox _owner;
private int _committedIndex = -1;
public int ItemWidth { get; set; }
public DropList(KComboBox owner, bool ownerDraw)
{
this._owner = owner;
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Selectable, false);
BorderStyle = BorderStyle.None;
if (ownerDraw)
{
DrawMode = DrawMode.OwnerDrawFixed;
}
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
_owner.OnDrawItem(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
// Perform the select to highlight
SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position));
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
ResetSelectedIndex();
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
}
private void ResetSelectedIndex()
{
SelectedIndex = _committedIndex >= Items.Count ? -1 : _committedIndex;
}
protected override void OnMouseDown(MouseEventArgs e)
{
// Select the item under the mouse and commit
SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position));
CommitSelection();
}
protected override void DefWndProc(ref Message m)
{
switch ((WM)m.Msg)
{
// Prevent mouse activity from grabbing the focus away from the edit
case WM.MOUSEACTIVATE:
m.Result = (IntPtr)MA.NOACTIVATE;
return;
}
base.DefWndProc(ref m);
}
public override Size GetPreferredSize(Size proposedSize)
{
// Preferred size is simply the size of the (maximum) number of items
Size prefSize = base.GetPreferredSize(proposedSize);
int w = Math.Max(prefSize.Width, ItemWidth);
return new Size(w, 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
}
public void ItemsChanged(int selectIndex)
{
_committedIndex = SelectedIndex = selectIndex;
}
}
private readonly DropList _list;
#endregion
#region Items properties #region Items properties
@ -26,13 +129,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")]
@ -40,37 +136,262 @@ namespace Acacia.Controls
#endregion #endregion
public KComboBox() private DisplayItem _selectedItem;
public KComboBox() : this(false)
{ {
}
protected internal KComboBox(bool ownerDraw)
{
MaxDropDownItems = 8; MaxDropDownItems = 8;
_list = new ListBox(); _list = new DropList(this, ownerDraw);
_list.IntegralHeight = true; _list.IntegralHeight = true;
_list.TabStop = false;
_list.SelectedIndexChanged += _list_SelectedIndexChanged;
DropControl = _list; DropControl = _list;
_list.DisplayMember = "DisplayName"; // TODO: remove from here
} }
public void BeginUpdate() private void _list_SelectedIndexChanged(object sender, EventArgs e)
{ {
if (_list.SelectedIndex >= 0)
{
_selectedItem = (DisplayItem)_list.SelectedItem;
Text = _selectedItem.ToString();
}
else
{
Text = "";
_selectedItem = null;
}
OnSelectedItemChanged();
}
public DisplayItem SelectedItem
{
get { return _selectedItem; }
}
public void Select(object data)
{
_list.SelectedIndex = -1;
Text = null;
_selectedItem = null;
if (data != null)
{
foreach (DisplayItem item in DisplayItems)
{
if (item.Item.Equals(data))
{
_list.SelectedItem = item;
_selectedItem = item;
break;
}
}
}
}
public event EventHandler SelectedItemChanged;
protected virtual void OnSelectedItemChanged()
{
SelectedItemChanged?.Invoke(this, new EventArgs());
}
/// <summary>
/// Wrapper for list items to use custom string formatting
/// </summary>
public class DisplayItem
{
private readonly KComboBox _owner;
public readonly object Item;
public DisplayItem(KComboBox owner, object item)
{
this._owner = owner;
this.Item = item;
}
public override string ToString()
{
return _owner.DataSource.GetItemText(Item);
}
public override bool Equals(object obj)
{
return obj is DisplayItem && ((DisplayItem)obj).Item == Item;
}
public override int GetHashCode()
{
return Item.GetHashCode();
}
}
private KDataSourceRaw _dataSource;
public KDataSourceRaw DataSource
{
get { return _dataSource; }
set
{
if (_dataSource != value)
{
_dataSource = value;
_displayItemCache.Clear();
UpdateItems();
}
}
}
private readonly Dictionary<object, DisplayItem> _displayItemCache = new Dictionary<object, DisplayItem>();
private void UpdateItems()
{
int oldCount = _list.Items.Count;
_list.BeginUpdate(); _list.BeginUpdate();
try
{
_list.Items.Clear();
int selected = -1;
foreach (object item in _dataSource.FilteredItems)
{
DisplayItem displayItem;
if (!_displayItemCache.TryGetValue(item, out displayItem))
{
displayItem = new DisplayItem(this, item);
_displayItemCache.Add(item, displayItem);
}
if (displayItem == _selectedItem)
selected = _list.Items.Count;
_list.Items.Add(displayItem);
}
if (_list.Items.Count == 0)
{
// Create a not-found item if requested
object item = _dataSource.NotFoundItem;
if (item != null)
{
_list.Items.Add(new DisplayItem(this, item));
}
}
// 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);
MeasureItems();
UpdateDropDownLayout();
}
finally
{
_list.EndUpdate();
}
} }
public void EndUpdate() protected IEnumerable<DisplayItem> DisplayItems
{
_list.EndUpdate();
}
public object DataSource
{ {
get get
{ {
return _list.DataSource; foreach (object item in _list.Items)
yield return (DisplayItem)item;
} }
}
set protected DisplayItem GetDisplayItem(int index)
{
return (DisplayItem)_list.Items[index];
}
protected int DisplayItemCount
{
get { return _list.Items.Count; }
}
virtual protected void OnDrawItem(DrawItemEventArgs e) { }
protected virtual void MeasureItems()
{
// Virtual placeholder
}
protected void SetItemSize(Size size)
{
ItemHeight = size.Height;
_list.ItemWidth = size.Width;
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
// Update the filter
if (DataSource != null)
{ {
_list.BindingContext = new BindingContext(); DataSource.Filter = new KDataFilter(Text);
_list.DataSource = value; UpdateItems();
if (_settingText == 0)
{
DroppedDown = true;
}
} }
} }
protected override int GetDropDownHeightMax()
{
return Util.Bound(_list.Items.Count, 1, MaxDropDownItems) * ItemHeight + _list.Margin.Vertical;
}
protected override int GetDropDownHeightMin()
{
return ItemHeight;
}
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
switch(e.KeyCode)
{
// Forward cursor keys to the list
case Keys.Down:
case Keys.Up:
case Keys.PageDown:
case Keys.PageUp:
case Keys.Home:
case Keys.End:
User32.SendMessage(_list.Handle, (int)WM.KEYDOWN, new IntPtr((int)e.KeyCode), IntPtr.Zero);
e.IsInputKey = true;
break;
// Enter commits the selected index and closes the drop down
case Keys.Enter:
case Keys.Tab:
if (DroppedDown)
{
if (_list.SelectedIndex >= 0)
_list.CommitSelection();
DroppedDown = false;
}
e.IsInputKey = e.KeyCode == Keys.Enter;
break;
default:
base.OnPreviewKeyDown(e);
break;
}
}
protected override void DefWndProc(ref Message m)
{
switch ((WM)m.Msg)
{
// Forward mouse wheel messages to the list
case WM.MOUSEWHEEL:
m.Result = (IntPtr) User32.SendMessage(_list.Handle, m.Msg, m.WParam, m.LParam);
return;
}
base.DefWndProc(ref m);
}
} }
} }

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Acacia.Controls
{
abstract public class KComboBoxCustomDraw : KComboBox
{
public class MeasureItemEventArgs : EventArgs
{
public readonly Graphics Graphics;
public readonly DisplayItem DisplayItem;
public object Item { get { return DisplayItem.Item; } }
public int ItemWidth { get; set; }
public int ItemHeight { get; set; }
public MeasureItemEventArgs(Graphics graphics, DisplayItem item)
{
this.Graphics = graphics;
this.DisplayItem = item;
}
}
public class DrawItemEventArgs : System.Windows.Forms.DrawItemEventArgs
{
public readonly DisplayItem DisplayItem;
public object Item { get { return DisplayItem.Item; } }
public DrawItemEventArgs(System.Windows.Forms.DrawItemEventArgs e, DisplayItem item)
:
base(e.Graphics, e.Font, e.Bounds, e.Index, e.State, e.ForeColor, e.BackColor)
{
DisplayItem = item;
}
}
public KComboBoxCustomDraw() : base(true)
{
}
sealed protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
{
OnDrawItem(new DrawItemEventArgs(e, GetDisplayItem(e.Index)));
}
protected abstract void OnDrawItem(DrawItemEventArgs e);
protected abstract void OnMeasureItem(MeasureItemEventArgs e);
private readonly Dictionary<DisplayItem, Size> _sizeCache = new Dictionary<DisplayItem, Size>();
protected override void MeasureItems()
{
int maxWidth = 0, maxHeight = 0;
using (Graphics graphics = CreateGraphics())
{
foreach (DisplayItem item in DisplayItems)
{
Size s;
if (!_sizeCache.TryGetValue(item, out s))
{
MeasureItemEventArgs e = new MeasureItemEventArgs(graphics, item);
OnMeasureItem(e);
s = new Size(e.ItemWidth, e.ItemHeight);
_sizeCache.Add(item, s);
}
maxWidth = Math.Max(maxWidth, s.Width);
maxHeight = Math.Max(maxHeight, s.Height);
}
}
if (maxHeight > 0)
{
SetItemSize(new Size(maxWidth, maxHeight));
}
}
}
}

View File

@ -0,0 +1,85 @@
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);
object NotFoundItem { get; }
}
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;
}
virtual public object NotFoundItem
{
get { return null; }
}
IEnumerable KDataSourceRaw.Items { get{return Items;}}
IEnumerable KDataSourceRaw.FilteredItems { get { return FilteredItems; } }
}
}

View File

@ -24,7 +24,7 @@ using System.Windows.Forms;
namespace Acacia.Controls namespace Acacia.Controls
{ {
internal static class KUIUtil public static class KUIUtil
{ {
#region Geometry #region Geometry
@ -126,6 +126,11 @@ namespace Acacia.Controls
return r; return r;
} }
public static Point TopLeft(this Rectangle _this)
{
return new Point(_this.Left, _this.Top);
}
#endregion #endregion
} }
} }

View File

@ -35,25 +35,23 @@
this._layoutMain = new System.Windows.Forms.TableLayoutPanel(); this._layoutMain = new System.Windows.Forms.TableLayoutPanel();
this._layoutSelectUser = new System.Windows.Forms.TableLayoutPanel(); this._layoutSelectUser = new System.Windows.Forms.TableLayoutPanel();
this.labelSelectUser = new System.Windows.Forms.Label(); this.labelSelectUser = new System.Windows.Forms.Label();
this.buttonOpenUser = new System.Windows.Forms.Button();
this._layoutCenterGABLookup = new System.Windows.Forms.TableLayoutPanel();
this.gabLookup = new Acacia.UI.GABLookupControl(); this.gabLookup = new Acacia.UI.GABLookupControl();
this.buttonOpenUser = new System.Windows.Forms.Button();
this.kTreeFolders = new Acacia.Controls.KTree(); this.kTreeFolders = new Acacia.Controls.KTree();
this._layoutOptions = new System.Windows.Forms.TableLayoutPanel(); this._layoutOptions = new System.Windows.Forms.TableLayoutPanel();
this._labelName = new System.Windows.Forms.Label(); this._labelName = new System.Windows.Forms.Label();
this.textName = new System.Windows.Forms.TextBox(); this.textName = new System.Windows.Forms.TextBox();
this._labelSendAs = new System.Windows.Forms.Label(); this._labelSendAs = new System.Windows.Forms.Label();
this.checkSendAs = new System.Windows.Forms.CheckBox(); this.checkSendAs = new System.Windows.Forms.CheckBox();
this._labelPermissions = new System.Windows.Forms.Label();
this.labelPermissionsValue = new System.Windows.Forms.Label();
this._labelReminders = new System.Windows.Forms.Label(); this._labelReminders = new System.Windows.Forms.Label();
this.checkReminders = new System.Windows.Forms.CheckBox(); this.checkReminders = new System.Windows.Forms.CheckBox();
this._labelPermissions = new System.Windows.Forms.Label();
this.labelPermissionsValue = new System.Windows.Forms.Label();
this.dialogButtons = new Acacia.Controls.KDialogButtons(); this.dialogButtons = new Acacia.Controls.KDialogButtons();
this._layout.SuspendLayout(); this._layout.SuspendLayout();
this._mainBusyHider.SuspendLayout(); this._mainBusyHider.SuspendLayout();
this._layoutMain.SuspendLayout(); this._layoutMain.SuspendLayout();
this._layoutSelectUser.SuspendLayout(); this._layoutSelectUser.SuspendLayout();
this._layoutCenterGABLookup.SuspendLayout();
this._layoutOptions.SuspendLayout(); this._layoutOptions.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
@ -85,8 +83,8 @@
// //
resources.ApplyResources(this._layoutSelectUser, "_layoutSelectUser"); resources.ApplyResources(this._layoutSelectUser, "_layoutSelectUser");
this._layoutSelectUser.Controls.Add(this.labelSelectUser, 0, 0); this._layoutSelectUser.Controls.Add(this.labelSelectUser, 0, 0);
this._layoutSelectUser.Controls.Add(this.gabLookup, 1, 0);
this._layoutSelectUser.Controls.Add(this.buttonOpenUser, 2, 0); this._layoutSelectUser.Controls.Add(this.buttonOpenUser, 2, 0);
this._layoutSelectUser.Controls.Add(this._layoutCenterGABLookup, 1, 0);
this._layoutSelectUser.Name = "_layoutSelectUser"; this._layoutSelectUser.Name = "_layoutSelectUser";
// //
// labelSelectUser // labelSelectUser
@ -94,19 +92,6 @@
resources.ApplyResources(this.labelSelectUser, "labelSelectUser"); resources.ApplyResources(this.labelSelectUser, "labelSelectUser");
this.labelSelectUser.Name = "labelSelectUser"; this.labelSelectUser.Name = "labelSelectUser";
// //
// buttonOpenUser
//
resources.ApplyResources(this.buttonOpenUser, "buttonOpenUser");
this.buttonOpenUser.Name = "buttonOpenUser";
this.buttonOpenUser.UseVisualStyleBackColor = true;
this.buttonOpenUser.Click += new System.EventHandler(this.buttonOpenUser_Click);
//
// _layoutCenterGABLookup
//
resources.ApplyResources(this._layoutCenterGABLookup, "_layoutCenterGABLookup");
this._layoutCenterGABLookup.Controls.Add(this.gabLookup, 0, 1);
this._layoutCenterGABLookup.Name = "_layoutCenterGABLookup";
//
// gabLookup // gabLookup
// //
this.gabLookup.DataSource = null; this.gabLookup.DataSource = null;
@ -114,9 +99,18 @@
this.gabLookup.DroppedDown = false; this.gabLookup.DroppedDown = false;
this.gabLookup.GAB = null; this.gabLookup.GAB = null;
this.gabLookup.Name = "gabLookup"; this.gabLookup.Name = "gabLookup";
this.gabLookup.PlaceholderColor = System.Drawing.Color.Gray;
this.gabLookup.PlaceholderFont = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.gabLookup.SelectedUser = null; this.gabLookup.SelectedUser = null;
this.gabLookup.SelectedUserChanged += new Acacia.UI.GABLookupControl.SelectedUserEventHandler(this.gabLookup_SelectedUserChanged); this.gabLookup.SelectedUserChanged += new Acacia.UI.GABLookupControl.SelectedUserEventHandler(this.gabLookup_SelectedUserChanged);
// //
// buttonOpenUser
//
resources.ApplyResources(this.buttonOpenUser, "buttonOpenUser");
this.buttonOpenUser.Name = "buttonOpenUser";
this.buttonOpenUser.UseVisualStyleBackColor = true;
this.buttonOpenUser.Click += new System.EventHandler(this.buttonOpenUser_Click);
//
// kTreeFolders // kTreeFolders
// //
this.kTreeFolders.BackColor = System.Drawing.SystemColors.Window; this.kTreeFolders.BackColor = System.Drawing.SystemColors.Window;
@ -140,10 +134,10 @@
this._layoutOptions.Controls.Add(this.textName, 1, 0); this._layoutOptions.Controls.Add(this.textName, 1, 0);
this._layoutOptions.Controls.Add(this._labelSendAs, 0, 1); this._layoutOptions.Controls.Add(this._labelSendAs, 0, 1);
this._layoutOptions.Controls.Add(this.checkSendAs, 1, 1); this._layoutOptions.Controls.Add(this.checkSendAs, 1, 1);
this._layoutOptions.Controls.Add(this._labelPermissions, 0, 3);
this._layoutOptions.Controls.Add(this.labelPermissionsValue, 1, 3);
this._layoutOptions.Controls.Add(this._labelReminders, 0, 2); this._layoutOptions.Controls.Add(this._labelReminders, 0, 2);
this._layoutOptions.Controls.Add(this.checkReminders, 1, 2); this._layoutOptions.Controls.Add(this.checkReminders, 1, 2);
this._layoutOptions.Controls.Add(this._labelPermissions, 0, 3);
this._layoutOptions.Controls.Add(this.labelPermissionsValue, 1, 3);
this._layoutOptions.Name = "_layoutOptions"; this._layoutOptions.Name = "_layoutOptions";
// //
// _labelName // _labelName
@ -170,16 +164,6 @@
this.checkSendAs.UseVisualStyleBackColor = true; this.checkSendAs.UseVisualStyleBackColor = true;
this.checkSendAs.CheckedChanged += new System.EventHandler(this.checkSendAs_CheckedChanged); this.checkSendAs.CheckedChanged += new System.EventHandler(this.checkSendAs_CheckedChanged);
// //
// _labelPermissions
//
resources.ApplyResources(this._labelPermissions, "_labelPermissions");
this._labelPermissions.Name = "_labelPermissions";
//
// labelPermissionsValue
//
resources.ApplyResources(this.labelPermissionsValue, "labelPermissionsValue");
this.labelPermissionsValue.Name = "labelPermissionsValue";
//
// _labelReminders // _labelReminders
// //
resources.ApplyResources(this._labelReminders, "_labelReminders"); resources.ApplyResources(this._labelReminders, "_labelReminders");
@ -192,6 +176,16 @@
this.checkReminders.UseVisualStyleBackColor = true; this.checkReminders.UseVisualStyleBackColor = true;
this.checkReminders.CheckedChanged += new System.EventHandler(this.checkReminders_CheckedChanged); this.checkReminders.CheckedChanged += new System.EventHandler(this.checkReminders_CheckedChanged);
// //
// _labelPermissions
//
resources.ApplyResources(this._labelPermissions, "_labelPermissions");
this._labelPermissions.Name = "_labelPermissions";
//
// labelPermissionsValue
//
resources.ApplyResources(this.labelPermissionsValue, "labelPermissionsValue");
this.labelPermissionsValue.Name = "labelPermissionsValue";
//
// dialogButtons // dialogButtons
// //
resources.ApplyResources(this.dialogButtons, "dialogButtons"); resources.ApplyResources(this.dialogButtons, "dialogButtons");
@ -219,7 +213,6 @@
this._layoutMain.PerformLayout(); this._layoutMain.PerformLayout();
this._layoutSelectUser.ResumeLayout(false); this._layoutSelectUser.ResumeLayout(false);
this._layoutSelectUser.PerformLayout(); this._layoutSelectUser.PerformLayout();
this._layoutCenterGABLookup.ResumeLayout(false);
this._layoutOptions.ResumeLayout(false); this._layoutOptions.ResumeLayout(false);
this._layoutOptions.PerformLayout(); this._layoutOptions.PerformLayout();
this.ResumeLayout(false); this.ResumeLayout(false);
@ -243,7 +236,6 @@
private System.Windows.Forms.Label labelPermissionsValue; private System.Windows.Forms.Label labelPermissionsValue;
private Controls.KBusyHider _mainBusyHider; private Controls.KBusyHider _mainBusyHider;
private Controls.KDialogButtons dialogButtons; private Controls.KDialogButtons dialogButtons;
private System.Windows.Forms.TableLayoutPanel _layoutCenterGABLookup;
private UI.GABLookupControl gabLookup; private UI.GABLookupControl gabLookup;
private System.Windows.Forms.Label _labelReminders; private System.Windows.Forms.Label _labelReminders;
private System.Windows.Forms.CheckBox checkReminders; private System.Windows.Forms.CheckBox checkReminders;

View File

@ -148,8 +148,12 @@ namespace Acacia.Features.SharedFolders
}; };
FocusNode(node); FocusNode(node);
} }
kTreeFolders.Focus();
}
else
{
gabLookup.FocusEdit();
} }
kTreeFolders.Focus();
} }
private void dialogButtons_Apply(object sender, EventArgs e) private void dialogButtons_Apply(object sender, EventArgs e)

View File

@ -148,7 +148,7 @@
<value>3, 0</value> <value>3, 0</value>
</data> </data>
<data name="labelSelectUser.Size" type="System.Drawing.Size, System.Drawing"> <data name="labelSelectUser.Size" type="System.Drawing.Size, System.Drawing">
<value>105, 31</value> <value>105, 29</value>
</data> </data>
<data name="labelSelectUser.TabIndex" type="System.Int32, mscorlib"> <data name="labelSelectUser.TabIndex" type="System.Int32, mscorlib">
<value>0</value> <value>0</value>
@ -171,6 +171,39 @@
<data name="&gt;&gt;labelSelectUser.ZOrder" xml:space="preserve"> <data name="&gt;&gt;labelSelectUser.ZOrder" xml:space="preserve">
<value>0</value> <value>0</value>
</data> </data>
<data name="gabLookup.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="gabLookup.Location" type="System.Drawing.Point, System.Drawing">
<value>114, 3</value>
</data>
<data name="gabLookup.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>200, 0</value>
</data>
<data name="gabLookup.NotFoundText" xml:space="preserve">
<value>The user was not found</value>
</data>
<data name="gabLookup.Placeholder" xml:space="preserve">
<value>Start typing name</value>
</data>
<data name="gabLookup.Size" type="System.Drawing.Size, System.Drawing">
<value>260, 23</value>
</data>
<data name="gabLookup.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="&gt;&gt;gabLookup.Name" xml:space="preserve">
<value>gabLookup</value>
</data>
<data name="&gt;&gt;gabLookup.Type" xml:space="preserve">
<value>Acacia.UI.GABLookupControl, Kopano, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;gabLookup.Parent" xml:space="preserve">
<value>_layoutSelectUser</value>
</data>
<data name="&gt;&gt;gabLookup.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="buttonOpenUser.AutoSize" type="System.Boolean, mscorlib"> <data name="buttonOpenUser.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
</data> </data>
@ -193,10 +226,10 @@
<value>8, 0, 8, 0</value> <value>8, 0, 8, 0</value>
</data> </data>
<data name="buttonOpenUser.Size" type="System.Drawing.Size, System.Drawing"> <data name="buttonOpenUser.Size" type="System.Drawing.Size, System.Drawing">
<value>59, 25</value> <value>59, 23</value>
</data> </data>
<data name="buttonOpenUser.TabIndex" type="System.Int32, mscorlib"> <data name="buttonOpenUser.TabIndex" type="System.Int32, mscorlib">
<value>1</value> <value>2</value>
</data> </data>
<data name="buttonOpenUser.Text" xml:space="preserve"> <data name="buttonOpenUser.Text" xml:space="preserve">
<value>Open</value> <value>Open</value>
@ -211,74 +244,8 @@
<value>_layoutSelectUser</value> <value>_layoutSelectUser</value>
</data> </data>
<data name="&gt;&gt;buttonOpenUser.ZOrder" xml:space="preserve"> <data name="&gt;&gt;buttonOpenUser.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="_layoutCenterGABLookup.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="_layoutCenterGABLookup.ColumnCount" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="gabLookup.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="gabLookup.Location" type="System.Drawing.Point, System.Drawing">
<value>3, 3</value>
</data>
<data name="gabLookup.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>200, 0</value>
</data>
<data name="gabLookup.Size" type="System.Drawing.Size, System.Drawing">
<value>256, 21</value>
</data>
<data name="gabLookup.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="&gt;&gt;gabLookup.Name" xml:space="preserve">
<value>gabLookup</value>
</data>
<data name="&gt;&gt;gabLookup.Type" xml:space="preserve">
<value>Acacia.UI.GABLookupControl, Kopano, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;gabLookup.Parent" xml:space="preserve">
<value>_layoutCenterGABLookup</value>
</data>
<data name="&gt;&gt;gabLookup.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="_layoutCenterGABLookup.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="_layoutCenterGABLookup.Location" type="System.Drawing.Point, System.Drawing">
<value>113, 2</value>
</data>
<data name="_layoutCenterGABLookup.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>2, 2, 2, 2</value>
</data>
<data name="_layoutCenterGABLookup.RowCount" type="System.Int32, mscorlib">
<value>3</value>
</data>
<data name="_layoutCenterGABLookup.Size" type="System.Drawing.Size, System.Drawing">
<value>262, 27</value>
</data>
<data name="_layoutCenterGABLookup.TabIndex" type="System.Int32, mscorlib">
<value>2</value> <value>2</value>
</data> </data>
<data name="&gt;&gt;_layoutCenterGABLookup.Name" xml:space="preserve">
<value>_layoutCenterGABLookup</value>
</data>
<data name="&gt;&gt;_layoutCenterGABLookup.Type" xml:space="preserve">
<value>System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;_layoutCenterGABLookup.Parent" xml:space="preserve">
<value>_layoutSelectUser</value>
</data>
<data name="&gt;&gt;_layoutCenterGABLookup.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<data name="_layoutCenterGABLookup.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="gabLookup" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,100" /&gt;&lt;Rows Styles="Percent,50,AutoSize,0,Percent,50" /&gt;&lt;/TableLayoutSettings&gt;</value>
</data>
<data name="_layoutSelectUser.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms"> <data name="_layoutSelectUser.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value> <value>Fill</value>
</data> </data>
@ -289,7 +256,7 @@
<value>1</value> <value>1</value>
</data> </data>
<data name="_layoutSelectUser.Size" type="System.Drawing.Size, System.Drawing"> <data name="_layoutSelectUser.Size" type="System.Drawing.Size, System.Drawing">
<value>442, 31</value> <value>442, 29</value>
</data> </data>
<data name="_layoutSelectUser.TabIndex" type="System.Int32, mscorlib"> <data name="_layoutSelectUser.TabIndex" type="System.Int32, mscorlib">
<value>0</value> <value>0</value>
@ -307,16 +274,16 @@
<value>0</value> <value>0</value>
</data> </data>
<data name="_layoutSelectUser.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms"> <data name="_layoutSelectUser.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="labelSelectUser" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="buttonOpenUser" Row="0" RowSpan="1" Column="2" ColumnSpan="1" /&gt;&lt;Control Name="_layoutCenterGABLookup" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="AutoSize,0,Percent,100,AutoSize,0" /&gt;&lt;Rows Styles="Percent,100,Absolute,31" /&gt;&lt;/TableLayoutSettings&gt;</value> <value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="labelSelectUser" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="gabLookup" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="buttonOpenUser" Row="0" RowSpan="1" Column="2" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="AutoSize,0,Percent,100,AutoSize,0" /&gt;&lt;Rows Styles="Percent,100,Absolute,29" /&gt;&lt;/TableLayoutSettings&gt;</value>
</data> </data>
<data name="kTreeFolders.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms"> <data name="kTreeFolders.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value> <value>Fill</value>
</data> </data>
<data name="kTreeFolders.Location" type="System.Drawing.Point, System.Drawing"> <data name="kTreeFolders.Location" type="System.Drawing.Point, System.Drawing">
<value>3, 40</value> <value>3, 38</value>
</data> </data>
<data name="kTreeFolders.Size" type="System.Drawing.Size, System.Drawing"> <data name="kTreeFolders.Size" type="System.Drawing.Size, System.Drawing">
<value>442, 275</value> <value>442, 277</value>
</data> </data>
<data name="kTreeFolders.TabIndex" type="System.Int32, mscorlib"> <data name="kTreeFolders.TabIndex" type="System.Int32, mscorlib">
<value>0</value> <value>0</value>
@ -468,6 +435,72 @@
<data name="&gt;&gt;checkSendAs.ZOrder" xml:space="preserve"> <data name="&gt;&gt;checkSendAs.ZOrder" xml:space="preserve">
<value>3</value> <value>3</value>
</data> </data>
<data name="_labelReminders.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="_labelReminders.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="_labelReminders.Location" type="System.Drawing.Point, System.Drawing">
<value>3, 53</value>
</data>
<data name="_labelReminders.Size" type="System.Drawing.Size, System.Drawing">
<value>82, 27</value>
</data>
<data name="_labelReminders.TabIndex" type="System.Int32, mscorlib">
<value>6</value>
</data>
<data name="_labelReminders.Text" xml:space="preserve">
<value>Show reminders</value>
</data>
<data name="_labelReminders.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>MiddleLeft</value>
</data>
<data name="&gt;&gt;_labelReminders.Name" xml:space="preserve">
<value>_labelReminders</value>
</data>
<data name="&gt;&gt;_labelReminders.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;_labelReminders.Parent" xml:space="preserve">
<value>_layoutOptions</value>
</data>
<data name="&gt;&gt;_labelReminders.ZOrder" xml:space="preserve">
<value>4</value>
</data>
<data name="checkReminders.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="checkReminders.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Left</value>
</data>
<data name="checkReminders.Location" type="System.Drawing.Point, System.Drawing">
<value>94, 57</value>
</data>
<data name="checkReminders.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>6, 4, 3, 3</value>
</data>
<data name="checkReminders.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 3, 0, 3</value>
</data>
<data name="checkReminders.Size" type="System.Drawing.Size, System.Drawing">
<value>15, 20</value>
</data>
<data name="checkReminders.TabIndex" type="System.Int32, mscorlib">
<value>7</value>
</data>
<data name="&gt;&gt;checkReminders.Name" xml:space="preserve">
<value>checkReminders</value>
</data>
<data name="&gt;&gt;checkReminders.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;checkReminders.Parent" xml:space="preserve">
<value>_layoutOptions</value>
</data>
<data name="&gt;&gt;checkReminders.ZOrder" xml:space="preserve">
<value>5</value>
</data>
<data name="_labelPermissions.AutoSize" type="System.Boolean, mscorlib"> <data name="_labelPermissions.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
</data> </data>
@ -502,7 +535,7 @@
<value>_layoutOptions</value> <value>_layoutOptions</value>
</data> </data>
<data name="&gt;&gt;_labelPermissions.ZOrder" xml:space="preserve"> <data name="&gt;&gt;_labelPermissions.ZOrder" xml:space="preserve">
<value>4</value> <value>6</value>
</data> </data>
<data name="labelPermissionsValue.AutoSize" type="System.Boolean, mscorlib"> <data name="labelPermissionsValue.AutoSize" type="System.Boolean, mscorlib">
<value>True</value> <value>True</value>
@ -541,72 +574,6 @@
<value>_layoutOptions</value> <value>_layoutOptions</value>
</data> </data>
<data name="&gt;&gt;labelPermissionsValue.ZOrder" xml:space="preserve"> <data name="&gt;&gt;labelPermissionsValue.ZOrder" xml:space="preserve">
<value>5</value>
</data>
<data name="_labelReminders.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="_labelReminders.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="_labelReminders.Location" type="System.Drawing.Point, System.Drawing">
<value>3, 53</value>
</data>
<data name="_labelReminders.Size" type="System.Drawing.Size, System.Drawing">
<value>82, 27</value>
</data>
<data name="_labelReminders.TabIndex" type="System.Int32, mscorlib">
<value>6</value>
</data>
<data name="_labelReminders.Text" xml:space="preserve">
<value>Show reminders</value>
</data>
<data name="_labelReminders.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>MiddleLeft</value>
</data>
<data name="&gt;&gt;_labelReminders.Name" xml:space="preserve">
<value>_labelReminders</value>
</data>
<data name="&gt;&gt;_labelReminders.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;_labelReminders.Parent" xml:space="preserve">
<value>_layoutOptions</value>
</data>
<data name="&gt;&gt;_labelReminders.ZOrder" xml:space="preserve">
<value>6</value>
</data>
<data name="checkReminders.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="checkReminders.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Left</value>
</data>
<data name="checkReminders.Location" type="System.Drawing.Point, System.Drawing">
<value>94, 57</value>
</data>
<data name="checkReminders.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>6, 4, 3, 3</value>
</data>
<data name="checkReminders.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 3, 0, 3</value>
</data>
<data name="checkReminders.Size" type="System.Drawing.Size, System.Drawing">
<value>15, 20</value>
</data>
<data name="checkReminders.TabIndex" type="System.Int32, mscorlib">
<value>7</value>
</data>
<data name="&gt;&gt;checkReminders.Name" xml:space="preserve">
<value>checkReminders</value>
</data>
<data name="&gt;&gt;checkReminders.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;checkReminders.Parent" xml:space="preserve">
<value>_layoutOptions</value>
</data>
<data name="&gt;&gt;checkReminders.ZOrder" xml:space="preserve">
<value>7</value> <value>7</value>
</data> </data>
<data name="_layoutOptions.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms"> <data name="_layoutOptions.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
@ -640,7 +607,7 @@
<value>2</value> <value>2</value>
</data> </data>
<data name="_layoutOptions.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms"> <data name="_layoutOptions.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="_labelName" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="textName" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="_labelSendAs" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="checkSendAs" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="_labelPermissions" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="labelPermissionsValue" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="_labelReminders" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="checkReminders" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="AutoSize,0,Percent,100" /&gt;&lt;Rows Styles="AutoSize,0,AutoSize,0,AutoSize,0,AutoSize,0" /&gt;&lt;/TableLayoutSettings&gt;</value> <value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="_labelName" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="textName" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="_labelSendAs" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="checkSendAs" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="_labelReminders" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="checkReminders" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;Control Name="_labelPermissions" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="labelPermissionsValue" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="AutoSize,0,Percent,100" /&gt;&lt;Rows Styles="AutoSize,0,AutoSize,0,AutoSize,0,AutoSize,0" /&gt;&lt;/TableLayoutSettings&gt;</value>
</data> </data>
<data name="_layoutMain.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms"> <data name="_layoutMain.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value> <value>Fill</value>
@ -655,7 +622,7 @@
<value>448, 418</value> <value>448, 418</value>
</data> </data>
<data name="_layoutMain.TabIndex" type="System.Int32, mscorlib"> <data name="_layoutMain.TabIndex" type="System.Int32, mscorlib">
<value>3</value> <value>0</value>
</data> </data>
<data name="&gt;&gt;_layoutMain.Name" xml:space="preserve"> <data name="&gt;&gt;_layoutMain.Name" xml:space="preserve">
<value>_layoutMain</value> <value>_layoutMain</value>
@ -682,7 +649,7 @@
<value>448, 418</value> <value>448, 418</value>
</data> </data>
<data name="_mainBusyHider.TabIndex" type="System.Int32, mscorlib"> <data name="_mainBusyHider.TabIndex" type="System.Int32, mscorlib">
<value>4</value> <value>0</value>
</data> </data>
<data name="_mainBusyHider.Text" type="System.Resources.ResXNullRef, System.Windows.Forms"> <data name="_mainBusyHider.Text" type="System.Resources.ResXNullRef, System.Windows.Forms">
<value /> <value />
@ -718,7 +685,7 @@
<value>450, 35</value> <value>450, 35</value>
</data> </data>
<data name="dialogButtons.TabIndex" type="System.Int32, mscorlib"> <data name="dialogButtons.TabIndex" type="System.Int32, mscorlib">
<value>0</value> <value>1</value>
</data> </data>
<data name="&gt;&gt;dialogButtons.Name" xml:space="preserve"> <data name="&gt;&gt;dialogButtons.Name" xml:space="preserve">
<value>dialogButtons</value> <value>dialogButtons</value>

View File

@ -78,6 +78,21 @@ namespace Acacia.Native
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Point pt, int cPoints); public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Point pt, int cPoints);
public static int GetXLParam(IntPtr lParam)
{
return lParam.ToInt32() & 0xFFFF;
}
public static int GetYLParam(IntPtr lParam)
{
return (lParam.ToInt32() >> 16) & 0xFFFF;
}
public static Point GetPointLParam(IntPtr lParam)
{
return new Point(GetXLParam(lParam), GetYLParam(lParam));
}
#endregion #endregion
#region Messages #region Messages

View File

@ -23,8 +23,15 @@ using System.Text;
namespace Acacia.Native namespace Acacia.Native
{ {
public enum MA : int
{
NOACTIVATE = 0x0003
}
public enum WM : int public enum WM : int
{ {
MOUSEACTIVATE = 0x0021,
NCHITTEST = 0x0084, NCHITTEST = 0x0084,
NCPAINT = 0x0085, NCPAINT = 0x0085,
@ -38,7 +45,9 @@ namespace Acacia.Native
LBUTTONDOWN = 0x0201, LBUTTONDOWN = 0x0201,
RBUTTONDOWN = 0x0204, RBUTTONDOWN = 0x0204,
MBUTTONDOWN = 0x0207 MBUTTONDOWN = 0x0207,
MOUSEWHEEL = 0x020A,
} }
} }

View File

@ -1,4 +1,4 @@
/// Copyright 2016 Kopano b.v. /// Copyright 2017 Kopano b.v.
/// ///
/// This program is free software: you can redistribute it and/or modify /// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License, version 3, /// it under the terms of the GNU Affero General Public License, version 3,
@ -31,8 +31,74 @@ using Acacia.Controls;
namespace Acacia.UI namespace Acacia.UI
{ {
public partial class GABLookupControl : KComboBox public partial class GABLookupControl : KComboBoxCustomDraw
{ {
private class NotFoundGABUser : GABUser
{
public NotFoundGABUser(string userName) : base(userName)
{
}
}
private class GABDataSource : KDataSource<GABUser>
{
private readonly GABHandler _gab;
private readonly List<GABUser> _users;
public GABDataSource(GABHandler gab)
{
this._gab = gab;
_users = new List<GABUser>();
foreach (IItem item in _gab.Contacts.Items.Sort("FullName", false))
{
if (item is IContactItem)
_users.Add(new GABUser((IContactItem)item));
}
}
public override IEnumerable<GABUser> Items
{
get
{
return _users;
}
}
protected override string GetItemText(GABUser item)
{
// If there is a filter, try to complete that
if (!string.IsNullOrEmpty(Filter?.FilterText))
{
string s = Filter?.FilterText.ToLower();
if (item.UserName?.ToLower().StartsWith(s) == true)
return item.UserName;
else if (item.FullName?.ToLower().StartsWith(s) == true)
return item.FullName;
else if (item.EmailAddress?.ToLower().StartsWith(s) == true)
return item.EmailAddress;
}
return item.UserName;
}
protected override bool MatchesFilter(GABUser item)
{
string s = Filter.FilterText.ToLower();
return
item.FullName?.ToLower().StartsWith(s) == true ||
item.UserName?.ToLower().StartsWith(s) == true ||
item.EmailAddress?.ToLower().StartsWith(s) == true;
}
public override object NotFoundItem
{
get
{
return new NotFoundGABUser(Filter.FilterText);
}
}
}
public GABLookupControl() : this(null) public GABLookupControl() : this(null)
{ {
} }
@ -40,11 +106,20 @@ namespace Acacia.UI
public GABLookupControl(GABHandler gab) public GABLookupControl(GABHandler gab)
{ {
InitializeComponent(); InitializeComponent();
this.GAB = gab; GAB = gab;
} }
#region Properties and events #region Properties and events
[Category("Appearance")]
[Localizable(true)]
public string NotFoundText
{
get;
set;
}
#region SelectedUser #region SelectedUser
public class SelectedUserEventArgs : EventArgs public class SelectedUserEventArgs : EventArgs
@ -64,40 +139,31 @@ namespace Acacia.UI
[Category("Behavior")] [Category("Behavior")]
public event SelectedUserEventHandler SelectedUserChanged; public event SelectedUserEventHandler SelectedUserChanged;
private GABUser _selectedUser;
public GABUser SelectedUser public GABUser SelectedUser
{ {
get get
{ {
/*if (SelectedValue == null) return _selectedUser;
return new GABUser(Text, Text);
else
return (GABUser)SelectedValue;*/
return null;
} }
set set
{ {
/*if (value == null) _selectedUser = null;
{ Select(value);
SelectedIndex = -1;
Text = "";
}
else
{
}*/
} }
} }
private void SetSelectedUser(GABUser user, bool isChosen) protected override void OnTextChanged(EventArgs e)
{ {
if (SelectedUser != user || isChosen) base.OnTextChanged(e);
{ _selectedUser = string.IsNullOrEmpty(Text) ? null : new GABUser(Text);
System.Diagnostics.Trace.WriteLine(string.Format("SELECT: {0} -> {1} : {2}", SelectedUser, user, isChosen)); SelectedUserChanged?.Invoke(this, new SelectedUserEventArgs(_selectedUser, false));
if (isChosen) }
SelectedUser = user;
if (SelectedUserChanged != null) protected override void OnSelectedItemChanged()
SelectedUserChanged(this, new SelectedUserEventArgs(user, isChosen)); {
} _selectedUser = (GABUser)SelectedItem?.Item;
SelectedUserChanged?.Invoke(this, new SelectedUserEventArgs(_selectedUser, true));
} }
#endregion #endregion
@ -117,7 +183,7 @@ namespace Acacia.UI
if (_gab != value) if (_gab != value)
{ {
_gab = value; _gab = value;
LookupUsers(false); DataSource = _gab == null ? null : new GABDataSource(_gab);
} }
} }
} }
@ -126,147 +192,20 @@ namespace Acacia.UI
#endregion #endregion
protected override void OnTextChanged(EventArgs e)
{
LookupUsers(true);
SelectCurrentUser(false);
}
private void SelectCurrentUser(bool isChosen)
{
/*GABUser user = null;
// Select whatever is currently in the text box as a user
if (DataSource != null)
{
// Find if there's a user matching
user = ((List<GABUser>)DataSource).FirstOrDefault((u) => u.DisplayName == Text);
}
if (user == null && Text.Length > 0)
{
// Make a new one
user = new GABUser(Text, Text);
}
SetSelectedUser(user, isChosen);*/
}
/*private bool _needUpdate;
protected override void OnTextUpdate(EventArgs e)
{
_needUpdate = true;
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
SetSelectedUser((GABUser)SelectedItem, true);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.KeyCode == Keys.Enter)
{
SelectCurrentUser(true);
}
else
{
SetSelectedUser(null, false);
}
}
protected override void OnDataSourceChanged(EventArgs e)
{
// Suppress to prevent automatic selection
}*/
private string _lastText;
private List<GABUser> _allUsers;
private void LookupUsers(bool dropDown)
{
// Cannot lookup if there is no GAB
if (_gab == null)
return;
string text = this.Text;
// Only search if the text actually changed
if (_lastText != text)
{
// Limit search results if there is a filter, otherwise show everything
List<GABUser> users;
if (text.Length == 0)
{
// Cache the list of all users
if (_allUsers == null)
{
_allUsers = Lookup("", int.MaxValue);
}
users = _allUsers;
}
else
{
users = Lookup(text, 8);
}
// Sort the users if we have them
users.Sort();
_lastText = text;
// Setting the datasource will trigger a select if there is a match
BeginUpdate();
DataSource = users;
//SetItemsCore(users);
if (dropDown)
DroppedDown = true;
//Cursor.Current = Cursors.Default;
//Text = _lastText;
//SelectionLength = 0;
//SelectionStart = _lastText.Length;
EndUpdate();
}
}
#region Lookup helpers
// TODO: these probably belong in GAB
public List<GABUser> Lookup(string text, int max)
{
// Begin GAB lookup, search on full name or username
using (ISearch<IContactItem> search = _gab.Contacts.Search<IContactItem>())
{
ISearchOperator oper = search.AddOperator(SearchOperator.Or);
oper.AddField("urn:schemas:contacts:cn").SetOperation(SearchOperation.Like, text + "%");
oper.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Like, text + "%");
// Fetch the results up to the limit.
// TODO: make limit a property?
List<GABUser> users = new List<GABUser>();
foreach (IContactItem result in search.Search(max))
{
users.Add(new GABUser(result.FullName, result.CustomerID));
}
return users;
}
}
public GABUser LookupExact(string username) public GABUser LookupExact(string username)
{ {
if (_gab?.Contacts != null) string s = username.ToLower();
if (DataSource != null)
{ {
// Begin GAB lookup, search on full name or username foreach(GABUser user in DataSource.Items)
using (ISearch<IContactItem> search = _gab.Contacts.Search<IContactItem>())
{ {
search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, username); if (
user.FullName?.ToLower().Equals(s) == true ||
// Fetch the result, if any. user.UserName?.ToLower().Equals(s) == true ||
List<GABUser> users = new List<GABUser>(); user.EmailAddress?.ToLower().Equals(s) == true
using (IContactItem result = search.SearchOne()) )
{ {
if (result != null) return user;
return new GABUser(result.FullName, result.CustomerID);
} }
} }
} }
@ -274,6 +213,74 @@ namespace Acacia.UI
return new GABUser(username); return new GABUser(username);
} }
#region Rendering
private static readonly Size NameSpacing = new Size(12, 4);
private static readonly Padding ItemPadding = new Padding(5);
private static readonly Padding BorderPadding = new Padding(2);
private const int BorderThickness = 1;
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
GABUser item = (GABUser)e.Item;
Size nameSize = TextRenderer.MeasureText(e.Graphics, item.FullName, Font);
Size loginSize = TextRenderer.MeasureText(e.Graphics, item.UserName, Font);
Size emailSize = TextRenderer.MeasureText(e.Graphics, GetSecondLine(item), Font);
e.ItemWidth = Math.Max(emailSize.Width, nameSize.Width + loginSize.Width + NameSpacing.Width) +
ItemPadding.Horizontal;
e.ItemHeight = emailSize.Height + Math.Max(nameSize.Height, loginSize.Height) +
ItemPadding.Vertical +
NameSpacing.Height +
BorderThickness + BorderPadding.Vertical;
}
private string GetSecondLine(GABUser item)
{
if (item is NotFoundGABUser)
return NotFoundText;
else
return item.EmailAddress;
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
GABUser item = (GABUser)e.Item;
// Draw the background
e.DrawBackground();
// Get the sizes
Size nameSize = TextRenderer.MeasureText(e.Graphics, item.FullName, Font);
Size loginSize = TextRenderer.MeasureText(e.Graphics, item.UserName, Font);
Size emailSize = TextRenderer.MeasureText(e.Graphics, item.EmailAddress, Font);
// Draw the full name top-left
Point pt = e.Bounds.TopLeft();
pt.Y += ItemPadding.Top;
pt.X += ItemPadding.Left;
TextRenderer.DrawText(e.Graphics, item.FullName, Font, pt, e.ForeColor);
// Draw the username top-right
pt.X = e.Bounds.Right - loginSize.Width - ItemPadding.Right;
TextRenderer.DrawText(e.Graphics, item.UserName, Font, pt, e.ForeColor);
// Draw the email below
pt.Y += Math.Max(nameSize.Height, loginSize.Height) + NameSpacing.Height;
pt.X = e.Bounds.X + ItemPadding.Left;
TextRenderer.DrawText(e.Graphics, GetSecondLine(item), Font, pt, e.ForeColor);
// Draw a separator line
if (e.Index < DisplayItemCount - 1)
{
int lineY = e.Bounds.Bottom - 1 - BorderThickness - BorderPadding.Bottom;
e.Graphics.DrawLine(Pens.LightGray, BorderPadding.Left, lineY, e.Bounds.Width - BorderPadding.Right, lineY);
}
}
#endregion #endregion
} }
} }

View File

@ -179,5 +179,15 @@ namespace Acacia.Utils
int additional = (align - (size % align)) % align; int additional = (align - (size % align)) % align;
return size + additional; return size + additional;
} }
public static NumType Bound<NumType>(NumType value, NumType min, NumType max)
where NumType : IComparable
{
if (value.CompareTo(min) < 0)
return min;
if (value.CompareTo(max) > 0)
return max;
return value;
}
} }
} }

View File

@ -1,4 +1,6 @@
/// Copyright 2016 Kopano b.v. 
using Acacia.Stubs;
/// Copyright 2016 Kopano b.v.
/// ///
/// This program is free software: you can redistribute it and/or modify /// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License, version 3, /// it under the terms of the GNU Affero General Public License, version 3,
@ -13,7 +15,6 @@
/// along with this program.If not, see<http://www.gnu.org/licenses/>. /// along with this program.If not, see<http://www.gnu.org/licenses/>.
/// ///
/// Consult LICENSE file for details /// Consult LICENSE file for details
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -36,8 +37,9 @@ namespace Acacia.ZPush
public readonly string FullName; public readonly string FullName;
public readonly string UserName; public readonly string UserName;
public readonly string EmailAddress;
public GABUser(string displayName, string userName) private GABUser(string displayName, string userName)
{ {
this.FullName = displayName; this.FullName = displayName;
this.UserName = userName; this.UserName = userName;
@ -49,6 +51,13 @@ namespace Acacia.ZPush
this.UserName = userName; this.UserName = userName;
} }
public GABUser(IContactItem item)
{
this.FullName = item.FullName;
this.EmailAddress = item.Email1Address;
this.UserName = item.CustomerID;
}
public int CompareTo(GABUser other) public int CompareTo(GABUser other)
{ {
return FullName.CompareTo(other.FullName); return FullName.CompareTo(other.FullName);

View File

@ -172,6 +172,18 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\labelS
msgid "Open folders for user" msgid "Open folders for user"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\buttonOpenUser.Text #: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\buttonOpenUser.Text
#, csharp-format #, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\buttonOpenUser.Text" msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\buttonOpenUser.Text"
@ -190,6 +202,12 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_label
msgid "Send as owner" msgid "Send as owner"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelReminders.Text
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelReminders.Text"
msgid "Show reminders"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelPermissions.Text #: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelPermissions.Text
#, csharp-format #, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelPermissions.Text" msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelPermissions.Text"
@ -202,12 +220,6 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\labelP
msgid "Permissions" msgid "Permissions"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelReminders.Text
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelReminders.Text"
msgid "Show reminders"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\$this.Text #: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\$this.Text
#, csharp-format #, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\$this.Text" msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\$this.Text"

View File

@ -1211,3 +1211,15 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Ti
msgid "Private event" msgid "Private event"
msgstr "Privater Termin" msgstr "Privater Termin"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""

View File

@ -172,6 +172,18 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\labelS
msgid "Open folders for user" msgid "Open folders for user"
msgstr "Open folders for user" msgstr "Open folders for user"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr "The user was not found"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr "Start typing name"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\buttonOpenUser.Text #: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\buttonOpenUser.Text
#, csharp-format #, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\buttonOpenUser.Text" msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\buttonOpenUser.Text"
@ -190,6 +202,12 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_label
msgid "Send as owner" msgid "Send as owner"
msgstr "Send as owner" msgstr "Send as owner"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelReminders.Text
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelReminders.Text"
msgid "Show reminders"
msgstr "Show reminders"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelPermissions.Text #: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelPermissions.Text
#, csharp-format #, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelPermissions.Text" msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelPermissions.Text"
@ -202,12 +220,6 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\labelP
msgid "Permissions" msgid "Permissions"
msgstr "Permissions" msgstr "Permissions"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\_labelReminders.Text
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\_labelReminders.Text"
msgid "Show reminders"
msgstr "Show reminders"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\$this.Text #: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\$this.Text
#, csharp-format #, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\$this.Text" msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\$this.Text"

View File

@ -1209,3 +1209,15 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Ti
msgid "Private event" msgid "Private event"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""

View File

@ -1224,3 +1224,15 @@ msgstr ""
msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Title" msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Title"
msgid "Private event" msgid "Private event"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""

View File

@ -1176,3 +1176,15 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Ti
msgid "Private event" msgid "Private event"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""

View File

@ -964,3 +964,15 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Ti
msgid "Private event" msgid "Private event"
msgstr "" msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""

View File

@ -1211,3 +1211,15 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Ti
msgid "Private event" msgid "Private event"
msgstr "Privé afspraak" msgstr "Privé afspraak"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""

View File

@ -966,3 +966,15 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SharedFolders_PrivateEvent_Ti
msgid "Private event" msgid "Private event"
msgstr "Evento particular" msgstr "Evento particular"
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.NotFoundText
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.NotFoundText"
msgid "The user was not found"
msgstr ""
#: AcaciaZPushPlugin\Features\SharedFolders\SharedFoldersDialog\gabLookup.Placeholder
#, csharp-format
msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\gabLookup.Placeholder"
msgid "Start typing name"
msgstr ""